oj 3.9.1 → 3.16.11

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 (171) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +1452 -0
  3. data/README.md +21 -6
  4. data/RELEASE_NOTES.md +61 -0
  5. data/ext/oj/buf.h +50 -68
  6. data/ext/oj/cache.c +329 -0
  7. data/ext/oj/cache.h +22 -0
  8. data/ext/oj/cache8.c +60 -62
  9. data/ext/oj/cache8.h +9 -36
  10. data/ext/oj/circarray.c +38 -42
  11. data/ext/oj/circarray.h +12 -13
  12. data/ext/oj/code.c +158 -179
  13. data/ext/oj/code.h +20 -22
  14. data/ext/oj/compat.c +145 -205
  15. data/ext/oj/custom.c +740 -880
  16. data/ext/oj/debug.c +126 -0
  17. data/ext/oj/dump.c +1145 -844
  18. data/ext/oj/dump.h +71 -57
  19. data/ext/oj/dump_compat.c +575 -655
  20. data/ext/oj/dump_leaf.c +96 -186
  21. data/ext/oj/dump_object.c +533 -660
  22. data/ext/oj/dump_strict.c +306 -340
  23. data/ext/oj/encode.h +4 -33
  24. data/ext/oj/encoder.c +43 -0
  25. data/ext/oj/err.c +28 -28
  26. data/ext/oj/err.h +39 -42
  27. data/ext/oj/extconf.rb +28 -7
  28. data/ext/oj/fast.c +1052 -1113
  29. data/ext/oj/intern.c +313 -0
  30. data/ext/oj/intern.h +22 -0
  31. data/ext/oj/mem.c +318 -0
  32. data/ext/oj/mem.h +53 -0
  33. data/ext/oj/mimic_json.c +471 -430
  34. data/ext/oj/object.c +532 -580
  35. data/ext/oj/odd.c +156 -142
  36. data/ext/oj/odd.h +25 -26
  37. data/ext/oj/oj.c +1346 -961
  38. data/ext/oj/oj.h +307 -290
  39. data/ext/oj/parse.c +954 -858
  40. data/ext/oj/parse.h +74 -72
  41. data/ext/oj/parser.c +1600 -0
  42. data/ext/oj/parser.h +103 -0
  43. data/ext/oj/rails.c +819 -836
  44. data/ext/oj/rails.h +8 -11
  45. data/ext/oj/reader.c +136 -147
  46. data/ext/oj/reader.h +69 -83
  47. data/ext/oj/resolve.c +41 -63
  48. data/ext/oj/resolve.h +4 -6
  49. data/ext/oj/rxclass.c +69 -72
  50. data/ext/oj/rxclass.h +12 -13
  51. data/ext/oj/saj.c +440 -485
  52. data/ext/oj/saj2.c +584 -0
  53. data/ext/oj/saj2.h +23 -0
  54. data/ext/oj/scp.c +79 -118
  55. data/ext/oj/simd.h +10 -0
  56. data/ext/oj/sparse.c +739 -709
  57. data/ext/oj/stream_writer.c +141 -175
  58. data/ext/oj/strict.c +103 -128
  59. data/ext/oj/string_writer.c +244 -261
  60. data/ext/oj/trace.c +34 -41
  61. data/ext/oj/trace.h +42 -15
  62. data/ext/oj/usual.c +1218 -0
  63. data/ext/oj/usual.h +69 -0
  64. data/ext/oj/util.c +107 -107
  65. data/ext/oj/util.h +4 -3
  66. data/ext/oj/val_stack.c +61 -78
  67. data/ext/oj/val_stack.h +80 -114
  68. data/ext/oj/validate.c +46 -0
  69. data/ext/oj/wab.c +316 -361
  70. data/lib/oj/active_support_helper.rb +1 -3
  71. data/lib/oj/bag.rb +8 -1
  72. data/lib/oj/easy_hash.rb +9 -9
  73. data/lib/oj/error.rb +1 -2
  74. data/lib/oj/json.rb +162 -150
  75. data/lib/oj/mimic.rb +54 -20
  76. data/lib/oj/saj.rb +20 -6
  77. data/lib/oj/schandler.rb +5 -4
  78. data/lib/oj/state.rb +12 -8
  79. data/lib/oj/version.rb +1 -2
  80. data/lib/oj.rb +2 -8
  81. data/pages/Compatibility.md +1 -1
  82. data/pages/Encoding.md +1 -1
  83. data/pages/InstallOptions.md +20 -0
  84. data/pages/JsonGem.md +15 -0
  85. data/pages/Modes.md +9 -3
  86. data/pages/Options.md +62 -12
  87. data/pages/Parser.md +309 -0
  88. data/pages/Rails.md +73 -22
  89. metadata +68 -192
  90. data/ext/oj/hash.c +0 -163
  91. data/ext/oj/hash.h +0 -46
  92. data/ext/oj/hash_test.c +0 -512
  93. data/test/_test_active.rb +0 -76
  94. data/test/_test_active_mimic.rb +0 -96
  95. data/test/_test_mimic_rails.rb +0 -126
  96. data/test/activerecord/result_test.rb +0 -27
  97. data/test/activesupport4/decoding_test.rb +0 -108
  98. data/test/activesupport4/encoding_test.rb +0 -531
  99. data/test/activesupport4/test_helper.rb +0 -41
  100. data/test/activesupport5/decoding_test.rb +0 -125
  101. data/test/activesupport5/encoding_test.rb +0 -485
  102. data/test/activesupport5/encoding_test_cases.rb +0 -90
  103. data/test/activesupport5/test_helper.rb +0 -50
  104. data/test/activesupport5/time_zone_test_helpers.rb +0 -24
  105. data/test/bar.rb +0 -25
  106. data/test/files.rb +0 -29
  107. data/test/foo.rb +0 -21
  108. data/test/helper.rb +0 -26
  109. data/test/isolated/shared.rb +0 -308
  110. data/test/isolated/test_mimic_after.rb +0 -13
  111. data/test/isolated/test_mimic_alone.rb +0 -12
  112. data/test/isolated/test_mimic_as_json.rb +0 -45
  113. data/test/isolated/test_mimic_before.rb +0 -13
  114. data/test/isolated/test_mimic_define.rb +0 -28
  115. data/test/isolated/test_mimic_rails_after.rb +0 -22
  116. data/test/isolated/test_mimic_rails_before.rb +0 -21
  117. data/test/isolated/test_mimic_redefine.rb +0 -15
  118. data/test/json_gem/json_addition_test.rb +0 -216
  119. data/test/json_gem/json_common_interface_test.rb +0 -148
  120. data/test/json_gem/json_encoding_test.rb +0 -107
  121. data/test/json_gem/json_ext_parser_test.rb +0 -20
  122. data/test/json_gem/json_fixtures_test.rb +0 -35
  123. data/test/json_gem/json_generator_test.rb +0 -383
  124. data/test/json_gem/json_generic_object_test.rb +0 -90
  125. data/test/json_gem/json_parser_test.rb +0 -470
  126. data/test/json_gem/json_string_matching_test.rb +0 -42
  127. data/test/json_gem/test_helper.rb +0 -18
  128. data/test/perf.rb +0 -107
  129. data/test/perf_compat.rb +0 -130
  130. data/test/perf_fast.rb +0 -164
  131. data/test/perf_file.rb +0 -64
  132. data/test/perf_object.rb +0 -138
  133. data/test/perf_saj.rb +0 -109
  134. data/test/perf_scp.rb +0 -151
  135. data/test/perf_simple.rb +0 -287
  136. data/test/perf_strict.rb +0 -145
  137. data/test/perf_wab.rb +0 -131
  138. data/test/sample/change.rb +0 -14
  139. data/test/sample/dir.rb +0 -19
  140. data/test/sample/doc.rb +0 -36
  141. data/test/sample/file.rb +0 -48
  142. data/test/sample/group.rb +0 -16
  143. data/test/sample/hasprops.rb +0 -16
  144. data/test/sample/layer.rb +0 -12
  145. data/test/sample/line.rb +0 -20
  146. data/test/sample/oval.rb +0 -10
  147. data/test/sample/rect.rb +0 -10
  148. data/test/sample/shape.rb +0 -35
  149. data/test/sample/text.rb +0 -20
  150. data/test/sample.rb +0 -54
  151. data/test/sample_json.rb +0 -37
  152. data/test/test_compat.rb +0 -509
  153. data/test/test_custom.rb +0 -503
  154. data/test/test_debian.rb +0 -53
  155. data/test/test_fast.rb +0 -470
  156. data/test/test_file.rb +0 -239
  157. data/test/test_gc.rb +0 -49
  158. data/test/test_hash.rb +0 -29
  159. data/test/test_integer_range.rb +0 -73
  160. data/test/test_null.rb +0 -376
  161. data/test/test_object.rb +0 -1018
  162. data/test/test_saj.rb +0 -186
  163. data/test/test_scp.rb +0 -433
  164. data/test/test_strict.rb +0 -410
  165. data/test/test_various.rb +0 -741
  166. data/test/test_wab.rb +0 -307
  167. data/test/test_writer.rb +0 -380
  168. data/test/tests.rb +0 -24
  169. data/test/tests_mimic.rb +0 -14
  170. data/test/tests_mimic_addition.rb +0 -7
  171. data/test/zoo.rb +0 -13
