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