json 2.7.2 → 2.8.2

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