json 2.7.2 → 2.9.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,340 +1,387 @@
1
+ #include "ruby.h"
1
2
  #include "../fbuffer/fbuffer.h"
2
- #include "generator.h"
3
3
 
4
- static VALUE mJSON, mExt, mGenerator, cState, mGeneratorMethods, mObject,
5
- mHash, mArray,
6
- #ifdef RUBY_INTEGER_UNIFICATION
7
- mInteger,
8
- #else
9
- mFixnum, mBignum,
4
+ #include <math.h>
5
+ #include <ctype.h>
6
+
7
+ /* ruby api and some helpers */
8
+
9
+ typedef struct JSON_Generator_StateStruct {
10
+ VALUE indent;
11
+ VALUE space;
12
+ VALUE space_before;
13
+ VALUE object_nl;
14
+ VALUE array_nl;
15
+
16
+ long max_nesting;
17
+ long depth;
18
+ long buffer_initial_length;
19
+
20
+ bool allow_nan;
21
+ bool ascii_only;
22
+ bool script_safe;
23
+ bool strict;
24
+ } JSON_Generator_State;
25
+
26
+ #ifndef RB_UNLIKELY
27
+ #define RB_UNLIKELY(cond) (cond)
10
28
  #endif
11
- mFloat, mString, mString_Extend,
12
- mTrueClass, mFalseClass, mNilClass, eGeneratorError,
13
- eNestingError;
14
29
 
15
- static ID i_to_s, i_to_json, i_new, i_indent, i_space, i_space_before,
16
- i_object_nl, i_array_nl, i_max_nesting, i_allow_nan, i_ascii_only,
17
- i_pack, i_unpack, i_create_id, i_extend, i_key_p,
18
- i_aref, i_send, i_respond_to_p, i_match, i_keys, i_depth,
19
- i_buffer_initial_length, i_dup, i_script_safe, i_escape_slash, i_strict;
30
+ static VALUE mJSON, cState, mString_Extend, eGeneratorError, eNestingError, Encoding_UTF_8;
20
31
 
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
- */
32
+ static ID i_to_s, i_to_json, i_new, i_pack, i_unpack, i_create_id, i_extend, i_encode;
33
+ static ID sym_indent, sym_space, sym_space_before, sym_object_nl, sym_array_nl, sym_max_nesting, sym_allow_nan,
34
+ sym_ascii_only, sym_depth, sym_buffer_initial_length, sym_script_safe, sym_escape_slash, sym_strict;
42
35
 
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
36
 
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 };
37
+ #define GET_STATE_TO(self, state) \
38
+ TypedData_Get_Struct(self, JSON_Generator_State, &JSON_Generator_State_type, state)
68
39
 
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
- }
40
+ #define GET_STATE(self) \
41
+ JSON_Generator_State *state; \
42
+ GET_STATE_TO(self, state)
98
43
 
99
- case 1: if (*source >= 0x80 && *source < 0xC2) return 0;
100
- }
101
- if (*source > 0xF4) return 0;
102
- return 1;
103
- }
44
+ struct generate_json_data;
104
45
 
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";
46
+ typedef void (*generator_func)(FBuffer *buffer, struct generate_json_data *data, JSON_Generator_State *state, VALUE obj);
47
+
48
+ struct generate_json_data {
49
+ FBuffer *buffer;
50
+ VALUE vstate;
51
+ JSON_Generator_State *state;
52
+ VALUE obj;
53
+ generator_func func;
54
+ };
55
+
56
+ static VALUE cState_from_state_s(VALUE self, VALUE opts);
57
+ static VALUE cState_partial_generate(VALUE self, VALUE obj, generator_func, VALUE io);
58
+ static void generate_json(FBuffer *buffer, struct generate_json_data *data, JSON_Generator_State *state, VALUE obj);
59
+ static void generate_json_object(FBuffer *buffer, struct generate_json_data *data, JSON_Generator_State *state, VALUE obj);
60
+ static void generate_json_array(FBuffer *buffer, struct generate_json_data *data, JSON_Generator_State *state, VALUE obj);
61
+ static void generate_json_string(FBuffer *buffer, struct generate_json_data *data, JSON_Generator_State *state, VALUE obj);
62
+ static void generate_json_null(FBuffer *buffer, struct generate_json_data *data, JSON_Generator_State *state, VALUE obj);
63
+ static void generate_json_false(FBuffer *buffer, struct generate_json_data *data, JSON_Generator_State *state, VALUE obj);
64
+ static void generate_json_true(FBuffer *buffer, struct generate_json_data *data, JSON_Generator_State *state, VALUE obj);
65
+ #ifdef RUBY_INTEGER_UNIFICATION
66
+ static void generate_json_integer(FBuffer *buffer, struct generate_json_data *data, JSON_Generator_State *state, VALUE obj);
67
+ #endif
68
+ static void generate_json_fixnum(FBuffer *buffer, struct generate_json_data *data, JSON_Generator_State *state, VALUE obj);
69
+ static void generate_json_bignum(FBuffer *buffer, struct generate_json_data *data, JSON_Generator_State *state, VALUE obj);
70
+ static void generate_json_float(FBuffer *buffer, struct generate_json_data *data, JSON_Generator_State *state, VALUE obj);
109
71
 
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];
72
+ static int usascii_encindex, utf8_encindex, binary_encindex;
73
+
74
+ #ifdef RBIMPL_ATTR_NORETURN
75
+ RBIMPL_ATTR_NORETURN()
76
+ #endif
77
+ static void raise_generator_error_str(VALUE invalid_object, VALUE str)
78
+ {
79
+ VALUE exc = rb_exc_new_str(eGeneratorError, str);
80
+ rb_ivar_set(exc, rb_intern("@invalid_object"), invalid_object);
81
+ rb_exc_raise(exc);
114
82
  }
115
83
 
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)
84
+ #ifdef RBIMPL_ATTR_NORETURN
85
+ RBIMPL_ATTR_NORETURN()
86
+ #endif
87
+ #ifdef RBIMPL_ATTR_FORMAT
88
+ RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT, 2, 3)
89
+ #endif
90
+ static void raise_generator_error(VALUE invalid_object, const char *fmt, ...)
120
91
  {
121
- unicode_escape(buf, character);
122
- fbuffer_append(buffer, buf, 6);
92
+ va_list args;
93
+ va_start(args, fmt);
94
+ VALUE str = rb_vsprintf(fmt, args);
95
+ va_end(args);
96
+ raise_generator_error_str(invalid_object, str);
123
97
  }
