oj 3.7.4 → 3.11.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +12 -4
- data/ext/oj/buf.h +6 -34
- data/ext/oj/cache8.c +3 -3
- data/ext/oj/cache8.h +5 -33
- data/ext/oj/circarray.c +5 -9
- data/ext/oj/circarray.h +5 -8
- data/ext/oj/code.c +3 -6
- data/ext/oj/code.h +7 -10
- data/ext/oj/compat.c +11 -14
- data/ext/oj/custom.c +108 -75
- data/ext/oj/dump.c +132 -92
- data/ext/oj/dump.h +6 -7
- data/ext/oj/dump_compat.c +37 -34
- data/ext/oj/dump_leaf.c +3 -6
- data/ext/oj/dump_object.c +23 -17
- data/ext/oj/dump_strict.c +7 -9
- data/ext/oj/encode.h +6 -32
- data/ext/oj/err.c +2 -5
- data/ext/oj/err.h +6 -34
- data/ext/oj/extconf.rb +6 -0
- data/ext/oj/fast.c +39 -56
- data/ext/oj/hash.c +11 -39
- data/ext/oj/hash.h +5 -33
- data/ext/oj/hash_test.c +3 -31
- data/ext/oj/mimic_json.c +65 -44
- data/ext/oj/object.c +38 -69
- data/ext/oj/odd.c +18 -17
- data/ext/oj/odd.h +6 -9
- data/ext/oj/oj.c +139 -93
- data/ext/oj/oj.h +43 -35
- data/ext/oj/parse.c +164 -60
- data/ext/oj/parse.h +30 -31
- data/ext/oj/rails.c +119 -83
- data/ext/oj/rails.h +4 -7
- data/ext/oj/reader.c +5 -8
- data/ext/oj/reader.h +7 -10
- data/ext/oj/resolve.c +4 -7
- data/ext/oj/resolve.h +4 -7
- data/ext/oj/rxclass.c +8 -11
- data/ext/oj/rxclass.h +8 -11
- data/ext/oj/saj.c +9 -12
- data/ext/oj/scp.c +4 -7
- data/ext/oj/sparse.c +67 -33
- data/ext/oj/stream_writer.c +16 -15
- data/ext/oj/strict.c +9 -12
- data/ext/oj/string_writer.c +27 -8
- data/ext/oj/trace.c +5 -8
- data/ext/oj/trace.h +9 -12
- data/ext/oj/util.c +136 -0
- data/ext/oj/util.h +19 -0
- data/ext/oj/val_stack.c +28 -36
- data/ext/oj/val_stack.h +19 -50
- data/ext/oj/wab.c +29 -29
- data/lib/oj.rb +0 -8
- data/lib/oj/json.rb +1 -1
- data/lib/oj/mimic.rb +46 -2
- data/lib/oj/version.rb +2 -2
- data/pages/Modes.md +47 -45
- data/pages/Options.md +43 -10
- data/pages/Rails.md +60 -21
- data/pages/Security.md +1 -1
- data/test/activesupport5/abstract_unit.rb +45 -0
- data/test/activesupport5/decoding_test.rb +68 -60
- data/test/activesupport5/encoding_test.rb +111 -96
- data/test/activesupport5/encoding_test_cases.rb +33 -25
- data/test/activesupport5/test_helper.rb +43 -21
- data/test/activesupport5/time_zone_test_helpers.rb +18 -3
- data/test/activesupport6/abstract_unit.rb +44 -0
- data/test/activesupport6/decoding_test.rb +133 -0
- data/test/activesupport6/encoding_test.rb +507 -0
- data/test/activesupport6/encoding_test_cases.rb +98 -0
- data/test/activesupport6/test_common.rb +17 -0
- data/test/activesupport6/test_helper.rb +163 -0
- data/test/activesupport6/time_zone_test_helpers.rb +39 -0
- data/test/bar.rb +24 -6
- data/test/baz.rb +16 -0
- data/test/foo.rb +26 -57
- data/test/helper.rb +10 -0
- data/test/json_gem/json_common_interface_test.rb +8 -3
- data/test/json_gem/json_generator_test.rb +15 -3
- data/test/json_gem/test_helper.rb +8 -0
- data/test/prec.rb +23 -0
- data/test/sample_json.rb +1 -1
- data/test/test_compat.rb +21 -10
- data/test/test_custom.rb +135 -8
- data/test/test_integer_range.rb +1 -2
- data/test/test_object.rb +35 -2
- data/test/test_rails.rb +35 -0
- data/test/test_strict.rb +24 -1
- data/test/test_various.rb +52 -63
- data/test/test_writer.rb +19 -2
- data/test/tests.rb +1 -0
- data/test/zoo.rb +13 -0
- metadata +100 -75
data/ext/oj/oj.h
CHANGED
@@ -1,12 +1,9 @@
|
|
1
|
-
|
2
|
-
* Copyright (c) 2011, Peter Ohler
|
3
|
-
* All rights reserved.
|
4
|
-
*/
|
1
|
+
// Copyright (c) 2011 Peter Ohler. All rights reserved.
|
5
2
|
|
6
|
-
#ifndef
|
7
|
-
#define
|
3
|
+
#ifndef OJ_H
|
4
|
+
#define OJ_H
|
8
5
|
|
9
|
-
#if defined(
|
6
|
+
#if defined(cplusplus)
|
10
7
|
extern "C" {
|
11
8
|
#if 0
|
12
9
|
} /* satisfy cc-mode */
|
@@ -21,7 +18,7 @@ extern "C" {
|
|
21
18
|
#include <stdint.h>
|
22
19
|
#include <stdbool.h>
|
23
20
|
|
24
|
-
#
|
21
|
+
#ifdef HAVE_PTHREAD_MUTEX_INIT
|
25
22
|
#include <pthread.h>
|
26
23
|
#endif
|
27
24
|
#include "cache8.h"
|
@@ -69,14 +66,17 @@ typedef enum {
|
|
69
66
|
JSONEsc = 'j',
|
70
67
|
XSSEsc = 'x',
|
71
68
|
ASCIIEsc = 'a',
|
72
|
-
JXEsc = '
|
69
|
+
JXEsc = 'g', // json gem
|
70
|
+
RailsXEsc = 'r', // rails xss mode
|
73
71
|
RailsEsc = 'R', // rails non escape
|
74
72
|
} Encoding;
|
75
73
|
|
76
74
|
typedef enum {
|
77
75
|
BigDec = 'b',
|
78
76
|
FloatDec = 'f',
|
79
|
-
AutoDec = 'a'
|
77
|
+
AutoDec = 'a',
|
78
|
+
FastDec = 'F',
|
79
|
+
RubyDec = 'r',
|
80
80
|
} BigLoad;
|
81
81
|
|
82
82
|
typedef enum {
|
@@ -107,7 +107,7 @@ typedef enum {
|
|
107
107
|
// Add the fast versions if necessary. Maybe unparse as well if needed.
|
108
108
|
} DumpCaller;
|
109
109
|
|
110
|
-
typedef struct
|
110
|
+
typedef struct _dumpOpts {
|
111
111
|
bool use;
|
112
112
|
char indent_str[16];
|
113
113
|
char before_sep[16];
|
@@ -124,7 +124,7 @@ typedef struct _DumpOpts {
|
|
124
124
|
int max_depth;
|
125
125
|
} *DumpOpts;
|
126
126
|
|
127
|
-
typedef struct
|
127
|
+
typedef struct _options {
|
128
128
|
int indent; // indention for dump, default 2
|
129
129
|
char circular; // YesNo
|
130
130
|
char auto_define; // YesNo
|
@@ -135,9 +135,11 @@ typedef struct _Options {
|
|
135
135
|
char time_format; // TimeFormat
|
136
136
|
char bigdec_as_num; // YesNo
|
137
137
|
char bigdec_load; // BigLoad
|
138
|
+
char compat_bigdec; // boolean (0 or 1)
|
138
139
|
char to_hash; // YesNo
|
139
140
|
char to_json; // YesNo
|
140
141
|
char as_json; // YesNo
|
142
|
+
char raw_json; // YesNo
|
141
143
|
char nilnil; // YesNo
|
142
144
|
char empty_string; // YesNo
|
143
145
|
char allow_gc; // allow GC during parse
|
@@ -146,8 +148,11 @@ typedef struct _Options {
|
|
146
148
|
char create_ok; // YesNo allow create_id
|
147
149
|
char allow_nan; // YEsyNo for parsing only
|
148
150
|
char trace; // YesNo
|
149
|
-
|
150
|
-
|
151
|
+
char safe; // YesNo
|
152
|
+
char sec_prec_set; // boolean (0 or 1)
|
153
|
+
char ignore_under; // YesNo - ignore attrs starting with _ if true in object and custom modes
|
154
|
+
int64_t int_range_min; // dump numbers below as string
|
155
|
+
int64_t int_range_max; // dump numbers above as string
|
151
156
|
const char *create_id; // 0 or string
|
152
157
|
size_t create_id_len; // length of create_id
|
153
158
|
int sec_prec; // second precision when dumping time
|
@@ -155,28 +160,28 @@ typedef struct _Options {
|
|
155
160
|
char float_fmt[7]; // float format for dumping, if empty use Ruby
|
156
161
|
VALUE hash_class; // class to use in place of Hash on load
|
157
162
|
VALUE array_class; // class to use in place of Array on load
|
158
|
-
struct
|
159
|
-
struct
|
163
|
+
struct _dumpOpts dump_opts;
|
164
|
+
struct _rxClass str_rx;
|
160
165
|
VALUE *ignore; // Qnil terminated array of classes or NULL
|
161
166
|
} *Options;
|
162
167
|
|
163
|
-
struct
|
164
|
-
typedef void (*DumpFunc)(VALUE obj, int depth, struct
|
168
|
+
struct _out;
|
169
|
+
typedef void (*DumpFunc)(VALUE obj, int depth, struct _out *out, bool as_ok);
|
165
170
|
|
166
171
|
// rails optimize
|
167
|
-
typedef struct
|
172
|
+
typedef struct _rOpt {
|
168
173
|
VALUE clas;
|
169
174
|
bool on;
|
170
175
|
DumpFunc dump;
|
171
176
|
} *ROpt;
|
172
177
|
|
173
|
-
typedef struct
|
178
|
+
typedef struct _rOptTable {
|
174
179
|
int len;
|
175
180
|
int alen;
|
176
181
|
ROpt table;
|
177
182
|
} *ROptTable;
|
178
183
|
|
179
|
-
typedef struct
|
184
|
+
typedef struct _out {
|
180
185
|
char *buf;
|
181
186
|
char *end;
|
182
187
|
char *cur;
|
@@ -194,18 +199,18 @@ typedef struct _Out {
|
|
194
199
|
ROptTable ropts;
|
195
200
|
} *Out;
|
196
201
|
|
197
|
-
typedef struct
|
198
|
-
struct
|
199
|
-
struct
|
202
|
+
typedef struct _strWriter {
|
203
|
+
struct _out out;
|
204
|
+
struct _options opts;
|
200
205
|
int depth;
|
201
206
|
char *types; // DumpType
|
202
207
|
char *types_end;
|
203
208
|
int keyWritten;
|
204
|
-
|
209
|
+
|
205
210
|
} *StrWriter;
|
206
211
|
|
207
|
-
typedef struct
|
208
|
-
struct
|
212
|
+
typedef struct _streamWriter {
|
213
|
+
struct _strWriter sw;
|
209
214
|
StreamWriterType type;
|
210
215
|
VALUE stream;
|
211
216
|
int fd;
|
@@ -218,16 +223,16 @@ enum {
|
|
218
223
|
COL_VAL = 0x02,
|
219
224
|
RUBY_VAL = 0x03
|
220
225
|
};
|
221
|
-
|
222
|
-
typedef struct
|
223
|
-
struct
|
226
|
+
|
227
|
+
typedef struct _leaf {
|
228
|
+
struct _leaf *next;
|
224
229
|
union {
|
225
230
|
const char *key; // hash key
|
226
231
|
size_t index; // array index, 0 is not set
|
227
232
|
};
|
228
233
|
union {
|
229
234
|
char *str; // pointer to location in json string or allocated
|
230
|
-
struct
|
235
|
+
struct _leaf *elements; // array and hash elements
|
231
236
|
VALUE value;
|
232
237
|
};
|
233
238
|
uint8_t rtype;
|
@@ -284,7 +289,7 @@ extern void oj_parse_opt_match_string(RxClass rc, VALUE ropts);
|
|
284
289
|
extern VALUE oj_rails_encode(int argc, VALUE *argv, VALUE self);
|
285
290
|
|
286
291
|
extern VALUE Oj;
|
287
|
-
extern struct
|
292
|
+
extern struct _options oj_default_options;
|
288
293
|
extern rb_encoding *oj_utf8_encoding;
|
289
294
|
|
290
295
|
extern VALUE oj_bag_class;
|
@@ -306,6 +311,7 @@ extern VALUE oj_array_class_sym;
|
|
306
311
|
extern VALUE oj_array_nl_sym;
|
307
312
|
extern VALUE oj_ascii_only_sym;
|
308
313
|
extern VALUE oj_create_additions_sym;
|
314
|
+
extern VALUE oj_decimal_class_sym;
|
309
315
|
extern VALUE oj_hash_class_sym;
|
310
316
|
extern VALUE oj_indent_sym;
|
311
317
|
extern VALUE oj_max_nesting_sym;
|
@@ -348,6 +354,7 @@ extern ID oj_readpartial_id;
|
|
348
354
|
extern ID oj_replace_id;
|
349
355
|
extern ID oj_stat_id;
|
350
356
|
extern ID oj_string_id;
|
357
|
+
extern ID oj_raw_json_id;
|
351
358
|
extern ID oj_to_h_id;
|
352
359
|
extern ID oj_to_hash_id;
|
353
360
|
extern ID oj_to_json_id;
|
@@ -364,17 +371,18 @@ extern ID oj_write_id;
|
|
364
371
|
|
365
372
|
extern bool oj_use_hash_alt;
|
366
373
|
extern bool oj_use_array_alt;
|
374
|
+
extern bool string_writer_optimized;
|
367
375
|
|
368
|
-
#
|
376
|
+
#ifdef HAVE_PTHREAD_MUTEX_INIT
|
369
377
|
extern pthread_mutex_t oj_cache_mutex;
|
370
378
|
#else
|
371
379
|
extern VALUE oj_cache_mutex;
|
372
380
|
#endif
|
373
381
|
|
374
|
-
#if defined(
|
382
|
+
#if defined(cplusplus)
|
375
383
|
#if 0
|
376
384
|
{ /* satisfy cc-mode */
|
377
385
|
#endif
|
378
386
|
} /* extern "C" { */
|
379
387
|
#endif
|
380
|
-
#endif /*
|
388
|
+
#endif /* OJ_H */
|
data/ext/oj/parse.c
CHANGED
@@ -1,13 +1,11 @@
|
|
1
|
-
|
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>
|
8
5
|
#include <string.h>
|
9
6
|
#include <unistd.h>
|
10
7
|
#include <math.h>
|
8
|
+
#include <ruby/util.h>
|
11
9
|
|
12
10
|
#include "oj.h"
|
13
11
|
#include "encode.h"
|
@@ -188,7 +186,7 @@ unicode_to_chars(ParseInfo pi, Buf buf, uint32_t code) {
|
|
188
186
|
// entered at /
|
189
187
|
static void
|
190
188
|
read_escaped_str(ParseInfo pi, const char *start) {
|
191
|
-
struct
|
189
|
+
struct _buf buf;
|
192
190
|
const char *s;
|
193
191
|
int cnt = (int)(pi->cur - start);
|
194
192
|
uint32_t code;
|
@@ -214,18 +212,6 @@ read_escaped_str(ParseInfo pi, const char *start) {
|
|
214
212
|
case '"': buf_append(&buf, '"'); break;
|
215
213
|
case '/': buf_append(&buf, '/'); break;
|
216
214
|
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;
|
229
215
|
case 'u':
|
230
216
|
s++;
|
231
217
|
if (0 == (code = read_hex(pi, s)) && err_has(&pi->err)) {
|
@@ -265,6 +251,12 @@ read_escaped_str(ParseInfo pi, const char *start) {
|
|
265
251
|
}
|
266
252
|
break;
|
267
253
|
default:
|
254
|
+
// The json gem claims this is not an error despite the
|
255
|
+
// ECMA-404 indicating it is not valid.
|
256
|
+
if (CompatMode == pi->options.mode) {
|
257
|
+
buf_append(&buf, *s);
|
258
|
+
break;
|
259
|
+
}
|
268
260
|
pi->cur = s;
|
269
261
|
oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "invalid escaped character");
|
270
262
|
buf_cleanup(&buf);
|
@@ -378,7 +370,7 @@ read_str(ParseInfo pi) {
|
|
378
370
|
|
379
371
|
static void
|
380
372
|
read_num(ParseInfo pi) {
|
381
|
-
struct
|
373
|
+
struct _numInfo ni;
|
382
374
|
Val parent = stack_peek(&pi->stack);
|
383
375
|
|
384
376
|
ni.str = pi->cur;
|
@@ -392,13 +384,23 @@ read_num(ParseInfo pi) {
|
|
392
384
|
ni.infinity = 0;
|
393
385
|
ni.nan = 0;
|
394
386
|
ni.neg = 0;
|
395
|
-
ni.
|
396
|
-
|
387
|
+
ni.has_exp = 0;
|
388
|
+
if (CompatMode == pi->options.mode) {
|
389
|
+
ni.no_big = !pi->options.compat_bigdec;
|
390
|
+
ni.bigdec_load = pi->options.compat_bigdec;
|
391
|
+
} else {
|
392
|
+
ni.no_big = (FloatDec == pi->options.bigdec_load || FastDec == pi->options.bigdec_load || RubyDec == pi->options.bigdec_load);
|
393
|
+
ni.bigdec_load = pi->options.bigdec_load;
|
394
|
+
}
|
397
395
|
|
398
396
|
if ('-' == *pi->cur) {
|
399
397
|
pi->cur++;
|
400
398
|
ni.neg = 1;
|
401
399
|
} else if ('+' == *pi->cur) {
|
400
|
+
if (StrictMode == pi->options.mode) {
|
401
|
+
oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "not a number or other value");
|
402
|
+
return;
|
403
|
+
}
|
402
404
|
pi->cur++;
|
403
405
|
}
|
404
406
|
if ('I' == *pi->cur) {
|
@@ -418,7 +420,7 @@ read_num(ParseInfo pi) {
|
|
418
420
|
} else {
|
419
421
|
int dec_cnt = 0;
|
420
422
|
bool zero1 = false;
|
421
|
-
|
423
|
+
|
422
424
|
for (; '0' <= *pi->cur && *pi->cur <= '9'; pi->cur++) {
|
423
425
|
if (0 == ni.i && '0' == *pi->cur) {
|
424
426
|
zero1 = true;
|
@@ -445,8 +447,14 @@ read_num(ParseInfo pi) {
|
|
445
447
|
if ('.' == *pi->cur) {
|
446
448
|
pi->cur++;
|
447
449
|
// A trailing . is not a valid decimal but if encountered allow it
|
448
|
-
// except when mimicing the JSON gem.
|
449
|
-
if (CompatMode == pi->options.mode) {
|
450
|
+
// except when mimicing the JSON gem or in strict mode.
|
451
|
+
if (StrictMode == pi->options.mode || CompatMode == pi->options.mode) {
|
452
|
+
int pos = (int)(pi->cur - ni.str);
|
453
|
+
|
454
|
+
if (1 == pos || (2 == pos && ni.neg)) {
|
455
|
+
oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "not a number");
|
456
|
+
return;
|
457
|
+
}
|
450
458
|
if (*pi->cur < '0' || '9' < *pi->cur) {
|
451
459
|
oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "not a number");
|
452
460
|
return;
|
@@ -458,18 +466,26 @@ read_num(ParseInfo pi) {
|
|
458
466
|
if (0 < ni.num || 0 < ni.i) {
|
459
467
|
dec_cnt++;
|
460
468
|
}
|
461
|
-
|
462
|
-
|
463
|
-
|
464
|
-
|
465
|
-
|
469
|
+
if (INT64_MAX <= ni.div) {
|
470
|
+
if (!ni.no_big) {
|
471
|
+
ni.big = true;
|
472
|
+
}
|
473
|
+
} else {
|
474
|
+
ni.num = ni.num * 10 + d;
|
475
|
+
ni.div *= 10;
|
476
|
+
ni.di++;
|
477
|
+
if (INT64_MAX <= ni.div || DEC_MAX < dec_cnt) {
|
478
|
+
if (!ni.no_big) {
|
479
|
+
ni.big = true;
|
480
|
+
}
|
481
|
+
}
|
466
482
|
}
|
467
483
|
}
|
468
484
|
}
|
469
485
|
if ('e' == *pi->cur || 'E' == *pi->cur) {
|
470
486
|
int eneg = 0;
|
471
487
|
|
472
|
-
ni.
|
488
|
+
ni.has_exp = 1;
|
473
489
|
pi->cur++;
|
474
490
|
if ('-' == *pi->cur) {
|
475
491
|
pi->cur++;
|
@@ -480,7 +496,7 @@ read_num(ParseInfo pi) {
|
|
480
496
|
for (; '0' <= *pi->cur && *pi->cur <= '9'; pi->cur++) {
|
481
497
|
ni.exp = ni.exp * 10 + (*pi->cur - '0');
|
482
498
|
if (EXP_MAX <= ni.exp) {
|
483
|
-
ni.big =
|
499
|
+
ni.big = true;
|
484
500
|
}
|
485
501
|
}
|
486
502
|
if (eneg) {
|
@@ -500,7 +516,11 @@ read_num(ParseInfo pi) {
|
|
500
516
|
ni.nan = 1;
|
501
517
|
}
|
502
518
|
}
|
503
|
-
if (
|
519
|
+
if (CompatMode == pi->options.mode) {
|
520
|
+
if (pi->options.compat_bigdec) {
|
521
|
+
ni.big = 1;
|
522
|
+
}
|
523
|
+
} else if (BigDec == pi->options.bigdec_load) {
|
504
524
|
ni.big = 1;
|
505
525
|
}
|
506
526
|
if (0 == parent) {
|
@@ -607,7 +627,7 @@ oj_parse2(ParseInfo pi) {
|
|
607
627
|
while (1) {
|
608
628
|
if (0 < pi->max_depth && pi->max_depth <= pi->stack.tail - pi->stack.head - 1) {
|
609
629
|
VALUE err_clas = oj_get_json_err_class("NestingError");
|
610
|
-
|
630
|
+
|
611
631
|
oj_set_error_at(pi, err_clas, __FILE__, __LINE__, "Too deeply nested.");
|
612
632
|
pi->err_class = err_clas;
|
613
633
|
return;
|
@@ -729,6 +749,70 @@ oj_parse2(ParseInfo pi) {
|
|
729
749
|
}
|
730
750
|
}
|
731
751
|
|
752
|
+
static VALUE
|
753
|
+
rescue_big_decimal(VALUE str, VALUE ignore) {
|
754
|
+
rb_raise(oj_parse_error_class, "Invalid value for BigDecimal()");
|
755
|
+
return Qnil;
|
756
|
+
}
|
757
|
+
|
758
|
+
static VALUE
|
759
|
+
parse_big_decimal(VALUE str) {
|
760
|
+
return rb_funcall(rb_cObject, oj_bigdecimal_id, 1, str);
|
761
|
+
}
|
762
|
+
|
763
|
+
static long double exp_plus[] = {
|
764
|
+
1.0,
|
765
|
+
1.0e1,
|
766
|
+
1.0e2,
|
767
|
+
1.0e3,
|
768
|
+
1.0e4,
|
769
|
+
1.0e5,
|
770
|
+
1.0e6,
|
771
|
+
1.0e7,
|
772
|
+
1.0e8,
|
773
|
+
1.0e9,
|
774
|
+
1.0e10,
|
775
|
+
1.0e11,
|
776
|
+
1.0e12,
|
777
|
+
1.0e13,
|
778
|
+
1.0e14,
|
779
|
+
1.0e15,
|
780
|
+
1.0e16,
|
781
|
+
1.0e17,
|
782
|
+
1.0e18,
|
783
|
+
1.0e19,
|
784
|
+
1.0e20,
|
785
|
+
1.0e21,
|
786
|
+
1.0e22,
|
787
|
+
1.0e23,
|
788
|
+
1.0e24,
|
789
|
+
1.0e25,
|
790
|
+
1.0e26,
|
791
|
+
1.0e27,
|
792
|
+
1.0e28,
|
793
|
+
1.0e29,
|
794
|
+
1.0e30,
|
795
|
+
1.0e31,
|
796
|
+
1.0e32,
|
797
|
+
1.0e33,
|
798
|
+
1.0e34,
|
799
|
+
1.0e35,
|
800
|
+
1.0e36,
|
801
|
+
1.0e37,
|
802
|
+
1.0e38,
|
803
|
+
1.0e39,
|
804
|
+
1.0e40,
|
805
|
+
1.0e41,
|
806
|
+
1.0e42,
|
807
|
+
1.0e43,
|
808
|
+
1.0e44,
|
809
|
+
1.0e45,
|
810
|
+
1.0e46,
|
811
|
+
1.0e47,
|
812
|
+
1.0e48,
|
813
|
+
1.0e49,
|
814
|
+
};
|
815
|
+
|
732
816
|
VALUE
|
733
817
|
oj_num_as_value(NumInfo ni) {
|
734
818
|
volatile VALUE rnum = Qnil;
|
@@ -741,7 +825,7 @@ oj_num_as_value(NumInfo ni) {
|
|
741
825
|
}
|
742
826
|
} else if (ni->nan) {
|
743
827
|
rnum = rb_float_new(0.0/0.0);
|
744
|
-
} else if (1 == ni->div && 0 == ni->exp) { // fixnum
|
828
|
+
} else if (1 == ni->div && 0 == ni->exp && !ni->has_exp) { // fixnum
|
745
829
|
if (ni->big) {
|
746
830
|
if (256 > ni->len) {
|
747
831
|
char buf[256];
|
@@ -766,35 +850,45 @@ oj_num_as_value(NumInfo ni) {
|
|
766
850
|
}
|
767
851
|
} else { // decimal
|
768
852
|
if (ni->big) {
|
769
|
-
|
853
|
+
volatile VALUE bd = rb_str_new(ni->str, ni->len);
|
854
|
+
|
855
|
+
rnum = rb_rescue2(parse_big_decimal, bd, rescue_big_decimal, bd, rb_eException, 0);
|
770
856
|
if (ni->no_big) {
|
771
857
|
rnum = rb_funcall(rnum, rb_intern("to_f"), 0);
|
772
858
|
}
|
773
|
-
} else {
|
774
|
-
|
775
|
-
long double d = (long double)ni->i * (long double)ni->div + (long double)ni->num;
|
859
|
+
} else if (FastDec == ni->bigdec_load) {
|
860
|
+
long double ld = (long double)ni->i * (long double)ni->div + (long double)ni->num;
|
776
861
|
int x = (int)((int64_t)ni->exp - ni->di);
|
777
862
|
|
778
|
-
|
779
|
-
|
780
|
-
|
781
|
-
|
782
|
-
|
783
|
-
if (ni->no_big) {
|
784
|
-
rnum = rb_funcall(rnum, rb_intern("to_f"), 0);
|
785
|
-
}
|
786
|
-
} else {
|
787
|
-
d = roundl(d);
|
788
|
-
if (0 < x) {
|
789
|
-
d *= powl(10.0L, x);
|
790
|
-
} else if (0 > x) {
|
791
|
-
d /= powl(10.0L, -x);
|
863
|
+
if (0 < x) {
|
864
|
+
if (x < (int)(sizeof(exp_plus) / sizeof(*exp_plus))) {
|
865
|
+
ld *= exp_plus[x];
|
866
|
+
} else {
|
867
|
+
ld *= powl(10.0, x);
|
792
868
|
}
|
793
|
-
|
794
|
-
|
869
|
+
} else if (x < 0) {
|
870
|
+
if (-x < (int)(sizeof(exp_plus) / sizeof(*exp_plus))) {
|
871
|
+
ld /= exp_plus[-x];
|
872
|
+
} else {
|
873
|
+
ld /= powl(10.0, -x);
|
795
874
|
}
|
796
|
-
rnum = rb_float_new((double)d);
|
797
875
|
}
|
876
|
+
if (ni->neg) {
|
877
|
+
ld = -ld;
|
878
|
+
}
|
879
|
+
rnum = rb_float_new((double)ld);
|
880
|
+
} else if (RubyDec == ni->bigdec_load) {
|
881
|
+
volatile VALUE sv = rb_str_new(ni->str, ni->len);
|
882
|
+
|
883
|
+
rnum = rb_funcall(sv, rb_intern("to_f"), 0);
|
884
|
+
} else {
|
885
|
+
char *end;
|
886
|
+
double d = strtod(ni->str, &end);
|
887
|
+
|
888
|
+
if ((long)ni->len != (long)(end - ni->str)) {
|
889
|
+
rb_raise(oj_parse_error_class, "Invalid float");
|
890
|
+
}
|
891
|
+
rnum = rb_float_new(d);
|
798
892
|
}
|
799
893
|
}
|
800
894
|
return rnum;
|
@@ -816,6 +910,12 @@ oj_set_error_at(ParseInfo pi, VALUE err_clas, const char* file, int line, const
|
|
816
910
|
if (p + 3 < end) {
|
817
911
|
*p++ = ' ';
|
818
912
|
*p++ = '(';
|
913
|
+
*p++ = 'a';
|
914
|
+
*p++ = 'f';
|
915
|
+
*p++ = 't';
|
916
|
+
*p++ = 'e';
|
917
|
+
*p++ = 'r';
|
918
|
+
*p++ = ' ';
|
819
919
|
start = p;
|
820
920
|
for (vp = pi->stack.head; vp < pi->stack.tail; vp++) {
|
821
921
|
if (end <= p + 1 + vp->klen) {
|
@@ -833,7 +933,7 @@ oj_set_error_at(ParseInfo pi, VALUE err_clas, const char* file, int line, const
|
|
833
933
|
break;
|
834
934
|
}
|
835
935
|
p += snprintf(p, end - p, "[%ld]", RARRAY_LEN(vp->val));
|
836
|
-
}
|
936
|
+
}
|
837
937
|
}
|
838
938
|
}
|
839
939
|
*p++ = ')';
|
@@ -976,12 +1076,12 @@ oj_pi_parse(int argc, VALUE *argv, ParseInfo pi, char *json, size_t len, int yie
|
|
976
1076
|
if (0 != line) {
|
977
1077
|
VALUE ec = rb_obj_class(rb_errinfo());
|
978
1078
|
|
979
|
-
if (rb_eIOError != ec) {
|
980
|
-
goto CLEANUP;
|
981
|
-
}
|
982
1079
|
if (rb_eArgError != ec && 0 != ec) {
|
983
1080
|
err_class = ec;
|
984
1081
|
}
|
1082
|
+
if (rb_eIOError != ec) {
|
1083
|
+
goto CLEANUP;
|
1084
|
+
}
|
985
1085
|
}
|
986
1086
|
if (NULL != (v = stack_peek(&pi->stack))) {
|
987
1087
|
switch (v->next) {
|
@@ -1021,7 +1121,7 @@ CLEANUP:
|
|
1021
1121
|
if (Qnil != pi->err_class) {
|
1022
1122
|
pi->err.clas = pi->err_class;
|
1023
1123
|
}
|
1024
|
-
if (CompatMode == pi->options.mode) {
|
1124
|
+
if (CompatMode == pi->options.mode && Yes != pi->options.safe) {
|
1025
1125
|
// The json gem requires the error message be UTF-8 encoded. In
|
1026
1126
|
// additional the complete JSON source must be returned. There
|
1027
1127
|
// does not seem to be a size limit.
|
@@ -1033,6 +1133,10 @@ CLEANUP:
|
|
1033
1133
|
msg = rb_str_append(msg, oj_encode(rb_str_new2(pi->json)));
|
1034
1134
|
}
|
1035
1135
|
args[0] = msg;
|
1136
|
+
if (pi->err.clas == oj_parse_error_class) {
|
1137
|
+
// The error was an Oj::ParseError so change to a JSON::ParserError.
|
1138
|
+
pi->err.clas = oj_json_parser_error_class;
|
1139
|
+
}
|
1036
1140
|
rb_exc_raise(rb_class_new_instance(1, args, pi->err.clas));
|
1037
1141
|
} else {
|
1038
1142
|
oj_err_raise(&pi->err);
|
@@ -1050,7 +1154,7 @@ CLEANUP:
|
|
1050
1154
|
case T_CLASS:
|
1051
1155
|
case T_STRING:
|
1052
1156
|
case T_SYMBOL: {
|
1053
|
-
struct
|
1157
|
+
struct _err err;
|
1054
1158
|
|
1055
1159
|
if (Qnil == pi->err_class) {
|
1056
1160
|
err.clas = oj_parse_error_class;
|