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