oj 3.13.23 → 3.16.9

Sign up to get free protection for your applications and to get access to all the features.
Files changed (158) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +81 -0
  3. data/README.md +2 -2
  4. data/ext/oj/buf.h +7 -6
  5. data/ext/oj/cache.c +29 -26
  6. data/ext/oj/cache.h +3 -2
  7. data/ext/oj/cache8.c +10 -9
  8. data/ext/oj/circarray.c +7 -5
  9. data/ext/oj/circarray.h +2 -2
  10. data/ext/oj/code.c +5 -12
  11. data/ext/oj/code.h +2 -2
  12. data/ext/oj/compat.c +20 -60
  13. data/ext/oj/custom.c +26 -59
  14. data/ext/oj/debug.c +3 -9
  15. data/ext/oj/dump.c +103 -53
  16. data/ext/oj/dump.h +1 -4
  17. data/ext/oj/dump_compat.c +557 -592
  18. data/ext/oj/dump_leaf.c +3 -5
  19. data/ext/oj/dump_object.c +42 -48
  20. data/ext/oj/dump_strict.c +10 -22
  21. data/ext/oj/encoder.c +1 -1
  22. data/ext/oj/err.c +2 -13
  23. data/ext/oj/err.h +9 -12
  24. data/ext/oj/extconf.rb +16 -7
  25. data/ext/oj/fast.c +60 -92
  26. data/ext/oj/intern.c +62 -47
  27. data/ext/oj/intern.h +3 -7
  28. data/ext/oj/mem.c +318 -0
  29. data/ext/oj/mem.h +53 -0
  30. data/ext/oj/mimic_json.c +51 -32
  31. data/ext/oj/object.c +33 -43
  32. data/ext/oj/odd.c +8 -6
  33. data/ext/oj/odd.h +4 -4
  34. data/ext/oj/oj.c +243 -212
  35. data/ext/oj/oj.h +83 -81
  36. data/ext/oj/parse.c +94 -148
  37. data/ext/oj/parse.h +21 -24
  38. data/ext/oj/parser.c +80 -67
  39. data/ext/oj/parser.h +7 -8
  40. data/ext/oj/rails.c +70 -92
  41. data/ext/oj/reader.c +9 -14
  42. data/ext/oj/reader.h +4 -2
  43. data/ext/oj/resolve.c +3 -4
  44. data/ext/oj/rxclass.c +6 -5
  45. data/ext/oj/rxclass.h +1 -1
  46. data/ext/oj/saj.c +10 -9
  47. data/ext/oj/saj2.c +37 -49
  48. data/ext/oj/saj2.h +1 -1
  49. data/ext/oj/scp.c +3 -14
  50. data/ext/oj/sparse.c +22 -70
  51. data/ext/oj/stream_writer.c +45 -41
  52. data/ext/oj/strict.c +20 -52
  53. data/ext/oj/string_writer.c +64 -38
  54. data/ext/oj/trace.h +31 -4
  55. data/ext/oj/usual.c +125 -114
  56. data/ext/oj/usual.h +7 -6
  57. data/ext/oj/util.h +1 -1
  58. data/ext/oj/val_stack.c +13 -2
  59. data/ext/oj/val_stack.h +8 -7
  60. data/ext/oj/wab.c +25 -57
  61. data/lib/oj/active_support_helper.rb +1 -3
  62. data/lib/oj/bag.rb +7 -1
  63. data/lib/oj/easy_hash.rb +4 -5
  64. data/lib/oj/error.rb +0 -1
  65. data/lib/oj/json.rb +162 -150
  66. data/lib/oj/mimic.rb +7 -7
  67. data/lib/oj/schandler.rb +5 -4
  68. data/lib/oj/state.rb +8 -5
  69. data/lib/oj/version.rb +1 -2
  70. data/lib/oj.rb +2 -0
  71. data/pages/InstallOptions.md +20 -0
  72. data/pages/Options.md +4 -0
  73. data/test/_test_active.rb +8 -9
  74. data/test/_test_active_mimic.rb +7 -8
  75. data/test/_test_mimic_rails.rb +17 -20
  76. data/test/activerecord/result_test.rb +5 -6
  77. data/test/activesupport6/encoding_test.rb +63 -28
  78. data/test/activesupport7/abstract_unit.rb +4 -1
  79. data/test/activesupport7/encoding_test.rb +72 -22
  80. data/test/files.rb +15 -15
  81. data/test/foo.rb +18 -69
  82. data/test/helper.rb +5 -8
  83. data/test/isolated/shared.rb +3 -2
  84. data/test/json_gem/json_addition_test.rb +2 -2
  85. data/test/json_gem/json_common_interface_test.rb +8 -6
  86. data/test/json_gem/json_encoding_test.rb +0 -0
  87. data/test/json_gem/json_ext_parser_test.rb +1 -0
  88. data/test/json_gem/json_fixtures_test.rb +3 -2
  89. data/test/json_gem/json_generator_test.rb +50 -33
  90. data/test/json_gem/json_generic_object_test.rb +11 -11
  91. data/test/json_gem/json_parser_test.rb +46 -46
  92. data/test/json_gem/json_string_matching_test.rb +9 -9
  93. data/test/mem.rb +13 -12
  94. data/test/perf.rb +21 -26
  95. data/test/perf_compat.rb +31 -33
  96. data/test/perf_dump.rb +28 -28
  97. data/test/perf_fast.rb +80 -82
  98. data/test/perf_file.rb +27 -29
  99. data/test/perf_object.rb +65 -69
  100. data/test/perf_once.rb +12 -11
  101. data/test/perf_parser.rb +42 -48
  102. data/test/perf_saj.rb +46 -54
  103. data/test/perf_scp.rb +57 -69
  104. data/test/perf_simple.rb +41 -39
  105. data/test/perf_strict.rb +68 -70
  106. data/test/perf_wab.rb +67 -69
  107. data/test/prec.rb +5 -5
  108. data/test/sample/change.rb +0 -1
  109. data/test/sample/dir.rb +0 -1
  110. data/test/sample/doc.rb +0 -1
  111. data/test/sample/file.rb +0 -1
  112. data/test/sample/group.rb +0 -1
  113. data/test/sample/hasprops.rb +0 -1
  114. data/test/sample/layer.rb +0 -1
  115. data/test/sample/rect.rb +0 -1
  116. data/test/sample/shape.rb +0 -1
  117. data/test/sample/text.rb +0 -1
  118. data/test/sample.rb +16 -16
  119. data/test/sample_json.rb +8 -8
  120. data/test/test_compat.rb +81 -54
  121. data/test/test_custom.rb +63 -52
  122. data/test/test_debian.rb +7 -10
  123. data/test/test_fast.rb +86 -90
  124. data/test/test_file.rb +24 -29
  125. data/test/test_gc.rb +5 -5
  126. data/test/test_generate.rb +5 -5
  127. data/test/test_hash.rb +4 -4
  128. data/test/test_integer_range.rb +9 -9
  129. data/test/test_null.rb +20 -20
  130. data/test/test_object.rb +92 -87
  131. data/test/test_parser.rb +4 -4
  132. data/test/test_parser_debug.rb +5 -5
  133. data/test/test_parser_saj.rb +27 -25
  134. data/test/test_parser_usual.rb +44 -6
  135. data/test/test_rails.rb +2 -2
  136. data/test/test_saj.rb +10 -8
  137. data/test/test_scp.rb +35 -35
  138. data/test/test_strict.rb +38 -32
  139. data/test/test_various.rb +146 -97
  140. data/test/test_wab.rb +46 -44
  141. data/test/test_writer.rb +63 -47
  142. data/test/tests.rb +7 -7
  143. data/test/tests_mimic.rb +6 -6
  144. data/test/tests_mimic_addition.rb +6 -6
  145. metadata +46 -26
  146. data/test/activesupport4/decoding_test.rb +0 -108
  147. data/test/activesupport4/encoding_test.rb +0 -531
  148. data/test/activesupport4/test_helper.rb +0 -41
  149. data/test/activesupport5/abstract_unit.rb +0 -45
  150. data/test/activesupport5/decoding_test.rb +0 -133
  151. data/test/activesupport5/encoding_test.rb +0 -500
  152. data/test/activesupport5/encoding_test_cases.rb +0 -98
  153. data/test/activesupport5/test_helper.rb +0 -72
  154. data/test/activesupport5/time_zone_test_helpers.rb +0 -39
  155. data/test/bar.rb +0 -11
  156. data/test/baz.rb +0 -16
  157. data/test/bug.rb +0 -16
  158. data/test/zoo.rb +0 -13
