diff options
author | Florian Frank <flori@ping.de> | 2009-10-25 22:24:08 +0100 |
---|---|---|
committer | Florian Frank <flori@ping.de> | 2009-10-26 22:58:08 +0100 |
commit | 1bc403acd9b3945b62ed746356f0bc4f800e0ea0 (patch) | |
tree | c9d477580cc49d5d4f0b9f512544c590cd0cb47f /ext/json | |
parent | 6752404ac8a66bd959d8908e363d2784edd91bfc (diff) | |
download | json-1bc403acd9b3945b62ed746356f0bc4f800e0ea0.tar.gz |
first version to pass the tests again
Diffstat (limited to 'ext/json')
-rw-r--r-- | ext/json/ext/generator/fbuffer.c | 12 | ||||
-rw-r--r-- | ext/json/ext/generator/fbuffer.h | 15 | ||||
-rw-r--r-- | ext/json/ext/generator/generator.c | 399 | ||||
-rw-r--r-- | ext/json/ext/generator/unicode.c | 23 | ||||
-rw-r--r-- | ext/json/ext/generator/unicode.h | 3 |
5 files changed, 218 insertions, 234 deletions
diff --git a/ext/json/ext/generator/fbuffer.c b/ext/json/ext/generator/fbuffer.c index 507a432..ed92936 100644 --- a/ext/json/ext/generator/fbuffer.c +++ b/ext/json/ext/generator/fbuffer.c @@ -1,14 +1,14 @@ #include "ruby.h" #include "fbuffer.h" -FBuffer *fbuffer_alloc() +inline FBuffer *fbuffer_alloc() { FBuffer *fb = ALLOC(FBuffer); memset((void *) fb, 0, sizeof(FBuffer)); return fb; } -void fbuffer_free(FBuffer *fb) +inline void fbuffer_free(FBuffer *fb) { if (fb->ptr) ruby_xfree(fb->ptr); ruby_xfree(fb); @@ -19,19 +19,19 @@ inline void fbuffer_inc_capa(FBuffer *fb, unsigned int requested) unsigned int required; if (!fb->ptr) { - fb->ptr = ALLOC_N(unsigned char, FBUFFER_INITIAL_LENGTH); + fb->ptr = ALLOC_N(char, FBUFFER_INITIAL_LENGTH); fb->capa = FBUFFER_INITIAL_LENGTH; } for (required = fb->capa; requested > required - fb->len; required <<= 1); if (required > fb->capa) { - fb->ptr = (unsigned char *) REALLOC_N((long*) fb->ptr, unsigned char, required); + fb->ptr = (char *) REALLOC_N((long*) fb->ptr, char, required); fb->capa = required; } } -inline void fbuffer_append(FBuffer *fb, const unsigned char *newstr, unsigned int len) +inline void fbuffer_append(FBuffer *fb, const char *newstr, unsigned int len) { if (len > 0) { fbuffer_inc_capa(fb, len); @@ -40,7 +40,7 @@ inline void fbuffer_append(FBuffer *fb, const unsigned char *newstr, unsigned in } } -inline void fbuffer_append_char(FBuffer *fb, const unsigned char newchr) +inline void fbuffer_append_char(FBuffer *fb, const char newchr) { fbuffer_inc_capa(fb, 1); *(fb->ptr + fb->len) = newchr; diff --git a/ext/json/ext/generator/fbuffer.h b/ext/json/ext/generator/fbuffer.h index d789da8..06adb25 100644 --- a/ext/json/ext/generator/fbuffer.h +++ b/ext/json/ext/generator/fbuffer.h @@ -1,5 +1,8 @@ +#ifndef _FBUFFER_H_ +#define _FBUFFER_H_ + typedef struct FBufferStruct { - unsigned char *ptr; + char *ptr; unsigned int len; unsigned int capa; } FBuffer; @@ -10,8 +13,10 @@ typedef struct FBufferStruct { #define FBUFFER_LEN(fb) (fb->len) -FBuffer *fbuffer_alloc(); -void fbuffer_free(FBuffer *fb); +inline FBuffer *fbuffer_alloc(); +inline void fbuffer_free(FBuffer *fb); inline void fbuffer_inc_capa(FBuffer *fb, unsigned int requested); -inline void fbuffer_append(FBuffer *fb, const unsigned char *newstr, unsigned int len); -inline void fbuffer_append_char(FBuffer *fb, const unsigned char newchr); +inline void fbuffer_append(FBuffer *fb, const char *newstr, unsigned int len); +inline void fbuffer_append_char(FBuffer *fb, const char newchr); + +#endif diff --git a/ext/json/ext/generator/generator.c b/ext/json/ext/generator/generator.c index a63afa5..093d5d3 100644 --- a/ext/json/ext/generator/generator.c +++ b/ext/json/ext/generator/generator.c @@ -15,6 +15,7 @@ #include "re.h" #endif +inline static VALUE cState_partial_generate(VALUE self, VALUE obj); #ifndef RHASH_TBL #define RHASH_TBL(hsh) (RHASH(hsh)->tbl) @@ -37,12 +38,6 @@ static ID i_encoding, i_encode; #define FORCE_UTF8(obj) #endif -#define check_max_nesting(state, depth) do { \ - long current_nesting = 1 + depth; \ - if (state->max_nesting != 0 && current_nesting > state->max_nesting) \ - rb_raise(eNestingError, "nesting of %ld is too deep", current_nesting); \ -} while (0); - static VALUE mJSON, mExt, mGenerator, cState, mGeneratorMethods, mObject, mHash, mArray, mInteger, mFloat, mString, mString_Extend, mTrueClass, mFalseClass, mNilClass, eGeneratorError, @@ -69,6 +64,8 @@ typedef struct JSON_Generator_StateStruct { JSON_Generator_State *state; \ Data_Get_Struct(self, JSON_Generator_State, state); +#define RSTRING_PAIR(string) RSTRING_PTR(string), RSTRING_LEN(string) + /* * Document-module: JSON::Ext::Generator * @@ -81,81 +78,6 @@ typedef struct JSON_Generator_StateStruct { * */ -static int hash_to_json_state_i(VALUE key, VALUE value, VALUE Vstate) -{ - VALUE json, buf, Vdepth; - GET_STATE(Vstate); - buf = state->memo; - Vdepth = state->depth; - - if (key == Qundef) return ST_CONTINUE; - if (state->flag) { - state->flag = 0; - rb_str_buf_cat2(buf, ","); - if (RSTRING_LEN(state->object_nl)) rb_str_buf_append(buf, state->object_nl); - } - if (RSTRING_LEN(state->object_nl)) { - rb_str_buf_append(buf, rb_str_times(state->indent, Vdepth)); - } - json = rb_funcall(rb_funcall(key, i_to_s, 0), i_to_json, 2, Vstate, Vdepth); - Check_Type(json, T_STRING); - rb_str_buf_append(buf, json); - OBJ_INFECT(buf, json); - if (RSTRING_LEN(state->space_before)) { - rb_str_buf_append(buf, state->space_before); - } - rb_str_buf_cat2(buf, ":"); - if (RSTRING_LEN(state->space)) rb_str_buf_append(buf, state->space); - json = rb_funcall(value, i_to_json, 2, Vstate, Vdepth); - Check_Type(json, T_STRING); - state->flag = 1; - rb_str_buf_append(buf, json); - OBJ_INFECT(buf, json); - state->depth = Vdepth; - state->memo = buf; - return ST_CONTINUE; -} - -inline static VALUE mHash_json_transform(VALUE self, VALUE Vstate, VALUE Vdepth) { - long depth, len = RHASH_SIZE(self); - VALUE result; - GET_STATE(Vstate); - - depth = 1 + FIX2LONG(Vdepth); - result = rb_str_buf_new(len); - state->memo = result; - state->depth = LONG2FIX(depth); - state->flag = 0; - rb_str_buf_cat2(result, "{"); - if (RSTRING_LEN(state->object_nl)) rb_str_buf_append(result, state->object_nl); - rb_hash_foreach(self, hash_to_json_state_i, Vstate); - if (RSTRING_LEN(state->object_nl)) rb_str_buf_append(result, state->object_nl); - if (RSTRING_LEN(state->object_nl)) { - rb_str_buf_append(result, rb_str_times(state->indent, Vdepth)); - } - rb_str_buf_cat2(result, "}"); - return result; -} - -static int hash_to_json_i(VALUE key, VALUE value, VALUE buf) -{ - VALUE tmp; - - if (key == Qundef) return ST_CONTINUE; - if (RSTRING_LEN(buf) > 1) rb_str_buf_cat2(buf, ","); - tmp = rb_funcall(rb_funcall(key, i_to_s, 0), i_to_json, 0); - Check_Type(tmp, T_STRING); - rb_str_buf_append(buf, tmp); - OBJ_INFECT(buf, tmp); - rb_str_buf_cat2(buf, ":"); - tmp = rb_funcall(value, i_to_json, 0); - Check_Type(tmp, T_STRING); - rb_str_buf_append(buf, tmp); - OBJ_INFECT(buf, tmp); - - return ST_CONTINUE; -} - /* * call-seq: to_json(state = nil, depth = 0) * @@ -167,56 +89,11 @@ static int hash_to_json_i(VALUE key, VALUE value, VALUE buf) */ static VALUE mHash_to_json(int argc, VALUE *argv, VALUE self) { - VALUE Vstate, Vdepth, result; - long depth; - - rb_scan_args(argc, argv, "02", &Vstate, &Vdepth); - depth = NIL_P(Vdepth) ? 0 : FIX2LONG(Vdepth); - if (NIL_P(Vstate)) { - long len = RHASH_SIZE(self); - result = rb_str_buf_new(len); - rb_str_buf_cat2(result, "{"); - rb_hash_foreach(self, hash_to_json_i, result); - rb_str_buf_cat2(result, "}"); - } else { - GET_STATE(Vstate); - check_max_nesting(state, depth); - result = mHash_json_transform(self, Vstate, LONG2FIX(depth)); - } - OBJ_INFECT(result, self); - FORCE_UTF8(result); - return result; -} + VALUE state, depth, result; -inline static VALUE mArray_json_transform(VALUE self, VALUE Vstate, VALUE Vdepth) { - long i, len = RARRAY_LEN(self); - VALUE shift, result; - long depth = NIL_P(Vdepth) ? 0 : FIX2LONG(Vdepth); - VALUE delim = rb_str_new2(","); - GET_STATE(Vstate); - - check_max_nesting(state, depth); - result = rb_str_buf_new(len); - OBJ_INFECT(result, self); - if (RSTRING_LEN(state->array_nl)) rb_str_append(delim, state->array_nl); - shift = rb_str_times(state->indent, LONG2FIX(depth + 1)); - - rb_str_buf_cat2(result, "["); - rb_str_buf_append(result, state->array_nl); - for (i = 0; i < len; i++) { - VALUE element = RARRAY_PTR(self)[i]; - OBJ_INFECT(result, element); - if (i > 0) rb_str_buf_append(result, delim); - rb_str_buf_append(result, shift); - element = rb_funcall(element, i_to_json, 2, Vstate, LONG2FIX(depth + 1)); - Check_Type(element, T_STRING); - rb_str_buf_append(result, element); - } - rb_str_buf_append(result, state->array_nl); - if (RSTRING_LEN(state->array_nl)) { - rb_str_buf_append(result, rb_str_times(state->indent, LONG2FIX(depth))); - } - rb_str_buf_cat2(result, "]"); + rb_scan_args(argc, argv, "02", &state, &depth); + if (NIL_P(state)) state = rb_class_new_instance(0, NULL, cState); + return cState_partial_generate(state, self); return result; } @@ -230,29 +107,11 @@ inline static VALUE mArray_json_transform(VALUE self, VALUE Vstate, VALUE Vdepth * _depth_ is used to find out nesting depth, to indent accordingly. */ static VALUE mArray_to_json(int argc, VALUE *argv, VALUE self) { - VALUE Vstate, Vdepth, result; - - rb_scan_args(argc, argv, "02", &Vstate, &Vdepth); - if (NIL_P(Vstate)) { - long i, len = RARRAY_LEN(self); - result = rb_str_buf_new(2 + 2 * len); - rb_str_buf_cat2(result, "["); - OBJ_INFECT(result, self); - for (i = 0; i < len; i++) { - VALUE element = RARRAY_PTR(self)[i]; - OBJ_INFECT(result, element); - if (i > 0) rb_str_buf_cat2(result, ","); - element = rb_funcall(element, i_to_json, 0); - Check_Type(element, T_STRING); - rb_str_buf_append(result, element); - } - rb_str_buf_cat2(result, "]"); - } else { - result = mArray_json_transform(self, Vstate, Vdepth); - } - OBJ_INFECT(result, self); - FORCE_UTF8(result); - return result; + VALUE state, depth; + + rb_scan_args(argc, argv, "02", &state, &depth); + if (NIL_P(state)) state = rb_class_new_instance(0, NULL, cState); + return cState_partial_generate(state, self); } /* @@ -262,9 +121,9 @@ static VALUE mArray_to_json(int argc, VALUE *argv, VALUE self) { */ static VALUE mInteger_to_json(int argc, VALUE *argv, VALUE self) { - VALUE result = rb_funcall(self, i_to_s, 0); - FORCE_UTF8(result); - return result; + VALUE state; + if (NIL_P(state)) state = rb_class_new_instance(0, NULL, cState); + return cState_partial_generate(state, self); } /* @@ -274,30 +133,9 @@ static VALUE mInteger_to_json(int argc, VALUE *argv, VALUE self) */ static VALUE mFloat_to_json(int argc, VALUE *argv, VALUE self) { - JSON_Generator_State *state = NULL; - VALUE Vstate, rest, tmp, result; - double value = RFLOAT_VALUE(self); - rb_scan_args(argc, argv, "01*", &Vstate, &rest); - if (!NIL_P(Vstate)) Data_Get_Struct(Vstate, JSON_Generator_State, state); - if (isinf(value)) { - if (state && state->allow_nan) { - result = rb_funcall(self, i_to_s, 0); - } else { - tmp = rb_funcall(self, i_to_s, 0); - rb_raise(eGeneratorError, "%u: %s not allowed in JSON", __LINE__, StringValueCStr(tmp)); - } - } else if (isnan(value)) { - if (state && state->allow_nan) { - result = rb_funcall(self, i_to_s, 0); - } else { - tmp = rb_funcall(self, i_to_s, 0); - rb_raise(eGeneratorError, "%u: %s not allowed in JSON", __LINE__, StringValueCStr(tmp)); - } - } else { - result = rb_funcall(self, i_to_s, 0); - } - FORCE_UTF8(result); - return result; + VALUE state; + if (NIL_P(state)) state = rb_class_new_instance(0, NULL, cState); + return cState_partial_generate(state, self); } /* @@ -307,7 +145,6 @@ static VALUE mFloat_to_json(int argc, VALUE *argv, VALUE self) */ static VALUE mString_included_s(VALUE self, VALUE modul) { VALUE result = rb_funcall(modul, i_extend, 1, mString_Extend); - FORCE_UTF8(result); return result; } @@ -320,21 +157,10 @@ static VALUE mString_included_s(VALUE self, VALUE modul) { */ static VALUE mString_to_json(int argc, VALUE *argv, VALUE self) { - VALUE result = rb_str_buf_new(RSTRING_LEN(self)); - rb_str_buf_cat2(result, "\""); -#ifdef HAVE_RUBY_ENCODING_H - if (rb_funcall(self, i_encoding, 0) == CEncoding_UTF_8) { - JSON_convert_UTF8_to_JSON(result, self); - } else { - VALUE string = rb_funcall(self, i_encode, 1, CEncoding_UTF_8); - JSON_convert_UTF8_to_JSON(result, string); - } -#else - JSON_convert_UTF8_to_JSON(result, self); -#endif - rb_str_buf_cat2(result, "\""); - FORCE_UTF8(result); - return result; + VALUE state; + rb_scan_args(argc, argv, "01", &state); + if (NIL_P(state)) state = rb_class_new_instance(0, NULL, cState); + return cState_partial_generate(state, self); } /* @@ -389,9 +215,9 @@ static VALUE mString_Extend_json_create(VALUE self, VALUE o) { */ static VALUE mTrueClass_to_json(int argc, VALUE *argv, VALUE self) { - VALUE result = rb_str_new2("true"); - FORCE_UTF8(result); - return result; + VALUE state; + if (NIL_P(state)) state = rb_class_new_instance(0, NULL, cState); + return cState_partial_generate(state, self); } /* @@ -401,9 +227,9 @@ static VALUE mTrueClass_to_json(int argc, VALUE *argv, VALUE self) */ static VALUE mFalseClass_to_json(int argc, VALUE *argv, VALUE self) { - VALUE result = rb_str_new2("false"); - FORCE_UTF8(result); - return result; + VALUE state; + if (NIL_P(state)) state = rb_class_new_instance(0, NULL, cState); + return cState_partial_generate(state, self); } /* @@ -412,9 +238,9 @@ static VALUE mFalseClass_to_json(int argc, VALUE *argv, VALUE self) */ static VALUE mNilClass_to_json(int argc, VALUE *argv, VALUE self) { - VALUE result = rb_str_new2("null"); - FORCE_UTF8(result); - return result; + VALUE state; + if (NIL_P(state)) state = rb_class_new_instance(0, NULL, cState); + return cState_partial_generate(state, self); } /* @@ -426,11 +252,11 @@ static VALUE mNilClass_to_json(int argc, VALUE *argv, VALUE self) */ static VALUE mObject_to_json(int argc, VALUE *argv, VALUE self) { - VALUE result, string = rb_funcall(self, i_to_s, 0); + VALUE state; + VALUE string = rb_funcall(self, i_to_s, 0); Check_Type(string, T_STRING); - result = mString_to_json(argc, argv, string); - FORCE_UTF8(result); - return result; + if (NIL_P(state)) state = rb_class_new_instance(0, NULL, cState); + return cState_partial_generate(state, string); } /* @@ -540,14 +366,164 @@ static VALUE cState_to_h(VALUE self) return result; } +void generate_json(FBuffer *buffer, JSON_Generator_State *state, VALUE obj, long depth) +{ + VALUE tmp; + switch (TYPE(obj)) { + case T_HASH: + { + int i, j; + VALUE delim = rb_str_new2(","), delim2 = rb_str_new2(""); + depth++; + if (state->max_nesting != 0 && depth > state->max_nesting) { + fbuffer_free(buffer); + rb_raise(eNestingError, "nesting of %ld is too deep", depth); + } + if (RSTRING_LEN(state->object_nl)) rb_str_append(delim, state->object_nl); + if (RSTRING_LEN(state->space_before)) rb_str_buf_append(delim2, state->space_before); + rb_str_buf_cat2(delim2, ":"); + if (RSTRING_LEN(state->space)) { + rb_str_buf_append(delim2, state->space); + fbuffer_append_char(buffer, '{'); + fbuffer_append(buffer, RSTRING_PAIR(state->object_nl)); + } else { + fbuffer_append_char(buffer, '{'); + } + VALUE keys = rb_funcall(obj, rb_intern("keys"), 0); + VALUE key, key_to_s; + for(i = 0; i < RARRAY_LEN(keys); i++) { + if (i > 0) fbuffer_append(buffer, RSTRING_PAIR(delim)); + for (j = 0; j < depth; j++) { + fbuffer_append(buffer, RSTRING_PAIR(state->indent)); + } + 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, state, key_to_s, depth); + fbuffer_append(buffer, RSTRING_PAIR(delim2)); + generate_json(buffer, state, rb_hash_aref(obj, key), depth); + } + depth--; + if (RSTRING_LEN(state->object_nl)) { + for (j = 0; j < depth; j++) { + fbuffer_append(buffer, RSTRING_PAIR(state->indent)); + } + fbuffer_append(buffer, RSTRING_PAIR(state->object_nl)); + } + fbuffer_append_char(buffer, '}'); + } + break; + case T_ARRAY: + { + int i, j; + VALUE delim = rb_str_new2(","); + depth++; + if (state->max_nesting != 0 && depth > state->max_nesting) { + fbuffer_free(buffer); + rb_raise(eNestingError, "nesting of %ld is too deep", depth); + } + if (RSTRING_LEN(state->array_nl)) rb_str_append(delim, state->array_nl); + fbuffer_append_char(buffer, '['); + fbuffer_append(buffer, RSTRING_PAIR(state->array_nl)); + for(i = 0; i < RARRAY_LEN(obj); i++) { + if (i > 0) fbuffer_append(buffer, RSTRING_PAIR(delim)); + for (j = 0; j < depth; j++) { + fbuffer_append(buffer, RSTRING_PAIR(state->indent)); + } + generate_json(buffer, state, rb_ary_entry(obj, i), depth); + } + depth--; + fbuffer_append(buffer, RSTRING_PAIR(state->array_nl)); + if (RSTRING_LEN(state->array_nl)) { + for (j = 0; j < depth; j++) { + fbuffer_append(buffer, RSTRING_PAIR(state->indent)); + } + } + fbuffer_append_char(buffer, ']'); + } + break; + case T_STRING: + fbuffer_append_char(buffer, '"'); +#ifdef HAVE_RUBY_ENCODING_H + if (rb_funcall(obj, i_encoding, 0) == CEncoding_UTF_8) { + JSON_convert_UTF8_to_JSON(buffer, obj); + } else { + VALUE string = rb_funcall(obj, i_encode, 1, CEncoding_UTF_8); + JSON_convert_UTF8_to_JSON(buffer, string); + } +#else + JSON_convert_UTF8_to_JSON(buffer, obj); +#endif + fbuffer_append_char(buffer, '"'); + break; + case T_NIL: + fbuffer_append(buffer, "null", 4); + break; + case T_FALSE: + fbuffer_append(buffer, "false", 5); + break; + case T_TRUE: + fbuffer_append(buffer, "true", 4); + break; + case T_FIXNUM: + case T_BIGNUM: + tmp = rb_funcall(obj, i_to_s, 0); + fbuffer_append(buffer, RSTRING_PAIR(tmp)); + break; + case T_FLOAT: + { + double value = RFLOAT_VALUE(obj); + tmp = rb_funcall(obj, i_to_s, 0); + if (isinf(value) && !state->allow_nan) { + fbuffer_free(buffer); + rb_raise(eGeneratorError, "%u: %s not allowed in JSON", __LINE__, StringValueCStr(tmp)); + } else if (isnan(value) && !state->allow_nan) { + fbuffer_free(buffer); + rb_raise(eGeneratorError, "%u: %s not allowed in JSON", __LINE__, StringValueCStr(tmp)); + } + fbuffer_append(buffer, RSTRING_PAIR(tmp)); + } + break; + default: + if (rb_respond_to(obj, i_to_json)) { + tmp = rb_funcall(obj, i_to_json, 0); + Check_Type(tmp, T_STRING); + fbuffer_append(buffer, RSTRING_PAIR(tmp)); + } else { + tmp = rb_funcall(obj, i_to_s, 0); + Check_Type(tmp, T_STRING); + generate_json(buffer, state, tmp, depth + 1); + } + break; + + } +} + +/* + * call-seq: generate(obj) + * + * XXX + */ +inline static VALUE cState_partial_generate(VALUE self, VALUE obj) +{ + VALUE result; + FBuffer *buffer = fbuffer_alloc(); + GET_STATE(self); + generate_json(buffer, state, obj, 0); + result = rb_str_new(buffer->ptr, buffer->len); + fbuffer_free(buffer); + FORCE_UTF8(result); + return result; +} + /* * call-seq: generate(obj) * * XXX */ -static VALUE cState_generate(VALUE self, VALUE obj) +inline static VALUE cState_generate(VALUE self, VALUE obj) { - VALUE result = rb_funcall(obj, i_to_json, 1, self); + VALUE result = cState_partial_generate(self, obj); VALUE re, args[2]; args[0] = rb_str_new2("\\A\\s*(?:\\[.*\\]|\\{.*\\})\\s*\\Z"); args[1] = CRegexp_MULTILINE; @@ -805,6 +781,7 @@ void Init_generator() rb_define_method(cState, "configure", cState_configure, 1); rb_define_method(cState, "to_h", cState_to_h, 0); rb_define_method(cState, "generate", cState_generate, 1); + rb_define_method(cState, "partial_generate", cState_partial_generate, 1); mGeneratorMethods = rb_define_module_under(mGenerator, "GeneratorMethods"); mObject = rb_define_module_under(mGeneratorMethods, "Object"); diff --git a/ext/json/ext/generator/unicode.c b/ext/json/ext/generator/unicode.c index 1d0b675..7bac615 100644 --- a/ext/json/ext/generator/unicode.c +++ b/ext/json/ext/generator/unicode.c @@ -1,4 +1,5 @@ #include "unicode.h" +#include "fbuffer.h" /* * Copyright 2001-2004 Unicode, Inc. @@ -85,7 +86,7 @@ inline static unsigned char isLegalUTF8(const UTF8 *source, int length) return 1; } -inline static void unicode_escape(VALUE buffer, UTF16 character) +inline static void unicode_escape(FBuffer *buffer, UTF16 character) { const char *digits = "0123456789abcdef"; char buf[7] = { '\\', 'u' }; @@ -95,10 +96,10 @@ inline static void unicode_escape(VALUE buffer, UTF16 character) buf[3] = digits[(character >> 8) & 0xf]; buf[4] = digits[(character >> 4) & 0xf]; buf[5] = digits[character & 0xf]; - rb_str_buf_cat(buffer, buf, 6); + fbuffer_append(buffer, buf, 6); } -inline void JSON_convert_UTF8_to_JSON(VALUE buffer, VALUE string) +inline void JSON_convert_UTF8_to_JSON(FBuffer *buffer, VALUE string) { const UTF8* source = (UTF8 *) RSTRING_PTR(string); const UTF8* sourceEnd = source + RSTRING_LEN(string); @@ -141,29 +142,29 @@ inline void JSON_convert_UTF8_to_JSON(VALUE buffer, VALUE string) /* normal case */ switch(ch) { case '\n': - rb_str_buf_cat2(buffer, "\\n"); + fbuffer_append(buffer, "\\n", 2); break; case '\r': - rb_str_buf_cat2(buffer, "\\r"); + fbuffer_append(buffer, "\\r", 2); break; case '\\': - rb_str_buf_cat2(buffer, "\\\\"); + fbuffer_append(buffer, "\\\\", 2); break; case '"': - rb_str_buf_cat2(buffer, "\\\""); + fbuffer_append(buffer, "\\\"", 2); break; case '\t': - rb_str_buf_cat2(buffer, "\\t"); + fbuffer_append(buffer, "\\t", 2); break; case '\f': - rb_str_buf_cat2(buffer, "\\f"); + fbuffer_append(buffer, "\\f", 2); break; case '\b': - rb_str_buf_cat2(buffer, "\\b"); + fbuffer_append(buffer, "\\b", 2); break; default: if (ch >= 0x20 && ch <= 0x7f) { - rb_str_buf_cat(buffer, (char *) source - 1, 1); + fbuffer_append_char(buffer, ch); } else { unicode_escape(buffer, (UTF16) ch); } diff --git a/ext/json/ext/generator/unicode.h b/ext/json/ext/generator/unicode.h index 77b29a4..0652a19 100644 --- a/ext/json/ext/generator/unicode.h +++ b/ext/json/ext/generator/unicode.h @@ -1,4 +1,5 @@ #include "ruby.h" +#include "fbuffer.h" #ifndef _GENERATOR_UNICODE_H_ #define _GENERATOR_UNICODE_H_ @@ -25,7 +26,7 @@ static const int halfShift = 10; /* used for shifting by 10 bits */ static const UTF32 halfBase = 0x0010000UL; static const UTF32 halfMask = 0x3FFUL; -inline void JSON_convert_UTF8_to_JSON(VALUE buffer, VALUE string); +inline void JSON_convert_UTF8_to_JSON(FBuffer *buffer, VALUE string); #ifndef RARRAY_PTR #define RARRAY_PTR(ARRAY) RARRAY(ARRAY)->ptr |