oj 3.16.16 → 3.16.17
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/CHANGELOG.md +14 -0
- data/ext/oj/custom.c +5 -0
- data/ext/oj/dump.c +105 -29
- data/ext/oj/dump.h +2 -0
- data/ext/oj/dump_compat.c +5 -0
- data/ext/oj/dump_object.c +5 -0
- data/ext/oj/dump_strict.c +13 -8
- data/ext/oj/mimic_json.c +2 -0
- data/ext/oj/oj.c +130 -0
- data/ext/oj/oj.h +18 -16
- data/ext/oj/parse.c +18 -10
- data/ext/oj/parser.c +37 -7
- data/ext/oj/rails.c +15 -15
- data/ext/oj/saj.c +10 -2
- data/ext/oj/simd.h +25 -0
- data/ext/oj/sparse.c +3 -3
- data/lib/oj/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 8cea6645d77bacff66ea8a69d5c5211aa2e9366decc1e8dec909cc83f08933af
|
|
4
|
+
data.tar.gz: d286d46148ef014003a9a23a87cf33da532e09a6ce0228f4e5b47eff963d985f
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: a66845146062e764671ed0556076590ecc6507f04e21613ed5514df9e19e35c5e48b2fe9095cd7376fd82376a9b055aa8fc9e17e74c2bfaaa80ba1cebef0ddfe
|
|
7
|
+
data.tar.gz: 8b4af7c9cc6fadf664ff643c081783921e05f793d03c512bcf178e47173fc0e620f851382cb423c99769f01fd6080ad376c663a781faa14249cfc66009a182d2
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
# CHANGELOG
|
|
2
2
|
|
|
3
|
+
## 3.16.17 - 2026-04-12
|
|
4
|
+
|
|
5
|
+
- Rails optimize for Hash and Array now overrides `as_json` for those
|
|
6
|
+
classes. Note that when either is optimized with `Oj.optimize_rails`
|
|
7
|
+
the `Array.as_json` and `Hash.as_json` will not be called.
|
|
8
|
+
|
|
9
|
+
- Add support for the rails encoder `:only` and `:except` options.
|
|
10
|
+
|
|
11
|
+
- Handle unterminated strings in usual parser (#1002)
|
|
12
|
+
|
|
13
|
+
- Fix read() not handling partial reads for large files (#1004)
|
|
14
|
+
|
|
15
|
+
- Raise error for incomplete primitive literals (#1005)
|
|
16
|
+
|
|
3
17
|
## 3.16.16 - 2026-03-13
|
|
4
18
|
|
|
5
19
|
- Not closed arrays and objects are reported corrected in the usual parser.
|
data/ext/oj/custom.c
CHANGED
|
@@ -287,6 +287,11 @@ static int hash_cb(VALUE key, VALUE value, VALUE ov) {
|
|
|
287
287
|
if (out->omit_nil && Qnil == value) {
|
|
288
288
|
return ST_CONTINUE;
|
|
289
289
|
}
|
|
290
|
+
if (NULL != out->opts->dump_opts.only || NULL != out->opts->dump_opts.except) {
|
|
291
|
+
if (oj_key_skip(key, out->opts->dump_opts.only, out->opts->dump_opts.except)) {
|
|
292
|
+
return ST_CONTINUE;
|
|
293
|
+
}
|
|
294
|
+
}
|
|
290
295
|
if (!out->opts->dump_opts.use) {
|
|
291
296
|
assure_size(out, depth * out->indent + 1);
|
|
292
297
|
fill_indent(out, depth);
|
data/ext/oj/dump.c
CHANGED
|
@@ -257,7 +257,30 @@ inline static size_t hibit_friendly_size(const uint8_t *str, size_t len) {
|
|
|
257
257
|
size += tmp;
|
|
258
258
|
}
|
|
259
259
|
|
|
260
|
+
#ifdef HAVE_FAST_MEMCPY
|
|
261
|
+
size_t total = 0;
|
|
262
|
+
if (len - i > 4) {
|
|
263
|
+
size += (len - i);
|
|
264
|
+
unsigned char buf[sizeof(uint8x16_t)];
|
|
265
|
+
memset(buf, ' ', sizeof(buf));
|
|
266
|
+
fast_memcpy16(buf, str, len - i);
|
|
267
|
+
|
|
268
|
+
uint8x16_t chunk = vld1q_u8((const unsigned char *)buf);
|
|
269
|
+
uint8x16_t tmp1 = vqtbl4q_u8(hibit_friendly_chars_neon[0], chunk);
|
|
270
|
+
uint8x16_t tmp2 = vqtbl4q_u8(hibit_friendly_chars_neon[1], veorq_u8(chunk, vdupq_n_u8(0x40)));
|
|
271
|
+
uint8x16_t result = vorrq_u8(tmp1, tmp2);
|
|
272
|
+
uint8_t tmp = vaddvq_u8(result);
|
|
273
|
+
|
|
274
|
+
size += tmp;
|
|
275
|
+
|
|
276
|
+
total = size;
|
|
277
|
+
} else {
|
|
278
|
+
total = size + calculate_string_size(str, len - i, hibit_friendly_chars);
|
|
279
|
+
}
|
|
280
|
+
#else
|
|
260
281
|
size_t total = size + calculate_string_size(str, len - i, hibit_friendly_chars);
|
|
282
|
+
#endif
|
|
283
|
+
|
|
261
284
|
return total;
|
|
262
285
|
#elif defined(HAVE_SIMD_SSE4_2)
|
|
263
286
|
if (SIMD_Impl == SIMD_SSE42) {
|
|
@@ -967,11 +990,12 @@ typedef struct _neon_match_result {
|
|
|
967
990
|
uint8x16_t needs_escape;
|
|
968
991
|
bool has_some_hibit;
|
|
969
992
|
bool do_unicode_validation;
|
|
993
|
+
uint64_t escape_mask;
|
|
970
994
|
} neon_match_result;
|
|
971
995
|
|
|
972
996
|
static inline FORCE_INLINE neon_match_result
|
|
973
997
|
neon_update(const char *str, uint8x16x4_t *cmap_neon, int neon_table_size, bool do_unicode_validation, bool has_hi) {
|
|
974
|
-
neon_match_result result = {.has_some_hibit = false, .do_unicode_validation = false};
|
|
998
|
+
neon_match_result result = {.has_some_hibit = false, .do_unicode_validation = false, .escape_mask = 0};
|
|
975
999
|
|
|
976
1000
|
uint8x16_t chunk = vld1q_u8((const unsigned char *)str);
|
|
977
1001
|
uint8x16_t tmp1 = vqtbl4q_u8(cmap_neon[0], chunk);
|
|
@@ -987,6 +1011,9 @@ neon_update(const char *str, uint8x16x4_t *cmap_neon, int neon_table_size, bool
|
|
|
987
1011
|
result.has_some_hibit = vmaxvq_u8(has_some_hibit) != 0;
|
|
988
1012
|
result.do_unicode_validation = has_hi && do_unicode_validation && result.has_some_hibit;
|
|
989
1013
|
}
|
|
1014
|
+
const uint8x8_t res = vshrn_n_u16(vreinterpretq_u16_u8(vmvnq_u8(vceqq_u8(result.needs_escape, vdupq_n_u8(0)))), 4);
|
|
1015
|
+
const uint64_t mask = vget_lane_u64(vreinterpret_u64_u8(res), 0);
|
|
1016
|
+
result.escape_mask = mask & 0x8888888888888888ull;
|
|
990
1017
|
return result;
|
|
991
1018
|
}
|
|
992
1019
|
|
|
@@ -1189,7 +1216,16 @@ void oj_dump_cstr(const char *str, size_t cnt, bool is_sym, bool escape1, Out ou
|
|
|
1189
1216
|
if (is_sym) {
|
|
1190
1217
|
*out->cur++ = ':';
|
|
1191
1218
|
}
|
|
1219
|
+
#ifdef HAVE_FAST_MEMCPY
|
|
1220
|
+
if (cnt <= 16) {
|
|
1221
|
+
fast_memcpy16(out->cur, str, cnt);
|
|
1222
|
+
out->cur += size;
|
|
1223
|
+
} else {
|
|
1224
|
+
APPEND_CHARS(out->cur, str, cnt);
|
|
1225
|
+
}
|
|
1226
|
+
#else
|
|
1192
1227
|
APPEND_CHARS(out->cur, str, cnt);
|
|
1228
|
+
#endif
|
|
1193
1229
|
*out->cur++ = '"';
|
|
1194
1230
|
} else {
|
|
1195
1231
|
const char *end = str + cnt;
|
|
@@ -1223,6 +1259,17 @@ void oj_dump_cstr(const char *str, size_t cnt, bool is_sym, bool escape1, Out ou
|
|
|
1223
1259
|
#endif
|
|
1224
1260
|
|
|
1225
1261
|
#ifdef HAVE_SIMD_NEON
|
|
1262
|
+
|
|
1263
|
+
#ifdef HAVE_FAST_MEMCPY
|
|
1264
|
+
#define APPEND_CHARS_SMALL(dst, src, length) \
|
|
1265
|
+
fast_memcpy16((dst), (src), (length)); \
|
|
1266
|
+
(dst) += (length);
|
|
1267
|
+
#define MEMCPY16 fast_memcpy16
|
|
1268
|
+
#else
|
|
1269
|
+
#define APPEND_CHARS_SMALL(dst, src, length) APPEND_CHARS(dst, str, length);
|
|
1270
|
+
#define MEMCPY16 memcpy
|
|
1271
|
+
#endif
|
|
1272
|
+
|
|
1226
1273
|
if (use_simd) {
|
|
1227
1274
|
while (str < end) {
|
|
1228
1275
|
const char *chunk_ptr = NULL;
|
|
@@ -1231,8 +1278,8 @@ void oj_dump_cstr(const char *str, size_t cnt, bool is_sym, bool escape1, Out ou
|
|
|
1231
1278
|
chunk_start = str;
|
|
1232
1279
|
chunk_end = str + sizeof(uint8x16_t);
|
|
1233
1280
|
} else if ((end - str) >= SIMD_MINIMUM_THRESHOLD) {
|
|
1234
|
-
memset(out->cur, '
|
|
1235
|
-
|
|
1281
|
+
memset(out->cur, ' ', sizeof(uint8x16_t));
|
|
1282
|
+
MEMCPY16(out->cur, str, (end - str));
|
|
1236
1283
|
chunk_ptr = out->cur;
|
|
1237
1284
|
chunk_start = str;
|
|
1238
1285
|
chunk_end = end;
|
|
@@ -1244,32 +1291,22 @@ void oj_dump_cstr(const char *str, size_t cnt, bool is_sym, bool escape1, Out ou
|
|
|
1244
1291
|
neon_table_size,
|
|
1245
1292
|
do_unicode_validation,
|
|
1246
1293
|
has_hi);
|
|
1247
|
-
if ((result.do_unicode_validation) ||
|
|
1294
|
+
if ((result.do_unicode_validation) || result.escape_mask != 0) {
|
|
1248
1295
|
SEARCH_FLUSH;
|
|
1249
|
-
|
|
1250
|
-
|
|
1296
|
+
bool process_each = result.do_unicode_validation;
|
|
1297
|
+
uint8x16_t actions = vaddq_u8(result.needs_escape, vdupq_n_u8('1'));
|
|
1251
1298
|
vst1q_u8((unsigned char *)matches, actions);
|
|
1252
|
-
bool process_each = result.do_unicode_validation || (num_matches > sizeof(uint8x16_t) / 2);
|
|
1253
1299
|
// If no byte in this chunk had the high bit set then we can skip
|
|
1254
1300
|
// all of the '1' bytes by directly copying them to the output.
|
|
1255
1301
|
if (!process_each) {
|
|
1256
|
-
while (
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1302
|
+
while (result.escape_mask) {
|
|
1303
|
+
int esc_pos = OJ_CTZ64(result.escape_mask) >> 2;
|
|
1304
|
+
long run_len = esc_pos - (str - chunk_start);
|
|
1305
|
+
if (run_len > 0) {
|
|
1306
|
+
APPEND_CHARS_SMALL(out->cur, str, run_len);
|
|
1307
|
+
str += run_len;
|
|
1261
1308
|
}
|
|
1262
|
-
|
|
1263
|
-
if (str >= chunk_end) {
|
|
1264
|
-
break;
|
|
1265
|
-
}
|
|
1266
|
-
str = process_character(action, str, end, out, orig, do_unicode_validation, &check_start);
|
|
1267
|
-
str++;
|
|
1268
|
-
}
|
|
1269
|
-
} else {
|
|
1270
|
-
while (str < chunk_end) {
|
|
1271
|
-
long match_index = str - chunk_start;
|
|
1272
|
-
str = process_character(matches[match_index],
|
|
1309
|
+
str = process_character(matches[esc_pos],
|
|
1273
1310
|
str,
|
|
1274
1311
|
end,
|
|
1275
1312
|
out,
|
|
@@ -1277,6 +1314,23 @@ void oj_dump_cstr(const char *str, size_t cnt, bool is_sym, bool escape1, Out ou
|
|
|
1277
1314
|
do_unicode_validation,
|
|
1278
1315
|
&check_start);
|
|
1279
1316
|
str++;
|
|
1317
|
+
result.escape_mask &= result.escape_mask - 1;
|
|
1318
|
+
}
|
|
1319
|
+
if (str < chunk_end) {
|
|
1320
|
+
APPEND_CHARS_SMALL(out->cur, str, chunk_end - str);
|
|
1321
|
+
str = chunk_end;
|
|
1322
|
+
}
|
|
1323
|
+
} else {
|
|
1324
|
+
while (str < chunk_end) {
|
|
1325
|
+
long match_index = str - chunk_start;
|
|
1326
|
+
str = process_character(matches[match_index],
|
|
1327
|
+
str,
|
|
1328
|
+
end,
|
|
1329
|
+
out,
|
|
1330
|
+
orig,
|
|
1331
|
+
do_unicode_validation,
|
|
1332
|
+
&check_start);
|
|
1333
|
+
str++;
|
|
1280
1334
|
}
|
|
1281
1335
|
}
|
|
1282
1336
|
cursor = str;
|
|
@@ -1317,12 +1371,12 @@ void oj_dump_cstr(const char *str, size_t cnt, bool is_sym, bool escape1, Out ou
|
|
|
1317
1371
|
while (str < chunk_end) {
|
|
1318
1372
|
long match_index = str - chunk_start;
|
|
1319
1373
|
str = process_character(matches[match_index],
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1374
|
+
str,
|
|
1375
|
+
end,
|
|
1376
|
+
out,
|
|
1377
|
+
orig,
|
|
1378
|
+
do_unicode_validation,
|
|
1379
|
+
&check_start);
|
|
1326
1380
|
str++;
|
|
1327
1381
|
}
|
|
1328
1382
|
cursor = str;
|
|
@@ -1687,3 +1741,25 @@ size_t oj_dump_float_printf(char *buf, size_t blen, VALUE obj, double d, const c
|
|
|
1687
1741
|
}
|
|
1688
1742
|
return cnt;
|
|
1689
1743
|
}
|
|
1744
|
+
|
|
1745
|
+
bool oj_key_skip(VALUE key, const char *only, const char *except) {
|
|
1746
|
+
const char *skey;
|
|
1747
|
+
|
|
1748
|
+
switch (rb_type(key)) {
|
|
1749
|
+
case RUBY_T_STRING: skey = StringValueCStr(key); break;
|
|
1750
|
+
case RUBY_T_SYMBOL: skey = rb_id2name(rb_sym2id(key)); break;
|
|
1751
|
+
default: skey = NULL; break;
|
|
1752
|
+
}
|
|
1753
|
+
if (NULL != skey && '\0' != *skey) {
|
|
1754
|
+
size_t size = strlen(skey);
|
|
1755
|
+
char *buf = alloca(size + 3);
|
|
1756
|
+
|
|
1757
|
+
buf[0] = ':';
|
|
1758
|
+
strcpy(buf + 1, skey);
|
|
1759
|
+
buf[size + 1] = ':';
|
|
1760
|
+
buf[size + 2] = '\0';
|
|
1761
|
+
|
|
1762
|
+
return ((NULL != only && NULL == strstr(only, buf)) || (NULL != except && NULL != strstr(except, buf)));
|
|
1763
|
+
}
|
|
1764
|
+
return NULL != only;
|
|
1765
|
+
}
|
data/ext/oj/dump.h
CHANGED
|
@@ -62,6 +62,8 @@ extern size_t oj_dump_float_printf(char *buf, size_t blen, VALUE obj, double d,
|
|
|
62
62
|
|
|
63
63
|
extern time_t oj_sec_from_time_hard_way(VALUE obj);
|
|
64
64
|
|
|
65
|
+
extern bool oj_key_skip(VALUE key, const char *only, const char *except);
|
|
66
|
+
|
|
65
67
|
inline static void assure_size(Out out, size_t len) {
|
|
66
68
|
if (out->end - out->cur <= (long)len) {
|
|
67
69
|
oj_grow_out(out, len);
|
data/ext/oj/dump_compat.c
CHANGED
|
@@ -605,6 +605,11 @@ static int hash_cb(VALUE key, VALUE value, VALUE ov) {
|
|
|
605
605
|
if (out->omit_nil && Qnil == value) {
|
|
606
606
|
return ST_CONTINUE;
|
|
607
607
|
}
|
|
608
|
+
if (NULL != out->opts->dump_opts.only || NULL != out->opts->dump_opts.except) {
|
|
609
|
+
if (oj_key_skip(key, out->opts->dump_opts.only, out->opts->dump_opts.except)) {
|
|
610
|
+
return ST_CONTINUE;
|
|
611
|
+
}
|
|
612
|
+
}
|
|
608
613
|
if (!out->opts->dump_opts.use) {
|
|
609
614
|
assure_size(out, depth * out->indent + 1);
|
|
610
615
|
fill_indent(out, depth);
|
data/ext/oj/dump_object.c
CHANGED
|
@@ -210,6 +210,11 @@ static int hash_cb(VALUE key, VALUE value, VALUE ov) {
|
|
|
210
210
|
if (out->omit_nil && Qnil == value) {
|
|
211
211
|
return ST_CONTINUE;
|
|
212
212
|
}
|
|
213
|
+
if (NULL != out->opts->dump_opts.only || NULL != out->opts->dump_opts.except) {
|
|
214
|
+
if (oj_key_skip(key, out->opts->dump_opts.only, out->opts->dump_opts.except)) {
|
|
215
|
+
return ST_CONTINUE;
|
|
216
|
+
}
|
|
217
|
+
}
|
|
213
218
|
assure_size(out, size);
|
|
214
219
|
fill_indent(out, depth);
|
|
215
220
|
switch (rb_type(key)) {
|
data/ext/oj/dump_strict.c
CHANGED
|
@@ -193,14 +193,19 @@ static int hash_cb(VALUE key, VALUE value, VALUE ov) {
|
|
|
193
193
|
if (out->omit_nil && Qnil == value) {
|
|
194
194
|
return ST_CONTINUE;
|
|
195
195
|
}
|
|
196
|
+
if (NULL != out->opts->dump_opts.only || NULL != out->opts->dump_opts.except) {
|
|
197
|
+
if (oj_key_skip(key, out->opts->dump_opts.only, out->opts->dump_opts.except)) {
|
|
198
|
+
return ST_CONTINUE;
|
|
199
|
+
}
|
|
200
|
+
}
|
|
196
201
|
if (!out->opts->dump_opts.use) {
|
|
197
202
|
size = depth * out->indent + 1;
|
|
198
203
|
assure_size(out, size);
|
|
199
204
|
fill_indent(out, depth);
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
205
|
+
switch (rtype) {
|
|
206
|
+
case T_STRING: oj_dump_str(key, 0, out, false); break;
|
|
207
|
+
case T_SYMBOL: oj_dump_sym(key, 0, out, false); break;
|
|
208
|
+
default: oj_dump_str(oj_safe_string_convert(key), 0, out, false); break;
|
|
204
209
|
}
|
|
205
210
|
*out->cur++ = ':';
|
|
206
211
|
} else {
|
|
@@ -215,10 +220,10 @@ static int hash_cb(VALUE key, VALUE value, VALUE ov) {
|
|
|
215
220
|
APPEND_CHARS(out->cur, out->opts->dump_opts.indent_str, out->opts->dump_opts.indent_size);
|
|
216
221
|
}
|
|
217
222
|
}
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
223
|
+
switch (rtype) {
|
|
224
|
+
case T_STRING: oj_dump_str(key, 0, out, false); break;
|
|
225
|
+
case T_SYMBOL: oj_dump_sym(key, 0, out, false); break;
|
|
226
|
+
default: oj_dump_str(oj_safe_string_convert(key), 0, out, false); break;
|
|
222
227
|
}
|
|
223
228
|
size = out->opts->dump_opts.before_size + out->opts->dump_opts.after_size + 2;
|
|
224
229
|
assure_size(out, size);
|
data/ext/oj/mimic_json.c
CHANGED
data/ext/oj/oj.c
CHANGED
|
@@ -120,6 +120,7 @@ static VALUE create_id_sym;
|
|
|
120
120
|
static VALUE custom_sym;
|
|
121
121
|
static VALUE empty_string_sym;
|
|
122
122
|
static VALUE escape_mode_sym;
|
|
123
|
+
static VALUE except_sym;
|
|
123
124
|
static VALUE integer_range_sym;
|
|
124
125
|
static VALUE fast_sym;
|
|
125
126
|
static VALUE float_prec_sym;
|
|
@@ -138,6 +139,7 @@ static VALUE null_sym;
|
|
|
138
139
|
static VALUE object_sym;
|
|
139
140
|
static VALUE omit_null_byte_sym;
|
|
140
141
|
static VALUE omit_nil_sym;
|
|
142
|
+
static VALUE only_sym;
|
|
141
143
|
static VALUE rails_sym;
|
|
142
144
|
static VALUE raise_sym;
|
|
143
145
|
static VALUE ruby_sym;
|
|
@@ -228,6 +230,8 @@ struct _options oj_default_options = {
|
|
|
228
230
|
false, // omit_nil
|
|
229
231
|
false, // omit_null_byte
|
|
230
232
|
MAX_DEPTH, // max_depth
|
|
233
|
+
NULL, // only
|
|
234
|
+
NULL, // except
|
|
231
235
|
},
|
|
232
236
|
{
|
|
233
237
|
// str_rx
|
|
@@ -238,6 +242,22 @@ struct _options oj_default_options = {
|
|
|
238
242
|
NULL,
|
|
239
243
|
};
|
|
240
244
|
|
|
245
|
+
static VALUE only_array_from_string(const char *str) {
|
|
246
|
+
volatile VALUE a = Qnil;
|
|
247
|
+
|
|
248
|
+
if (NULL != str && 2 < strlen(str)) {
|
|
249
|
+
str++;
|
|
250
|
+
char *cp;
|
|
251
|
+
|
|
252
|
+
a = rb_ary_new();
|
|
253
|
+
while (NULL != (cp = strchr(str, ':'))) {
|
|
254
|
+
rb_ary_push(a, rb_id2sym(rb_intern2(str, cp - str)));
|
|
255
|
+
str = cp + 1;
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
return a;
|
|
259
|
+
}
|
|
260
|
+
|
|
241
261
|
/* Document-method: default_options()
|
|
242
262
|
* call-seq: default_options()
|
|
243
263
|
*
|
|
@@ -318,6 +338,8 @@ struct _options oj_default_options = {
|
|
|
318
338
|
* (trace is off)
|
|
319
339
|
* - *:safe* [_true,_|_false_] Safe mimic breaks JSON mimic to be safer, default
|
|
320
340
|
* is false (safe is off)
|
|
341
|
+
* - *:only* [_nil,_|_Array_] A list of the fields to encode. All others are skipped.
|
|
342
|
+
* - *:except* [_nil,_|_Array_] A list of the fields to not encode. All others are encoded.
|
|
321
343
|
*
|
|
322
344
|
* Return [_Hash_] all current option settings.
|
|
323
345
|
*/
|
|
@@ -483,6 +505,9 @@ static VALUE get_def_opts(VALUE self) {
|
|
|
483
505
|
rb_hash_aset(opts, oj_hash_class_sym, oj_default_options.hash_class);
|
|
484
506
|
rb_hash_aset(opts, oj_array_class_sym, oj_default_options.array_class);
|
|
485
507
|
|
|
508
|
+
rb_hash_aset(opts, only_sym, only_array_from_string(oj_default_options.dump_opts.only));
|
|
509
|
+
rb_hash_aset(opts, except_sym, only_array_from_string(oj_default_options.dump_opts.except));
|
|
510
|
+
|
|
486
511
|
if (NULL == oj_default_options.ignore) {
|
|
487
512
|
rb_hash_aset(opts, ignore_sym, Qnil);
|
|
488
513
|
} else {
|
|
@@ -625,6 +650,95 @@ bool set_yesno_options(VALUE key, VALUE value, Options copts) {
|
|
|
625
650
|
return false;
|
|
626
651
|
}
|
|
627
652
|
|
|
653
|
+
static const char *make_only_value(VALUE v) {
|
|
654
|
+
switch (rb_type(v)) {
|
|
655
|
+
case RUBY_T_NIL:
|
|
656
|
+
case RUBY_T_NONE: return NULL;
|
|
657
|
+
case RUBY_T_ARRAY: {
|
|
658
|
+
long len = rb_array_len(v);
|
|
659
|
+
long i;
|
|
660
|
+
long size = 0;
|
|
661
|
+
char *buf;
|
|
662
|
+
char *bp;
|
|
663
|
+
|
|
664
|
+
for (i = 0; i < len; i++) {
|
|
665
|
+
VALUE x = rb_ary_entry(v, i);
|
|
666
|
+
|
|
667
|
+
switch (rb_type(x)) {
|
|
668
|
+
case RUBY_T_SYMBOL:
|
|
669
|
+
size += strlen(rb_id2name(rb_sym2id(x)));
|
|
670
|
+
size++;
|
|
671
|
+
break;
|
|
672
|
+
case RUBY_T_STRING:
|
|
673
|
+
size += strlen(StringValueCStr(x));
|
|
674
|
+
size++;
|
|
675
|
+
break;
|
|
676
|
+
default: rb_raise(rb_eArgError, ":only and :except must be nil, symbol, string, or array."); break;
|
|
677
|
+
}
|
|
678
|
+
}
|
|
679
|
+
if (0 == size) {
|
|
680
|
+
return NULL;
|
|
681
|
+
}
|
|
682
|
+
buf = OJ_R_ALLOC_N(char, size + 2);
|
|
683
|
+
bp = buf;
|
|
684
|
+
*bp++ = ':';
|
|
685
|
+
for (i = 0; i < len; i++) {
|
|
686
|
+
VALUE x = rb_ary_entry(v, i);
|
|
687
|
+
const char *str;
|
|
688
|
+
|
|
689
|
+
switch (rb_type(x)) {
|
|
690
|
+
case RUBY_T_SYMBOL:
|
|
691
|
+
str = rb_id2name(rb_sym2id(x));
|
|
692
|
+
size = strlen(str);
|
|
693
|
+
memcpy(bp, str, size);
|
|
694
|
+
bp += size;
|
|
695
|
+
*bp++ = ':';
|
|
696
|
+
break;
|
|
697
|
+
case RUBY_T_STRING:
|
|
698
|
+
str = StringValueCStr(x);
|
|
699
|
+
size = strlen(str);
|
|
700
|
+
memcpy(bp, str, size);
|
|
701
|
+
bp += size;
|
|
702
|
+
*bp++ = ':';
|
|
703
|
+
break;
|
|
704
|
+
default:
|
|
705
|
+
// ignore
|
|
706
|
+
break;
|
|
707
|
+
}
|
|
708
|
+
}
|
|
709
|
+
*bp = '\0';
|
|
710
|
+
|
|
711
|
+
return buf;
|
|
712
|
+
}
|
|
713
|
+
case RUBY_T_STRING: {
|
|
714
|
+
const char *str = StringValueCStr(v);
|
|
715
|
+
size_t size = strlen(str);
|
|
716
|
+
char *buf = OJ_R_ALLOC_N(char, size + 3);
|
|
717
|
+
|
|
718
|
+
buf[0] = ':';
|
|
719
|
+
strcpy(buf + 1, str);
|
|
720
|
+
buf[size + 1] = ':';
|
|
721
|
+
buf[size + 2] = '\0';
|
|
722
|
+
|
|
723
|
+
return buf;
|
|
724
|
+
}
|
|
725
|
+
case RUBY_T_SYMBOL: {
|
|
726
|
+
const char *str = rb_id2name(rb_sym2id(v));
|
|
727
|
+
size_t size = strlen(str);
|
|
728
|
+
char *buf = OJ_R_ALLOC_N(char, size + 3);
|
|
729
|
+
|
|
730
|
+
buf[0] = ':';
|
|
731
|
+
strcpy(buf + 1, str);
|
|
732
|
+
buf[size + 1] = ':';
|
|
733
|
+
buf[size + 2] = '\0';
|
|
734
|
+
|
|
735
|
+
return buf;
|
|
736
|
+
}
|
|
737
|
+
default: rb_raise(rb_eArgError, ":only and zzz :except must be nil, symbol, string, or array."); break;
|
|
738
|
+
}
|
|
739
|
+
return NULL;
|
|
740
|
+
}
|
|
741
|
+
|
|
628
742
|
static int parse_options_cb(VALUE k, VALUE v, VALUE opts) {
|
|
629
743
|
Options copts = (Options)opts;
|
|
630
744
|
size_t len;
|
|
@@ -981,6 +1095,18 @@ static int parse_options_cb(VALUE k, VALUE v, VALUE opts) {
|
|
|
981
1095
|
}
|
|
982
1096
|
strncpy(copts->float_fmt, RSTRING_PTR(v), (size_t)RSTRING_LEN(v));
|
|
983
1097
|
copts->float_fmt[RSTRING_LEN(v)] = '\0';
|
|
1098
|
+
} else if (only_sym == k) {
|
|
1099
|
+
if (NULL != copts->dump_opts.only) {
|
|
1100
|
+
OJ_R_FREE((void *)copts->dump_opts.only);
|
|
1101
|
+
copts->dump_opts.only = NULL;
|
|
1102
|
+
}
|
|
1103
|
+
copts->dump_opts.only = make_only_value(v);
|
|
1104
|
+
} else if (except_sym == k) {
|
|
1105
|
+
if (NULL != copts->dump_opts.except) {
|
|
1106
|
+
OJ_R_FREE((void *)copts->dump_opts.except);
|
|
1107
|
+
copts->dump_opts.except = NULL;
|
|
1108
|
+
}
|
|
1109
|
+
copts->dump_opts.except = make_only_value(v);
|
|
984
1110
|
}
|
|
985
1111
|
return ST_CONTINUE;
|
|
986
1112
|
}
|
|
@@ -2133,6 +2259,10 @@ void Init_oj(void) {
|
|
|
2133
2259
|
rb_gc_register_address(&xmlschema_sym);
|
|
2134
2260
|
xss_safe_sym = ID2SYM(rb_intern("xss_safe"));
|
|
2135
2261
|
rb_gc_register_address(&xss_safe_sym);
|
|
2262
|
+
only_sym = ID2SYM(rb_intern("only"));
|
|
2263
|
+
rb_gc_register_address(&only_sym);
|
|
2264
|
+
except_sym = ID2SYM(rb_intern("except"));
|
|
2265
|
+
rb_gc_register_address(&except_sym);
|
|
2136
2266
|
|
|
2137
2267
|
oj_slash_string = rb_str_new2("/");
|
|
2138
2268
|
rb_gc_register_address(&oj_slash_string);
|
data/ext/oj/oj.h
CHANGED
|
@@ -104,21 +104,23 @@ typedef enum {
|
|
|
104
104
|
} StreamWriterType;
|
|
105
105
|
|
|
106
106
|
typedef struct _dumpOpts {
|
|
107
|
-
bool
|
|
108
|
-
char
|
|
109
|
-
char
|
|
110
|
-
char
|
|
111
|
-
char
|
|
112
|
-
char
|
|
113
|
-
uint8_t
|
|
114
|
-
uint8_t
|
|
115
|
-
uint8_t
|
|
116
|
-
uint8_t
|
|
117
|
-
uint8_t
|
|
118
|
-
char
|
|
119
|
-
bool
|
|
120
|
-
bool
|
|
121
|
-
int
|
|
107
|
+
bool use;
|
|
108
|
+
char indent_str[16];
|
|
109
|
+
char before_sep[16];
|
|
110
|
+
char after_sep[16];
|
|
111
|
+
char hash_nl[16];
|
|
112
|
+
char array_nl[16];
|
|
113
|
+
uint8_t indent_size;
|
|
114
|
+
uint8_t before_size;
|
|
115
|
+
uint8_t after_size;
|
|
116
|
+
uint8_t hash_size;
|
|
117
|
+
uint8_t array_size;
|
|
118
|
+
char nan_dump; // NanDump
|
|
119
|
+
bool omit_nil;
|
|
120
|
+
bool omit_null_byte;
|
|
121
|
+
int max_depth;
|
|
122
|
+
const char *only;
|
|
123
|
+
const char *except;
|
|
122
124
|
} *DumpOpts;
|
|
123
125
|
|
|
124
126
|
typedef struct _options {
|
|
@@ -143,7 +145,7 @@ typedef struct _options {
|
|
|
143
145
|
char quirks_mode; // allow single JSON values instead of documents
|
|
144
146
|
char allow_invalid; // YesNo - allow invalid unicode
|
|
145
147
|
char create_ok; // YesNo allow create_id
|
|
146
|
-
char allow_nan; //
|
|
148
|
+
char allow_nan; // YesNo for parsing only
|
|
147
149
|
char trace; // YesNo
|
|
148
150
|
char safe; // YesNo
|
|
149
151
|
char sec_prec_set; // boolean (0 or 1)
|
data/ext/oj/parse.c
CHANGED
|
@@ -209,7 +209,7 @@ static inline const char *string_scan_neon(const char *str, const char *end) {
|
|
|
209
209
|
while (str + sizeof(uint8x16_t) <= end) {
|
|
210
210
|
uint8x16_t chunk = vld1q_u8((const uint8_t *)str);
|
|
211
211
|
uint8x16_t tmp = vorrq_u8(vorrq_u8(vceqq_u8(chunk, null_char), vceqq_u8(chunk, backslash)),
|
|
212
|
-
|
|
212
|
+
vceqq_u8(chunk, quote));
|
|
213
213
|
const uint8x8_t res = vshrn_n_u16(vreinterpretq_u16_u8(tmp), 4);
|
|
214
214
|
uint64_t mask = vget_lane_u64(vreinterpret_u64_u8(res), 0);
|
|
215
215
|
if (mask != 0) {
|
|
@@ -285,10 +285,10 @@ static OJ_TARGET_SSE42 const char *scan_string_SSE42(const char *str, const char
|
|
|
285
285
|
for (; str <= safe_end_16; str += 16) {
|
|
286
286
|
const __m128i string = _mm_loadu_si128((const __m128i *)str);
|
|
287
287
|
const int r = _mm_cmpestri(terminate,
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
288
|
+
3,
|
|
289
|
+
string,
|
|
290
|
+
16,
|
|
291
|
+
_SIDD_UBYTE_OPS | _SIDD_CMP_EQUAL_ANY | _SIDD_LEAST_SIGNIFICANT);
|
|
292
292
|
if (r != 16)
|
|
293
293
|
return str + r;
|
|
294
294
|
}
|
|
@@ -611,7 +611,7 @@ static void read_num(ParseInfo pi) {
|
|
|
611
611
|
ni.bigdec_load = pi->options.compat_bigdec;
|
|
612
612
|
} else {
|
|
613
613
|
ni.no_big = (FloatDec == pi->options.bigdec_load || FastDec == pi->options.bigdec_load ||
|
|
614
|
-
|
|
614
|
+
RubyDec == pi->options.bigdec_load);
|
|
615
615
|
ni.bigdec_load = pi->options.bigdec_load;
|
|
616
616
|
}
|
|
617
617
|
|
|
@@ -1193,11 +1193,19 @@ oj_pi_parse(int argc, VALUE *argv, ParseInfo pi, char *json, size_t len, int yie
|
|
|
1193
1193
|
buf = OJ_R_ALLOC_N(char, len + 1);
|
|
1194
1194
|
pi->json = buf;
|
|
1195
1195
|
pi->end = buf + len;
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1196
|
+
{
|
|
1197
|
+
size_t total = 0;
|
|
1198
|
+
|
|
1199
|
+
while (total < len) {
|
|
1200
|
+
cnt = read(fd, (char *)pi->json + total, len - total);
|
|
1201
|
+
if (cnt <= 0) {
|
|
1202
|
+
if (0 != buf) {
|
|
1203
|
+
OJ_R_FREE(buf);
|
|
1204
|
+
}
|
|
1205
|
+
rb_raise(rb_eIOError, "failed to read from IO Object.");
|
|
1206
|
+
}
|
|
1207
|
+
total += cnt;
|
|
1199
1208
|
}
|
|
1200
|
-
rb_raise(rb_eIOError, "failed to read from IO Object.");
|
|
1201
1209
|
}
|
|
1202
1210
|
((char *)pi->json)[len] = '\0';
|
|
1203
1211
|
/* skip UTF-8 BOM if present */
|
data/ext/oj/parser.c
CHANGED
|
@@ -635,6 +635,9 @@ static void parse(ojParser p, const byte *json) {
|
|
|
635
635
|
if ('"' == *b) {
|
|
636
636
|
p->map = colon_map;
|
|
637
637
|
break;
|
|
638
|
+
} else if ('\0' == *b) {
|
|
639
|
+
parse_error(p, "quoted string not terminated");
|
|
640
|
+
break;
|
|
638
641
|
}
|
|
639
642
|
b--;
|
|
640
643
|
p->map = string_map;
|
|
@@ -659,6 +662,9 @@ static void parse(ojParser p, const byte *json) {
|
|
|
659
662
|
p->funcs[p->stack[p->depth]].add_str(p);
|
|
660
663
|
p->map = (0 == p->depth) ? value_map : after_map;
|
|
661
664
|
break;
|
|
665
|
+
} else if ('\0' == *b) {
|
|
666
|
+
parse_error(p, "quoted string not terminated");
|
|
667
|
+
break;
|
|
662
668
|
}
|
|
663
669
|
b--;
|
|
664
670
|
p->map = string_map;
|
|
@@ -1354,6 +1360,35 @@ static VALUE parser_missing(int argc, VALUE *argv, VALUE self) {
|
|
|
1354
1360
|
return p->option(p, key, rv);
|
|
1355
1361
|
}
|
|
1356
1362
|
|
|
1363
|
+
static void validate_primitives_are_complete(ojParser p) {
|
|
1364
|
+
if (0 >= p->ri) {
|
|
1365
|
+
return;
|
|
1366
|
+
}
|
|
1367
|
+
|
|
1368
|
+
switch (p->map[256]) {
|
|
1369
|
+
case 'N': parse_error(p, "expected null"); break;
|
|
1370
|
+
case 'F': parse_error(p, "expected false"); break;
|
|
1371
|
+
case 'T': parse_error(p, "expected true"); break;
|
|
1372
|
+
}
|
|
1373
|
+
}
|
|
1374
|
+
|
|
1375
|
+
static void validate_non_primitives_are_complete(ojParser p) {
|
|
1376
|
+
if (0 >= p->depth) {
|
|
1377
|
+
return;
|
|
1378
|
+
}
|
|
1379
|
+
|
|
1380
|
+
if (OBJECT_FUN == p->stack[p->depth]) {
|
|
1381
|
+
parse_error(p, "Object is not closed");
|
|
1382
|
+
} else {
|
|
1383
|
+
parse_error(p, "Array is not closed");
|
|
1384
|
+
}
|
|
1385
|
+
}
|
|
1386
|
+
|
|
1387
|
+
static void validate_document_end(ojParser p) {
|
|
1388
|
+
validate_primitives_are_complete(p);
|
|
1389
|
+
validate_non_primitives_are_complete(p);
|
|
1390
|
+
}
|
|
1391
|
+
|
|
1357
1392
|
/* Document-method: parse(json)
|
|
1358
1393
|
* call-seq: parse(json)
|
|
1359
1394
|
*
|
|
@@ -1371,13 +1406,8 @@ static VALUE parser_parse(VALUE self, VALUE json) {
|
|
|
1371
1406
|
p->start(p);
|
|
1372
1407
|
parse(p, ptr);
|
|
1373
1408
|
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
parse_error(p, "Object is not closed");
|
|
1377
|
-
} else {
|
|
1378
|
-
parse_error(p, "Array is not closed");
|
|
1379
|
-
}
|
|
1380
|
-
}
|
|
1409
|
+
validate_document_end(p);
|
|
1410
|
+
|
|
1381
1411
|
return p->result(p);
|
|
1382
1412
|
}
|
|
1383
1413
|
|
data/ext/oj/rails.c
CHANGED
|
@@ -920,7 +920,7 @@ static VALUE encode(VALUE obj, ROptTable ropts, Options opts, int argc, VALUE *a
|
|
|
920
920
|
if (Yes == copts.circular) {
|
|
921
921
|
oj_cache8_new(&out.circ_cache);
|
|
922
922
|
}
|
|
923
|
-
|
|
923
|
+
|
|
924
924
|
rb_protect(protect_dump, (VALUE)&oo, &line);
|
|
925
925
|
|
|
926
926
|
if (0 == line) {
|
|
@@ -1219,8 +1219,7 @@ static void dump_array(VALUE a, int depth, Out out, bool as_ok) {
|
|
|
1219
1219
|
return;
|
|
1220
1220
|
}
|
|
1221
1221
|
}
|
|
1222
|
-
|
|
1223
|
-
if (as_ok && 0 < out->argc && rb_respond_to(a, oj_as_json_id)) {
|
|
1222
|
+
if (!oj_rails_array_opt && as_ok && rb_respond_to(a, oj_as_json_id)) {
|
|
1224
1223
|
dump_as_json(a, depth, out, false);
|
|
1225
1224
|
return;
|
|
1226
1225
|
}
|
|
@@ -1287,18 +1286,19 @@ static int hash_cb(VALUE key, VALUE value, VALUE ov) {
|
|
|
1287
1286
|
if (out->omit_nil && Qnil == value) {
|
|
1288
1287
|
return ST_CONTINUE;
|
|
1289
1288
|
}
|
|
1290
|
-
if (
|
|
1291
|
-
|
|
1292
|
-
|
|
1289
|
+
if (NULL != out->opts->dump_opts.only || NULL != out->opts->dump_opts.except) {
|
|
1290
|
+
if (oj_key_skip(key, out->opts->dump_opts.only, out->opts->dump_opts.except)) {
|
|
1291
|
+
return ST_CONTINUE;
|
|
1292
|
+
}
|
|
1293
1293
|
}
|
|
1294
1294
|
if (!out->opts->dump_opts.use) {
|
|
1295
1295
|
size = depth * out->indent + 1;
|
|
1296
1296
|
assure_size(out, size);
|
|
1297
1297
|
fill_indent(out, depth);
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1298
|
+
switch (rtype) {
|
|
1299
|
+
case T_STRING: oj_dump_str(key, 0, out, false); break;
|
|
1300
|
+
case T_SYMBOL: oj_dump_sym(key, 0, out, false); break;
|
|
1301
|
+
default: oj_dump_str(oj_safe_string_convert(key), 0, out, false); break;
|
|
1302
1302
|
}
|
|
1303
1303
|
*out->cur++ = ':';
|
|
1304
1304
|
} else {
|
|
@@ -1313,10 +1313,10 @@ static int hash_cb(VALUE key, VALUE value, VALUE ov) {
|
|
|
1313
1313
|
APPEND_CHARS(out->cur, out->opts->dump_opts.indent_str, out->opts->dump_opts.indent_size);
|
|
1314
1314
|
}
|
|
1315
1315
|
}
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1316
|
+
switch (rtype) {
|
|
1317
|
+
case T_STRING: oj_dump_str(key, 0, out, false); break;
|
|
1318
|
+
case T_SYMBOL: oj_dump_sym(key, 0, out, false); break;
|
|
1319
|
+
default: oj_dump_str(oj_safe_string_convert(key), 0, out, false); break;
|
|
1320
1320
|
}
|
|
1321
1321
|
size = out->opts->dump_opts.before_size + out->opts->dump_opts.after_size + 2;
|
|
1322
1322
|
assure_size(out, size);
|
|
@@ -1345,7 +1345,7 @@ static void dump_hash(VALUE obj, int depth, Out out, bool as_ok) {
|
|
|
1345
1345
|
return;
|
|
1346
1346
|
}
|
|
1347
1347
|
}
|
|
1348
|
-
if (
|
|
1348
|
+
if (!oj_rails_hash_opt && as_ok && rb_respond_to(obj, oj_as_json_id)) {
|
|
1349
1349
|
dump_as_json(obj, depth, out, false);
|
|
1350
1350
|
return;
|
|
1351
1351
|
}
|
data/ext/oj/saj.c
CHANGED
|
@@ -648,8 +648,16 @@ oj_saj_parse(int argc, VALUE *argv, VALUE self) {
|
|
|
648
648
|
len = lseek(fd, 0, SEEK_END);
|
|
649
649
|
lseek(fd, 0, SEEK_SET);
|
|
650
650
|
json = OJ_R_ALLOC_N(char, len + 1);
|
|
651
|
-
|
|
652
|
-
|
|
651
|
+
{
|
|
652
|
+
size_t total = 0;
|
|
653
|
+
|
|
654
|
+
while (total < len) {
|
|
655
|
+
cnt = read(fd, json + total, len - total);
|
|
656
|
+
if (cnt <= 0) {
|
|
657
|
+
rb_raise(rb_eIOError, "failed to read from IO Object.");
|
|
658
|
+
}
|
|
659
|
+
total += cnt;
|
|
660
|
+
}
|
|
653
661
|
}
|
|
654
662
|
json[len] = '\0';
|
|
655
663
|
#endif
|
data/ext/oj/simd.h
CHANGED
|
@@ -191,4 +191,29 @@ static inline OJ_TARGET_SSE42 __m128i vector_lookup_sse42(__m128i input, __m128i
|
|
|
191
191
|
|
|
192
192
|
#endif
|
|
193
193
|
|
|
194
|
+
#ifndef __has_builtin
|
|
195
|
+
#define __has_builtin(x) 0
|
|
196
|
+
#endif
|
|
197
|
+
|
|
198
|
+
#if __has_builtin(__builtin_memcpy)
|
|
199
|
+
#define HAVE_FAST_MEMCPY 1
|
|
200
|
+
|
|
201
|
+
inline static void fast_memcpy16(void *dest, const void *src, size_t n) {
|
|
202
|
+
char *d = (char *)dest;
|
|
203
|
+
char *s = (char *)src;
|
|
204
|
+
if (n >= 8) {
|
|
205
|
+
__builtin_memcpy(d, s, 8);
|
|
206
|
+
__builtin_memcpy(d + n - 8, s + n - 8, 8);
|
|
207
|
+
} else if (n >= 4) {
|
|
208
|
+
__builtin_memcpy(d, s, 4);
|
|
209
|
+
__builtin_memcpy(d + n - 4, s + n - 4, 4);
|
|
210
|
+
} else if (n >= 2) {
|
|
211
|
+
__builtin_memcpy(d, s, 2);
|
|
212
|
+
__builtin_memcpy(d + n - 2, s + n - 2, 2);
|
|
213
|
+
} else if (n >= 1) {
|
|
214
|
+
*d = *s;
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
#endif
|
|
218
|
+
|
|
194
219
|
#endif /* OJ_SIMD_H */
|
data/ext/oj/sparse.c
CHANGED
|
@@ -415,7 +415,7 @@ static void read_num(ParseInfo pi) {
|
|
|
415
415
|
ni.bigdec_load = pi->options.compat_bigdec;
|
|
416
416
|
} else {
|
|
417
417
|
ni.no_big = (FloatDec == pi->options.bigdec_load || FastDec == pi->options.bigdec_load ||
|
|
418
|
-
|
|
418
|
+
RubyDec == pi->options.bigdec_load);
|
|
419
419
|
ni.bigdec_load = pi->options.bigdec_load;
|
|
420
420
|
}
|
|
421
421
|
|
|
@@ -565,7 +565,7 @@ static void read_nan(ParseInfo pi) {
|
|
|
565
565
|
ni.bigdec_load = pi->options.compat_bigdec;
|
|
566
566
|
} else {
|
|
567
567
|
ni.no_big = (FloatDec == pi->options.bigdec_load || FastDec == pi->options.bigdec_load ||
|
|
568
|
-
|
|
568
|
+
RubyDec == pi->options.bigdec_load);
|
|
569
569
|
ni.bigdec_load = pi->options.bigdec_load;
|
|
570
570
|
}
|
|
571
571
|
|
|
@@ -761,7 +761,7 @@ void oj_sparse2(ParseInfo pi) {
|
|
|
761
761
|
ni.bigdec_load = pi->options.compat_bigdec;
|
|
762
762
|
} else {
|
|
763
763
|
ni.no_big = (FloatDec == pi->options.bigdec_load || FastDec == pi->options.bigdec_load ||
|
|
764
|
-
|
|
764
|
+
RubyDec == pi->options.bigdec_load);
|
|
765
765
|
ni.bigdec_load = pi->options.bigdec_load;
|
|
766
766
|
}
|
|
767
767
|
add_num_value(pi, &ni);
|
data/lib/oj/version.rb
CHANGED