data/ext/oj/sparse.c CHANGED
@@ -1,784 +1,808 @@
1
- /* sparse.c
2
- * Copyright (c) 2013, Peter Ohler
3
- * All rights reserved.
4
- */
1
+ // Copyright (c) 2013 Peter Ohler. All rights reserved.
2
+ // Licensed under the MIT License. See LICENSE file in the project root for license details.
5
3
 
6
- #include <stdlib.h>
4
+ #include <math.h>
7
5
  #include <stdio.h>
6
+ #include <stdlib.h>
8
7
  #include <string.h>
9
8
  #include <unistd.h>
10
- #include <math.h>
11
9
 
12
- #include "oj.h"
10
+ #include "buf.h"
13
11
  #include "encode.h"
12
+ #include "intern.h" // for oj_strndup()
13
+ #include "mem.h"
14
+ #include "oj.h"
14
15
  #include "parse.h"
15
- #include "buf.h"
16
- #include "hash.h" // for oj_strndup()
17
16
  #include "val_stack.h"
18
17
 
19
18
  // Workaround in case INFINITY is not defined in math.h or if the OS is CentOS
20
- #define OJ_INFINITY (1.0/0.0)
19
+ #define OJ_INFINITY (1.0 / 0.0)
21
20
 
22
21
  #ifdef RUBINIUS_RUBY
23
- #define NUM_MAX 0x07FFFFFF
22
+ #define NUM_MAX 0x07FFFFFF
24
23
  #else
25
- #define NUM_MAX (FIXNUM_MAX >> 8)
24
+ #define NUM_MAX (FIXNUM_MAX >> 8)
26
25
  #endif
27
- #define EXP_MAX 100000
28
- #define DEC_MAX 15
26
+ #define EXP_MAX 100000
27
+ #define DEC_MAX 15
29
28
 
30
- static void
31
- skip_comment(ParseInfo pi) {
32
- char c = reader_get(&pi->rd);
29
+ static void skip_comment(ParseInfo pi) {
30
+ char c = reader_get(&pi->rd);
33
31
 
34
32
  if ('*' == c) {
35
- while ('\0' != (c = reader_get(&pi->rd))) {
36
- if ('*' == c) {
37
- c = reader_get(&pi->rd);
38
- if ('/' == c) {
39
- return;
40
- }
41
- }
42
- }
33
+ while ('\0' != (c = reader_get(&pi->rd))) {
34
+ if ('*' == c) {
35
+ c = reader_get(&pi->rd);
36
+ if ('/' == c) {
37
+ return;
38
+ }
39
+ }
40
+ }
43
41
  } else if ('/' == c) {
44
- while ('\0' != (c = reader_get(&pi->rd))) {
45
- switch (c) {
46
- case '\n':
47
- case '\r':
48
- case '\f':
49
- case '\0':
50
- return;
51
- default:
52
- break;
53
- }
54
- }
42
+ while ('\0' != (c = reader_get(&pi->rd))) {
43
+ switch (c) {
44
+ case '\n':
45
+ case '\r':
46
+ case '\f':
47
+ case '\0': return;
48
+ default: break;
49
+ }
50
+ }
55
51
  } else {
56
- oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "invalid comment format");
52
+ oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "invalid comment format");
57
53
  }
58
54
  if ('\0' == c) {
59
- oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "comment not terminated");
60
- return;
55
+ oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "comment not terminated");
56
+ return;
61
57
  }
62
58
  }
63
59
 
64
- static void
65
- add_value(ParseInfo pi, VALUE rval) {
66
- Val parent = stack_peek(&pi->stack);
60
+ static void add_value(ParseInfo pi, VALUE rval) {
61
+ Val parent = stack_peek(&pi->stack);
67
62
 
68
- if (0 == parent) { // simple add
69
- pi->add_value(pi, rval);
63
+ if (0 == parent) { // simple add
64
+ pi->add_value(pi, rval);
70
65
  } else {
71
- switch (parent->next) {
72
- case NEXT_ARRAY_NEW:
73
- case NEXT_ARRAY_ELEMENT:
74
- pi->array_append_value(pi, rval);
75
- parent->next = NEXT_ARRAY_COMMA;
76
- break;
77
- case NEXT_HASH_VALUE:
78
- pi->hash_set_value(pi, parent, rval);
79
- if (parent->kalloc) {
80
- xfree((char*)parent->key);
81
- }
82
- parent->key = 0;
83
- parent->kalloc = 0;
84
- parent->next = NEXT_HASH_COMMA;
85
- break;
86
- case NEXT_HASH_NEW:
87
- case NEXT_HASH_KEY:
88
- case NEXT_HASH_COMMA:
89
- case NEXT_NONE:
90
- case NEXT_ARRAY_COMMA:
91
- case NEXT_HASH_COLON:
92
- default:
93
- oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "expected %s", oj_stack_next_string(parent->next));
94
- break;
95
- }
66
+ switch (parent->next) {
67
+ case NEXT_ARRAY_NEW:
68
+ case NEXT_ARRAY_ELEMENT:
69
+ pi->array_append_value(pi, rval);
70
+ parent->next = NEXT_ARRAY_COMMA;
71
+ break;
72
+ case NEXT_HASH_VALUE:
73
+ pi->hash_set_value(pi, parent, rval);
74
+ if (parent->kalloc) {
75
+ OJ_R_FREE((char *)parent->key);
76
+ }
77
+ parent->key = 0;
78
+ parent->kalloc = 0;
79
+ parent->next = NEXT_HASH_COMMA;
80
+ break;
81
+ case NEXT_HASH_NEW:
82
+ case NEXT_HASH_KEY:
83
+ case NEXT_HASH_COMMA:
84
+ case NEXT_NONE:
85
+ case NEXT_ARRAY_COMMA:
86
+ case NEXT_HASH_COLON:
87
+ default:
88
+ oj_set_error_at(pi,
89
+ oj_parse_error_class,
90
+ __FILE__,
91
+ __LINE__,
92
+ "expected %s",
93
+ oj_stack_next_string(parent->next));
94
+ break;
95
+ }
96
96
  }
97
97
  }
98
98
 
99
- static void
100
- add_num_value(ParseInfo pi, NumInfo ni) {
101
- Val parent = stack_peek(&pi->stack);
99
+ static void add_num_value(ParseInfo pi, NumInfo ni) {
100
+ Val parent = stack_peek(&pi->stack);
102
101
 
103
102
  if (0 == parent) {
104
- pi->add_num(pi, ni);
103
+ pi->add_num(pi, ni);
105
104
  } else {
106
- switch (parent->next) {
107
- case NEXT_ARRAY_NEW:
108
- case NEXT_ARRAY_ELEMENT:
109
- pi->array_append_num(pi, ni);
110
- parent->next = NEXT_ARRAY_COMMA;
111
- break;
112
- case NEXT_HASH_VALUE:
113
- pi->hash_set_num(pi, parent, ni);
114
- if (parent->kalloc) {
115
- xfree((char*)parent->key);
116
- }
117
- parent->key = 0;
118
- parent->kalloc = 0;
119
- parent->next = NEXT_HASH_COMMA;
120
- break;
121
- default:
122
- oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "expected %s", oj_stack_next_string(parent->next));
123
- break;
124
- }
105
+ switch (parent->next) {
106
+ case NEXT_ARRAY_NEW:
107
+ case NEXT_ARRAY_ELEMENT:
108
+ pi->array_append_num(pi, ni);
109
+ parent->next = NEXT_ARRAY_COMMA;
110
+ break;
111
+ case NEXT_HASH_VALUE:
112
+ pi->hash_set_num(pi, parent, ni);
113
+ if (parent->kalloc) {
114
+ OJ_R_FREE((char *)parent->key);
115
+ }
116
+ parent->key = 0;
117
+ parent->kalloc = 0;
118
+ parent->next = NEXT_HASH_COMMA;
119
+ break;
120
+ default:
121
+ oj_set_error_at(pi,
122
+ oj_parse_error_class,
123
+ __FILE__,
124
+ __LINE__,
125
+ "expected %s",
126
+ oj_stack_next_string(parent->next));
127
+ break;
128
+ }
125
129
  }
126
130
  }
127
131
 
128
- static void
129
- read_true(ParseInfo pi) {
132
+ static void read_true(ParseInfo pi) {
130
133
  if (0 == reader_expect(&pi->rd, "rue")) {
131
- add_value(pi, Qtrue);
134
+ add_value(pi, Qtrue);
132
135
  } else {
133
- oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "expected true");
136
+ oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "expected true");
134
137
  }
135
138
  }
136
139
 
137
- static void
138
- read_false(ParseInfo pi) {
140
+ static void read_false(ParseInfo pi) {
139
141
  if (0 == reader_expect(&pi->rd, "alse")) {
140
- add_value(pi, Qfalse);
142
+ add_value(pi, Qfalse);
141
143
  } else {
142
- oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "expected false");
144
+ oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "expected false");
143
145
  }
144
146
  }
145
147
 
