oj 3.7.4 → 3.11.2

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.
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);