00001 #include "../fbuffer/fbuffer.h"
00002 #include "generator.h"
00003
00004 #ifdef HAVE_RUBY_ENCODING_H
00005 static VALUE CEncoding_UTF_8;
00006 static ID i_encoding, i_encode;
00007 #endif
00008
00009 static VALUE mJSON, mExt, mGenerator, cState, mGeneratorMethods, mObject,
00010 mHash, mArray, mFixnum, mBignum, mFloat, mString, mString_Extend,
00011 mTrueClass, mFalseClass, mNilClass, eGeneratorError,
00012 eNestingError, CRegexp_MULTILINE, CJSON_SAFE_STATE_PROTOTYPE,
00013 i_SAFE_STATE_PROTOTYPE;
00014
00015 static ID i_to_s, i_to_json, i_new, i_indent, i_space, i_space_before,
00016 i_object_nl, i_array_nl, i_max_nesting, i_allow_nan, i_ascii_only,
00017 i_quirks_mode, i_pack, i_unpack, i_create_id, i_extend, i_key_p,
00018 i_aref, i_send, i_respond_to_p, i_match, i_keys, i_depth,
00019 i_buffer_initial_length, i_dup;
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050 static const char trailingBytesForUTF8[256] = {
00051 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
00052 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
00053 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
00054 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
00055 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
00056 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
00057 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
00058 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 3,3,3,3,3,3,3,3,4,4,4,4,5,5,5,5
00059 };
00060
00061
00062
00063
00064
00065
00066 static const UTF32 offsetsFromUTF8[6] = { 0x00000000UL, 0x00003080UL, 0x000E2080UL,
00067 0x03C82080UL, 0xFA082080UL, 0x82082080UL };
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079 static unsigned char isLegalUTF8(const UTF8 *source, unsigned long length)
00080 {
00081 UTF8 a;
00082 const UTF8 *srcptr = source+length;
00083 switch (length) {
00084 default: return 0;
00085
00086 case 4: if ((a = (*--srcptr)) < 0x80 || a > 0xBF) return 0;
00087 case 3: if ((a = (*--srcptr)) < 0x80 || a > 0xBF) return 0;
00088 case 2: if ((a = (*--srcptr)) > 0xBF) return 0;
00089
00090 switch (*source) {
00091
00092 case 0xE0: if (a < 0xA0) return 0; break;
00093 case 0xED: if (a > 0x9F) return 0; break;
00094 case 0xF0: if (a < 0x90) return 0; break;
00095 case 0xF4: if (a > 0x8F) return 0; break;
00096 default: if (a < 0x80) return 0;
00097 }
00098
00099 case 1: if (*source >= 0x80 && *source < 0xC2) return 0;
00100 }
00101 if (*source > 0xF4) return 0;
00102 return 1;
00103 }
00104
00105
00106 static void unicode_escape(char *buf, UTF16 character)
00107 {
00108 const char *digits = "0123456789abcdef";
00109
00110 buf[2] = digits[character >> 12];
00111 buf[3] = digits[(character >> 8) & 0xf];
00112 buf[4] = digits[(character >> 4) & 0xf];
00113 buf[5] = digits[character & 0xf];
00114 }
00115
00116
00117
00118 static void unicode_escape_to_buffer(FBuffer *buffer, char buf[6], UTF16
00119 character)
00120 {
00121 unicode_escape(buf, character);
00122 fbuffer_append(buffer, buf, 6);
00123 }
00124
00125
00126
00127 static void convert_UTF8_to_JSON_ASCII(FBuffer *buffer, VALUE string)
00128 {
00129 const UTF8 *source = (UTF8 *) RSTRING_PTR(string);
00130 const UTF8 *sourceEnd = source + RSTRING_LEN(string);
00131 char buf[6] = { '\\', 'u' };
00132
00133 while (source < sourceEnd) {
00134 UTF32 ch = 0;
00135 unsigned short extraBytesToRead = trailingBytesForUTF8[*source];
00136 if (source + extraBytesToRead >= sourceEnd) {
00137 rb_raise(rb_path2class("JSON::GeneratorError"),
00138 "partial character in source, but hit end");
00139 }
00140 if (!isLegalUTF8(source, extraBytesToRead+1)) {
00141 rb_raise(rb_path2class("JSON::GeneratorError"),
00142 "source sequence is illegal/malformed utf-8");
00143 }
00144
00145
00146
00147 switch (extraBytesToRead) {
00148 case 5: ch += *source++; ch <<= 6;
00149 case 4: ch += *source++; ch <<= 6;
00150 case 3: ch += *source++; ch <<= 6;
00151 case 2: ch += *source++; ch <<= 6;
00152 case 1: ch += *source++; ch <<= 6;
00153 case 0: ch += *source++;
00154 }
00155 ch -= offsetsFromUTF8[extraBytesToRead];
00156
00157 if (ch <= UNI_MAX_BMP) {
00158
00159 if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) {
00160 #if UNI_STRICT_CONVERSION
00161 source -= (extraBytesToRead+1);
00162 rb_raise(rb_path2class("JSON::GeneratorError"),
00163 "source sequence is illegal/malformed utf-8");
00164 #else
00165 unicode_escape_to_buffer(buffer, buf, UNI_REPLACEMENT_CHAR);
00166 #endif
00167 } else {
00168
00169 if (ch >= 0x20 && ch <= 0x7f) {
00170 switch (ch) {
00171 case '\\':
00172 fbuffer_append(buffer, "\\\\", 2);
00173 break;
00174 case '"':
00175 fbuffer_append(buffer, "\\\"", 2);
00176 break;
00177 default:
00178 fbuffer_append_char(buffer, (char)ch);
00179 break;
00180 }
00181 } else {
00182 switch (ch) {
00183 case '\n':
00184 fbuffer_append(buffer, "\\n", 2);
00185 break;
00186 case '\r':
00187 fbuffer_append(buffer, "\\r", 2);
00188 break;
00189 case '\t':
00190 fbuffer_append(buffer, "\\t", 2);
00191 break;
00192 case '\f':
00193 fbuffer_append(buffer, "\\f", 2);
00194 break;
00195 case '\b':
00196 fbuffer_append(buffer, "\\b", 2);
00197 break;
00198 default:
00199 unicode_escape_to_buffer(buffer, buf, (UTF16) ch);
00200 break;
00201 }
00202 }
00203 }
00204 } else if (ch > UNI_MAX_UTF16) {
00205 #if UNI_STRICT_CONVERSION
00206 source -= (extraBytesToRead+1);
00207 rb_raise(rb_path2class("JSON::GeneratorError"),
00208 "source sequence is illegal/malformed utf8");
00209 #else
00210 unicode_escape_to_buffer(buffer, buf, UNI_REPLACEMENT_CHAR);
00211 #endif
00212 } else {
00213
00214 ch -= halfBase;
00215 unicode_escape_to_buffer(buffer, buf, (UTF16)((ch >> halfShift) + UNI_SUR_HIGH_START));
00216 unicode_escape_to_buffer(buffer, buf, (UTF16)((ch & halfMask) + UNI_SUR_LOW_START));
00217 }
00218 }
00219 }
00220
00221
00222
00223
00224
00225 static void convert_UTF8_to_JSON(FBuffer *buffer, VALUE string)
00226 {
00227 const char *ptr = RSTRING_PTR(string), *p;
00228 unsigned long len = RSTRING_LEN(string), start = 0, end = 0;
00229 const char *escape = NULL;
00230 int escape_len;
00231 unsigned char c;
00232 char buf[6] = { '\\', 'u' };
00233
00234 for (start = 0, end = 0; end < len;) {
00235 p = ptr + end;
00236 c = (unsigned char) *p;
00237 if (c < 0x20) {
00238 switch (c) {
00239 case '\n':
00240 escape = "\\n";
00241 escape_len = 2;
00242 break;
00243 case '\r':
00244 escape = "\\r";
00245 escape_len = 2;
00246 break;
00247 case '\t':
00248 escape = "\\t";
00249 escape_len = 2;
00250 break;
00251 case '\f':
00252 escape = "\\f";
00253 escape_len = 2;
00254 break;
00255 case '\b':
00256 escape = "\\b";
00257 escape_len = 2;
00258 break;
00259 default:
00260 unicode_escape(buf, (UTF16) *p);
00261 escape = buf;
00262 escape_len = 6;
00263 break;
00264 }
00265 } else {
00266 switch (c) {
00267 case '\\':
00268 escape = "\\\\";
00269 escape_len = 2;
00270 break;
00271 case '"':
00272 escape = "\\\"";
00273 escape_len = 2;
00274 break;
00275 default:
00276 {
00277 unsigned short clen = trailingBytesForUTF8[c] + 1;
00278 if (end + clen > len) {
00279 rb_raise(rb_path2class("JSON::GeneratorError"),
00280 "partial character in source, but hit end");
00281 }
00282 if (!isLegalUTF8((UTF8 *) p, clen)) {
00283 rb_raise(rb_path2class("JSON::GeneratorError"),
00284 "source sequence is illegal/malformed utf-8");
00285 }
00286 end += clen;
00287 }
00288 continue;
00289 break;
00290 }
00291 }
00292 fbuffer_append(buffer, ptr + start, end - start);
00293 fbuffer_append(buffer, escape, escape_len);
00294 start = ++end;
00295 escape = NULL;
00296 }
00297 fbuffer_append(buffer, ptr + start, end - start);
00298 }
00299
00300 static char *fstrndup(const char *ptr, unsigned long len) {
00301 char *result;
00302 if (len <= 0) return NULL;
00303 result = ALLOC_N(char, len);
00304 memccpy(result, ptr, 0, len);
00305 return result;
00306 }
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328 static VALUE mHash_to_json(int argc, VALUE *argv, VALUE self)
00329 {
00330 GENERATE_JSON(object);
00331 }
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341 static VALUE mArray_to_json(int argc, VALUE *argv, VALUE self) {
00342 GENERATE_JSON(array);
00343 }
00344
00345
00346
00347
00348
00349
00350 static VALUE mFixnum_to_json(int argc, VALUE *argv, VALUE self)
00351 {
00352 GENERATE_JSON(fixnum);
00353 }
00354
00355
00356
00357
00358
00359
00360 static VALUE mBignum_to_json(int argc, VALUE *argv, VALUE self)
00361 {
00362 GENERATE_JSON(bignum);
00363 }
00364
00365
00366
00367
00368
00369
00370 static VALUE mFloat_to_json(int argc, VALUE *argv, VALUE self)
00371 {
00372 GENERATE_JSON(float);
00373 }
00374
00375
00376
00377
00378
00379
00380 static VALUE mString_included_s(VALUE self, VALUE modul) {
00381 VALUE result = rb_funcall(modul, i_extend, 1, mString_Extend);
00382 return result;
00383 }
00384
00385
00386
00387
00388
00389
00390
00391
00392 static VALUE mString_to_json(int argc, VALUE *argv, VALUE self)
00393 {
00394 GENERATE_JSON(string);
00395 }
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405 static VALUE mString_to_json_raw_object(VALUE self)
00406 {
00407 VALUE ary;
00408 VALUE result = rb_hash_new();
00409 rb_hash_aset(result, rb_funcall(mJSON, i_create_id, 0), rb_class_name(rb_obj_class(self)));
00410 ary = rb_funcall(self, i_unpack, 1, rb_str_new2("C*"));
00411 rb_hash_aset(result, rb_str_new2("raw"), ary);
00412 return result;
00413 }
00414
00415
00416
00417
00418
00419
00420
00421 static VALUE mString_to_json_raw(int argc, VALUE *argv, VALUE self)
00422 {
00423 VALUE obj = mString_to_json_raw_object(self);
00424 Check_Type(obj, T_HASH);
00425 return mHash_to_json(argc, argv, obj);
00426 }
00427
00428
00429
00430
00431
00432
00433
00434 static VALUE mString_Extend_json_create(VALUE self, VALUE o)
00435 {
00436 VALUE ary;
00437 Check_Type(o, T_HASH);
00438 ary = rb_hash_aref(o, rb_str_new2("raw"));
00439 return rb_funcall(ary, i_pack, 1, rb_str_new2("C*"));
00440 }
00441
00442
00443
00444
00445
00446
00447 static VALUE mTrueClass_to_json(int argc, VALUE *argv, VALUE self)
00448 {
00449 GENERATE_JSON(true);
00450 }
00451
00452
00453
00454
00455
00456
00457 static VALUE mFalseClass_to_json(int argc, VALUE *argv, VALUE self)
00458 {
00459 GENERATE_JSON(false);
00460 }
00461
00462
00463
00464
00465
00466
00467 static VALUE mNilClass_to_json(int argc, VALUE *argv, VALUE self)
00468 {
00469 GENERATE_JSON(null);
00470 }
00471
00472
00473
00474
00475
00476
00477
00478
00479 static VALUE mObject_to_json(int argc, VALUE *argv, VALUE self)
00480 {
00481 VALUE state;
00482 VALUE string = rb_funcall(self, i_to_s, 0);
00483 rb_scan_args(argc, argv, "01", &state);
00484 Check_Type(string, T_STRING);
00485 state = cState_from_state_s(cState, state);
00486 return cState_partial_generate(state, string);
00487 }
00488
00489 static void State_free(JSON_Generator_State *state)
00490 {
00491 if (state->indent) ruby_xfree(state->indent);
00492 if (state->space) ruby_xfree(state->space);
00493 if (state->space_before) ruby_xfree(state->space_before);
00494 if (state->object_nl) ruby_xfree(state->object_nl);
00495 if (state->array_nl) ruby_xfree(state->array_nl);
00496 if (state->array_delim) fbuffer_free(state->array_delim);
00497 if (state->object_delim) fbuffer_free(state->object_delim);
00498 if (state->object_delim2) fbuffer_free(state->object_delim2);
00499 ruby_xfree(state);
00500 }
00501
00502 static JSON_Generator_State *State_allocate()
00503 {
00504 JSON_Generator_State *state = ALLOC(JSON_Generator_State);
00505 MEMZERO(state, JSON_Generator_State, 1);
00506 return state;
00507 }
00508
00509 static VALUE cState_s_allocate(VALUE klass)
00510 {
00511 JSON_Generator_State *state = State_allocate();
00512 return Data_Wrap_Struct(klass, NULL, State_free, state);
00513 }
00514
00515
00516
00517
00518
00519
00520
00521 static VALUE cState_configure(VALUE self, VALUE opts)
00522 {
00523 VALUE tmp;
00524 GET_STATE(self);
00525 tmp = rb_check_convert_type(opts, T_HASH, "Hash", "to_hash");
00526 if (NIL_P(tmp)) tmp = rb_convert_type(opts, T_HASH, "Hash", "to_h");
00527 opts = tmp;
00528 tmp = rb_hash_aref(opts, ID2SYM(i_indent));
00529 if (RTEST(tmp)) {
00530 unsigned long len;
00531 Check_Type(tmp, T_STRING);
00532 len = RSTRING_LEN(tmp);
00533 state->indent = fstrndup(RSTRING_PTR(tmp), len + 1);
00534 state->indent_len = len;
00535 }
00536 tmp = rb_hash_aref(opts, ID2SYM(i_space));
00537 if (RTEST(tmp)) {
00538 unsigned long len;
00539 Check_Type(tmp, T_STRING);
00540 len = RSTRING_LEN(tmp);
00541 state->space = fstrndup(RSTRING_PTR(tmp), len + 1);
00542 state->space_len = len;
00543 }
00544 tmp = rb_hash_aref(opts, ID2SYM(i_space_before));
00545 if (RTEST(tmp)) {
00546 unsigned long len;
00547 Check_Type(tmp, T_STRING);
00548 len = RSTRING_LEN(tmp);
00549 state->space_before = fstrndup(RSTRING_PTR(tmp), len + 1);
00550 state->space_before_len = len;
00551 }
00552 tmp = rb_hash_aref(opts, ID2SYM(i_array_nl));
00553 if (RTEST(tmp)) {
00554 unsigned long len;
00555 Check_Type(tmp, T_STRING);
00556 len = RSTRING_LEN(tmp);
00557 state->array_nl = fstrndup(RSTRING_PTR(tmp), len + 1);
00558 state->array_nl_len = len;
00559 }
00560 tmp = rb_hash_aref(opts, ID2SYM(i_object_nl));
00561 if (RTEST(tmp)) {
00562 unsigned long len;
00563 Check_Type(tmp, T_STRING);
00564 len = RSTRING_LEN(tmp);
00565 state->object_nl = fstrndup(RSTRING_PTR(tmp), len + 1);
00566 state->object_nl_len = len;
00567 }
00568 tmp = ID2SYM(i_max_nesting);
00569 state->max_nesting = 100;
00570 if (option_given_p(opts, tmp)) {
00571 VALUE max_nesting = rb_hash_aref(opts, tmp);
00572 if (RTEST(max_nesting)) {
00573 Check_Type(max_nesting, T_FIXNUM);
00574 state->max_nesting = FIX2LONG(max_nesting);
00575 } else {
00576 state->max_nesting = 0;
00577 }
00578 }
00579 tmp = ID2SYM(i_depth);
00580 state->depth = 0;
00581 if (option_given_p(opts, tmp)) {
00582 VALUE depth = rb_hash_aref(opts, tmp);
00583 if (RTEST(depth)) {
00584 Check_Type(depth, T_FIXNUM);
00585 state->depth = FIX2LONG(depth);
00586 } else {
00587 state->depth = 0;
00588 }
00589 }
00590 tmp = ID2SYM(i_buffer_initial_length);
00591 if (option_given_p(opts, tmp)) {
00592 VALUE buffer_initial_length = rb_hash_aref(opts, tmp);
00593 if (RTEST(buffer_initial_length)) {
00594 long initial_length;
00595 Check_Type(buffer_initial_length, T_FIXNUM);
00596 initial_length = FIX2LONG(buffer_initial_length);
00597 if (initial_length > 0) state->buffer_initial_length = initial_length;
00598 }
00599 }
00600 tmp = rb_hash_aref(opts, ID2SYM(i_allow_nan));
00601 state->allow_nan = RTEST(tmp);
00602 tmp = rb_hash_aref(opts, ID2SYM(i_ascii_only));
00603 state->ascii_only = RTEST(tmp);
00604 tmp = rb_hash_aref(opts, ID2SYM(i_quirks_mode));
00605 state->quirks_mode = RTEST(tmp);
00606 return self;
00607 }
00608
00609 static void set_state_ivars(VALUE hash, VALUE state)
00610 {
00611 VALUE ivars = rb_obj_instance_variables(state);
00612 int i = 0;
00613 for (i = 0; i < RARRAY_LEN(ivars); i++) {
00614 VALUE key = rb_funcall(rb_ary_entry(ivars, i), i_to_s, 0);
00615 long key_len = RSTRING_LEN(key);
00616 VALUE value = rb_iv_get(state, StringValueCStr(key));
00617 rb_hash_aset(hash, rb_str_intern(rb_str_substr(key, 1, key_len - 1)), value);
00618 }
00619 }
00620
00621
00622
00623
00624
00625
00626
00627 static VALUE cState_to_h(VALUE self)
00628 {
00629 VALUE result = rb_hash_new();
00630 GET_STATE(self);
00631 set_state_ivars(result, self);
00632 rb_hash_aset(result, ID2SYM(i_indent), rb_str_new(state->indent, state->indent_len));
00633 rb_hash_aset(result, ID2SYM(i_space), rb_str_new(state->space, state->space_len));
00634 rb_hash_aset(result, ID2SYM(i_space_before), rb_str_new(state->space_before, state->space_before_len));
00635 rb_hash_aset(result, ID2SYM(i_object_nl), rb_str_new(state->object_nl, state->object_nl_len));
00636 rb_hash_aset(result, ID2SYM(i_array_nl), rb_str_new(state->array_nl, state->array_nl_len));
00637 rb_hash_aset(result, ID2SYM(i_allow_nan), state->allow_nan ? Qtrue : Qfalse);
00638 rb_hash_aset(result, ID2SYM(i_ascii_only), state->ascii_only ? Qtrue : Qfalse);
00639 rb_hash_aset(result, ID2SYM(i_quirks_mode), state->quirks_mode ? Qtrue : Qfalse);
00640 rb_hash_aset(result, ID2SYM(i_max_nesting), LONG2FIX(state->max_nesting));
00641 rb_hash_aset(result, ID2SYM(i_depth), LONG2FIX(state->depth));
00642 rb_hash_aset(result, ID2SYM(i_buffer_initial_length), LONG2FIX(state->buffer_initial_length));
00643 return result;
00644 }
00645
00646
00647
00648
00649
00650
00651 static VALUE cState_aref(VALUE self, VALUE name)
00652 {
00653 name = rb_funcall(name, i_to_s, 0);
00654 if (RTEST(rb_funcall(self, i_respond_to_p, 1, name))) {
00655 return rb_funcall(self, i_send, 1, name);
00656 } else {
00657 return rb_ivar_get(self, rb_intern_str(rb_str_concat(rb_str_new2("@"), name)));
00658 }
00659 }
00660
00661
00662
00663
00664
00665
00666 static VALUE cState_aset(VALUE self, VALUE name, VALUE value)
00667 {
00668 VALUE name_writer;
00669
00670 name = rb_funcall(name, i_to_s, 0);
00671 name_writer = rb_str_cat2(rb_str_dup(name), "=");
00672 if (RTEST(rb_funcall(self, i_respond_to_p, 1, name_writer))) {
00673 return rb_funcall(self, i_send, 2, name_writer, value);
00674 } else {
00675 rb_ivar_set(self, rb_intern_str(rb_str_concat(rb_str_new2("@"), name)), value);
00676 }
00677 return Qnil;
00678 }
00679
00680 static void generate_json_object(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj)
00681 {
00682 char *object_nl = state->object_nl;
00683 long object_nl_len = state->object_nl_len;
00684 char *indent = state->indent;
00685 long indent_len = state->indent_len;
00686 long max_nesting = state->max_nesting;
00687 char *delim = FBUFFER_PTR(state->object_delim);
00688 long delim_len = FBUFFER_LEN(state->object_delim);
00689 char *delim2 = FBUFFER_PTR(state->object_delim2);
00690 long delim2_len = FBUFFER_LEN(state->object_delim2);
00691 long depth = ++state->depth;
00692 int i, j;
00693 VALUE key, key_to_s, keys;
00694 if (max_nesting != 0 && depth > max_nesting) {
00695 fbuffer_free(buffer);
00696 rb_raise(eNestingError, "nesting of %ld is too deep", --state->depth);
00697 }
00698 fbuffer_append_char(buffer, '{');
00699 keys = rb_funcall(obj, i_keys, 0);
00700 for(i = 0; i < RARRAY_LEN(keys); i++) {
00701 if (i > 0) fbuffer_append(buffer, delim, delim_len);
00702 if (object_nl) {
00703 fbuffer_append(buffer, object_nl, object_nl_len);
00704 }
00705 if (indent) {
00706 for (j = 0; j < depth; j++) {
00707 fbuffer_append(buffer, indent, indent_len);
00708 }
00709 }
00710 key = rb_ary_entry(keys, i);
00711 key_to_s = rb_funcall(key, i_to_s, 0);
00712 Check_Type(key_to_s, T_STRING);
00713 generate_json(buffer, Vstate, state, key_to_s);
00714 fbuffer_append(buffer, delim2, delim2_len);
00715 generate_json(buffer, Vstate, state, rb_hash_aref(obj, key));
00716 }
00717 depth = --state->depth;
00718 if (object_nl) {
00719 fbuffer_append(buffer, object_nl, object_nl_len);
00720 if (indent) {
00721 for (j = 0; j < depth; j++) {
00722 fbuffer_append(buffer, indent, indent_len);
00723 }
00724 }
00725 }
00726 fbuffer_append_char(buffer, '}');
00727 }
00728
00729 static void generate_json_array(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj)
00730 {
00731 char *array_nl = state->array_nl;
00732 long array_nl_len = state->array_nl_len;
00733 char *indent = state->indent;
00734 long indent_len = state->indent_len;
00735 long max_nesting = state->max_nesting;
00736 char *delim = FBUFFER_PTR(state->array_delim);
00737 long delim_len = FBUFFER_LEN(state->array_delim);
00738 long depth = ++state->depth;
00739 int i, j;
00740 if (max_nesting != 0 && depth > max_nesting) {
00741 fbuffer_free(buffer);
00742 rb_raise(eNestingError, "nesting of %ld is too deep", --state->depth);
00743 }
00744 fbuffer_append_char(buffer, '[');
00745 if (array_nl) fbuffer_append(buffer, array_nl, array_nl_len);
00746 for(i = 0; i < RARRAY_LEN(obj); i++) {
00747 if (i > 0) fbuffer_append(buffer, delim, delim_len);
00748 if (indent) {
00749 for (j = 0; j < depth; j++) {
00750 fbuffer_append(buffer, indent, indent_len);
00751 }
00752 }
00753 generate_json(buffer, Vstate, state, rb_ary_entry(obj, i));
00754 }
00755 state->depth = --depth;
00756 if (array_nl) {
00757 fbuffer_append(buffer, array_nl, array_nl_len);
00758 if (indent) {
00759 for (j = 0; j < depth; j++) {
00760 fbuffer_append(buffer, indent, indent_len);
00761 }
00762 }
00763 }
00764 fbuffer_append_char(buffer, ']');
00765 }
00766
00767 static void generate_json_string(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj)
00768 {
00769 fbuffer_append_char(buffer, '"');
00770 #ifdef HAVE_RUBY_ENCODING_H
00771 obj = rb_funcall(obj, i_encode, 1, CEncoding_UTF_8);
00772 #endif
00773 if (state->ascii_only) {
00774 convert_UTF8_to_JSON_ASCII(buffer, obj);
00775 } else {
00776 convert_UTF8_to_JSON(buffer, obj);
00777 }
00778 fbuffer_append_char(buffer, '"');
00779 }
00780
00781 static void generate_json_null(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj)
00782 {
00783 fbuffer_append(buffer, "null", 4);
00784 }
00785
00786 static void generate_json_false(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj)
00787 {
00788 fbuffer_append(buffer, "false", 5);
00789 }
00790
00791 static void generate_json_true(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj)
00792 {
00793 fbuffer_append(buffer, "true", 4);
00794 }
00795
00796 static void generate_json_fixnum(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj)
00797 {
00798 fbuffer_append_long(buffer, FIX2LONG(obj));
00799 }
00800
00801 static void generate_json_bignum(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj)
00802 {
00803 VALUE tmp = rb_funcall(obj, i_to_s, 0);
00804 fbuffer_append_str(buffer, tmp);
00805 }
00806
00807 static void generate_json_float(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj)
00808 {
00809 double value = RFLOAT_VALUE(obj);
00810 char allow_nan = state->allow_nan;
00811 VALUE tmp = rb_funcall(obj, i_to_s, 0);
00812 if (!allow_nan) {
00813 if (isinf(value)) {
00814 fbuffer_free(buffer);
00815 rb_raise(eGeneratorError, "%u: %s not allowed in JSON", __LINE__, StringValueCStr(tmp));
00816 } else if (isnan(value)) {
00817 fbuffer_free(buffer);
00818 rb_raise(eGeneratorError, "%u: %s not allowed in JSON", __LINE__, StringValueCStr(tmp));
00819 }
00820 }
00821 fbuffer_append_str(buffer, tmp);
00822 }
00823
00824 static void generate_json(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj)
00825 {
00826 VALUE tmp;
00827 VALUE klass = CLASS_OF(obj);
00828 if (klass == rb_cHash) {
00829 generate_json_object(buffer, Vstate, state, obj);
00830 } else if (klass == rb_cArray) {
00831 generate_json_array(buffer, Vstate, state, obj);
00832 } else if (klass == rb_cString) {
00833 generate_json_string(buffer, Vstate, state, obj);
00834 } else if (obj == Qnil) {
00835 generate_json_null(buffer, Vstate, state, obj);
00836 } else if (obj == Qfalse) {
00837 generate_json_false(buffer, Vstate, state, obj);
00838 } else if (obj == Qtrue) {
00839 generate_json_true(buffer, Vstate, state, obj);
00840 } else if (klass == rb_cFixnum) {
00841 generate_json_fixnum(buffer, Vstate, state, obj);
00842 } else if (klass == rb_cBignum) {
00843 generate_json_bignum(buffer, Vstate, state, obj);
00844 } else if (klass == rb_cFloat) {
00845 generate_json_float(buffer, Vstate, state, obj);
00846 } else if (rb_respond_to(obj, i_to_json)) {
00847 tmp = rb_funcall(obj, i_to_json, 1, Vstate);
00848 Check_Type(tmp, T_STRING);
00849 fbuffer_append_str(buffer, tmp);
00850 } else {
00851 tmp = rb_funcall(obj, i_to_s, 0);
00852 Check_Type(tmp, T_STRING);
00853 generate_json(buffer, Vstate, state, tmp);
00854 }
00855 }
00856
00857 static FBuffer *cState_prepare_buffer(VALUE self)
00858 {
00859 FBuffer *buffer;
00860 GET_STATE(self);
00861 buffer = fbuffer_alloc(state->buffer_initial_length);
00862
00863 if (state->object_delim) {
00864 fbuffer_clear(state->object_delim);
00865 } else {
00866 state->object_delim = fbuffer_alloc(16);
00867 }
00868 fbuffer_append_char(state->object_delim, ',');
00869 if (state->object_delim2) {
00870 fbuffer_clear(state->object_delim2);
00871 } else {
00872 state->object_delim2 = fbuffer_alloc(16);
00873 }
00874 fbuffer_append_char(state->object_delim2, ':');
00875 if (state->space) fbuffer_append(state->object_delim2, state->space, state->space_len);
00876
00877 if (state->array_delim) {
00878 fbuffer_clear(state->array_delim);
00879 } else {
00880 state->array_delim = fbuffer_alloc(16);
00881 }
00882 fbuffer_append_char(state->array_delim, ',');
00883 if (state->array_nl) fbuffer_append(state->array_delim, state->array_nl, state->array_nl_len);
00884 return buffer;
00885 }
00886
00887 static VALUE cState_partial_generate(VALUE self, VALUE obj)
00888 {
00889 FBuffer *buffer = cState_prepare_buffer(self);
00890 GET_STATE(self);
00891 generate_json(buffer, self, state, obj);
00892 return fbuffer_to_s(buffer);
00893 }
00894
00895
00896
00897
00898
00899
00900 static int isArrayOrObject(VALUE string)
00901 {
00902 long string_len = RSTRING_LEN(string);
00903 char *p = RSTRING_PTR(string), *q = p + string_len - 1;
00904 if (string_len < 2) return 0;
00905 for (; p < q && isspace((unsigned char)*p); p++);
00906 for (; q > p && isspace((unsigned char)*q); q--);
00907 return (*p == '[' && *q == ']') || (*p == '{' && *q == '}');
00908 }
00909
00910
00911
00912
00913
00914
00915
00916
00917 static VALUE cState_generate(VALUE self, VALUE obj)
00918 {
00919 VALUE result = cState_partial_generate(self, obj);
00920 GET_STATE(self);
00921 if (!state->quirks_mode && !isArrayOrObject(result)) {
00922 rb_raise(eGeneratorError, "only generation of JSON objects or arrays allowed");
00923 }
00924 return result;
00925 }
00926
00927
00928
00929
00930
00931
00932
00933
00934
00935
00936
00937
00938
00939
00940
00941
00942
00943
00944
00945
00946
00947 static VALUE cState_initialize(int argc, VALUE *argv, VALUE self)
00948 {
00949 VALUE opts;
00950 GET_STATE(self);
00951 state->max_nesting = 100;
00952 state->buffer_initial_length = FBUFFER_INITIAL_LENGTH_DEFAULT;
00953 rb_scan_args(argc, argv, "01", &opts);
00954 if (!NIL_P(opts)) cState_configure(self, opts);
00955 return self;
00956 }
00957
00958
00959
00960
00961
00962
00963
00964 static VALUE cState_init_copy(VALUE obj, VALUE orig)
00965 {
00966 JSON_Generator_State *objState, *origState;
00967
00968 if (obj == orig) return obj;
00969 Data_Get_Struct(obj, JSON_Generator_State, objState);
00970 Data_Get_Struct(orig, JSON_Generator_State, origState);
00971 if (!objState) rb_raise(rb_eArgError, "unallocated JSON::State");
00972
00973 MEMCPY(objState, origState, JSON_Generator_State, 1);
00974 objState->indent = fstrndup(origState->indent, origState->indent_len);
00975 objState->space = fstrndup(origState->space, origState->space_len);
00976 objState->space_before = fstrndup(origState->space_before, origState->space_before_len);
00977 objState->object_nl = fstrndup(origState->object_nl, origState->object_nl_len);
00978 objState->array_nl = fstrndup(origState->array_nl, origState->array_nl_len);
00979 if (origState->array_delim) objState->array_delim = fbuffer_dup(origState->array_delim);
00980 if (origState->object_delim) objState->object_delim = fbuffer_dup(origState->object_delim);
00981 if (origState->object_delim2) objState->object_delim2 = fbuffer_dup(origState->object_delim2);
00982 return obj;
00983 }
00984
00985
00986
00987
00988
00989
00990
00991
00992 static VALUE cState_from_state_s(VALUE self, VALUE opts)
00993 {
00994 if (rb_obj_is_kind_of(opts, self)) {
00995 return opts;
00996 } else if (rb_obj_is_kind_of(opts, rb_cHash)) {
00997 return rb_funcall(self, i_new, 1, opts);
00998 } else {
00999 if (NIL_P(CJSON_SAFE_STATE_PROTOTYPE)) {
01000 CJSON_SAFE_STATE_PROTOTYPE = rb_const_get(mJSON, i_SAFE_STATE_PROTOTYPE);
01001 }
01002 return rb_funcall(CJSON_SAFE_STATE_PROTOTYPE, i_dup, 0);
01003 }
01004 }
01005
01006
01007
01008
01009
01010
01011 static VALUE cState_indent(VALUE self)
01012 {
01013 GET_STATE(self);
01014 return state->indent ? rb_str_new(state->indent, state->indent_len) : rb_str_new2("");
01015 }
01016
01017
01018
01019
01020
01021
01022 static VALUE cState_indent_set(VALUE self, VALUE indent)
01023 {
01024 unsigned long len;
01025 GET_STATE(self);
01026 Check_Type(indent, T_STRING);
01027 len = RSTRING_LEN(indent);
01028 if (len == 0) {
01029 if (state->indent) {
01030 ruby_xfree(state->indent);
01031 state->indent = NULL;
01032 state->indent_len = 0;
01033 }
01034 } else {
01035 if (state->indent) ruby_xfree(state->indent);
01036 state->indent = strdup(RSTRING_PTR(indent));
01037 state->indent_len = len;
01038 }
01039 return Qnil;
01040 }
01041
01042
01043
01044
01045
01046
01047
01048 static VALUE cState_space(VALUE self)
01049 {
01050 GET_STATE(self);
01051 return state->space ? rb_str_new(state->space, state->space_len) : rb_str_new2("");
01052 }
01053
01054
01055
01056
01057
01058
01059
01060 static VALUE cState_space_set(VALUE self, VALUE space)
01061 {
01062 unsigned long len;
01063 GET_STATE(self);
01064 Check_Type(space, T_STRING);
01065 len = RSTRING_LEN(space);
01066 if (len == 0) {
01067 if (state->space) {
01068 ruby_xfree(state->space);
01069 state->space = NULL;
01070 state->space_len = 0;
01071 }
01072 } else {
01073 if (state->space) ruby_xfree(state->space);
01074 state->space = strdup(RSTRING_PTR(space));
01075 state->space_len = len;
01076 }
01077 return Qnil;
01078 }
01079
01080
01081
01082
01083
01084
01085 static VALUE cState_space_before(VALUE self)
01086 {
01087 GET_STATE(self);
01088 return state->space_before ? rb_str_new(state->space_before, state->space_before_len) : rb_str_new2("");
01089 }
01090
01091
01092
01093
01094
01095
01096 static VALUE cState_space_before_set(VALUE self, VALUE space_before)
01097 {
01098 unsigned long len;
01099 GET_STATE(self);
01100 Check_Type(space_before, T_STRING);
01101 len = RSTRING_LEN(space_before);
01102 if (len == 0) {
01103 if (state->space_before) {
01104 ruby_xfree(state->space_before);
01105 state->space_before = NULL;
01106 state->space_before_len = 0;
01107 }
01108 } else {
01109 if (state->space_before) ruby_xfree(state->space_before);
01110 state->space_before = strdup(RSTRING_PTR(space_before));
01111 state->space_before_len = len;
01112 }
01113 return Qnil;
01114 }
01115
01116
01117
01118
01119
01120
01121
01122 static VALUE cState_object_nl(VALUE self)
01123 {
01124 GET_STATE(self);
01125 return state->object_nl ? rb_str_new(state->object_nl, state->object_nl_len) : rb_str_new2("");
01126 }
01127
01128
01129
01130
01131
01132
01133
01134 static VALUE cState_object_nl_set(VALUE self, VALUE object_nl)
01135 {
01136 unsigned long len;
01137 GET_STATE(self);
01138 Check_Type(object_nl, T_STRING);
01139 len = RSTRING_LEN(object_nl);
01140 if (len == 0) {
01141 if (state->object_nl) {
01142 ruby_xfree(state->object_nl);
01143 state->object_nl = NULL;
01144 }
01145 } else {
01146 if (state->object_nl) ruby_xfree(state->object_nl);
01147 state->object_nl = strdup(RSTRING_PTR(object_nl));
01148 state->object_nl_len = len;
01149 }
01150 return Qnil;
01151 }
01152
01153
01154
01155
01156
01157
01158 static VALUE cState_array_nl(VALUE self)
01159 {
01160 GET_STATE(self);
01161 return state->array_nl ? rb_str_new(state->array_nl, state->array_nl_len) : rb_str_new2("");
01162 }
01163
01164
01165
01166
01167
01168
01169 static VALUE cState_array_nl_set(VALUE self, VALUE array_nl)
01170 {
01171 unsigned long len;
01172 GET_STATE(self);
01173 Check_Type(array_nl, T_STRING);
01174 len = RSTRING_LEN(array_nl);
01175 if (len == 0) {
01176 if (state->array_nl) {
01177 ruby_xfree(state->array_nl);
01178 state->array_nl = NULL;
01179 }
01180 } else {
01181 if (state->array_nl) ruby_xfree(state->array_nl);
01182 state->array_nl = strdup(RSTRING_PTR(array_nl));
01183 state->array_nl_len = len;
01184 }
01185 return Qnil;
01186 }
01187
01188
01189
01190
01191
01192
01193
01194
01195 static VALUE cState_check_circular_p(VALUE self)
01196 {
01197 GET_STATE(self);
01198 return state->max_nesting ? Qtrue : Qfalse;
01199 }
01200
01201
01202
01203
01204
01205
01206
01207 static VALUE cState_max_nesting(VALUE self)
01208 {
01209 GET_STATE(self);
01210 return LONG2FIX(state->max_nesting);
01211 }
01212
01213
01214
01215
01216
01217
01218
01219 static VALUE cState_max_nesting_set(VALUE self, VALUE depth)
01220 {
01221 GET_STATE(self);
01222 Check_Type(depth, T_FIXNUM);
01223 return state->max_nesting = FIX2LONG(depth);
01224 }
01225
01226
01227
01228
01229
01230
01231
01232 static VALUE cState_allow_nan_p(VALUE self)
01233 {
01234 GET_STATE(self);
01235 return state->allow_nan ? Qtrue : Qfalse;
01236 }
01237
01238
01239
01240
01241
01242
01243
01244 static VALUE cState_ascii_only_p(VALUE self)
01245 {
01246 GET_STATE(self);
01247 return state->ascii_only ? Qtrue : Qfalse;
01248 }
01249
01250
01251
01252
01253
01254
01255 static VALUE cState_quirks_mode_p(VALUE self)
01256 {
01257 GET_STATE(self);
01258 return state->quirks_mode ? Qtrue : Qfalse;
01259 }
01260
01261
01262
01263
01264
01265
01266 static VALUE cState_quirks_mode_set(VALUE self, VALUE enable)
01267 {
01268 GET_STATE(self);
01269 state->quirks_mode = RTEST(enable);
01270 return Qnil;
01271 }
01272
01273
01274
01275
01276
01277
01278 static VALUE cState_depth(VALUE self)
01279 {
01280 GET_STATE(self);
01281 return LONG2FIX(state->depth);
01282 }
01283
01284
01285
01286
01287
01288
01289
01290 static VALUE cState_depth_set(VALUE self, VALUE depth)
01291 {
01292 GET_STATE(self);
01293 Check_Type(depth, T_FIXNUM);
01294 state->depth = FIX2LONG(depth);
01295 return Qnil;
01296 }
01297
01298
01299
01300
01301
01302
01303 static VALUE cState_buffer_initial_length(VALUE self)
01304 {
01305 GET_STATE(self);
01306 return LONG2FIX(state->buffer_initial_length);
01307 }
01308
01309
01310
01311
01312
01313
01314
01315 static VALUE cState_buffer_initial_length_set(VALUE self, VALUE buffer_initial_length)
01316 {
01317 long initial_length;
01318 GET_STATE(self);
01319 Check_Type(buffer_initial_length, T_FIXNUM);
01320 initial_length = FIX2LONG(buffer_initial_length);
01321 if (initial_length > 0) {
01322 state->buffer_initial_length = initial_length;
01323 }
01324 return Qnil;
01325 }
01326
01327
01328
01329
01330 void Init_generator()
01331 {
01332 rb_require("json/common");
01333
01334 mJSON = rb_define_module("JSON");
01335 mExt = rb_define_module_under(mJSON, "Ext");
01336 mGenerator = rb_define_module_under(mExt, "Generator");
01337
01338 eGeneratorError = rb_path2class("JSON::GeneratorError");
01339 eNestingError = rb_path2class("JSON::NestingError");
01340
01341 cState = rb_define_class_under(mGenerator, "State", rb_cObject);
01342 rb_define_alloc_func(cState, cState_s_allocate);
01343 rb_define_singleton_method(cState, "from_state", cState_from_state_s, 1);
01344 rb_define_method(cState, "initialize", cState_initialize, -1);
01345 rb_define_method(cState, "initialize_copy", cState_init_copy, 1);
01346 rb_define_method(cState, "indent", cState_indent, 0);
01347 rb_define_method(cState, "indent=", cState_indent_set, 1);
01348 rb_define_method(cState, "space", cState_space, 0);
01349 rb_define_method(cState, "space=", cState_space_set, 1);
01350 rb_define_method(cState, "space_before", cState_space_before, 0);
01351 rb_define_method(cState, "space_before=", cState_space_before_set, 1);
01352 rb_define_method(cState, "object_nl", cState_object_nl, 0);
01353 rb_define_method(cState, "object_nl=", cState_object_nl_set, 1);
01354 rb_define_method(cState, "array_nl", cState_array_nl, 0);
01355 rb_define_method(cState, "array_nl=", cState_array_nl_set, 1);
01356 rb_define_method(cState, "max_nesting", cState_max_nesting, 0);
01357 rb_define_method(cState, "max_nesting=", cState_max_nesting_set, 1);
01358 rb_define_method(cState, "check_circular?", cState_check_circular_p, 0);
01359 rb_define_method(cState, "allow_nan?", cState_allow_nan_p, 0);
01360 rb_define_method(cState, "ascii_only?", cState_ascii_only_p, 0);
01361 rb_define_method(cState, "quirks_mode?", cState_quirks_mode_p, 0);
01362 rb_define_method(cState, "quirks_mode", cState_quirks_mode_p, 0);
01363 rb_define_method(cState, "quirks_mode=", cState_quirks_mode_set, 1);
01364 rb_define_method(cState, "depth", cState_depth, 0);
01365 rb_define_method(cState, "depth=", cState_depth_set, 1);
01366 rb_define_method(cState, "buffer_initial_length", cState_buffer_initial_length, 0);
01367 rb_define_method(cState, "buffer_initial_length=", cState_buffer_initial_length_set, 1);
01368 rb_define_method(cState, "configure", cState_configure, 1);
01369 rb_define_alias(cState, "merge", "configure");
01370 rb_define_method(cState, "to_h", cState_to_h, 0);
01371 rb_define_alias(cState, "to_hash", "to_h");
01372 rb_define_method(cState, "[]", cState_aref, 1);
01373 rb_define_method(cState, "[]=", cState_aset, 2);
01374 rb_define_method(cState, "generate", cState_generate, 1);
01375
01376 mGeneratorMethods = rb_define_module_under(mGenerator, "GeneratorMethods");
01377 mObject = rb_define_module_under(mGeneratorMethods, "Object");
01378 rb_define_method(mObject, "to_json", mObject_to_json, -1);
01379 mHash = rb_define_module_under(mGeneratorMethods, "Hash");
01380 rb_define_method(mHash, "to_json", mHash_to_json, -1);
01381 mArray = rb_define_module_under(mGeneratorMethods, "Array");
01382 rb_define_method(mArray, "to_json", mArray_to_json, -1);
01383 mFixnum = rb_define_module_under(mGeneratorMethods, "Fixnum");
01384 rb_define_method(mFixnum, "to_json", mFixnum_to_json, -1);
01385 mBignum = rb_define_module_under(mGeneratorMethods, "Bignum");
01386 rb_define_method(mBignum, "to_json", mBignum_to_json, -1);
01387 mFloat = rb_define_module_under(mGeneratorMethods, "Float");
01388 rb_define_method(mFloat, "to_json", mFloat_to_json, -1);
01389 mString = rb_define_module_under(mGeneratorMethods, "String");
01390 rb_define_singleton_method(mString, "included", mString_included_s, 1);
01391 rb_define_method(mString, "to_json", mString_to_json, -1);
01392 rb_define_method(mString, "to_json_raw", mString_to_json_raw, -1);
01393 rb_define_method(mString, "to_json_raw_object", mString_to_json_raw_object, 0);
01394 mString_Extend = rb_define_module_under(mString, "Extend");
01395 rb_define_method(mString_Extend, "json_create", mString_Extend_json_create, 1);
01396 mTrueClass = rb_define_module_under(mGeneratorMethods, "TrueClass");
01397 rb_define_method(mTrueClass, "to_json", mTrueClass_to_json, -1);
01398 mFalseClass = rb_define_module_under(mGeneratorMethods, "FalseClass");
01399 rb_define_method(mFalseClass, "to_json", mFalseClass_to_json, -1);
01400 mNilClass = rb_define_module_under(mGeneratorMethods, "NilClass");
01401 rb_define_method(mNilClass, "to_json", mNilClass_to_json, -1);
01402
01403 CRegexp_MULTILINE = rb_const_get(rb_cRegexp, rb_intern("MULTILINE"));
01404 i_to_s = rb_intern("to_s");
01405 i_to_json = rb_intern("to_json");
01406 i_new = rb_intern("new");
01407 i_indent = rb_intern("indent");
01408 i_space = rb_intern("space");
01409 i_space_before = rb_intern("space_before");
01410 i_object_nl = rb_intern("object_nl");
01411 i_array_nl = rb_intern("array_nl");
01412 i_max_nesting = rb_intern("max_nesting");
01413 i_allow_nan = rb_intern("allow_nan");
01414 i_ascii_only = rb_intern("ascii_only");
01415 i_quirks_mode = rb_intern("quirks_mode");
01416 i_depth = rb_intern("depth");
01417 i_buffer_initial_length = rb_intern("buffer_initial_length");
01418 i_pack = rb_intern("pack");
01419 i_unpack = rb_intern("unpack");
01420 i_create_id = rb_intern("create_id");
01421 i_extend = rb_intern("extend");
01422 i_key_p = rb_intern("key?");
01423 i_aref = rb_intern("[]");
01424 i_send = rb_intern("__send__");
01425 i_respond_to_p = rb_intern("respond_to?");
01426 i_match = rb_intern("match");
01427 i_keys = rb_intern("keys");
01428 i_dup = rb_intern("dup");
01429 #ifdef HAVE_RUBY_ENCODING_H
01430 CEncoding_UTF_8 = rb_funcall(rb_path2class("Encoding"), rb_intern("find"), 1, rb_str_new2("utf-8"));
01431 i_encoding = rb_intern("encoding");
01432 i_encode = rb_intern("encode");
01433 #endif
01434 i_SAFE_STATE_PROTOTYPE = rb_intern("SAFE_STATE_PROTOTYPE");
01435 CJSON_SAFE_STATE_PROTOTYPE = Qnil;
01436 }
01437