146
- static uint32_t
147
- read_hex(ParseInfo pi) {
148
- uint32_t b = 0;
149
- int i;
150
- char c;
148
+ static uint32_t read_hex(ParseInfo pi) {
149
+ uint32_t b = 0;
150
+ int i;
151
+ char c;
151
152
 
152
153
  for (i = 0; i < 4; i++) {
153
- c = reader_get(&pi->rd);
154
- b = b << 4;
155
- if ('0' <= c && c <= '9') {
156
- b += c - '0';
157
- } else if ('A' <= c && c <= 'F') {
158
- b += c - 'A' + 10;
159
- } else if ('a' <= c && c <= 'f') {
160
- b += c - 'a' + 10;
161
- } else {
162
- oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "invalid hex character");
163
- return 0;
164
- }
154
+ c = reader_get(&pi->rd);
155
+ b = b << 4;
156
+ if ('0' <= c && c <= '9') {
157
+ b += c - '0';
158
+ } else if ('A' <= c && c <= 'F') {
159
+ b += c - 'A' + 10;
160
+ } else if ('a' <= c && c <= 'f') {
161
+ b += c - 'a' + 10;
162
+ } else {
163
+ oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "invalid hex character");
164
+ return 0;
165
+ }
165
166
  }
166
167
  return b;
167
168
  }
168
169
 
169
- static void
170
- unicode_to_chars(ParseInfo pi, Buf buf, uint32_t code) {
170
+ static void unicode_to_chars(ParseInfo pi, Buf buf, uint32_t code) {
171
171
  if (0x0000007F >= code) {
172
- buf_append(buf, (char)code);
172
+ buf_append(buf, (char)code);
173
173
  } else if (0x000007FF >= code) {
174
- buf_append(buf, 0xC0 | (code >> 6));
175
- buf_append(buf, 0x80 | (0x3F & code));
174
+ buf_append(buf, 0xC0 | (code >> 6));
175
+ buf_append(buf, 0x80 | (0x3F & code));
176
176
  } else if (0x0000FFFF >= code) {
177
- buf_append(buf, 0xE0 | (code >> 12));
178
- buf_append(buf, 0x80 | ((code >> 6) & 0x3F));
179
- buf_append(buf, 0x80 | (0x3F & code));
177
+ buf_append(buf, 0xE0 | (code >> 12));
178
+ buf_append(buf, 0x80 | ((code >> 6) & 0x3F));
179
+ buf_append(buf, 0x80 | (0x3F & code));
180
180
  } else if (0x001FFFFF >= code) {
181
- buf_append(buf, 0xF0 | (code >> 18));
182
- buf_append(buf, 0x80 | ((code >> 12) & 0x3F));
183
- buf_append(buf, 0x80 | ((code >> 6) & 0x3F));
184
- buf_append(buf, 0x80 | (0x3F & code));
181
+ buf_append(buf, 0xF0 | (code >> 18));
182
+ buf_append(buf, 0x80 | ((code >> 12) & 0x3F));
183
+ buf_append(buf, 0x80 | ((code >> 6) & 0x3F));
184
+ buf_append(buf, 0x80 | (0x3F & code));
185
185
  } else if (0x03FFFFFF >= code) {
186
- buf_append(buf, 0xF8 | (code >> 24));
187
- buf_append(buf, 0x80 | ((code >> 18) & 0x3F));
188
- buf_append(buf, 0x80 | ((code >> 12) & 0x3F));
189
- buf_append(buf, 0x80 | ((code >> 6) & 0x3F));
190
- buf_append(buf, 0x80 | (0x3F & code));
186
+ buf_append(buf, 0xF8 | (code >> 24));
187
+ buf_append(buf, 0x80 | ((code >> 18) & 0x3F));
188
+ buf_append(buf, 0x80 | ((code >> 12) & 0x3F));
189
+ buf_append(buf, 0x80 | ((code >> 6) & 0x3F));
190
+ buf_append(buf, 0x80 | (0x3F & code));
191
191
  } else if (0x7FFFFFFF >= code) {
192
- buf_append(buf, 0xFC | (code >> 30));
193
- buf_append(buf, 0x80 | ((code >> 24) & 0x3F));
194
- buf_append(buf, 0x80 | ((code >> 18) & 0x3F));
195
- buf_append(buf, 0x80 | ((code >> 12) & 0x3F));
196
- buf_append(buf, 0x80 | ((code >> 6) & 0x3F));
197
- buf_append(buf, 0x80 | (0x3F & code));
192
+ buf_append(buf, 0xFC | (code >> 30));
193
+ buf_append(buf, 0x80 | ((code >> 24) & 0x3F));
194
+ buf_append(buf, 0x80 | ((code >> 18) & 0x3F));
195
+ buf_append(buf, 0x80 | ((code >> 12) & 0x3F));
196
+ buf_append(buf, 0x80 | ((code >> 6) & 0x3F));
197
+ buf_append(buf, 0x80 | (0x3F & code));
198
198
  } else {
199
- oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "invalid Unicode character");
199
+ oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "invalid Unicode character");
200
200
  }
201
201
  }
202
202
 
203
203
  // entered at backslash
204
- static void
205
- read_escaped_str(ParseInfo pi) {
206
- struct _buf buf;
207
- char c;
208
- uint32_t code;
209
- Val parent = stack_peek(&pi->stack);
204
+ static void read_escaped_str(ParseInfo pi) {
205
+ struct _buf buf;
206
+ char c;
207
+ uint32_t code;
208
+ Val parent = stack_peek(&pi->stack);
210
209
 
211
210
  buf_init(&buf);
212
211
  if (pi->rd.str < pi->rd.tail) {
213
- buf_append_string(&buf, pi->rd.str, pi->rd.tail - pi->rd.str);
212
+ buf_append_string(&buf, pi->rd.str, pi->rd.tail - pi->rd.str);
214
213
  }
215
214
  while ('\"' != (c = reader_get(&pi->rd))) {
216
- if ('\0' == c) {
217
- oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "quoted string not terminated");
218
- buf_cleanup(&buf);
219
- return;
220
- } else if ('\\' == c) {
221
- c = reader_get(&pi->rd);
222
- switch (c) {
223
- case 'n': buf_append(&buf, '\n'); break;
224
- case 'r': buf_append(&buf, '\r'); break;
225
- case 't': buf_append(&buf, '\t'); break;
226
- case 'f': buf_append(&buf, '\f'); break;
227
- case 'b': buf_append(&buf, '\b'); break;
228
- case '"': buf_append(&buf, '"'); break;
229
- case '/': buf_append(&buf, '/'); break;
230
- 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
- case 'u':
243
- if (0 == (code = read_hex(pi)) && err_has(&pi->err)) {
244
- buf_cleanup(&buf);
245
- return;
246
- }
247
- if (0x0000D800 <= code && code <= 0x0000DFFF) {
248
- uint32_t c1 = (code - 0x0000D800) & 0x000003FF;
249
- uint32_t c2;
250
- char ch2;
251
-
252
- c = reader_get(&pi->rd);
253
- ch2 = reader_get(&pi->rd);
254
- if ('\\' != c || 'u' != ch2) {
255
- if (Yes == pi->options.allow_invalid) {
256
- unicode_to_chars(pi, &buf, code);
257
- reader_backup(&pi->rd);
258
- reader_backup(&pi->rd);
259
- break;
260
- }
261
- oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "invalid escaped character");
262
- buf_cleanup(&buf);
263
- return;
264
- }
265
- if (0 == (c2 = read_hex(pi)) && err_has(&pi->err)) {
266
- buf_cleanup(&buf);
267
- return;
268
- }
269
- c2 = (c2 - 0x0000DC00) & 0x000003FF;
270
- code = ((c1 << 10) | c2) + 0x00010000;
271
- }
272
- unicode_to_chars(pi, &buf, code);
273
- if (err_has(&pi->err)) {
274
- buf_cleanup(&buf);
275
- return;
276
- }
277
- break;
278
- default:
279
- oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "invalid escaped character");
280
- buf_cleanup(&buf);
281
- return;
282
- }
283
- } else {
284
- buf_append(&buf, c);
285
- }
215
+ if ('\0' == c) {
216
+ oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "quoted string not terminated");
217
+ buf_cleanup(&buf);
218
+ return;
219
+ } else if ('\\' == c) {
220
+ c = reader_get(&pi->rd);
221
+ switch (c) {
222
+ case 'n': buf_append(&buf, '\n'); break;
223
+ case 'r': buf_append(&buf, '\r'); break;
224
+ case 't': buf_append(&buf, '\t'); break;
225
+ case 'f': buf_append(&buf, '\f'); break;
226
+ case 'b': buf_append(&buf, '\b'); break;
227
+ case '"': buf_append(&buf, '"'); break;
228
+ case '/': buf_append(&buf, '/'); break;
229
+ case '\\': buf_append(&buf, '\\'); break;
230
+ case 'u':
231
+ if (0 == (code = read_hex(pi)) && err_has(&pi->err)) {
232
+ buf_cleanup(&buf);
233
+ return;
234
+ }
235
+ if (0x0000D800 <= code && code <= 0x0000DFFF) {
236
+ uint32_t c1 = (code - 0x0000D800) & 0x000003FF;
237
+ uint32_t c2;
238
+ char ch2;
239
+
240
+ c = reader_get(&pi->rd);
241
+ ch2 = reader_get(&pi->rd);
242
+ if ('\\' != c || 'u' != ch2) {
243
+ if (Yes == pi->options.allow_invalid) {
244
+ unicode_to_chars(pi, &buf, code);
245
+ reader_backup(&pi->rd);
246
+ reader_backup(&pi->rd);
247
+ break;
248
+ }
249
+ oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "invalid escaped character");
250
+ buf_cleanup(&buf);
251
+ return;
252
+ }
253
+ if (0 == (c2 = read_hex(pi)) && err_has(&pi->err)) {
254
+ buf_cleanup(&buf);
255
+ return;
256
+ }
257
+ c2 = (c2 - 0x0000DC00) & 0x000003FF;
258
+ code = ((c1 << 10) | c2) + 0x00010000;
259
+ }
260
+ unicode_to_chars(pi, &buf, code);
261
+ if (err_has(&pi->err)) {
262
+ buf_cleanup(&buf);
263
+ return;
264
+ }
265
+ break;
266
+ default:
267
+ // The json gem claims this is not an error despite the
268
+ // ECMA-404 indicating it is not valid.
269
+ if (CompatMode == pi->options.mode) {
270
+ buf_append(&buf, c);
271
+ break;
272
+ }
273
+ oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "invalid escaped character");
274
+ buf_cleanup(&buf);
275
+ return;
276
+ }
277
+ } else {
278
+ buf_append(&buf, c);
279
+ }
286
280
  }
