oj 3.7.4 → 3.11.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (95) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +12 -4
  3. data/ext/oj/buf.h +6 -34
  4. data/ext/oj/cache8.c +3 -3
  5. data/ext/oj/cache8.h +5 -33
  6. data/ext/oj/circarray.c +5 -9
  7. data/ext/oj/circarray.h +5 -8
  8. data/ext/oj/code.c +3 -6
  9. data/ext/oj/code.h +7 -10
  10. data/ext/oj/compat.c +11 -14
  11. data/ext/oj/custom.c +108 -75
  12. data/ext/oj/dump.c +132 -92
  13. data/ext/oj/dump.h +6 -7
  14. data/ext/oj/dump_compat.c +37 -34
  15. data/ext/oj/dump_leaf.c +3 -6
  16. data/ext/oj/dump_object.c +23 -17
  17. data/ext/oj/dump_strict.c +7 -9
  18. data/ext/oj/encode.h +6 -32
  19. data/ext/oj/err.c +2 -5
  20. data/ext/oj/err.h +6 -34
  21. data/ext/oj/extconf.rb +6 -0
  22. data/ext/oj/fast.c +39 -56
  23. data/ext/oj/hash.c +11 -39
  24. data/ext/oj/hash.h +5 -33
  25. data/ext/oj/hash_test.c +3 -31
  26. data/ext/oj/mimic_json.c +65 -44
  27. data/ext/oj/object.c +38 -69
  28. data/ext/oj/odd.c +18 -17
  29. data/ext/oj/odd.h +6 -9
  30. data/ext/oj/oj.c +139 -93
  31. data/ext/oj/oj.h +43 -35
  32. data/ext/oj/parse.c +164 -60
  33. data/ext/oj/parse.h +30 -31
  34. data/ext/oj/rails.c +119 -83
  35. data/ext/oj/rails.h +4 -7
  36. data/ext/oj/reader.c +5 -8
  37. data/ext/oj/reader.h +7 -10
  38. data/ext/oj/resolve.c +4 -7
  39. data/ext/oj/resolve.h +4 -7
  40. data/ext/oj/rxclass.c +8 -11
  41. data/ext/oj/rxclass.h +8 -11
  42. data/ext/oj/saj.c +9 -12
  43. data/ext/oj/scp.c +4 -7
  44. data/ext/oj/sparse.c +67 -33
  45. data/ext/oj/stream_writer.c +16 -15
  46. data/ext/oj/strict.c +9 -12
  47. data/ext/oj/string_writer.c +27 -8
  48. data/ext/oj/trace.c +5 -8
  49. data/ext/oj/trace.h +9 -12
  50. data/ext/oj/util.c +136 -0
  51. data/ext/oj/util.h +19 -0
  52. data/ext/oj/val_stack.c +28 -36
  53. data/ext/oj/val_stack.h +19 -50
  54. data/ext/oj/wab.c +29 -29
  55. data/lib/oj.rb +0 -8
  56. data/lib/oj/json.rb +1 -1
  57. data/lib/oj/mimic.rb +46 -2
  58. data/lib/oj/version.rb +2 -2
  59. data/pages/Modes.md +47 -45
  60. data/pages/Options.md +43 -10
  61. data/pages/Rails.md +60 -21
  62. data/pages/Security.md +1 -1
  63. data/test/activesupport5/abstract_unit.rb +45 -0
  64. data/test/activesupport5/decoding_test.rb +68 -60
  65. data/test/activesupport5/encoding_test.rb +111 -96
  66. data/test/activesupport5/encoding_test_cases.rb +33 -25
  67. data/test/activesupport5/test_helper.rb +43 -21
  68. data/test/activesupport5/time_zone_test_helpers.rb +18 -3
  69. data/test/activesupport6/abstract_unit.rb +44 -0
  70. data/test/activesupport6/decoding_test.rb +133 -0
  71. data/test/activesupport6/encoding_test.rb +507 -0
  72. data/test/activesupport6/encoding_test_cases.rb +98 -0
  73. data/test/activesupport6/test_common.rb +17 -0
  74. data/test/activesupport6/test_helper.rb +163 -0
  75. data/test/activesupport6/time_zone_test_helpers.rb +39 -0
  76. data/test/bar.rb +24 -6
  77. data/test/baz.rb +16 -0
  78. data/test/foo.rb +26 -57
  79. data/test/helper.rb +10 -0
  80. data/test/json_gem/json_common_interface_test.rb +8 -3
  81. data/test/json_gem/json_generator_test.rb +15 -3
  82. data/test/json_gem/test_helper.rb +8 -0
  83. data/test/prec.rb +23 -0
  84. data/test/sample_json.rb +1 -1
  85. data/test/test_compat.rb +21 -10
  86. data/test/test_custom.rb +135 -8
  87. data/test/test_integer_range.rb +1 -2
  88. data/test/test_object.rb +35 -2
  89. data/test/test_rails.rb +35 -0
  90. data/test/test_strict.rb +24 -1
  91. data/test/test_various.rb +52 -63
  92. data/test/test_writer.rb +19 -2
  93. data/test/tests.rb +1 -0
  94. data/test/zoo.rb +13 -0
  95. metadata +100 -75
