예제 #1
0
파일: generator.c 프로젝트: 1nueve/MacRuby
static FBuffer *cState_prepare_buffer(VALUE self)
{
    FBuffer *buffer;
    GET_STATE(self);
    buffer = fbuffer_alloc(state->buffer_initial_length);

    if (state->object_delim) {
        fbuffer_clear(state->object_delim);
    } else {
        state->object_delim = fbuffer_alloc(16);
    }
    fbuffer_append_char(state->object_delim, ',');
    if (state->object_delim2) {
        fbuffer_clear(state->object_delim2);
    } else {
        state->object_delim2 = fbuffer_alloc(16);
    }
    fbuffer_append_char(state->object_delim2, ':');
    if (state->space) fbuffer_append(state->object_delim2, state->space, state->space_len);

    if (state->array_delim) {
        fbuffer_clear(state->array_delim);
    } else {
        state->array_delim = fbuffer_alloc(16);
    }
    fbuffer_append_char(state->array_delim, ',');
    if (state->array_nl) fbuffer_append(state->array_delim, state->array_nl, state->array_nl_len);
    return buffer;
}
예제 #2
0
파일: generator.c 프로젝트: 1nueve/MacRuby
static void generate_json_array(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj)
{
    char *array_nl = state->array_nl;
    long array_nl_len = state->array_nl_len;
    char *indent = state->indent;
    long indent_len = state->indent_len;
    long max_nesting = state->max_nesting;
    char *delim = FBUFFER_PTR(state->array_delim);
    long delim_len = FBUFFER_LEN(state->array_delim);
    long depth = ++state->depth;
    int i, j;
    if (max_nesting != 0 && depth > max_nesting) {
        fbuffer_free(buffer);
        rb_raise(eNestingError, "nesting of %ld is too deep", --state->depth);
    }
    fbuffer_append_char(buffer, '[');
    if (array_nl) fbuffer_append(buffer, array_nl, array_nl_len);
    for(i = 0; i < RARRAY_LEN(obj); i++) {
        if (i > 0) fbuffer_append(buffer, delim, delim_len);
        if (indent) {
            for (j = 0; j < depth; j++) {
                fbuffer_append(buffer, indent, indent_len);
            }
        }
        generate_json(buffer, Vstate, state, rb_ary_entry(obj, i));
    }
    state->depth = --depth;
    if (array_nl) {
        fbuffer_append(buffer, array_nl, array_nl_len);
        if (indent) {
            for (j = 0; j < depth; j++) {
                fbuffer_append(buffer, indent, indent_len);
            }
        }
    }
    fbuffer_append_char(buffer, ']');
}
예제 #3
0
파일: generator.c 프로젝트: 1nueve/MacRuby
static void generate_json_object(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj)
{
    char *object_nl = state->object_nl;
    long object_nl_len = state->object_nl_len;
    char *indent = state->indent;
    long indent_len = state->indent_len;
    long max_nesting = state->max_nesting;
    char *delim = FBUFFER_PTR(state->object_delim);
    long delim_len = FBUFFER_LEN(state->object_delim);
    char *delim2 = FBUFFER_PTR(state->object_delim2);
    long delim2_len = FBUFFER_LEN(state->object_delim2);
    long depth = ++state->depth;
    int i, j;
    VALUE key, key_to_s, keys;
    if (max_nesting != 0 && depth > max_nesting) {
        fbuffer_free(buffer);
        rb_raise(eNestingError, "nesting of %ld is too deep", --state->depth);
    }
    fbuffer_append_char(buffer, '{');
    keys = rb_funcall(obj, i_keys, 0);
    for(i = 0; i < RARRAY_LEN(keys); i++) {
        if (i > 0) fbuffer_append(buffer, delim, delim_len);
        if (object_nl) {
            fbuffer_append(buffer, object_nl, object_nl_len);
        }
        if (indent) {
            for (j = 0; j < depth; j++) {
                fbuffer_append(buffer, indent, indent_len);
            }
        }
        key = rb_ary_entry(keys, i);
        key_to_s = rb_funcall(key, i_to_s, 0);
        Check_Type(key_to_s, T_STRING);
        generate_json(buffer, Vstate, state, key_to_s);
        fbuffer_append(buffer, delim2, delim2_len);
        generate_json(buffer, Vstate, state, rb_hash_aref(obj, key));
    }
    depth = --state->depth;
    if (object_nl) {
        fbuffer_append(buffer, object_nl, object_nl_len);
        if (indent) {
            for (j = 0; j < depth; j++) {
                fbuffer_append(buffer, indent, indent_len);
            }
        }
    }
    fbuffer_append_char(buffer, '}');
}
예제 #4
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);
}
예제 #5
0
/* Converts string to a JSON string in FBuffer buffer, where all but the ASCII
 * and control characters are JSON escaped. */