124
98
 
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, char script_safe)
99
+ /* Converts in_string to a JSON string (without the wrapping '"'
100
+ * characters) in FBuffer out_buffer.
101
+ *
102
+ * Character are JSON-escaped according to:
103
+ *
104
+ * - Always: ASCII control characters (0x00-0x1F), dquote, and
105
+ * backslash.
106
+ *
107
+ * - If out_ascii_only: non-ASCII characters (>0x7F)
108
+ *
109
+ * - If out_script_safe: forwardslash, line separator (U+2028), and
110
+ * paragraph separator (U+2029)
111
+ *
112
+ * Everything else (should be UTF-8) is just passed through and
113
+ * appended to the result.
114
+ */
115
+ static void convert_UTF8_to_JSON(FBuffer *out_buffer, VALUE str, const char escape_table[256], bool out_script_safe)
128
116
  {
129
- const UTF8 *source = (UTF8 *) RSTRING_PTR(string);
130
- const UTF8 *sourceEnd = source + RSTRING_LEN(string);
131
- char buf[6] = { '\\', 'u' };
117
+ const char *hexdig = "0123456789abcdef";
118
+ char scratch[12] = { '\\', 'u', 0, 0, 0, 0, '\\', 'u' };
132
119
 
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
165
- unicode_escape_to_buffer(buffer, buf, UNI_REPLACEMENT_CHAR);
166
- #endif
167
- } else {
168
- /* normal case */
169
- if (ch >= 0x20 && ch <= 0x7f) {
120
+ const char *ptr = RSTRING_PTR(str);
121
+ unsigned long len = RSTRING_LEN(str);
122
+
123
+ unsigned long beg = 0, pos = 0;
124
+
125
+ #define FLUSH_POS(bytes) if (pos > beg) { fbuffer_append(out_buffer, &ptr[beg], pos - beg); } pos += bytes; beg = pos;
126
+
127
+ while (pos < len) {
128
+ unsigned char ch = ptr[pos];
129
+ unsigned char ch_len = escape_table[ch];
130
+ /* JSON encoding */
131
+
132
+ if (RB_UNLIKELY(ch_len)) {
133
+ switch (ch_len) {
134
+ case 1: {
135
+ FLUSH_POS(1);
170
136
  switch (ch) {
171
- case '\\':
172
- fbuffer_append(buffer, "\\\\", 2);
173
- break;
174
- case '"':
175
- fbuffer_append(buffer, "\\\"", 2);
176
- break;
177
- case '/':
178
- if(script_safe) {
179
- fbuffer_append(buffer, "\\/", 2);
180
- break;
181
- }
182
- default:
183
- fbuffer_append_char(buffer, (char)ch);
137
+ case '"': fbuffer_append(out_buffer, "\\\"", 2); break;
138
+ case '\\': fbuffer_append(out_buffer, "\\\\", 2); break;
139
+ case '/': fbuffer_append(out_buffer, "\\/", 2); break;
140
+ case '\b': fbuffer_append(out_buffer, "\\b", 2); break;
141
+ case '\f': fbuffer_append(out_buffer, "\\f", 2); break;
142
+ case '\n': fbuffer_append(out_buffer, "\\n", 2); break;
143
+ case '\r': fbuffer_append(out_buffer, "\\r", 2); break;
144
+ case '\t': fbuffer_append(out_buffer, "\\t", 2); break;
145
+ default: {
146
+ scratch[2] = '0';
147
+ scratch[3] = '0';
148
+ scratch[4] = hexdig[(ch >> 4) & 0xf];
149
+ scratch[5] = hexdig[ch & 0xf];
150
+ fbuffer_append(out_buffer, scratch, 6);
184
151
  break;
152
+ }
185
153
  }
186
- } else {
187
- switch (ch) {
188
- case '\n':
189
- fbuffer_append(buffer, "\\n", 2);
190
- break;
191
- case '\r':
192
- fbuffer_append(buffer, "\\r", 2);
193
- break;
194
- case '\t':
195
- fbuffer_append(buffer, "\\t", 2);
196
- break;
197
- case '\f':
198
- fbuffer_append(buffer, "\\f", 2);
199
- break;
200
- case '\b':
201
- fbuffer_append(buffer, "\\b", 2);
154
+ break;
155
+ }
156
+ case 3: {
157
+ unsigned char b2 = ptr[pos + 1];
158
+ if (RB_UNLIKELY(out_script_safe && ch == 0xE2 && b2 == 0x80)) {
159
+ unsigned char b3 = ptr[pos + 2];
160
+ if (b3 == 0xA8) {
161
+ FLUSH_POS(3);
162
+ fbuffer_append(out_buffer, "\\u2028", 6);
202
163
  break;
203
- default:
204
- unicode_escape_to_buffer(buffer, buf, (UTF16) ch);
164
+ } else if (b3 == 0xA9) {
165
+ FLUSH_POS(3);
166
+ fbuffer_append(out_buffer, "\\u2029", 6);
205
167
  break;
168
+ }
206
169
  }
170
+ // fallthrough
207
171
  }
172
+ default:
173
+ pos += ch_len;
174
+ break;
208
175
  }
209
- } else if (ch > UNI_MAX_UTF16) {
210
- #if UNI_STRICT_CONVERSION
211
- source -= (extraBytesToRead+1); /* return to the start */
212
- rb_raise(rb_path2class("JSON::GeneratorError"),
213
- "source sequence is illegal/malformed utf8");
214
- #else
215
- unicode_escape_to_buffer(buffer, buf, UNI_REPLACEMENT_CHAR);
216
- #endif
217
176
  } else {
218
- /* target is a character in range 0xFFFF - 0x10FFFF. */
219
- ch -= halfBase;
220
- unicode_escape_to_buffer(buffer, buf, (UTF16)((ch >> halfShift) + UNI_SUR_HIGH_START));
221
- unicode_escape_to_buffer(buffer, buf, (UTF16)((ch & halfMask) + UNI_SUR_LOW_START));
177
+ pos++;
222
178
  }
223
179
  }
224
- RB_GC_GUARD(string);
225
- }
226
-
227
- /* Converts string to a JSON string in FBuffer buffer, where only the
228
- * characters required by the JSON standard are JSON escaped. The remaining
229
- * characters (should be UTF8) are just passed through and appended to the
230
- * result. */
231
- static void convert_UTF8_to_JSON(FBuffer *buffer, VALUE string, char script_safe)
232
- {
233
- const char *ptr = RSTRING_PTR(string), *p;
234
- unsigned long len = RSTRING_LEN(string), start = 0, end = 0;
235
- const char *escape = NULL;
236
- int escape_len;
237
- unsigned char c;
238
- char buf[6] = { '\\', 'u' };
239
- int ascii_only = rb_enc_str_asciionly_p(string);
240
-
241
- for (start = 0, end = 0; end < len;) {
242
- p = ptr + end;
243
- c = (unsigned char) *p;
244
- if (c < 0x20) {
245
- switch (c) {
246
- case '\n':
247
- escape = "\\n";
248
- escape_len = 2;
249
- break;
250
- case '\r':
251
- escape = "\\r";
252
- escape_len = 2;
253
- break;
254
- case '\t':
255
- escape = "\\t";
256
- escape_len = 2;
257
- break;
258
- case '\f':
259
- escape = "\\f";
260
- escape_len = 2;
261
- break;
262
- case '\b':
263
- escape = "\\b";
264
- escape_len = 2;
265
- break;
180
+ #undef FLUSH_POS
181
+
182
+ if (beg < len) {
183
+ fbuffer_append(out_buffer, &ptr[beg], len - beg);
184
+ }
185
+
186
+ RB_GC_GUARD(str);
187
+ }
188
+
189
+ static const char escape_table[256] = {
190
+ // ASCII Control Characters
191
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
192
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
193
+ // ASCII Characters
194
+ 0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0, // '"'
195
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
196
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
197
+ 0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0, // '\\'
198
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
199
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
200
+ // Continuation byte
201
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
202
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
203
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
204
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
205
+ // First byte of a 2-byte code point
206
+ 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
207
+ 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
208
+ // First byte of a 4-byte code point
209
+ 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
210
+ //First byte of a 4+byte code point
211
+ 4,4,4,4,4,4,4,4,5,5,5,5,6,6,1,1,
212
+ };
213
+
214
+ static const char script_safe_escape_table[256] = {
215
+ // ASCII Control Characters
216
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
217
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
218
+ // ASCII Characters
219
+ 0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,1, // '"' and '/'
220
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
221
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
222
+ 0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0, // '\\'
223
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
224
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
225
+ // Continuation byte
226
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
227
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
228
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
229
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
230
+ // First byte of a 2-byte code point
231
+ 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
232
+ 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
233
+ // First byte of a 4-byte code point
234
+ 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
235
+ //First byte of a 4+byte code point
236
+ 4,4,4,4,4,4,4,4,5,5,5,5,6,6,1,1,
237
+ };
238
+
239
+ static void convert_ASCII_to_JSON(FBuffer *out_buffer, VALUE str, const char escape_table[256])
240
+ {
241
+ const char *hexdig = "0123456789abcdef";
242
+ char scratch[12] = { '\\', 'u', 0, 0, 0, 0, '\\', 'u' };
243
+
244
+ const char *ptr = RSTRING_PTR(str);
245
+ unsigned long len = RSTRING_LEN(str);
246
+
247
+ unsigned long beg = 0, pos;
248
+
249
+ for (pos = 0; pos < len;) {
250
+ unsigned char ch = ptr[pos];
251
+ /* JSON encoding */
252
+ if (escape_table[ch]) {
253
+ if (pos > beg) {
254
+ fbuffer_append(out_buffer, &ptr[beg], pos - beg);
255
+ }
256
+
257
+ beg = pos + 1;
258
+ switch (ch) {
259
+ case '"': fbuffer_append(out_buffer, "\\\"", 2); break;
260
+ case '\\': fbuffer_append(out_buffer, "\\\\", 2); break;
261
+ case '/': fbuffer_append(out_buffer, "\\/", 2); break;
262
+ case '\b': fbuffer_append(out_buffer, "\\b", 2); break;
263
+ case '\f': fbuffer_append(out_buffer, "\\f", 2); break;
264
+ case '\n': fbuffer_append(out_buffer, "\\n", 2); break;
265
+ case '\r': fbuffer_append(out_buffer, "\\r", 2); break;
266
+ case '\t': fbuffer_append(out_buffer, "\\t", 2); break;
266
267
  default:
267
- unicode_escape(buf, (UTF16) *p);
268
- escape = buf;
269
- escape_len = 6;
270
- break;
268
+ scratch[2] = '0';
269
+ scratch[3] = '0';
270
+ scratch[4] = hexdig[(ch >> 4) & 0xf];
271
+ scratch[5] = hexdig[ch & 0xf];
272
+ fbuffer_append(out_buffer, scratch, 6);
271
273
  }
272
- } else {
273
- switch (c) {
274
- case '\\':
275
- escape = "\\\\";
276
- escape_len = 2;
277
- break;
278
- case '"':
279
- escape = "\\\"";
280
- escape_len = 2;
274
+ }
275
+
276
+ pos++;
277
+ }
278
+
279
+ if (beg < len) {
280
+ fbuffer_append(out_buffer, &ptr[beg], len - beg);
281
+ }
282
+
283
+ RB_GC_GUARD(str);
284
+ }
285
+
286
+ static void convert_UTF8_to_ASCII_only_JSON(FBuffer *out_buffer, VALUE str, const char escape_table[256], bool out_script_safe)
287
+ {
288
+ const char *hexdig = "0123456789abcdef";
289
+ char scratch[12] = { '\\', 'u', 0, 0, 0, 0, '\\', 'u' };
290
+
291
+ const char *ptr = RSTRING_PTR(str);
292
+ unsigned long len = RSTRING_LEN(str);
293
+
294
+ unsigned long beg = 0, pos = 0;
295
+
296
+ #define FLUSH_POS(bytes) if (pos > beg) { fbuffer_append(out_buffer, &ptr[beg], pos - beg); } pos += bytes; beg = pos;
297
+
298
+ while (pos < len) {
299
+ unsigned char ch = ptr[pos];
300
+ unsigned char ch_len = escape_table[ch];
301
+
302
+ if (RB_UNLIKELY(ch_len)) {
303
+ switch (ch_len) {
304
+ case 1: {
305
+ FLUSH_POS(1);
306
+ switch (ch) {
307
+ case '"': fbuffer_append(out_buffer, "\\\"", 2); break;
308
+ case '\\': fbuffer_append(out_buffer, "\\\\", 2); break;
309
+ case '/': fbuffer_append(out_buffer, "\\/", 2); break;
310
+ case '\b': fbuffer_append(out_buffer, "\\b", 2); break;
311
+ case '\f': fbuffer_append(out_buffer, "\\f", 2); break;
312
+ case '\n': fbuffer_append(out_buffer, "\\n", 2); break;
313
+ case '\r': fbuffer_append(out_buffer, "\\r", 2); break;
314
+ case '\t': fbuffer_append(out_buffer, "\\t", 2); break;
315
+ default: {
316
+ scratch[2] = '0';
317
+ scratch[3] = '0';
318
+ scratch[4] = hexdig[(ch >> 4) & 0xf];
319
+ scratch[5] = hexdig[ch & 0xf];
320
+ fbuffer_append(out_buffer, scratch, 6);
321
+ break;
322
+ }
323
+ }
281
324
  break;
282
- case '/':
283
- if(script_safe) {
284
- escape = "\\/";
285
- escape_len = 2;
286
- break;
325
+ }
326
+ default: {
327
+ uint32_t wchar = 0;
328
+ switch(ch_len) {
329
+ case 2:
330
+ wchar = ptr[pos] & 0x1F;
331
+ break;
332
+ case 3:
333
+ wchar = ptr[pos] & 0x0F;
334
+ break;
335
+ case 4:
336
+ wchar = ptr[pos] & 0x07;
337
+ break;
287
338
  }
288
- default:
289
- {
290
- unsigned short clen = 1;
291
- if (!ascii_only) {
292
- clen += trailingBytesForUTF8[c];
293
- if (end + clen > len) {
294
- rb_raise(rb_path2class("JSON::GeneratorError"),
295
- "partial character in source, but hit end");
296
- }
297
-
298
- if (script_safe && c == 0xE2) {
299
- unsigned char c2 = (unsigned char) *(p+1);
300
- unsigned char c3 = (unsigned char) *(p+2);
301
- if (c2 == 0x80 && (c3 == 0xA8 || c3 == 0xA9)) {
302
- fbuffer_append(buffer, ptr + start, end - start);
303
- start = end = (end + clen);
304
- if (c3 == 0xA8) {
305
- fbuffer_append(buffer, "\\u2028", 6);
306
- } else {
307
- fbuffer_append(buffer, "\\u2029", 6);
308
- }
309
- continue;
310
- }
311
- }
312
-
313
- if (!isLegalUTF8((UTF8 *) p, clen)) {
314
- rb_raise(rb_path2class("JSON::GeneratorError"),
315
- "source sequence is illegal/malformed utf-8");
316
- }
317
- }
318
- end += clen;
339
+
340
+ for (short i = 1; i < ch_len; i++) {
341
+ wchar = (wchar << 6) | (ptr[pos+i] & 0x3F);
319
342
  }
320
- continue;
343
+
344
+ FLUSH_POS(ch_len);
345
+
346
+ if (wchar <= 0xFFFF) {
347
+ scratch[2] = hexdig[wchar >> 12];
348
+ scratch[3] = hexdig[(wchar >> 8) & 0xf];
349
+ scratch[4] = hexdig[(wchar >> 4) & 0xf];
350
+ scratch[5] = hexdig[wchar & 0xf];
351
+ fbuffer_append(out_buffer, scratch, 6);
352
+ } else {
353
+ uint16_t hi, lo;
354
+ wchar -= 0x10000;
355
+ hi = 0xD800 + (uint16_t)(wchar >> 10);
356
+ lo = 0xDC00 + (uint16_t)(wchar & 0x3FF);
357
+
358
+ scratch[2] = hexdig[hi >> 12];
359
+ scratch[3] = hexdig[(hi >> 8) & 0xf];
360
+ scratch[4] = hexdig[(hi >> 4) & 0xf];
361
+ scratch[5] = hexdig[hi & 0xf];
362
+
363
+ scratch[8] = hexdig[lo >> 12];
364
+ scratch[9] = hexdig[(lo >> 8) & 0xf];
365
+ scratch[10] = hexdig[(lo >> 4) & 0xf];
366
+ scratch[11] = hexdig[lo & 0xf];
367
+
368
+ fbuffer_append(out_buffer, scratch, 12);
369
+ }
370
+
321
371
  break;
372
+ }
322
373
  }
374
+ } else {
375
+ pos++;
323
376
  }
324
- fbuffer_append(buffer, ptr + start, end - start);
325
- fbuffer_append(buffer, escape, escape_len);
326
- start = ++end;
327
- escape = NULL;
328
377
  }
329
- fbuffer_append(buffer, ptr + start, end - start);
330
- }
378
+ #undef FLUSH_POS
331
379
 
332
- static char *fstrndup(const char *ptr, unsigned long len) {
333
- char *result;
334
- if (len <= 0) return NULL;
335
- result = ALLOC_N(char, len);
336
- memcpy(result, ptr, len);
337
- return result;
380
+ if (beg < len) {
381
+ fbuffer_append(out_buffer, &ptr[beg], len - beg);
382
+ }
383
+
384
+ RB_GC_GUARD(str);
338
385
  }
339
386
 
340
387
  /*
@@ -429,7 +476,9 @@ static char *fstrndup(const char *ptr, unsigned long len) {
429
476
  */
430
477
  static VALUE mHash_to_json(int argc, VALUE *argv, VALUE self)
431
478
  {
432
- GENERATE_JSON(object);
479
+ rb_check_arity(argc, 0, 1);
480
+ VALUE Vstate = cState_from_state_s(cState, argc == 1 ? argv[0] : Qnil);
481
+ return cState_partial_generate(Vstate, self, generate_json_object, Qfalse);
433
482
  }
434
483
 
435
484
  /*
@@ -441,7 +490,9 @@ static VALUE mHash_to_json(int argc, VALUE *argv, VALUE self)
441
490
  * produced JSON string output further.
442
491
  */
443
492
  static VALUE mArray_to_json(int argc, VALUE *argv, VALUE self) {
444
- GENERATE_JSON(array);
493
+ rb_check_arity(argc, 0, 1);
494
+ VALUE Vstate = cState_from_state_s(cState, argc == 1 ? argv[0] : Qnil);
495
+ return cState_partial_generate(Vstate, self, generate_json_array, Qfalse);
445
496
  }
446
497
 
447
498
  #ifdef RUBY_INTEGER_UNIFICATION
@@ -452,7 +503,9 @@ static VALUE mArray_to_json(int argc, VALUE *argv, VALUE self) {
452
503
  */
453
504
  static VALUE mInteger_to_json(int argc, VALUE *argv, VALUE self)
454
505
  {
455
- GENERATE_JSON(integer);
506
+ rb_check_arity(argc, 0, 1);
507
+ VALUE Vstate = cState_from_state_s(cState, argc == 1 ? argv[0] : Qnil);
508
+ return cState_partial_generate(Vstate, self, generate_json_integer, Qfalse);
456
509
  }
457
510
 
458
511
  #else
@@ -463,7 +516,9 @@ static VALUE mInteger_to_json(int argc, VALUE *argv, VALUE self)
463
516
  */
464
517
  static VALUE mFixnum_to_json(int argc, VALUE *argv, VALUE self)
465
518
  {
466
- GENERATE_JSON(fixnum);
519
+ rb_check_arity(argc, 0, 1);
520
+ VALUE Vstate = cState_from_state_s(cState, argc == 1 ? argv[0] : Qnil);
521
+ return cState_partial_generate(Vstate, self, generate_json_fixnum, Qfalse);
467
522
  }
468
523
 
469
524
  /*
@@ -473,7 +528,9 @@ static VALUE mFixnum_to_json(int argc, VALUE *argv, VALUE self)
473
528
  */
474
529
  static VALUE mBignum_to_json(int argc, VALUE *argv, VALUE self)
475
530
  {
476
- GENERATE_JSON(bignum);
531
+ rb_check_arity(argc, 0, 1);
532
+ VALUE Vstate = cState_from_state_s(cState, argc == 1 ? argv[0] : Qnil);
533
+ return cState_partial_generate(Vstate, self, generate_json_bignum, Qfalse);
477
534
  }
478
535
  #endif
479
536
 
@@ -484,7 +541,9 @@ static VALUE mBignum_to_json(int argc, VALUE *argv, VALUE self)
484
541
  */
485
542
  static VALUE mFloat_to_json(int argc, VALUE *argv, VALUE self)
486
543
  {
487
- GENERATE_JSON(float);
544
+ rb_check_arity(argc, 0, 1);
545
+ VALUE Vstate = cState_from_state_s(cState, argc == 1 ? argv[0] : Qnil);
546
+ return cState_partial_generate(Vstate, self, generate_json_float, Qfalse);
488
547
  }
489
548
 
490
549
  /*
@@ -507,7 +566,9 @@ static VALUE mString_included_s(VALUE self, VALUE modul) {
507
566
  */
508
567
  static VALUE mString_to_json(int argc, VALUE *argv, VALUE self)
509
568
  {
510
- GENERATE_JSON(string);
569
+ rb_check_arity(argc, 0, 1);
570
+ VALUE Vstate = cState_from_state_s(cState, argc == 1 ? argv[0] : Qnil);
571
+ return cState_partial_generate(Vstate, self, generate_json_string, Qfalse);
511
572
  }
512
573
 
513
574
  /*
@@ -524,7 +585,7 @@ static VALUE mString_to_json_raw_object(VALUE self)
524
585
  VALUE result = rb_hash_new();
525
586
  rb_hash_aset(result, rb_funcall(mJSON, i_create_id, 0), rb_class_name(rb_obj_class(self)));
526
587
  ary = rb_funcall(self, i_unpack, 1, rb_str_new2("C*"));
527
- rb_hash_aset(result, rb_str_new2("raw"), ary);
588
+ rb_hash_aset(result, rb_utf8_str_new_lit("raw"), ary);
528
589
  return result;
529
590
  }
530
591
 
@@ -562,7 +623,8 @@ static VALUE mString_Extend_json_create(VALUE self, VALUE o)
562
623
  */
563
624
  static VALUE mTrueClass_to_json(int argc, VALUE *argv, VALUE self)
564
625
  {
565
- GENERATE_JSON(true);
626
+ rb_check_arity(argc, 0, 1);
627
+ return rb_utf8_str_new("true", 4);
566
628
  }
567
629
 
568
630
  /*
@@ -572,7 +634,8 @@ static VALUE mTrueClass_to_json(int argc, VALUE *argv, VALUE self)
572
634
  */
573
635
  static VALUE mFalseClass_to_json(int argc, VALUE *argv, VALUE self)
574
636
  {
575
- GENERATE_JSON(false);
637
+ rb_check_arity(argc, 0, 1);
638
+ return rb_utf8_str_new("false", 5);
576
639
  }
577
640
 
578
641
  /*
@@ -582,7 +645,8 @@ static VALUE mFalseClass_to_json(int argc, VALUE *argv, VALUE self)
582
645
  */
583
646
  static VALUE mNilClass_to_json(int argc, VALUE *argv, VALUE self)
584
647
  {
585
- GENERATE_JSON(null);
648
+ rb_check_arity(argc, 0, 1);
649
+ return rb_utf8_str_new("null", 4);
586
650
  }
587
651
 
588
652
  /*
@@ -599,36 +663,38 @@ static VALUE mObject_to_json(int argc, VALUE *argv, VALUE self)
599
663
  rb_scan_args(argc, argv, "01", &state);
600
664
  Check_Type(string, T_STRING);
601
665
  state = cState_from_state_s(cState, state);
602
- return cState_partial_generate(state, string);
666
+ return cState_partial_generate(state, string, generate_json_string, Qfalse);
667
+ }
668
+
669
+ static void State_mark(void *ptr)
670
+ {
671
+ JSON_Generator_State *state = ptr;
672
+ rb_gc_mark_movable(state->indent);
673
+ rb_gc_mark_movable(state->space);
674
+ rb_gc_mark_movable(state->space_before);
675
+ rb_gc_mark_movable(state->object_nl);
676
+ rb_gc_mark_movable(state->array_nl);
677
+ }
678
+
679
+ static void State_compact(void *ptr)
680
+ {
681
+ JSON_Generator_State *state = ptr;
682
+ state->indent = rb_gc_location(state->indent);
683
+ state->space = rb_gc_location(state->space);
684
+ state->space_before = rb_gc_location(state->space_before);
685
+ state->object_nl = rb_gc_location(state->object_nl);
686
+ state->array_nl = rb_gc_location(state->array_nl);
603
687
  }
604
688
 
605
689
  static void State_free(void *ptr)
606
690
  {
607
691
  JSON_Generator_State *state = ptr;
608
- if (state->indent) ruby_xfree(state->indent);
609
- if (state->space) ruby_xfree(state->space);
610
- if (state->space_before) ruby_xfree(state->space_before);
611
- if (state->object_nl) ruby_xfree(state->object_nl);
612
- if (state->array_nl) ruby_xfree(state->array_nl);
613
- if (state->array_delim) fbuffer_free(state->array_delim);
614
- if (state->object_delim) fbuffer_free(state->object_delim);
615
- if (state->object_delim2) fbuffer_free(state->object_delim2);
616
692
  ruby_xfree(state);
617
693
  }
618
694
 
619
695
  static size_t State_memsize(const void *ptr)
620
696
  {
621
- const JSON_Generator_State *state = ptr;
622
- size_t size = sizeof(*state);
623
- if (state->indent) size += state->indent_len + 1;
624
- if (state->space) size += state->space_len + 1;
625
- if (state->space_before) size += state->space_before_len + 1;
626
- if (state->object_nl) size += state->object_nl_len + 1;
627
- if (state->array_nl) size += state->array_nl_len + 1;
628
- if (state->array_delim) size += FBUFFER_CAPA(state->array_delim);
629
- if (state->object_delim) size += FBUFFER_CAPA(state->object_delim);
630
- if (state->object_delim2) size += FBUFFER_CAPA(state->object_delim2);
631
- return size;
697
+ return sizeof(JSON_Generator_State);
632
698
  }
633
699
 
634
700
  #ifndef HAVE_RB_EXT_RACTOR_SAFE
@@ -636,200 +702,56 @@ static size_t State_memsize(const void *ptr)
636
702
  # define RUBY_TYPED_FROZEN_SHAREABLE 0
637
703
  #endif
638
704
 
639
- #ifdef NEW_TYPEDDATA_WRAPPER
640
705
  static const rb_data_type_t JSON_Generator_State_type = {
641
706
  "JSON/Generator/State",
642
- {NULL, State_free, State_memsize,},
643
- #ifdef RUBY_TYPED_FREE_IMMEDIATELY
707
+ {
708
+ .dmark = State_mark,
709
+ .dfree = State_free,
710
+ .dsize = State_memsize,
711
+ .dcompact = State_compact,
712
+ },
644
713
  0, 0,
645
- RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_FROZEN_SHAREABLE,
646
- #endif
714
+ RUBY_TYPED_WB_PROTECTED | RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_FROZEN_SHAREABLE,
647
715
  };
648
- #endif
649
716
 
650
- static VALUE cState_s_allocate(VALUE klass)
717
+ static void state_init(JSON_Generator_State *state)
651
718
  {
652
- JSON_Generator_State *state;
653
- return TypedData_Make_Struct(klass, JSON_Generator_State,
654
- &JSON_Generator_State_type, state);
655
- }
656
-
657
- /*
658
- * call-seq: configure(opts)
659
- *
660
- * Configure this State instance with the Hash _opts_, and return
661
- * itself.
662
- */
663
- static VALUE cState_configure(VALUE self, VALUE opts)
664
- {
665
- VALUE tmp;
666
- GET_STATE(self);
667
- tmp = rb_check_convert_type(opts, T_HASH, "Hash", "to_hash");
668
- if (NIL_P(tmp)) tmp = rb_convert_type(opts, T_HASH, "Hash", "to_h");
669
- opts = tmp;
670
- tmp = rb_hash_aref(opts, ID2SYM(i_indent));
671
- if (RTEST(tmp)) {
672
- unsigned long len;
673
- Check_Type(tmp, T_STRING);
674
- len = RSTRING_LEN(tmp);
675
- state->indent = fstrndup(RSTRING_PTR(tmp), len + 1);
676
- state->indent_len = len;
677
- }
678
- tmp = rb_hash_aref(opts, ID2SYM(i_space));
679
- if (RTEST(tmp)) {
680
- unsigned long len;
681
- Check_Type(tmp, T_STRING);
682
- len = RSTRING_LEN(tmp);
683
- state->space = fstrndup(RSTRING_PTR(tmp), len + 1);
684
- state->space_len = len;
685
- }
686
- tmp = rb_hash_aref(opts, ID2SYM(i_space_before));
687
- if (RTEST(tmp)) {
688
- unsigned long len;
689
- Check_Type(tmp, T_STRING);
690
- len = RSTRING_LEN(tmp);
691
- state->space_before = fstrndup(RSTRING_PTR(tmp), len + 1);
692
- state->space_before_len = len;
693
- }
694
- tmp = rb_hash_aref(opts, ID2SYM(i_array_nl));
695
- if (RTEST(tmp)) {
696
- unsigned long len;
697
- Check_Type(tmp, T_STRING);
698
- len = RSTRING_LEN(tmp);
699
- state->array_nl = fstrndup(RSTRING_PTR(tmp), len + 1);
700
- state->array_nl_len = len;
701
- }
702
- tmp = rb_hash_aref(opts, ID2SYM(i_object_nl));
703
- if (RTEST(tmp)) {
704
- unsigned long len;
705
- Check_Type(tmp, T_STRING);
706
- len = RSTRING_LEN(tmp);
707
- state->object_nl = fstrndup(RSTRING_PTR(tmp), len + 1);
708
- state->object_nl_len = len;
709
- }
710
- tmp = ID2SYM(i_max_nesting);
711
719
  state->max_nesting = 100;
712
- if (option_given_p(opts, tmp)) {
713
- VALUE max_nesting = rb_hash_aref(opts, tmp);
714
- if (RTEST(max_nesting)) {
715
- Check_Type(max_nesting, T_FIXNUM);
716
- state->max_nesting = FIX2LONG(max_nesting);
717
- } else {
718
- state->max_nesting = 0;
719
- }
720
- }
721
- tmp = ID2SYM(i_depth);
722
- state->depth = 0;
723
- if (option_given_p(opts, tmp)) {
724
- VALUE depth = rb_hash_aref(opts, tmp);
725
- if (RTEST(depth)) {
726
- Check_Type(depth, T_FIXNUM);
727
- state->depth = FIX2LONG(depth);
728
- } else {
729
- state->depth = 0;
730
- }
731
- }
732
- tmp = ID2SYM(i_buffer_initial_length);
733
- if (option_given_p(opts, tmp)) {
734
- VALUE buffer_initial_length = rb_hash_aref(opts, tmp);
735
- if (RTEST(buffer_initial_length)) {
736
- long initial_length;
737
- Check_Type(buffer_initial_length, T_FIXNUM);
738
- initial_length = FIX2LONG(buffer_initial_length);
739
- if (initial_length > 0) state->buffer_initial_length = initial_length;
740
- }
741
- }
742
- tmp = rb_hash_aref(opts, ID2SYM(i_allow_nan));
743
- state->allow_nan = RTEST(tmp);
744
- tmp = rb_hash_aref(opts, ID2SYM(i_ascii_only));
745
- state->ascii_only = RTEST(tmp);
746
- tmp = rb_hash_aref(opts, ID2SYM(i_script_safe));
747
- state->script_safe = RTEST(tmp);
748
- if (!state->script_safe) {
749
- tmp = rb_hash_aref(opts, ID2SYM(i_escape_slash));
750
- state->script_safe = RTEST(tmp);
751
- }
752
- tmp = rb_hash_aref(opts, ID2SYM(i_strict));
753
- state->strict = RTEST(tmp);
754
- return self;
720
+ state->buffer_initial_length = FBUFFER_INITIAL_LENGTH_DEFAULT;
755
721
  }
756
722
 
757
- static void set_state_ivars(VALUE hash, VALUE state)
723
+ static VALUE cState_s_allocate(VALUE klass)
758
724
  {
759
- VALUE ivars = rb_obj_instance_variables(state);
760
- int i = 0;
761
- for (i = 0; i < RARRAY_LEN(ivars); i++) {
762
- VALUE key = rb_funcall(rb_ary_entry(ivars, i), i_to_s, 0);
763
- long key_len = RSTRING_LEN(key);
764
- VALUE value = rb_iv_get(state, StringValueCStr(key));
765
- rb_hash_aset(hash, rb_str_intern(rb_str_substr(key, 1, key_len - 1)), value);
766
- }
725
+ JSON_Generator_State *state;
726
+ VALUE obj = TypedData_Make_Struct(klass, JSON_Generator_State, &JSON_Generator_State_type, state);
727
+ state_init(state);
728
+ return obj;
767
729
  }
768
730
 
769
- /*
770
- * call-seq: to_h
771
- *
772
- * Returns the configuration instance variables as a hash, that can be
773
- * passed to the configure method.
774
- */
775
- static VALUE cState_to_h(VALUE self)
731
+ static void vstate_spill(struct generate_json_data *data)
776
732
  {
777
- VALUE result = rb_hash_new();
778
- GET_STATE(self);
779
- set_state_ivars(result, self);
780
- rb_hash_aset(result, ID2SYM(i_indent), rb_str_new(state->indent, state->indent_len));
781
- rb_hash_aset(result, ID2SYM(i_space), rb_str_new(state->space, state->space_len));
782
- rb_hash_aset(result, ID2SYM(i_space_before), rb_str_new(state->space_before, state->space_before_len));
783
- rb_hash_aset(result, ID2SYM(i_object_nl), rb_str_new(state->object_nl, state->object_nl_len));
784
- rb_hash_aset(result, ID2SYM(i_array_nl), rb_str_new(state->array_nl, state->array_nl_len));
785
- rb_hash_aset(result, ID2SYM(i_allow_nan), state->allow_nan ? Qtrue : Qfalse);
786
- rb_hash_aset(result, ID2SYM(i_ascii_only), state->ascii_only ? Qtrue : Qfalse);
787
- rb_hash_aset(result, ID2SYM(i_max_nesting), LONG2FIX(state->max_nesting));
788
- rb_hash_aset(result, ID2SYM(i_script_safe), state->script_safe ? Qtrue : Qfalse);
789
- rb_hash_aset(result, ID2SYM(i_strict), state->strict ? Qtrue : Qfalse);
790
- rb_hash_aset(result, ID2SYM(i_depth), LONG2FIX(state->depth));
791
- rb_hash_aset(result, ID2SYM(i_buffer_initial_length), LONG2FIX(state->buffer_initial_length));
792
- return result;
733
+ VALUE vstate = cState_s_allocate(cState);
734
+ GET_STATE(vstate);
735
+ MEMCPY(state, data->state, JSON_Generator_State, 1);
736
+ data->state = state;
737
+ data->vstate = vstate;
738
+ RB_OBJ_WRITTEN(vstate, Qundef, state->indent);
739
+ RB_OBJ_WRITTEN(vstate, Qundef, state->space);
740
+ RB_OBJ_WRITTEN(vstate, Qundef, state->space_before);
741
+ RB_OBJ_WRITTEN(vstate, Qundef, state->object_nl);
742
+ RB_OBJ_WRITTEN(vstate, Qundef, state->array_nl);
793
743
  }
794
744
 
795
- /*
796
- * call-seq: [](name)
797
- *
798
- * Returns the value returned by method +name+.
799
- */
800
- static VALUE cState_aref(VALUE self, VALUE name)
745
+ static inline VALUE vstate_get(struct generate_json_data *data)
801
746
  {
802
- name = rb_funcall(name, i_to_s, 0);
803
- if (RTEST(rb_funcall(self, i_respond_to_p, 1, name))) {
804
- return rb_funcall(self, i_send, 1, name);
805
- } else {
806
- return rb_attr_get(self, rb_intern_str(rb_str_concat(rb_str_new2("@"), name)));
747
+ if (RB_UNLIKELY(!data->vstate)) {
748
+ vstate_spill(data);
807
749
  }
808
- }
809
-
810
- /*
811
- * call-seq: []=(name, value)
812
- *
813
- * Sets the attribute name to value.
814
- */
815
- static VALUE cState_aset(VALUE self, VALUE name, VALUE value)
816
- {
817
- VALUE name_writer;
818
-
819
- name = rb_funcall(name, i_to_s, 0);
820
- name_writer = rb_str_cat2(rb_str_dup(name), "=");
821
- if (RTEST(rb_funcall(self, i_respond_to_p, 1, name_writer))) {
822
- return rb_funcall(self, i_send, 2, name_writer, value);
823
- } else {
824
- rb_ivar_set(self, rb_intern_str(rb_str_concat(rb_str_new2("@"), name)), value);
825
- }
826
- return Qnil;
750
+ return data->vstate;
827
751
  }
828
752
 
829
753
  struct hash_foreach_arg {
830
- FBuffer *buffer;
831
- JSON_Generator_State *state;
832
- VALUE Vstate;
754
+ struct generate_json_data *data;
833
755
  int iter;
834
756
  };
835
757
 
@@ -837,273 +759,308 @@ static int
837
759
  json_object_i(VALUE key, VALUE val, VALUE _arg)
838
760
  {
839
761
  struct hash_foreach_arg *arg = (struct hash_foreach_arg *)_arg;
840
- FBuffer *buffer = arg->buffer;
841
- JSON_Generator_State *state = arg->state;
842
- VALUE Vstate = arg->Vstate;
843
-
844
- char *object_nl = state->object_nl;
845
- long object_nl_len = state->object_nl_len;
846
- char *indent = state->indent;
847
- long indent_len = state->indent_len;
848
- char *delim = FBUFFER_PTR(state->object_delim);
849
- long delim_len = FBUFFER_LEN(state->object_delim);
850
- char *delim2 = FBUFFER_PTR(state->object_delim2);
851
- long delim2_len = FBUFFER_LEN(state->object_delim2);
762
+ struct generate_json_data *data = arg->data;
763
+
764
+ FBuffer *buffer = data->buffer;
765
+ JSON_Generator_State *state = data->state;
766
+
852
767
  long depth = state->depth;
853
768
  int j;
854
- VALUE klass, key_to_s;
855
769
 
856
- if (arg->iter > 0) fbuffer_append(buffer, delim, delim_len);
857
- if (object_nl) {
858
- fbuffer_append(buffer, object_nl, object_nl_len);
770
+ if (arg->iter > 0) fbuffer_append_char(buffer, ',');
771
+ if (RB_UNLIKELY(state->object_nl)) {
772
+ fbuffer_append_str(buffer, state->object_nl);
859
773
  }
860
- if (indent) {
774
+ if (RB_UNLIKELY(state->indent)) {
861
775
  for (j = 0; j < depth; j++) {
862
- fbuffer_append(buffer, indent, indent_len);
776
+ fbuffer_append_str(buffer, state->indent);
863
777
  }
864
778
  }
865
779
 
866
- klass = CLASS_OF(key);
867
- if (klass == rb_cString) {
868
- key_to_s = key;
869
- } else if (klass == rb_cSymbol) {
870
- key_to_s = rb_sym2str(key);
780
+ VALUE key_to_s;
781
+ switch(rb_type(key)) {
782
+ case T_STRING:
783
+ if (RB_LIKELY(RBASIC_CLASS(key) == rb_cString)) {
784
+ key_to_s = key;
785
+ } else {
786
+ key_to_s = rb_funcall(key, i_to_s, 0);
787
+ }
788
+ break;
789
+ case T_SYMBOL:
790
+ key_to_s = rb_sym2str(key);
791
+ break;
792
+ default:
793
+ key_to_s = rb_convert_type(key, T_STRING, "String", "to_s");
794
+ break;
795
+ }
796
+
797
+ if (RB_LIKELY(RBASIC_CLASS(key_to_s) == rb_cString)) {
798
+ generate_json_string(buffer, data, state, key_to_s);
871
799
  } else {
872
- key_to_s = rb_funcall(key, i_to_s, 0);
800
+ generate_json(buffer, data, state, key_to_s);
873
801
  }
874
- Check_Type(key_to_s, T_STRING);
875
- generate_json(buffer, Vstate, state, key_to_s);
876
- fbuffer_append(buffer, delim2, delim2_len);
877
- generate_json(buffer, Vstate, state, val);
802
+ if (RB_UNLIKELY(state->space_before)) fbuffer_append_str(buffer, state->space_before);
803
+ fbuffer_append_char(buffer, ':');
804
+ if (RB_UNLIKELY(state->space)) fbuffer_append_str(buffer, state->space);
805
+ generate_json(buffer, data, state, val);
878
806
 
879
807
  arg->iter++;
880
808
  return ST_CONTINUE;
881
809
  }
882
810
 
883
- static void generate_json_object(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj)
811
+ static void generate_json_object(FBuffer *buffer, struct generate_json_data *data, JSON_Generator_State *state, VALUE obj)
884
812
  {
885
- char *object_nl = state->object_nl;
886
- long object_nl_len = state->object_nl_len;
887
- char *indent = state->indent;
888
- long indent_len = state->indent_len;
889
813
  long max_nesting = state->max_nesting;
890
814
  long depth = ++state->depth;
891
815
  int j;
892
- struct hash_foreach_arg arg;
893
816
 
894
817
  if (max_nesting != 0 && depth > max_nesting) {
895
818
  rb_raise(eNestingError, "nesting of %ld is too deep", --state->depth);
896
819
  }
820
+
821
+ if (RHASH_SIZE(obj) == 0) {
822
+ fbuffer_append(buffer, "{}", 2);
823
+ --state->depth;
824
+ return;
825
+ }
826
+
897
827
  fbuffer_append_char(buffer, '{');
898
828
 
899
- arg.buffer = buffer;
900
- arg.state = state;
901
- arg.Vstate = Vstate;
902
- arg.iter = 0;
829
+ struct hash_foreach_arg arg = {
830
+ .data = data,
831
+ .iter = 0,
832
+ };
903
833
  rb_hash_foreach(obj, json_object_i, (VALUE)&arg);
904
834
 
905
835
  depth = --state->depth;
906
- if (object_nl) {
907
- fbuffer_append(buffer, object_nl, object_nl_len);
908
- if (indent) {
836
+ if (RB_UNLIKELY(state->object_nl)) {
837
+ fbuffer_append_str(buffer, state->object_nl);
838
+ if (RB_UNLIKELY(state->indent)) {
909
839
  for (j = 0; j < depth; j++) {
910
- fbuffer_append(buffer, indent, indent_len);
840
+ fbuffer_append_str(buffer, state->indent);
911
841
  }
912
842
  }
913
843
  }
914
844
  fbuffer_append_char(buffer, '}');
915
845
  }
916
846
 
917
- static void generate_json_array(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj)
847
+ static void generate_json_array(FBuffer *buffer, struct generate_json_data *data, JSON_Generator_State *state, VALUE obj)
918
848
  {
919
- char *array_nl = state->array_nl;
920
- long array_nl_len = state->array_nl_len;
921
- char *indent = state->indent;
922
- long indent_len = state->indent_len;
923
849
  long max_nesting = state->max_nesting;
924
- char *delim = FBUFFER_PTR(state->array_delim);
925
- long delim_len = FBUFFER_LEN(state->array_delim);
926
850
  long depth = ++state->depth;
927
851
  int i, j;
928
852
  if (max_nesting != 0 && depth > max_nesting) {
929
853
  rb_raise(eNestingError, "nesting of %ld is too deep", --state->depth);
930
854
  }
855
+
856
+ if (RARRAY_LEN(obj) == 0) {
857
+ fbuffer_append(buffer, "[]", 2);
858
+ --state->depth;
859
+ return;
860
+ }
861
+
931
862
  fbuffer_append_char(buffer, '[');
932
- if (array_nl) fbuffer_append(buffer, array_nl, array_nl_len);
863
+ if (RB_UNLIKELY(state->array_nl)) fbuffer_append_str(buffer, state->array_nl);
933
864
  for(i = 0; i < RARRAY_LEN(obj); i++) {
934
- if (i > 0) fbuffer_append(buffer, delim, delim_len);
935
- if (indent) {
865
+ if (i > 0) {
866
+ fbuffer_append_char(buffer, ',');
867
+ if (RB_UNLIKELY(state->array_nl)) fbuffer_append_str(buffer, state->array_nl);
868
+ }
869
+ if (RB_UNLIKELY(state->indent)) {
936
870
  for (j = 0; j < depth; j++) {
937
- fbuffer_append(buffer, indent, indent_len);
871
+ fbuffer_append_str(buffer, state->indent);
938
872
  }
939
873
  }
940
- generate_json(buffer, Vstate, state, rb_ary_entry(obj, i));
874
+ generate_json(buffer, data, state, RARRAY_AREF(obj, i));
941
875
  }
942
876
  state->depth = --depth;
943
- if (array_nl) {
944
- fbuffer_append(buffer, array_nl, array_nl_len);
945
- if (indent) {
877
+ if (RB_UNLIKELY(state->array_nl)) {
878
+ fbuffer_append_str(buffer, state->array_nl);
879
+ if (RB_UNLIKELY(state->indent)) {
946
880
  for (j = 0; j < depth; j++) {
947
- fbuffer_append(buffer, indent, indent_len);
881
+ fbuffer_append_str(buffer, state->indent);
948
882
  }
949
883
  }
950
884
  }
951
885
  fbuffer_append_char(buffer, ']');
952
886
  }
953
887
 
954
- #ifdef HAVE_RUBY_ENCODING_H
955
- static int enc_utf8_compatible_p(rb_encoding *enc)
888
+ static inline int enc_utf8_compatible_p(int enc_idx)
956
889
  {
957
- if (enc == rb_usascii_encoding()) return 1;
958
- if (enc == rb_utf8_encoding()) return 1;
890
+ if (enc_idx == usascii_encindex) return 1;
891
+ if (enc_idx == utf8_encindex) return 1;
959
892
  return 0;
960
893
  }
961
- #endif
962
894
 
963
- static void generate_json_string(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj)
895
+ static VALUE encode_json_string_try(VALUE str)
964
896
  {
965
- fbuffer_append_char(buffer, '"');
966
- #ifdef HAVE_RUBY_ENCODING_H
967
- if (!enc_utf8_compatible_p(rb_enc_get(obj))) {
968
- obj = rb_str_export_to_enc(obj, rb_utf8_encoding());
897
+ return rb_funcall(str, i_encode, 1, Encoding_UTF_8);
898
+ }
899
+
900
+ static VALUE encode_json_string_rescue(VALUE str, VALUE exception)
901
+ {
902
+ raise_generator_error_str(str, rb_funcall(exception, rb_intern("message"), 0));
903
+ return Qundef;
904
+ }
905
+
906
+ static inline VALUE ensure_valid_encoding(VALUE str)
907
+ {
908
+ int encindex = RB_ENCODING_GET(str);
909
+ VALUE utf8_string;
910
+ if (RB_UNLIKELY(!enc_utf8_compatible_p(encindex))) {
911
+ if (encindex == binary_encindex) {
912
+ utf8_string = rb_enc_associate_index(rb_str_dup(str), utf8_encindex);
913
+ switch (rb_enc_str_coderange(utf8_string)) {
914
+ case ENC_CODERANGE_7BIT:
915
+ return utf8_string;
916
+ case ENC_CODERANGE_VALID:
917
+ // For historical reason, we silently reinterpret binary strings as UTF-8 if it would work.
918
+ // TODO: Raise in 3.0.0
919
+ rb_warn("JSON.generate: UTF-8 string passed as BINARY, this will raise an encoding error in json 3.0");
920
+ return utf8_string;
921
+ break;
922
+ }
923
+ }
924
+
925
+ str = rb_rescue(encode_json_string_try, str, encode_json_string_rescue, str);
969
926
  }
970
- #endif
971
- if (state->ascii_only) {
972
- convert_UTF8_to_JSON_ASCII(buffer, obj, state->script_safe);
973
- } else {
974
- convert_UTF8_to_JSON(buffer, obj, state->script_safe);
927
+ return str;
928
+ }
929
+
930
+ static void generate_json_string(FBuffer *buffer, struct generate_json_data *data, JSON_Generator_State *state, VALUE obj)
931
+ {
932
+ obj = ensure_valid_encoding(obj);
933
+
934
+ fbuffer_append_char(buffer, '"');
935
+
936
+ switch(rb_enc_str_coderange(obj)) {
937
+ case ENC_CODERANGE_7BIT:
938
+ convert_ASCII_to_JSON(buffer, obj, state->script_safe ? script_safe_escape_table : escape_table);
939
+ break;
940
+ case ENC_CODERANGE_VALID:
941
+ if (RB_UNLIKELY(state->ascii_only)) {
942
+ convert_UTF8_to_ASCII_only_JSON(buffer, obj, state->script_safe ? script_safe_escape_table : escape_table, state->script_safe);
943
+ } else {
944
+ convert_UTF8_to_JSON(buffer, obj, state->script_safe ? script_safe_escape_table : escape_table, state->script_safe);
945
+ }
946
+ break;
947
+ default:
948
+ raise_generator_error(obj, "source sequence is illegal/malformed utf-8");
949
+ break;
975
950
  }
976
951
  fbuffer_append_char(buffer, '"');
977
952
  }
978
953
 
979
- static void generate_json_null(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj)
954
+ static void generate_json_null(FBuffer *buffer, struct generate_json_data *data, JSON_Generator_State *state, VALUE obj)
980
955
  {
981
956
  fbuffer_append(buffer, "null", 4);
982
957
  }
983
958
 
984
- static void generate_json_false(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj)
959
+ static void generate_json_false(FBuffer *buffer, struct generate_json_data *data, JSON_Generator_State *state, VALUE obj)
985
960
  {
986
961
  fbuffer_append(buffer, "false", 5);
987
962
  }
988
963
 
989
- static void generate_json_true(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj)
964
+ static void generate_json_true(FBuffer *buffer, struct generate_json_data *data, JSON_Generator_State *state, VALUE obj)
990
965
  {
991
966
  fbuffer_append(buffer, "true", 4);
992
967
  }
993
968
 
994
- static void generate_json_fixnum(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj)
969
+ static void generate_json_fixnum(FBuffer *buffer, struct generate_json_data *data, JSON_Generator_State *state, VALUE obj)
995
970
  {
996
971
  fbuffer_append_long(buffer, FIX2LONG(obj));
997
972
  }
998
973
 
999
- static void generate_json_bignum(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj)
974
+ static void generate_json_bignum(FBuffer *buffer, struct generate_json_data *data, JSON_Generator_State *state, VALUE obj)
1000
975
  {
1001
976
  VALUE tmp = rb_funcall(obj, i_to_s, 0);
1002
977
  fbuffer_append_str(buffer, tmp);
1003
978
  }
1004
979
 
1005
980
  #ifdef RUBY_INTEGER_UNIFICATION
1006
- static void generate_json_integer(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj)
981
+ static void generate_json_integer(FBuffer *buffer, struct generate_json_data *data, JSON_Generator_State *state, VALUE obj)
1007
982
  {
1008
983
  if (FIXNUM_P(obj))
1009
- generate_json_fixnum(buffer, Vstate, state, obj);
984
+ generate_json_fixnum(buffer, data, state, obj);
1010
985
  else
1011
- generate_json_bignum(buffer, Vstate, state, obj);
986
+ generate_json_bignum(buffer, data, state, obj);
1012
987
  }
1013
988
  #endif
1014
- static void generate_json_float(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj)
989
+
990
+ static void generate_json_float(FBuffer *buffer, struct generate_json_data *data, JSON_Generator_State *state, VALUE obj)
1015
991
  {
1016
992
  double value = RFLOAT_VALUE(obj);
1017
993
  char allow_nan = state->allow_nan;
1018
994
  VALUE tmp = rb_funcall(obj, i_to_s, 0);
1019
995
  if (!allow_nan) {
1020
- if (isinf(value)) {
1021
- rb_raise(eGeneratorError, "%"PRIsVALUE" not allowed in JSON", RB_OBJ_STRING(tmp));
1022
- } else if (isnan(value)) {
1023
- rb_raise(eGeneratorError, "%"PRIsVALUE" not allowed in JSON", RB_OBJ_STRING(tmp));
996
+ if (isinf(value) || isnan(value)) {
997
+ raise_generator_error(obj, "%"PRIsVALUE" not allowed in JSON", tmp);
1024
998
  }
1025
999
  }
1026
1000
  fbuffer_append_str(buffer, tmp);
1027
1001
  }
1028
1002
 
1029
- static void generate_json(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj)
1003
+ static void generate_json(FBuffer *buffer, struct generate_json_data *data, JSON_Generator_State *state, VALUE obj)
1030
1004
  {
1031
1005
  VALUE tmp;
1032
- VALUE klass = CLASS_OF(obj);
1033
- if (klass == rb_cHash) {
1034
- generate_json_object(buffer, Vstate, state, obj);
1035
- } else if (klass == rb_cArray) {
1036
- generate_json_array(buffer, Vstate, state, obj);
1037
- } else if (klass == rb_cString) {
1038
- generate_json_string(buffer, Vstate, state, obj);
1039
- } else if (obj == Qnil) {
1040
- generate_json_null(buffer, Vstate, state, obj);
1006
+ if (obj == Qnil) {
1007
+ generate_json_null(buffer, data, state, obj);
1041
1008
  } else if (obj == Qfalse) {
1042
- generate_json_false(buffer, Vstate, state, obj);
1009
+ generate_json_false(buffer, data, state, obj);
1043
1010
  } else if (obj == Qtrue) {
1044
- generate_json_true(buffer, Vstate, state, obj);
1045
- } else if (FIXNUM_P(obj)) {
1046
- generate_json_fixnum(buffer, Vstate, state, obj);
1047
- } else if (RB_TYPE_P(obj, T_BIGNUM)) {
1048
- generate_json_bignum(buffer, Vstate, state, obj);
1049
- } else if (klass == rb_cFloat) {
1050
- generate_json_float(buffer, Vstate, state, obj);
1051
- } else if (state->strict) {
1052
- rb_raise(eGeneratorError, "%"PRIsVALUE" not allowed in JSON", RB_OBJ_STRING(CLASS_OF(obj)));
1053
- } else if (rb_respond_to(obj, i_to_json)) {
1054
- tmp = rb_funcall(obj, i_to_json, 1, Vstate);
1055
- Check_Type(tmp, T_STRING);
1056
- fbuffer_append_str(buffer, tmp);
1057
- } else {
1058
- tmp = rb_funcall(obj, i_to_s, 0);
1059
- Check_Type(tmp, T_STRING);
1060
- generate_json_string(buffer, Vstate, state, tmp);
1061
- }
1062
- }
1063
-
1064
- static FBuffer *cState_prepare_buffer(VALUE self)
1065
- {
1066
- FBuffer *buffer;
1067
- GET_STATE(self);
1068
- buffer = fbuffer_alloc(state->buffer_initial_length);
1069
-
1070
- if (state->object_delim) {
1071
- fbuffer_clear(state->object_delim);
1072
- } else {
1073
- state->object_delim = fbuffer_alloc(16);
1074
- }
1075
- fbuffer_append_char(state->object_delim, ',');
1076
- if (state->object_delim2) {
1077
- fbuffer_clear(state->object_delim2);
1078
- } else {
1079
- state->object_delim2 = fbuffer_alloc(16);
1080
- }
1081
- if (state->space_before) fbuffer_append(state->object_delim2, state->space_before, state->space_before_len);
1082
- fbuffer_append_char(state->object_delim2, ':');
1083
- if (state->space) fbuffer_append(state->object_delim2, state->space, state->space_len);
1084
-
1085
- if (state->array_delim) {
1086
- fbuffer_clear(state->array_delim);
1011
+ generate_json_true(buffer, data, state, obj);
1012
+ } else if (RB_SPECIAL_CONST_P(obj)) {
1013
+ if (RB_FIXNUM_P(obj)) {
1014
+ generate_json_fixnum(buffer, data, state, obj);
1015
+ } else if (RB_FLONUM_P(obj)) {
1016
+ generate_json_float(buffer, data, state, obj);
1017
+ } else {
1018
+ goto general;
1019
+ }
1087
1020
  } else {
1088
- state->array_delim = fbuffer_alloc(16);
1021
+ VALUE klass = RBASIC_CLASS(obj);
1022
+ switch (RB_BUILTIN_TYPE(obj)) {
1023
+ case T_BIGNUM:
1024
+ generate_json_bignum(buffer, data, state, obj);
1025
+ break;
1026
+ case T_HASH:
1027
+ if (klass != rb_cHash) goto general;
1028
+ generate_json_object(buffer, data, state, obj);
1029
+ break;
1030
+ case T_ARRAY:
1031
+ if (klass != rb_cArray) goto general;
1032
+ generate_json_array(buffer, data, state, obj);
1033
+ break;
1034
+ case T_STRING:
1035
+ if (klass != rb_cString) goto general;
1036
+ generate_json_string(buffer, data, state, obj);
1037
+ break;
1038
+ case T_FLOAT:
1039
+ if (klass != rb_cFloat) goto general;
1040
+ generate_json_float(buffer, data, state, obj);
1041
+ break;
1042
+ default:
1043
+ general:
1044
+ if (state->strict) {
1045
+ raise_generator_error(obj, "%"PRIsVALUE" not allowed in JSON", CLASS_OF(obj));
1046
+ } else if (rb_respond_to(obj, i_to_json)) {
1047
+ tmp = rb_funcall(obj, i_to_json, 1, vstate_get(data));
1048
+ Check_Type(tmp, T_STRING);
1049
+ fbuffer_append_str(buffer, tmp);
1050
+ } else {
1051
+ tmp = rb_funcall(obj, i_to_s, 0);
1052
+ Check_Type(tmp, T_STRING);
1053
+ generate_json_string(buffer, data, state, tmp);
1054
+ }
1055
+ }
1089
1056
  }
1090
- fbuffer_append_char(state->array_delim, ',');
1091
- if (state->array_nl) fbuffer_append(state->array_delim, state->array_nl, state->array_nl_len);
1092
- return buffer;
1093
1057
  }
1094
1058
 
1095
- struct generate_json_data {
1096
- FBuffer *buffer;
1097
- VALUE vstate;
1098
- JSON_Generator_State *state;
1099
- VALUE obj;
1100
- };
1101
-
1102
1059
  static VALUE generate_json_try(VALUE d)
1103
1060
  {
1104
1061
  struct generate_json_data *data = (struct generate_json_data *)d;
1105
1062
 
1106
- generate_json(data->buffer, data->vstate, data->state, data->obj);
1063
+ data->func(data->buffer, data, data->state, data->obj);
1107
1064
 
1108
1065
  return Qnil;
1109
1066
  }
@@ -1118,65 +1075,39 @@ static VALUE generate_json_rescue(VALUE d, VALUE exc)
1118
1075
  return Qundef;
1119
1076
  }
1120
1077
 
1121
- static VALUE cState_partial_generate(VALUE self, VALUE obj)
1078
+ static VALUE cState_partial_generate(VALUE self, VALUE obj, generator_func func, VALUE io)
1122
1079
  {
1123
- FBuffer *buffer = cState_prepare_buffer(self);
1124
1080
  GET_STATE(self);
1125
1081
 
1082
+ char stack_buffer[FBUFFER_STACK_SIZE];
1083
+ FBuffer buffer = {
1084
+ .io = RTEST(io) ? io : Qfalse,
1085
+ };
1086
+ fbuffer_stack_init(&buffer, state->buffer_initial_length, stack_buffer, FBUFFER_STACK_SIZE);
1087
+
1126
1088
  struct generate_json_data data = {
1127
- .buffer = buffer,
1089
+ .buffer = &buffer,
1128
1090
  .vstate = self,
1129
1091
  .state = state,
1130
- .obj = obj
1092
+ .obj = obj,
1093
+ .func = func
1131
1094
  };
1132
1095
  rb_rescue(generate_json_try, (VALUE)&data, generate_json_rescue, (VALUE)&data);
1133
1096
 
1134
- return fbuffer_to_s(buffer);
1097
+ return fbuffer_finalize(&buffer);
1135
1098
  }
1136
1099
 
1137
- /*
1138
- * call-seq: generate(obj)
1139
- *
1140
- * Generates a valid JSON document from object +obj+ and returns the
1141
- * result. If no valid JSON document can be created this method raises a
1142
- * GeneratorError exception.
1143
- */
1144
- static VALUE cState_generate(VALUE self, VALUE obj)
1100
+ static VALUE cState_generate(VALUE self, VALUE obj, VALUE io)
1145
1101
  {
1146
- VALUE result = cState_partial_generate(self, obj);
1102
+ VALUE result = cState_partial_generate(self, obj, generate_json, io);
1147
1103
  GET_STATE(self);
1148
1104
  (void)state;
1149
1105
  return result;
1150
1106
  }
1151
1107
 
1152
- /*
1153
- * call-seq: new(opts = {})
1154
- *
1155
- * Instantiates a new State object, configured by _opts_.
1156
- *
1157
- * _opts_ can have the following keys:
1158
- *
1159
- * * *indent*: a string used to indent levels (default: ''),
1160
- * * *space*: a string that is put after, a : or , delimiter (default: ''),
1161
- * * *space_before*: a string that is put before a : pair delimiter (default: ''),
1162
- * * *object_nl*: a string that is put at the end of a JSON object (default: ''),
1163
- * * *array_nl*: a string that is put at the end of a JSON array (default: ''),
1164
- * * *allow_nan*: true if NaN, Infinity, and -Infinity should be
1165
- * generated, otherwise an exception is thrown, if these values are
1166
- * encountered. This options defaults to false.
1167
- * * *ascii_only*: true if only ASCII characters should be generated. This
1168
- * option defaults to false.
1169
- * * *buffer_initial_length*: sets the initial length of the generator's
1170
- * internal buffer.
1171
- */
1172
1108
  static VALUE cState_initialize(int argc, VALUE *argv, VALUE self)
1173
1109
  {
1174
- VALUE opts;
1175
- GET_STATE(self);
1176
- state->max_nesting = 100;
1177
- state->buffer_initial_length = FBUFFER_INITIAL_LENGTH_DEFAULT;
1178
- rb_scan_args(argc, argv, "01", &opts);
1179
- if (!NIL_P(opts)) cState_configure(self, opts);
1110
+ rb_warn("The json gem extension was loaded with the stdlib ruby code. You should upgrade rubygems with `gem update --system`");
1180
1111
  return self;
1181
1112
  }
1182
1113
 
@@ -1196,14 +1127,11 @@ static VALUE cState_init_copy(VALUE obj, VALUE orig)
1196
1127
  if (!objState) rb_raise(rb_eArgError, "unallocated JSON::State");
1197
1128
 
1198
1129
  MEMCPY(objState, origState, JSON_Generator_State, 1);
1199
- objState->indent = fstrndup(origState->indent, origState->indent_len);
1200
- objState->space = fstrndup(origState->space, origState->space_len);
1201
- objState->space_before = fstrndup(origState->space_before, origState->space_before_len);
1202
- objState->object_nl = fstrndup(origState->object_nl, origState->object_nl_len);
1203
- objState->array_nl = fstrndup(origState->array_nl, origState->array_nl_len);
1204
- if (origState->array_delim) objState->array_delim = fbuffer_dup(origState->array_delim);
1205
- if (origState->object_delim) objState->object_delim = fbuffer_dup(origState->object_delim);
1206
- if (origState->object_delim2) objState->object_delim2 = fbuffer_dup(origState->object_delim2);
1130
+ objState->indent = origState->indent;
1131
+ objState->space = origState->space;
1132
+ objState->space_before = origState->space_before;
1133
+ objState->object_nl = origState->object_nl;
1134
+ objState->array_nl = origState->array_nl;
1207
1135
  return obj;
1208
1136
  }
1209
1137
 
@@ -1233,7 +1161,18 @@ static VALUE cState_from_state_s(VALUE self, VALUE opts)
1233
1161
  static VALUE cState_indent(VALUE self)
1234
1162
  {
1235
1163
  GET_STATE(self);
1236
- return state->indent ? rb_str_new(state->indent, state->indent_len) : rb_str_new2("");
1164
+ return state->indent ? state->indent : rb_str_freeze(rb_utf8_str_new("", 0));
1165
+ }
1166
+
1167
+ static VALUE string_config(VALUE config)
1168
+ {
1169
+ if (RTEST(config)) {
1170
+ Check_Type(config, T_STRING);
1171
+ if (RSTRING_LEN(config)) {
1172
+ return rb_str_new_frozen(config);
1173
+ }
1174
+ }
1175
+ return Qfalse;
1237
1176
  }
1238
1177
 
1239
1178
  /*
@@ -1243,21 +1182,8 @@ static VALUE cState_indent(VALUE self)
1243
1182
  */
1244
1183
  static VALUE cState_indent_set(VALUE self, VALUE indent)
1245
1184
  {
1246
- unsigned long len;
1247
1185
  GET_STATE(self);
1248
- Check_Type(indent, T_STRING);
1249
- len = RSTRING_LEN(indent);
1250
- if (len == 0) {
1251
- if (state->indent) {
1252
- ruby_xfree(state->indent);
1253
- state->indent = NULL;
1254
- state->indent_len = 0;
1255
- }
1256
- } else {
1257
- if (state->indent) ruby_xfree(state->indent);
1258
- state->indent = fstrndup(RSTRING_PTR(indent), len);
1259
- state->indent_len = len;
1260
- }
1186
+ RB_OBJ_WRITE(self, &state->indent, string_config(indent));
1261
1187
  return Qnil;
1262
1188
  }
1263
1189
 
@@ -1270,7 +1196,7 @@ static VALUE cState_indent_set(VALUE self, VALUE indent)
1270
1196
  static VALUE cState_space(VALUE self)
1271
1197
  {
1272
1198
  GET_STATE(self);
1273
- return state->space ? rb_str_new(state->space, state->space_len) : rb_str_new2("");
1199
+ return state->space ? state->space : rb_str_freeze(rb_utf8_str_new("", 0));
1274
1200
  }
1275
1201
 
1276
1202
  /*
@@ -1281,21 +1207,8 @@ static VALUE cState_space(VALUE self)
1281
1207
  */
1282
1208
  static VALUE cState_space_set(VALUE self, VALUE space)
1283
1209
  {
1284
- unsigned long len;
1285
1210
  GET_STATE(self);
1286
- Check_Type(space, T_STRING);
1287
- len = RSTRING_LEN(space);
1288
- if (len == 0) {
1289
- if (state->space) {
1290
- ruby_xfree(state->space);
1291
- state->space = NULL;
1292
- state->space_len = 0;
1293
- }
1294
- } else {
1295
- if (state->space) ruby_xfree(state->space);
1296
- state->space = fstrndup(RSTRING_PTR(space), len);
1297
- state->space_len = len;
1298
- }
1211
+ RB_OBJ_WRITE(self, &state->space, string_config(space));
1299
1212
  return Qnil;
1300
1213
  }
1301
1214
 
@@ -1307,7 +1220,7 @@ static VALUE cState_space_set(VALUE self, VALUE space)
1307
1220
  static VALUE cState_space_before(VALUE self)
1308
1221
  {
1309
1222
  GET_STATE(self);
1310
- return state->space_before ? rb_str_new(state->space_before, state->space_before_len) : rb_str_new2("");
1223
+ return state->space_before ? state->space_before : rb_str_freeze(rb_utf8_str_new("", 0));
1311
1224
  }
1312
1225
 
1313
1226
  /*
@@ -1317,21 +1230,8 @@ static VALUE cState_space_before(VALUE self)
1317
1230
  */
1318
1231
  static VALUE cState_space_before_set(VALUE self, VALUE space_before)
1319
1232
  {
1320
- unsigned long len;
1321
1233
  GET_STATE(self);
1322
- Check_Type(space_before, T_STRING);
1323
- len = RSTRING_LEN(space_before);
1324
- if (len == 0) {
1325
- if (state->space_before) {
1326
- ruby_xfree(state->space_before);
1327
- state->space_before = NULL;
1328
- state->space_before_len = 0;
1329
- }
1330
- } else {
1331
- if (state->space_before) ruby_xfree(state->space_before);
1332
- state->space_before = fstrndup(RSTRING_PTR(space_before), len);
1333
- state->space_before_len = len;
1334
- }
1234
+ RB_OBJ_WRITE(self, &state->space_before, string_config(space_before));
1335
1235
  return Qnil;
1336
1236
  }
1337
1237
 
@@ -1344,7 +1244,7 @@ static VALUE cState_space_before_set(VALUE self, VALUE space_before)
1344
1244
  static VALUE cState_object_nl(VALUE self)
1345
1245
  {
1346
1246
  GET_STATE(self);
1347
- return state->object_nl ? rb_str_new(state->object_nl, state->object_nl_len) : rb_str_new2("");
1247
+ return state->object_nl ? state->object_nl : rb_str_freeze(rb_utf8_str_new("", 0));
1348
1248
  }
1349
1249
 
1350
1250
  /*
@@ -1355,20 +1255,8 @@ static VALUE cState_object_nl(VALUE self)
1355
1255
  */
1356
1256
  static VALUE cState_object_nl_set(VALUE self, VALUE object_nl)
1357
1257
  {
1358
- unsigned long len;
1359
1258
  GET_STATE(self);
1360
- Check_Type(object_nl, T_STRING);
1361
- len = RSTRING_LEN(object_nl);
1362
- if (len == 0) {
1363
- if (state->object_nl) {
1364
- ruby_xfree(state->object_nl);
1365
- state->object_nl = NULL;
1366
- }
1367
- } else {
1368
- if (state->object_nl) ruby_xfree(state->object_nl);
1369
- state->object_nl = fstrndup(RSTRING_PTR(object_nl), len);
1370
- state->object_nl_len = len;
1371
- }
1259
+ RB_OBJ_WRITE(self, &state->object_nl, string_config(object_nl));
1372
1260
  return Qnil;
1373
1261
  }
1374
1262
 
@@ -1380,7 +1268,7 @@ static VALUE cState_object_nl_set(VALUE self, VALUE object_nl)
1380
1268
  static VALUE cState_array_nl(VALUE self)
1381
1269
  {
1382
1270
  GET_STATE(self);
1383
- return state->array_nl ? rb_str_new(state->array_nl, state->array_nl_len) : rb_str_new2("");
1271
+ return state->array_nl ? state->array_nl : rb_str_freeze(rb_utf8_str_new("", 0));
1384
1272
  }
1385
1273
 
1386
1274
  /*
@@ -1390,20 +1278,8 @@ static VALUE cState_array_nl(VALUE self)
1390
1278
  */
1391
1279
  static VALUE cState_array_nl_set(VALUE self, VALUE array_nl)
1392
1280
  {
1393
- unsigned long len;
1394
1281
  GET_STATE(self);
1395
- Check_Type(array_nl, T_STRING);
1396
- len = RSTRING_LEN(array_nl);
1397
- if (len == 0) {
1398
- if (state->array_nl) {
1399
- ruby_xfree(state->array_nl);
1400
- state->array_nl = NULL;
1401
- }
1402
- } else {
1403
- if (state->array_nl) ruby_xfree(state->array_nl);
1404
- state->array_nl = fstrndup(RSTRING_PTR(array_nl), len);
1405
- state->array_nl_len = len;
1406
- }
1282
+ RB_OBJ_WRITE(self, &state->array_nl, string_config(array_nl));
1407
1283
  return Qnil;
1408
1284
  }
1409
1285
 
@@ -1432,6 +1308,11 @@ static VALUE cState_max_nesting(VALUE self)
1432
1308
  return LONG2FIX(state->max_nesting);
1433
1309
  }
1434
1310
 
1311
+ static long long_config(VALUE num)
1312
+ {
1313
+ return RTEST(num) ? FIX2LONG(num) : 0;
1314
+ }
1315
+
1435
1316
  /*
1436
1317
  * call-seq: max_nesting=(depth)
1437
1318
  *
@@ -1441,8 +1322,8 @@ static VALUE cState_max_nesting(VALUE self)
1441
1322
  static VALUE cState_max_nesting_set(VALUE self, VALUE depth)
1442
1323
  {
1443
1324
  GET_STATE(self);
1444
- Check_Type(depth, T_FIXNUM);
1445
- return state->max_nesting = FIX2LONG(depth);
1325
+ state->max_nesting = long_config(depth);
1326
+ return Qnil;
1446
1327
  }
1447
1328
 
1448
1329
  /*
@@ -1513,6 +1394,18 @@ static VALUE cState_allow_nan_p(VALUE self)
1513
1394
  return state->allow_nan ? Qtrue : Qfalse;
1514
1395
  }
1515
1396
 
1397
+ /*
1398
+ * call-seq: allow_nan=(enable)
1399
+ *
1400
+ * This sets whether or not to serialize NaN, Infinity, and -Infinity
1401
+ */
1402
+ static VALUE cState_allow_nan_set(VALUE self, VALUE enable)
1403
+ {
1404
+ GET_STATE(self);
1405
+ state->allow_nan = RTEST(enable);
1406
+ return Qnil;
1407
+ }
1408
+
1516
1409
  /*
1517
1410
  * call-seq: ascii_only?
1518
1411
  *
@@ -1525,6 +1418,18 @@ static VALUE cState_ascii_only_p(VALUE self)
1525
1418
  return state->ascii_only ? Qtrue : Qfalse;
1526
1419
  }
1527
1420
 
1421
+ /*
1422
+ * call-seq: ascii_only=(enable)
1423
+ *
1424
+ * This sets whether only ASCII characters should be generated.
1425
+ */
1426
+ static VALUE cState_ascii_only_set(VALUE self, VALUE enable)
1427
+ {
1428
+ GET_STATE(self);
1429
+ state->ascii_only = RTEST(enable);
1430
+ return Qnil;
1431
+ }
1432
+
1528
1433
  /*
1529
1434
  * call-seq: depth
1530
1435
  *
@@ -1545,8 +1450,7 @@ static VALUE cState_depth(VALUE self)
1545
1450
  static VALUE cState_depth_set(VALUE self, VALUE depth)
1546
1451
  {
1547
1452
  GET_STATE(self);
1548
- Check_Type(depth, T_FIXNUM);
1549
- state->depth = FIX2LONG(depth);
1453
+ state->depth = long_config(depth);
1550
1454
  return Qnil;
1551
1455
  }
1552
1456
 
@@ -1561,6 +1465,15 @@ static VALUE cState_buffer_initial_length(VALUE self)
1561
1465
  return LONG2FIX(state->buffer_initial_length);
1562
1466
  }
1563
1467
 
1468
+ static void buffer_initial_length_set(JSON_Generator_State *state, VALUE buffer_initial_length)
1469
+ {
1470
+ Check_Type(buffer_initial_length, T_FIXNUM);
1471
+ long initial_length = FIX2LONG(buffer_initial_length);
1472
+ if (initial_length > 0) {
1473
+ state->buffer_initial_length = initial_length;
1474
+ }
1475
+ }
1476
+
1564
1477
  /*
1565
1478
  * call-seq: buffer_initial_length=(length)
1566
1479
  *
@@ -1569,16 +1482,75 @@ static VALUE cState_buffer_initial_length(VALUE self)
1569
1482
  */
1570
1483
  static VALUE cState_buffer_initial_length_set(VALUE self, VALUE buffer_initial_length)
1571
1484
  {
1572
- long initial_length;
1573
1485
  GET_STATE(self);
1574
- Check_Type(buffer_initial_length, T_FIXNUM);
1575
- initial_length = FIX2LONG(buffer_initial_length);
1576
- if (initial_length > 0) {
1577
- state->buffer_initial_length = initial_length;
1578
- }
1486
+ buffer_initial_length_set(state, buffer_initial_length);
1579
1487
  return Qnil;
1580
1488
  }
1581
1489
 
1490
+ static int configure_state_i(VALUE key, VALUE val, VALUE _arg)
1491
+ {
1492
+ JSON_Generator_State *state = (JSON_Generator_State *)_arg;
1493
+
1494
+ if (key == sym_indent) { state->indent = string_config(val); }
1495
+ else if (key == sym_space) { state->space = string_config(val); }
1496
+ else if (key == sym_space_before) { state->space_before = string_config(val); }
1497
+ else if (key == sym_object_nl) { state->object_nl = string_config(val); }
1498
+ else if (key == sym_array_nl) { state->array_nl = string_config(val); }
1499
+ else if (key == sym_max_nesting) { state->max_nesting = long_config(val); }
1500
+ else if (key == sym_allow_nan) { state->allow_nan = RTEST(val); }
1501
+ else if (key == sym_ascii_only) { state->ascii_only = RTEST(val); }
1502
+ else if (key == sym_depth) { state->depth = long_config(val); }
1503
+ else if (key == sym_buffer_initial_length) { buffer_initial_length_set(state, val); }
1504
+ else if (key == sym_script_safe) { state->script_safe = RTEST(val); }
1505
+ else if (key == sym_escape_slash) { state->script_safe = RTEST(val); }
1506
+ else if (key == sym_strict) { state->strict = RTEST(val); }
1507
+ return ST_CONTINUE;
1508
+ }
1509
+
1510
+ static void configure_state(JSON_Generator_State *state, VALUE config)
1511
+ {
1512
+ if (!RTEST(config)) return;
1513
+
1514
+ Check_Type(config, T_HASH);
1515
+
1516
+ if (!RHASH_SIZE(config)) return;
1517
+
1518
+ // We assume in most cases few keys are set so it's faster to go over
1519
+ // the provided keys than to check all possible keys.
1520
+ rb_hash_foreach(config, configure_state_i, (VALUE)state);
1521
+ }
1522
+
1523
+ static VALUE cState_configure(VALUE self, VALUE opts)
1524
+ {
1525
+ GET_STATE(self);
1526
+ configure_state(state, opts);
1527
+ return self;
1528
+ }
1529
+
1530
+ static VALUE cState_m_generate(VALUE klass, VALUE obj, VALUE opts, VALUE io)
1531
+ {
1532
+ JSON_Generator_State state = {0};
1533
+ state_init(&state);
1534
+ configure_state(&state, opts);
1535
+
1536
+ char stack_buffer[FBUFFER_STACK_SIZE];
1537
+ FBuffer buffer = {
1538
+ .io = RTEST(io) ? io : Qfalse,
1539
+ };
1540
+ fbuffer_stack_init(&buffer, state.buffer_initial_length, stack_buffer, FBUFFER_STACK_SIZE);
1541
+
1542
+ struct generate_json_data data = {
1543
+ .buffer = &buffer,
1544
+ .vstate = Qfalse,
1545
+ .state = &state,
1546
+ .obj = obj,
1547
+ .func = generate_json,
1548
+ };
1549
+ rb_rescue(generate_json_try, (VALUE)&data, generate_json_rescue, (VALUE)&data);
1550
+
1551
+ return fbuffer_finalize(&buffer);
1552
+ }
1553
+
1582
1554
  /*
1583
1555
  *
1584
1556
  */
@@ -1592,18 +1564,22 @@ void Init_generator(void)
1592
1564
  rb_require("json/common");
1593
1565
 
1594
1566
  mJSON = rb_define_module("JSON");
1595
- mExt = rb_define_module_under(mJSON, "Ext");
1596
- mGenerator = rb_define_module_under(mExt, "Generator");
1567
+ VALUE mExt = rb_define_module_under(mJSON, "Ext");
1568
+ VALUE mGenerator = rb_define_module_under(mExt, "Generator");
1597
1569
 
1570
+ rb_global_variable(&eGeneratorError);
1598
1571
  eGeneratorError = rb_path2class("JSON::GeneratorError");
1572
+
1573
+ rb_global_variable(&eNestingError);
1599
1574
  eNestingError = rb_path2class("JSON::NestingError");
1600
- rb_gc_register_mark_object(eGeneratorError);
1601
- rb_gc_register_mark_object(eNestingError);
1602
1575
 
1603
1576
  cState = rb_define_class_under(mGenerator, "State", rb_cObject);
1604
1577
  rb_define_alloc_func(cState, cState_s_allocate);
1605
1578
  rb_define_singleton_method(cState, "from_state", cState_from_state_s, 1);
1606
1579
  rb_define_method(cState, "initialize", cState_initialize, -1);
1580
+ rb_define_alias(cState, "initialize", "initialize"); // avoid method redefinition warnings
1581
+ rb_define_private_method(cState, "_configure", cState_configure, 1);
1582
+
1607
1583
  rb_define_method(cState, "initialize_copy", cState_init_copy, 1);
1608
1584
  rb_define_method(cState, "indent", cState_indent, 0);
1609
1585
  rb_define_method(cState, "indent=", cState_indent_set, 1);
@@ -1628,76 +1604,88 @@ void Init_generator(void)
1628
1604
  rb_define_method(cState, "strict=", cState_strict_set, 1);
1629
1605
  rb_define_method(cState, "check_circular?", cState_check_circular_p, 0);
1630
1606
  rb_define_method(cState, "allow_nan?", cState_allow_nan_p, 0);
1607
+ rb_define_method(cState, "allow_nan=", cState_allow_nan_set, 1);
1631
1608
  rb_define_method(cState, "ascii_only?", cState_ascii_only_p, 0);
1609
+ rb_define_method(cState, "ascii_only=", cState_ascii_only_set, 1);
1632
1610
  rb_define_method(cState, "depth", cState_depth, 0);
1633
1611
  rb_define_method(cState, "depth=", cState_depth_set, 1);
1634
1612
  rb_define_method(cState, "buffer_initial_length", cState_buffer_initial_length, 0);
1635
1613
  rb_define_method(cState, "buffer_initial_length=", cState_buffer_initial_length_set, 1);
1636
- rb_define_method(cState, "configure", cState_configure, 1);
1637
- rb_define_alias(cState, "merge", "configure");
1638
- rb_define_method(cState, "to_h", cState_to_h, 0);
1639
- rb_define_alias(cState, "to_hash", "to_h");
1640
- rb_define_method(cState, "[]", cState_aref, 1);
1641
- rb_define_method(cState, "[]=", cState_aset, 2);
1642
- rb_define_method(cState, "generate", cState_generate, 1);
1643
-
1644
- mGeneratorMethods = rb_define_module_under(mGenerator, "GeneratorMethods");
1645
- mObject = rb_define_module_under(mGeneratorMethods, "Object");
1614
+ rb_define_private_method(cState, "_generate", cState_generate, 2);
1615
+
1616
+ rb_define_singleton_method(cState, "generate", cState_m_generate, 3);
1617
+
1618
+ VALUE mGeneratorMethods = rb_define_module_under(mGenerator, "GeneratorMethods");
1619
+
1620
+ VALUE mObject = rb_define_module_under(mGeneratorMethods, "Object");
1646
1621
  rb_define_method(mObject, "to_json", mObject_to_json, -1);
1647
- mHash = rb_define_module_under(mGeneratorMethods, "Hash");
1622
+
1623
+ VALUE mHash = rb_define_module_under(mGeneratorMethods, "Hash");
1648
1624
  rb_define_method(mHash, "to_json", mHash_to_json, -1);
1649
- mArray = rb_define_module_under(mGeneratorMethods, "Array");
1625
+
1626
+ VALUE mArray = rb_define_module_under(mGeneratorMethods, "Array");
1650
1627
  rb_define_method(mArray, "to_json", mArray_to_json, -1);
1628
+
1651
1629
  #ifdef RUBY_INTEGER_UNIFICATION
1652
- mInteger = rb_define_module_under(mGeneratorMethods, "Integer");
1630
+ VALUE mInteger = rb_define_module_under(mGeneratorMethods, "Integer");
1653
1631
  rb_define_method(mInteger, "to_json", mInteger_to_json, -1);
1654
1632
  #else
1655
- mFixnum = rb_define_module_under(mGeneratorMethods, "Fixnum");
1633
+ VALUE mFixnum = rb_define_module_under(mGeneratorMethods, "Fixnum");
1656
1634
  rb_define_method(mFixnum, "to_json", mFixnum_to_json, -1);
1657
- mBignum = rb_define_module_under(mGeneratorMethods, "Bignum");
1635
+
1636
+ VALUE mBignum = rb_define_module_under(mGeneratorMethods, "Bignum");
1658
1637
  rb_define_method(mBignum, "to_json", mBignum_to_json, -1);
1659
1638
  #endif
1660
- mFloat = rb_define_module_under(mGeneratorMethods, "Float");
1639
+ VALUE mFloat = rb_define_module_under(mGeneratorMethods, "Float");
1661
1640
  rb_define_method(mFloat, "to_json", mFloat_to_json, -1);
1662
- mString = rb_define_module_under(mGeneratorMethods, "String");
1641
+
1642
+ VALUE mString = rb_define_module_under(mGeneratorMethods, "String");
1663
1643
  rb_define_singleton_method(mString, "included", mString_included_s, 1);
1664
1644
  rb_define_method(mString, "to_json", mString_to_json, -1);
1665
1645
  rb_define_method(mString, "to_json_raw", mString_to_json_raw, -1);
1666
1646
  rb_define_method(mString, "to_json_raw_object", mString_to_json_raw_object, 0);
1647
+
1667
1648
  mString_Extend = rb_define_module_under(mString, "Extend");
1668
1649
  rb_define_method(mString_Extend, "json_create", mString_Extend_json_create, 1);
1669
- mTrueClass = rb_define_module_under(mGeneratorMethods, "TrueClass");
1650
+
1651
+ VALUE mTrueClass = rb_define_module_under(mGeneratorMethods, "TrueClass");
1670
1652
  rb_define_method(mTrueClass, "to_json", mTrueClass_to_json, -1);
1671
- mFalseClass = rb_define_module_under(mGeneratorMethods, "FalseClass");
1653
+
1654
+ VALUE mFalseClass = rb_define_module_under(mGeneratorMethods, "FalseClass");
1672
1655
  rb_define_method(mFalseClass, "to_json", mFalseClass_to_json, -1);
1673
- mNilClass = rb_define_module_under(mGeneratorMethods, "NilClass");
1656
+
1657
+ VALUE mNilClass = rb_define_module_under(mGeneratorMethods, "NilClass");
1674
1658
  rb_define_method(mNilClass, "to_json", mNilClass_to_json, -1);
1675
1659
 
1660
+ rb_global_variable(&Encoding_UTF_8);
1661
+ Encoding_UTF_8 = rb_const_get(rb_path2class("Encoding"), rb_intern("UTF_8"));
1662
+
1676
1663
  i_to_s = rb_intern("to_s");
1677
1664
  i_to_json = rb_intern("to_json");
1678
1665
  i_new = rb_intern("new");
1679
- i_indent = rb_intern("indent");
1680
- i_space = rb_intern("space");
1681
- i_space_before = rb_intern("space_before");
1682
- i_object_nl = rb_intern("object_nl");
1683
- i_array_nl = rb_intern("array_nl");
1684
- i_max_nesting = rb_intern("max_nesting");
1685
- i_script_safe = rb_intern("script_safe");
1686
- i_escape_slash = rb_intern("escape_slash");
1687
- i_strict = rb_intern("strict");
1688
- i_allow_nan = rb_intern("allow_nan");
1689
- i_ascii_only = rb_intern("ascii_only");
1690
- i_depth = rb_intern("depth");
1691
- i_buffer_initial_length = rb_intern("buffer_initial_length");
1692
1666
  i_pack = rb_intern("pack");
1693
1667
  i_unpack = rb_intern("unpack");
1694
1668
  i_create_id = rb_intern("create_id");
1695
1669
  i_extend = rb_intern("extend");
1696
- i_key_p = rb_intern("key?");
1697
- i_aref = rb_intern("[]");
1698
- i_send = rb_intern("__send__");
1699
- i_respond_to_p = rb_intern("respond_to?");
1700
- i_match = rb_intern("match");
1701
- i_keys = rb_intern("keys");
1702
- i_dup = rb_intern("dup");
1670
+ i_encode = rb_intern("encode");
1671
+
1672
+ sym_indent = ID2SYM(rb_intern("indent"));
1673
+ sym_space = ID2SYM(rb_intern("space"));
1674
+ sym_space_before = ID2SYM(rb_intern("space_before"));
1675
+ sym_object_nl = ID2SYM(rb_intern("object_nl"));
1676
+ sym_array_nl = ID2SYM(rb_intern("array_nl"));
1677
+ sym_max_nesting = ID2SYM(rb_intern("max_nesting"));
1678
+ sym_allow_nan = ID2SYM(rb_intern("allow_nan"));
1679
+ sym_ascii_only = ID2SYM(rb_intern("ascii_only"));
1680
+ sym_depth = ID2SYM(rb_intern("depth"));
1681
+ sym_buffer_initial_length = ID2SYM(rb_intern("buffer_initial_length"));
1682
+ sym_script_safe = ID2SYM(rb_intern("script_safe"));
1683
+ sym_escape_slash = ID2SYM(rb_intern("escape_slash"));
1684
+ sym_strict = ID2SYM(rb_intern("strict"));
1685
+
1686
+ usascii_encindex = rb_usascii_encindex();
1687
+ utf8_encindex = rb_utf8_encindex();
1688
+ binary_encindex = rb_ascii8bit_encindex();
1689
+
1690
+ rb_require("json/ext/generator/state");
1703
1691
  }