json_pure 1.2.4 → 1.4.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,294 +1,444 @@
1
- #include <string.h>
2
- #include "ruby.h"
3
- #if HAVE_RUBY_ST_H
4
- #include "ruby/st.h"
5
- #endif
6
- #if HAVE_ST_H
7
- #include "st.h"
8
- #endif
9
- #include "unicode.h"
10
- #include <math.h>
11
-
12
- #ifndef RHASH_SIZE
13
- #define RHASH_SIZE(hsh) (RHASH(hsh)->tbl->num_entries)
14
- #endif
15
-
16
- #ifndef RFLOAT_VALUE
17
- #define RFLOAT_VALUE(val) (RFLOAT(val)->value)
18
- #endif
19
-
20
- #define option_given_p(opts, key) RTEST(rb_funcall(opts, i_key_p, 1, key))
1
+ #include "generator.h"
21
2
 
22
3
  #ifdef HAVE_RUBY_ENCODING_H
23
- #include "ruby/encoding.h"
24
- #define FORCE_UTF8(obj) rb_enc_associate((obj), rb_utf8_encoding())
25
- static VALUE mEncoding_UTF_8;
4
+ static VALUE CEncoding_UTF_8;
26
5
  static ID i_encoding, i_encode;
27
- #else
28
- #define FORCE_UTF8(obj)
29
6
  #endif
30
7
 
31
- #define check_max_nesting(state, depth) do { \
32
- long current_nesting = 1 + depth; \
33
- if (state->max_nesting != 0 && current_nesting > state->max_nesting) \
34
- rb_raise(eNestingError, "nesting of %ld is too deep", current_nesting); \
35
- } while (0);
36
-
37
8
  static VALUE mJSON, mExt, mGenerator, cState, mGeneratorMethods, mObject,
38
- mHash, mArray, mInteger, mFloat, mString, mString_Extend,
9
+ mHash, mArray, mFixnum, mBignum, mFloat, mString, mString_Extend,
39
10
  mTrueClass, mFalseClass, mNilClass, eGeneratorError,
40
- eCircularDatastructure, eNestingError;
11
+ eNestingError, CRegexp_MULTILINE, CJSON_SAFE_STATE_PROTOTYPE,
12
+ i_SAFE_STATE_PROTOTYPE;
41
13
 
42
14
  static ID i_to_s, i_to_json, i_new, i_indent, i_space, i_space_before,
43
- i_object_nl, i_array_nl, i_check_circular, i_max_nesting,
44
- i_allow_nan, i_pack, i_unpack, i_create_id, i_extend, i_key_p,
45
- i_aref, i_send, i_respond_to_p;
46
-
47
- typedef struct JSON_Generator_StateStruct {
48
- VALUE indent;
49
- VALUE space;
50
- VALUE space_before;
51
- VALUE object_nl;
52
- VALUE array_nl;
53
- int check_circular;
54
- VALUE seen;
55
- VALUE memo;
56
- VALUE depth;
57
- long max_nesting;
58
- int flag;
59
- int allow_nan;
60
- } JSON_Generator_State;
61
-
62
- #define GET_STATE(self) \
63
- JSON_Generator_State *state; \
64
- Data_Get_Struct(self, JSON_Generator_State, state);
15
+ i_object_nl, i_array_nl, i_max_nesting, i_allow_nan, i_ascii_only,
16
+ i_pack, i_unpack, i_create_id, i_extend, i_key_p, i_aref, i_send,
17
+ i_respond_to_p, i_match, i_keys, i_depth, i_dup;
65
18
 
66
- /*
67
- * Document-module: JSON::Ext::Generator
68
- *
69
- * This is the JSON generator implemented as a C extension. It can be
70
- * configured to be used by setting
71
- *
72
- * JSON.generator = JSON::Ext::Generator
73
- *
74
- * with the method generator= in JSON.
75
- *
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.
76
39
  */
77
40
 
78
- static int hash_to_json_state_i(VALUE key, VALUE value, VALUE Vstate)
79
- {
80
- VALUE json, buf, Vdepth;
81
- GET_STATE(Vstate);
82
- buf = state->memo;
83
- Vdepth = state->depth;
84
-
85
- if (key == Qundef) return ST_CONTINUE;
86
- if (state->flag) {
87
- state->flag = 0;
88
- rb_str_buf_cat2(buf, ",");
89
- if (RSTRING_LEN(state->object_nl)) rb_str_buf_append(buf, state->object_nl);
90
- }
91
- if (RSTRING_LEN(state->object_nl)) {
92
- rb_str_buf_append(buf, rb_str_times(state->indent, Vdepth));
93
- }
94
- json = rb_funcall(rb_funcall(key, i_to_s, 0), i_to_json, 2, Vstate, Vdepth);
95
- Check_Type(json, T_STRING);
96
- rb_str_buf_append(buf, json);
97
- OBJ_INFECT(buf, json);
98
- if (RSTRING_LEN(state->space_before)) {
99
- rb_str_buf_append(buf, state->space_before);
100
- }
101
- rb_str_buf_cat2(buf, ":");
102
- if (RSTRING_LEN(state->space)) rb_str_buf_append(buf, state->space);
103
- json = rb_funcall(value, i_to_json, 2, Vstate, Vdepth);
104
- Check_Type(json, T_STRING);
105
- state->flag = 1;
106
- rb_str_buf_append(buf, json);
107
- OBJ_INFECT(buf, json);
108
- state->depth = Vdepth;
109
- state->memo = buf;
110
- return ST_CONTINUE;
111
- }
112
-
113
- inline static VALUE mHash_json_transfrom(VALUE self, VALUE Vstate, VALUE Vdepth) {
114
- long depth, len = RHASH_SIZE(self);
115
- VALUE result;
116
- GET_STATE(Vstate);
117
-
118
- depth = 1 + FIX2LONG(Vdepth);
119
- result = rb_str_buf_new(len);
120
- state->memo = result;
121
- state->depth = LONG2FIX(depth);
122
- state->flag = 0;
123
- rb_str_buf_cat2(result, "{");
124
- if (RSTRING_LEN(state->object_nl)) rb_str_buf_append(result, state->object_nl);
125
- rb_hash_foreach(self, hash_to_json_state_i, Vstate);
126
- if (RSTRING_LEN(state->object_nl)) rb_str_buf_append(result, state->object_nl);
127
- if (RSTRING_LEN(state->object_nl)) {
128
- rb_str_buf_append(result, rb_str_times(state->indent, Vdepth));
129
- }
130
- rb_str_buf_cat2(result, "}");
131
- return result;
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, int 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;
132
101
  }
133
102
 
134
- static int hash_to_json_i(VALUE key, VALUE value, VALUE buf)
103
+ /* Escapes the UTF16 character and stores the result in the buffer buf. */
104
+ static void unicode_escape(char *buf, UTF16 character)
135
105
  {
136
- VALUE tmp;
106
+ const char *digits = "0123456789abcdef";
137
107
 
138
- if (key == Qundef) return ST_CONTINUE;
139
- if (RSTRING_LEN(buf) > 1) rb_str_buf_cat2(buf, ",");
140
- tmp = rb_funcall(rb_funcall(key, i_to_s, 0), i_to_json, 0);
141
- Check_Type(tmp, T_STRING);
142
- rb_str_buf_append(buf, tmp);
143
- OBJ_INFECT(buf, tmp);
144
- rb_str_buf_cat2(buf, ":");
145
- tmp = rb_funcall(value, i_to_json, 0);
146
- Check_Type(tmp, T_STRING);
147
- rb_str_buf_append(buf, tmp);
148
- OBJ_INFECT(buf, tmp);
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
+ }
149
113
 
150
- return ST_CONTINUE;
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);
151
121
  }
152
122
 