287
281
  if (0 == parent) {
288
- pi->add_cstr(pi, buf.head, buf_len(&buf), pi->rd.str);
282
+ pi->add_cstr(pi, buf.head, buf_len(&buf), pi->rd.str);
289
283
  } else {
290
- switch (parent->next) {
291
- case NEXT_ARRAY_NEW:
292
- case NEXT_ARRAY_ELEMENT:
293
- pi->array_append_cstr(pi, buf.head, buf_len(&buf), pi->rd.str);
294
- parent->next = NEXT_ARRAY_COMMA;
295
- break;
296
- case NEXT_HASH_NEW:
297
- case NEXT_HASH_KEY:
298
- if (Qundef == (parent->key_val = pi->hash_key(pi, buf.head, buf_len(&buf)))) {
299
- parent->klen = buf_len(&buf);
300
- parent->key = malloc(parent->klen + 1);
301
- memcpy((char*)parent->key, buf.head, parent->klen);
302
- *(char*)(parent->key + parent->klen) = '\0';
303
- } else {
304
- parent->key = "";
305
- parent->klen = 0;
306
- }
307
- parent->k1 = *pi->rd.str;
308
- parent->next = NEXT_HASH_COLON;
309
- break;
310
- case NEXT_HASH_VALUE:
311
- pi->hash_set_cstr(pi, parent, buf.head, buf_len(&buf), pi->rd.str);
312
- if (parent->kalloc) {
313
- xfree((char*)parent->key);
314
- }
315
- parent->key = 0;
316
- parent->kalloc = 0;
317
- parent->next = NEXT_HASH_COMMA;
318
- break;
319
- case NEXT_HASH_COMMA:
320
- case NEXT_NONE:
321
- case NEXT_ARRAY_COMMA:
322
- case NEXT_HASH_COLON:
323
- default:
324
- oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "expected %s, not a string", oj_stack_next_string(parent->next));
325
- break;
326
- }
284
+ switch (parent->next) {
285
+ case NEXT_ARRAY_NEW:
286
+ case NEXT_ARRAY_ELEMENT:
287
+ pi->array_append_cstr(pi, buf.head, buf_len(&buf), pi->rd.str);
288
+ parent->next = NEXT_ARRAY_COMMA;
289
+ break;
290
+ case NEXT_HASH_NEW:
291
+ case NEXT_HASH_KEY:
292
+ if (Qundef == (parent->key_val = pi->hash_key(pi, buf.head, buf_len(&buf)))) {
293
+ parent->klen = buf_len(&buf);
294
+ parent->key = malloc(parent->klen + 1);
295
+ memcpy((char *)parent->key, buf.head, parent->klen);
296
+ *(char *)(parent->key + parent->klen) = '\0';
297
+ } else {
298
+ parent->key = "";
299
+ parent->klen = 0;
300
+ }
301
+ parent->k1 = *pi->rd.str;
302
+ parent->next = NEXT_HASH_COLON;
303
+ break;
304
+ case NEXT_HASH_VALUE:
305
+ pi->hash_set_cstr(pi, parent, buf.head, buf_len(&buf), pi->rd.str);
306
+ if (parent->kalloc) {
307
+ OJ_R_FREE((char *)parent->key);
308
+ }
309
+ parent->key = 0;
310
+ parent->kalloc = 0;
311
+ parent->next = NEXT_HASH_COMMA;
312
+ break;
313
+ case NEXT_HASH_COMMA:
314
+ case NEXT_NONE:
315
+ case NEXT_ARRAY_COMMA:
316
+ case NEXT_HASH_COLON:
317
+ default:
318
+ oj_set_error_at(pi,
319
+ oj_parse_error_class,
320
+ __FILE__,
321
+ __LINE__,
322
+ "expected %s, not a string",
323
+ oj_stack_next_string(parent->next));
324
+ break;
325
+ }
327
326
  }
328
327
  buf_cleanup(&buf);
329
328
  }
330
329
 
331
- static void
332
- read_str(ParseInfo pi) {
333
- Val parent = stack_peek(&pi->stack);
334
- char c;
330
+ static void read_str(ParseInfo pi) {
331
+ Val parent = stack_peek(&pi->stack);
332
+ char c;
335
333
 
336
334
  reader_protect(&pi->rd);
337
335
  while ('\"' != (c = reader_get(&pi->rd))) {
338
- if ('\0' == c) {
339
- oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "quoted string not terminated");
340
- return;
341
- } else if ('\\' == c) {
342
- reader_backup(&pi->rd);
343
- read_escaped_str(pi);
344
- reader_release(&pi->rd);
345
- return;
346
- }
347
- }
348
- if (0 == parent) { // simple add
349
- pi->add_cstr(pi, pi->rd.str, pi->rd.tail - pi->rd.str - 1, pi->rd.str);
336
+ if ('\0' == c) {
337
+ oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "quoted string not terminated");
338
+ return;
339
+ } else if ('\\' == c) {
340
+ reader_backup(&pi->rd);
341
+ read_escaped_str(pi);
342
+ reader_release(&pi->rd);
343
+ return;
344
+ }
345
+ }
346
+ if (0 == parent) { // simple add
347
+ pi->add_cstr(pi, pi->rd.str, pi->rd.tail - pi->rd.str - 1, pi->rd.str);
350
348
  } else {
351
- switch (parent->next) {
352
- case NEXT_ARRAY_NEW:
353
- case NEXT_ARRAY_ELEMENT:
354
- pi->array_append_cstr(pi, pi->rd.str, pi->rd.tail - pi->rd.str - 1, pi->rd.str);
355
- parent->next = NEXT_ARRAY_COMMA;
356
- break;
357
- case NEXT_HASH_NEW:
358
- case NEXT_HASH_KEY:
359
- parent->klen = pi->rd.tail - pi->rd.str - 1;
360
- if (sizeof(parent->karray) <= parent->klen) {
361
- parent->key = oj_strndup(pi->rd.str, parent->klen);
362
- parent->kalloc = 1;
363
- } else {
364
- memcpy(parent->karray, pi->rd.str, parent->klen);
365
- parent->karray[parent->klen] = '\0';
366
- parent->key = parent->karray;
367
- parent->kalloc = 0;
368
- }
369
- parent->key_val = pi->hash_key(pi, parent->key, parent->klen);
370
- parent->k1 = *pi->rd.str;
371
- parent->next = NEXT_HASH_COLON;
372
- break;
373
- case NEXT_HASH_VALUE:
374
- pi->hash_set_cstr(pi, parent, pi->rd.str, pi->rd.tail - pi->rd.str - 1, pi->rd.str);
375
- if (parent->kalloc) {
376
- xfree((char*)parent->key);
377
- }
378
- parent->key = 0;
379
- parent->kalloc = 0;
380
- parent->next = NEXT_HASH_COMMA;
381
- break;
382
- case NEXT_HASH_COMMA:
383
- case NEXT_NONE:
384
- case NEXT_ARRAY_COMMA:
385
- case NEXT_HASH_COLON:
386
- default:
387
- oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "expected %s, not a string", oj_stack_next_string(parent->next));
388
- break;
389
- }
349
+ switch (parent->next) {
350
+ case NEXT_ARRAY_NEW:
351
+ case NEXT_ARRAY_ELEMENT:
352
+ pi->array_append_cstr(pi, pi->rd.str, pi->rd.tail - pi->rd.str - 1, pi->rd.str);
353
+ parent->next = NEXT_ARRAY_COMMA;
354
+ break;
355
+ case NEXT_HASH_NEW:
356
+ case NEXT_HASH_KEY:
357
+ parent->klen = pi->rd.tail - pi->rd.str - 1;
358
+ if (sizeof(parent->karray) <= parent->klen) {
359
+ parent->key = oj_strndup(pi->rd.str, parent->klen);
360
+ parent->kalloc = 1;
361
+ } else {
362
+ memcpy(parent->karray, pi->rd.str, parent->klen);
363
+ parent->karray[parent->klen] = '\0';
364
+ parent->key = parent->karray;
365
+ parent->kalloc = 0;
366
+ }
367
+ parent->key_val = pi->hash_key(pi, parent->key, parent->klen);
368
+ parent->k1 = *pi->rd.str;
369
+ parent->next = NEXT_HASH_COLON;
370
+ break;
371
+ case NEXT_HASH_VALUE:
372
+ pi->hash_set_cstr(pi, parent, pi->rd.str, pi->rd.tail - pi->rd.str - 1, pi->rd.str);
373
+ if (parent->kalloc) {
374
+ OJ_R_FREE((char *)parent->key);
375
+ }
376
+ parent->key = 0;
377
+ parent->kalloc = 0;
378
+ parent->next = NEXT_HASH_COMMA;
379
+ break;
380
+ case NEXT_HASH_COMMA:
381
+ case NEXT_NONE:
382
+ case NEXT_ARRAY_COMMA:
383
+ case NEXT_HASH_COLON:
384
+ default:
385
+ oj_set_error_at(pi,
386
+ oj_parse_error_class,
387
+ __FILE__,
388
+ __LINE__,
389
+ "expected %s, not a string",
390
+ oj_stack_next_string(parent->next));
391
+ break;
392
+ }
390
393
  }
