json 2.7.5 → 2.9.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,5 +1,309 @@
1
+ #include "ruby.h"
1
2
  #include "../fbuffer/fbuffer.h"
2
- #include "parser.h"
3
+
4
+ static VALUE mJSON, mExt, cParser, eNestingError, Encoding_UTF_8;
5
+ static VALUE CNaN, CInfinity, CMinusInfinity;
6
+
7
+ static ID i_json_creatable_p, i_json_create, i_create_id,
8
+ i_chr, i_deep_const_get, i_match, i_aset, i_aref,
9
+ i_leftshift, i_new, i_try_convert, i_uminus, i_encode;
10
+
11
+ static VALUE sym_max_nesting, sym_allow_nan, sym_allow_trailing_comma, sym_symbolize_names, sym_freeze,
12
+ sym_create_additions, sym_create_id, sym_object_class, sym_array_class,
13
+ sym_decimal_class, sym_match_string;
14
+
15
+ static int binary_encindex;
16
+ static int utf8_encindex;
17
+
18
+ #ifdef HAVE_RB_CATEGORY_WARN
19
+ # define json_deprecated(message) rb_category_warn(RB_WARN_CATEGORY_DEPRECATED, message)
20
+ #else
21
+ # define json_deprecated(message) rb_warn(message)
22
+ #endif
23
+
24
+ static const char deprecated_create_additions_warning[] =
25
+ "JSON.load implicit support for `create_additions: true` is deprecated "
26
+ "and will be removed in 3.0, use JSON.unsafe_load or explicitly "
27
+ "pass `create_additions: true`";
28
+
29
+ #ifndef HAVE_RB_HASH_BULK_INSERT
30
+ // For TruffleRuby
31
+ void rb_hash_bulk_insert(long count, const VALUE *pairs, VALUE hash)
32
+ {
33
+ long index = 0;
34
+ while (index < count) {
35
+ VALUE name = pairs[index++];
36
+ VALUE value = pairs[index++];
37
+ rb_hash_aset(hash, name, value);
38
+ }
39
+ RB_GC_GUARD(hash);
40
+ }
41
+ #endif
42
+
43
+ /* name cache */
44
+
45
+ #include <string.h>
46
+ #include <ctype.h>
47
+
48
+ // Object names are likely to be repeated, and are frozen.
49
+ // As such we can re-use them if we keep a cache of the ones we've seen so far,
50
+ // and save much more expensive lookups into the global fstring table.
51
+ // This cache implementation is deliberately simple, as we're optimizing for compactness,
52
+ // to be able to fit safely on the stack.
53
+ // As such, binary search into a sorted array gives a good tradeoff between compactness and
54
+ // performance.
55
+ #define JSON_RVALUE_CACHE_CAPA 63
56
+ typedef struct rvalue_cache_struct {
57
+ int length;
58
+ VALUE entries[JSON_RVALUE_CACHE_CAPA];
59
+ } rvalue_cache;
60
+
61
+ static rb_encoding *enc_utf8;
62
+
63
+ #define JSON_RVALUE_CACHE_MAX_ENTRY_LENGTH 55
64
+
65
+ static inline VALUE build_interned_string(const char *str, const long length)
66
+ {
67
+ # ifdef HAVE_RB_ENC_INTERNED_STR
68
+ return rb_enc_interned_str(str, length, enc_utf8);
69
+ # else
70
+ VALUE rstring = rb_utf8_str_new(str, length);
71
+ return rb_funcall(rb_str_freeze(rstring), i_uminus, 0);
72
+ # endif
73
+ }
74
+
75
+ static inline VALUE build_symbol(const char *str, const long length)
76
+ {
77
+ return rb_str_intern(build_interned_string(str, length));
78
+ }
79
+
80
+ static void rvalue_cache_insert_at(rvalue_cache *cache, int index, VALUE rstring)
81
+ {
82
+ MEMMOVE(&cache->entries[index + 1], &cache->entries[index], VALUE, cache->length - index);
83
+ cache->length++;
84
+ cache->entries[index] = rstring;
85
+ }
86
+
87
+ static inline int rstring_cache_cmp(const char *str, const long length, VALUE rstring)
88
+ {
89
+ long rstring_length = RSTRING_LEN(rstring);
90
+ if (length == rstring_length) {
91
+ return memcmp(str, RSTRING_PTR(rstring), length);
92
+ } else {
93
+ return (int)(length - rstring_length);
94
+ }
95
+ }
96
+
97
+ static VALUE rstring_cache_fetch(rvalue_cache *cache, const char *str, const long length)
98
+ {
99
+ if (RB_UNLIKELY(length > JSON_RVALUE_CACHE_MAX_ENTRY_LENGTH)) {
100
+ // Common names aren't likely to be very long. So we just don't
101
+ // cache names above an arbitrary threshold.
102
+ return Qfalse;
103
+ }
104
+
105
+ if (RB_UNLIKELY(!isalpha(str[0]))) {
106
+ // Simple heuristic, if the first character isn't a letter,
107
+ // we're much less likely to see this string again.
108
+ // We mostly want to cache strings that are likely to be repeated.
109
+ return Qfalse;
110
+ }
111
+
112
+ int low = 0;
113
+ int high = cache->length - 1;
114
+ int mid = 0;
115
+ int last_cmp = 0;
116
+
117
+ while (low <= high) {
118
+ mid = (high + low) >> 1;
119
+ VALUE entry = cache->entries[mid];
120
+ last_cmp = rstring_cache_cmp(str, length, entry);
121
+
122
+ if (last_cmp == 0) {
123
+ return entry;
124
+ } else if (last_cmp > 0) {
125
+ low = mid + 1;
126
+ } else {
127
+ high = mid - 1;
128
+ }
129
+ }
130
+
131
+ if (RB_UNLIKELY(memchr(str, '\\', length))) {
132
+ // We assume the overwhelming majority of names don't need to be escaped.
133
+ // But if they do, we have to fallback to the slow path.
134
+ return Qfalse;
135
+ }
136
+
137
+ VALUE rstring = build_interned_string(str, length);
138
+
139
+ if (cache->length < JSON_RVALUE_CACHE_CAPA) {
140
+ if (last_cmp > 0) {
141
+ mid += 1;
142
+ }
143
+
144
+ rvalue_cache_insert_at(cache, mid, rstring);
145
+ }
146
+ return rstring;
147
+ }
148
+
149
+ static VALUE rsymbol_cache_fetch(rvalue_cache *cache, const char *str, const long length)
150
+ {
151
+ if (RB_UNLIKELY(length > JSON_RVALUE_CACHE_MAX_ENTRY_LENGTH)) {
152
+ // Common names aren't likely to be very long. So we just don't
153
+ // cache names above an arbitrary threshold.
154
+ return Qfalse;
155
+ }
156
+
157
+ if (RB_UNLIKELY(!isalpha(str[0]))) {
158
+ // Simple heuristic, if the first character isn't a letter,
159
+ // we're much less likely to see this string again.
160
+ // We mostly want to cache strings that are likely to be repeated.
161
+ return Qfalse;
162
+ }
163
+
164
+ int low = 0;
165
+ int high = cache->length - 1;
166
+ int mid = 0;
167
+ int last_cmp = 0;
168
+
169
+ while (low <= high) {
170
+ mid = (high + low) >> 1;
171
+ VALUE entry = cache->entries[mid];
172
+ last_cmp = rstring_cache_cmp(str, length, rb_sym2str(entry));
173
+
174
+ if (last_cmp == 0) {
175
+ return entry;
176
+ } else if (last_cmp > 0) {
177
+ low = mid + 1;
178
+ } else {
179
+ high = mid - 1;
180
+ }
181
+ }
182
+
183
+ if (RB_UNLIKELY(memchr(str, '\\', length))) {
184
+ // We assume the overwhelming majority of names don't need to be escaped.
185
+ // But if they do, we have to fallback to the slow path.
186
+ return Qfalse;
187
+ }
188
+
189
+ VALUE rsymbol = build_symbol(str, length);
190
+
191
+ if (cache->length < JSON_RVALUE_CACHE_CAPA) {
192
+ if (last_cmp > 0) {
193
+ mid += 1;
194
+ }
195
+
196
+ rvalue_cache_insert_at(cache, mid, rsymbol);
197
+ }
198
+ return rsymbol;
199
+ }
200
+
201
+ /* rvalue stack */
202
+
203
+ #define RVALUE_STACK_INITIAL_CAPA 128
204
+
205
+ enum rvalue_stack_type {
206
+ RVALUE_STACK_HEAP_ALLOCATED = 0,
207
+ RVALUE_STACK_STACK_ALLOCATED = 1,
208
+ };
209
+
210
+ typedef struct rvalue_stack_struct {
211
+ enum rvalue_stack_type type;
212
+ long capa;
213
+ long head;
214
+ VALUE *ptr;
215
+ } rvalue_stack;
216
+
217
+ static rvalue_stack *rvalue_stack_spill(rvalue_stack *old_stack, VALUE *handle, rvalue_stack **stack_ref);
218
+
219
+ static rvalue_stack *rvalue_stack_grow(rvalue_stack *stack, VALUE *handle, rvalue_stack **stack_ref)
220
+ {
221
+ long required = stack->capa * 2;
222
+
223
+ if (stack->type == RVALUE_STACK_STACK_ALLOCATED) {
224
+ stack = rvalue_stack_spill(stack, handle, stack_ref);
225
+ } else {
226
+ REALLOC_N(stack->ptr, VALUE, required);
227
+ stack->capa = required;
228
+ }
229
+ return stack;
230
+ }
231
+
232
+ static void rvalue_stack_push(rvalue_stack *stack, VALUE value, VALUE *handle, rvalue_stack **stack_ref)
233
+ {
234
+ if (RB_UNLIKELY(stack->head >= stack->capa)) {
235
+ stack = rvalue_stack_grow(stack, handle, stack_ref);
236
+ }
237
+ stack->ptr[stack->head] = value;
238
+ stack->head++;
239
+ }
240
+
241
+ static inline VALUE *rvalue_stack_peek(rvalue_stack *stack, long count)
242
+ {
243
+ return stack->ptr + (stack->head - count);
244
+ }
245
+
246
+ static inline void rvalue_stack_pop(rvalue_stack *stack, long count)
247
+ {
248
+ stack->head -= count;
249
+ }
250
+
251
+ static void rvalue_stack_mark(void *ptr)
252
+ {
253
+ rvalue_stack *stack = (rvalue_stack *)ptr;
254
+ long index;
255
+ for (index = 0; index < stack->head; index++) {
256
+ rb_gc_mark(stack->ptr[index]);
257
+ }
258
+ }
259
+
260
+ static void rvalue_stack_free(void *ptr)
261
+ {
262
+ rvalue_stack *stack = (rvalue_stack *)ptr;
263
+ if (stack) {
264
+ ruby_xfree(stack->ptr);
265
+ ruby_xfree(stack);
266
+ }
267
+ }
268
+
269
+ static size_t rvalue_stack_memsize(const void *ptr)
270
+ {
271
+ const rvalue_stack *stack = (const rvalue_stack *)ptr;
272
+ return sizeof(rvalue_stack) + sizeof(VALUE) * stack->capa;
273
+ }
274
+
275
+ static const rb_data_type_t JSON_Parser_rvalue_stack_type = {
276
+ "JSON::Ext::Parser/rvalue_stack",
277
+ {
278
+ .dmark = rvalue_stack_mark,
279
+ .dfree = rvalue_stack_free,
280
+ .dsize = rvalue_stack_memsize,
281
+ },
282
+ 0, 0,
283
+ RUBY_TYPED_FREE_IMMEDIATELY,
284
+ };
285
+
286
+ static rvalue_stack *rvalue_stack_spill(rvalue_stack *old_stack, VALUE *handle, rvalue_stack **stack_ref)
287
+ {
288
+ rvalue_stack *stack;
289
+ *handle = TypedData_Make_Struct(0, rvalue_stack, &JSON_Parser_rvalue_stack_type, stack);
290
+ *stack_ref = stack;
291
+ MEMCPY(stack, old_stack, rvalue_stack, 1);
292
+
293
+ stack->capa = old_stack->capa << 1;
294
+ stack->ptr = ALLOC_N(VALUE, stack->capa);
295
+ stack->type = RVALUE_STACK_HEAP_ALLOCATED;
296
+ MEMCPY(stack->ptr, old_stack->ptr, VALUE, old_stack->head);
297
+ return stack;
298
+ }
299
+
300
+ static void rvalue_stack_eagerly_release(VALUE handle)
301
+ {
302
+ rvalue_stack *stack;
303
+ TypedData_Get_Struct(handle, rvalue_stack, &JSON_Parser_rvalue_stack_type, stack);
304
+ RTYPEDDATA_DATA(handle) = NULL;
305
+ rvalue_stack_free(stack);
306
+ }
3
307
 
