in json/apr_json_encode.c [63:164]
static apr_status_t apr_json_encode_string(apr_json_serializer_t * self,
const apr_json_string_t * string)
{
apr_status_t status;
const char *p, *e, *chunk;
const char invalid[4] = { 0xEF, 0xBF, 0xBD, 0x00 };
unsigned char c;
status = apr_brigade_putc(self->brigade, self->flush, self->ctx, '\"');
if (APR_SUCCESS != status) {
return status;
}
for (p = chunk = string->p, e = string->p
+ (APR_JSON_VALUE_STRING == string->len ?
strlen(string->p) : string->len); p < e; p++) {
switch (*p) {
case '\n':
status = apr_json_brigade_write(self, chunk, p - chunk, "\\n");
chunk = p + 1;
break;
case '\r':
status = apr_json_brigade_write(self, chunk, p - chunk, "\\r");
chunk = p + 1;
break;
case '\t':
status = apr_json_brigade_write(self, chunk, p - chunk, "\\t");
chunk = p + 1;
break;
case '\b':
status = apr_json_brigade_write(self, chunk, p - chunk, "\\b");
chunk = p + 1;
break;
case '\f':
status = apr_json_brigade_write(self, chunk, p - chunk, "\\f");
chunk = p + 1;
break;
case '\\':
status = apr_json_brigade_write(self, chunk, p - chunk, "\\\\");
chunk = p + 1;
break;
case '"':
status = apr_json_brigade_write(self, chunk, p - chunk, "\\\"");
chunk = p + 1;
break;
default:
c = (unsigned char)(*p);
apr_size_t left = e - p;
if (c < 0x20) {
status = apr_json_brigade_printf(self, chunk, p - chunk,
"\\u%04x", c);
chunk = p + 1;
}
else if (((c >> 7) == 0x00)) {
/* 1 byte */
}
else if (left > 1 && ((c >> 5) == 0x06) && p[1]) {
/* 2 bytes */
if (left < 2 || (p[1] >> 6) != 0x02) {
status = apr_json_brigade_write(self, chunk, p - chunk,
invalid);
chunk = p + 1;
}
}
else if (((c >> 4) == 0x0E)) {
/* 3 bytes */
if (left < 3 || (p[1] >> 6) != 0x02 || (p[2] >> 6) != 0x02) {
status = apr_json_brigade_write(self, chunk, p - chunk,
invalid);
chunk = p + 1;
}
}
else if ((c >> 3) == 0x1E) {
/* 4 bytes */
if (left < 4 || (p[1] >> 6) != 0x02 || (p[2] >> 6) != 0x02 || (p[3] >> 6) != 0x02) {
status = apr_json_brigade_write(self, chunk, p - chunk,
invalid);
chunk = p + 1;
}
}
else {
status = apr_json_brigade_write(self, chunk, p - chunk,
invalid);
chunk = p + 1;
}
break;
}
if (APR_SUCCESS != status) {
return status;
}
}
if (chunk < p) {
status = apr_brigade_write(self->brigade, self->flush, self->ctx, chunk, p - chunk);
if (APR_SUCCESS != status) {
return status;
}
}
return apr_brigade_putc(self->brigade, self->flush, self->ctx, '\"');
}