Ruby 1.9.3p327(2012-11-10revision37606)
|
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 * Copyright 2001-2004 Unicode, Inc. 00021 * 00022 * Disclaimer 00023 * 00024 * This source code is provided as is by Unicode, Inc. No claims are 00025 * made as to fitness for any particular purpose. No warranties of any 00026 * kind are expressed or implied. The recipient agrees to determine 00027 * applicability of information provided. If this file has been 00028 * purchased on magnetic or optical media from Unicode, Inc., the 00029 * sole remedy for any claim will be exchange of defective media 00030 * within 90 days of receipt. 00031 * 00032 * Limitations on Rights to Redistribute This Code 00033 * 00034 * Unicode, Inc. hereby grants the right to freely use the information 00035 * supplied in this file in the creation of products supporting the 00036 * Unicode Standard, and to make copies of this file in any form 00037 * for internal or external distribution as long as this notice 00038 * remains attached. 00039 */ 00040 00041 /* 00042 * Index into the table below with the first byte of a UTF-8 sequence to 00043 * get the number of trailing bytes that are supposed to follow it. 00044 * Note that *legal* UTF-8 values can't have 4 or 5-bytes. The table is 00045 * left as-is for anyone who may want to do such conversion, which was 00046 * allowed in earlier algorithms. 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 * Magic values subtracted from a buffer value during UTF8 conversion. 00061 * This table contains as many values as there might be trailing bytes 00062 * in a UTF-8 sequence. 00063 */ 00064 static const UTF32 offsetsFromUTF8[6] = { 0x00000000UL, 0x00003080UL, 0x000E2080UL, 00065 0x03C82080UL, 0xFA082080UL, 0x82082080UL }; 00066 00067 /* 00068 * Utility routine to tell whether a sequence of bytes is legal UTF-8. 00069 * This must be called with the length pre-determined by the first byte. 00070 * If not calling this from ConvertUTF8to*, then the length can be set by: 00071 * length = trailingBytesForUTF8[*source]+1; 00072 * and the sequence is illegal right away if there aren't that many bytes 00073 * available. 00074 * If presented with a length > 4, this returns 0. The Unicode 00075 * definition of UTF-8 goes up to 4-byte sequences. 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 /* Everything else falls through when "1"... */ 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 /* no fall-through in this inner switch */ 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 /* Escapes the UTF16 character and stores the result in the buffer buf. */ 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 /* Escapes the UTF16 character and stores the result in the buffer buf, then 00115 * the buffer buf іs appended to the FBuffer buffer. */ 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 /* Converts string to a JSON string in FBuffer buffer, where all but the ASCII 00124 * and control characters are JSON escaped. */ 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 * The cases all fall through. See "Note A" below. 00144 */ 00145 switch (extraBytesToRead) { 00146 case 5: ch += *source++; ch <<= 6; /* remember, illegal UTF-8 */ 00147 case 4: ch += *source++; ch <<= 6; /* remember, illegal UTF-8 */ 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) { /* Target is a character <= 0xFFFF */ 00156 /* UTF-16 surrogate values are illegal in UTF-32 */ 00157 if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) { 00158 #if UNI_STRICT_CONVERSION 00159 source -= (extraBytesToRead+1); /* return to the illegal value itself */ 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 /* normal case */ 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); /* return to the start */ 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 /* target is a character in range 0xFFFF - 0x10FFFF. */ 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 /* Converts string to a JSON string in FBuffer buffer, where only the 00220 * characters required by the JSON standard are JSON escaped. The remaining 00221 * characters (should be UTF8) are just passed through and appended to the 00222 * result. */ 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 /* fbuffer implementation */ 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 * Document-module: JSON::Ext::Generator 00414 * 00415 * This is the JSON generator implemented as a C extension. It can be 00416 * configured to be used by setting 00417 * 00418 * JSON.generator = JSON::Ext::Generator 00419 * 00420 * with the method generator= in JSON. 00421 * 00422 */ 00423 00424 /* 00425 * call-seq: to_json(state = nil) 00426 * 00427 * Returns a JSON string containing a JSON object, that is generated from 00428 * this Hash instance. 00429 * _state_ is a JSON::State object, that can also be used to configure the 00430 * produced JSON string output further. 00431 */ 00432 static VALUE mHash_to_json(int argc, VALUE *argv, VALUE self) 00433 { 00434 GENERATE_JSON(object); 00435 } 00436 00437 /* 00438 * call-seq: to_json(state = nil) 00439 * 00440 * Returns a JSON string containing a JSON array, that is generated from 00441 * this Array instance. 00442 * _state_ is a JSON::State object, that can also be used to configure the 00443 * produced JSON string output further. 00444 */ 00445 static VALUE mArray_to_json(int argc, VALUE *argv, VALUE self) { 00446 GENERATE_JSON(array); 00447 } 00448 00449 /* 00450 * call-seq: to_json(*) 00451 * 00452 * Returns a JSON string representation for this Integer number. 00453 */ 00454 static VALUE mFixnum_to_json(int argc, VALUE *argv, VALUE self) 00455 { 00456 GENERATE_JSON(fixnum); 00457 } 00458 00459 /* 00460 * call-seq: to_json(*) 00461 * 00462 * Returns a JSON string representation for this Integer number. 00463 */ 00464 static VALUE mBignum_to_json(int argc, VALUE *argv, VALUE self) 00465 { 00466 GENERATE_JSON(bignum); 00467 } 00468 00469 /* 00470 * call-seq: to_json(*) 00471 * 00472 * Returns a JSON string representation for this Float number. 00473 */ 00474 static VALUE mFloat_to_json(int argc, VALUE *argv, VALUE self) 00475 { 00476 GENERATE_JSON(float); 00477 } 00478 00479 /* 00480 * call-seq: String.included(modul) 00481 * 00482 * Extends _modul_ with the String::Extend module. 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 * call-seq: to_json(*) 00491 * 00492 * This string should be encoded with UTF-8 A call to this method 00493 * returns a JSON string encoded with UTF16 big endian characters as 00494 * \u????. 00495 */ 00496 static VALUE mString_to_json(int argc, VALUE *argv, VALUE self) 00497 { 00498 GENERATE_JSON(string); 00499 } 00500 00501 /* 00502 * call-seq: to_json_raw_object() 00503 * 00504 * This method creates a raw object hash, that can be nested into 00505 * other data structures and will be generated as a raw string. This 00506 * method should be used, if you want to convert raw strings to JSON 00507 * instead of UTF-8 strings, e. g. binary data. 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 * call-seq: to_json_raw(*args) 00521 * 00522 * This method creates a JSON text from the result of a call to 00523 * to_json_raw_object of this String. 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 * call-seq: json_create(o) 00534 * 00535 * Raw Strings are JSON Objects (the raw bytes are stored in an array for the 00536 * key "raw"). The Ruby String can be created by this module method. 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 * call-seq: to_json(*) 00548 * 00549 * Returns a JSON string for true: 'true'. 00550 */ 00551 static VALUE mTrueClass_to_json(int argc, VALUE *argv, VALUE self) 00552 { 00553 GENERATE_JSON(true); 00554 } 00555 00556 /* 00557 * call-seq: to_json(*) 00558 * 00559 * Returns a JSON string for false: 'false'. 00560 */ 00561 static VALUE mFalseClass_to_json(int argc, VALUE *argv, VALUE self) 00562 { 00563 GENERATE_JSON(false); 00564 } 00565 00566 /* 00567 * call-seq: to_json(*) 00568 * 00569 * Returns a JSON string for nil: 'null'. 00570 */ 00571 static VALUE mNilClass_to_json(int argc, VALUE *argv, VALUE self) 00572 { 00573 GENERATE_JSON(null); 00574 } 00575 00576 /* 00577 * call-seq: to_json(*) 00578 * 00579 * Converts this object to a string (calling #to_s), converts 00580 * it to a JSON string, and returns the result. This is a fallback, if no 00581 * special method #to_json was defined for some object. 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 * call-seq: configure(opts) 00621 * 00622 * Configure this State instance with the Hash _opts_, and return 00623 * itself. 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 * call-seq: to_h 00708 * 00709 * Returns the configuration instance variables as a hash, that can be 00710 * passed to the configure method. 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 * call-seq: [](name) 00731 * 00732 * Return the value returned by method +name+. 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 * call-seq: generate(obj) 00968 * 00969 * Generates a valid JSON document from object +obj+ and returns the 00970 * result. If no valid JSON document can be created this method raises a 00971 * GeneratorError exception. 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 * call-seq: new(opts = {}) 00991 * 00992 * Instantiates a new State object, configured by _opts_. 00993 * 00994 * _opts_ can have the following keys: 00995 * 00996 * * *indent*: a string used to indent levels (default: ''), 00997 * * *space*: a string that is put after, a : or , delimiter (default: ''), 00998 * * *space_before*: a string that is put before a : pair delimiter (default: ''), 00999 * * *object_nl*: a string that is put at the end of a JSON object (default: ''), 01000 * * *array_nl*: a string that is put at the end of a JSON array (default: ''), 01001 * * *allow_nan*: true if NaN, Infinity, and -Infinity should be 01002 * generated, otherwise an exception is thrown, if these values are 01003 * encountered. This options defaults to false. 01004 * * *quirks_mode*: Enables quirks_mode for parser, that is for example 01005 * generating single JSON values instead of documents is possible. 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 * call-seq: initialize_copy(orig) 01019 * 01020 * Initializes this object from orig if it to be duplicated/cloned and returns 01021 * it. 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 * call-seq: from_state(opts) 01045 * 01046 * Creates a State object from _opts_, which ought to be Hash to create a 01047 * new State instance configured by _opts_, something else to create an 01048 * unconfigured instance. If _opts_ is a State object, it is just returned. 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 * call-seq: indent() 01066 * 01067 * This string is used to indent levels in the JSON text. 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 * call-seq: indent=(indent) 01077 * 01078 * This string is used to indent levels in the JSON text. 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 * call-seq: space() 01102 * 01103 * This string is used to insert a space between the tokens in a JSON 01104 * string. 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 * call-seq: space=(space) 01114 * 01115 * This string is used to insert a space between the tokens in a JSON 01116 * string. 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 * call-seq: space_before() 01140 * 01141 * This string is used to insert a space before the ':' in JSON objects. 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 * call-seq: space_before=(space_before) 01151 * 01152 * This string is used to insert a space before the ':' in JSON objects. 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 * call-seq: object_nl() 01176 * 01177 * This string is put at the end of a line that holds a JSON object (or 01178 * Hash). 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 * call-seq: object_nl=(object_nl) 01188 * 01189 * This string is put at the end of a line that holds a JSON object (or 01190 * Hash). 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 * call-seq: array_nl() 01213 * 01214 * This string is put at the end of a line that holds a JSON array. 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 * call-seq: array_nl=(array_nl) 01224 * 01225 * This string is put at the end of a line that holds a JSON array. 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 * call-seq: check_circular? 01249 * 01250 * Returns true, if circular data structures should be checked, 01251 * otherwise returns false. 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 * call-seq: max_nesting 01261 * 01262 * This integer returns the maximum level of data structure nesting in 01263 * the generated JSON, max_nesting = 0 if no maximum is checked. 01264 */ 01265 static VALUE cState_max_nesting(VALUE self) 01266 { 01267 GET_STATE(self); 01268 return LONG2FIX(state->max_nesting); 01269 } 01270 01271 /* 01272 * call-seq: max_nesting=(depth) 01273 * 01274 * This sets the maximum level of data structure nesting in the generated JSON 01275 * to the integer depth, max_nesting = 0 if no maximum should be checked. 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 * call-seq: allow_nan? 01286 * 01287 * Returns true, if NaN, Infinity, and -Infinity should be generated, otherwise 01288 * returns false. 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 * call-seq: ascii_only? 01298 * 01299 * Returns true, if NaN, Infinity, and -Infinity should be generated, otherwise 01300 * returns false. 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 * call-seq: quirks_mode? 01310 * 01311 * Returns true, if quirks mode is enabled. Otherwise returns false. 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 * call-seq: quirks_mode=(enable) 01321 * 01322 * If set to true, enables the quirks_mode mode. 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 * call-seq: depth 01333 * 01334 * This integer returns the current depth of data structure nesting. 01335 */ 01336 static VALUE cState_depth(VALUE self) 01337 { 01338 GET_STATE(self); 01339 return LONG2FIX(state->depth); 01340 } 01341 01342 /* 01343 * call-seq: depth=(depth) 01344 * 01345 * This sets the maximum level of data structure nesting in the generated JSON 01346 * to the integer depth, max_nesting = 0 if no maximum should be checked. 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