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