153
- /*
154
- * call-seq: to_json(state = nil, depth = 0)
155
- *
156
- * Returns a JSON string containing a JSON object, that is unparsed from
157
- * this Hash instance.
158
- * _state_ is a JSON::State object, that can also be used to configure the
159
- * produced JSON string output further.
160
- * _depth_ is used to find out nesting depth, to indent accordingly.
161
- */
162
- static VALUE mHash_to_json(int argc, VALUE *argv, VALUE self)
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)
163
126
  {
164
- VALUE Vstate, Vdepth, result;
165
- long depth;
166
-
167
- rb_scan_args(argc, argv, "02", &Vstate, &Vdepth);
168
- depth = NIL_P(Vdepth) ? 0 : FIX2LONG(Vdepth);
169
- if (NIL_P(Vstate)) {
170
- long len = RHASH_SIZE(self);
171
- result = rb_str_buf_new(len);
172
- rb_str_buf_cat2(result, "{");
173
- rb_hash_foreach(self, hash_to_json_i, result);
174
- rb_str_buf_cat2(result, "}");
175
- } else {
176
- GET_STATE(Vstate);
177
- check_max_nesting(state, depth);
178
- if (state->check_circular) {
179
- VALUE self_id = rb_obj_id(self);
180
- if (RTEST(rb_hash_aref(state->seen, self_id))) {
181
- rb_raise(eCircularDatastructure,
182
- "circular data structures not supported!");
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
163
+ unicode_escape_to_buffer(buffer, buf, UNI_REPLACEMENT_CHAR);
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
+ }
183
201
  }
184
- rb_hash_aset(state->seen, self_id, Qtrue);
185
- result = mHash_json_transfrom(self, Vstate, LONG2FIX(depth));
186
- rb_hash_delete(state->seen, self_id);
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
208
+ unicode_escape_to_buffer(buffer, buf, UNI_REPLACEMENT_CHAR);
209
+ #endif
187
210
  } else {
188
- result = mHash_json_transfrom(self, Vstate, LONG2FIX(depth));
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));
189
215
  }
190
216
  }
191
- OBJ_INFECT(result, self);
192
- FORCE_UTF8(result);
193
- return result;
194
217
  }
195
218
 
