Ruby  1.9.3p551(2014-11-13revision48407)
generator.c
Go to the documentation of this file.
1 #include "generator.h"
2 
3 #ifdef HAVE_RUBY_ENCODING_H
4 static VALUE CEncoding_UTF_8;
5 static ID i_encoding, i_encode;
6 #endif
7 
8 #ifdef PRIsVALUE
9 # define RB_OBJ_CLASSNAME(obj) rb_obj_class(obj)
10 # define RB_OBJ_STRING(obj) (obj)
11 #else
12 # define PRIsVALUE "s"
13 # define RB_OBJ_CLASSNAME(obj) rb_obj_classname(obj)
14 # define RB_OBJ_STRING(obj) StringValueCStr(obj)
15 #endif
16 
22 
27 
28 /*
29  * Copyright 2001-2004 Unicode, Inc.
30  *
31  * Disclaimer
32  *
33  * This source code is provided as is by Unicode, Inc. No claims are
34  * made as to fitness for any particular purpose. No warranties of any
35  * kind are expressed or implied. The recipient agrees to determine
36  * applicability of information provided. If this file has been
37  * purchased on magnetic or optical media from Unicode, Inc., the
38  * sole remedy for any claim will be exchange of defective media
39  * within 90 days of receipt.
40  *
41  * Limitations on Rights to Redistribute This Code
42  *
43  * Unicode, Inc. hereby grants the right to freely use the information
44  * supplied in this file in the creation of products supporting the
45  * Unicode Standard, and to make copies of this file in any form
46  * for internal or external distribution as long as this notice
47  * remains attached.
48  */
49 
50 /*
51  * Index into the table below with the first byte of a UTF-8 sequence to
52  * get the number of trailing bytes that are supposed to follow it.
53  * Note that *legal* UTF-8 values can't have 4 or 5-bytes. The table is
54  * left as-is for anyone who may want to do such conversion, which was
55  * allowed in earlier algorithms.
56  */
57 static const char trailingBytesForUTF8[256] = {
58  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,
59  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,
60  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,
61  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,
62  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,
63  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,
64  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,
65  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
66 };
67 
68 /*
69  * Magic values subtracted from a buffer value during UTF8 conversion.
70  * This table contains as many values as there might be trailing bytes
71  * in a UTF-8 sequence.
72  */
73 static const UTF32 offsetsFromUTF8[6] = { 0x00000000UL, 0x00003080UL, 0x000E2080UL,
74  0x03C82080UL, 0xFA082080UL, 0x82082080UL };
75 
76 /*
77  * Utility routine to tell whether a sequence of bytes is legal UTF-8.
78  * This must be called with the length pre-determined by the first byte.
79  * If not calling this from ConvertUTF8to*, then the length can be set by:
80  * length = trailingBytesForUTF8[*source]+1;
81  * and the sequence is illegal right away if there aren't that many bytes
82  * available.
83  * If presented with a length > 4, this returns 0. The Unicode
84  * definition of UTF-8 goes up to 4-byte sequences.
85  */
86 static unsigned char isLegalUTF8(const UTF8 *source, unsigned long length)
87 {
88  UTF8 a;
89  const UTF8 *srcptr = source+length;
90  switch (length) {
91  default: return 0;
92  /* Everything else falls through when "1"... */
93  case 4: if ((a = (*--srcptr)) < 0x80 || a > 0xBF) return 0;
94  case 3: if ((a = (*--srcptr)) < 0x80 || a > 0xBF) return 0;
95  case 2: if ((a = (*--srcptr)) > 0xBF) return 0;
96 
97  switch (*source) {
98  /* no fall-through in this inner switch */
99  case 0xE0: if (a < 0xA0) return 0; break;
100  case 0xED: if (a > 0x9F) return 0; break;
101  case 0xF0: if (a < 0x90) return 0; break;
102  case 0xF4: if (a > 0x8F) return 0; break;
103  default: if (a < 0x80) return 0;
104  }
105 
106  case 1: if (*source >= 0x80 && *source < 0xC2) return 0;
107  }
108  if (*source > 0xF4) return 0;
109  return 1;
110 }
111 
112 /* Escapes the UTF16 character and stores the result in the buffer buf. */
113 static void unicode_escape(char *buf, UTF16 character)
114 {
115  const char *digits = "0123456789abcdef";
116 
117  buf[2] = digits[character >> 12];
118  buf[3] = digits[(character >> 8) & 0xf];
119  buf[4] = digits[(character >> 4) & 0xf];
120  buf[5] = digits[character & 0xf];
121 }
122 
123 /* Escapes the UTF16 character and stores the result in the buffer buf, then
124  * the buffer buf іs appended to the FBuffer buffer. */
125 static void unicode_escape_to_buffer(FBuffer *buffer, char buf[6], UTF16
126  character)
127 {
128  unicode_escape(buf, character);
129  fbuffer_append(buffer, buf, 6);
130 }
131 
132 /* Converts string to a JSON string in FBuffer buffer, where all but the ASCII
133  * and control characters are JSON escaped. */
134 static void convert_UTF8_to_JSON_ASCII(FBuffer *buffer, VALUE string)
135 {
136  const UTF8 *source = (UTF8 *) RSTRING_PTR(string);
137  const UTF8 *sourceEnd = source + RSTRING_LEN(string);
138  char buf[6] = { '\\', 'u' };
139 
140  while (source < sourceEnd) {
141  UTF32 ch = 0;
142  unsigned short extraBytesToRead = trailingBytesForUTF8[*source];
143  if (source + extraBytesToRead >= sourceEnd) {
144  rb_raise(rb_path2class("JSON::GeneratorError"),
145  "partial character in source, but hit end");
146  }
147  if (!isLegalUTF8(source, extraBytesToRead+1)) {
148  rb_raise(rb_path2class("JSON::GeneratorError"),
149  "source sequence is illegal/malformed utf-8");
150  }
151  /*
152  * The cases all fall through. See "Note A" below.
153  */
154  switch (extraBytesToRead) {
155  case 5: ch += *source++; ch <<= 6; /* remember, illegal UTF-8 */
156  case 4: ch += *source++; ch <<= 6; /* remember, illegal UTF-8 */
157  case 3: ch += *source++; ch <<= 6;
158  case 2: ch += *source++; ch <<= 6;
159  case 1: ch += *source++; ch <<= 6;
160  case 0: ch += *source++;
161  }
162  ch -= offsetsFromUTF8[extraBytesToRead];
163 
164  if (ch <= UNI_MAX_BMP) { /* Target is a character <= 0xFFFF */
165  /* UTF-16 surrogate values are illegal in UTF-32 */
166  if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) {
167 #if UNI_STRICT_CONVERSION
168  source -= (extraBytesToRead+1); /* return to the illegal value itself */
169  rb_raise(rb_path2class("JSON::GeneratorError"),
170  "source sequence is illegal/malformed utf-8");
171 #else
173 #endif
174  } else {
175  /* normal case */
176  if (ch >= 0x20 && ch <= 0x7f) {
177  switch (ch) {
178  case '\\':
179  fbuffer_append(buffer, "\\\\", 2);
180  break;
181  case '"':
182  fbuffer_append(buffer, "\\\"", 2);
183  break;
184  default:
185  fbuffer_append_char(buffer, (char)ch);
186  break;
187  }
188  } else {
189  switch (ch) {
190  case '\n':
191  fbuffer_append(buffer, "\\n", 2);
192  break;
193  case '\r':
194  fbuffer_append(buffer, "\\r", 2);
195  break;
196  case '\t':
197  fbuffer_append(buffer, "\\t", 2);
198  break;
199  case '\f':
200  fbuffer_append(buffer, "\\f", 2);
201  break;
202  case '\b':
203  fbuffer_append(buffer, "\\b", 2);
204  break;
205  default:
206  unicode_escape_to_buffer(buffer, buf, (UTF16) ch);
207  break;
208  }
209  }
210  }
211  } else if (ch > UNI_MAX_UTF16) {
212 #if UNI_STRICT_CONVERSION
213  source -= (extraBytesToRead+1); /* return to the start */
214  rb_raise(rb_path2class("JSON::GeneratorError"),
215  "source sequence is illegal/malformed utf8");
216 #else
218 #endif
219  } else {
220  /* target is a character in range 0xFFFF - 0x10FFFF. */
221  ch -= halfBase;
222  unicode_escape_to_buffer(buffer, buf, (UTF16)((ch >> halfShift) + UNI_SUR_HIGH_START));
223  unicode_escape_to_buffer(buffer, buf, (UTF16)((ch & halfMask) + UNI_SUR_LOW_START));
224  }
225  }
226 }
227 
228 /* Converts string to a JSON string in FBuffer buffer, where only the
229  * characters required by the JSON standard are JSON escaped. The remaining
230  * characters (should be UTF8) are just passed through and appended to the
231  * result. */
232 static void convert_UTF8_to_JSON(FBuffer *buffer, VALUE string)
233 {
234  const char *ptr = RSTRING_PTR(string), *p;
235  unsigned long len = RSTRING_LEN(string), start = 0, end = 0;
236  const char *escape = NULL;
237  int escape_len;
238  unsigned char c;
239  char buf[6] = { '\\', 'u' };
240 
241  for (start = 0, end = 0; end < len;) {
242  p = ptr + end;
243  c = (unsigned char) *p;
244  if (c < 0x20) {
245  switch (c) {
246  case '\n':
247  escape = "\\n";
248  escape_len = 2;
249  break;
250  case '\r':
251  escape = "\\r";
252  escape_len = 2;
253  break;
254  case '\t':
255  escape = "\\t";
256  escape_len = 2;
257  break;
258  case '\f':
259  escape = "\\f";
260  escape_len = 2;
261  break;
262  case '\b':
263  escape = "\\b";
264  escape_len = 2;
265  break;
266  default:
267  unicode_escape(buf, (UTF16) *p);
268  escape = buf;
269  escape_len = 6;
270  break;
271  }
272  } else {
273  switch (c) {
274  case '\\':
275  escape = "\\\\";
276  escape_len = 2;
277  break;
278  case '"':
279  escape = "\\\"";
280  escape_len = 2;
281  break;
282  default:
283  end++;
284  continue;
285  break;
286  }
287  }
288  fbuffer_append(buffer, ptr + start, end - start);
289  fbuffer_append(buffer, escape, escape_len);
290  start = ++end;
291  escape = NULL;
292  }
293  fbuffer_append(buffer, ptr + start, end - start);
294 }
295 
296 static char *fstrndup(const char *ptr, unsigned long len) {
297  char *result;
298  if (len <= 0) return NULL;
299  result = ALLOC_N(char, len);
300  memccpy(result, ptr, 0, len);
301  return result;
302 }
303 
304 /* fbuffer implementation */
305 
307 {
308  FBuffer *fb = ALLOC(FBuffer);
309  memset((void *) fb, 0, sizeof(FBuffer));
311  return fb;
312 }
313 
314 static FBuffer *fbuffer_alloc_with_length(unsigned long initial_length)
315 {
316  FBuffer *fb;
317  assert(initial_length > 0);
318  fb = ALLOC(FBuffer);
319  memset((void *) fb, 0, sizeof(FBuffer));
320  fb->initial_length = initial_length;
321  return fb;
322 }
323 
324 static void fbuffer_free(FBuffer *fb)
325 {
326  if (fb->ptr) ruby_xfree(fb->ptr);
327  ruby_xfree(fb);
328 }
329 
330 static void fbuffer_clear(FBuffer *fb)
331 {
332  fb->len = 0;
333 }
334 
335 static void fbuffer_inc_capa(FBuffer *fb, unsigned long requested)
336 {
337  unsigned long required;
338 
339  if (!fb->ptr) {
340  fb->ptr = ALLOC_N(char, fb->initial_length);
341  fb->capa = fb->initial_length;
342  }
343 
344  for (required = fb->capa; requested > required - fb->len; required <<= 1);
345 
346  if (required > fb->capa) {
347  REALLOC_N(fb->ptr, char, required);
348  fb->capa = required;
349  }
350 }
351 
352 static void fbuffer_append(FBuffer *fb, const char *newstr, unsigned long len)
353 {
354  if (len > 0) {
355  fbuffer_inc_capa(fb, len);
356  MEMCPY(fb->ptr + fb->len, newstr, char, len);
357  fb->len += len;
358  }
359 }
360 
362 {
363  const char *newstr = StringValuePtr(str);
364  unsigned long len = RSTRING_LEN(str);
365 
366  RB_GC_GUARD(str);
367 
368  fbuffer_append(fb, newstr, len);
369 }
370 
371 static void fbuffer_append_char(FBuffer *fb, char newchr)
372 {
373  fbuffer_inc_capa(fb, 1);
374  *(fb->ptr + fb->len) = newchr;
375  fb->len++;
376 }
377 
378 static void freverse(char *start, char *end)
379 {
380  char c;
381 
382  while (end > start) {
383  c = *end, *end-- = *start, *start++ = c;
384  }
385 }
386 
387 static long fltoa(long number, char *buf)
388 {
389  static char digits[] = "0123456789";
390  long sign = number;
391  char* tmp = buf;
392 
393  if (sign < 0) number = -number;
394  do *tmp++ = digits[number % 10]; while (number /= 10);
395  if (sign < 0) *tmp++ = '-';
396  freverse(buf, tmp - 1);
397  return tmp - buf;
398 }
399 
400 static void fbuffer_append_long(FBuffer *fb, long number)
401 {
402  char buf[20];
403  unsigned long len = fltoa(number, buf);
404  fbuffer_append(fb, buf, len);
405 }
406 
408 {
409  unsigned long len = fb->len;
410  FBuffer *result;
411 
412  if (len > 0) {
413  result = fbuffer_alloc_with_length(len);
414  fbuffer_append(result, FBUFFER_PAIR(fb));
415  } else {
416  result = fbuffer_alloc();
417  }
418  return result;
419 }
420 
421 /*
422  * Document-module: JSON::Ext::Generator
423  *
424  * This is the JSON generator implemented as a C extension. It can be
425  * configured to be used by setting
426  *
427  * JSON.generator = JSON::Ext::Generator
428  *
429  * with the method generator= in JSON.
430  *
431  */
432 
433 /*
434  * call-seq: to_json(state = nil)
435  *
436  * Returns a JSON string containing a JSON object, that is generated from
437  * this Hash instance.
438  * _state_ is a JSON::State object, that can also be used to configure the
439  * produced JSON string output further.
440  */
441 static VALUE mHash_to_json(int argc, VALUE *argv, VALUE self)
442 {
443  GENERATE_JSON(object);
444 }
445 
446 /*
447  * call-seq: to_json(state = nil)
448  *
449  * Returns a JSON string containing a JSON array, that is generated from
450  * this Array instance.
451  * _state_ is a JSON::State object, that can also be used to configure the
452  * produced JSON string output further.
453  */
454 static VALUE mArray_to_json(int argc, VALUE *argv, VALUE self) {
455  GENERATE_JSON(array);
456 }
457 
458 /*
459  * call-seq: to_json(*)
460  *
461  * Returns a JSON string representation for this Integer number.
462  */
464 {
465  GENERATE_JSON(fixnum);
466 }
467 
468 /*
469  * call-seq: to_json(*)
470  *
471  * Returns a JSON string representation for this Integer number.
472  */
474 {
475  GENERATE_JSON(bignum);
476 }
477 
478 /*
479  * call-seq: to_json(*)
480  *
481  * Returns a JSON string representation for this Float number.
482  */
484 {
485  GENERATE_JSON(float);
486 }
487 
488 /*
489  * call-seq: String.included(modul)
490  *
491  * Extends _modul_ with the String::Extend module.
492  */
493 static VALUE mString_included_s(VALUE self, VALUE modul) {
495  return result;
496 }
497 
498 /*
499  * call-seq: to_json(*)
500  *
501  * This string should be encoded with UTF-8 A call to this method
502  * returns a JSON string encoded with UTF16 big endian characters as
503  * \u????.
504  */
506 {
507  GENERATE_JSON(string);
508 }
509 
510 /*
511  * call-seq: to_json_raw_object()
512  *
513  * This method creates a raw object hash, that can be nested into
514  * other data structures and will be generated as a raw string. This
515  * method should be used, if you want to convert raw strings to JSON
516  * instead of UTF-8 strings, e. g. binary data.
517  */
519 {
520  VALUE ary;
523  ary = rb_funcall(self, i_unpack, 1, rb_str_new2("C*"));
524  rb_hash_aset(result, rb_str_new2("raw"), ary);
525  return result;
526 }
527 
528 /*
529  * call-seq: to_json_raw(*args)
530  *
531  * This method creates a JSON text from the result of a call to
532  * to_json_raw_object of this String.
533  */
535 {
537  Check_Type(obj, T_HASH);
538  return mHash_to_json(argc, argv, obj);
539 }
540 
541 /*
542  * call-seq: json_create(o)
543  *
544  * Raw Strings are JSON Objects (the raw bytes are stored in an array for the
545  * key "raw"). The Ruby String can be created by this module method.
546  */
548 {
549  VALUE ary;
550  Check_Type(o, T_HASH);
551  ary = rb_hash_aref(o, rb_str_new2("raw"));
552  return rb_funcall(ary, i_pack, 1, rb_str_new2("C*"));
553 }
554 
555 /*
556  * call-seq: to_json(*)
557  *
558  * Returns a JSON string for true: 'true'.
559  */
561 {
562  GENERATE_JSON(true);
563 }
564 
565 /*
566  * call-seq: to_json(*)
567  *
568  * Returns a JSON string for false: 'false'.
569  */
571 {
572  GENERATE_JSON(false);
573 }
574 
575 /*
576  * call-seq: to_json(*)
577  *
578  * Returns a JSON string for nil: 'null'.
579  */
581 {
582  GENERATE_JSON(null);
583 }
584 
585 /*
586  * call-seq: to_json(*)
587  *
588  * Converts this object to a string (calling #to_s), converts
589  * it to a JSON string, and returns the result. This is a fallback, if no
590  * special method #to_json was defined for some object.
591  */
593 {
594  VALUE state;
595  VALUE string = rb_funcall(self, i_to_s, 0);
596  rb_scan_args(argc, argv, "01", &state);
597  Check_Type(string, T_STRING);
598  state = cState_from_state_s(cState, state);
599  return cState_partial_generate(state, string);
600 }
601 
603 {
604  if (state->indent) ruby_xfree(state->indent);
605  if (state->space) ruby_xfree(state->space);
606  if (state->space_before) ruby_xfree(state->space_before);
607  if (state->object_nl) ruby_xfree(state->object_nl);
608  if (state->array_nl) ruby_xfree(state->array_nl);
609  if (state->array_delim) fbuffer_free(state->array_delim);
610  if (state->object_delim) fbuffer_free(state->object_delim);
611  if (state->object_delim2) fbuffer_free(state->object_delim2);
612  ruby_xfree(state);
613 }
614 
616 {
618  MEMZERO(state, JSON_Generator_State, 1);
619  return state;
620 }
621 
623 {
625  return Data_Wrap_Struct(klass, NULL, State_free, state);
626 }
627 
628 /*
629  * call-seq: configure(opts)
630  *
631  * Configure this State instance with the Hash _opts_, and return
632  * itself.
633  */
635 {
636  VALUE tmp;
637  GET_STATE(self);
638  tmp = rb_convert_type(opts, T_HASH, "Hash", "to_hash");
639  if (NIL_P(tmp)) tmp = rb_convert_type(opts, T_HASH, "Hash", "to_h");
640  if (NIL_P(tmp)) {
641  rb_raise(rb_eArgError, "opts has to be hash like or convertable into a hash");
642  }
643  opts = tmp;
644  tmp = rb_hash_aref(opts, ID2SYM(i_indent));
645  if (RTEST(tmp)) {
646  unsigned long len;
647  Check_Type(tmp, T_STRING);
648  len = RSTRING_LEN(tmp);
649  state->indent = fstrndup(RSTRING_PTR(tmp), len);
650  state->indent_len = len;
651  }
652  tmp = rb_hash_aref(opts, ID2SYM(i_space));
653  if (RTEST(tmp)) {
654  unsigned long len;
655  Check_Type(tmp, T_STRING);
656  len = RSTRING_LEN(tmp);
657  state->space = fstrndup(RSTRING_PTR(tmp), len);
658  state->space_len = len;
659  }
660  tmp = rb_hash_aref(opts, ID2SYM(i_space_before));
661  if (RTEST(tmp)) {
662  unsigned long len;
663  Check_Type(tmp, T_STRING);
664  len = RSTRING_LEN(tmp);
665  state->space_before = fstrndup(RSTRING_PTR(tmp), len);
666  state->space_before_len = len;
667  }
668  tmp = rb_hash_aref(opts, ID2SYM(i_array_nl));
669  if (RTEST(tmp)) {
670  unsigned long len;
671  Check_Type(tmp, T_STRING);
672  len = RSTRING_LEN(tmp);
673  state->array_nl = fstrndup(RSTRING_PTR(tmp), len);
674  state->array_nl_len = len;
675  }
676  tmp = rb_hash_aref(opts, ID2SYM(i_object_nl));
677  if (RTEST(tmp)) {
678  unsigned long len;
679  Check_Type(tmp, T_STRING);
680  len = RSTRING_LEN(tmp);
681  state->object_nl = fstrndup(RSTRING_PTR(tmp), len);
682  state->object_nl_len = len;
683  }
684  tmp = ID2SYM(i_max_nesting);
685  state->max_nesting = 19;
686  if (option_given_p(opts, tmp)) {
687  VALUE max_nesting = rb_hash_aref(opts, tmp);
688  if (RTEST(max_nesting)) {
689  Check_Type(max_nesting, T_FIXNUM);
690  state->max_nesting = FIX2LONG(max_nesting);
691  } else {
692  state->max_nesting = 0;
693  }
694  }
695  tmp = ID2SYM(i_depth);
696  state->depth = 0;
697  if (option_given_p(opts, tmp)) {
698  VALUE depth = rb_hash_aref(opts, tmp);
699  if (RTEST(depth)) {
700  Check_Type(depth, T_FIXNUM);
701  state->depth = FIX2LONG(depth);
702  } else {
703  state->depth = 0;
704  }
705  }
706  tmp = rb_hash_aref(opts, ID2SYM(i_allow_nan));
707  state->allow_nan = RTEST(tmp);
708  tmp = rb_hash_aref(opts, ID2SYM(i_ascii_only));
709  state->ascii_only = RTEST(tmp);
710  tmp = rb_hash_aref(opts, ID2SYM(i_quirks_mode));
711  state->quirks_mode = RTEST(tmp);
712  return self;
713 }
714 
715 /*
716  * call-seq: to_h
717  *
718  * Returns the configuration instance variables as a hash, that can be
719  * passed to the configure method.
720  */
721 static VALUE cState_to_h(VALUE self)
722 {
724  GET_STATE(self);
725  rb_hash_aset(result, ID2SYM(i_indent), rb_str_new(state->indent, state->indent_len));
726  rb_hash_aset(result, ID2SYM(i_space), rb_str_new(state->space, state->space_len));
727  rb_hash_aset(result, ID2SYM(i_space_before), rb_str_new(state->space_before, state->space_before_len));
728  rb_hash_aset(result, ID2SYM(i_object_nl), rb_str_new(state->object_nl, state->object_nl_len));
729  rb_hash_aset(result, ID2SYM(i_array_nl), rb_str_new(state->array_nl, state->array_nl_len));
730  rb_hash_aset(result, ID2SYM(i_allow_nan), state->allow_nan ? Qtrue : Qfalse);
731  rb_hash_aset(result, ID2SYM(i_ascii_only), state->ascii_only ? Qtrue : Qfalse);
732  rb_hash_aset(result, ID2SYM(i_quirks_mode), state->quirks_mode ? Qtrue : Qfalse);
733  rb_hash_aset(result, ID2SYM(i_max_nesting), LONG2FIX(state->max_nesting));
734  rb_hash_aset(result, ID2SYM(i_depth), LONG2FIX(state->depth));
735  return result;
736 }
737 
738 /*
739 * call-seq: [](name)
740 *
741 * Return the value returned by method +name+.
742 */
744 {
745  GET_STATE(self);
746  if (RTEST(rb_funcall(self, i_respond_to_p, 1, name))) {
747  return rb_funcall(self, i_send, 1, name);
748  } else {
749  return Qnil;
750  }
751 }
752 
754 {
755  char *object_nl = state->object_nl;
756  long object_nl_len = state->object_nl_len;
757  char *indent = state->indent;
758  long indent_len = state->indent_len;
759  long max_nesting = state->max_nesting;
760  char *delim = FBUFFER_PTR(state->object_delim);
761  long delim_len = FBUFFER_LEN(state->object_delim);
762  char *delim2 = FBUFFER_PTR(state->object_delim2);
763  long delim2_len = FBUFFER_LEN(state->object_delim2);
764  long depth = ++state->depth;
765  int i, j;
766  VALUE key, key_to_s, keys;
767  if (max_nesting != 0 && depth > max_nesting) {
768  fbuffer_free(buffer);
769  rb_raise(eNestingError, "nesting of %ld is too deep", --state->depth);
770  }
771  fbuffer_append_char(buffer, '{');
772  keys = rb_funcall(obj, i_keys, 0);
773  for(i = 0; i < RARRAY_LEN(keys); i++) {
774  if (i > 0) fbuffer_append(buffer, delim, delim_len);
775  if (object_nl) {
776  fbuffer_append(buffer, object_nl, object_nl_len);
777  }
778  if (indent) {
779  for (j = 0; j < depth; j++) {
780  fbuffer_append(buffer, indent, indent_len);
781  }
782  }
783  key = rb_ary_entry(keys, i);
784  key_to_s = rb_funcall(key, i_to_s, 0);
785  Check_Type(key_to_s, T_STRING);
786  generate_json(buffer, Vstate, state, key_to_s);
787  fbuffer_append(buffer, delim2, delim2_len);
788  generate_json(buffer, Vstate, state, rb_hash_aref(obj, key));
789  }
790  depth = --state->depth;
791  if (object_nl) {
792  fbuffer_append(buffer, object_nl, object_nl_len);
793  if (indent) {
794  for (j = 0; j < depth; j++) {
795  fbuffer_append(buffer, indent, indent_len);
796  }
797  }
798  }
799  fbuffer_append_char(buffer, '}');
800 }
801 
803 {
804  char *array_nl = state->array_nl;
805  long array_nl_len = state->array_nl_len;
806  char *indent = state->indent;
807  long indent_len = state->indent_len;
808  long max_nesting = state->max_nesting;
809  char *delim = FBUFFER_PTR(state->array_delim);
810  long delim_len = FBUFFER_LEN(state->array_delim);
811  long depth = ++state->depth;
812  int i, j;
813  if (max_nesting != 0 && depth > max_nesting) {
814  fbuffer_free(buffer);
815  rb_raise(eNestingError, "nesting of %ld is too deep", --state->depth);
816  }
817  fbuffer_append_char(buffer, '[');
818  if (array_nl) fbuffer_append(buffer, array_nl, array_nl_len);
819  for(i = 0; i < RARRAY_LEN(obj); i++) {
820  if (i > 0) fbuffer_append(buffer, delim, delim_len);
821  if (indent) {
822  for (j = 0; j < depth; j++) {
823  fbuffer_append(buffer, indent, indent_len);
824  }
825  }
826  generate_json(buffer, Vstate, state, rb_ary_entry(obj, i));
827  }
828  state->depth = --depth;
829  if (array_nl) {
830  fbuffer_append(buffer, array_nl, array_nl_len);
831  if (indent) {
832  for (j = 0; j < depth; j++) {
833  fbuffer_append(buffer, indent, indent_len);
834  }
835  }
836  }
837  fbuffer_append_char(buffer, ']');
838 }
839 
841 {
842  fbuffer_append_char(buffer, '"');
843 #ifdef HAVE_RUBY_ENCODING_H
844  obj = rb_funcall(obj, i_encode, 1, CEncoding_UTF_8);
845 #endif
846  if (state->ascii_only) {
847  convert_UTF8_to_JSON_ASCII(buffer, obj);
848  } else {
849  convert_UTF8_to_JSON(buffer, obj);
850  }
851  fbuffer_append_char(buffer, '"');
852 }
853 
855 {
856  fbuffer_append(buffer, "null", 4);
857 }
858 
860 {
861  fbuffer_append(buffer, "false", 5);
862 }
863 
865 {
866  fbuffer_append(buffer, "true", 4);
867 }
868 
870 {
871  fbuffer_append_long(buffer, FIX2LONG(obj));
872 }
873 
875 {
876  VALUE tmp = rb_funcall(obj, i_to_s, 0);
877  fbuffer_append_str(buffer, tmp);
878 }
879 
881 {
882  double value = RFLOAT_VALUE(obj);
883  char allow_nan = state->allow_nan;
884  VALUE tmp = rb_funcall(obj, i_to_s, 0);
885  if (!allow_nan) {
886  if (isinf(value)) {
887  fbuffer_free(buffer);
888  rb_raise(eGeneratorError, "%u: %"PRIsVALUE" not allowed in JSON", __LINE__, RB_OBJ_STRING(tmp));
889  } else if (isnan(value)) {
890  fbuffer_free(buffer);
891  rb_raise(eGeneratorError, "%u: %"PRIsVALUE" not allowed in JSON", __LINE__, RB_OBJ_STRING(tmp));
892  }
893  }
894  fbuffer_append_str(buffer, tmp);
895 }
896 
898 {
899  VALUE tmp;
900  VALUE klass = CLASS_OF(obj);
901  if (klass == rb_cHash) {
902  generate_json_object(buffer, Vstate, state, obj);
903  } else if (klass == rb_cArray) {
904  generate_json_array(buffer, Vstate, state, obj);
905  } else if (klass == rb_cString) {
906  generate_json_string(buffer, Vstate, state, obj);
907  } else if (obj == Qnil) {
908  generate_json_null(buffer, Vstate, state, obj);
909  } else if (obj == Qfalse) {
910  generate_json_false(buffer, Vstate, state, obj);
911  } else if (obj == Qtrue) {
912  generate_json_true(buffer, Vstate, state, obj);
913  } else if (klass == rb_cFixnum) {
914  generate_json_fixnum(buffer, Vstate, state, obj);
915  } else if (klass == rb_cBignum) {
916  generate_json_bignum(buffer, Vstate, state, obj);
917  } else if (klass == rb_cFloat) {
918  generate_json_float(buffer, Vstate, state, obj);
919  } else if (rb_respond_to(obj, i_to_json)) {
920  tmp = rb_funcall(obj, i_to_json, 1, Vstate);
921  Check_Type(tmp, T_STRING);
922  fbuffer_append_str(buffer, tmp);
923  } else {
924  tmp = rb_funcall(obj, i_to_s, 0);
925  Check_Type(tmp, T_STRING);
926  generate_json(buffer, Vstate, state, tmp);
927  }
928 }
929 
931 {
932  FBuffer *buffer = fbuffer_alloc();
933  GET_STATE(self);
934 
935  if (state->object_delim) {
936  fbuffer_clear(state->object_delim);
937  } else {
938  state->object_delim = fbuffer_alloc_with_length(16);
939  }
940  fbuffer_append_char(state->object_delim, ',');
941  if (state->object_delim2) {
942  fbuffer_clear(state->object_delim2);
943  } else {
944  state->object_delim2 = fbuffer_alloc_with_length(16);
945  }
946  fbuffer_append_char(state->object_delim2, ':');
947  if (state->space) fbuffer_append(state->object_delim2, state->space, state->space_len);
948 
949  if (state->array_delim) {
950  fbuffer_clear(state->array_delim);
951  } else {
952  state->array_delim = fbuffer_alloc_with_length(16);
953  }
954  fbuffer_append_char(state->array_delim, ',');
955  if (state->array_nl) fbuffer_append(state->array_delim, state->array_nl, state->array_nl_len);
956  return buffer;
957 }
958 
960 {
962  fbuffer_free(fb);
963  FORCE_UTF8(result);
964  return result;
965 }
966 
968 {
969  FBuffer *buffer = cState_prepare_buffer(self);
970  GET_STATE(self);
971  generate_json(buffer, self, state, obj);
972  return fbuffer_to_s(buffer);
973 }
974 
975 /*
976  * call-seq: generate(obj)
977  *
978  * Generates a valid JSON document from object +obj+ and returns the
979  * result. If no valid JSON document can be created this method raises a
980  * GeneratorError exception.
981  */
983 {
984  VALUE result = cState_partial_generate(self, obj);
985  VALUE re, args[2];
986  GET_STATE(self);
987  if (!state->quirks_mode) {
988  args[0] = rb_str_new2("\\A\\s*(?:\\[.*\\]|\\{.*\\})\\s*\\Z");
989  args[1] = CRegexp_MULTILINE;
990  re = rb_class_new_instance(2, args, rb_cRegexp);
991  if (NIL_P(rb_funcall(re, i_match, 1, result))) {
992  rb_raise(eGeneratorError, "only generation of JSON objects or arrays allowed");
993  }
994  }
995  return result;
996 }
997 
998 /*
999  * call-seq: new(opts = {})
1000  *
1001  * Instantiates a new State object, configured by _opts_.
1002  *
1003  * _opts_ can have the following keys:
1004  *
1005  * * *indent*: a string used to indent levels (default: ''),
1006  * * *space*: a string that is put after, a : or , delimiter (default: ''),
1007  * * *space_before*: a string that is put before a : pair delimiter (default: ''),
1008  * * *object_nl*: a string that is put at the end of a JSON object (default: ''),
1009  * * *array_nl*: a string that is put at the end of a JSON array (default: ''),
1010  * * *allow_nan*: true if NaN, Infinity, and -Infinity should be
1011  * generated, otherwise an exception is thrown, if these values are
1012  * encountered. This options defaults to false.
1013  * * *quirks_mode*: Enables quirks_mode for parser, that is for example
1014  * generating single JSON values instead of documents is possible.
1015  */
1017 {
1018  VALUE opts;
1019  GET_STATE(self);
1020  state->max_nesting = 19;
1021  rb_scan_args(argc, argv, "01", &opts);
1022  if (!NIL_P(opts)) cState_configure(self, opts);
1023  return self;
1024 }
1025 
1026 /*
1027  * call-seq: initialize_copy(orig)
1028  *
1029  * Initializes this object from orig if it to be duplicated/cloned and returns
1030  * it.
1031 */
1033 {
1034  JSON_Generator_State *objState, *origState;
1035 
1036  if (obj == orig) return obj;
1037  Data_Get_Struct(obj, JSON_Generator_State, objState);
1038  Data_Get_Struct(orig, JSON_Generator_State, origState);
1039  if (!objState) rb_raise(rb_eArgError, "unallocated JSON::State");
1040 
1041  MEMCPY(objState, origState, JSON_Generator_State, 1);
1042  objState->indent = fstrndup(origState->indent, origState->indent_len);
1043  objState->space = fstrndup(origState->space, origState->space_len);
1044  objState->space_before = fstrndup(origState->space_before, origState->space_before_len);
1045  objState->object_nl = fstrndup(origState->object_nl, origState->object_nl_len);
1046  objState->array_nl = fstrndup(origState->array_nl, origState->array_nl_len);
1047  if (origState->array_delim) objState->array_delim = fbuffer_dup(origState->array_delim);
1048  if (origState->object_delim) objState->object_delim = fbuffer_dup(origState->object_delim);
1049  if (origState->object_delim2) objState->object_delim2 = fbuffer_dup(origState->object_delim2);
1050  return obj;
1051 }
1052 
1053 /*
1054  * call-seq: from_state(opts)
1055  *
1056  * Creates a State object from _opts_, which ought to be Hash to create a
1057  * new State instance configured by _opts_, something else to create an
1058  * unconfigured instance. If _opts_ is a State object, it is just returned.
1059  */
1061 {
1062  if (rb_obj_is_kind_of(opts, self)) {
1063  return opts;
1064  } else if (rb_obj_is_kind_of(opts, rb_cHash)) {
1065  return rb_funcall(self, i_new, 1, opts);
1066  } else {
1069  }
1071  }
1072 }
1073 
1074 /*
1075  * call-seq: indent()
1076  *
1077  * This string is used to indent levels in the JSON text.
1078  */
1080 {
1081  GET_STATE(self);
1082  return state->indent ? rb_str_new2(state->indent) : rb_str_new2("");
1083 }
1084 
1085 /*
1086  * call-seq: indent=(indent)
1087  *
1088  * This string is used to indent levels in the JSON text.
1089  */
1090 static VALUE cState_indent_set(VALUE self, VALUE indent)
1091 {
1092  unsigned long len;
1093  GET_STATE(self);
1094  Check_Type(indent, T_STRING);
1095  len = RSTRING_LEN(indent);
1096  if (len == 0) {
1097  if (state->indent) {
1098  ruby_xfree(state->indent);
1099  state->indent = NULL;
1100  state->indent_len = 0;
1101  }
1102  } else {
1103  if (state->indent) ruby_xfree(state->indent);
1104  state->indent = strdup(RSTRING_PTR(indent));
1105  state->indent_len = len;
1106  }
1107  return Qnil;
1108 }
1109 
1110 /*
1111  * call-seq: space()
1112  *
1113  * This string is used to insert a space between the tokens in a JSON
1114  * string.
1115  */
1117 {
1118  GET_STATE(self);
1119  return state->space ? rb_str_new2(state->space) : rb_str_new2("");
1120 }
1121 
1122 /*
1123  * call-seq: space=(space)
1124  *
1125  * This string is used to insert a space between the tokens in a JSON
1126  * string.
1127  */
1128 static VALUE cState_space_set(VALUE self, VALUE space)
1129 {
1130  unsigned long len;
1131  GET_STATE(self);
1132  Check_Type(space, T_STRING);
1133  len = RSTRING_LEN(space);
1134  if (len == 0) {
1135  if (state->space) {
1136  ruby_xfree(state->space);
1137  state->space = NULL;
1138  state->space_len = 0;
1139  }
1140  } else {
1141  if (state->space) ruby_xfree(state->space);
1142  state->space = strdup(RSTRING_PTR(space));
1143  state->space_len = len;
1144  }
1145  return Qnil;
1146 }
1147 
1148 /*
1149  * call-seq: space_before()
1150  *
1151  * This string is used to insert a space before the ':' in JSON objects.
1152  */
1154 {
1155  GET_STATE(self);
1156  return state->space_before ? rb_str_new2(state->space_before) : rb_str_new2("");
1157 }
1158 
1159 /*
1160  * call-seq: space_before=(space_before)
1161  *
1162  * This string is used to insert a space before the ':' in JSON objects.
1163  */
1164 static VALUE cState_space_before_set(VALUE self, VALUE space_before)
1165 {
1166  unsigned long len;
1167  GET_STATE(self);
1168  Check_Type(space_before, T_STRING);
1169  len = RSTRING_LEN(space_before);
1170  if (len == 0) {
1171  if (state->space_before) {
1172  ruby_xfree(state->space_before);
1173  state->space_before = NULL;
1174  state->space_before_len = 0;
1175  }
1176  } else {
1177  if (state->space_before) ruby_xfree(state->space_before);
1178  state->space_before = strdup(RSTRING_PTR(space_before));
1179  state->space_before_len = len;
1180  }
1181  return Qnil;
1182 }
1183 
1184 /*
1185  * call-seq: object_nl()
1186  *
1187  * This string is put at the end of a line that holds a JSON object (or
1188  * Hash).
1189  */
1191 {
1192  GET_STATE(self);
1193  return state->object_nl ? rb_str_new2(state->object_nl) : rb_str_new2("");
1194 }
1195 
1196 /*
1197  * call-seq: object_nl=(object_nl)
1198  *
1199  * This string is put at the end of a line that holds a JSON object (or
1200  * Hash).
1201  */
1202 static VALUE cState_object_nl_set(VALUE self, VALUE object_nl)
1203 {
1204  unsigned long len;
1205  GET_STATE(self);
1206  Check_Type(object_nl, T_STRING);
1207  len = RSTRING_LEN(object_nl);
1208  if (len == 0) {
1209  if (state->object_nl) {
1210  ruby_xfree(state->object_nl);
1211  state->object_nl = NULL;
1212  }
1213  } else {
1214  if (state->object_nl) ruby_xfree(state->object_nl);
1215  state->object_nl = strdup(RSTRING_PTR(object_nl));
1216  state->object_nl_len = len;
1217  }
1218  return Qnil;
1219 }
1220 
1221 /*
1222  * call-seq: array_nl()
1223  *
1224  * This string is put at the end of a line that holds a JSON array.
1225  */
1227 {
1228  GET_STATE(self);
1229  return state->array_nl ? rb_str_new2(state->array_nl) : rb_str_new2("");
1230 }
1231 
1232 /*
1233  * call-seq: array_nl=(array_nl)
1234  *
1235  * This string is put at the end of a line that holds a JSON array.
1236  */
1237 static VALUE cState_array_nl_set(VALUE self, VALUE array_nl)
1238 {
1239  unsigned long len;
1240  GET_STATE(self);
1241  Check_Type(array_nl, T_STRING);
1242  len = RSTRING_LEN(array_nl);
1243  if (len == 0) {
1244  if (state->array_nl) {
1245  ruby_xfree(state->array_nl);
1246  state->array_nl = NULL;
1247  }
1248  } else {
1249  if (state->array_nl) ruby_xfree(state->array_nl);
1250  state->array_nl = strdup(RSTRING_PTR(array_nl));
1251  state->array_nl_len = len;
1252  }
1253  return Qnil;
1254 }
1255 
1256 
1257 /*
1258 * call-seq: check_circular?
1259 *
1260 * Returns true, if circular data structures should be checked,
1261 * otherwise returns false.
1262 */
1264 {
1265  GET_STATE(self);
1266  return state->max_nesting ? Qtrue : Qfalse;
1267 }
1268 
1269 /*
1270  * call-seq: max_nesting
1271  *
1272  * This integer returns the maximum level of data structure nesting in
1273  * the generated JSON, max_nesting = 0 if no maximum is checked.
1274  */
1276 {
1277  GET_STATE(self);
1278  return LONG2FIX(state->max_nesting);
1279 }
1280 
1281 /*
1282  * call-seq: max_nesting=(depth)
1283  *
1284  * This sets the maximum level of data structure nesting in the generated JSON
1285  * to the integer depth, max_nesting = 0 if no maximum should be checked.
1286  */
1288 {
1289  GET_STATE(self);
1290  Check_Type(depth, T_FIXNUM);
1291  return state->max_nesting = FIX2LONG(depth);
1292 }
1293 
1294 /*
1295  * call-seq: allow_nan?
1296  *
1297  * Returns true, if NaN, Infinity, and -Infinity should be generated, otherwise
1298  * returns false.
1299  */
1301 {
1302  GET_STATE(self);
1303  return state->allow_nan ? Qtrue : Qfalse;
1304 }
1305 
1306 /*
1307  * call-seq: ascii_only?
1308  *
1309  * Returns true, if NaN, Infinity, and -Infinity should be generated, otherwise
1310  * returns false.
1311  */
1313 {
1314  GET_STATE(self);
1315  return state->ascii_only ? Qtrue : Qfalse;
1316 }
1317 
1318 /*
1319  * call-seq: quirks_mode?
1320  *
1321  * Returns true, if quirks mode is enabled. Otherwise returns false.
1322  */
1324 {
1325  GET_STATE(self);
1326  return state->quirks_mode ? Qtrue : Qfalse;
1327 }
1328 
1329 /*
1330  * call-seq: quirks_mode=(enable)
1331  *
1332  * If set to true, enables the quirks_mode mode.
1333  */
1335 {
1336  GET_STATE(self);
1337  state->quirks_mode = RTEST(enable);
1338  return Qnil;
1339 }
1340 
1341 /*
1342  * call-seq: depth
1343  *
1344  * This integer returns the current depth of data structure nesting.
1345  */
1347 {
1348  GET_STATE(self);
1349  return LONG2FIX(state->depth);
1350 }
1351 
1352 /*
1353  * call-seq: depth=(depth)
1354  *
1355  * This sets the maximum level of data structure nesting in the generated JSON
1356  * to the integer depth, max_nesting = 0 if no maximum should be checked.
1357  */
1359 {
1360  GET_STATE(self);
1361  Check_Type(depth, T_FIXNUM);
1362  return state->depth = FIX2LONG(depth);
1363 }
1364 
1365 /*
1366  *
1367  */
1369 {
1370  rb_require("json/common");
1371 
1372  mJSON = rb_define_module("JSON");
1373  mExt = rb_define_module_under(mJSON, "Ext");
1374  mGenerator = rb_define_module_under(mExt, "Generator");
1375 
1376  eGeneratorError = rb_path2class("JSON::GeneratorError");
1377  eNestingError = rb_path2class("JSON::NestingError");
1378 
1382  rb_define_method(cState, "initialize", cState_initialize, -1);
1383  rb_define_method(cState, "initialize_copy", cState_init_copy, 1);
1384  rb_define_method(cState, "indent", cState_indent, 0);
1385  rb_define_method(cState, "indent=", cState_indent_set, 1);
1386  rb_define_method(cState, "space", cState_space, 0);
1387  rb_define_method(cState, "space=", cState_space_set, 1);
1388  rb_define_method(cState, "space_before", cState_space_before, 0);
1389  rb_define_method(cState, "space_before=", cState_space_before_set, 1);
1390  rb_define_method(cState, "object_nl", cState_object_nl, 0);
1391  rb_define_method(cState, "object_nl=", cState_object_nl_set, 1);
1392  rb_define_method(cState, "array_nl", cState_array_nl, 0);
1393  rb_define_method(cState, "array_nl=", cState_array_nl_set, 1);
1394  rb_define_method(cState, "max_nesting", cState_max_nesting, 0);
1395  rb_define_method(cState, "max_nesting=", cState_max_nesting_set, 1);
1396  rb_define_method(cState, "check_circular?", cState_check_circular_p, 0);
1397  rb_define_method(cState, "allow_nan?", cState_allow_nan_p, 0);
1398  rb_define_method(cState, "ascii_only?", cState_ascii_only_p, 0);
1399  rb_define_method(cState, "quirks_mode?", cState_quirks_mode_p, 0);
1400  rb_define_method(cState, "quirks_mode", cState_quirks_mode_p, 0);
1401  rb_define_method(cState, "quirks_mode=", cState_quirks_mode_set, 1);
1402  rb_define_method(cState, "depth", cState_depth, 0);
1403  rb_define_method(cState, "depth=", cState_depth_set, 1);
1404  rb_define_method(cState, "configure", cState_configure, 1);
1405  rb_define_alias(cState, "merge", "configure");
1406  rb_define_method(cState, "to_h", cState_to_h, 0);
1407  rb_define_method(cState, "[]", cState_aref, 1);
1408  rb_define_method(cState, "generate", cState_generate, 1);
1409 
1410  mGeneratorMethods = rb_define_module_under(mGenerator, "GeneratorMethods");
1412  rb_define_method(mObject, "to_json", mObject_to_json, -1);
1414  rb_define_method(mHash, "to_json", mHash_to_json, -1);
1416  rb_define_method(mArray, "to_json", mArray_to_json, -1);
1418  rb_define_method(mFixnum, "to_json", mFixnum_to_json, -1);
1420  rb_define_method(mBignum, "to_json", mBignum_to_json, -1);
1422  rb_define_method(mFloat, "to_json", mFloat_to_json, -1);
1425  rb_define_method(mString, "to_json", mString_to_json, -1);
1426  rb_define_method(mString, "to_json_raw", mString_to_json_raw, -1);
1427  rb_define_method(mString, "to_json_raw_object", mString_to_json_raw_object, 0);
1435  rb_define_method(mNilClass, "to_json", mNilClass_to_json, -1);
1436 
1438  i_to_s = rb_intern("to_s");
1439  i_to_json = rb_intern("to_json");
1440  i_new = rb_intern("new");
1441  i_indent = rb_intern("indent");
1442  i_space = rb_intern("space");
1443  i_space_before = rb_intern("space_before");
1444  i_object_nl = rb_intern("object_nl");
1445  i_array_nl = rb_intern("array_nl");
1446  i_max_nesting = rb_intern("max_nesting");
1447  i_allow_nan = rb_intern("allow_nan");
1448  i_ascii_only = rb_intern("ascii_only");
1449  i_quirks_mode = rb_intern("quirks_mode");
1450  i_depth = rb_intern("depth");
1451  i_pack = rb_intern("pack");
1452  i_unpack = rb_intern("unpack");
1453  i_create_id = rb_intern("create_id");
1454  i_extend = rb_intern("extend");
1455  i_key_p = rb_intern("key?");
1456  i_aref = rb_intern("[]");
1457  i_send = rb_intern("__send__");
1458  i_respond_to_p = rb_intern("respond_to?");
1459  i_match = rb_intern("match");
1460  i_keys = rb_intern("keys");
1461  i_dup = rb_intern("dup");
1462 #ifdef HAVE_RUBY_ENCODING_H
1463  CEncoding_UTF_8 = rb_funcall(rb_path2class("Encoding"), rb_intern("find"), 1, rb_str_new2("utf-8"));
1464  i_encoding = rb_intern("encoding");
1465  i_encode = rb_intern("encode");
1466 #endif
1467  i_SAFE_STATE_PROTOTYPE = rb_intern("SAFE_STATE_PROTOTYPE");
1469 }
RUBY_EXTERN VALUE rb_cString
Definition: ruby.h:1276
#define RSTRING_LEN(string)
Definition: generator.h:45
static ID i_max_nesting
Definition: generator.c:23
static void fbuffer_free(FBuffer *fb)
Definition: generator.c:324
static VALUE fbuffer_to_s(FBuffer *fb)
Definition: generator.c:959
#define FBUFFER_LEN(fb)
Definition: generator.h:65
static VALUE eGeneratorError
Definition: generator.c:17
volatile VALUE ary
Definition: tcltklib.c:9700
static JSON_Generator_State * State_allocate()
Definition: generator.c:615
VALUE rb_ary_entry(VALUE ary, long offset)
Definition: array.c:956
RUBY_EXTERN VALUE rb_cFloat
Definition: ruby.h:1259
static VALUE i_SAFE_STATE_PROTOTYPE
Definition: generator.c:17
static VALUE cState_array_nl(VALUE self)
Definition: generator.c:1226
static void generate_json_false(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj)
Definition: generator.c:859
static VALUE mGenerator
Definition: generator.c:17
static VALUE CRegexp_MULTILINE
Definition: generator.c:17
static VALUE mArray_to_json(int argc, VALUE *argv, VALUE self)
Definition: generator.c:454
#define T_FIXNUM
Definition: ruby.h:425
static void unicode_escape_to_buffer(FBuffer *buffer, char buf[6], UTF16 character)
Definition: generator.c:125
static FBuffer * fbuffer_alloc()
Definition: generator.c:306
static const char trailingBytesForUTF8[256]
Definition: generator.c:57
#define Data_Get_Struct(obj, type, sval)
Definition: ruby.h:835
void rb_define_singleton_method(VALUE obj, const char *name, VALUE(*func)(ANYARGS), int argc)
Defines a singleton method for obj.
Definition: class.c:1343
static VALUE mFixnum_to_json(int argc, VALUE *argv, VALUE self)
Definition: generator.c:463
static VALUE cState_from_state_s(VALUE self, VALUE opts)
Definition: generator.c:1060
#define CLASS_OF(v)
Definition: ruby.h:376
static VALUE mTrueClass
Definition: generator.c:17
static void fbuffer_append_long(FBuffer *fb, long number)
Definition: generator.c:400
static ID i_extend
Definition: generator.c:23
static VALUE cState_array_nl_set(VALUE self, VALUE array_nl)
Definition: generator.c:1237
rb_hash_aset(CALLBACK_TABLE, id_num, cmd)
VALUE rb_cHash
Definition: hash.c:35
#define RFLOAT_VALUE(val)
Definition: generator.h:32
static unsigned char isLegalUTF8(const UTF8 *source, unsigned long length)
Definition: generator.c:86
unsigned long capa
Definition: generator.h:59
#define option_given_p(opts, key)
Definition: generator.h:25
static ID i_keys
Definition: generator.c:23
static ID i_space
Definition: generator.c:23
static void generate_json_array(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj)
Definition: generator.c:802
static VALUE mString_Extend_json_create(VALUE self, VALUE o)
Definition: generator.c:547
static ID i_space_before
Definition: generator.c:23
static const UTF32 offsetsFromUTF8[6]
Definition: generator.c:73
static VALUE mFixnum
Definition: generator.c:17
SYMID SyckParser * p
Definition: yaml2byte.c:119
#define FBUFFER_PTR(fb)
Definition: generator.h:64
unsigned char UTF8
Definition: generator.h:86
static VALUE cState_object_nl(VALUE self)
Definition: generator.c:1190
static ID i_object_nl
Definition: generator.c:23
static VALUE cState_check_circular_p(VALUE self)
Definition: generator.c:1263
static VALUE cState_max_nesting(VALUE self)
Definition: generator.c:1275
unsigned long VALUE
Definition: ruby.h:88
static ID i_respond_to_p
Definition: generator.c:23
static void fbuffer_clear(FBuffer *fb)
Definition: generator.c:330
static VALUE cState_initialize(int argc, VALUE *argv, VALUE self)
Definition: generator.c:1016
static VALUE cState_space_before_set(VALUE self, VALUE space_before)
Definition: generator.c:1164
static const UTF32 halfBase
Definition: generator.h:101
static VALUE mGeneratorMethods
Definition: generator.c:17
static VALUE cState_configure(VALUE self, VALUE opts)
Definition: generator.c:634
#define RSTRING_PTR(string)
Definition: generator.h:42
VALUE rb_define_class_under(VALUE outer, const char *name, VALUE super)
Defines a class under the namespace of outer.
Definition: class.c:515
#define Check_Type(v, t)
Definition: ruby.h:459
void rb_raise(VALUE exc, const char *fmt,...)
Definition: error.c:1574
return Qtrue
Definition: tcltklib.c:9597
static VALUE cState_quirks_mode_p(VALUE self)
Definition: generator.c:1323
VALUE rb_convert_type(VALUE, int, const char *, const char *)
Definition: object.c:2079
static void freverse(char *start, char *end)
Definition: generator.c:378
void rb_define_alloc_func(VALUE, rb_alloc_func_t)
VALUE rb_obj_is_kind_of(VALUE, VALUE)
Definition: object.c:525
#define T_HASH
Definition: ruby.h:421
static VALUE mJSON
Definition: generator.c:17
static void fbuffer_append_char(FBuffer *fb, char newchr)
Definition: generator.c:371
static VALUE cState_max_nesting_set(VALUE self, VALUE depth)
Definition: generator.c:1287
#define RARRAY_LEN(ARRAY)
Definition: generator.h:39
return str
Definition: ruby.c:1183
#define RB_OBJ_STRING(obj)
Definition: generator.c:14
static VALUE mObject
Definition: generator.c:17
static VALUE mString_to_json_raw(int argc, VALUE *argv, VALUE self)
Definition: generator.c:534
static VALUE cState_s_allocate(VALUE klass)
Definition: generator.c:622
static VALUE cState_allow_nan_p(VALUE self)
Definition: generator.c:1300
static VALUE mTrueClass_to_json(int argc, VALUE *argv, VALUE self)
Definition: generator.c:560
static ID i_depth
Definition: generator.c:23
VALUE rb_path2class(const char *)
Definition: variable.c:293
VALUE VALUE args
Definition: tcltklib.c:2550
#define ID2SYM(i)
Definition: cparse.c:63
unsigned short UTF16
Definition: generator.h:85
static VALUE mString
Definition: generator.c:17
static VALUE cState
Definition: generator.c:17
VALUE keys
Definition: tkutil.c:277
static VALUE cState_indent(VALUE self)
Definition: generator.c:1079
static void generate_json(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj)
Definition: generator.c:897
static void generate_json_float(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj)
Definition: generator.c:880
static VALUE cState_space_set(VALUE self, VALUE space)
Definition: generator.c:1128
static FBuffer * fbuffer_dup(FBuffer *fb)
Definition: generator.c:407
static ID i_dup
Definition: generator.c:23
static void fbuffer_append(FBuffer *fb, const char *newstr, unsigned long len)
Definition: generator.c:352
#define Qnil
Definition: ruby.h:367
static VALUE mNilClass_to_json(int argc, VALUE *argv, VALUE self)
Definition: generator.c:580
static VALUE mString_to_json(int argc, VALUE *argv, VALUE self)
Definition: generator.c:505
static VALUE mExt
Definition: generator.c:17
#define MEMZERO(p, type, n)
Definition: ruby.h:1052
static void generate_json_true(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj)
Definition: generator.c:864
VALUE rb_require(const char *)
Definition: load.c:652
n NULL
Definition: yaml2byte.c:134
memset(y->frac+ix+1, 0,(y->Prec-(ix+1))*sizeof(BDIGIT))
return Data_Wrap_Struct(CLASS_OF(interp), 0, ip_free, slave)
static ID i_array_nl
Definition: generator.c:23
static void generate_json_fixnum(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj)
Definition: generator.c:869
static ID i_aref
Definition: generator.c:23
static ID i_send
Definition: generator.c:23
static VALUE cState_generate(VALUE self, VALUE obj)
Definition: generator.c:982
VALUE rb_class_new_instance(int, VALUE *, VALUE)
Definition: object.c:1639
return Qfalse
Definition: tcltklib.c:6768
VALUE rb_class_name(VALUE)
Definition: variable.c:305
#define ALLOC_N(type, n)
Definition: ruby.h:1034
unsigned long initial_length
Definition: generator.h:56
RUBY_EXTERN VALUE rb_cObject
Definition: ruby.h:1246
int depth
Definition: tcltklib.c:2187
static VALUE cState_depth(VALUE self)
Definition: generator.c:1346
static ID i_indent
Definition: generator.c:23
static VALUE mArray
Definition: generator.c:17
static VALUE mNilClass
Definition: generator.c:17
unsigned long UTF32
Definition: generator.h:84
#define NIL_P(v)
Definition: ruby.h:374
static ID i_ascii_only
Definition: generator.c:23
static VALUE cState_indent_set(VALUE self, VALUE indent)
Definition: generator.c:1090
static VALUE VALUE obj
Definition: tcltklib.c:3147
static VALUE mFalseClass_to_json(int argc, VALUE *argv, VALUE self)
Definition: generator.c:570
static VALUE mFloat
Definition: generator.c:17
static void convert_UTF8_to_JSON_ASCII(FBuffer *buffer, VALUE string)
Definition: generator.c:134
static VALUE cState_depth_set(VALUE self, VALUE depth)
Definition: generator.c:1358
#define MEMCPY(p1, p2, type, n)
Definition: ruby.h:1053
unsigned char buf[MIME_BUF_SIZE]
Definition: nkf.c:3913
static ID i_to_json
Definition: generator.c:23
RUBY_EXTERN int isinf(double)
Definition: isinf.c:56
static ID i_unpack
Definition: generator.c:23
static int VALUE key
Definition: tkutil.c:265
#define ALLOC(type)
Definition: ruby.h:1035
static VALUE mHash
Definition: generator.c:17
static void generate_json_string(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj)
Definition: generator.c:840
static VALUE mBignum
Definition: generator.c:17
static ID i_new
Definition: generator.c:23
VALUE rb_const_get(VALUE, ID)
Definition: variable.c:1635
static VALUE mString_to_json_raw_object(VALUE self)
Definition: generator.c:518
VALUE * argv
Definition: tcltklib.c:1962
static VALUE mFloat_to_json(int argc, VALUE *argv, VALUE self)
Definition: generator.c:483
void rb_define_alias(VALUE klass, const char *name1, const char *name2)
Defines an alias of a method.
Definition: class.c:1385
RUBY_EXTERN VALUE rb_cRegexp
Definition: ruby.h:1274
static const int halfShift
Definition: generator.h:99
#define REALLOC_N(var, type, n)
Definition: ruby.h:1036
q result
Definition: tcltklib.c:7059
static char * fstrndup(const char *ptr, unsigned long len)
Definition: generator.c:296
volatile VALUE value
Definition: tcltklib.c:9429
#define RB_GC_GUARD(object)
Definition: generator.h:50
VALUE rb_hash_new(void)
Definition: hash.c:229
void ruby_xfree(void *x)
Definition: gc.c:916
#define strdup(s)
Definition: util.h:69
int rb_scan_args(int argc, const VALUE *argv, const char *fmt,...)
Definition: class.c:1416
static VALUE cState_to_h(VALUE self)
Definition: generator.c:721
static VALUE cState_space_before(VALUE self)
Definition: generator.c:1153
size_t length
Definition: tcltklib.c:4548
unsigned long ID
Definition: ruby.h:89
static VALUE cState_partial_generate(VALUE self, VALUE obj)
Definition: generator.c:967
#define FBUFFER_PAIR(fb)
Definition: generator.h:67
static ID i_allow_nan
Definition: generator.c:23
int argc
Definition: tcltklib.c:1961
static ID i_pack
Definition: generator.c:23
static const UTF32 halfMask
Definition: generator.h:102
static VALUE cState_ascii_only_p(VALUE self)
Definition: generator.c:1312
static void unicode_escape(char *buf, UTF16 character)
Definition: generator.c:113
register unsigned int len
Definition: name2ctype.h:22210
char * ptr
Definition: generator.h:57
#define UNI_SUR_HIGH_START
Definition: generator.h:94
#define isnan(x)
Definition: win32.h:334
static void fbuffer_inc_capa(FBuffer *fb, unsigned long requested)
Definition: generator.c:335
static VALUE mObject_to_json(int argc, VALUE *argv, VALUE self)
Definition: generator.c:592
void Init_generator()
Definition: generator.c:1368
static ID i_create_id
Definition: generator.c:23
return ptr
Definition: tcltklib.c:780
VpDivd * c
Definition: bigdecimal.c:1163
state
Definition: gb18030.c:213
int rb_respond_to(VALUE, ID)
Definition: vm_method.c:1231
VALUE rb_define_module_under(VALUE outer, const char *name)
Definition: class.c:607
static VALUE CJSON_SAFE_STATE_PROTOTYPE
Definition: generator.c:17
gz end
Definition: zlib.c:2033
static ID i_match
Definition: generator.c:23
static void generate_json_object(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj)
Definition: generator.c:753
static ID i_to_s
Definition: generator.c:23
unsigned long len
Definition: generator.h:58
static FBuffer * cState_prepare_buffer(VALUE self)
Definition: generator.c:930
static VALUE cState_aref(VALUE self, VALUE name)
Definition: generator.c:743
#define UNI_MAX_BMP
Definition: generator.h:89
static VALUE cState_quirks_mode_set(VALUE self, VALUE enable)
Definition: generator.c:1334
VALUE rb_cBignum
Definition: bignum.c:27
static void fbuffer_append_str(FBuffer *fb, VALUE str)
Definition: generator.c:361
#define UNI_SUR_LOW_END
Definition: generator.h:97
static VALUE mString_Extend
Definition: generator.c:17
static void convert_UTF8_to_JSON(FBuffer *buffer, VALUE string)
Definition: generator.c:232
#define GENERATE_JSON(type)
Definition: generator.h:137
#define UNI_MAX_UTF16
Definition: generator.h:90
VALUE rb_hash_aref(VALUE hash, VALUE key)
Definition: hash.c:518
char * start
Definition: yaml2byte.c:126
static VALUE cState_object_nl_set(VALUE self, VALUE object_nl)
Definition: generator.c:1202
static void generate_json_null(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj)
Definition: generator.c:854
#define LONG2FIX(i)
Definition: ruby.h:226
#define RTEST(v)
Definition: ruby.h:373
static ID i_key_p
Definition: generator.c:23
#define T_STRING
Definition: ruby.h:418
klass
Definition: tcltklib.c:3493
char ch
Definition: yaml2byte.c:124
static VALUE mFalseClass
Definition: generator.c:17
#define UNI_SUR_LOW_START
Definition: generator.h:96
static VALUE eNestingError
Definition: generator.c:17
#define UNI_REPLACEMENT_CHAR
Definition: generator.h:88
static ID i_quirks_mode
Definition: generator.c:23
VALUE rb_cArray
Definition: array.c:27
#define assert(condition)
Definition: ossl.h:44
return rb_funcall(q->proc, ID_call, 0)
#define StringValuePtr(v)
Definition: ruby.h:467
static VALUE cState_init_copy(VALUE obj, VALUE orig)
Definition: generator.c:1032
static VALUE cState_space(VALUE self)
Definition: generator.c:1116
VALUE opts
Definition: tcltklib.c:6135
static VALUE mBignum_to_json(int argc, VALUE *argv, VALUE self)
Definition: generator.c:473
#define FBUFFER_INITIAL_LENGTH
Definition: generator.h:62
#define PRIsVALUE
Definition: generator.c:12
ssize_t i
Definition: bigdecimal.c:5519
VALUE rb_define_module(const char *name)
Definition: class.c:587
#define rb_intern(str)
static long fltoa(long number, char *buf)
Definition: generator.c:387
const char * name
Definition: nkf.c:208
static FBuffer * fbuffer_alloc_with_length(unsigned long initial_length)
Definition: generator.c:314
#define FIX2LONG(x)
Definition: ruby.h:336
RUBY_EXTERN VALUE rb_cFixnum
Definition: ruby.h:1258
static VALUE mHash_to_json(int argc, VALUE *argv, VALUE self)
Definition: generator.c:441
Real * a
Definition: bigdecimal.c:1140
void rb_define_method(VALUE klass, const char *name, VALUE(*func)(ANYARGS), int argc)
Definition: class.c:1210
VALUE rb_str_new2(const char *)
VALUE rb_eArgError
Definition: error.c:468
static void generate_json_bignum(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj)
Definition: generator.c:874
#define GET_STATE(self)
Definition: generator.h:133
static VALUE mString_included_s(VALUE self, VALUE modul)
Definition: generator.c:493
#define FORCE_UTF8(obj)
Definition: generator.h:22
VALUE rb_str_new(const char *, long)
Definition: string.c:410
VALUE rb_obj_class(VALUE)
Definition: object.c:177
static void State_free(JSON_Generator_State *state)
Definition: generator.c:602