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