Example #1
0
/* Converts string to a JSON string in FBuffer buffer, where only the
 * characters required by the JSON standard are JSON escaped. The remaining
 * characters (should be UTF8) are just passed through and appended to the
 * result. */
static void convert_UTF8_to_JSON(FBuffer *buffer, VALUE string)
{
    const char *ptr = RSTRING_PTR(string), *p;
    int len = RSTRING_LEN(string), start = 0, end = 0;
    const char *escape = NULL;
    int escape_len;
    unsigned char c;
    char buf[6] = { '\\', 'u' };

    for (start = 0, end = 0; end < len;) {
        p = ptr + end;
        c = (unsigned char) *p;
        if (c < 0x20) {
            switch (c) {
                case '\n':
                    escape = "\\n";
                    escape_len = 2;
                    break;
                case '\r':
                    escape = "\\r";
                    escape_len = 2;
                    break;
                case '\t':
                    escape = "\\t";
                    escape_len = 2;
                    break;
                case '\f':
                    escape = "\\f";
                    escape_len = 2;
                    break;
                case '\b':
                    escape = "\\b";
                    escape_len = 2;
                    break;
                default:
                    unicode_escape(buf, (UTF16) *p);
                    escape = buf;
                    escape_len = 6;
                    break;
            }
        } else {
            switch (c) {
                case '\\':
                    escape = "\\\\";
                    escape_len = 2;
                    break;
                case '"':
                    escape =  "\\\"";
                    escape_len = 2;
                    break;
                default:
                    end++;
                    continue;
                    break;
            }
        }
        fbuffer_append(buffer, ptr + start, end - start);
        fbuffer_append(buffer, escape, escape_len);
        start = ++end;
        escape = NULL;
    }
    fbuffer_append(buffer, ptr + start, end - start);
}
Example #2
0
/* Converts string to a JSON string in FBuffer buffer, where only the
 * characters required by the JSON standard are JSON escaped. The remaining
 * characters (should be UTF8) are just passed through and appended to the
 * result. */
static void convert_UTF8_to_JSON(FBuffer *buffer, VALUE string)
{
    const char *ptr = RSTRING_PTR(string), *p;
    unsigned long len = RSTRING_LEN(string), start = 0, end = 0;
    const char *escape = NULL;
    int escape_len;
    unsigned char c;
    char buf[6] = { '\\', 'u' };

    for (start = 0, end = 0; end < len;) {
        p = ptr + end;
        c = (unsigned char) *p;
        if (c < 0x20) {
            switch (c) {
                case '\n':
                    escape = "\\n";
                    escape_len = 2;
                    break;
                case '\r':
                    escape = "\\r";
                    escape_len = 2;
                    break;
                case '\t':
                    escape = "\\t";
                    escape_len = 2;
                    break;
                case '\f':
                    escape = "\\f";
                    escape_len = 2;
                    break;
                case '\b':
                    escape = "\\b";
                    escape_len = 2;
                    break;
                default:
                    unicode_escape(buf, (UTF16) *p);
                    escape = buf;
                    escape_len = 6;
                    break;
            }
        } else {
            switch (c) {
                case '\\':
                    escape = "\\\\";
                    escape_len = 2;
                    break;
                case '"':
                    escape =  "\\\"";
                    escape_len = 2;
                    break;
                default:
                    {
                        unsigned short clen = trailingBytesForUTF8[c] + 1;
                        if (end + clen > len) {
                            rb_raise(rb_path2class("JSON::GeneratorError"),
                                    "partial character in source, but hit end");
                        }
                        if (!isLegalUTF8((UTF8 *) p, clen)) {
                            rb_raise(rb_path2class("JSON::GeneratorError"),
                                    "source sequence is illegal/malformed utf-8");
                        }
                        end += clen;
                    }
                    continue;
                    break;
            }
        }
        fbuffer_append(buffer, ptr + start, end - start);
        fbuffer_append(buffer, escape, escape_len);
        start = ++end;
        escape = NULL;
    }
    fbuffer_append(buffer, ptr + start, end - start);
}
Example #3
0
/* Escapes the UTF16 character and stores the result in the buffer buf, then
 * the buffer buf іs appended to the FBuffer buffer. */
