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