data/ext/oj/rails.h CHANGED
@@ -1,10 +1,7 @@
1
- /* rails.h
2
- * Copyright (c) 2017, Peter Ohler
3
- * All rights reserved.
4
- */
1
+ // Copyright (c) 2017 Peter Ohler. All rights reserved.
5
2
 
6
- #ifndef __OJ_RAILS_H__
7
- #define __OJ_RAILS_H__
3
+ #ifndef OJ_RAILS_H
4
+ #define OJ_RAILS_H
8
5
 
9
6
  #include "dump.h"
10
7
 
@@ -18,4 +15,4 @@ extern bool oj_rails_float_opt;
18
15
  extern VALUE oj_optimize_rails(VALUE self);
19
16
 
20
17
 
21
- #endif /* __OJ_RAILS_H__ */
18
+ #endif /* OJ_RAILS_H */
data/ext/oj/reader.c CHANGED
@@ -1,7 +1,4 @@
1
- /* reader.c
2
- * Copyright (c) 2011, Peter Ohler
3
- * All rights reserved.
4
- */
1
+ // Copyright (c) 2011 Peter Ohler. All rights reserved.
5
2
 
6
3
  #include <stdlib.h>
7
4
  #include <errno.h>
@@ -9,7 +6,7 @@
9
6
  #include <strings.h>
10
7
  #include <sys/types.h>
11
8
  #if NEEDS_UIO
12
- #include <sys/uio.h>
9
+ #include <sys/uio.h>
13
10
  #endif
14
11
  #include <unistd.h>
15
12
  #include <time.h>
@@ -78,13 +75,13 @@ oj_reader_init(Reader reader, VALUE io, int fd, bool to_s) {
78
75
  reader->io = io;
79
76
  } else if (to_s) {
80
77
  volatile VALUE rstr = rb_funcall(io, oj_to_s_id, 0);
81
-
78
+
82
79
  reader->read_func = 0;
83
80
  reader->in_str = StringValuePtr(rstr);
84
81
  reader->head = (char*)reader->in_str;
85
82
  reader->tail = reader->head;
86
83
  reader->read_end = reader->head + RSTRING_LEN(rstr);
87
- } else {
84
+ } else {
88
85
  rb_raise(rb_eArgError, "parser io argument must be a String or respond to readpartial() or read().\n");
89
86
  }
90
87
  }