data/ext/oj/parse.c CHANGED
@@ -12,14 +12,19 @@
12
12
 
13
13
  #include "buf.h"
14
14
  #include "encode.h"
15
+ #include "mem.h"
15
16
  #include "oj.h"
16
17
  #include "rxclass.h"
17
18
  #include "val_stack.h"
18
19
 
20
+ #ifdef OJ_USE_SSE4_2
21
+ #include <nmmintrin.h>
22
+ #endif
23
+
19
24
  // Workaround in case INFINITY is not defined in math.h or if the OS is CentOS
20
25
  #define OJ_INFINITY (1.0 / 0.0)
21
26
 
22
- //#define EXP_MAX 1023
27
+ // #define EXP_MAX 1023
23
28
  #define EXP_MAX 100000
24
29
  #define DEC_MAX 15
25
30
 
@@ -44,11 +49,7 @@ static void skip_comment(ParseInfo pi) {
44
49
  pi->cur += 2;
45
50
  return;
46
51
  } else if (pi->end <= pi->cur) {
47
- oj_set_error_at(pi,
48
- oj_parse_error_class,
49
- __FILE__,
50
- __LINE__,
51
- "comment not terminated");
52
+ oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "comment not terminated");
52
53
  return;
53
54
  }
54
55
  }
@@ -81,9 +82,8 @@ static void add_value(ParseInfo pi, VALUE rval) {
81
82
  break;
82
83
  case NEXT_HASH_VALUE:
83
84
  pi->hash_set_value(pi, parent, rval);
84
- if (0 != parent->key && 0 < parent->klen &&
85
- (parent->key < pi->json || pi->cur < parent->key)) {
86
- xfree((char *)parent->key);
85
+ if (0 != parent->key && 0 < parent->klen && (parent->key < pi->json || pi->cur < parent->key)) {
86
+ OJ_R_FREE((char *)parent->key);
87
87
  parent->key = 0;
88
88
  }
89
89
  parent->next = NEXT_HASH_COMMA;
@@ -195,14 +195,18 @@ static inline const char *scan_string_noSIMD(const char *str, const char *end) {
195
195
  #ifdef OJ_USE_SSE4_2
196
196
  static inline const char *scan_string_SIMD(const char *str, const char *end) {
197
197
  static const char chars[16] = "\x00\\\"";
198
- const __m128i terminate = _mm_loadu_si128((const __m128i *)&chars[0]);
199
- const char *_end = (const char *)(end - 16);
198
+ const __m128i terminate = _mm_loadu_si128((const __m128i *)&chars[0]);
199
+ const char *_end = (const char *)(end - 16);
200
200
 
201
201
  for (; str <= _end; str += 16) {
202
202
  const __m128i string = _mm_loadu_si128((const __m128i *)str);
203
- const int r = _mm_cmpestri(terminate, 3, string, 16, _SIDD_UBYTE_OPS | _SIDD_CMP_EQUAL_ANY | _SIDD_LEAST_SIGNIFICANT);
203
+ const int r = _mm_cmpestri(terminate,
204
+ 3,
205
+ string,
206
+ 16,
207
+ _SIDD_UBYTE_OPS | _SIDD_CMP_EQUAL_ANY | _SIDD_LEAST_SIGNIFICANT);
204
208
  if (r != 16) {
205
- str = (char*)(str + r);
209
+ str = (char *)(str + r);
206
210
  return str;
207
211
  }
208
212
  }
@@ -211,7 +215,7 @@ static inline const char *scan_string_SIMD(const char *str, const char *end) {
211
215
  }
212
216
  #endif
213
217
 
214
- static const char *(*scan_func) (const char *str, const char *end) = scan_string_noSIMD;
218
+ static const char *(*scan_func)(const char *str, const char *end) = scan_string_noSIMD;
215
219
 
216
220
  void oj_scanner_init(void) {
217
221
  #ifdef OJ_USE_SSE4_2
@@ -232,16 +236,12 @@ static void read_escaped_str(ParseInfo pi, const char *start) {
232
236
 
233
237
  for (s = pi->cur; '"' != *s;) {
234
238
  const char *scanned = scan_func(s, pi->end);
235
- if (scanned >= pi->end) {
236
- oj_set_error_at(pi,
237
- oj_parse_error_class,
238
- __FILE__,
239
- __LINE__,
240
- "quoted string not terminated");
239
+ if (scanned >= pi->end || '\0' == *scanned) {
240
+ // if (scanned >= pi->end) {
241
+ oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "quoted string not terminated");
241
242
  buf_cleanup(&buf);
242
243
  return;
243
244
  }
244
-
245
245
  buf_append_string(&buf, s, (size_t)(scanned - s));
246
246
  s = scanned;
247
247
 
@@ -275,11 +275,7 @@ static void read_escaped_str(ParseInfo pi, const char *start) {
275
275
  break;
276
276
  }
277
277
  pi->cur = s;
278
- oj_set_error_at(pi,
279
- oj_parse_error_class,
280
- __FILE__,
281
- __LINE__,
282
- "invalid escaped character");
278
+ oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "invalid escaped character");
283
279
  buf_cleanup(&buf);
284
280
  return;
285
281
  }
@@ -306,11 +302,7 @@ static void read_escaped_str(ParseInfo pi, const char *start) {
306
302
  break;
307
303
  }
308
304
  pi->cur = s;
309
- oj_set_error_at(pi,
310
- oj_parse_error_class,
311
- __FILE__,
312
- __LINE__,
313
- "invalid escaped character");
305
+ oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "invalid escaped character");
314
306
  buf_cleanup(&buf);
315
307
  return;
316
308
  }
@@ -330,7 +322,7 @@ static void read_escaped_str(ParseInfo pi, const char *start) {
330
322
  case NEXT_HASH_KEY:
331
323
  if (Qundef == (parent->key_val = pi->hash_key(pi, buf.head, buf_len(&buf)))) {
332
324
  parent->klen = buf_len(&buf);
333
- parent->key = malloc(parent->klen + 1);
325
+ parent->key = OJ_MALLOC(parent->klen + 1);
334
326
  memcpy((char *)parent->key, buf.head, parent->klen);
335
327
  *(char *)(parent->key + parent->klen) = '\0';
336
328
  } else {
@@ -342,9 +334,8 @@ static void read_escaped_str(ParseInfo pi, const char *start) {
342
334
  break;
343
335
  case NEXT_HASH_VALUE:
344
336
  pi->hash_set_cstr(pi, parent, buf.head, buf_len(&buf), start);
345
- if (0 != parent->key && 0 < parent->klen &&
346
- (parent->key < pi->json || pi->cur < parent->key)) {
347
- xfree((char *)parent->key);
337
+ if (0 != parent->key && 0 < parent->klen && (parent->key < pi->json || pi->cur < parent->key)) {
338
+ OJ_R_FREE((char *)parent->key);
348
339
  parent->key = 0;
349
340
  }
350
341
  parent->next = NEXT_HASH_COMMA;
@@ -373,11 +364,7 @@ static void read_str(ParseInfo pi) {
373
364
 
374
365
  pi->cur = scan_func(pi->cur, pi->end);
375
366
  if (RB_UNLIKELY(pi->end <= pi->cur)) {
376
- oj_set_error_at(pi,
377
- oj_parse_error_class,
378
- __FILE__,
379
- __LINE__,
380
- "quoted string not terminated");
367
+ oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "quoted string not terminated");
381
368
  return;
382
369
  }
383
370
  if (RB_UNLIKELY('\0' == *pi->cur)) {
@@ -412,9 +399,8 @@ static void read_str(ParseInfo pi) {
412
399
  break;
413
400
  case NEXT_HASH_VALUE:
414
401
  pi->hash_set_cstr(pi, parent, str, pi->cur - str, str);
415
- if (0 != parent->key && 0 < parent->klen &&
416
- (parent->key < pi->json || pi->cur < parent->key)) {
417
- xfree((char *)parent->key);
402
+ if (0 != parent->key && 0 < parent->klen && (parent->key < pi->json || pi->cur < parent->key)) {
403
+ OJ_R_FREE((char *)parent->key);
418
404
  parent->key = 0;
419
405
  }
420
406
  parent->next = NEXT_HASH_COMMA;
@@ -440,6 +426,7 @@ static void read_num(ParseInfo pi) {
440
426
  struct _numInfo ni;
441
427
  Val parent = stack_peek(&pi->stack);
442
428
 
429
+ ni.pi = pi;
443
430
  ni.str = pi->cur;
444
431
  ni.i = 0;
445
432
  ni.num = 0;
@@ -456,7 +443,7 @@ static void read_num(ParseInfo pi) {
456
443
  ni.no_big = !pi->options.compat_bigdec;
457
444
  ni.bigdec_load = pi->options.compat_bigdec;
458
445
  } else {
459
- ni.no_big = (FloatDec == pi->options.bigdec_load || FastDec == pi->options.bigdec_load ||
446
+ ni.no_big = (FloatDec == pi->options.bigdec_load || FastDec == pi->options.bigdec_load ||
460
447
  RubyDec == pi->options.bigdec_load);
461
448
  ni.bigdec_load = pi->options.bigdec_load;
462
449
  }
@@ -466,33 +453,21 @@ static void read_num(ParseInfo pi) {
466
453
  ni.neg = 1;
467
454
  } else if ('+' == *pi->cur) {
468
455
  if (StrictMode == pi->options.mode) {
469
- oj_set_error_at(pi,
470
- oj_parse_error_class,
471
- __FILE__,
472
- __LINE__,
473
- "not a number or other value");
456
+ oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "not a number or other value");
474
457
  return;
475
458
  }
476
459
  pi->cur++;
477
460
  }
478
461
  if ('I' == *pi->cur) {
479
462
  if (No == pi->options.allow_nan || 0 != strncmp("Infinity", pi->cur, 8)) {
480
- oj_set_error_at(pi,
481
- oj_parse_error_class,
482
- __FILE__,
483
- __LINE__,
484
- "not a number or other value");
463
+ oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "not a number or other value");
485
464
  return;
486
465
  }
487
466
  pi->cur += 8;
488
467
  ni.infinity = 1;
489
468
  } else if ('N' == *pi->cur || 'n' == *pi->cur) {
490
469
  if ('a' != pi->cur[1] || ('N' != pi->cur[2] && 'n' != pi->cur[2])) {
491
- oj_set_error_at(pi,
492
- oj_parse_error_class,
493
- __FILE__,
494
- __LINE__,
495
- "not a number or other value");
470
+ oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "not a number or other value");
496
471
  return;
497
472
  }
498
473
  pi->cur += 3;
@@ -515,11 +490,7 @@ static void read_num(ParseInfo pi) {
515
490
  ni.i = ni.i * 10 + d;
516
491
  }
517
492
  if (RB_UNLIKELY(0 != ni.i && zero1 && CompatMode == pi->options.mode)) {
518
- oj_set_error_at(pi,
519
- oj_parse_error_class,
520
- __FILE__,
521
- __LINE__,
522
- "not a number");
493
+ oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "not a number");
523
494
  return;
524
495
  }
525
496
  if (INT64_MAX <= ni.i || DEC_MAX < dec_cnt) {
@@ -611,9 +582,8 @@ static void read_num(ParseInfo pi) {
611
582
  break;
612
583
  case NEXT_HASH_VALUE:
613
584
  pi->hash_set_num(pi, parent, &ni);
614
- if (0 != parent->key && 0 < parent->klen &&
615
- (parent->key < pi->json || pi->cur < parent->key)) {
616
- xfree((char *)parent->key);
585
+ if (0 != parent->key && 0 < parent->klen && (parent->key < pi->json || pi->cur < parent->key)) {
586
+ OJ_R_FREE((char *)parent->key);
617
587
  parent->key = 0;
618
588
  }
619
589
  parent->next = NEXT_HASH_COMMA;
@@ -711,7 +681,7 @@ void oj_parse2(ParseInfo pi) {
711
681
  pi->cur = pi->json;
712
682
  err_init(&pi->err);
713
683
  while (1) {
714
- if (0 < pi->max_depth && pi->max_depth <= pi->stack.tail - pi->stack.head - 1) {
684
+ if (RB_UNLIKELY(0 < pi->max_depth && pi->max_depth <= pi->stack.tail - pi->stack.head - 1)) {
715
685
  VALUE err_clas = oj_get_json_err_class("NestingError");
716
686
 
717
687
  oj_set_error_at(pi, err_clas, __FILE__, __LINE__, "Too deeply nested.");
@@ -719,18 +689,20 @@ void oj_parse2(ParseInfo pi) {
719
689
  return;
720
690
  }
721
691
  next_non_white(pi);
722
- if (!first && '\0' != *pi->cur) {
723
- oj_set_error_at(pi,
724
- oj_parse_error_class,
725
- __FILE__,
726
- __LINE__,
727
- "unexpected characters after the JSON document");
728
- }
729
-
730
- // If no tokens are consumed (i.e. empty string), throw a parse error
731
- // this is the behavior of JSON.parse in both Ruby and JS.
732
- if (No == pi->options.empty_string && 1 == first && '\0' == *pi->cur) {
733
- oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "unexpected character");
692
+ if (first) {
693
+ // If no tokens are consumed (i.e. empty string), throw a parse error
694
+ // this is the behavior of JSON.parse in both Ruby and JS.
695
+ if (RB_UNLIKELY('\0' == *pi->cur && No == pi->options.empty_string)) {
696
+ oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "unexpected character");
697
+ }
698
+ } else {
699
+ if (RB_UNLIKELY('\0' != *pi->cur)) {
700
+ oj_set_error_at(pi,
701
+ oj_parse_error_class,
702
+ __FILE__,
703
+ __LINE__,
704
+ "unexpected characters after the JSON document");
705
+ }
734
706
  }
735
707
 
736
708
  switch (*pi->cur++) {
@@ -740,17 +712,10 @@ void oj_parse2(ParseInfo pi) {
740
712
  case '[': array_start(pi); break;
741
713
  case ']': array_end(pi); break;
742
714
  case ',': comma(pi); break;
743
- case '"':
744
- read_str(pi);
745
- break;
746
- // case '+':
715
+ case '"': read_str(pi); break;
747
716
  case '+':
748
717
  if (CompatMode == pi->options.mode) {
749
- oj_set_error_at(pi,
750
- oj_parse_error_class,
751
- __FILE__,
752
- __LINE__,
753
- "unexpected character");
718
+ oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "unexpected character");
754
719
  return;
755
720
  }
756
721
  pi->cur--;
@@ -776,11 +741,7 @@ void oj_parse2(ParseInfo pi) {
776
741
  pi->cur--;
777
742
  read_num(pi);
778
743
  } else {
779
- oj_set_error_at(pi,
780
- oj_parse_error_class,
781
- __FILE__,
782
- __LINE__,
783
- "unexpected character");
744
+ oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "unexpected character");
784
745
  }
785
746
  break;
786
747
  case 't': read_true(pi); break;
@@ -800,11 +761,9 @@ void oj_parse2(ParseInfo pi) {
800
761
  }
801
762
  break;
802
763
  case '\0': pi->cur--; return;
803
- default:
804
- oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "unexpected character");
805
- return;
764
+ default: oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "unexpected character"); return;
806
765
  }
807
- if (err_has(&pi->err)) {
766
+ if (RB_UNLIKELY(err_has(&pi->err))) {
808
767
  return;
809
768
  }
810
769
  if (stack_empty(&pi->stack)) {
@@ -839,11 +798,10 @@ static VALUE parse_big_decimal(VALUE str) {
839
798
  }
840
799
 
841
800
  static long double exp_plus[] = {
842
- 1.0, 1.0e1, 1.0e2, 1.0e3, 1.0e4, 1.0e5, 1.0e6, 1.0e7, 1.0e8, 1.0e9,
843
- 1.0e10, 1.0e11, 1.0e12, 1.0e13, 1.0e14, 1.0e15, 1.0e16, 1.0e17, 1.0e18, 1.0e19,
844
- 1.0e20, 1.0e21, 1.0e22, 1.0e23, 1.0e24, 1.0e25, 1.0e26, 1.0e27, 1.0e28, 1.0e29,
845
- 1.0e30, 1.0e31, 1.0e32, 1.0e33, 1.0e34, 1.0e35, 1.0e36, 1.0e37, 1.0e38, 1.0e39,
846
- 1.0e40, 1.0e41, 1.0e42, 1.0e43, 1.0e44, 1.0e45, 1.0e46, 1.0e47, 1.0e48, 1.0e49,
801
+ 1.0, 1.0e1, 1.0e2, 1.0e3, 1.0e4, 1.0e5, 1.0e6, 1.0e7, 1.0e8, 1.0e9, 1.0e10, 1.0e11, 1.0e12,
802
+ 1.0e13, 1.0e14, 1.0e15, 1.0e16, 1.0e17, 1.0e18, 1.0e19, 1.0e20, 1.0e21, 1.0e22, 1.0e23, 1.0e24, 1.0e25,
803
+ 1.0e26, 1.0e27, 1.0e28, 1.0e29, 1.0e30, 1.0e31, 1.0e32, 1.0e33, 1.0e34, 1.0e35, 1.0e36, 1.0e37, 1.0e38,
804
+ 1.0e39, 1.0e40, 1.0e41, 1.0e42, 1.0e43, 1.0e44, 1.0e45, 1.0e46, 1.0e47, 1.0e48, 1.0e49,
847
805
  };
848
806
 
849
807
  VALUE
@@ -867,12 +825,12 @@ oj_num_as_value(NumInfo ni) {
867
825
  buf[ni->len] = '\0';
868
826
  rnum = rb_cstr_to_inum(buf, 10, 0);
869
827
  } else {
870
- char *buf = ALLOC_N(char, ni->len + 1);
828
+ char *buf = OJ_R_ALLOC_N(char, ni->len + 1);
871
829
 
872
830
  memcpy(buf, ni->str, ni->len);
873
831
  buf[ni->len] = '\0';
874
832
  rnum = rb_cstr_to_inum(buf, 10, 0);
875
- xfree(buf);
833
+ OJ_R_FREE(buf);
876
834
  }
877
835
  } else {
878
836
  if (ni->neg) {
@@ -915,11 +873,15 @@ oj_num_as_value(NumInfo ni) {
915
873
 
916
874
  rnum = rb_funcall(sv, rb_intern("to_f"), 0);
917
875
  } else {
918
- char * end;
876
+ char *end;
919
877
  double d = strtod(ni->str, &end);
920
878
 
921
879
  if ((long)ni->len != (long)(end - ni->str)) {
922
- rb_raise(oj_parse_error_class, "Invalid float");
880
+ if (Qnil == ni->pi->err_class) {
881
+ rb_raise(oj_parse_error_class, "Invalid float");
882
+ } else {
883
+ rb_raise(ni->pi->err_class, "Invalid float");
884
+ }
923
885
  }
924
886
  rnum = rb_float_new(d);
925
887
  }
@@ -927,28 +889,23 @@ oj_num_as_value(NumInfo ni) {
927
889
  return rnum;
928
890
  }
929
891
 
930
- void oj_set_error_at(ParseInfo pi,
931
- VALUE err_clas,
932
- const char *file,
933
- int line,
934
- const char *format,
935
- ...) {
892
+ void oj_set_error_at(ParseInfo pi, VALUE err_clas, const char *file, int line, const char *format, ...) {
936
893
  va_list ap;
937
894
  char msg[256];
938
- char * p = msg;
939
- char * end = p + sizeof(msg) - 2;
940
- char * start;
895
+ char *p = msg;
896
+ char *end = p + sizeof(msg) - 2;
897
+ char *start;
941
898
  Val vp;
942
- int mlen;
899
+ int mlen;
943
900
 
944
901
  va_start(ap, format);
945
902
  mlen = vsnprintf(msg, sizeof(msg) - 1, format, ap);
946
903
  if (0 < mlen) {
947
- if (sizeof(msg) - 2 < (size_t)mlen) {
948
- p = end - 2;
949
- } else {
950
- p += mlen;
951
- }
904
+ if (sizeof(msg) - 2 < (size_t)mlen) {
905
+ p = end - 2;
906
+ } else {
907
+ p += mlen;
908
+ }
952
909
  }
953
910
  va_end(ap);
954
911
  pi->err.clas = err_clas;
@@ -985,14 +942,7 @@ void oj_set_error_at(ParseInfo pi,
985
942
  }
986
943
  *p = '\0';
987
944
  if (0 == pi->json) {
988
- oj_err_set(&pi->err,
989
- err_clas,
990
- "%s at line %d, column %d [%s:%d]",
991
- msg,
992
- pi->rd.line,
993
- pi->rd.col,
994
- file,
995
- line);
945
+ oj_err_set(&pi->err, err_clas, "%s at line %d, column %d [%s:%d]", msg, pi->rd.line, pi->rd.col, file, line);
996
946
  } else {
997
947
  _oj_err_set_with_location(&pi->err, err_clas, msg, pi->json, pi->cur - 1, file, line);
998
948
  }
@@ -1011,7 +961,7 @@ static void oj_pi_set_input_str(ParseInfo pi, VALUE *inputp) {
1011
961
 
1012
962
  if (oj_utf8_encoding_index != idx) {
1013
963
  rb_encoding *enc = rb_enc_from_index(idx);
1014
- *inputp = rb_str_conv_enc(*inputp, enc, oj_utf8_encoding);
964
+ *inputp = rb_str_conv_enc(*inputp, enc, oj_utf8_encoding);
1015
965
  }
1016
966
  pi->json = RSTRING_PTR(*inputp);
1017
967
  pi->end = pi->json + RSTRING_LEN(*inputp);
@@ -1019,12 +969,12 @@ static void oj_pi_set_input_str(ParseInfo pi, VALUE *inputp) {
1019
969
 
1020
970
  VALUE
1021
971
  oj_pi_parse(int argc, VALUE *argv, ParseInfo pi, char *json, size_t len, int yieldOk) {
1022
- char * buf = 0;
1023
- VALUE input;
1024
- VALUE wrapped_stack;
1025
- VALUE result = Qnil;
1026
- int line = 0;
1027
- int free_json = 0;
972
+ char *buf = 0;
973
+ VALUE input;
974
+ VALUE wrapped_stack;
975
+ VALUE result = Qnil;
976
+ int line = 0;
977
+ int free_json = 0;
1028
978
 
1029
979
  if (argc < 1) {
1030
980
  rb_raise(rb_eArgError, "Wrong number of arguments to parse.");
@@ -1073,19 +1023,18 @@ oj_pi_parse(int argc, VALUE *argv, ParseInfo pi, char *json, size_t len, int yie
1073
1023
  size_t len = lseek(fd, 0, SEEK_END);
1074
1024
 
1075
1025
  lseek(fd, 0, SEEK_SET);
1076
- buf = ALLOC_N(char, len + 1);
1026
+ buf = OJ_R_ALLOC_N(char, len + 1);
1077
1027
  pi->json = buf;
1078
1028
  pi->end = buf + len;
1079
1029
  if (0 >= (cnt = read(fd, (char *)pi->json, len)) || cnt != (ssize_t)len) {
1080
1030
  if (0 != buf) {
1081
- xfree(buf);
1031
+ OJ_R_FREE(buf);
1082
1032
  }
1083
1033
  rb_raise(rb_eIOError, "failed to read from IO Object.");
1084
1034
  }
1085
1035
  ((char *)pi->json)[len] = '\0';
1086
1036
  /* skip UTF-8 BOM if present */
1087
- if (0xEF == (uint8_t)*pi->json && 0xBB == (uint8_t)pi->json[1] &&
1088
- 0xBF == (uint8_t)pi->json[2]) {
1037
+ if (0xEF == (uint8_t)*pi->json && 0xBB == (uint8_t)pi->json[1] && 0xBF == (uint8_t)pi->json[2]) {
1089
1038
  pi->cur += 3;
1090
1039
  }
1091
1040
  #endif
@@ -1111,8 +1060,7 @@ oj_pi_parse(int argc, VALUE *argv, ParseInfo pi, char *json, size_t len, int yie
1111
1060
  wrapped_stack = oj_stack_init(&pi->stack);
1112
1061
  rb_protect(protect_parse, (VALUE)pi, &line);
1113
1062
  if (Qundef == pi->stack.head->val && !empty_ok(&pi->options)) {
1114
- if (No == pi->options.nilnil ||
1115
- (CompatMode == pi->options.mode && 0 < pi->cur - pi->json)) {
1063
+ if (No == pi->options.nilnil || (CompatMode == pi->options.mode && 0 < pi->cur - pi->json)) {
1116
1064
  oj_set_error_at(pi, oj_json_parser_error_class, __FILE__, __LINE__, "Empty input");
1117
1065
  }
1118
1066
  }
@@ -1140,9 +1088,7 @@ oj_pi_parse(int argc, VALUE *argv, ParseInfo pi, char *json, size_t len, int yie
1140
1088
  switch (v->next) {
1141
1089
  case NEXT_ARRAY_NEW:
1142
1090
  case NEXT_ARRAY_ELEMENT:
1143
- case NEXT_ARRAY_COMMA:
1144
- oj_set_error_at(pi, err_class, __FILE__, __LINE__, "Array not terminated");
1145
- break;
1091
+ case NEXT_ARRAY_COMMA: oj_set_error_at(pi, err_class, __FILE__, __LINE__, "Array not terminated"); break;
1146
1092
  case NEXT_HASH_NEW:
1147
1093
  case NEXT_HASH_KEY:
1148
1094
  case NEXT_HASH_COLON:
@@ -1160,9 +1106,9 @@ CLEANUP:
1160
1106
  oj_circ_array_free(pi->circ_array);
1161
1107
  }
1162
1108
  if (0 != buf) {
1163
- xfree(buf);
1109
+ OJ_R_FREE(buf);
1164
1110
  } else if (free_json) {
1165
- xfree(json);
1111
+ OJ_R_FREE(json);
1166
1112
  }
1167
1113
  stack_cleanup(&pi->stack);
1168
1114
  if (pi->str_rx.head != oj_default_options.str_rx.head) {
data/ext/oj/parse.h CHANGED
@@ -16,23 +16,25 @@
16
16
  #include "val_stack.h"
17
17
 
18
18
  struct _rxClass;
19
+ struct _parseInfo;
19
20
 
20
21
  typedef struct _numInfo {
21
- int64_t i;
22
- int64_t num;
23
- int64_t div;
24
- int64_t di;
25
- const char *str;
26
- size_t len;
27
- long exp;
28
- int big;
29
- int infinity;
30
- int nan;
31
- int neg;
32
- int has_exp;
33
- int no_big;
34
- int bigdec_load;
35
- } * NumInfo;
22
+ int64_t i;
23
+ int64_t num;
24
+ int64_t div;
25
+ int64_t di;
26
+ const char *str;
27
+ size_t len;
28
+ long exp;
29
+ struct _parseInfo *pi;
30
+ int big;
31
+ int infinity;
32
+ int nan;
33
+ int neg;
34
+ int has_exp;
35
+ int no_big;
36
+ int bigdec_load;
37
+ } *NumInfo;
36
38
 
37
39
  typedef struct _parseInfo {
38
40
  // used for the string parser
@@ -54,11 +56,7 @@ typedef struct _parseInfo {
54
56
  VALUE (*start_hash)(struct _parseInfo *pi);
55
57
  void (*end_hash)(struct _parseInfo *pi);
56
58
  VALUE (*hash_key)(struct _parseInfo *pi, const char *key, size_t klen);
57
- void (*hash_set_cstr)(struct _parseInfo *pi,
58
- Val kval,
59
- const char * str,
60
- size_t len,
61
- const char * orig);
59
+ void (*hash_set_cstr)(struct _parseInfo *pi, Val kval, const char *str, size_t len, const char *orig);
62
60
  void (*hash_set_num)(struct _parseInfo *pi, Val kval, NumInfo ni);
63
61
  void (*hash_set_value)(struct _parseInfo *pi, Val kval, VALUE value);
64
62
 
@@ -73,11 +71,10 @@ typedef struct _parseInfo {
73
71
  void (*add_value)(struct _parseInfo *pi, VALUE val);
74
72
  VALUE err_class;
75
73
  bool has_callbacks;
76
- } * ParseInfo;
74
+ } *ParseInfo;
77
75
 
78
- extern void oj_parse2(ParseInfo pi);
79
- extern void
80
- oj_set_error_at(ParseInfo pi, VALUE err_clas, const char *file, int line, const char *format, ...);
76
+ extern void oj_parse2(ParseInfo pi);
77
+ extern void oj_set_error_at(ParseInfo pi, VALUE err_clas, const char *file, int line, const char *format, ...);
81
78
  extern VALUE oj_pi_parse(int argc, VALUE *argv, ParseInfo pi, char *json, size_t len, int yieldOk);
82
79
  extern VALUE oj_num_as_value(NumInfo ni);
83
80