391
394
  reader_release(&pi->rd);
392
395
  }
393
396
 
394
- static void
395
- read_num(ParseInfo pi) {
396
- struct _numInfo ni;
397
- char c;
397
+ static void read_num(ParseInfo pi) {
398
+ struct _numInfo ni;
399
+ char c;
398
400
 
399
401
  reader_protect(&pi->rd);
400
- ni.i = 0;
401
- ni.num = 0;
402
- ni.div = 1;
403
- ni.di = 0;
404
- ni.len = 0;
405
- ni.exp = 0;
406
- ni.big = 0;
402
+ ni.i = 0;
403
+ ni.num = 0;
404
+ ni.div = 1;
405
+ ni.di = 0;
406
+ ni.len = 0;
407
+ ni.exp = 0;
408
+ ni.big = 0;
407
409
  ni.infinity = 0;
408
- ni.nan = 0;
409
- ni.neg = 0;
410
- ni.hasExp = 0;
411
- ni.no_big = (FloatDec == pi->options.bigdec_load);
410
+ ni.nan = 0;
411
+ ni.neg = 0;
412
+ ni.has_exp = 0;
413
+ if (CompatMode == pi->options.mode) {
414
+ ni.no_big = !pi->options.compat_bigdec;
415
+ ni.bigdec_load = pi->options.compat_bigdec;
416
+ } else {
417
+ ni.no_big = (FloatDec == pi->options.bigdec_load || FastDec == pi->options.bigdec_load ||
418
+ RubyDec == pi->options.bigdec_load);
419
+ ni.bigdec_load = pi->options.bigdec_load;
420
+ }
421
+
412
422
  c = reader_get(&pi->rd);
413
423
  if ('-' == c) {
414
- c = reader_get(&pi->rd);
415
- ni.neg = 1;
424
+ c = reader_get(&pi->rd);
425
+ ni.neg = 1;
416
426
  } else if ('+' == c) {
417
- c = reader_get(&pi->rd);
427
+ c = reader_get(&pi->rd);
418
428
  }
419
429
  if ('I' == c) {
420
- if (No == pi->options.allow_nan) {
421
- oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "not a number or other value");
422
- return;
423
- } else if (0 != reader_expect(&pi->rd, "nfinity")) {
424
- oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "not a number or other value");
425
- return;
426
- }
427
- ni.infinity = 1;
430
+ if (No == pi->options.allow_nan) {
431
+ oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "not a number or other value");
432
+ return;
433
+ } else if (0 != reader_expect(&pi->rd, "nfinity")) {
434
+ oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "not a number or other value");
435
+ return;
436
+ }
437
+ ni.infinity = 1;
428
438
  } else {
429
- int dec_cnt = 0;
430
- bool zero1 = false;
431
-
432
- for (; '0' <= c && c <= '9'; c = reader_get(&pi->rd)) {
433
- if (0 == ni.i && '0' == c) {
434
- zero1 = true;
435
- }
436
- if (0 < ni.i) {
437
- dec_cnt++;
438
- }
439
- if (ni.big) {
440
- ni.big++;
441
- } else {
442
- int d = (c - '0');
443
-
444
- if (0 < d) {
445
- if (zero1 && CompatMode == pi->options.mode) {
446
- oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "not a number");
447
- return;
448
- }
449
- zero1 = false;
450
- }
451
- ni.i = ni.i * 10 + d;
452
- if (INT64_MAX <= ni.i || DEC_MAX < dec_cnt) {
453
- ni.big = 1;
454
- }
455
- }
456
- }
457
- if ('.' == c) {
458
- c = reader_get(&pi->rd);
459
- // A trailing . is not a valid decimal but if encountered allow it
460
- // except when mimicing the JSON gem.
461
- if (CompatMode == pi->options.mode) {
462
- if (c < '0' || '9' < c) {
463
- oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "not a number");
464
- }
465
- }
466
- for (; '0' <= c && c <= '9'; c = reader_get(&pi->rd)) {
467
- int d = (c - '0');
468
-
469
- if (0 < ni.num || 0 < ni.i) {
470
- dec_cnt++;
471
- }
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;
477
- }
478
- }
479
- }
480
- if ('e' == c || 'E' == c) {
481
- int eneg = 0;
482
-
483
- ni.hasExp = 1;
484
- c = reader_get(&pi->rd);
485
- if ('-' == c) {
486
- c = reader_get(&pi->rd);
487
- eneg = 1;
488
- } else if ('+' == c) {
489
- c = reader_get(&pi->rd);
490
- }
491
- for (; '0' <= c && c <= '9'; c = reader_get(&pi->rd)) {
492
- ni.exp = ni.exp * 10 + (c - '0');
493
- if (EXP_MAX <= ni.exp) {
494
- ni.big = 1;
495
- }
496
- }
497
- if (eneg) {
498
- ni.exp = -ni.exp;
499
- }
500
- }
501
- ni.len = pi->rd.tail - pi->rd.str;
502
- if (0 != c) {
503
- reader_backup(&pi->rd);
504
- }
439
+ int dec_cnt = 0;
440
+ bool zero1 = false;
441
+
442
+ for (; '0' <= c && c <= '9'; c = reader_get(&pi->rd)) {
443
+ if (0 == ni.i && '0' == c) {
444
+ zero1 = true;
445
+ }
446
+ if (0 < ni.i) {
447
+ dec_cnt++;
448
+ }
449
+ if (ni.big) {
450
+ ni.big++;
451
+ } else {
452
+ int d = (c - '0');
453
+
454
+ if (0 < d) {
455
+ if (zero1 && CompatMode == pi->options.mode) {
456
+ oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "not a number");
457
+ return;
458
+ }
459
+ zero1 = false;
460
+ }
461
+ ni.i = ni.i * 10 + d;
462
+ if (INT64_MAX <= ni.i || DEC_MAX < dec_cnt) {
463
+ ni.big = 1;
464
+ }
465
+ }
466
+ }
467
+ if ('.' == c) {
468
+ c = reader_get(&pi->rd);
469
+ // A trailing . is not a valid decimal but if encountered allow it
470
+ // except when mimicking the JSON gem.
471
+ if (CompatMode == pi->options.mode) {
472
+ if (c < '0' || '9' < c) {
473
+ oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "not a number");
474
+ }
475
+ }
476
+ for (; '0' <= c && c <= '9'; c = reader_get(&pi->rd)) {
477
+ int d = (c - '0');
478
+
479
+ if (0 < ni.num || 0 < ni.i) {
480
+ dec_cnt++;
481
+ }
482
+ if (INT64_MAX <= ni.div) {
483
+ if (!ni.no_big) {
484
+ ni.big = true;
485
+ }
486
+ } else {
487
+ ni.num = ni.num * 10 + d;
488
+ ni.div *= 10;
489
+ ni.di++;
490
+ if (INT64_MAX <= ni.div || DEC_MAX < dec_cnt) {
491
+ if (!ni.no_big) {
492
+ ni.big = true;
493
+ }
494
+ }
495
+ }
496
+ }
497
+ }
498
+ if ('e' == c || 'E' == c) {
499
+ int eneg = 0;
500
+
501
+ ni.has_exp = 1;
502
+ c = reader_get(&pi->rd);
503
+ if ('-' == c) {
504
+ c = reader_get(&pi->rd);
505
+ eneg = 1;
506
+ } else if ('+' == c) {
507
+ c = reader_get(&pi->rd);
508
+ }
509
+ for (; '0' <= c && c <= '9'; c = reader_get(&pi->rd)) {
510
+ ni.exp = ni.exp * 10 + (c - '0');
511
+ if (EXP_MAX <= ni.exp) {
512
+ ni.big = 1;
513
+ }
514
+ }
515
+ if (eneg) {
516
+ ni.exp = -ni.exp;
517
+ }
518
+ }
519
+ ni.len = pi->rd.tail - pi->rd.str;
520
+ if (0 != c) {
521
+ reader_backup(&pi->rd);
522
+ }
505
523
  }