@@ -107,7 +104,7 @@ oj_reader_read(Reader reader) {
107
104
  if (0 >= shift) { /* no space left so allocate more */
108
105
  const char *old = reader->head;
109
106
  size_t size = reader->end - reader->head + BUF_PAD;
110
-
107
+
111
108
  if (reader->head == reader->base) {
112
109
  reader->head = ALLOC_N(char, size * 2);
113
110
  memcpy((char*)reader->head, old, size);
data/ext/oj/reader.h CHANGED
@@ -1,12 +1,9 @@
1
- /* reader.h
2
- * Copyright (c) 2011, Peter Ohler
3
- * All rights reserved.
4
- */
1
+ // Copyright (c) 2011 Peter Ohler. All rights reserved.
5
2
 
6
- #ifndef __OJ_READER_H__
7
- #define __OJ_READER_H__
3
+ #ifndef OJ_READER_H
4
+ #define OJ_READER_H
8
5
 
9
- typedef struct _Reader {
6
+ typedef struct _reader {
10
7
  char base[0x00001000];
11
8
  char *head;
12
9
  char *end;
@@ -18,7 +15,7 @@ typedef struct _Reader {
18
15
  int line;
19
16
  int col;
20
17
  int free_head;
21
- int (*read_func)(struct _Reader *reader);
18
+ int (*read_func)(struct _reader *reader);
22
19
  union {
23
20
  int fd;
24
21
  VALUE io;
@@ -43,7 +40,7 @@ reader_get(Reader reader) {
43
40
  }
44
41
  reader->col++;
45
42
  reader->pos++;
46
-
43
+
47
44
  return *reader->tail++;
48
45
  }
49
46
 
@@ -148,4 +145,4 @@ is_white(char c) {
148
145
  return 0;
149
146
  }
150
147
 
151
- #endif /* __OJ_READER_H__ */
148
+ #endif /* OJ_READER_H */
data/ext/oj/resolve.c CHANGED
@@ -1,12 +1,9 @@
1
- /* resolve.c
2
- * Copyright (c) 2012, Peter Ohler
3
- * All rights reserved.
4
- */
1
+ // Copyright (c) 2012 Peter Ohler. All rights reserved.
5
2
 
6
3
  #include <stdlib.h>
7
4
  #include <stdio.h>
8
5
  #include <string.h>
9
- #if HAVE_LIBPTHREAD
6
+ #ifdef HAVE_PTHREAD_MUTEX_INIT
10
7
  #include <pthread.h>
11
8
  #endif
12
9
 
@@ -75,7 +72,7 @@ oj_name2class(ParseInfo pi, const char *name, size_t len, int auto_define, VALUE
75
72
  if (No == pi->options.class_cache) {
76
73
  return resolve_classpath(pi, name, len, auto_define, error_class);
77
74
  }
78
- #if HAVE_LIBPTHREAD
75
+ #ifdef HAVE_PTHREAD_MUTEX_INIT
79
76
  pthread_mutex_lock(&oj_cache_mutex);
80
77
  #else
81
78
  rb_mutex_lock(oj_cache_mutex);
@@ -85,7 +82,7 @@ oj_name2class(ParseInfo pi, const char *name, size_t len, int auto_define, VALUE
85
82
  *slot = clas;
86
83
  }
87
84
  }
88
- #if HAVE_LIBPTHREAD
85
+ #ifdef HAVE_PTHREAD_MUTEX_INIT
89
86
  pthread_mutex_unlock(&oj_cache_mutex);
90
87
  #else
91
88
  rb_mutex_unlock(oj_cache_mutex);
data/ext/oj/resolve.h CHANGED
@@ -1,14 +1,11 @@
1
- /* resolve.h
2
- * Copyright (c) 2011, Peter Ohler
3
- * All rights reserved.
4
- */
1
+ // Copyright (c) 2011 Peter Ohler. All rights reserved.
5
2
 
6
- #ifndef __OJ_RESOLVE_H__
7
- #define __OJ_RESOLVE_H__
3
+ #ifndef OJ_RESOLVE_H
4
+ #define OJ_RESOLVE_H
8
5
 
9
6
  #include "ruby.h"
10
7
 
11
8
  extern VALUE oj_name2class(ParseInfo pi, const char *name, size_t len, int auto_define, VALUE error_class);
12
9
  extern VALUE oj_name2struct(ParseInfo pi, VALUE nameVal, VALUE error_class);
13
10
 
14
- #endif /* __OJ_RESOLVE_H__ */
11
+ #endif /* OJ_RESOLVE_H */
data/ext/oj/rxclass.c CHANGED
@@ -1,7 +1,4 @@
1
- /* rxclass.c
2
- * Copyright (c) 2017, Peter Ohler
3
- * All rights reserved.
4
- */
1
+ // Copyright (c) 2017 Peter Ohler. All rights reserved.
5
2
 
6
3
  #include <sys/types.h>
7
4
  #include <stdlib.h>
@@ -14,8 +11,8 @@
14
11
 
15
12
  #include "rxclass.h"
16
13
 
17
- typedef struct _RxC {
18
- struct _RxC *next;
14
+ typedef struct _rxC {
15
+ struct _rxC *next;
19
16
  VALUE rrx;
20
17
  #if !IS_WINDOWS
21
18
  regex_t rx;
@@ -48,9 +45,9 @@ oj_rxclass_cleanup(RxClass rc) {
48
45
 
49
46
  void
50
47
  oj_rxclass_rappend(RxClass rc, VALUE rx, VALUE clas) {
51
- RxC rxc = ALLOC_N(struct _RxC, 1);
48
+ RxC rxc = ALLOC_N(struct _rxC, 1);
52
49
 
53
- memset(rxc, 0, sizeof(struct _RxC));
50
+ memset(rxc, 0, sizeof(struct _rxC));
54
51
  rxc->rrx = rx;
55
52
  rxc->clas = clas;
56
53
  if (NULL == rc->tail) {
@@ -73,7 +70,7 @@ oj_rxclass_append(RxClass rc, const char *expr, VALUE clas) {
73
70
  snprintf(rc->err, sizeof(rc->err), "expressions must be less than %lu characters", (unsigned long)sizeof(rxc->src));
74
71
  return EINVAL;
75
72
  }
76
- rxc = ALLOC_N(struct _RxC, 1);
73
+ rxc = ALLOC_N(struct _rxC, 1);
77
74
  rxc->next = 0;
78
75
  rxc->clas = clas;
79
76
 
@@ -101,12 +98,12 @@ VALUE
101
98
  oj_rxclass_match(RxClass rc, const char *str, int len) {
102
99
  RxC rxc;
103
100
  char buf[4096];
104
-
101
+
105
102
  for (rxc = rc->head; NULL != rxc; rxc = rxc->next) {
106
103
  if (Qnil != rxc->rrx) {
107
104
  // Must use a valiabel for this to work.
108
105
  volatile VALUE rstr = rb_str_new(str, len);
109
-
106
+
110
107
  //if (Qtrue == rb_funcall(rxc->rrx, rb_intern("match?"), 1, rstr)) {
111
108
  if (Qnil != rb_funcall(rxc->rrx, rb_intern("match"), 1, rstr)) {
112
109
  return rxc->clas;
data/ext/oj/rxclass.h CHANGED
@@ -1,19 +1,16 @@
1
- /* rxclass.h
2
- * Copyright (c) 2017, Peter Ohler
3
- * All rights reserved.
4
- */
1
+ // Copyright (c) 2017 Peter Ohler. All rights reserved.
5
2
 
6
- #ifndef __OJ_RXCLASS_H__
7
- #define __OJ_RXCLASS_H__
3
+ #ifndef OJ_RXCLASS_H
4
+ #define OJ_RXCLASS_H
8
5
 
9
6
  #include <stdbool.h>
10
7
  #include "ruby.h"
11
8
 
12
- struct _RxC;
9
+ struct _rxC;
13
10
 
14
- typedef struct _RxClass {
15
- struct _RxC *head;
16
- struct _RxC *tail;
11
+ typedef struct _rxClass {
12
+ struct _rxC *head;
13
+ struct _rxC *tail;
17
14
  char err[128];
18
15
  } *RxClass;
19
16
 
@@ -24,4 +21,4 @@ extern VALUE oj_rxclass_match(RxClass rc, const char *str, int len);
24
21
  extern void oj_rxclass_copy(RxClass src, RxClass dest);
25
22
  extern void oj_rxclass_rappend(RxClass rc, VALUE rx, VALUE clas);
26
23
 
27
- #endif /* __OJ_RXCLASS_H__ */
24
+ #endif /* OJ_RXCLASS_H */
data/ext/oj/saj.c CHANGED
@@ -1,7 +1,4 @@
1
- /* saj.c
2
- * Copyright (c) 2012, Peter Ohler
3
- * All rights reserved.
4
- */
1
+ // Copyright (c) 2012 Peter Ohler. All rights reserved.
5
2
 
6
3
  #if !IS_WINDOWS
7
4
  #include <sys/resource.h> /* for getrlimit() on linux */
@@ -19,7 +16,7 @@
19
16
  #include "oj.h"
20
17
  #include "encode.h"
21
18
 
22
- typedef struct _ParseInfo {
19
+ typedef struct _parseInfo {
23
20
  char *str; /* buffer being read from */
24
21
  char *s; /* current position in buffer */
25
22
  void *stack_min;
@@ -213,7 +210,7 @@ read_next(ParseInfo pi, const char *key) {
213
210
  static void
214
211
  read_hash(ParseInfo pi, const char *key) {
215
212
  const char *ks;
216
-
213
+
217
214
  if (pi->has_hash_start) {
218
215
  call_no_value(pi->handler, oj_hash_start_id, key);
219
216
  }
@@ -378,7 +375,7 @@ read_num(ParseInfo pi, const char *key) {
378
375
  if (0 == e && 0 == a && 1 == div) {
379
376
  if (big) {
380
377
  char c = *pi->s;
381
-
378
+
382
379
  *pi->s = '\0';
383
380
  if (pi->has_add_value) {
384
381
  call_add_value(pi->handler, rb_funcall(rb_cObject, oj_bigdecimal_id, 1, rb_str_new2(start)), key);
@@ -396,7 +393,7 @@ read_num(ParseInfo pi, const char *key) {
396
393
  } else { /* decimal */
397
394
  if (big) {
398
395
  char c = *pi->s;
399
-
396
+
400
397
  *pi->s = '\0';
401
398
  if (pi->has_add_value) {
402
399
  call_add_value(pi->handler, rb_funcall(rb_cObject, oj_bigdecimal_id, 1, rb_str_new2(start)), key);
@@ -541,7 +538,7 @@ read_quoted_value(ParseInfo pi) {
541
538
  char *h = pi->s; /* head */
542
539
  char *t = h; /* tail */
543
540
  uint32_t code;
544
-
541
+
545
542
  h++; /* skip quote character */
546
543
  t++;
547
544
  value = h;
@@ -605,7 +602,7 @@ read_quoted_value(ParseInfo pi) {
605
602
  static void
606
603
  saj_parse(VALUE handler, char *json) {
607
604
  volatile VALUE obj = Qnil;
608
- struct _ParseInfo pi;
605
+ struct _parseInfo pi;
609
606
 
610
607
  if (0 == json) {
611
608
  if (pi.has_error) {
@@ -626,7 +623,7 @@ saj_parse(VALUE handler, char *json) {
626
623
  {
627
624
  struct rlimit lim;
628
625
 
629
- if (0 == getrlimit(RLIMIT_STACK, &lim)) {
626
+ if (0 == getrlimit(RLIMIT_STACK, &lim) && RLIM_INFINITY != lim.rlim_cur) {
630
627
  pi.stack_min = (void*)((char*)&obj - (lim.rlim_cur / 4 * 3)); /* let 3/4ths of the stack be used only */
631
628
  } else {
632
629
  pi.stack_min = 0; /* indicates not to check stack limit */
@@ -679,7 +676,7 @@ oj_saj_parse(int argc, VALUE *argv, VALUE self) {
679
676
  } else {
680
677
  VALUE clas = rb_obj_class(input);
681
678
  volatile VALUE s;
682
-
679
+
683
680
  if (oj_stringio_class == clas) {
684
681
  s = rb_funcall2(input, oj_string_id, 0, 0);
685
682
  len = RSTRING_LEN(s) + 1;
data/ext/oj/scp.c CHANGED
@@ -1,7 +1,4 @@
1
- /* scp.c
2
- * Copyright (c) 2012, Peter Ohler
3
- * All rights reserved.
4
- */
1
+ // Copyright (c) 2012 Peter Ohler. All rights reserved.
5
2
 
6
3
  #include <stdlib.h>
7
4
  #include <stdio.h>
@@ -36,7 +33,7 @@ noop_add_num(ParseInfo pi, NumInfo ni) {
36
33
  }
37
34
 
38
35
  static VALUE
39
- noop_hash_key(struct _ParseInfo *pi, const char *key, size_t klen) {
36
+ noop_hash_key(ParseInfo pi, const char *key, size_t klen) {
40
37
  return Qundef;
41
38
  }
42
39
 
@@ -117,7 +114,7 @@ calc_hash_key(ParseInfo pi, Val kval) {
117
114
  }
118
115
 
119
116
  static VALUE
120
- hash_key(struct _ParseInfo *pi, const char *key, size_t klen) {
117
+ hash_key(ParseInfo pi, const char *key, size_t klen) {
121
118
  return rb_funcall(pi->handler, oj_hash_key_id, 1, rb_str_new(key, klen));
122
119
  }
123
120
 
@@ -159,7 +156,7 @@ array_append_value(ParseInfo pi, VALUE value) {
159
156
 
160
157
  VALUE
161
158
  oj_sc_parse(int argc, VALUE *argv, VALUE self) {
162
- struct _ParseInfo pi;
159
+ struct _parseInfo pi;
163
160
  VALUE input = argv[1];
164
161
 
165
162
  parse_info_init(&pi);
data/ext/oj/sparse.c CHANGED
@@ -1,7 +1,4 @@
1
- /* sparse.c
2
- * Copyright (c) 2013, Peter Ohler
3
- * All rights reserved.
4
- */
1
+ // Copyright (c) 2013 Peter Ohler. All rights reserved.
5
2
 
6
3
  #include <stdlib.h>
7
4
  #include <stdio.h>
@@ -203,7 +200,7 @@ unicode_to_chars(ParseInfo pi, Buf buf, uint32_t code) {
203
200
  // entered at backslash
204
201
  static void
205
202
  read_escaped_str(ParseInfo pi) {
206
- struct _Buf buf;
203
+ struct _buf buf;
207
204
  char c;
208
205
  uint32_t code;
209
206
  Val parent = stack_peek(&pi->stack);
@@ -228,17 +225,6 @@ read_escaped_str(ParseInfo pi) {
228
225
  case '"': buf_append(&buf, '"'); break;
229
226
  case '/': buf_append(&buf, '/'); break;
230
227
  case '\\': buf_append(&buf, '\\'); break;
231
- case '\'':
232
- // The json gem claims this is not an error despite the
233
- // ECMA-404 indicating it is not valid.
234
- if (CompatMode == pi->options.mode) {
235
- buf_append(&buf, '\'');
236
- } else {
237
- oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "invalid escaped character");
238
- buf_cleanup(&buf);
239
- return;
240
- }
241
- break;
242
228
  case 'u':
243
229
  if (0 == (code = read_hex(pi)) && err_has(&pi->err)) {
244
230
  buf_cleanup(&buf);
@@ -276,6 +262,12 @@ read_escaped_str(ParseInfo pi) {
276
262
  }
277
263
  break;
278
264
  default:
265
+ // The json gem claims this is not an error despite the
266
+ // ECMA-404 indicating it is not valid.
267
+ if (CompatMode == pi->options.mode) {
268
+ buf_append(&buf, c);
269
+ break;
270
+ }
279
271
  oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "invalid escaped character");
280
272
  buf_cleanup(&buf);
281
273
  return;
@@ -393,7 +385,7 @@ read_str(ParseInfo pi) {
393
385
 
394
386
  static void
395
387
  read_num(ParseInfo pi) {
396
- struct _NumInfo ni;
388
+ struct _numInfo ni;
397
389
  char c;
398
390
 
399
391
  reader_protect(&pi->rd);
@@ -407,8 +399,15 @@ read_num(ParseInfo pi) {
407
399
  ni.infinity = 0;
408
400
  ni.nan = 0;
409
401
  ni.neg = 0;
410
- ni.hasExp = 0;
411
- ni.no_big = (FloatDec == pi->options.bigdec_load);
402
+ ni.has_exp = 0;
403
+ if (CompatMode == pi->options.mode) {
404
+ ni.no_big = !pi->options.compat_bigdec;
405
+ ni.bigdec_load = pi->options.compat_bigdec;
406
+ } else {
407
+ ni.no_big = (FloatDec == pi->options.bigdec_load || FastDec == pi->options.bigdec_load || RubyDec == pi->options.bigdec_load);
408
+ ni.bigdec_load = pi->options.bigdec_load;
409
+ }
410
+
412
411
  c = reader_get(&pi->rd);
413
412
  if ('-' == c) {
414
413
  c = reader_get(&pi->rd);
@@ -469,18 +468,26 @@ read_num(ParseInfo pi) {
469
468
  if (0 < ni.num || 0 < ni.i) {
470
469
  dec_cnt++;
471
470
  }
472
- ni.num = ni.num * 10 + d;
473
- ni.div *= 10;
474
- ni.di++;
475
- if (INT64_MAX <= ni.div || DEC_MAX < dec_cnt) {
476
- ni.big = 1;
471
+ if (INT64_MAX <= ni.div) {
472
+ if (!ni.no_big) {
473
+ ni.big = true;
474
+ }
475
+ } else {
476
+ ni.num = ni.num * 10 + d;
477
+ ni.div *= 10;
478
+ ni.di++;
479
+ if (INT64_MAX <= ni.div || DEC_MAX < dec_cnt) {
480
+ if (!ni.no_big) {
481
+ ni.big = true;
482
+ }
483
+ }
477
484
  }
478
485
  }
479
486
  }
480
487
  if ('e' == c || 'E' == c) {
481
488
  int eneg = 0;
482
489
 
483
- ni.hasExp = 1;
490
+ ni.has_exp = 1;
484
491
  c = reader_get(&pi->rd);
485
492
  if ('-' == c) {
486
493
  c = reader_get(&pi->rd);
@@ -516,7 +523,11 @@ read_num(ParseInfo pi) {
516
523
  ni.nan = 1;
517
524
  }
518
525
  }
519
- if (BigDec == pi->options.bigdec_load) {
526
+ if (CompatMode == pi->options.mode) {
527
+ if (pi->options.compat_bigdec) {
528
+ ni.big = 1;
529
+ }
530
+ } else if (BigDec == pi->options.bigdec_load) {
520
531
  ni.big = 1;
521
532
  }
522
533
  add_num_value(pi, &ni);
@@ -525,7 +536,7 @@ read_num(ParseInfo pi) {
525
536
 
526
537
  static void
527
538
  read_nan(ParseInfo pi) {
528
- struct _NumInfo ni;
539
+ struct _numInfo ni;
529
540
  char c;
530
541
 
531
542
  ni.str = pi->rd.str;
@@ -539,14 +550,24 @@ read_nan(ParseInfo pi) {
539
550
  ni.infinity = 0;
540
551
  ni.nan = 1;
541
552
  ni.neg = 0;
542
- ni.no_big = (FloatDec == pi->options.bigdec_load);
553
+ if (CompatMode == pi->options.mode) {
554
+ ni.no_big = !pi->options.compat_bigdec;
555
+ ni.bigdec_load = pi->options.compat_bigdec;
556
+ } else {
557
+ ni.no_big = (FloatDec == pi->options.bigdec_load || FastDec == pi->options.bigdec_load || RubyDec == pi->options.bigdec_load);
558
+ ni.bigdec_load = pi->options.bigdec_load;
559
+ }
543
560
 
544
561
  if ('a' != reader_get(&pi->rd) ||
545
562
  ('N' != (c = reader_get(&pi->rd)) && 'n' != c)) {
546
563
  oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "not a number or other value");
547
564
  return;
548
565
  }
549
- if (BigDec == pi->options.bigdec_load) {
566
+ if (CompatMode == pi->options.mode) {
567
+ if (pi->options.compat_bigdec) {
568
+ ni.big = 1;
569
+ }
570
+ } else if (BigDec == pi->options.bigdec_load) {
550
571
  ni.big = 1;
551
572
  }
552
573
  add_num_value(pi, &ni);
@@ -632,7 +653,7 @@ oj_sparse2(ParseInfo pi) {
632
653
  while (1) {
633
654
  if (0 < pi->max_depth && pi->max_depth <= pi->stack.tail - pi->stack.head - 1) {
634
655
  VALUE err_clas = oj_get_json_err_class("NestingError");
635
-
656
+
636
657
  oj_set_error_at(pi, err_clas, __FILE__, __LINE__, "Too deeply nested.");
637
658
  pi->err_class = err_clas;
638
659
  return;
@@ -718,7 +739,7 @@ oj_sparse2(ParseInfo pi) {
718
739
  return;
719
740
  }
720
741
  } else if ('a' == c) {
721
- struct _NumInfo ni;
742
+ struct _numInfo ni;
722
743
 
723
744
  c = reader_get(&pi->rd);
724
745
  if ('N' != c && 'n' != c) {
@@ -736,7 +757,15 @@ oj_sparse2(ParseInfo pi) {
736
757
  ni.infinity = 0;
737
758
  ni.nan = 1;
738
759
  ni.neg = 0;
739
- ni.no_big = (FloatDec == pi->options.bigdec_load);
760
+ if (CompatMode == pi->options.mode) {
761
+ ni.no_big = !pi->options.compat_bigdec;
762
+ ni.bigdec_load = pi->options.compat_bigdec;
763
+ } else {
764
+ ni.no_big = (FloatDec == pi->options.bigdec_load ||
765
+ FastDec == pi->options.bigdec_load ||
766
+ RubyDec == pi->options.bigdec_load);
767
+ ni.bigdec_load = pi->options.bigdec_load;
768
+ }
740
769
  add_num_value(pi, &ni);
741
770
  } else {
742
771
  oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "invalid token");
@@ -773,6 +802,7 @@ oj_sparse2(ParseInfo pi) {
773
802
  first = 0;
774
803
  }
775
804
  start = pi->rd.pos;
805
+ // TBD break if option set to allow that
776
806
  }
777
807
  }
778
808
  }
@@ -890,7 +920,7 @@ CLEANUP:
890
920
  if (Qnil != pi->err_class && 0 != pi->err_class) {
891
921
  pi->err.clas = pi->err_class;
892
922
  }
893
- if (CompatMode == pi->options.mode) {
923
+ if (CompatMode == pi->options.mode && Yes != pi->options.safe) {
894
924
  // The json gem requires the error message be UTF-8 encoded. In
895
925
  // additional the complete JSON source should be returned but that
896
926
  // is not possible without stored all the bytes read and reading
@@ -898,6 +928,10 @@ CLEANUP:
898
928
  // idea.
899
929
  VALUE args[] = { oj_encode(rb_str_new2(pi->err.msg)) };
900
930
 
931
+ if (pi->err.clas == oj_parse_error_class) {
932
+ // The error was an Oj::ParseError so change to a JSON::ParserError.
933
+ pi->err.clas = oj_json_parser_error_class;
934
+ }
901
935
  rb_exc_raise(rb_class_new_instance(1, args, pi->err.clas));
902
936
  } else {
903
937
  oj_err_raise(&pi->err);