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