static void convert_UTF8_to_JSON_ASCII(FBuffer *buffer, VALUE string)
{
    const UTF8 *source = (UTF8 *) RSTRING_PTR(string);
    const UTF8 *sourceEnd = source + RSTRING_LEN(string);
    char buf[6] = { '\\', 'u' };

    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 utf-8");
        }
        /*
         * 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 UNI_STRICT_CONVERSION
                source -= (extraBytesToRead+1); /* return to the illegal value itself */
                rb_raise(rb_path2class("JSON::GeneratorError"),
                        "source sequence is illegal/malformed utf-8");
#else
                unicode_escape_to_buffer(buffer, buf, UNI_REPLACEMENT_CHAR);
#endif
            } else {
                /* normal case */
                if (ch >= 0x20 && ch <= 0x7f) {
                    switch (ch) {
                        case '\\':
                            fbuffer_append(buffer, "\\\\", 2);
                            break;
                        case '"':
                            fbuffer_append(buffer, "\\\"", 2);
                            break;
                        default:
                            fbuffer_append_char(buffer, (char)ch);
                            break;
                    }
                } else {
                    switch (ch) {
                        case '\n':
                            fbuffer_append(buffer, "\\n", 2);
                            break;
                        case '\r':
                            fbuffer_append(buffer, "\\r", 2);
                            break;
                        case '\t':
                            fbuffer_append(buffer, "\\t", 2);
                            break;
                        case '\f':
                            fbuffer_append(buffer, "\\f", 2);
                            break;
                        case '\b':
                            fbuffer_append(buffer, "\\b", 2);
                            break;
                        default:
                            unicode_escape_to_buffer(buffer, buf, (UTF16) ch);
                            break;
                    }
                }
            }
        } else if (ch > UNI_MAX_UTF16) {
#if UNI_STRICT_CONVERSION
            source -= (extraBytesToRead+1); /* return to the start */
            rb_raise(rb_path2class("JSON::GeneratorError"),
                    "source sequence is illegal/malformed utf8");
#else
            unicode_escape_to_buffer(buffer, buf, UNI_REPLACEMENT_CHAR);
#endif
        } else {
            /* target is a character in range 0xFFFF - 0x10FFFF. */
            ch -= halfBase;
            unicode_escape_to_buffer(buffer, buf, (UTF16)((ch >> halfShift) + UNI_SUR_HIGH_START));
            unicode_escape_to_buffer(buffer, buf, (UTF16)((ch & halfMask) + UNI_SUR_LOW_START));
        }
    }
}
예제 #6
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);
}
예제 #7
0
파일: generator.c 프로젝트: 1nueve/MacRuby
static void generate_json_true(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj)
{
    fbuffer_append(buffer, "true", 4);
}
예제 #8
0
파일: generator.c 프로젝트: 1nueve/MacRuby
static void generate_json_false(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj)
{
    fbuffer_append(buffer, "false", 5);
}
예제 #9
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);
}