• Main Page
  • Modules
  • Data Structures
  • Files
  • File List
  • Globals

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

Generated on Wed Sep 8 2010 21:53:50 for Ruby by  doxygen 1.7.1