oj 2.18.5 → 3.0.0
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.
- checksums.yaml +4 -4
- data/README.md +33 -226
- data/ext/oj/circarray.c +0 -25
- data/ext/oj/circarray.h +0 -25
- data/ext/oj/code.c +227 -0
- data/ext/oj/code.h +40 -0
- data/ext/oj/compat.c +126 -38
- data/ext/oj/custom.c +1097 -0
- data/ext/oj/dump.c +658 -2376
- data/ext/oj/dump.h +92 -0
- data/ext/oj/dump_compat.c +937 -0
- data/ext/oj/dump_leaf.c +254 -0
- data/ext/oj/dump_object.c +810 -0
- data/ext/oj/dump_rails.c +329 -0
- data/ext/oj/dump_strict.c +416 -0
- data/ext/oj/err.c +0 -25
- data/ext/oj/err.h +8 -2
- data/ext/oj/fast.c +24 -24
- data/ext/oj/mimic_json.c +817 -0
- data/ext/oj/mimic_rails.c +806 -0
- data/ext/oj/mimic_rails.h +17 -0
- data/ext/oj/object.c +18 -72
- data/ext/oj/odd.c +0 -25
- data/ext/oj/odd.h +2 -27
- data/ext/oj/oj.c +655 -1503
- data/ext/oj/oj.h +93 -40
- data/ext/oj/parse.c +99 -46
- data/ext/oj/parse.h +12 -26
- data/ext/oj/reader.c +1 -25
- data/ext/oj/reader.h +3 -25
- data/ext/oj/resolve.c +9 -11
- data/ext/oj/resolve.h +2 -2
- data/ext/oj/rxclass.c +133 -0
- data/ext/oj/rxclass.h +27 -0
- data/ext/oj/saj.c +4 -25
- data/ext/oj/scp.c +3 -25
- data/ext/oj/sparse.c +89 -13
- data/ext/oj/stream_writer.c +301 -0
- data/ext/oj/strict.c +4 -27
- data/ext/oj/string_writer.c +480 -0
- data/ext/oj/val_stack.h +6 -2
- data/lib/oj.rb +1 -23
- data/lib/oj/easy_hash.rb +12 -4
- data/lib/oj/json.rb +172 -0
- data/lib/oj/mimic.rb +123 -18
- data/lib/oj/state.rb +131 -0
- data/lib/oj/version.rb +1 -1
- data/pages/Advanced.md +22 -0
- data/pages/Compatibility.md +25 -0
- data/pages/Custom.md +23 -0
- data/pages/Encoding.md +65 -0
- data/pages/JsonGem.md +79 -0
- data/pages/Modes.md +140 -0
- data/pages/Options.md +250 -0
- data/pages/Rails.md +60 -0
- data/pages/Security.md +20 -0
- data/test/activesupport4/decoding_test.rb +105 -0
- data/test/activesupport4/encoding_test.rb +531 -0
- data/test/activesupport4/test_helper.rb +41 -0
- data/test/activesupport5/decoding_test.rb +125 -0
- data/test/activesupport5/encoding_test.rb +483 -0
- data/test/activesupport5/encoding_test_cases.rb +90 -0
- data/test/activesupport5/test_helper.rb +50 -0
- data/test/activesupport5/time_zone_test_helpers.rb +24 -0
- data/test/json_gem/json_addition_test.rb +216 -0
- data/test/json_gem/json_common_interface_test.rb +143 -0
- data/test/json_gem/json_encoding_test.rb +109 -0
- data/test/json_gem/json_ext_parser_test.rb +20 -0
- data/test/json_gem/json_fixtures_test.rb +35 -0
- data/test/json_gem/json_generator_test.rb +383 -0
- data/test/json_gem/json_generic_object_test.rb +90 -0
- data/test/json_gem/json_parser_test.rb +470 -0
- data/test/json_gem/json_string_matching_test.rb +42 -0
- data/test/json_gem/test_helper.rb +18 -0
- data/test/perf_compat.rb +30 -28
- data/test/perf_object.rb +1 -1
- data/test/perf_strict.rb +18 -1
- data/test/sample.rb +0 -1
- data/test/test_compat.rb +169 -93
- data/test/test_custom.rb +355 -0
- data/test/test_file.rb +0 -8
- data/test/test_null.rb +376 -0
- data/test/test_object.rb +268 -3
- data/test/test_scp.rb +22 -1
- data/test/test_strict.rb +160 -4
- data/test/test_various.rb +52 -620
- data/test/tests.rb +14 -0
- data/test/tests_mimic.rb +14 -0
- data/test/tests_mimic_addition.rb +7 -0
- metadata +89 -47
- data/test/activesupport_datetime_test.rb +0 -23
- data/test/bug.rb +0 -51
- data/test/bug2.rb +0 -10
- data/test/bug3.rb +0 -46
- data/test/bug_fast.rb +0 -32
- data/test/bug_load.rb +0 -24
- data/test/crash.rb +0 -111
- data/test/curl/curl_oj.rb +0 -46
- data/test/curl/get_oj.rb +0 -24
- data/test/curl/just_curl.rb +0 -31
- data/test/curl/just_oj.rb +0 -51
- data/test/example.rb +0 -11
- data/test/foo.rb +0 -24
- data/test/io.rb +0 -48
- data/test/isolated/test_mimic_rails_datetime.rb +0 -27
- data/test/mod.rb +0 -16
- data/test/rails.rb +0 -50
- data/test/russian.rb +0 -18
- data/test/struct.rb +0 -29
- data/test/test_serializer.rb +0 -59
- data/test/write_timebars.rb +0 -31
data/ext/oj/oj.h
CHANGED
@@ -1,31 +1,6 @@
|
|
1
1
|
/* oj.h
|
2
2
|
* Copyright (c) 2011, Peter Ohler
|
3
3
|
* All rights reserved.
|
4
|
-
*
|
5
|
-
* Redistribution and use in source and binary forms, with or without
|
6
|
-
* modification, are permitted provided that the following conditions are met:
|
7
|
-
*
|
8
|
-
* - Redistributions of source code must retain the above copyright notice, this
|
9
|
-
* list of conditions and the following disclaimer.
|
10
|
-
*
|
11
|
-
* - Redistributions in binary form must reproduce the above copyright notice,
|
12
|
-
* this list of conditions and the following disclaimer in the documentation
|
13
|
-
* and/or other materials provided with the distribution.
|
14
|
-
*
|
15
|
-
* - Neither the name of Peter Ohler nor the names of its contributors may be
|
16
|
-
* used to endorse or promote products derived from this software without
|
17
|
-
* specific prior written permission.
|
18
|
-
*
|
19
|
-
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
20
|
-
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
21
|
-
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
22
|
-
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
23
|
-
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
24
|
-
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
25
|
-
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
26
|
-
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
27
|
-
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
28
|
-
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
29
4
|
*/
|
30
5
|
|
31
6
|
#ifndef __OJ_H__
|
@@ -45,8 +20,8 @@ extern "C" {
|
|
45
20
|
#include "ruby/encoding.h"
|
46
21
|
#endif
|
47
22
|
|
48
|
-
#include
|
49
|
-
#include
|
23
|
+
#include <stdint.h>
|
24
|
+
#include <stdbool.h>
|
50
25
|
|
51
26
|
#if USE_PTHREAD_MUTEX
|
52
27
|
#include <pthread.h>
|
@@ -66,6 +41,7 @@ enum st_retval {ST_CONTINUE = 0, ST_STOP = 1, ST_DELETE = 2, ST_CHECK};
|
|
66
41
|
#endif
|
67
42
|
#endif
|
68
43
|
|
44
|
+
#include "rxclass.h"
|
69
45
|
#include "err.h"
|
70
46
|
|
71
47
|
#define INF_VAL "3.0e14159265358979323846"
|
@@ -82,7 +58,9 @@ typedef enum {
|
|
82
58
|
StrictMode = 's',
|
83
59
|
ObjectMode = 'o',
|
84
60
|
NullMode = 'n',
|
85
|
-
CompatMode = 'c'
|
61
|
+
CompatMode = 'c',
|
62
|
+
RailsMode = 'r',
|
63
|
+
CustomMode = 'C',
|
86
64
|
} Mode;
|
87
65
|
|
88
66
|
typedef enum {
|
@@ -96,7 +74,9 @@ typedef enum {
|
|
96
74
|
NLEsc = 'n',
|
97
75
|
JSONEsc = 'j',
|
98
76
|
XSSEsc = 'x',
|
99
|
-
ASCIIEsc = 'a'
|
77
|
+
ASCIIEsc = 'a',
|
78
|
+
JXEsc = 'r', // json
|
79
|
+
RailsEsc = 'R', // rails non escape
|
100
80
|
} Encoding;
|
101
81
|
|
102
82
|
typedef enum {
|
@@ -126,6 +106,13 @@ typedef enum {
|
|
126
106
|
FILE_IO = 'f',
|
127
107
|
} StreamWriterType;
|
128
108
|
|
109
|
+
typedef enum {
|
110
|
+
CALLER_DUMP = 'd',
|
111
|
+
CALLER_TO_JSON = 't',
|
112
|
+
CALLER_GENERATE = 'g',
|
113
|
+
// Add the fast versions if necessary. Maybe unparse as well if needed.
|
114
|
+
} DumpCaller;
|
115
|
+
|
129
116
|
typedef struct _DumpOpts {
|
130
117
|
bool use;
|
131
118
|
char indent_str[16];
|
@@ -140,6 +127,7 @@ typedef struct _DumpOpts {
|
|
140
127
|
uint8_t array_size;
|
141
128
|
char nan_dump; // NanDump
|
142
129
|
bool omit_nil;
|
130
|
+
int max_depth;
|
143
131
|
} *DumpOpts;
|
144
132
|
|
145
133
|
typedef struct _Options {
|
@@ -153,6 +141,7 @@ typedef struct _Options {
|
|
153
141
|
char time_format; // TimeFormat
|
154
142
|
char bigdec_as_num; // YesNo
|
155
143
|
char bigdec_load; // BigLoad
|
144
|
+
char to_hash; // YesNo
|
156
145
|
char to_json; // YesNo
|
157
146
|
char as_json; // YesNo
|
158
147
|
char nilnil; // YesNo
|
@@ -160,27 +149,51 @@ typedef struct _Options {
|
|
160
149
|
char allow_gc; // allow GC during parse
|
161
150
|
char quirks_mode; // allow single JSON values instead of documents
|
162
151
|
char allow_invalid; // YesNo - allow invalid unicode
|
152
|
+
char create_ok; // YesNo allow create_id
|
153
|
+
char allow_nan; // YEsyNo for parsing only
|
163
154
|
const char *create_id; // 0 or string
|
164
155
|
size_t create_id_len; // length of create_id
|
165
156
|
int sec_prec; // second precision when dumping time
|
166
157
|
char float_prec; // float precision, linked to float_fmt
|
167
158
|
char float_fmt[7]; // float format for dumping, if empty use Ruby
|
168
159
|
VALUE hash_class; // class to use in place of Hash on load
|
160
|
+
VALUE array_class; // class to use in place of Array on load
|
169
161
|
struct _DumpOpts dump_opts;
|
162
|
+
struct _RxClass str_rx;
|
170
163
|
} *Options;
|
171
164
|
|
165
|
+
struct _Out;
|
166
|
+
typedef void (*DumpFunc)(VALUE obj, int depth, struct _Out *out, bool as_ok);
|
167
|
+
|
168
|
+
// rails optimize
|
169
|
+
typedef struct _ROpt {
|
170
|
+
VALUE clas;
|
171
|
+
bool on;
|
172
|
+
DumpFunc dump;
|
173
|
+
} *ROpt;
|
174
|
+
|
175
|
+
typedef struct _ROptTable {
|
176
|
+
int len;
|
177
|
+
int alen;
|
178
|
+
ROpt table;
|
179
|
+
} *ROptTable;
|
180
|
+
|
172
181
|
typedef struct _Out {
|
173
|
-
char
|
174
|
-
char
|
175
|
-
char
|
176
|
-
Cache8
|
177
|
-
slot_t
|
178
|
-
int
|
179
|
-
int
|
180
|
-
Options
|
181
|
-
uint32_t
|
182
|
-
int
|
183
|
-
bool
|
182
|
+
char *buf;
|
183
|
+
char *end;
|
184
|
+
char *cur;
|
185
|
+
Cache8 circ_cache;
|
186
|
+
slot_t circ_cnt;
|
187
|
+
int indent;
|
188
|
+
int depth; // used by dump_hash
|
189
|
+
Options opts;
|
190
|
+
uint32_t hash_cnt;
|
191
|
+
int allocated;
|
192
|
+
bool omit_nil;
|
193
|
+
int argc;
|
194
|
+
VALUE *argv;
|
195
|
+
DumpCaller caller; // used for the mimic json only
|
196
|
+
ROptTable ropts;
|
184
197
|
} *Out;
|
185
198
|
|
186
199
|
typedef struct _StrWriter {
|
@@ -229,10 +242,12 @@ extern VALUE oj_strict_parse(int argc, VALUE *argv, VALUE self);
|
|
229
242
|
extern VALUE oj_strict_sparse(int argc, VALUE *argv, VALUE self);
|
230
243
|
extern VALUE oj_compat_parse(int argc, VALUE *argv, VALUE self);
|
231
244
|
extern VALUE oj_object_parse(int argc, VALUE *argv, VALUE self);
|
245
|
+
extern VALUE oj_custom_parse(int argc, VALUE *argv, VALUE self);
|
232
246
|
|
233
247
|
extern VALUE oj_strict_parse_cstr(int argc, VALUE *argv, char *json, size_t len);
|
234
248
|
extern VALUE oj_compat_parse_cstr(int argc, VALUE *argv, char *json, size_t len);
|
235
249
|
extern VALUE oj_object_parse_cstr(int argc, VALUE *argv, char *json, size_t len);
|
250
|
+
extern VALUE oj_custom_parse_cstr(int argc, VALUE *argv, char *json, size_t len);
|
236
251
|
|
237
252
|
extern void oj_parse_options(VALUE ropts, Options copts);
|
238
253
|
|
@@ -252,6 +267,19 @@ extern void oj_str_writer_pop(StrWriter sw);
|
|
252
267
|
extern void oj_str_writer_pop_all(StrWriter sw);
|
253
268
|
|
254
269
|
extern void oj_init_doc(void);
|
270
|
+
extern void oj_string_writer_init();
|
271
|
+
extern void oj_stream_writer_init();
|
272
|
+
extern void oj_str_writer_init(StrWriter sw);
|
273
|
+
extern VALUE oj_define_mimic_json(int argc, VALUE *argv, VALUE self);
|
274
|
+
extern VALUE oj_mimic_generate(int argc, VALUE *argv, VALUE self);
|
275
|
+
extern VALUE oj_mimic_pretty_generate(int argc, VALUE *argv, VALUE self);
|
276
|
+
extern void oj_parse_mimic_dump_options(VALUE ropts, Options copts);
|
277
|
+
|
278
|
+
extern VALUE oj_mimic_parse(int argc, VALUE *argv, VALUE self);
|
279
|
+
extern VALUE oj_get_json_err_class(const char *err_classname);
|
280
|
+
extern void oj_parse_opt_match_string(RxClass rc, VALUE ropts);
|
281
|
+
|
282
|
+
extern VALUE oj_rails_encode(int argc, VALUE *argv, VALUE self);
|
255
283
|
|
256
284
|
extern VALUE Oj;
|
257
285
|
extern struct _Options oj_default_options;
|
@@ -267,11 +295,28 @@ extern VALUE oj_cstack_class;
|
|
267
295
|
extern VALUE oj_date_class;
|
268
296
|
extern VALUE oj_datetime_class;
|
269
297
|
extern VALUE oj_doc_class;
|
298
|
+
extern VALUE oj_enumerable_class;
|
299
|
+
extern VALUE oj_json_generator_error_class;
|
300
|
+
extern VALUE oj_json_parser_error_class;
|
270
301
|
extern VALUE oj_stream_writer_class;
|
271
302
|
extern VALUE oj_string_writer_class;
|
272
303
|
extern VALUE oj_stringio_class;
|
273
304
|
extern VALUE oj_struct_class;
|
274
305
|
|
306
|
+
extern VALUE oj_allow_nan_sym;
|
307
|
+
extern VALUE oj_array_class_sym;
|
308
|
+
extern VALUE oj_array_nl_sym;
|
309
|
+
extern VALUE oj_ascii_only_sym;
|
310
|
+
extern VALUE oj_create_additions_sym;
|
311
|
+
extern VALUE oj_hash_class_sym;
|
312
|
+
extern VALUE oj_indent_sym;
|
313
|
+
extern VALUE oj_max_nesting_sym;
|
314
|
+
extern VALUE oj_object_class_sym;
|
315
|
+
extern VALUE oj_object_nl_sym;
|
316
|
+
extern VALUE oj_quirks_mode_sym;
|
317
|
+
extern VALUE oj_space_before_sym;
|
318
|
+
extern VALUE oj_space_sym;
|
319
|
+
|
275
320
|
extern VALUE oj_slash_string;
|
276
321
|
|
277
322
|
extern ID oj_add_value_id;
|
@@ -279,10 +324,14 @@ extern ID oj_array_append_id;
|
|
279
324
|
extern ID oj_array_end_id;
|
280
325
|
extern ID oj_array_start_id;
|
281
326
|
extern ID oj_as_json_id;
|
327
|
+
extern ID oj_begin_id;
|
328
|
+
extern ID oj_end_id;
|
282
329
|
extern ID oj_error_id;
|
330
|
+
extern ID oj_exclude_end_id;
|
283
331
|
extern ID oj_file_id;
|
284
332
|
extern ID oj_fileno_id;
|
285
333
|
extern ID oj_ftype_id;
|
334
|
+
extern ID oj_has_key_id;
|
286
335
|
extern ID oj_hash_end_id;
|
287
336
|
extern ID oj_hash_key_id;
|
288
337
|
extern ID oj_hash_set_id;
|
@@ -299,6 +348,7 @@ extern ID oj_readpartial_id;
|
|
299
348
|
extern ID oj_replace_id;
|
300
349
|
extern ID oj_stat_id;
|
301
350
|
extern ID oj_string_id;
|
351
|
+
extern ID oj_to_h_id;
|
302
352
|
extern ID oj_to_hash_id;
|
303
353
|
extern ID oj_to_json_id;
|
304
354
|
extern ID oj_to_s_id;
|
@@ -312,6 +362,9 @@ extern ID oj_utc_offset_id;
|
|
312
362
|
extern ID oj_utcq_id;
|
313
363
|
extern ID oj_write_id;
|
314
364
|
|
365
|
+
extern bool oj_use_hash_alt;
|
366
|
+
extern bool oj_use_array_alt;
|
367
|
+
|
315
368
|
#if USE_PTHREAD_MUTEX
|
316
369
|
extern pthread_mutex_t oj_cache_mutex;
|
317
370
|
#elif USE_RB_MUTEX
|
data/ext/oj/parse.c
CHANGED
@@ -1,31 +1,6 @@
|
|
1
1
|
/* parse.c
|
2
2
|
* Copyright (c) 2013, Peter Ohler
|
3
3
|
* All rights reserved.
|
4
|
-
*
|
5
|
-
* Redistribution and use in source and binary forms, with or without
|
6
|
-
* modification, are permitted provided that the following conditions are met:
|
7
|
-
*
|
8
|
-
* - Redistributions of source code must retain the above copyright notice, this
|
9
|
-
* list of conditions and the following disclaimer.
|
10
|
-
*
|
11
|
-
* - Redistributions in binary form must reproduce the above copyright notice,
|
12
|
-
* this list of conditions and the following disclaimer in the documentation
|
13
|
-
* and/or other materials provided with the distribution.
|
14
|
-
*
|
15
|
-
* - Neither the name of Peter Ohler nor the names of its contributors may be
|
16
|
-
* used to endorse or promote products derived from this software without
|
17
|
-
* specific prior written permission.
|
18
|
-
*
|
19
|
-
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
20
|
-
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
21
|
-
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
22
|
-
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
23
|
-
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
24
|
-
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
25
|
-
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
26
|
-
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
27
|
-
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
28
|
-
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
29
4
|
*/
|
30
5
|
|
31
6
|
#include <stdlib.h>
|
@@ -35,9 +10,11 @@
|
|
35
10
|
#include <math.h>
|
36
11
|
|
37
12
|
#include "oj.h"
|
13
|
+
#include "encode.h"
|
38
14
|
#include "parse.h"
|
39
15
|
#include "buf.h"
|
40
16
|
#include "val_stack.h"
|
17
|
+
#include "rxclass.h"
|
41
18
|
|
42
19
|
// Workaround in case INFINITY is not defined in math.h or if the OS is CentOS
|
43
20
|
#define OJ_INFINITY (1.0/0.0)
|
@@ -237,6 +214,18 @@ read_escaped_str(ParseInfo pi, const char *start) {
|
|
237
214
|
case '"': buf_append(&buf, '"'); break;
|
238
215
|
case '/': buf_append(&buf, '/'); break;
|
239
216
|
case '\\': buf_append(&buf, '\\'); break;
|
217
|
+
case '\'':
|
218
|
+
// The json gem claims this is not an error despite the
|
219
|
+
// ECMA-404 indicating it is not valid.
|
220
|
+
if (CompatMode == pi->options.mode) {
|
221
|
+
buf_append(&buf, '\'');
|
222
|
+
} else {
|
223
|
+
pi->cur = s;
|
224
|
+
oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "invalid escaped character");
|
225
|
+
buf_cleanup(&buf);
|
226
|
+
return;
|
227
|
+
}
|
228
|
+
break;
|
240
229
|
case 'u':
|
241
230
|
s++;
|
242
231
|
if (0 == (code = read_hex(pi, s)) && err_has(&pi->err)) {
|
@@ -411,7 +400,7 @@ read_num(ParseInfo pi) {
|
|
411
400
|
pi->cur++;
|
412
401
|
}
|
413
402
|
if ('I' == *pi->cur) {
|
414
|
-
if (0 != strncmp("Infinity", pi->cur, 8)) {
|
403
|
+
if (No == pi->options.allow_nan || 0 != strncmp("Infinity", pi->cur, 8)) {
|
415
404
|
oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "not a number or other value");
|
416
405
|
return;
|
417
406
|
}
|
@@ -426,14 +415,25 @@ read_num(ParseInfo pi) {
|
|
426
415
|
ni.nan = 1;
|
427
416
|
} else {
|
428
417
|
int dec_cnt = 0;
|
429
|
-
|
418
|
+
bool zero1 = false;
|
419
|
+
|
430
420
|
for (; '0' <= *pi->cur && *pi->cur <= '9'; pi->cur++) {
|
421
|
+
if (0 == ni.i && '0' == *pi->cur) {
|
422
|
+
zero1 = true;
|
423
|
+
}
|
431
424
|
if (0 < ni.i) {
|
432
425
|
dec_cnt++;
|
433
426
|
}
|
434
427
|
if (!ni.big) {
|
435
428
|
int d = (*pi->cur - '0');
|
436
429
|
|
430
|
+
if (0 < d) {
|
431
|
+
if (zero1 && CompatMode == pi->options.mode) {
|
432
|
+
oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "not a number");
|
433
|
+
return;
|
434
|
+
}
|
435
|
+
zero1 = false;
|
436
|
+
}
|
437
437
|
ni.i = ni.i * 10 + d;
|
438
438
|
if (INT64_MAX <= ni.i || DEC_MAX < dec_cnt) {
|
439
439
|
ni.big = 1;
|
@@ -442,6 +442,10 @@ read_num(ParseInfo pi) {
|
|
442
442
|
}
|
443
443
|
if ('.' == *pi->cur) {
|
444
444
|
pi->cur++;
|
445
|
+
if (*pi->cur < '0' || '9' < *pi->cur) {
|
446
|
+
oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "not a number");
|
447
|
+
return;
|
448
|
+
}
|
445
449
|
for (; '0' <= *pi->cur && *pi->cur <= '9'; pi->cur++) {
|
446
450
|
int d = (*pi->cur - '0');
|
447
451
|
|
@@ -589,18 +593,26 @@ colon(ParseInfo pi) {
|
|
589
593
|
|
590
594
|
void
|
591
595
|
oj_parse2(ParseInfo pi) {
|
592
|
-
int
|
596
|
+
int first = 1;
|
597
|
+
long start = 0;
|
593
598
|
|
594
599
|
pi->cur = pi->json;
|
595
600
|
err_init(&pi->err);
|
596
601
|
while (1) {
|
602
|
+
if (0 < pi->max_depth && pi->max_depth <= pi->stack.tail - pi->stack.head - 1) {
|
603
|
+
VALUE err_clas = oj_get_json_err_class("NestingError");
|
604
|
+
|
605
|
+
oj_set_error_at(pi, err_clas, __FILE__, __LINE__, "Too deeply nested.");
|
606
|
+
pi->err_class = err_clas;
|
607
|
+
return;
|
608
|
+
}
|
597
609
|
next_non_white(pi);
|
598
610
|
if (!first && '\0' != *pi->cur) {
|
599
611
|
oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "unexpected characters after the JSON document");
|
600
612
|
}
|
601
613
|
|
602
|
-
//
|
603
|
-
// this is the behavior of JSON.parse in both Ruby and JS
|
614
|
+
// If no tokens are consumed (i.e. empty string), throw a parse error
|
615
|
+
// this is the behavior of JSON.parse in both Ruby and JS.
|
604
616
|
if (No == pi->options.empty_string && 1 == first && '\0' == *pi->cur) {
|
605
617
|
oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "unexpected character");
|
606
618
|
}
|
@@ -627,7 +639,7 @@ oj_parse2(ParseInfo pi) {
|
|
627
639
|
case '"':
|
628
640
|
read_str(pi);
|
629
641
|
break;
|
630
|
-
|
642
|
+
//case '+':
|
631
643
|
case '-':
|
632
644
|
case '0':
|
633
645
|
case '1':
|
@@ -639,11 +651,18 @@ oj_parse2(ParseInfo pi) {
|
|
639
651
|
case '7':
|
640
652
|
case '8':
|
641
653
|
case '9':
|
642
|
-
case 'I':
|
643
|
-
case 'N':
|
644
654
|
pi->cur--;
|
645
655
|
read_num(pi);
|
646
656
|
break;
|
657
|
+
case 'I':
|
658
|
+
case 'N':
|
659
|
+
if (Yes == pi->options.allow_nan) {
|
660
|
+
pi->cur--;
|
661
|
+
read_num(pi);
|
662
|
+
} else {
|
663
|
+
oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "unexpected character");
|
664
|
+
}
|
665
|
+
break;
|
647
666
|
case 't':
|
648
667
|
read_true(pi);
|
649
668
|
break;
|
@@ -676,22 +695,27 @@ oj_parse2(ParseInfo pi) {
|
|
676
695
|
}
|
677
696
|
if (stack_empty(&pi->stack)) {
|
678
697
|
if (Qundef != pi->proc) {
|
698
|
+
VALUE args[3];
|
699
|
+
long len = (pi->cur - pi->json) - start;
|
700
|
+
|
701
|
+
*args = stack_head_val(&pi->stack);
|
702
|
+
args[1] = LONG2NUM(start);
|
703
|
+
args[2] = LONG2NUM(len);
|
704
|
+
|
679
705
|
if (Qnil == pi->proc) {
|
680
|
-
|
706
|
+
rb_yield_values2(3, args);
|
681
707
|
} else {
|
682
708
|
#if HAS_PROC_WITH_BLOCK
|
683
|
-
|
684
|
-
|
685
|
-
*args = stack_head_val(&pi->stack);
|
686
|
-
rb_proc_call_with_block(pi->proc, 1, args, Qnil);
|
709
|
+
rb_proc_call_with_block(pi->proc, 3, args, Qnil);
|
687
710
|
#else
|
688
711
|
rb_raise(rb_eNotImpError,
|
689
712
|
"Calling a Proc with a block not supported in this version. Use func() {|x| } syntax instead.");
|
690
713
|
#endif
|
691
714
|
}
|
692
|
-
} else {
|
715
|
+
} else if (!pi->has_callbacks) {
|
693
716
|
first = 0;
|
694
717
|
}
|
718
|
+
start = pi->cur - pi->json;
|
695
719
|
}
|
696
720
|
}
|
697
721
|
}
|
@@ -818,8 +842,12 @@ oj_pi_parse(int argc, VALUE *argv, ParseInfo pi, char *json, size_t len, int yie
|
|
818
842
|
rb_raise(rb_eArgError, "Wrong number of arguments to parse.");
|
819
843
|
}
|
820
844
|
input = argv[0];
|
821
|
-
if (2
|
822
|
-
|
845
|
+
if (2 <= argc) {
|
846
|
+
if (T_HASH == rb_type(argv[1])) {
|
847
|
+
oj_parse_options(argv[1], &pi->options);
|
848
|
+
} else if (3 <= argc && T_HASH == rb_type(argv[2])) {
|
849
|
+
oj_parse_options(argv[2], &pi->options);
|
850
|
+
}
|
823
851
|
}
|
824
852
|
if (yieldOk && rb_block_given_p()) {
|
825
853
|
pi->proc = Qnil;
|
@@ -831,9 +859,16 @@ oj_pi_parse(int argc, VALUE *argv, ParseInfo pi, char *json, size_t len, int yie
|
|
831
859
|
pi->end = json + len;
|
832
860
|
free_json = 1;
|
833
861
|
} else if (T_STRING == rb_type(input)) {
|
862
|
+
if (No == pi->options.nilnil && 0 == RSTRING_LEN(input)) {
|
863
|
+
rb_raise(oj_json_parser_error_class, "An empty string is not a valid JSON string.");
|
864
|
+
}
|
834
865
|
oj_pi_set_input_str(pi, &input);
|
835
|
-
} else if (Qnil == input
|
836
|
-
|
866
|
+
} else if (Qnil == input) {
|
867
|
+
if (Yes == pi->options.nilnil) {
|
868
|
+
return Qnil;
|
869
|
+
} else {
|
870
|
+
rb_raise(rb_eTypeError, "Nil is not a valid JSON source.");
|
871
|
+
}
|
837
872
|
} else {
|
838
873
|
VALUE clas = rb_obj_class(input);
|
839
874
|
volatile VALUE s;
|
@@ -860,14 +895,14 @@ oj_pi_parse(int argc, VALUE *argv, ParseInfo pi, char *json, size_t len, int yie
|
|
860
895
|
((char*)pi->json)[len] = '\0';
|
861
896
|
/* skip UTF-8 BOM if present */
|
862
897
|
if (0xEF == (uint8_t)*pi->json && 0xBB == (uint8_t)pi->json[1] && 0xBF == (uint8_t)pi->json[2]) {
|
863
|
-
pi->
|
898
|
+
pi->cur += 3;
|
864
899
|
}
|
865
900
|
#endif
|
866
901
|
} else if (rb_respond_to(input, oj_read_id)) {
|
867
902
|
// use stream parser instead
|
868
903
|
return oj_pi_sparse(argc, argv, pi, 0);
|
869
904
|
} else {
|
870
|
-
rb_raise(rb_eArgError, "
|
905
|
+
rb_raise(rb_eArgError, "parse() expected a String or IO Object.");
|
871
906
|
}
|
872
907
|
}
|
873
908
|
if (Yes == pi->options.circular) {
|
@@ -922,6 +957,9 @@ oj_pi_parse(int argc, VALUE *argv, ParseInfo pi, char *json, size_t len, int yie
|
|
922
957
|
xfree(json);
|
923
958
|
}
|
924
959
|
stack_cleanup(&pi->stack);
|
960
|
+
if (pi->str_rx.head != oj_default_options.str_rx.head) {
|
961
|
+
oj_rxclass_cleanup(&pi->str_rx);
|
962
|
+
}
|
925
963
|
if (0 != line) {
|
926
964
|
rb_jump_tag(line);
|
927
965
|
}
|
@@ -929,7 +967,22 @@ oj_pi_parse(int argc, VALUE *argv, ParseInfo pi, char *json, size_t len, int yie
|
|
929
967
|
if (Qnil != pi->err_class) {
|
930
968
|
pi->err.clas = pi->err_class;
|
931
969
|
}
|
932
|
-
|
970
|
+
if (CompatMode == pi->options.mode) {
|
971
|
+
// The json gem requires the error message be UTF-8 encoded. In
|
972
|
+
// additional the complete JSON source must be returned. There
|
973
|
+
// does not seem to be a size limit.
|
974
|
+
VALUE msg = oj_encode(rb_str_new2(pi->err.msg));
|
975
|
+
VALUE args[1];
|
976
|
+
|
977
|
+
if (NULL != pi->json) {
|
978
|
+
msg = rb_str_append(msg, oj_encode(rb_str_new2(" in '")));
|
979
|
+
msg = rb_str_append(msg, oj_encode(rb_str_new2(pi->json)));
|
980
|
+
}
|
981
|
+
args[0] = msg;
|
982
|
+
rb_exc_raise(rb_class_new_instance(1, args, pi->err.clas));
|
983
|
+
} else {
|
984
|
+
oj_err_raise(&pi->err);
|
985
|
+
}
|
933
986
|
}
|
934
987
|
if (pi->options.quirks_mode == No) {
|
935
988
|
switch (rb_type(result)) {
|