506
524
  ni.str = pi->rd.str;
507
525
  ni.len = pi->rd.tail - pi->rd.str;
508
526
  // Check for special reserved values for Infinity and NaN.
509
527
  if (ni.big) {
510
- if (0 == strcasecmp(INF_VAL, ni.str)) {
511
- ni.infinity = 1;
512
- } else if (0 == strcasecmp(NINF_VAL, ni.str)) {
513
- ni.infinity = 1;
514
- ni.neg = 1;
515
- } else if (0 == strcasecmp(NAN_VAL, ni.str)) {
516
- ni.nan = 1;
517
- }
518
- }
519
- if (BigDec == pi->options.bigdec_load) {
520
- ni.big = 1;
528
+ if (0 == strcasecmp(INF_VAL, ni.str)) {
529
+ ni.infinity = 1;
530
+ } else if (0 == strcasecmp(NINF_VAL, ni.str)) {
531
+ ni.infinity = 1;
532
+ ni.neg = 1;
533
+ } else if (0 == strcasecmp(NAN_VAL, ni.str)) {
534
+ ni.nan = 1;
535
+ }
536
+ }
537
+ if (CompatMode == pi->options.mode) {
538
+ if (pi->options.compat_bigdec) {
539
+ ni.big = 1;
540
+ }
541
+ } else if (BigDec == pi->options.bigdec_load) {
542
+ ni.big = 1;
521
543
  }
522
544
  add_num_value(pi, &ni);
523
545
  reader_release(&pi->rd);
524
546
  }
525
547
 
526
- static void
527
- read_nan(ParseInfo pi) {
528
- struct _numInfo ni;
529
- char c;
530
-
531
- ni.str = pi->rd.str;
532
- ni.i = 0;
533
- ni.num = 0;
534
- ni.div = 1;
535
- ni.di = 0;
536
- ni.len = 0;
537
- ni.exp = 0;
538
- ni.big = 0;
548
+ static void read_nan(ParseInfo pi) {
549
+ struct _numInfo ni;
550
+ char c;
551
+
552
+ ni.str = pi->rd.str;
553
+ ni.i = 0;
554
+ ni.num = 0;
555
+ ni.div = 1;
556
+ ni.di = 0;
557
+ ni.len = 0;
558
+ ni.exp = 0;
559
+ ni.big = 0;
539
560
  ni.infinity = 0;
540
- ni.nan = 1;
541
- ni.neg = 0;
542
- ni.no_big = (FloatDec == pi->options.bigdec_load);
561
+ ni.nan = 1;
562
+ ni.neg = 0;
563
+ if (CompatMode == pi->options.mode) {
564
+ ni.no_big = !pi->options.compat_bigdec;
565
+ ni.bigdec_load = pi->options.compat_bigdec;
566
+ } else {
567
+ ni.no_big = (FloatDec == pi->options.bigdec_load || FastDec == pi->options.bigdec_load ||
568
+ RubyDec == pi->options.bigdec_load);
569
+ ni.bigdec_load = pi->options.bigdec_load;
570
+ }
543
571
 
544
- if ('a' != reader_get(&pi->rd) ||
545
- ('N' != (c = reader_get(&pi->rd)) && 'n' != c)) {
546
- oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "not a number or other value");
547
- return;
572
+ if ('a' != reader_get(&pi->rd) || ('N' != (c = reader_get(&pi->rd)) && 'n' != c)) {
573
+ oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "not a number or other value");
574
+ return;
548
575
  }
549
- if (BigDec == pi->options.bigdec_load) {
550
- ni.big = 1;
576
+ if (CompatMode == pi->options.mode) {
577
+ if (pi->options.compat_bigdec) {
578
+ ni.big = 1;
579
+ }
580
+ } else if (BigDec == pi->options.bigdec_load) {
581
+ ni.big = 1;
551
582
  }
552
583
  add_num_value(pi, &ni);
553
584
  }
554
585
 
555
- static void
556
- array_start(ParseInfo pi) {
557
- VALUE v = pi->start_array(pi);
586
+ static void array_start(ParseInfo pi) {
587
+ VALUE v = pi->start_array(pi);
558
588
 
559
589
  stack_push(&pi->stack, v, NEXT_ARRAY_NEW);
560
590
  }
561
591
 
562
- static void
563
- array_end(ParseInfo pi) {
564
- Val array = stack_pop(&pi->stack);
592
+ static void array_end(ParseInfo pi) {
593
+ Val array = stack_pop(&pi->stack);
565
594
 
566
595
  if (0 == array) {
567
- oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "unexpected array close");
596
+ oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "unexpected array close");
568
597
  } else if (NEXT_ARRAY_COMMA != array->next && NEXT_ARRAY_NEW != array->next) {
569
- oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "expected %s, not an array close", oj_stack_next_string(array->next));
598
+ oj_set_error_at(pi,
599
+ oj_parse_error_class,
600
+ __FILE__,
601
+ __LINE__,
602
+ "expected %s, not an array close",
603
+ oj_stack_next_string(array->next));
570
604
  } else {
571
- pi->end_array(pi);
572
- add_value(pi, array->val);
605
+ pi->end_array(pi);
606
+ add_value(pi, array->val);
573
607
  }
574
608
  }
575
609
 
576
- static void
577
- hash_start(ParseInfo pi) {
578
- volatile VALUE v = pi->start_hash(pi);
610
+ static void hash_start(ParseInfo pi) {
611
+ volatile VALUE v = pi->start_hash(pi);
579
612
 
580
613
  stack_push(&pi->stack, v, NEXT_HASH_NEW);
581
614
  }
582
615
 
583
- static void
584
- hash_end(ParseInfo pi) {
585
- volatile Val hash = stack_peek(&pi->stack);
616
+ static void hash_end(ParseInfo pi) {
617
+ volatile Val hash = stack_peek(&pi->stack);
586
618
 
587
619
  // leave hash on stack until just before
588
620
  if (0 == hash) {
589
- oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "unexpected hash close");
621
+ oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "unexpected hash close");
590
622
  } else if (NEXT_HASH_COMMA != hash->next && NEXT_HASH_NEW != hash->next) {
591
- oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "expected %s, not a hash close", oj_stack_next_string(hash->next));
623
+ oj_set_error_at(pi,
624
+ oj_parse_error_class,
625
+ __FILE__,
626
+ __LINE__,
627
+ "expected %s, not a hash close",
628
+ oj_stack_next_string(hash->next));
592
629
  } else {
593
- pi->end_hash(pi);
594
- stack_pop(&pi->stack);
595
- add_value(pi, hash->val);
630
+ pi->end_hash(pi);
631
+ stack_pop(&pi->stack);
632
+ add_value(pi, hash->val);
596
633
  }
597
634
  }
598
635
 
599
- static void
600
- comma(ParseInfo pi) {
601
- Val parent = stack_peek(&pi->stack);
636
+ static void comma(ParseInfo pi) {
637
+ Val parent = stack_peek(&pi->stack);
602
638
 
603
639
  if (0 == parent) {
604
- oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "unexpected comma");
640
+ oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "unexpected comma");
605
641
  } else if (NEXT_ARRAY_COMMA == parent->next) {
606
- parent->next = NEXT_ARRAY_ELEMENT;
642
+ parent->next = NEXT_ARRAY_ELEMENT;
607
643
  } else if (NEXT_HASH_COMMA == parent->next) {
608
- parent->next = NEXT_HASH_KEY;
644
+ parent->next = NEXT_HASH_KEY;
609
645
  } else {
610
- oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "unexpected comma");
646
+ oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "unexpected comma");
611
647
  }
612
648
  }
613
649
 
614
- static void
615
- colon(ParseInfo pi) {
616
- Val parent = stack_peek(&pi->stack);
650
+ static void colon(ParseInfo pi) {
651
+ Val parent = stack_peek(&pi->stack);
617
652
 
618
653
  if (0 != parent && NEXT_HASH_COLON == parent->next) {
619
- parent->next = NEXT_HASH_VALUE;
654
+ parent->next = NEXT_HASH_VALUE;
620
655
  } else {
621
- oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "unexpected colon");
656
+ oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "unexpected colon");
622
657
  }
623
658
  }
624
659
 