4
308
  /* unicode */
5
309
 
@@ -67,6 +371,58 @@ static int convert_UTF32_to_UTF8(char *buf, uint32_t ch)
67
371
  return len;
68
372
  }
69
373
 
374
+ typedef struct JSON_ParserStruct {
375
+ VALUE Vsource;
376
+ char *source;
377
+ long len;
378
+ char *memo;
379
+ VALUE create_id;
380
+ VALUE object_class;
381
+ VALUE array_class;
382
+ VALUE decimal_class;
383
+ VALUE match_string;
384
+ FBuffer fbuffer;
385
+ int in_array;
386
+ int max_nesting;
387
+ bool allow_nan;
388
+ bool allow_trailing_comma;
389
+ bool parsing_name;
390
+ bool symbolize_names;
391
+ bool freeze;
392
+ bool create_additions;
393
+ bool deprecated_create_additions;
394
+ rvalue_cache name_cache;
395
+ rvalue_stack *stack;
396
+ VALUE stack_handle;
397
+ } JSON_Parser;
398
+
399
+ #define GET_PARSER \
400
+ GET_PARSER_INIT; \
401
+ if (!json->Vsource) rb_raise(rb_eTypeError, "uninitialized instance")
402
+
403
+ #define GET_PARSER_INIT \
404
+ JSON_Parser *json; \
405
+ TypedData_Get_Struct(self, JSON_Parser, &JSON_Parser_type, json)
406
+
407
+ #define MinusInfinity "-Infinity"
408
+ #define EVIL 0x666
409
+
410
+ static const rb_data_type_t JSON_Parser_type;
411
+ static char *JSON_parse_string(JSON_Parser *json, char *p, char *pe, VALUE *result);
412
+ static char *JSON_parse_object(JSON_Parser *json, char *p, char *pe, VALUE *result, int current_nesting);
413
+ static char *JSON_parse_value(JSON_Parser *json, char *p, char *pe, VALUE *result, int current_nesting);
414
+ static char *JSON_parse_number(JSON_Parser *json, char *p, char *pe, VALUE *result);
415
+ static char *JSON_parse_array(JSON_Parser *json, char *p, char *pe, VALUE *result, int current_nesting);
416
+
417
+
418
+ #ifndef HAVE_STRNLEN
419
+ static size_t strnlen(const char *s, size_t maxlen)
420
+ {
421
+ char *p;
422
+ return ((p = memchr(s, '\0', maxlen)) ? p - s : maxlen);
423
+ }
424
+ #endif
425
+
70
426
  #define PARSE_ERROR_FRAGMENT_LEN 32
