static apr_status_t apr_json_encode_string()

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, '\"');
}