625
- void
626
- oj_sparse2(ParseInfo pi) {
627
- int first = 1;
628
- char c;
629
- long start = 0;
660
+ void oj_sparse2(ParseInfo pi) {
661
+ int first = 1;
662
+ char c;
663
+ long start = 0;
630
664
 
631
665
  err_init(&pi->err);
632
666
  while (1) {
633
- if (0 < pi->max_depth && pi->max_depth <= pi->stack.tail - pi->stack.head - 1) {
634
- VALUE err_clas = oj_get_json_err_class("NestingError");
635
-
636
- oj_set_error_at(pi, err_clas, __FILE__, __LINE__, "Too deeply nested.");
637
- pi->err_class = err_clas;
638
- return;
639
- }
640
- c = reader_next_non_white(&pi->rd);
641
- if (!first && '\0' != c) {
642
- oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "unexpected characters after the JSON document");
643
- }
644
- switch (c) {
645
- case '{':
646
- hash_start(pi);
647
- break;
648
- case '}':
649
- hash_end(pi);
650
- break;
651
- case ':':
652
- colon(pi);
653
- break;
654
- case '[':
655
- array_start(pi);
656
- break;
657
- case ']':
658
- array_end(pi);
659
- break;
660
- case ',':
661
- comma(pi);
662
- break;
663
- case '"':
664
- read_str(pi);
665
- break;
666
- case '+':
667
- if (CompatMode == pi->options.mode) {
668
- oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "unexpected character");
669
- return;
670
- }
671
- pi->cur--;
672
- read_num(pi);
673
- break;
674
- case '-':
675
- case '0':
676
- case '1':
677
- case '2':
678
- case '3':
679
- case '4':
680
- case '5':
681
- case '6':
682
- case '7':
683
- case '8':
684
- case '9':
685
- reader_backup(&pi->rd);
686
- read_num(pi);
687
- break;
688
- case 'I':
689
- if (Yes == pi->options.allow_nan) {
690
- reader_backup(&pi->rd);
691
- read_num(pi);
692
- } else {
693
- oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "unexpected character");
694
- return;
695
- }
696
- break;
697
- case 'N':
698
- if (Yes == pi->options.allow_nan) {
699
- read_nan(pi);
700
- } else {
701
- oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "unexpected character");
702
- return;
703
- }
704
- break;
705
- case 't':
706
- read_true(pi);
707
- break;
708
- case 'f':
709
- read_false(pi);
710
- break;
711
- case 'n':
712
- c = reader_get(&pi->rd);
713
- if ('u' == c) {
714
- if (0 == reader_expect(&pi->rd, "ll")) {
715
- add_value(pi, Qnil);
716
- } else {
717
- oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "expected null");
718
- return;
719
- }
720
- } else if ('a' == c) {
721
- struct _numInfo ni;
722
-
723
- c = reader_get(&pi->rd);
724
- if ('N' != c && 'n' != c) {
725
- oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "expected NaN");
726
- return;
727
- }
728
- ni.str = pi->rd.str;
729
- ni.i = 0;
730
- ni.num = 0;
731
- ni.div = 1;
732
- ni.di = 0;
733
- ni.len = 0;
734
- ni.exp = 0;
735
- ni.big = 0;
736
- ni.infinity = 0;
737
- ni.nan = 1;
738
- ni.neg = 0;
739
- ni.no_big = (FloatDec == pi->options.bigdec_load);
740
- add_num_value(pi, &ni);
741
- } else {
742
- oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "invalid token");
743
- return;
744
- }
745
- break;
746
- case '/':
747
- skip_comment(pi);
748
- break;
749
- case '\0':
750
- return;
751
- default:
752
- oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "unexpected character '%c' [0x%02x]", c, c);
753
- return;
754
- }
755
- if (err_has(&pi->err)) {
756
- return;
757
- }
758
- if (stack_empty(&pi->stack)) {
759
- if (Qundef != pi->proc) {
760
- VALUE args[3];
761
- long len = pi->rd.pos - start;
762
-
763
- *args = stack_head_val(&pi->stack);
764
- args[1] = LONG2NUM(start);
765
- args[2] = LONG2NUM(len);
766
-
767
- if (Qnil == pi->proc) {
768
- rb_yield_values2(3, args);
769
- } else {
770
- rb_proc_call_with_block(pi->proc, 3, args, Qnil);
771
- }
772
- } else if (!pi->has_callbacks) {
773
- first = 0;
774
- }
775
- start = pi->rd.pos;
776
- }
667
+ if (0 < pi->max_depth && pi->max_depth <= pi->stack.tail - pi->stack.head - 1) {
668
+ VALUE err_clas = oj_get_json_err_class("NestingError");
669
+
670
+ oj_set_error_at(pi, err_clas, __FILE__, __LINE__, "Too deeply nested.");
671
+ pi->err_class = err_clas;
672
+ return;
673
+ }
674
+ c = reader_next_non_white(&pi->rd);
675
+ if (!first && '\0' != c) {
676
+ oj_set_error_at(pi,
677
+ oj_parse_error_class,
678
+ __FILE__,
679
+ __LINE__,
680
+ "unexpected characters after the JSON document");
681
+ }
682
+ switch (c) {
683
+ case '{': hash_start(pi); break;
684
+ case '}': hash_end(pi); break;
685
+ case ':': colon(pi); break;
686
+ case '[': array_start(pi); break;
687
+ case ']': array_end(pi); break;
688
+ case ',': comma(pi); break;
689
+ case '"': read_str(pi); break;
690
+ case '+':
691
+ if (CompatMode == pi->options.mode) {
692
+ oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "unexpected character");
693
+ return;
694
+ }
695
+ pi->cur--;
696
+ read_num(pi);
697
+ break;
698
+ case '-':
699
+ case '0':
700
+ case '1':
701
+ case '2':
702
+ case '3':
703
+ case '4':
704
+ case '5':
705
+ case '6':
706
+ case '7':
707
+ case '8':
708
+ case '9':
709
+ reader_backup(&pi->rd);
710
+ read_num(pi);
711
+ break;
712
+ case 'I':
713
+ if (Yes == pi->options.allow_nan) {
714
+ reader_backup(&pi->rd);
715
+ read_num(pi);
716
+ } else {
717
+ oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "unexpected character");
718
+ return;
719
+ }
720
+ break;
721
+ case 'N':
722
+ if (Yes == pi->options.allow_nan) {
723
+ read_nan(pi);
724
+ } else {
725
+ oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "unexpected character");
726
+ return;
727
+ }
728
+ break;
729
+ case 't': read_true(pi); break;
730
+ case 'f': read_false(pi); break;
731
+ case 'n':
732
+ c = reader_get(&pi->rd);
733
+ if ('u' == c) {
734
+ if (0 == reader_expect(&pi->rd, "ll")) {
735
+ add_value(pi, Qnil);
736
+ } else {
737
+ oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "expected null");
738
+ return;
739
+ }
740
+ } else if ('a' == c) {
741
+ struct _numInfo ni;
742
+
743
+ c = reader_get(&pi->rd);
744
+ if ('N' != c && 'n' != c) {
745
+ oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "expected NaN");
746
+ return;
747
+ }
748
+ ni.str = pi->rd.str;
749
+ ni.i = 0;
750
+ ni.num = 0;
751
+ ni.div = 1;
752
+ ni.di = 0;
753
+ ni.len = 0;
754
+ ni.exp = 0;
755
+ ni.big = 0;
756
+ ni.infinity = 0;
757
+ ni.nan = 1;
758
+ ni.neg = 0;
759
+ if (CompatMode == pi->options.mode) {
760
+ ni.no_big = !pi->options.compat_bigdec;
761
+ ni.bigdec_load = pi->options.compat_bigdec;
762
+ } else {
763
+ ni.no_big = (FloatDec == pi->options.bigdec_load || FastDec == pi->options.bigdec_load ||
764
+ RubyDec == pi->options.bigdec_load);
765
+ ni.bigdec_load = pi->options.bigdec_load;
766
+ }
767
+ add_num_value(pi, &ni);
768
+ } else {
769
+ oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "invalid token");
770
+ return;
771
+ }
772
+ break;
773
+ case '/': skip_comment(pi); break;
774
+ case '\0': return;
775
+ default:
776
+ oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "unexpected character '%c' [0x%02x]", c, c);
777
+ return;
778
+ }
779
+ if (err_has(&pi->err)) {
780
+ return;
781
+ }
782
+ if (stack_empty(&pi->stack)) {
783
+ if (Qundef != pi->proc) {
784
+ VALUE args[3];
785
+ long len = pi->rd.pos - start;
786
+
787
+ *args = stack_head_val(&pi->stack);
788
+ args[1] = LONG2NUM(start);
789
+ args[2] = LONG2NUM(len);
790
+
791
+ if (Qnil == pi->proc) {
792
+ rb_yield_values2(3, args);
793
+ } else {
794
+ rb_proc_call_with_block(pi->proc, 3, args, Qnil);
795
+ }
796
+ } else if (!pi->has_callbacks) {
797
+ first = 0;
798
+ }
799
+ start = pi->rd.pos;
800
+ // TBD break if option set to allow that
801
+ }
777
802
  }
778
803
  }
779
804
 
