oj 3.7.4 → 3.11.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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;
|