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