780
- static VALUE
781
- protect_parse(VALUE pip) {
805
+ static VALUE protect_parse(VALUE pip) {
782
806
  oj_sparse2((ParseInfo)pip);
783
807
 
784
808
  return Qnil;
@@ -786,46 +810,47 @@ protect_parse(VALUE pip) {
786
810
 
787
811
  VALUE
788
812
  oj_pi_sparse(int argc, VALUE *argv, ParseInfo pi, int fd) {
789
- volatile VALUE input;
790
- volatile VALUE wrapped_stack;
791
- VALUE result = Qnil;
792
- int line = 0;
813
+ volatile VALUE input;
814
+ volatile VALUE wrapped_stack;
815
+ VALUE result = Qnil;
816
+ int line = 0;
793
817
 
794
818
  if (argc < 1) {
795
- rb_raise(rb_eArgError, "Wrong number of arguments to parse.");
819
+ rb_raise(rb_eArgError, "Wrong number of arguments to parse.");
796
820
  }
797
821
  input = argv[0];
798
822
  if (2 <= argc) {
799
- if (T_HASH == rb_type(argv[1])) {
800
- oj_parse_options(argv[1], &pi->options);
801
- } else if (3 <= argc && T_HASH == rb_type(argv[2])) {
802
- oj_parse_options(argv[2], &pi->options);
803
- }
823
+ if (T_HASH == rb_type(argv[1])) {
824
+ oj_parse_options(argv[1], &pi->options);
825
+ } else if (3 <= argc && T_HASH == rb_type(argv[2])) {
826
+ oj_parse_options(argv[2], &pi->options);
827
+ }
804
828
  }
805
829
  if (Qnil == input) {
806
- if (Yes == pi->options.nilnil) {
807
- return Qnil;
808
- } else {
809
- rb_raise(rb_eTypeError, "Nil is not a valid JSON source.");
810
- }
811
- } else if (CompatMode == pi->options.mode && T_STRING == rb_type(input) && No == pi->options.nilnil && 0 == RSTRING_LEN(input)) {
812
- rb_raise(oj_json_parser_error_class, "An empty string is not a valid JSON string.");
830
+ if (Yes == pi->options.nilnil) {
831
+ return Qnil;
832
+ } else {
833
+ rb_raise(rb_eTypeError, "Nil is not a valid JSON source.");
834
+ }
835
+ } else if (CompatMode == pi->options.mode && T_STRING == rb_type(input) && No == pi->options.nilnil &&
836
+ 0 == RSTRING_LEN(input)) {
837
+ rb_raise(oj_json_parser_error_class, "An empty string is not a valid JSON string.");
813
838
  }
814
839
  if (rb_block_given_p()) {
815
- pi->proc = Qnil;
840
+ pi->proc = Qnil;
816
841
  } else {
817
- pi->proc = Qundef;
842
+ pi->proc = Qundef;
818
843
  }
819
844
  oj_reader_init(&pi->rd, input, fd, CompatMode == pi->options.mode);
820
- pi->json = 0; // indicates reader is in use
845
+ pi->json = 0; // indicates reader is in use
821
846
 
822
847
  if (Yes == pi->options.circular) {
823
- pi->circ_array = oj_circ_array_new();
848
+ pi->circ_array = oj_circ_array_new();
824
849
  } else {
825
- pi->circ_array = 0;
850
+ pi->circ_array = 0;
826
851
  }
827
852
  if (No == pi->options.allow_gc) {
828
- rb_gc_disable();
853
+ rb_gc_disable();
829
854
  }
830
855
  // GC can run at any time. When it runs any Object created by C will be
831
856
  // freed. We protect against this by wrapping the value stack in a ruby
@@ -834,77 +859,82 @@ oj_pi_sparse(int argc, VALUE *argv, ParseInfo pi, int fd) {
834
859
  wrapped_stack = oj_stack_init(&pi->stack);
835
860
  rb_protect(protect_parse, (VALUE)pi, &line);
836
861
  if (Qundef == pi->stack.head->val && !empty_ok(&pi->options)) {
837
- oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "Empty input");
862
+ oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "Empty input");
838
863
  }
839
- result = stack_head_val(&pi->stack);
864
+ result = stack_head_val(&pi->stack);
840
865
  DATA_PTR(wrapped_stack) = 0;
841
866
  if (No == pi->options.allow_gc) {
842
- rb_gc_enable();
867
+ rb_gc_enable();
843
868
  }
844
869
  if (!err_has(&pi->err)) {
845
- // If the stack is not empty then the JSON terminated early.
846
- Val v;
847
- VALUE err_class = oj_parse_error_class;
848
-
849
- if (0 != line) {
850
- VALUE ec = rb_obj_class(rb_errinfo());
851
-
852
- if (rb_eIOError != ec) {
853
- goto CLEANUP;
854
- }
855
- // Sometimes the class of the error is 0 which seems broken.
856
- if (rb_eArgError != ec && 0 != ec) {
857
- err_class = ec;
858
- }
859
- }
860
- if (0 != (v = stack_peek(&pi->stack))) {
861
- switch (v->next) {
862
- case NEXT_ARRAY_NEW:
863
- case NEXT_ARRAY_ELEMENT:
864
- case NEXT_ARRAY_COMMA:
865
- oj_set_error_at(pi, err_class, __FILE__, __LINE__, "Array not terminated");
866
- break;
867
- case NEXT_HASH_NEW:
868
- case NEXT_HASH_KEY:
869
- case NEXT_HASH_COLON:
870
- case NEXT_HASH_VALUE:
871
- case NEXT_HASH_COMMA:
872
- oj_set_error_at(pi, err_class, __FILE__, __LINE__, "Hash/Object not terminated");
873
- break;
874
- default:
875
- oj_set_error_at(pi, err_class, __FILE__, __LINE__, "not terminated");
876
- }
877
- }
870
+ // If the stack is not empty then the JSON terminated early.
871
+ Val v;
872
+ VALUE err_class = oj_parse_error_class;
873
+
874
+ if (0 != line) {
875
+ VALUE ec = rb_obj_class(rb_errinfo());
876
+
877
+ if (rb_eIOError != ec) {
878
+ goto CLEANUP;
879
+ }
880
+ // Sometimes the class of the error is 0 which seems broken.
881
+ if (rb_eArgError != ec && 0 != ec) {
882
+ err_class = ec;
883
+ }
884
+ }
885
+ if (0 != (v = stack_peek(&pi->stack))) {
886
+ switch (v->next) {
887
+ case NEXT_ARRAY_NEW:
888
+ case NEXT_ARRAY_ELEMENT:
889
+ case NEXT_ARRAY_COMMA: oj_set_error_at(pi, err_class, __FILE__, __LINE__, "Array not terminated"); break;
890
+ case NEXT_HASH_NEW:
891
+ case NEXT_HASH_KEY:
892
+ case NEXT_HASH_COLON:
893
+ case NEXT_HASH_VALUE:
894
+ case NEXT_HASH_COMMA:
895
+ oj_set_error_at(pi, err_class, __FILE__, __LINE__, "Hash/Object not terminated");
896
+ break;
897
+ default: oj_set_error_at(pi, err_class, __FILE__, __LINE__, "not terminated");
898
+ }
899
+ }
878
900
  }
879
901
  CLEANUP:
880
902
  // proceed with cleanup
881
903
  if (0 != pi->circ_array) {
882
- oj_circ_array_free(pi->circ_array);
904
+ oj_circ_array_free(pi->circ_array);
883
905
  }
884
906
  stack_cleanup(&pi->stack);
885
907
  if (0 != fd) {
886
- close(fd);
908
+ #ifdef _WIN32
909
+ rb_w32_close(fd);
910
+ #else
911
+ close(fd);
912
+ #endif
887
913
  }
888
914
  if (err_has(&pi->err)) {
889
- rb_set_errinfo(Qnil);
890
- if (Qnil != pi->err_class && 0 != pi->err_class) {
891
- pi->err.clas = pi->err_class;
892
- }
893
- if (CompatMode == pi->options.mode && Yes != pi->options.safe) {
894
- // The json gem requires the error message be UTF-8 encoded. In
895
- // additional the complete JSON source should be returned but that
896
- // is not possible without stored all the bytes read and reading
897
- // the remaining bytes on the stream. Both seem like a very bad
898
- // idea.
899
- VALUE args[] = { oj_encode(rb_str_new2(pi->err.msg)) };
900
-
901
- rb_exc_raise(rb_class_new_instance(1, args, pi->err.clas));
902
- } else {
903
- oj_err_raise(&pi->err);
904
- }
905
- oj_err_raise(&pi->err);
915
+ rb_set_errinfo(Qnil);
916
+ if (Qnil != pi->err_class && 0 != pi->err_class) {
917
+ pi->err.clas = pi->err_class;
918
+ }
919
+ if (CompatMode == pi->options.mode && Yes != pi->options.safe) {
920
+ // The json gem requires the error message be UTF-8 encoded. In
921
+ // additional the complete JSON source should be returned but that
922
+ // is not possible without stored all the bytes read and reading
923
+ // the remaining bytes on the stream. Both seem like a very bad
924
+ // idea.
925
+ VALUE args[] = {oj_encode(rb_str_new2(pi->err.msg))};
926
+
927
+ if (pi->err.clas == oj_parse_error_class) {
928
+ // The error was an Oj::ParseError so change to a JSON::ParserError.
929
+ pi->err.clas = oj_json_parser_error_class;
930
+ }
931
+ rb_exc_raise(rb_class_new_instance(1, args, pi->err.clas));
932
+ } else {
933
+ oj_err_raise(&pi->err);
934
+ }
935
+ oj_err_raise(&pi->err);
906
936
  } else if (0 != line) {
907
- rb_jump_tag(line);
937
+ rb_jump_tag(line);
908
938
  }
909
939
  return result;
910
940
  }