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