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