static void unicode_escape_to_buffer(FBuffer *buffer, char buf[6], UTF16
        character)
{
    unicode_escape(buf, character);
    fbuffer_append(buffer, buf, 6);
}
Example #4
0
void JSON_convert_UTF8_to_JSON(VALUE buffer, VALUE string, ConversionFlags flags)
{
    char buf[7];
    const UTF8* source = (UTF8 *) RSTRING_PTR(string);
    const UTF8* sourceEnd = source + RSTRING_LEN(string);

    while (source < sourceEnd) {
        UTF32 ch = 0;
        unsigned short extraBytesToRead = trailingBytesForUTF8[*source];
        if (source + extraBytesToRead >= sourceEnd) {
            rb_raise(rb_path2class("JSON::GeneratorError"),
                    "partial character in source, but hit end");
        }
        if (!isLegalUTF8(source, extraBytesToRead+1)) {
            rb_raise(rb_path2class("JSON::GeneratorError"),
                    "source sequence is illegal/malformed");
        }
        /*
         * The cases all fall through. See "Note A" below.
         */
        switch (extraBytesToRead) {
            case 5: ch += *source++; ch <<= 6; /* remember, illegal UTF-8 */
            case 4: ch += *source++; ch <<= 6; /* remember, illegal UTF-8 */
            case 3: ch += *source++; ch <<= 6;
            case 2: ch += *source++; ch <<= 6;
            case 1: ch += *source++; ch <<= 6;
            case 0: ch += *source++;
        }
        ch -= offsetsFromUTF8[extraBytesToRead];

        if (ch <= UNI_MAX_BMP) { /* Target is a character <= 0xFFFF */
            /* UTF-16 surrogate values are illegal in UTF-32 */
            if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) {
                if (flags == strictConversion) {
                    source -= (extraBytesToRead+1); /* return to the illegal value itself */
                    rb_raise(rb_path2class("JSON::GeneratorError"),
                        "source sequence is illegal/malformed");
                } else {
                    unicode_escape(buffer, UNI_REPLACEMENT_CHAR);
                }
            } else {
                /* normal case */
                if (ch == '"') {
                    rb_str_buf_cat2(buffer, "\\\"");
                } else if (ch == '\\') {
                    rb_str_buf_cat2(buffer, "\\\\");
                } else if (ch == '/') {
                    rb_str_buf_cat2(buffer, "\\/");
                } else if (ch >= 0x20 && ch <= 0x7f) {
                    rb_str_buf_cat(buffer, (char *) source - 1, 1);
                } else if (ch == '\n') {
                    rb_str_buf_cat2(buffer, "\\n");
                } else if (ch == '\r') {
                    rb_str_buf_cat2(buffer, "\\r");
                } else if (ch == '\t') {
                    rb_str_buf_cat2(buffer, "\\t");
                } else if (ch == '\f') {
                    rb_str_buf_cat2(buffer, "\\f");
                } else if (ch == '\b') {
                    rb_str_buf_cat2(buffer, "\\b");
                } else if (ch < 0x20) {
                    unicode_escape(buffer, (UTF16) ch);
                } else {
                    unicode_escape(buffer, (UTF16) ch);
                }
            }
        } else if (ch > UNI_MAX_UTF16) {
            if (flags == strictConversion) {
                source -= (extraBytesToRead+1); /* return to the start */
                rb_raise(rb_path2class("JSON::GeneratorError"),
                        "source sequence is illegal/malformed");
            } else {
                unicode_escape(buffer, UNI_REPLACEMENT_CHAR);
            }
        } else {
            /* target is a character in range 0xFFFF - 0x10FFFF. */
            ch -= halfBase;
            unicode_escape(buffer, (UTF16)((ch >> halfShift) + UNI_SUR_HIGH_START));
            unicode_escape(buffer, (UTF16)((ch & halfMask) + UNI_SUR_LOW_START));
        }
    }
}