71
427
  #ifdef RBIMPL_ATTR_NORETURN
72
428
  RBIMPL_ATTR_NORETURN()
@@ -84,21 +440,9 @@ static void raise_parse_error(const char *format, const char *start)
84
440
  ptr = buffer;
85
441
  }
86
442
 
87
- rb_enc_raise(rb_utf8_encoding(), rb_path2class("JSON::ParserError"), format, ptr);
443
+ rb_enc_raise(enc_utf8, rb_path2class("JSON::ParserError"), format, ptr);
88
444
  }
89
445
 
90
- static VALUE mJSON, mExt, cParser, eNestingError;
91
- static VALUE CNaN, CInfinity, CMinusInfinity;
92
-
93
- static ID i_json_creatable_p, i_json_create, i_create_id, i_create_additions,
94
- i_chr, i_max_nesting, i_allow_nan, i_symbolize_names,
95
- i_object_class, i_array_class, i_decimal_class,
96
- i_deep_const_get, i_match, i_match_string, i_aset, i_aref,
97
- i_leftshift, i_new, i_try_convert, i_freeze, i_uminus;
98
-
99
- static int binary_encindex;
100
- static int utf8_encindex;
101
-
102
446
 
103
447
  %%{
104
448
  machine JSON_common;
@@ -135,27 +479,25 @@ static int utf8_encindex;
135
479
  write data;
136
480
 
137
481
  action parse_value {
138
- VALUE v = Qnil;
139
- char *np = JSON_parse_value(json, fpc, pe, &v, current_nesting);
482
+ char *np = JSON_parse_value(json, fpc, pe, result, current_nesting);
140
483
  if (np == NULL) {
141
484
  fhold; fbreak;
142
485
  } else {
143
- if (NIL_P(json->object_class)) {
144
- OBJ_FREEZE(last_name);
145
- rb_hash_aset(*result, last_name, v);
146
- } else {
147
- rb_funcall(*result, i_aset, 2, last_name, v);
148
- }
149
486
  fexec np;
150
487
  }
151
488
  }
152
489
 
490
+ action allow_trailing_comma { json->allow_trailing_comma }
491
+
153
492
  action parse_name {
154
493
  char *np;
155
- json->parsing_name = 1;
156
- np = JSON_parse_string(json, fpc, pe, &last_name);
157
- json->parsing_name = 0;
158
- if (np == NULL) { fhold; fbreak; } else fexec np;
494
+ json->parsing_name = true;
495
+ np = JSON_parse_string(json, fpc, pe, result);
496
+ json->parsing_name = false;
497
+ if (np == NULL) { fhold; fbreak; } else {
498
+ PUSH(*result);
499
+ fexec np;
500
+ }
159
501
  }
160
502
 
161
503
  action exit { fhold; fbreak; }
@@ -165,37 +507,64 @@ static int utf8_encindex;
165
507
 
166
508
  main := (
167
509
  begin_object
168
- (pair (next_pair)*)? ignore*
510
+ (pair (next_pair)*((ignore* value_separator) when allow_trailing_comma)?)? ignore*
169
511
  end_object
170
512
  ) @exit;
171
513
  }%%
172
514
 
515
+ #define PUSH(result) rvalue_stack_push(json->stack, result, &json->stack_handle, &json->stack)
516
+
173
517
  static char *JSON_parse_object(JSON_Parser *json, char *p, char *pe, VALUE *result, int current_nesting)
