#ifndef TEXT_H
#define TEXT_H
nonnull_all
static really_inline uint32_t unescape(const char *text, uint8_t *wire)
{
uint8_t d[3];
if ((d[0] = (uint8_t)text[1] - '0') > 9) {
*wire = (uint8_t)text[1];
return 2u;
} else {
d[1] = (uint8_t)text[2] - '0';
d[2] = (uint8_t)text[3] - '0';
uint32_t o = d[0] * 100 + d[1] * 10 + d[2];
*wire = (uint8_t)o;
return (o > 255 || d[1] > 9 || d[2] > 9) ? 0 : 4u;
}
}
nonnull_all
static really_inline int32_t scan_string(
const char *data,
size_t length,
uint8_t *octets,
const uint8_t *limit)
{
const char *text = data, *text_limit = data + length;
uint8_t *wire = octets;
if (likely((uintptr_t)limit - (uintptr_t)wire >= length)) {
while (text < text_limit) {
*wire = (uint8_t)*text;
if (likely(*text != '\\')) {
text += 1;
wire += 1;
} else {
const uint32_t octet = unescape(text, wire);
if (!octet)
return -1;
text += octet;
wire += 1;
}
}
if (text != text_limit)
return -1;
return (int32_t)(wire - octets);
} else {
while (text < text_limit && wire < limit) {
*wire = (uint8_t)*text;
if (likely(*text != '\\')) {
text += 1;
wire += 1;
} else {
const uint32_t octet = unescape(text, wire);
if (!octet)
return -1;
text += octet;
wire += 1;
}
}
if (text != text_limit || wire > limit)
return -1;
return (int32_t)(wire - octets);
}
}
#endif