196
- inline static VALUE mArray_json_transfrom(VALUE self, VALUE Vstate, VALUE Vdepth) {
197
- long i, len = RARRAY_LEN(self);
198
- VALUE shift, result;
199
- long depth = NIL_P(Vdepth) ? 0 : FIX2LONG(Vdepth);
200
- VALUE delim = rb_str_new2(",");
201
- GET_STATE(Vstate);
202
-
203
- check_max_nesting(state, depth);
204
- if (state->check_circular) {
205
- VALUE self_id = rb_obj_id(self);
206
- rb_hash_aset(state->seen, self_id, Qtrue);
207
- result = rb_str_buf_new(len);
208
- if (RSTRING_LEN(state->array_nl)) rb_str_append(delim, state->array_nl);
209
- shift = rb_str_times(state->indent, LONG2FIX(depth + 1));
210
-
211
- rb_str_buf_cat2(result, "[");
212
- OBJ_INFECT(result, self);
213
- rb_str_buf_append(result, state->array_nl);
214
- for (i = 0; i < len; i++) {
215
- VALUE element = RARRAY_PTR(self)[i];
216
- if (RTEST(rb_hash_aref(state->seen, rb_obj_id(element)))) {
217
- rb_raise(eCircularDatastructure,
218
- "circular data structures not supported!");
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
+ int 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;
219
277
  }
220
- OBJ_INFECT(result, element);
221
- if (i > 0) rb_str_buf_append(result, delim);
222
- rb_str_buf_append(result, shift);
223
- element = rb_funcall(element, i_to_json, 2, Vstate, LONG2FIX(depth + 1));
224
- Check_Type(element, T_STRING);
225
- rb_str_buf_append(result, element);
226
- }
227
- if (RSTRING_LEN(state->array_nl)) {
228
- rb_str_buf_append(result, state->array_nl);
229
- rb_str_buf_append(result, rb_str_times(state->indent, LONG2FIX(depth)));
230
278
  }
231
- rb_str_buf_cat2(result, "]");
232
- rb_hash_delete(state->seen, self_id);
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, int 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
+
297
+ static FBuffer *fbuffer_alloc()
298
+ {
299
+ FBuffer *fb = ALLOC(FBuffer);
300
+ memset((void *) fb, 0, sizeof(FBuffer));
301
+ fb->initial_length = FBUFFER_INITIAL_LENGTH;
302
+ return fb;
303
+ }
304
+
305
+ static FBuffer *fbuffer_alloc_with_length(unsigned int 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_free_only_buffer(FBuffer *fb)
322
+ {
323
+ ruby_xfree(fb);
324
+ }
325
+
326
+ static void fbuffer_clear(FBuffer *fb)
327
+ {
328
+ fb->len = 0;
329
+ }
330
+
331
+ static void fbuffer_inc_capa(FBuffer *fb, unsigned int requested)
332
+ {
333
+ unsigned int required;
334
+
335
+ if (!fb->ptr) {
336
+ fb->ptr = ALLOC_N(char, fb->initial_length);
337
+ fb->capa = fb->initial_length;
338
+ }
339
+
340
+ for (required = fb->capa; requested > required - fb->len; required <<= 1);
341
+
342
+ if (required > fb->capa) {
343
+ REALLOC_N(fb->ptr, char, required);
344
+ fb->capa = required;
345
+ }
346
+ }
347
+
348
+ static void fbuffer_append(FBuffer *fb, const char *newstr, unsigned int len)
349
+ {
350
+ if (len > 0) {
351
+ fbuffer_inc_capa(fb, len);
352
+ MEMCPY(fb->ptr + fb->len, newstr, char, len);
353
+ fb->len += len;
354
+ }
355
+ }
356
+
357
+ static void fbuffer_append_char(FBuffer *fb, char newchr)
358
+ {
359
+ fbuffer_inc_capa(fb, 1);
360
+ *(fb->ptr + fb->len) = newchr;
361
+ fb->len++;
362
+ }
363
+
364
+ static void freverse(char *start, char *end)
365
+ {
366
+ char c;
367
+
368
+ while (end > start) {
369
+ c = *end, *end-- = *start, *start++ = c;
370
+ }
371
+ }
372
+
373
+ static int fltoa(long number, char *buf)
374
+ {
375
+ static char digits[] = "0123456789";
376
+ long sign = number;
377
+ char* tmp = buf;
378
+
379
+ if (sign < 0) number = -number;
380
+ do *tmp++ = digits[number % 10]; while (number /= 10);
381
+ if (sign < 0) *tmp++ = '-';
382
+ freverse(buf, tmp - 1);
383
+ return tmp - buf;
384
+ }
385
+
386
+ static void fbuffer_append_long(FBuffer *fb, long number)
387
+ {
388
+ char buf[20];
389
+ int len = fltoa(number, buf);
390
+ fbuffer_append(fb, buf, len);
391
+ }
392
+
393
+ static FBuffer *fbuffer_dup(FBuffer *fb)
394
+ {
395
+ int len = fb->len;
396
+ FBuffer *result;
397
+
398
+ if (len > 0) {
399
+ result = fbuffer_alloc_with_length(len);
400
+ fbuffer_append(result, FBUFFER_PAIR(fb));
233
401
  } else {
234
- result = rb_str_buf_new(len);
235
- OBJ_INFECT(result, self);
236
- if (RSTRING_LEN(state->array_nl)) rb_str_append(delim, state->array_nl);
237
- shift = rb_str_times(state->indent, LONG2FIX(depth + 1));
238
-
239
- rb_str_buf_cat2(result, "[");
240
- rb_str_buf_append(result, state->array_nl);
241
- for (i = 0; i < len; i++) {
242
- VALUE element = RARRAY_PTR(self)[i];
243
- OBJ_INFECT(result, element);
244
- if (i > 0) rb_str_buf_append(result, delim);
245
- rb_str_buf_append(result, shift);
246
- element = rb_funcall(element, i_to_json, 2, Vstate, LONG2FIX(depth + 1));
247
- Check_Type(element, T_STRING);
248
- rb_str_buf_append(result, element);
249
- }
250
- rb_str_buf_append(result, state->array_nl);
251
- if (RSTRING_LEN(state->array_nl)) {
252
- rb_str_buf_append(result, rb_str_times(state->indent, LONG2FIX(depth)));
253
- }
254
- rb_str_buf_cat2(result, "]");
402
+ result = fbuffer_alloc();
255
403
  }
256
404
  return result;
257
405
  }
258
406
 
407
+ /*
408
+ * Document-module: JSON::Ext::Generator
409
+ *
410
+ * This is the JSON generator implemented as a C extension. It can be
411
+ * configured to be used by setting
412
+ *
413
+ * JSON.generator = JSON::Ext::Generator
414
+ *
415
+ * with the method generator= in JSON.
416
+ *
417
+ */
418
+
419
+ /*
420
+ * call-seq: to_json(state = nil)
421
+ *
422
+ * Returns a JSON string containing a JSON object, that is generated from
423
+ * this Hash instance.
424
+ * _state_ is a JSON::State object, that can also be used to configure the
425
+ * produced JSON string output further.
426
+ */
427
+ static VALUE mHash_to_json(int argc, VALUE *argv, VALUE self)
428
+ {
429
+ GENERATE_JSON(object);
430
+ }
431
+
259
432
  /*
260
- * call-seq: to_json(state = nil, depth = 0)
433
+ * call-seq: to_json(state = nil)
261
434
  *
262
- * Returns a JSON string containing a JSON array, that is unparsed from
435
+ * Returns a JSON string containing a JSON array, that is generated from
263
436
  * this Array instance.
264
437
  * _state_ is a JSON::State object, that can also be used to configure the
265
438
  * produced JSON string output further.
266
- * _depth_ is used to find out nesting depth, to indent accordingly.
267
439
  */
268
440
  static VALUE mArray_to_json(int argc, VALUE *argv, VALUE self) {
269
- VALUE Vstate, Vdepth, result;
270
-
271
- rb_scan_args(argc, argv, "02", &Vstate, &Vdepth);
272
- if (NIL_P(Vstate)) {
273
- long i, len = RARRAY_LEN(self);
274
- result = rb_str_buf_new(2 + 2 * len);
275
- rb_str_buf_cat2(result, "[");
276
- OBJ_INFECT(result, self);
277
- for (i = 0; i < len; i++) {
278
- VALUE element = RARRAY_PTR(self)[i];
279
- OBJ_INFECT(result, element);
280
- if (i > 0) rb_str_buf_cat2(result, ",");
281
- element = rb_funcall(element, i_to_json, 0);
282
- Check_Type(element, T_STRING);
283
- rb_str_buf_append(result, element);
284
- }
285
- rb_str_buf_cat2(result, "]");
286
- } else {
287
- result = mArray_json_transfrom(self, Vstate, Vdepth);
288
- }
289
- OBJ_INFECT(result, self);
290
- FORCE_UTF8(result);
291
- return result;
441
+ GENERATE_JSON(array);
292
442
  }
293
443
 
294
444
  /*
@@ -296,11 +446,19 @@ static VALUE mArray_to_json(int argc, VALUE *argv, VALUE self) {
296
446
  *
297
447
  * Returns a JSON string representation for this Integer number.
298
448
  */
299
- static VALUE mInteger_to_json(int argc, VALUE *argv, VALUE self)
449
+ static VALUE mFixnum_to_json(int argc, VALUE *argv, VALUE self)
300
450
  {
301
- VALUE result = rb_funcall(self, i_to_s, 0);
302
- FORCE_UTF8(result);
303
- return result;
451
+ GENERATE_JSON(fixnum);
452
+ }
453
+
454
+ /*
455
+ * call-seq: to_json(*)
456
+ *
457
+ * Returns a JSON string representation for this Integer number.
458
+ */
459
+ static VALUE mBignum_to_json(int argc, VALUE *argv, VALUE self)
460
+ {
461
+ GENERATE_JSON(bignum);
304
462
  }
305
463
 
306
464
  /*
@@ -310,30 +468,7 @@ static VALUE mInteger_to_json(int argc, VALUE *argv, VALUE self)
310
468
  */
311
469
  static VALUE mFloat_to_json(int argc, VALUE *argv, VALUE self)
312
470
  {
313
- JSON_Generator_State *state = NULL;
314
- VALUE Vstate, rest, tmp, result;
315
- double value = RFLOAT_VALUE(self);
316
- rb_scan_args(argc, argv, "01*", &Vstate, &rest);
317
- if (!NIL_P(Vstate)) Data_Get_Struct(Vstate, JSON_Generator_State, state);
318
- if (isinf(value)) {
319
- if (state && state->allow_nan) {
320
- result = rb_funcall(self, i_to_s, 0);
321
- } else {
322
- tmp = rb_funcall(self, i_to_s, 0);
323
- rb_raise(eGeneratorError, "%u: %s not allowed in JSON", __LINE__, StringValueCStr(tmp));
324
- }
325
- } else if (isnan(value)) {
326
- if (state && state->allow_nan) {
327
- result = rb_funcall(self, i_to_s, 0);
328
- } else {
329
- tmp = rb_funcall(self, i_to_s, 0);
330
- rb_raise(eGeneratorError, "%u: %s not allowed in JSON", __LINE__, StringValueCStr(tmp));
331
- }
332
- } else {
333
- result = rb_funcall(self, i_to_s, 0);
334
- }
335
- FORCE_UTF8(result);
336
- return result;
471
+ GENERATE_JSON(float);
337
472
  }
338
473
 
339
474
  /*
@@ -343,7 +478,6 @@ static VALUE mFloat_to_json(int argc, VALUE *argv, VALUE self)
343
478
  */
344
479
  static VALUE mString_included_s(VALUE self, VALUE modul) {
345
480
  VALUE result = rb_funcall(modul, i_extend, 1, mString_Extend);
346
- FORCE_UTF8(result);
347
481
  return result;
348
482
  }
349
483
 
@@ -356,38 +490,24 @@ static VALUE mString_included_s(VALUE self, VALUE modul) {
356
490
  */
357
491
  static VALUE mString_to_json(int argc, VALUE *argv, VALUE self)
358
492
  {
359
- VALUE result = rb_str_buf_new(RSTRING_LEN(self));
360
- rb_str_buf_cat2(result, "\"");
361
- #ifdef HAVE_RUBY_ENCODING_H
362
- if (rb_funcall(self, i_encoding, 0) == mEncoding_UTF_8) {
363
- JSON_convert_UTF8_to_JSON(result, self, strictConversion);
364
- } else {
365
- VALUE string = rb_funcall(self, i_encode, 1, mEncoding_UTF_8);
366
- JSON_convert_UTF8_to_JSON(result, string, strictConversion);
367
- }
368
- #else
369
- JSON_convert_UTF8_to_JSON(result, self, strictConversion);
370
- #endif
371
- rb_str_buf_cat2(result, "\"");
372
- FORCE_UTF8(result);
373
- return result;
493
+ GENERATE_JSON(string);
374
494
  }
375
495
 
376
496
  /*
377
497
  * call-seq: to_json_raw_object()
378
498
  *
379
499
  * This method creates a raw object hash, that can be nested into
380
- * other data structures and will be unparsed as a raw string. This
500
+ * other data structures and will be generated as a raw string. This
381
501
  * method should be used, if you want to convert raw strings to JSON
382
502
  * instead of UTF-8 strings, e. g. binary data.
383
503
  */
384
- static VALUE mString_to_json_raw_object(VALUE self) {
504
+ static VALUE mString_to_json_raw_object(VALUE self)
505
+ {
385
506
  VALUE ary;
386
507
  VALUE result = rb_hash_new();
387
508
  rb_hash_aset(result, rb_funcall(mJSON, i_create_id, 0), rb_class_name(rb_obj_class(self)));
388
509
  ary = rb_funcall(self, i_unpack, 1, rb_str_new2("C*"));
389
510
  rb_hash_aset(result, rb_str_new2("raw"), ary);
390
- FORCE_UTF8(result);
391
511
  return result;
392
512
  }
393
513
 
@@ -397,12 +517,11 @@ static VALUE mString_to_json_raw_object(VALUE self) {
397
517
  * This method creates a JSON text from the result of a call to
398
518
  * to_json_raw_object of this String.
399
519
  */
400
- static VALUE mString_to_json_raw(int argc, VALUE *argv, VALUE self) {
401
- VALUE result, obj = mString_to_json_raw_object(self);
520
+ static VALUE mString_to_json_raw(int argc, VALUE *argv, VALUE self)
521
+ {
522
+ VALUE obj = mString_to_json_raw_object(self);
402
523
  Check_Type(obj, T_HASH);
403
- result = mHash_to_json(argc, argv, obj);
404
- FORCE_UTF8(result);
405
- return result;
524
+ return mHash_to_json(argc, argv, obj);
406
525
  }
407
526
 
408
527
  /*
@@ -411,7 +530,8 @@ static VALUE mString_to_json_raw(int argc, VALUE *argv, VALUE self) {
411
530
  * Raw Strings are JSON Objects (the raw bytes are stored in an array for the
412
531
  * key "raw"). The Ruby String can be created by this module method.
413
532
  */
414
- static VALUE mString_Extend_json_create(VALUE self, VALUE o) {
533
+ static VALUE mString_Extend_json_create(VALUE self, VALUE o)
534
+ {
415
535
  VALUE ary;
416
536
  Check_Type(o, T_HASH);
417
537
  ary = rb_hash_aref(o, rb_str_new2("raw"));
@@ -425,9 +545,7 @@ static VALUE mString_Extend_json_create(VALUE self, VALUE o) {
425
545
  */
426
546
  static VALUE mTrueClass_to_json(int argc, VALUE *argv, VALUE self)
427
547
  {
428
- VALUE result = rb_str_new2("true");
429
- FORCE_UTF8(result);
430
- return result;
548
+ GENERATE_JSON(true);
431
549
  }
432
550
 
433
551
  /*
@@ -437,9 +555,7 @@ static VALUE mTrueClass_to_json(int argc, VALUE *argv, VALUE self)
437
555
  */
438
556
  static VALUE mFalseClass_to_json(int argc, VALUE *argv, VALUE self)
439
557
  {
440
- VALUE result = rb_str_new2("false");
441
- FORCE_UTF8(result);
442
- return result;
558
+ GENERATE_JSON(false);
443
559
  }
444
560
 
445
561
  /*
@@ -448,9 +564,7 @@ static VALUE mFalseClass_to_json(int argc, VALUE *argv, VALUE self)
448
564
  */
449
565
  static VALUE mNilClass_to_json(int argc, VALUE *argv, VALUE self)
450
566
  {
451
- VALUE result = rb_str_new2("null");
452
- FORCE_UTF8(result);
453
- return result;
567
+ GENERATE_JSON(null);
454
568
  }
455
569
 
456
570
  /*
@@ -462,42 +576,38 @@ static VALUE mNilClass_to_json(int argc, VALUE *argv, VALUE self)
462
576
  */
463
577
  static VALUE mObject_to_json(int argc, VALUE *argv, VALUE self)
464
578
  {
465
- VALUE result, string = rb_funcall(self, i_to_s, 0);
579
+ VALUE state;
580
+ VALUE string = rb_funcall(self, i_to_s, 0);
581
+ rb_scan_args(argc, argv, "01", &state);
466
582
  Check_Type(string, T_STRING);
467
- result = mString_to_json(argc, argv, string);
468
- FORCE_UTF8(result);
469
- return result;
583
+ state = cState_from_state_s(cState, state);
584
+ return cState_partial_generate(state, string);
470
585
  }
471
586
 
472
- /*
473
- * Document-class: JSON::Ext::Generator::State
474
- *
475
- * This class is used to create State instances, that are use to hold data
476
- * while generating a JSON text from a a Ruby data structure.
477
- */
478
-
479
- static void State_mark(JSON_Generator_State *state)
587
+ static void State_free(JSON_Generator_State *state)
480
588
  {
481
- rb_gc_mark_maybe(state->indent);
482
- rb_gc_mark_maybe(state->space);
483
- rb_gc_mark_maybe(state->space_before);
484
- rb_gc_mark_maybe(state->object_nl);
485
- rb_gc_mark_maybe(state->array_nl);
486
- rb_gc_mark_maybe(state->seen);
487
- rb_gc_mark_maybe(state->memo);
488
- rb_gc_mark_maybe(state->depth);
589
+ if (state->indent) ruby_xfree(state->indent);
590
+ if (state->space) ruby_xfree(state->space);
591
+ if (state->space_before) ruby_xfree(state->space_before);
592
+ if (state->object_nl) ruby_xfree(state->object_nl);
593
+ if (state->array_nl) ruby_xfree(state->array_nl);
594
+ if (state->array_delim) fbuffer_free(state->array_delim);
595
+ if (state->object_delim) fbuffer_free(state->object_delim);
596
+ if (state->object_delim2) fbuffer_free(state->object_delim2);
597
+ ruby_xfree(state);
489
598
  }
490
599
 
491
600
  static JSON_Generator_State *State_allocate()
492
601
  {
493
602
  JSON_Generator_State *state = ALLOC(JSON_Generator_State);
603
+ MEMZERO(state, JSON_Generator_State, 1);
494
604
  return state;
495
605
  }
496
606
 
497
607
  static VALUE cState_s_allocate(VALUE klass)
498
608
  {
499
609
  JSON_Generator_State *state = State_allocate();
500
- return Data_Wrap_Struct(klass, State_mark, -1, state);
610
+ return Data_Wrap_Struct(klass, NULL, State_free, state);
501
611
  }
502
612
 
503
613
  /*
@@ -518,35 +628,43 @@ static VALUE cState_configure(VALUE self, VALUE opts)
518
628
  opts = tmp;
519
629
  tmp = rb_hash_aref(opts, ID2SYM(i_indent));
520
630
  if (RTEST(tmp)) {
631
+ int len;
521
632
  Check_Type(tmp, T_STRING);
522
- state->indent = tmp;
633
+ len = RSTRING_LEN(tmp);
634
+ state->indent = fstrndup(RSTRING_PTR(tmp), len);
635
+ state->indent_len = len;
523
636
  }
524
637
  tmp = rb_hash_aref(opts, ID2SYM(i_space));
525
638
  if (RTEST(tmp)) {
639
+ int len;
526
640
  Check_Type(tmp, T_STRING);
527
- state->space = tmp;
641
+ len = RSTRING_LEN(tmp);
642
+ state->space = fstrndup(RSTRING_PTR(tmp), len);
643
+ state->space_len = len;
528
644
  }
529
645
  tmp = rb_hash_aref(opts, ID2SYM(i_space_before));
530
646
  if (RTEST(tmp)) {
647
+ int len;
531
648
  Check_Type(tmp, T_STRING);
532
- state->space_before = tmp;
649
+ len = RSTRING_LEN(tmp);
650
+ state->space_before = fstrndup(RSTRING_PTR(tmp), len);
651
+ state->space_before_len = len;
533
652
  }
534
653
  tmp = rb_hash_aref(opts, ID2SYM(i_array_nl));
535
654
  if (RTEST(tmp)) {
655
+ int len;
536
656
  Check_Type(tmp, T_STRING);
537
- state->array_nl = tmp;
657
+ len = RSTRING_LEN(tmp);
658
+ state->array_nl = fstrndup(RSTRING_PTR(tmp), len);
659
+ state->array_nl_len = len;
538
660
  }
539
661
  tmp = rb_hash_aref(opts, ID2SYM(i_object_nl));
540
662
  if (RTEST(tmp)) {
663
+ int len;
541
664
  Check_Type(tmp, T_STRING);
542
- state->object_nl = tmp;
543
- }
544
- tmp = ID2SYM(i_check_circular);
545
- if (option_given_p(opts, tmp)) {
546
- tmp = rb_hash_aref(opts, ID2SYM(i_check_circular));
547
- state->check_circular = RTEST(tmp);
548
- } else {
549
- state->check_circular = 1;
665
+ len = RSTRING_LEN(tmp);
666
+ state->object_nl = fstrndup(RSTRING_PTR(tmp), len);
667
+ state->object_nl_len = len;
550
668
  }
551
669
  tmp = ID2SYM(i_max_nesting);
552
670
  state->max_nesting = 19;
@@ -559,8 +677,21 @@ static VALUE cState_configure(VALUE self, VALUE opts)
559
677
  state->max_nesting = 0;
560
678
  }
561
679
  }
680
+ tmp = ID2SYM(i_depth);
681
+ state->depth = 0;
682
+ if (option_given_p(opts, tmp)) {
683
+ VALUE depth = rb_hash_aref(opts, tmp);
684
+ if (RTEST(depth)) {
685
+ Check_Type(depth, T_FIXNUM);
686
+ state->depth = FIX2LONG(depth);
687
+ } else {
688
+ state->depth = 0;
689
+ }
690
+ }
562
691
  tmp = rb_hash_aref(opts, ID2SYM(i_allow_nan));
563
692
  state->allow_nan = RTEST(tmp);
693
+ tmp = rb_hash_aref(opts, ID2SYM(i_ascii_only));
694
+ state->ascii_only = RTEST(tmp);
564
695
  return self;
565
696
  }
566
697
 
@@ -574,22 +705,23 @@ static VALUE cState_to_h(VALUE self)
574
705
  {
575
706
  VALUE result = rb_hash_new();
576
707
  GET_STATE(self);
577
- rb_hash_aset(result, ID2SYM(i_indent), state->indent);
578
- rb_hash_aset(result, ID2SYM(i_space), state->space);
579
- rb_hash_aset(result, ID2SYM(i_space_before), state->space_before);
580
- rb_hash_aset(result, ID2SYM(i_object_nl), state->object_nl);
581
- rb_hash_aset(result, ID2SYM(i_array_nl), state->array_nl);
582
- rb_hash_aset(result, ID2SYM(i_check_circular), state->check_circular ? Qtrue : Qfalse);
708
+ rb_hash_aset(result, ID2SYM(i_indent), rb_str_new(state->indent, state->indent_len));
709
+ rb_hash_aset(result, ID2SYM(i_space), rb_str_new(state->space, state->space_len));
710
+ rb_hash_aset(result, ID2SYM(i_space_before), rb_str_new(state->space_before, state->space_before_len));
711
+ rb_hash_aset(result, ID2SYM(i_object_nl), rb_str_new(state->object_nl, state->object_nl_len));
712
+ rb_hash_aset(result, ID2SYM(i_array_nl), rb_str_new(state->array_nl, state->array_nl_len));
583
713
  rb_hash_aset(result, ID2SYM(i_allow_nan), state->allow_nan ? Qtrue : Qfalse);
714
+ rb_hash_aset(result, ID2SYM(i_ascii_only), state->ascii_only ? Qtrue : Qfalse);
584
715
  rb_hash_aset(result, ID2SYM(i_max_nesting), LONG2FIX(state->max_nesting));
716
+ rb_hash_aset(result, ID2SYM(i_depth), LONG2FIX(state->depth));
585
717
  return result;
586
718
  }
587
719
 
588
720
  /*
589
- * call-seq: [](name)
590
- *
591
- * Return the value returned by method +name+.
592
- */
721
+ * call-seq: [](name)
722
+ *
723
+ * Return the value returned by method +name+.
724
+ */
593
725
  static VALUE cState_aref(VALUE self, VALUE name)
594
726
  {
595
727
  GET_STATE(self);
@@ -600,6 +732,248 @@ static VALUE cState_aref(VALUE self, VALUE name)
600
732
  }
601
733
  }
602
734
 
735
+ static void generate_json_object(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj)
736
+ {
737
+ char *object_nl = state->object_nl;
738
+ long object_nl_len = state->object_nl_len;
739
+ char *indent = state->indent;
740
+ long indent_len = state->indent_len;
741
+ long max_nesting = state->max_nesting;
742
+ char *delim = FBUFFER_PTR(state->object_delim);
743
+ long delim_len = FBUFFER_LEN(state->object_delim);
744
+ char *delim2 = FBUFFER_PTR(state->object_delim2);
745
+ long delim2_len = FBUFFER_LEN(state->object_delim2);
746
+ long depth = ++state->depth;
747
+ int i, j;
748
+ VALUE key, key_to_s, keys;
749
+ if (max_nesting != 0 && depth > max_nesting) {
750
+ fbuffer_free(buffer);
751
+ rb_raise(eNestingError, "nesting of %ld is too deep", --state->depth);
752
+ }
753
+ fbuffer_append_char(buffer, '{');
754
+ keys = rb_funcall(obj, i_keys, 0);
755
+ for(i = 0; i < RARRAY_LEN(keys); i++) {
756
+ if (i > 0) fbuffer_append(buffer, delim, delim_len);
757
+ if (object_nl) {
758
+ fbuffer_append(buffer, object_nl, object_nl_len);
759
+ }
760
+ if (indent) {
761
+ for (j = 0; j < depth; j++) {
762
+ fbuffer_append(buffer, indent, indent_len);
763
+ }
764
+ }
765
+ key = rb_ary_entry(keys, i);
766
+ key_to_s = rb_funcall(key, i_to_s, 0);
767
+ Check_Type(key_to_s, T_STRING);
768
+ generate_json(buffer, Vstate, state, key_to_s);
769
+ fbuffer_append(buffer, delim2, delim2_len);
770
+ generate_json(buffer, Vstate, state, rb_hash_aref(obj, key));
771
+ }
772
+ depth = --state->depth;
773
+ if (object_nl) {
774
+ fbuffer_append(buffer, object_nl, object_nl_len);
775
+ if (indent) {
776
+ for (j = 0; j < depth; j++) {
777
+ fbuffer_append(buffer, indent, indent_len);
778
+ }
779
+ }
780
+ }
781
+ fbuffer_append_char(buffer, '}');
782
+ }
783
+
784
+ static void generate_json_array(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj)
785
+ {
786
+ char *array_nl = state->array_nl;
787
+ long array_nl_len = state->array_nl_len;
788
+ char *indent = state->indent;
789
+ long indent_len = state->indent_len;
790
+ long max_nesting = state->max_nesting;
791
+ char *delim = FBUFFER_PTR(state->array_delim);
792
+ long delim_len = FBUFFER_LEN(state->array_delim);
793
+ long depth = ++state->depth;
794
+ int i, j;
795
+ if (max_nesting != 0 && depth > max_nesting) {
796
+ fbuffer_free(buffer);
797
+ rb_raise(eNestingError, "nesting of %ld is too deep", --state->depth);
798
+ }
799
+ fbuffer_append_char(buffer, '[');
800
+ if (array_nl) fbuffer_append(buffer, array_nl, array_nl_len);
801
+ for(i = 0; i < RARRAY_LEN(obj); i++) {
802
+ if (i > 0) fbuffer_append(buffer, delim, delim_len);
803
+ if (indent) {
804
+ for (j = 0; j < depth; j++) {
805
+ fbuffer_append(buffer, indent, indent_len);
806
+ }
807
+ }
808
+ generate_json(buffer, Vstate, state, rb_ary_entry(obj, i));
809
+ }
810
+ state->depth = --depth;
811
+ if (array_nl) {
812
+ fbuffer_append(buffer, array_nl, array_nl_len);
813
+ if (indent) {
814
+ for (j = 0; j < depth; j++) {
815
+ fbuffer_append(buffer, indent, indent_len);
816
+ }
817
+ }
818
+ }
819
+ fbuffer_append_char(buffer, ']');
820
+ }
821
+
822
+ static void generate_json_string(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj)
823
+ {
824
+ fbuffer_append_char(buffer, '"');
825
+ #ifdef HAVE_RUBY_ENCODING_H
826
+ obj = rb_funcall(obj, i_encode, 1, CEncoding_UTF_8);
827
+ #endif
828
+ if (state->ascii_only) {
829
+ convert_UTF8_to_JSON_ASCII(buffer, obj);
830
+ } else {
831
+ convert_UTF8_to_JSON(buffer, obj);
832
+ }
833
+ fbuffer_append_char(buffer, '"');
834
+ }
835
+
836
+ static void generate_json_null(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj)
837
+ {
838
+ fbuffer_append(buffer, "null", 4);
839
+ }
840
+
841
+ static void generate_json_false(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj)
842
+ {
843
+ fbuffer_append(buffer, "false", 5);
844
+ }
845
+
846
+ static void generate_json_true(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj)
847
+ {
848
+ fbuffer_append(buffer, "true", 4);
849
+ }
850
+
851
+ static void generate_json_fixnum(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj)
852
+ {
853
+ fbuffer_append_long(buffer, FIX2LONG(obj));
854
+ }
855
+
856
+ static void generate_json_bignum(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj)
857
+ {
858
+ VALUE tmp = rb_funcall(obj, i_to_s, 0);
859
+ fbuffer_append(buffer, RSTRING_PAIR(tmp));
860
+ }
861
+
862
+ static void generate_json_float(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj)
863
+ {
864
+ double value = RFLOAT_VALUE(obj);
865
+ char allow_nan = state->allow_nan;
866
+ VALUE tmp = rb_funcall(obj, i_to_s, 0);
867
+ if (!allow_nan) {
868
+ if (isinf(value)) {
869
+ fbuffer_free(buffer);
870
+ rb_raise(eGeneratorError, "%u: %s not allowed in JSON", __LINE__, StringValueCStr(tmp));
871
+ } else if (isnan(value)) {
872
+ fbuffer_free(buffer);
873
+ rb_raise(eGeneratorError, "%u: %s not allowed in JSON", __LINE__, StringValueCStr(tmp));
874
+ }
875
+ }
876
+ fbuffer_append(buffer, RSTRING_PAIR(tmp));
877
+ }
878
+
879
+ static void generate_json(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj)
880
+ {
881
+ VALUE tmp;
882
+ VALUE klass = CLASS_OF(obj);
883
+ if (klass == rb_cHash) {
884
+ generate_json_object(buffer, Vstate, state, obj);
885
+ } else if (klass == rb_cArray) {
886
+ generate_json_array(buffer, Vstate, state, obj);
887
+ } else if (klass == rb_cString) {
888
+ generate_json_string(buffer, Vstate, state, obj);
889
+ } else if (obj == Qnil) {
890
+ generate_json_null(buffer, Vstate, state, obj);
891
+ } else if (obj == Qfalse) {
892
+ generate_json_false(buffer, Vstate, state, obj);
893
+ } else if (obj == Qtrue) {
894
+ generate_json_true(buffer, Vstate, state, obj);
895
+ } else if (klass == rb_cFixnum) {
896
+ generate_json_fixnum(buffer, Vstate, state, obj);
897
+ } else if (klass == rb_cBignum) {
898
+ generate_json_bignum(buffer, Vstate, state, obj);
899
+ } else if (klass == rb_cFloat) {
900
+ generate_json_float(buffer, Vstate, state, obj);
901
+ } else if (rb_respond_to(obj, i_to_json)) {
902
+ tmp = rb_funcall(obj, i_to_json, 1, Vstate);
903
+ Check_Type(tmp, T_STRING);
904
+ fbuffer_append(buffer, RSTRING_PAIR(tmp));
905
+ } else {
906
+ tmp = rb_funcall(obj, i_to_s, 0);
907
+ Check_Type(tmp, T_STRING);
908
+ generate_json(buffer, Vstate, state, tmp);
909
+ }
910
+ }
911
+
912
+ static FBuffer *cState_prepare_buffer(VALUE self)
913
+ {
914
+ FBuffer *buffer = fbuffer_alloc();
915
+ GET_STATE(self);
916
+
917
+ if (state->object_delim) {
918
+ fbuffer_clear(state->object_delim);
919
+ } else {
920
+ state->object_delim = fbuffer_alloc_with_length(16);
921
+ }
922
+ fbuffer_append_char(state->object_delim, ',');
923
+ if (state->object_delim2) {
924
+ fbuffer_clear(state->object_delim2);
925
+ } else {
926
+ state->object_delim2 = fbuffer_alloc_with_length(16);
927
+ }
928
+ fbuffer_append_char(state->object_delim2, ':');
929
+ if (state->space) fbuffer_append(state->object_delim2, state->space, state->space_len);
930
+
931
+ if (state->array_delim) {
932
+ fbuffer_clear(state->array_delim);
933
+ } else {
934
+ state->array_delim = fbuffer_alloc_with_length(16);
935
+ }
936
+ fbuffer_append_char(state->array_delim, ',');
937
+ if (state->array_nl) fbuffer_append(state->array_delim, state->array_nl, state->array_nl_len);
938
+ return buffer;
939
+ }
940
+
941
+ static VALUE fbuffer_to_s(FBuffer *fb)
942
+ {
943
+ VALUE result = rb_str_new(FBUFFER_PAIR(fb));
944
+ fbuffer_free(fb);
945
+ FORCE_UTF8(result);
946
+ return result;
947
+ }
948
+
949
+ static VALUE cState_partial_generate(VALUE self, VALUE obj)
950
+ {
951
+ FBuffer *buffer = cState_prepare_buffer(self);
952
+ GET_STATE(self);
953
+ generate_json(buffer, self, state, obj);
954
+ return fbuffer_to_s(buffer);
955
+ }
956
+
957
+ /*
958
+ * call-seq: generate(obj)
959
+ *
960
+ * Generates a valid JSON document from object +obj+ and returns the
961
+ * result. If no valid JSON document can be created this method raises a
962
+ * GeneratorError exception.
963
+ */
964
+ static VALUE cState_generate(VALUE self, VALUE obj)
965
+ {
966
+ VALUE result = cState_partial_generate(self, obj);
967
+ VALUE re, args[2];
968
+ args[0] = rb_str_new2("\\A\\s*(?:\\[.*\\]|\\{.*\\})\\s*\\Z");
969
+ args[1] = CRegexp_MULTILINE;
970
+ re = rb_class_new_instance(2, args, rb_cRegexp);
971
+ if (NIL_P(rb_funcall(re, i_match, 1, result))) {
972
+ rb_raise(eGeneratorError, "only generation of JSON objects or arrays allowed");
973
+ }
974
+ return result;
975
+ }
976
+
603
977
  /*
604
978
  * call-seq: new(opts = {})
605
979
  *
@@ -612,8 +986,6 @@ static VALUE cState_aref(VALUE self, VALUE name)
612
986
  * * *space_before*: a string that is put before a : pair delimiter (default: ''),
613
987
  * * *object_nl*: a string that is put at the end of a JSON object (default: ''),
614
988
  * * *array_nl*: a string that is put at the end of a JSON array (default: ''),
615
- * * *check_circular*: true if checking for circular data structures
616
- * should be done, false (the default) otherwise.
617
989
  * * *allow_nan*: true if NaN, Infinity, and -Infinity should be
618
990
  * generated, otherwise an exception is thrown, if these values are
619
991
  * encountered. This options defaults to false.
@@ -622,26 +994,38 @@ static VALUE cState_initialize(int argc, VALUE *argv, VALUE self)
622
994
  {
623
995
  VALUE opts;
624
996
  GET_STATE(self);
625
-
997
+ state->max_nesting = 19;
626
998
  rb_scan_args(argc, argv, "01", &opts);
627
- state->indent = rb_str_new2("");
628
- state->space = rb_str_new2("");
629
- state->space_before = rb_str_new2("");
630
- state->array_nl = rb_str_new2("");
631
- state->object_nl = rb_str_new2("");
632
- if (NIL_P(opts)) {
633
- state->check_circular = 1;
634
- state->allow_nan = 0;
635
- state->max_nesting = 19;
636
- } else {
637
- cState_configure(self, opts);
638
- }
639
- state->seen = rb_hash_new();
640
- state->memo = Qnil;
641
- state->depth = INT2FIX(0);
999
+ if (!NIL_P(opts)) cState_configure(self, opts);
642
1000
  return self;
643
1001
  }
644
1002
 
1003
+ /*
1004
+ * call-seq: initialize_copy(orig)
1005
+ *
1006
+ * Initializes this object from orig if it to be duplicated/cloned and returns
1007
+ * it.
1008
+ */
1009
+ static VALUE cState_init_copy(VALUE obj, VALUE orig)
1010
+ {
1011
+ JSON_Generator_State *objState, *origState;
1012
+
1013
+ Data_Get_Struct(obj, JSON_Generator_State, objState);
1014
+ Data_Get_Struct(orig, JSON_Generator_State, origState);
1015
+ if (!objState) rb_raise(rb_eArgError, "unallocated JSON::State");
1016
+
1017
+ MEMCPY(objState, origState, JSON_Generator_State, 1);
1018
+ objState->indent = fstrndup(origState->indent, origState->indent_len);
1019
+ objState->space = fstrndup(origState->space, origState->space_len);
1020
+ objState->space_before = fstrndup(origState->space_before, origState->space_before_len);
1021
+ objState->object_nl = fstrndup(origState->object_nl, origState->object_nl_len);
1022
+ objState->array_nl = fstrndup(origState->array_nl, origState->array_nl_len);
1023
+ if (origState->array_delim) objState->array_delim = fbuffer_dup(origState->array_delim);
1024
+ if (origState->object_delim) objState->object_delim = fbuffer_dup(origState->object_delim);
1025
+ if (origState->object_delim2) objState->object_delim2 = fbuffer_dup(origState->object_delim2);
1026
+ return obj;
1027
+ }
1028
+
645
1029
  /*
646
1030
  * call-seq: from_state(opts)
647
1031
  *
@@ -656,7 +1040,10 @@ static VALUE cState_from_state_s(VALUE self, VALUE opts)
656
1040
  } else if (rb_obj_is_kind_of(opts, rb_cHash)) {
657
1041
  return rb_funcall(self, i_new, 1, opts);
658
1042
  } else {
659
- return rb_funcall(self, i_new, 0);
1043
+ if (NIL_P(CJSON_SAFE_STATE_PROTOTYPE)) {
1044
+ CJSON_SAFE_STATE_PROTOTYPE = rb_const_get(mJSON, i_SAFE_STATE_PROTOTYPE);
1045
+ }
1046
+ return rb_funcall(CJSON_SAFE_STATE_PROTOTYPE, i_dup, 0);
660
1047
  }
661
1048
  }
662
1049
 
@@ -668,7 +1055,7 @@ static VALUE cState_from_state_s(VALUE self, VALUE opts)
668
1055
  static VALUE cState_indent(VALUE self)
669
1056
  {
670
1057
  GET_STATE(self);
671
- return state->indent;
1058
+ return state->indent ? rb_str_new2(state->indent) : rb_str_new2("");
672
1059
  }
673
1060
 
674
1061
  /*
@@ -678,9 +1065,22 @@ static VALUE cState_indent(VALUE self)
678
1065
  */
679
1066
  static VALUE cState_indent_set(VALUE self, VALUE indent)
680
1067
  {
1068
+ int len;
681
1069
  GET_STATE(self);
682
1070
  Check_Type(indent, T_STRING);
683
- return state->indent = indent;
1071
+ len = RSTRING_LEN(indent);
1072
+ if (len == 0) {
1073
+ if (state->indent) {
1074
+ ruby_xfree(state->indent);
1075
+ state->indent = NULL;
1076
+ state->indent_len = 0;
1077
+ }
1078
+ } else {
1079
+ if (state->indent) ruby_xfree(state->indent);
1080
+ state->indent = strdup(RSTRING_PTR(indent));
1081
+ state->indent_len = len;
1082
+ }
1083
+ return Qnil;
684
1084
  }
685
1085
 
686
1086
  /*
@@ -692,7 +1092,7 @@ static VALUE cState_indent_set(VALUE self, VALUE indent)
692
1092
  static VALUE cState_space(VALUE self)
693
1093
  {
694
1094
  GET_STATE(self);
695
- return state->space;
1095
+ return state->space ? rb_str_new2(state->space) : rb_str_new2("");
696
1096
  }
697
1097
 
698
1098
  /*
@@ -703,9 +1103,22 @@ static VALUE cState_space(VALUE self)
703
1103
  */
704
1104
  static VALUE cState_space_set(VALUE self, VALUE space)
705
1105
  {
1106
+ int len;
706
1107
  GET_STATE(self);
707
1108
  Check_Type(space, T_STRING);
708
- return state->space = space;
1109
+ len = RSTRING_LEN(space);
1110
+ if (len == 0) {
1111
+ if (state->space) {
1112
+ ruby_xfree(state->space);
1113
+ state->space = NULL;
1114
+ state->space_len = 0;
1115
+ }
1116
+ } else {
1117
+ if (state->space) ruby_xfree(state->space);
1118
+ state->space = strdup(RSTRING_PTR(space));
1119
+ state->space_len = len;
1120
+ }
1121
+ return Qnil;
709
1122
  }
710
1123
 
711
1124
  /*
@@ -716,7 +1129,7 @@ static VALUE cState_space_set(VALUE self, VALUE space)
716
1129
  static VALUE cState_space_before(VALUE self)
717
1130
  {
718
1131
  GET_STATE(self);
719
- return state->space_before;
1132
+ return state->space_before ? rb_str_new2(state->space_before) : rb_str_new2("");
720
1133
  }
721
1134
 
722
1135
  /*
@@ -726,9 +1139,22 @@ static VALUE cState_space_before(VALUE self)
726
1139
  */
727
1140
  static VALUE cState_space_before_set(VALUE self, VALUE space_before)
728
1141
  {
1142
+ int len;
729
1143
  GET_STATE(self);
730
1144
  Check_Type(space_before, T_STRING);
731
- return state->space_before = space_before;
1145
+ len = RSTRING_LEN(space_before);
1146
+ if (len == 0) {
1147
+ if (state->space_before) {
1148
+ ruby_xfree(state->space_before);
1149
+ state->space_before = NULL;
1150
+ state->space_before_len = 0;
1151
+ }
1152
+ } else {
1153
+ if (state->space_before) ruby_xfree(state->space_before);
1154
+ state->space_before = strdup(RSTRING_PTR(space_before));
1155
+ state->space_before_len = len;
1156
+ }
1157
+ return Qnil;
732
1158
  }
733
1159
 
734
1160
  /*
@@ -740,7 +1166,7 @@ static VALUE cState_space_before_set(VALUE self, VALUE space_before)
740
1166
  static VALUE cState_object_nl(VALUE self)
741
1167
  {
742
1168
  GET_STATE(self);
743
- return state->object_nl;
1169
+ return state->object_nl ? rb_str_new2(state->object_nl) : rb_str_new2("");
744
1170
  }
745
1171
 
746
1172
  /*
@@ -751,9 +1177,21 @@ static VALUE cState_object_nl(VALUE self)
751
1177
  */
752
1178
  static VALUE cState_object_nl_set(VALUE self, VALUE object_nl)
753
1179
  {
1180
+ int len;
754
1181
  GET_STATE(self);
755
1182
  Check_Type(object_nl, T_STRING);
756
- return state->object_nl = object_nl;
1183
+ len = RSTRING_LEN(object_nl);
1184
+ if (len == 0) {
1185
+ if (state->object_nl) {
1186
+ ruby_xfree(state->object_nl);
1187
+ state->object_nl = NULL;
1188
+ }
1189
+ } else {
1190
+ if (state->object_nl) ruby_xfree(state->object_nl);
1191
+ state->object_nl = strdup(RSTRING_PTR(object_nl));
1192
+ state->object_nl_len = len;
1193
+ }
1194
+ return Qnil;
757
1195
  }
758
1196
 
759
1197
  /*
@@ -764,7 +1202,7 @@ static VALUE cState_object_nl_set(VALUE self, VALUE object_nl)
764
1202
  static VALUE cState_array_nl(VALUE self)
765
1203
  {
766
1204
  GET_STATE(self);
767
- return state->array_nl;
1205
+ return state->array_nl ? rb_str_new2(state->array_nl) : rb_str_new2("");
768
1206
  }
769
1207
 
770
1208
  /*
@@ -774,21 +1212,34 @@ static VALUE cState_array_nl(VALUE self)
774
1212
  */
775
1213
  static VALUE cState_array_nl_set(VALUE self, VALUE array_nl)
776
1214
  {
1215
+ int len;
777
1216
  GET_STATE(self);
778
1217
  Check_Type(array_nl, T_STRING);
779
- return state->array_nl = array_nl;
1218
+ len = RSTRING_LEN(array_nl);
1219
+ if (len == 0) {
1220
+ if (state->array_nl) {
1221
+ ruby_xfree(state->array_nl);
1222
+ state->array_nl = NULL;
1223
+ }
1224
+ } else {
1225
+ if (state->array_nl) ruby_xfree(state->array_nl);
1226
+ state->array_nl = strdup(RSTRING_PTR(array_nl));
1227
+ state->array_nl_len = len;
1228
+ }
1229
+ return Qnil;
780
1230
  }
781
1231
 
1232
+
782
1233
  /*
783
- * call-seq: check_circular?
784
- *
785
- * Returns true, if circular data structures should be checked,
786
- * otherwise returns false.
787
- */
1234
+ * call-seq: check_circular?
1235
+ *
1236
+ * Returns true, if circular data structures should be checked,
1237
+ * otherwise returns false.
1238
+ */
788
1239
  static VALUE cState_check_circular_p(VALUE self)
789
1240
  {
790
1241
  GET_STATE(self);
791
- return state->check_circular ? Qtrue : Qfalse;
1242
+ return state->max_nesting ? Qtrue : Qfalse;
792
1243
  }
793
1244
 
794
1245
  /*
@@ -813,8 +1264,7 @@ static VALUE cState_max_nesting_set(VALUE self, VALUE depth)
813
1264
  {
814
1265
  GET_STATE(self);
815
1266
  Check_Type(depth, T_FIXNUM);
816
- state->max_nesting = FIX2LONG(depth);
817
- return Qnil;
1267
+ return state->max_nesting = FIX2LONG(depth);
818
1268
  }
819
1269
 
820
1270
  /*
@@ -830,37 +1280,39 @@ static VALUE cState_allow_nan_p(VALUE self)
830
1280
  }
831
1281
 
832
1282
  /*
833
- * call-seq: seen?(object)
1283
+ * call-seq: ascii_only?
834
1284
  *
835
- * Returns _true_, if _object_ was already seen during this generating run.
1285
+ * Returns true, if NaN, Infinity, and -Infinity should be generated, otherwise
1286
+ * returns false.
836
1287
  */
837
- static VALUE cState_seen_p(VALUE self, VALUE object)
1288
+ static VALUE cState_ascii_only_p(VALUE self)
838
1289
  {
839
1290
  GET_STATE(self);
840
- return rb_hash_aref(state->seen, rb_obj_id(object));
1291
+ return state->ascii_only ? Qtrue : Qfalse;
841
1292
  }
842
1293
 
843
1294
  /*
844
- * call-seq: remember(object)
1295
+ * call-seq: depth
845
1296
  *
846
- * Remember _object_, to find out if it was already encountered (if a cyclic
847
- * data structure is rendered).
1297
+ * This integer returns the current depth of data structure nesting.
848
1298
  */
849
- static VALUE cState_remember(VALUE self, VALUE object)
1299
+ static VALUE cState_depth(VALUE self)
850
1300
  {
851
1301
  GET_STATE(self);
852
- return rb_hash_aset(state->seen, rb_obj_id(object), Qtrue);
1302
+ return LONG2FIX(state->depth);
853
1303
  }
854
1304
 
855
1305
  /*
856
- * call-seq: forget(object)
1306
+ * call-seq: depth=(depth)
857
1307
  *
858
- * Forget _object_ for this generating run.
1308
+ * This sets the maximum level of data structure nesting in the generated JSON
1309
+ * to the integer depth, max_nesting = 0 if no maximum should be checked.
859
1310
  */
860
- static VALUE cState_forget(VALUE self, VALUE object)
1311
+ static VALUE cState_depth_set(VALUE self, VALUE depth)
861
1312
  {
862
1313
  GET_STATE(self);
863
- return rb_hash_delete(state->seen, rb_obj_id(object));
1314
+ Check_Type(depth, T_FIXNUM);
1315
+ return state->depth = FIX2LONG(depth);
864
1316
  }
865
1317
 
866
1318
  /*
@@ -869,17 +1321,19 @@ static VALUE cState_forget(VALUE self, VALUE object)
869
1321
  void Init_generator()
870
1322
  {
871
1323
  rb_require("json/common");
1324
+
872
1325
  mJSON = rb_define_module("JSON");
873
1326
  mExt = rb_define_module_under(mJSON, "Ext");
874
1327
  mGenerator = rb_define_module_under(mExt, "Generator");
1328
+
875
1329
  eGeneratorError = rb_path2class("JSON::GeneratorError");
876
- eCircularDatastructure = rb_path2class("JSON::CircularDatastructure");
877
1330
  eNestingError = rb_path2class("JSON::NestingError");
1331
+
878
1332
  cState = rb_define_class_under(mGenerator, "State", rb_cObject);
879
1333
  rb_define_alloc_func(cState, cState_s_allocate);
880
1334
  rb_define_singleton_method(cState, "from_state", cState_from_state_s, 1);
881
1335
  rb_define_method(cState, "initialize", cState_initialize, -1);
882
-
1336
+ rb_define_method(cState, "initialize_copy", cState_init_copy, 1);
883
1337
  rb_define_method(cState, "indent", cState_indent, 0);
884
1338
  rb_define_method(cState, "indent=", cState_indent_set, 1);
885
1339
  rb_define_method(cState, "space", cState_space, 0);
@@ -890,16 +1344,17 @@ void Init_generator()
890
1344
  rb_define_method(cState, "object_nl=", cState_object_nl_set, 1);
891
1345
  rb_define_method(cState, "array_nl", cState_array_nl, 0);
892
1346
  rb_define_method(cState, "array_nl=", cState_array_nl_set, 1);
893
- rb_define_method(cState, "check_circular?", cState_check_circular_p, 0);
894
1347
  rb_define_method(cState, "max_nesting", cState_max_nesting, 0);
895
1348
  rb_define_method(cState, "max_nesting=", cState_max_nesting_set, 1);
1349
+ rb_define_method(cState, "check_circular?", cState_check_circular_p, 0);
896
1350
  rb_define_method(cState, "allow_nan?", cState_allow_nan_p, 0);
897
- rb_define_method(cState, "seen?", cState_seen_p, 1);
898
- rb_define_method(cState, "remember", cState_remember, 1);
899
- rb_define_method(cState, "forget", cState_forget, 1);
1351
+ rb_define_method(cState, "ascii_only?", cState_ascii_only_p, 0);
1352
+ rb_define_method(cState, "depth", cState_depth, 0);
1353
+ rb_define_method(cState, "depth=", cState_depth_set, 1);
900
1354
  rb_define_method(cState, "configure", cState_configure, 1);
901
1355
  rb_define_method(cState, "to_h", cState_to_h, 0);
902
1356
  rb_define_method(cState, "[]", cState_aref, 1);
1357
+ rb_define_method(cState, "generate", cState_generate, 1);
903
1358
 
904
1359
  mGeneratorMethods = rb_define_module_under(mGenerator, "GeneratorMethods");
905
1360
  mObject = rb_define_module_under(mGeneratorMethods, "Object");
@@ -908,8 +1363,10 @@ void Init_generator()
908
1363
  rb_define_method(mHash, "to_json", mHash_to_json, -1);
909
1364
  mArray = rb_define_module_under(mGeneratorMethods, "Array");
910
1365
  rb_define_method(mArray, "to_json", mArray_to_json, -1);
911
- mInteger = rb_define_module_under(mGeneratorMethods, "Integer");
912
- rb_define_method(mInteger, "to_json", mInteger_to_json, -1);
1366
+ mFixnum = rb_define_module_under(mGeneratorMethods, "Fixnum");
1367
+ rb_define_method(mFixnum, "to_json", mFixnum_to_json, -1);
1368
+ mBignum = rb_define_module_under(mGeneratorMethods, "Bignum");
1369
+ rb_define_method(mBignum, "to_json", mBignum_to_json, -1);
913
1370
  mFloat = rb_define_module_under(mGeneratorMethods, "Float");
914
1371
  rb_define_method(mFloat, "to_json", mFloat_to_json, -1);
915
1372
  mString = rb_define_module_under(mGeneratorMethods, "String");
@@ -926,6 +1383,7 @@ void Init_generator()
926
1383
  mNilClass = rb_define_module_under(mGeneratorMethods, "NilClass");
927
1384
  rb_define_method(mNilClass, "to_json", mNilClass_to_json, -1);
928
1385
 
1386
+ CRegexp_MULTILINE = rb_const_get(rb_cRegexp, rb_intern("MULTILINE"));
929
1387
  i_to_s = rb_intern("to_s");
930
1388
  i_to_json = rb_intern("to_json");
931
1389
  i_new = rb_intern("new");
@@ -934,9 +1392,10 @@ void Init_generator()
934
1392
  i_space_before = rb_intern("space_before");
935
1393
  i_object_nl = rb_intern("object_nl");
936
1394
  i_array_nl = rb_intern("array_nl");
937
- i_check_circular = rb_intern("check_circular");
938
1395
  i_max_nesting = rb_intern("max_nesting");
939
1396
  i_allow_nan = rb_intern("allow_nan");
1397
+ i_ascii_only = rb_intern("ascii_only");
1398
+ i_depth = rb_intern("depth");
940
1399
  i_pack = rb_intern("pack");
941
1400
  i_unpack = rb_intern("unpack");
942
1401
  i_create_id = rb_intern("create_id");
@@ -945,9 +1404,14 @@ void Init_generator()
945
1404
  i_aref = rb_intern("[]");
946
1405
  i_send = rb_intern("__send__");
947
1406
  i_respond_to_p = rb_intern("respond_to?");
1407
+ i_match = rb_intern("match");
1408
+ i_keys = rb_intern("keys");
1409
+ i_dup = rb_intern("dup");
948
1410
  #ifdef HAVE_RUBY_ENCODING_H
949
- mEncoding_UTF_8 = rb_funcall(rb_path2class("Encoding"), rb_intern("find"), 1, rb_str_new2("utf-8"));
1411
+ CEncoding_UTF_8 = rb_funcall(rb_path2class("Encoding"), rb_intern("find"), 1, rb_str_new2("utf-8"));
950
1412
  i_encoding = rb_intern("encoding");
951
1413
  i_encode = rb_intern("encode");
952
1414
  #endif
1415
+ i_SAFE_STATE_PROTOTYPE = rb_intern("SAFE_STATE_PROTOTYPE");
1416
+ CJSON_SAFE_STATE_PROTOTYPE = Qnil;
953
1417
  }