174
518
  {
175
519
  int cs = EVIL;
176
- VALUE last_name = Qnil;
177
- VALUE object_class = json->object_class;
178
520
 
179
521
  if (json->max_nesting && current_nesting > json->max_nesting) {
180
522
  rb_raise(eNestingError, "nesting of %d is too deep", current_nesting);
181
523
  }
182
524
 
183
- *result = NIL_P(object_class) ? rb_hash_new() : rb_class_new_instance(0, 0, object_class);
525
+ long stack_head = json->stack->head;
184
526
 
185
527
  %% write init;
186
528
  %% write exec;
187
529
 
188
530
  if (cs >= JSON_object_first_final) {
189
- if (json->create_additions) {
531
+ long count = json->stack->head - stack_head;
532
+
533
+ if (RB_UNLIKELY(json->object_class)) {
534
+ VALUE object = rb_class_new_instance(0, 0, json->object_class);
535
+ long index = 0;
536
+ VALUE *items = rvalue_stack_peek(json->stack, count);
537
+ while (index < count) {
538
+ VALUE name = items[index++];
539
+ VALUE value = items[index++];
540
+ rb_funcall(object, i_aset, 2, name, value);
541
+ }
542
+ *result = object;
543
+ } else {
544
+ VALUE hash;
545
+ #ifdef HAVE_RB_HASH_NEW_CAPA
546
+ hash = rb_hash_new_capa(count >> 1);
547
+ #else
548
+ hash = rb_hash_new();
549
+ #endif
550
+ rb_hash_bulk_insert(count, rvalue_stack_peek(json->stack, count), hash);
551
+ *result = hash;
552
+ }
553
+ rvalue_stack_pop(json->stack, count);
554
+
555
+ if (RB_UNLIKELY(json->create_additions)) {
190
556
  VALUE klassname;
191
- if (NIL_P(json->object_class)) {
192
- klassname = rb_hash_aref(*result, json->create_id);
557
+ if (json->object_class) {
558
+ klassname = rb_funcall(*result, i_aref, 1, json->create_id);
193
559
  } else {
194
- klassname = rb_funcall(*result, i_aref, 1, json->create_id);
560
+ klassname = rb_hash_aref(*result, json->create_id);
195
561
  }
196
562
  if (!NIL_P(klassname)) {
197
563
  VALUE klass = rb_funcall(mJSON, i_deep_const_get, 1, klassname);
198
564
  if (RTEST(rb_funcall(klass, i_json_creatable_p, 0))) {
565
+ if (json->deprecated_create_additions) {
566
+ json_deprecated(deprecated_create_additions_warning);
567
+ }
199
568
  *result = rb_funcall(klass, i_json_create, 1, *result);
200
569
  }
201
570
  }
@@ -206,7 +575,6 @@ static char *JSON_parse_object(JSON_Parser *json, char *p, char *pe, VALUE *resu
206
575
  }
207
576
  }
208
577
 
209
-
210
578
  %%{
211
579
  machine JSON_value;
212
580
  include JSON_common;
@@ -238,7 +606,12 @@ static char *JSON_parse_object(JSON_Parser *json, char *p, char *pe, VALUE *resu
238
606
  }
239
607
  action parse_string {
240
608
  char *np = JSON_parse_string(json, fpc, pe, result);
241
- if (np == NULL) { fhold; fbreak; } else fexec np;
609
+ if (np == NULL) {
610
+ fhold;
611
+ fbreak;
612
+ } else {
613
+ fexec np;
614
+ }
242
615
  }
243
616
 
244
617
  action parse_number {
@@ -252,16 +625,18 @@ static char *JSON_parse_object(JSON_Parser *json, char *p, char *pe, VALUE *resu
252
625
  raise_parse_error("unexpected token at '%s'", p);
253
626
  }
254
627
  }
255
- np = JSON_parse_float(json, fpc, pe, result);
256
- if (np != NULL) fexec np;
257
- np = JSON_parse_integer(json, fpc, pe, result);
258
- if (np != NULL) fexec np;
628
+ np = JSON_parse_number(json, fpc, pe, result);
629
+ if (np != NULL) {
630
+ fexec np;
631
+ }
259
632
  fhold; fbreak;
260
633
  }
261
634
 
262
635
  action parse_array {
263
636
  char *np;
637
+ json->in_array++;
264
638
  np = JSON_parse_array(json, fpc, pe, result, current_nesting + 1);
639
+ json->in_array--;
265
640
  if (np == NULL) { fhold; fbreak; } else fexec np;
266
641
  }
267
642
 
@@ -279,10 +654,10 @@ main := ignore* (
279
654
  Vtrue @parse_true |
280
655
  VNaN @parse_nan |
281
656
  VInfinity @parse_infinity |
282
- begin_number >parse_number |
283
- begin_string >parse_string |
284
- begin_array >parse_array |
285
- begin_object >parse_object
657
+ begin_number @parse_number |
658
+ begin_string @parse_string |
659
+ begin_array @parse_array |
660
+ begin_object @parse_object
286
661
  ) ignore* %*exit;
287
662
  }%%
288
663
 
@@ -298,6 +673,7 @@ static char *JSON_parse_value(JSON_Parser *json, char *p, char *pe, VALUE *resul
298
673
  }
299
674
 
300
675
  if (cs >= JSON_value_first_final) {
676
+ PUSH(*result);
301
677
  return p;
302
678
  } else {
303
679
  return NULL;
@@ -314,24 +690,40 @@ static char *JSON_parse_value(JSON_Parser *json, char *p, char *pe, VALUE *resul
314
690
  main := '-'? ('0' | [1-9][0-9]*) (^[0-9]? @exit);
315
691
  }%%
316
692
 
317
- static char *JSON_parse_integer(JSON_Parser *json, char *p, char *pe, VALUE *result)
693
+ #define MAX_FAST_INTEGER_SIZE 18
694
+ static inline VALUE fast_parse_integer(char *p, char *pe)
318
695
  {
319
- int cs = EVIL;
696
+ bool negative = false;
697
+ if (*p == '-') {
698
+ negative = true;
699
+ p++;
700
+ }
320
701
 
321
- %% write init;
322
- json->memo = p;
323
- %% write exec;
702
+ long long memo = 0;
703
+ while (p < pe) {
704
+ memo *= 10;
705
+ memo += *p - '0';
706
+ p++;
707
+ }
708
+
709
+ if (negative) {
710
+ memo = -memo;
711
+ }
712
+ return LL2NUM(memo);
713
+ }
324
714
 
325
- if (cs >= JSON_integer_first_final) {
715
+ static char *JSON_decode_integer(JSON_Parser *json, char *p, VALUE *result)
716
+ {
326
717
  long len = p - json->memo;
327
- fbuffer_clear(json->fbuffer);
328
- fbuffer_append(json->fbuffer, json->memo, len);
329
- fbuffer_append_char(json->fbuffer, '\0');
330
- *result = rb_cstr2inum(FBUFFER_PTR(json->fbuffer), 10);
718
+ if (RB_LIKELY(len < MAX_FAST_INTEGER_SIZE)) {
719
+ *result = fast_parse_integer(json->memo, p);
720
+ } else {
721
+ fbuffer_clear(&json->fbuffer);
722
+ fbuffer_append(&json->fbuffer, json->memo, len);
723
+ fbuffer_append_char(&json->fbuffer, '\0');
724
+ *result = rb_cstr2inum(FBUFFER_PTR(&json->fbuffer), 10);
725
+ }
331
726
  return p + 1;
332
- } else {
333
- return NULL;
334
- }
335
727
  }
336
728
 
337
729
  %%{
@@ -341,25 +733,31 @@ static char *JSON_parse_integer(JSON_Parser *json, char *p, char *pe, VALUE *res
341
733
  write data;
342
734
 
343
735
  action exit { fhold; fbreak; }
736
+ action isFloat { is_float = true; }
344
737
 
345
738
  main := '-'? (
346
- (('0' | [1-9][0-9]*) '.' [0-9]+ ([Ee] [+\-]?[0-9]+)?)
347
- | (('0' | [1-9][0-9]*) ([Ee] [+\-]?[0-9]+))
348
- ) (^[0-9Ee.\-]? @exit );
739
+ (('0' | [1-9][0-9]*)
740
+ ((('.' [0-9]+ ([Ee] [+\-]?[0-9]+)?) |
741
+ ([Ee] [+\-]?[0-9]+)) > isFloat)?
742
+ ) (^[0-9Ee.\-]? @exit ));
349
743
  }%%
350
744
 
351
- static char *JSON_parse_float(JSON_Parser *json, char *p, char *pe, VALUE *result)
745
+ static char *JSON_parse_number(JSON_Parser *json, char *p, char *pe, VALUE *result)
352
746
  {
353
747
  int cs = EVIL;
748
+ bool is_float = false;
354
749
 
355
750
  %% write init;
356
751
  json->memo = p;
357
752
  %% write exec;
358
753
 
359
754
  if (cs >= JSON_float_first_final) {
755
+ if (!is_float) {
756
+ return JSON_decode_integer(json, p, result);
757
+ }
360
758
  VALUE mod = Qnil;
361
759
  ID method_id = 0;
362
- if (!NIL_P(json->decimal_class)) {
760
+ if (json->decimal_class) {
363
761
  if (rb_respond_to(json->decimal_class, i_try_convert)) {
364
762
  mod = json->decimal_class;
365
763
  method_id = i_try_convert;
@@ -388,15 +786,15 @@ static char *JSON_parse_float(JSON_Parser *json, char *p, char *pe, VALUE *resul
388
786
  }
389
787
 
390
788
  long len = p - json->memo;
391
- fbuffer_clear(json->fbuffer);
392
- fbuffer_append(json->fbuffer, json->memo, len);
393
- fbuffer_append_char(json->fbuffer, '\0');
789
+ fbuffer_clear(&json->fbuffer);
790
+ fbuffer_append(&json->fbuffer, json->memo, len);
791
+ fbuffer_append_char(&json->fbuffer, '\0');
394
792
 
395
793
  if (method_id) {
396
- VALUE text = rb_str_new2(FBUFFER_PTR(json->fbuffer));
794
+ VALUE text = rb_str_new2(FBUFFER_PTR(&json->fbuffer));
397
795
  *result = rb_funcallv(mod, method_id, 1, &text);
398
796
  } else {
399
- *result = DBL2NUM(rb_cstr_to_dbl(FBUFFER_PTR(json->fbuffer), 1));
797
+ *result = DBL2NUM(rb_cstr_to_dbl(FBUFFER_PTR(&json->fbuffer), 1));
400
798
  }
401
799
 
402
800
  return p + 1;
@@ -418,39 +816,51 @@ static char *JSON_parse_float(JSON_Parser *json, char *p, char *pe, VALUE *resul
418
816
  if (np == NULL) {
419
817
  fhold; fbreak;
420
818
  } else {
421
- if (NIL_P(json->array_class)) {
422
- rb_ary_push(*result, v);
423
- } else {
424
- rb_funcall(*result, i_leftshift, 1, v);
425
- }
426
819
  fexec np;
427
820
  }
428
821
  }
429
822
 
823
+ action allow_trailing_comma { json->allow_trailing_comma }
824
+
430
825
  action exit { fhold; fbreak; }
431
826
 
432
827
  next_element = value_separator ignore* begin_value >parse_value;
433
828
 
434
829
  main := begin_array ignore*
435
830
  ((begin_value >parse_value ignore*)
436
- (ignore* next_element ignore*)*)?
831
+ (ignore* next_element ignore*)*((value_separator ignore*) when allow_trailing_comma)?)?
437
832
  end_array @exit;
438
833
  }%%
439
834
 
440
835
  static char *JSON_parse_array(JSON_Parser *json, char *p, char *pe, VALUE *result, int current_nesting)
441
836
  {
442
837
  int cs = EVIL;
443
- VALUE array_class = json->array_class;
444
838
 
445
839
  if (json->max_nesting && current_nesting > json->max_nesting) {
446
840
  rb_raise(eNestingError, "nesting of %d is too deep", current_nesting);
447
841
  }
448
- *result = NIL_P(array_class) ? rb_ary_new() : rb_class_new_instance(0, 0, array_class);
842
+ long stack_head = json->stack->head;
449
843
 
450
844
  %% write init;
451
845
  %% write exec;
452
846
 
453
847
  if(cs >= JSON_array_first_final) {
848
+ long count = json->stack->head - stack_head;
849
+
850
+ if (RB_UNLIKELY(json->array_class)) {
851
+ VALUE array = rb_class_new_instance(0, 0, json->array_class);
852
+ VALUE *items = rvalue_stack_peek(json->stack, count);
853
+ long index;
854
+ for (index = 0; index < count; index++) {
855
+ rb_funcall(array, i_leftshift, 1, items[index]);
856
+ }
857
+ *result = array;
858
+ } else {
859
+ VALUE array = rb_ary_new_from_values(count, rvalue_stack_peek(json->stack, count));
860
+ *result = array;
861
+ }
862
+ rvalue_stack_pop(json->stack, count);
863
+
454
864
  return p + 1;
455
865
  } else {
456
866
  raise_parse_error("unexpected token at '%s'", p);
@@ -458,29 +868,81 @@ static char *JSON_parse_array(JSON_Parser *json, char *p, char *pe, VALUE *resul
458
868
  }
459
869
  }
460
870
 
461
- static const size_t MAX_STACK_BUFFER_SIZE = 128;
462
- static VALUE json_string_unescape(char *string, char *stringEnd, int intern, int symbolize)
871
+ static inline VALUE build_string(const char *start, const char *end, bool intern, bool symbolize)
872
+ {
873
+ if (symbolize) {
874
+ intern = true;
875
+ }
876
+ VALUE result;
877
+ # ifdef HAVE_RB_ENC_INTERNED_STR
878
+ if (intern) {
879
+ result = rb_enc_interned_str(start, (long)(end - start), enc_utf8);
880
+ } else {
881
+ result = rb_utf8_str_new(start, (long)(end - start));
882
+ }
883
+ # else
884
+ result = rb_utf8_str_new(start, (long)(end - start));
885
+ if (intern) {
886
+ result = rb_funcall(rb_str_freeze(result), i_uminus, 0);
887
+ }
888
+ # endif
889
+
890
+ if (symbolize) {
891
+ result = rb_str_intern(result);
892
+ }
893
+
894
+ return result;
895
+ }
896
+
897
+ static VALUE json_string_fastpath(JSON_Parser *json, char *string, char *stringEnd, bool is_name, bool intern, bool symbolize)
898
+ {
899
+ size_t bufferSize = stringEnd - string;
900
+
901
+ if (is_name && json->in_array) {
902
+ VALUE cached_key;
903
+ if (RB_UNLIKELY(symbolize)) {
904
+ cached_key = rsymbol_cache_fetch(&json->name_cache, string, bufferSize);
905
+ } else {
906
+ cached_key = rstring_cache_fetch(&json->name_cache, string, bufferSize);
907
+ }
908
+
909
+ if (RB_LIKELY(cached_key)) {
910
+ return cached_key;
911
+ }
912
+ }
913
+
914
+ return build_string(string, stringEnd, intern, symbolize);
915
+ }
916
+
917
+ static VALUE json_string_unescape(JSON_Parser *json, char *string, char *stringEnd, bool is_name, bool intern, bool symbolize)
463
918
  {
464
- VALUE result = Qnil;
465
919
  size_t bufferSize = stringEnd - string;
466
920
  char *p = string, *pe = string, *unescape, *bufferStart, *buffer;
467
921
  int unescape_len;
468
922
  char buf[4];
469
923
 
470
- if (bufferSize > MAX_STACK_BUFFER_SIZE) {
471
- # ifdef HAVE_RB_ENC_INTERNED_STR
472
- bufferStart = buffer = ALLOC_N(char, bufferSize ? bufferSize : 1);
473
- # else
474
- bufferStart = buffer = ALLOC_N(char, bufferSize);
475
- # endif
476
- } else {
477
- # ifdef HAVE_RB_ENC_INTERNED_STR
478
- bufferStart = buffer = ALLOCA_N(char, bufferSize ? bufferSize : 1);
479
- # else
480
- bufferStart = buffer = ALLOCA_N(char, bufferSize);
481
- # endif
924
+ if (is_name && json->in_array) {
925
+ VALUE cached_key;
926
+ if (RB_UNLIKELY(symbolize)) {
927
+ cached_key = rsymbol_cache_fetch(&json->name_cache, string, bufferSize);
928
+ } else {
929
+ cached_key = rstring_cache_fetch(&json->name_cache, string, bufferSize);
930
+ }
931
+
932
+ if (RB_LIKELY(cached_key)) {
933
+ return cached_key;
934
+ }
935
+ }
936
+
937
+ pe = memchr(p, '\\', bufferSize);
938
+ if (RB_UNLIKELY(pe == NULL)) {
939
+ return build_string(string, stringEnd, intern, symbolize);
482
940
  }
483
941
 
942
+ VALUE result = rb_str_buf_new(bufferSize);
943
+ rb_enc_associate_index(result, utf8_encindex);
944
+ buffer = bufferStart = RSTRING_PTR(result);
945
+
484
946
  while (pe < stringEnd) {
485
947
  if (*pe == '\\') {
486
948
  unescape = (char *) "?";
@@ -513,9 +975,6 @@ static VALUE json_string_unescape(char *string, char *stringEnd, int intern, int
513
975
  break;
514
976
  case 'u':
515
977
  if (pe > stringEnd - 4) {
516
- if (bufferSize > MAX_STACK_BUFFER_SIZE) {
517
- ruby_xfree(bufferStart);
518
- }
519
978
  raise_parse_error("incomplete unicode character escape sequence at '%s'", p);
520
979
  } else {
521
980
  uint32_t ch = unescape_unicode((unsigned char *) ++pe);
@@ -533,9 +992,6 @@ static VALUE json_string_unescape(char *string, char *stringEnd, int intern, int
533
992
  if ((ch & 0xFC00) == 0xD800) {
534
993
  pe++;
535
994
  if (pe > stringEnd - 6) {
536
- if (bufferSize > MAX_STACK_BUFFER_SIZE) {
537
- ruby_xfree(bufferStart);
538
- }
539
995
  raise_parse_error("incomplete surrogate pair at '%s'", p);
540
996
  }
541
997
  if (pe[0] == '\\' && pe[1] == 'u') {
@@ -568,41 +1024,12 @@ static VALUE json_string_unescape(char *string, char *stringEnd, int intern, int
568
1024
  MEMCPY(buffer, p, char, pe - p);
569
1025
  buffer += pe - p;
570
1026
  }
571
-
572
- # ifdef HAVE_RB_ENC_INTERNED_STR
573
- if (intern) {
574
- result = rb_enc_interned_str(bufferStart, (long)(buffer - bufferStart), rb_utf8_encoding());
575
- } else {
576
- result = rb_utf8_str_new(bufferStart, (long)(buffer - bufferStart));
577
- }
578
- if (bufferSize > MAX_STACK_BUFFER_SIZE) {
579
- ruby_xfree(bufferStart);
580
- }
581
- # else
582
- result = rb_utf8_str_new(bufferStart, (long)(buffer - bufferStart));
583
-
584
- if (bufferSize > MAX_STACK_BUFFER_SIZE) {
585
- ruby_xfree(bufferStart);
586
- }
587
-
588
- if (intern) {
589
- # if STR_UMINUS_DEDUPE_FROZEN
590
- // Starting from MRI 2.8 it is preferable to freeze the string
591
- // before deduplication so that it can be interned directly
592
- // otherwise it would be duplicated first which is wasteful.
593
- result = rb_funcall(rb_str_freeze(result), i_uminus, 0);
594
- # elif STR_UMINUS_DEDUPE
595
- // MRI 2.5 and older do not deduplicate strings that are already
596
- // frozen.
597
- result = rb_funcall(result, i_uminus, 0);
598
- # else
599
- result = rb_str_freeze(result);
600
- # endif
601
- }
602
- # endif
1027
+ rb_str_set_len(result, buffer - bufferStart);
603
1028
 
604
1029
  if (symbolize) {
605
- result = rb_str_intern(result);
1030
+ result = rb_str_intern(result);
1031
+ } else if (intern) {
1032
+ result = rb_funcall(rb_str_freeze(result), i_uminus, 0);
606
1033
  }
607
1034
 
608
1035
  return result;
@@ -614,19 +1041,31 @@ static VALUE json_string_unescape(char *string, char *stringEnd, int intern, int
614
1041
 
615
1042
  write data;
616
1043
 
617
- action parse_string {
618
- *result = json_string_unescape(json->memo + 1, p, json->parsing_name || json-> freeze, json->parsing_name && json->symbolize_names);
619
- if (NIL_P(*result)) {
620
- fhold;
621
- fbreak;
622
- } else {
623
- fexec p + 1;
624
- }
1044
+ action parse_complex_string {
1045
+ *result = json_string_unescape(json, json->memo + 1, p, json->parsing_name, json->parsing_name || json-> freeze, json->parsing_name && json->symbolize_names);
1046
+ fexec p + 1;
1047
+ fhold;
1048
+ fbreak;
625
1049
  }
626
1050
 
627
- action exit { fhold; fbreak; }
1051
+ action parse_simple_string {
1052
+ *result = json_string_fastpath(json, json->memo + 1, p, json->parsing_name, json->parsing_name || json-> freeze, json->parsing_name && json->symbolize_names);
1053
+ fexec p + 1;
1054
+ fhold;
1055
+ fbreak;
1056
+ }
628
1057
 
629
- main := '"' ((^([\"\\] | 0..0x1f) | '\\'[\"\\/bfnrt] | '\\u'[0-9a-fA-F]{4} | '\\'^([\"\\/bfnrtu]|0..0x1f))* %parse_string) '"' @exit;
1058
+ double_quote = '"';
1059
+ escape = '\\';
1060
+ control = 0..0x1f;
1061
+ simple = any - escape - double_quote - control;
1062
+
1063
+ main := double_quote (
1064
+ (simple*)(
1065
+ (double_quote) @parse_simple_string |
1066
+ ((^([\"\\] | control) | escape[\"\\/bfnrt] | '\\u'[0-9a-fA-F]{4} | escape^([\"\\/bfnrtu]|0..0x1f))* double_quote) @parse_complex_string
1067
+ )
1068
+ );
630
1069
  }%%
631
1070
 
632
1071
  static int
@@ -684,18 +1123,78 @@ static VALUE convert_encoding(VALUE source)
684
1123
  {
685
1124
  int encindex = RB_ENCODING_GET(source);
686
1125
 
687
- if (encindex == utf8_encindex) {
1126
+ if (RB_LIKELY(encindex == utf8_encindex)) {
688
1127
  return source;
689
1128
  }
690
1129
 
691
1130
  if (encindex == binary_encindex) {
692
- // For historical reason, we silently reinterpret binary strings as UTF-8 if it would work.
693
- // TODO: Deprecate in 2.8.0
694
- // TODO: Remove in 3.0.0
1131
+ // For historical reason, we silently reinterpret binary strings as UTF-8
695
1132
  return rb_enc_associate_index(rb_str_dup(source), utf8_encindex);
696
1133
  }
697
1134
 
698
- return rb_str_conv_enc(source, rb_enc_from_index(encindex), rb_utf8_encoding());
1135
+ return rb_funcall(source, i_encode, 1, Encoding_UTF_8);
1136
+ }
1137
+
1138
+ static int configure_parser_i(VALUE key, VALUE val, VALUE data)
1139
+ {
1140
+ JSON_Parser *json = (JSON_Parser *)data;
1141
+
1142
+ if (key == sym_max_nesting) { json->max_nesting = RTEST(val) ? FIX2INT(val) : 0; }
1143
+ else if (key == sym_allow_nan) { json->allow_nan = RTEST(val); }
1144
+ else if (key == sym_allow_trailing_comma) { json->allow_trailing_comma = RTEST(val); }
1145
+ else if (key == sym_symbolize_names) { json->symbolize_names = RTEST(val); }
1146
+ else if (key == sym_freeze) { json->freeze = RTEST(val); }
1147
+ else if (key == sym_create_id) { json->create_id = RTEST(val) ? val : Qfalse; }
1148
+ else if (key == sym_object_class) { json->object_class = RTEST(val) ? val : Qfalse; }
1149
+ else if (key == sym_array_class) { json->array_class = RTEST(val) ? val : Qfalse; }
1150
+ else if (key == sym_decimal_class) { json->decimal_class = RTEST(val) ? val : Qfalse; }
1151
+ else if (key == sym_match_string) { json->match_string = RTEST(val) ? val : Qfalse; }
1152
+ else if (key == sym_create_additions) {
1153
+ if (NIL_P(val)) {
1154
+ json->create_additions = true;
1155
+ json->deprecated_create_additions = true;
1156
+ } else {
1157
+ json->create_additions = RTEST(val);
1158
+ json->deprecated_create_additions = false;
1159
+ }
1160
+ }
1161
+
1162
+ return ST_CONTINUE;
1163
+ }
1164
+
1165
+ static void parser_init(JSON_Parser *json, VALUE source, VALUE opts)
1166
+ {
1167
+ if (json->Vsource) {
1168
+ rb_raise(rb_eTypeError, "already initialized instance");
1169
+ }
1170
+
1171
+ json->fbuffer.initial_length = FBUFFER_INITIAL_LENGTH_DEFAULT;
1172
+ json->max_nesting = 100;
1173
+
1174
+ if (!NIL_P(opts)) {
1175
+ Check_Type(opts, T_HASH);
1176
+ if (RHASH_SIZE(opts) > 0) {
1177
+ // We assume in most cases few keys are set so it's faster to go over
1178
+ // the provided keys than to check all possible keys.
1179
+ rb_hash_foreach(opts, configure_parser_i, (VALUE)json);
1180
+
1181
+ if (json->symbolize_names && json->create_additions) {
1182
+ rb_raise(rb_eArgError,
1183
+ "options :symbolize_names and :create_additions cannot be "
1184
+ " used in conjunction");
1185
+ }
1186
+
1187
+ if (json->create_additions && !json->create_id) {
1188
+ json->create_id = rb_funcall(mJSON, i_create_id, 0);
1189
+ }
1190
+ }
1191
+
1192
+ }
1193
+ source = convert_encoding(StringValue(source));
1194
+ StringValue(source);
1195
+ json->len = RSTRING_LEN(source);
1196
+ json->source = RSTRING_PTR(source);
1197
+ json->Vsource = source;
699
1198
  }
700
1199
 
701
1200
  /*
@@ -732,111 +1231,11 @@ static VALUE convert_encoding(VALUE source)
732
1231
  */
733
1232
  static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
734
1233
  {
735
- VALUE source, opts;
736
1234
  GET_PARSER_INIT;
737
1235
 
738
- if (json->Vsource) {
739
- rb_raise(rb_eTypeError, "already initialized instance");
740
- }
741
-
742
1236
  rb_check_arity(argc, 1, 2);
743
- source = argv[0];
744
- opts = Qnil;
745
- if (argc == 2) {
746
- opts = argv[1];
747
- Check_Type(argv[1], T_HASH);
748
- if (RHASH_SIZE(argv[1]) > 0) {
749
- opts = argv[1];
750
- }
751
- }
752
1237
 
753
- if (!NIL_P(opts)) {
754
- VALUE tmp = ID2SYM(i_max_nesting);
755
- if (option_given_p(opts, tmp)) {
756
- VALUE max_nesting = rb_hash_aref(opts, tmp);
757
- if (RTEST(max_nesting)) {
758
- Check_Type(max_nesting, T_FIXNUM);
759
- json->max_nesting = FIX2INT(max_nesting);
760
- } else {
761
- json->max_nesting = 0;
762
- }
763
- } else {
764
- json->max_nesting = 100;
765
- }
766
- tmp = ID2SYM(i_allow_nan);
767
- if (option_given_p(opts, tmp)) {
768
- json->allow_nan = RTEST(rb_hash_aref(opts, tmp)) ? 1 : 0;
769
- } else {
770
- json->allow_nan = 0;
771
- }
772
- tmp = ID2SYM(i_symbolize_names);
773
- if (option_given_p(opts, tmp)) {
774
- json->symbolize_names = RTEST(rb_hash_aref(opts, tmp)) ? 1 : 0;
775
- } else {
776
- json->symbolize_names = 0;
777
- }
778
- tmp = ID2SYM(i_freeze);
779
- if (option_given_p(opts, tmp)) {
780
- json->freeze = RTEST(rb_hash_aref(opts, tmp)) ? 1 : 0;
781
- } else {
782
- json->freeze = 0;
783
- }
784
- tmp = ID2SYM(i_create_additions);
785
- if (option_given_p(opts, tmp)) {
786
- json->create_additions = RTEST(rb_hash_aref(opts, tmp));
787
- } else {
788
- json->create_additions = 0;
789
- }
790
- if (json->symbolize_names && json->create_additions) {
791
- rb_raise(rb_eArgError,
792
- "options :symbolize_names and :create_additions cannot be "
793
- " used in conjunction");
794
- }
795
- tmp = ID2SYM(i_create_id);
796
- if (option_given_p(opts, tmp)) {
797
- json->create_id = rb_hash_aref(opts, tmp);
798
- } else {
799
- json->create_id = rb_funcall(mJSON, i_create_id, 0);
800
- }
801
- tmp = ID2SYM(i_object_class);
802
- if (option_given_p(opts, tmp)) {
803
- json->object_class = rb_hash_aref(opts, tmp);
804
- } else {
805
- json->object_class = Qnil;
806
- }
807
- tmp = ID2SYM(i_array_class);
808
- if (option_given_p(opts, tmp)) {
809
- json->array_class = rb_hash_aref(opts, tmp);
810
- } else {
811
- json->array_class = Qnil;
812
- }
813
- tmp = ID2SYM(i_decimal_class);
814
- if (option_given_p(opts, tmp)) {
815
- json->decimal_class = rb_hash_aref(opts, tmp);
816
- } else {
817
- json->decimal_class = Qnil;
818
- }
819
- tmp = ID2SYM(i_match_string);
820
- if (option_given_p(opts, tmp)) {
821
- VALUE match_string = rb_hash_aref(opts, tmp);
822
- json->match_string = RTEST(match_string) ? match_string : Qnil;
823
- } else {
824
- json->match_string = Qnil;
825
- }
826
- } else {
827
- json->max_nesting = 100;
828
- json->allow_nan = 0;
829
- json->create_additions = 0;
830
- json->create_id = Qnil;
831
- json->object_class = Qnil;
832
- json->array_class = Qnil;
833
- json->decimal_class = Qnil;
834
- }
835
- source = convert_encoding(StringValue(source));
836
- StringValue(source);
837
- json->len = RSTRING_LEN(source);
838
- json->source = RSTRING_PTR(source);;
839
- json->Vsource = source;
1238
+ parser_init(json, argv[0], argc == 2 ? argv[1] : Qnil);
840
1239
  return self;
841
1240
  }
842
1241
 
@@ -871,11 +1270,64 @@ static VALUE cParser_parse(VALUE self)
871
1270
  VALUE result = Qnil;
872
1271
  GET_PARSER;
873
1272
 
1273
+ char stack_buffer[FBUFFER_STACK_SIZE];
1274
+ fbuffer_stack_init(&json->fbuffer, FBUFFER_INITIAL_LENGTH_DEFAULT, stack_buffer, FBUFFER_STACK_SIZE);
1275
+
1276
+ VALUE rvalue_stack_buffer[RVALUE_STACK_INITIAL_CAPA];
1277
+ rvalue_stack stack = {
1278
+ .type = RVALUE_STACK_STACK_ALLOCATED,
1279
+ .ptr = rvalue_stack_buffer,
1280
+ .capa = RVALUE_STACK_INITIAL_CAPA,
1281
+ };
1282
+ json->stack = &stack;
1283
+
874
1284
  %% write init;
875
1285
  p = json->source;
876
1286
  pe = p + json->len;
877
1287
  %% write exec;
878
1288
 
1289
+ if (json->stack_handle) {
1290
+ rvalue_stack_eagerly_release(json->stack_handle);
1291
+ }
1292
+
1293
+ if (cs >= JSON_first_final && p == pe) {
1294
+ return result;
1295
+ } else {
1296
+ raise_parse_error("unexpected token at '%s'", p);
1297
+ return Qnil;
1298
+ }
1299
+ }
1300
+
1301
+ static VALUE cParser_m_parse(VALUE klass, VALUE source, VALUE opts)
1302
+ {
1303
+ char *p, *pe;
1304
+ int cs = EVIL;
1305
+ VALUE result = Qnil;
1306
+
1307
+ JSON_Parser _parser = {0};
1308
+ JSON_Parser *json = &_parser;
1309
+ parser_init(json, source, opts);
1310
+
1311
+ char stack_buffer[FBUFFER_STACK_SIZE];
1312
+ fbuffer_stack_init(&json->fbuffer, FBUFFER_INITIAL_LENGTH_DEFAULT, stack_buffer, FBUFFER_STACK_SIZE);
1313
+
1314
+ VALUE rvalue_stack_buffer[RVALUE_STACK_INITIAL_CAPA];
1315
+ rvalue_stack stack = {
1316
+ .type = RVALUE_STACK_STACK_ALLOCATED,
1317
+ .ptr = rvalue_stack_buffer,
1318
+ .capa = RVALUE_STACK_INITIAL_CAPA,
1319
+ };
1320
+ json->stack = &stack;
1321
+
1322
+ %% write init;
1323
+ p = json->source;
1324
+ pe = p + json->len;
1325
+ %% write exec;
1326
+
1327
+ if (json->stack_handle) {
1328
+ rvalue_stack_eagerly_release(json->stack_handle);
1329
+ }
1330
+
879
1331
  if (cs >= JSON_first_final && p == pe) {
880
1332
  return result;
881
1333
  } else {
@@ -893,19 +1345,25 @@ static void JSON_mark(void *ptr)
893
1345
  rb_gc_mark(json->array_class);
894
1346
  rb_gc_mark(json->decimal_class);
895
1347
  rb_gc_mark(json->match_string);
1348
+ rb_gc_mark(json->stack_handle);
1349
+
1350
+ long index;
1351
+ for (index = 0; index < json->name_cache.length; index++) {
1352
+ rb_gc_mark(json->name_cache.entries[index]);
1353
+ }
896
1354
  }
897
1355
 
898
1356
  static void JSON_free(void *ptr)
899
1357
  {
900
1358
  JSON_Parser *json = ptr;
901
- fbuffer_free(json->fbuffer);
1359
+ fbuffer_free(&json->fbuffer);
902
1360
  ruby_xfree(json);
903
1361
  }
904
1362
 
905
1363
  static size_t JSON_memsize(const void *ptr)
906
1364
  {
907
1365
  const JSON_Parser *json = ptr;
908
- return sizeof(*json) + FBUFFER_CAPA(json->fbuffer);
1366
+ return sizeof(*json) + FBUFFER_CAPA(&json->fbuffer);
909
1367
  }
910
1368
 
911
1369
  static const rb_data_type_t JSON_Parser_type = {
@@ -919,7 +1377,7 @@ static VALUE cJSON_parser_s_allocate(VALUE klass)
919
1377
  {
920
1378
  JSON_Parser *json;
921
1379
  VALUE obj = TypedData_Make_Struct(klass, JSON_Parser, &JSON_Parser_type, json);
922
- json->fbuffer = fbuffer_alloc(0);
1380
+ fbuffer_stack_init(&json->fbuffer, 0, NULL, 0);
923
1381
  return obj;
924
1382
  }
925
1383
 
@@ -953,6 +1411,8 @@ void Init_parser(void)
953
1411
  rb_define_method(cParser, "parse", cParser_parse, 0);
954
1412
  rb_define_method(cParser, "source", cParser_source, 0);
955
1413
 
1414
+ rb_define_singleton_method(cParser, "parse", cParser_m_parse, 2);
1415
+
956
1416
  CNaN = rb_const_get(mJSON, rb_intern("NaN"));
957
1417
  rb_gc_register_mark_object(CNaN);
958
1418
 
@@ -962,30 +1422,38 @@ void Init_parser(void)
962
1422
  CMinusInfinity = rb_const_get(mJSON, rb_intern("MinusInfinity"));
963
1423
  rb_gc_register_mark_object(CMinusInfinity);
964
1424
 
1425
+ rb_global_variable(&Encoding_UTF_8);
1426
+ Encoding_UTF_8 = rb_const_get(rb_path2class("Encoding"), rb_intern("UTF_8"));
1427
+
1428
+ sym_max_nesting = ID2SYM(rb_intern("max_nesting"));
1429
+ sym_allow_nan = ID2SYM(rb_intern("allow_nan"));
1430
+ sym_allow_trailing_comma = ID2SYM(rb_intern("allow_trailing_comma"));
1431
+ sym_symbolize_names = ID2SYM(rb_intern("symbolize_names"));
1432
+ sym_freeze = ID2SYM(rb_intern("freeze"));
1433
+ sym_create_additions = ID2SYM(rb_intern("create_additions"));
1434
+ sym_create_id = ID2SYM(rb_intern("create_id"));
1435
+ sym_object_class = ID2SYM(rb_intern("object_class"));
1436
+ sym_array_class = ID2SYM(rb_intern("array_class"));
1437
+ sym_decimal_class = ID2SYM(rb_intern("decimal_class"));
1438
+ sym_match_string = ID2SYM(rb_intern("match_string"));
1439
+
1440
+ i_create_id = rb_intern("create_id");
965
1441
  i_json_creatable_p = rb_intern("json_creatable?");
966
1442
  i_json_create = rb_intern("json_create");
967
- i_create_id = rb_intern("create_id");
968
- i_create_additions = rb_intern("create_additions");
969
1443
  i_chr = rb_intern("chr");
970
- i_max_nesting = rb_intern("max_nesting");
971
- i_allow_nan = rb_intern("allow_nan");
972
- i_symbolize_names = rb_intern("symbolize_names");
973
- i_object_class = rb_intern("object_class");
974
- i_array_class = rb_intern("array_class");
975
- i_decimal_class = rb_intern("decimal_class");
976
1444
  i_match = rb_intern("match");
977
- i_match_string = rb_intern("match_string");
978
1445
  i_deep_const_get = rb_intern("deep_const_get");
979
1446
  i_aset = rb_intern("[]=");
980
1447
  i_aref = rb_intern("[]");
981
1448
  i_leftshift = rb_intern("<<");
982
1449
  i_new = rb_intern("new");
983
1450
  i_try_convert = rb_intern("try_convert");
984
- i_freeze = rb_intern("freeze");
985
1451
  i_uminus = rb_intern("-@");
1452
+ i_encode = rb_intern("encode");
986
1453
 
987
1454
  binary_encindex = rb_ascii8bit_encindex();
988
1455
  utf8_encindex = rb_utf8_encindex();
1456
+ enc_utf8 = rb_utf8_encoding();
989
1457
  }
990
1458
 
991
1459
  /*