oj 2.9.9 → 2.10.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of oj might be problematic. Click here for more details.
- checksums.yaml +7 -0
- data/README.md +10 -23
- data/ext/oj/compat.c +14 -8
- data/ext/oj/dump.c +2 -2
- data/ext/oj/object.c +39 -28
- data/ext/oj/oj.c +3 -1
- data/ext/oj/oj.h +1 -0
- data/ext/oj/parse.c +25 -16
- data/ext/oj/parse.h +4 -3
- data/ext/oj/scp.c +29 -15
- data/ext/oj/sparse.c +13 -7
- data/ext/oj/strict.c +17 -8
- data/ext/oj/val_stack.c +1 -0
- data/ext/oj/val_stack.h +3 -1
- data/lib/oj/schandler.rb +11 -0
- data/lib/oj/version.rb +1 -1
- data/test/bug.rb +40 -51
- data/test/bug2.rb +10 -0
- data/test/io.rb +48 -0
- data/test/struct.rb +29 -0
- data/test/test_compat.rb +2 -0
- data/test/test_file.rb +2 -0
- data/test/test_object.rb +2 -0
- data/test/test_scp.rb +42 -5
- data/test/test_strict.rb +2 -0
- data/test/test_various.rb +2 -0
- data/test/write_timebars.rb +31 -0
- data/test/zip.rb +34 -0
- metadata +89 -104
- data/test/perf1.rb +0 -64
- data/test/perf2.rb +0 -76
- data/test/perf_obj_old.rb +0 -213
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 0a5afd2bda72fb22d683e9a6ed9f3064b423e8fa
|
4
|
+
data.tar.gz: b15ae64080dedd08f70ae05fc9dcaff5212ae3c0
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: bbb37aa63c547484e68159b90896357b02af944abefbf391f4cafedf67baddc213f8592f9907be7c59a267008d43c8a3166ccc066ab60f68704daa854c183e0a
|
7
|
+
data.tar.gz: 9a4833e9d76eb017c5cf7b34c7a28c48c8e7d673c18a4df6839100102099558329e2bbe5173cf02955ab98ddcd049187c692bc49c7a24326df2a72cbf065bba4
|
data/README.md
CHANGED
@@ -12,7 +12,7 @@ gem 'oj'
|
|
12
12
|
|
13
13
|
## Documentation
|
14
14
|
|
15
|
-
*Documentation*: http://www.ohler.com/oj
|
15
|
+
*Documentation*: http://www.ohler.com/oj, http://rubydoc.info/gems/oj
|
16
16
|
|
17
17
|
## Source
|
18
18
|
|
@@ -26,31 +26,18 @@ Follow [@peterohler on Twitter](http://twitter.com/#!/peterohler) for announceme
|
|
26
26
|
|
27
27
|
[![Build Status](https://secure.travis-ci.org/ohler55/oj.png?branch=master)](http://travis-ci.org/ohler55/oj)
|
28
28
|
|
29
|
-
### Current Release 2.
|
29
|
+
### Current Release 2.10.0
|
30
30
|
|
31
|
-
-
|
31
|
+
- Using an indent of less than zero will not place newline characters between
|
32
|
+
JSON elements when using the string or stream writer.
|
32
33
|
|
33
|
-
-
|
34
|
-
|
34
|
+
- new options callback method was added to the Simple Callback Parser. If
|
35
|
+
defined the prepare_key() method will be called when an JSON object ket is
|
36
|
+
first encountered. The return value is then used as the key in the key-value
|
37
|
+
pair.
|
35
38
|
|
36
|
-
-
|
37
|
-
|
38
|
-
|
39
|
-
- Using echo to STDIN as an IO input works around the exception raised when
|
40
|
-
asking the IO for it's position (IO.pos).
|
41
|
-
|
42
|
-
- Simple Callback Parser now uses the new stream parser for handling files and
|
43
|
-
IO so that larger files are handled more efficiently and streams are read as
|
44
|
-
data arrives instead of on close.
|
45
|
-
|
46
|
-
- Handles file FIFO pipes correctly now.
|
47
|
-
|
48
|
-
### Release 2.9.8
|
49
|
-
|
50
|
-
- Changed escaping back to previous release and added a new escape mode.
|
51
|
-
|
52
|
-
- Strict mode and compat mode no longer parse Infinity or NaN as a valid
|
53
|
-
number. Both are valid in object mode still.
|
39
|
+
- Increased significants digits to 16 from 15. On occasion there may be
|
40
|
+
unexpected round off results. Tou avoid those use the bigdecimal options.
|
54
41
|
|
55
42
|
[Older release notes](http://www.ohler.com/dev/oj_misc/release_notes.html).
|
56
43
|
|
data/ext/oj/compat.c
CHANGED
@@ -38,10 +38,14 @@
|
|
38
38
|
#include "encode.h"
|
39
39
|
|
40
40
|
static void
|
41
|
-
hash_set_cstr(ParseInfo pi,
|
42
|
-
|
41
|
+
hash_set_cstr(ParseInfo pi, Val kval, const char *str, size_t len, const char *orig) {
|
42
|
+
const char *key = kval->key;
|
43
|
+
int klen = kval->klen;
|
44
|
+
Val parent = stack_peek(&pi->stack);
|
45
|
+
volatile VALUE rkey = kval->key_val;
|
43
46
|
|
44
|
-
if (
|
47
|
+
if (Qundef == rkey &&
|
48
|
+
0 != pi->options.create_id &&
|
45
49
|
*pi->options.create_id == *key &&
|
46
50
|
pi->options.create_id_len == klen &&
|
47
51
|
0 == strncmp(pi->options.create_id, key, klen)) {
|
@@ -49,12 +53,14 @@ hash_set_cstr(ParseInfo pi, const char *key, size_t klen, const char *str, size_
|
|
49
53
|
parent->clen = len;
|
50
54
|
} else {
|
51
55
|
volatile VALUE rstr = rb_str_new(str, len);
|
52
|
-
volatile VALUE rkey = rb_str_new(key, klen);
|
53
56
|
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
rkey =
|
57
|
+
if (Qundef == rkey) {
|
58
|
+
rkey = rb_str_new(key, klen);
|
59
|
+
rstr = oj_encode(rstr);
|
60
|
+
rkey = oj_encode(rkey);
|
61
|
+
if (Yes == pi->options.sym_key) {
|
62
|
+
rkey = rb_str_intern(rkey);
|
63
|
+
}
|
58
64
|
}
|
59
65
|
rb_hash_aset(parent->val, rkey, rstr);
|
60
66
|
}
|
data/ext/oj/dump.c
CHANGED
@@ -468,7 +468,7 @@ dump_float(VALUE obj, Out out) {
|
|
468
468
|
} else if (d == (double)(long long int)d) {
|
469
469
|
cnt = sprintf(buf, "%.1f", d); // used sprintf due to bug in snprintf
|
470
470
|
} else {
|
471
|
-
cnt = sprintf(buf, "%0.
|
471
|
+
cnt = sprintf(buf, "%0.16g", d); // used sprintf due to bug in snprintf
|
472
472
|
}
|
473
473
|
if (out->end - out->cur <= (long)cnt) {
|
474
474
|
grow(out, cnt);
|
@@ -2340,7 +2340,7 @@ oj_str_writer_pop(StrWriter sw) {
|
|
2340
2340
|
*sw->out.cur++ = ']';
|
2341
2341
|
break;
|
2342
2342
|
}
|
2343
|
-
if (0 == sw->depth) {
|
2343
|
+
if (0 == sw->depth && 0 <= sw->out.indent) {
|
2344
2344
|
*sw->out.cur++ = '\n';
|
2345
2345
|
}
|
2346
2346
|
}
|
data/ext/oj/object.c
CHANGED
@@ -53,15 +53,15 @@ read_long(const char *str, size_t len) {
|
|
53
53
|
}
|
54
54
|
|
55
55
|
static VALUE
|
56
|
-
|
56
|
+
calc_hash_key(ParseInfo pi, Val kval, char k1) {
|
57
57
|
VALUE rkey;
|
58
58
|
|
59
59
|
if (':' == k1) {
|
60
|
-
rkey = rb_str_new(key + 1, klen - 1);
|
60
|
+
rkey = rb_str_new(kval->key + 1, kval->klen - 1);
|
61
61
|
rkey = oj_encode(rkey);
|
62
62
|
rkey = rb_funcall(rkey, oj_to_sym_id, 0);
|
63
63
|
} else {
|
64
|
-
rkey = rb_str_new(key, klen);
|
64
|
+
rkey = rb_str_new(kval->key, kval->klen);
|
65
65
|
rkey = oj_encode(rkey);
|
66
66
|
if (Yes == pi->options.sym_key) {
|
67
67
|
rkey = rb_str_intern(rkey);
|
@@ -94,7 +94,10 @@ str_to_value(ParseInfo pi, const char *str, size_t len, const char *orig) {
|
|
94
94
|
}
|
95
95
|
|
96
96
|
static int
|
97
|
-
hat_cstr(ParseInfo pi, Val parent,
|
97
|
+
hat_cstr(ParseInfo pi, Val parent, Val kval, const char *str, size_t len) {
|
98
|
+
const char *key = kval->key;
|
99
|
+
int klen = kval->klen;
|
100
|
+
|
98
101
|
if (2 == klen) {
|
99
102
|
switch (key[1]) {
|
100
103
|
case 'o': // object
|
@@ -139,9 +142,9 @@ hat_cstr(ParseInfo pi, Val parent, const char *key, size_t klen, const char *str
|
|
139
142
|
}
|
140
143
|
|
141
144
|
static int
|
142
|
-
hat_num(ParseInfo pi, Val parent,
|
143
|
-
if (2 == klen) {
|
144
|
-
switch (key[1]) {
|
145
|
+
hat_num(ParseInfo pi, Val parent, Val kval, NumInfo ni) {
|
146
|
+
if (2 == kval->klen) {
|
147
|
+
switch (kval->key[1]) {
|
145
148
|
case 't': // time as a float
|
146
149
|
{
|
147
150
|
int64_t nsec = ni->num * 1000000000LL / ni->div;
|
@@ -256,9 +259,11 @@ copy_ivars(VALUE target, VALUE src) {
|
|
256
259
|
}
|
257
260
|
|
258
261
|
static void
|
259
|
-
set_obj_ivar(Val parent,
|
260
|
-
|
261
|
-
|
262
|
+
set_obj_ivar(Val parent, Val kval, VALUE value) {
|
263
|
+
const char *key = kval->key;
|
264
|
+
int klen = kval->klen;
|
265
|
+
ID var_id;
|
266
|
+
ID *slot;
|
262
267
|
|
263
268
|
if ('~' == *key && Qtrue == rb_obj_is_kind_of(parent->val, rb_eException)) {
|
264
269
|
if (5 == klen && 0 == strncmp("~mesg", key, klen)) {
|
@@ -315,36 +320,38 @@ set_obj_ivar(Val parent, const char *key, size_t klen, VALUE value) {
|
|
315
320
|
}
|
316
321
|
|
317
322
|
static void
|
318
|
-
hash_set_cstr(ParseInfo pi,
|
319
|
-
|
323
|
+
hash_set_cstr(ParseInfo pi, Val kval, const char *str, size_t len, const char *orig) {
|
324
|
+
const char *key = kval->key;
|
325
|
+
int klen = kval->klen;
|
326
|
+
Val parent = stack_peek(&pi->stack);
|
320
327
|
|
321
328
|
WHICH_TYPE:
|
322
329
|
switch (rb_type(parent->val)) {
|
323
330
|
case T_NIL:
|
324
331
|
parent->odd_args = 0; // make sure it is 0 in case not odd
|
325
|
-
if ('^' != *key || !hat_cstr(pi, parent,
|
332
|
+
if ('^' != *key || !hat_cstr(pi, parent, kval, str, len)) {
|
326
333
|
parent->val = rb_hash_new();
|
327
334
|
goto WHICH_TYPE;
|
328
335
|
}
|
329
336
|
break;
|
330
337
|
case T_HASH:
|
331
|
-
rb_hash_aset(parent->val,
|
338
|
+
rb_hash_aset(parent->val, calc_hash_key(pi, kval, parent->k1), str_to_value(pi, str, len, orig));
|
332
339
|
break;
|
333
340
|
case T_STRING:
|
334
341
|
if (4 == klen && 's' == *key && 'e' == key[1] && 'l' == key[2] && 'f' == key[3]) {
|
335
342
|
rb_funcall(parent->val, oj_replace_id, 1, str_to_value(pi, str, len, orig));
|
336
343
|
} else {
|
337
|
-
set_obj_ivar(parent,
|
344
|
+
set_obj_ivar(parent, kval, str_to_value(pi, str, len, orig));
|
338
345
|
}
|
339
346
|
break;
|
340
347
|
case T_OBJECT:
|
341
|
-
set_obj_ivar(parent,
|
348
|
+
set_obj_ivar(parent, kval, str_to_value(pi, str, len, orig));
|
342
349
|
break;
|
343
350
|
case T_CLASS:
|
344
351
|
if (0 == parent->odd_args) {
|
345
352
|
oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "%s is not an odd class", rb_class2name(rb_obj_class(parent->val)));
|
346
353
|
return;
|
347
|
-
} else if (0 != oj_odd_set_arg(parent->odd_args, key, klen, str_to_value(pi, str, len, orig))) {
|
354
|
+
} else if (0 != oj_odd_set_arg(parent->odd_args, kval->key, kval->klen, str_to_value(pi, str, len, orig))) {
|
348
355
|
char buf[256];
|
349
356
|
|
350
357
|
if (sizeof(buf) - 1 <= klen) {
|
@@ -362,27 +369,29 @@ hash_set_cstr(ParseInfo pi, const char *key, size_t klen, const char *str, size_
|
|
362
369
|
}
|
363
370
|
|
364
371
|
static void
|
365
|
-
hash_set_num(ParseInfo pi,
|
366
|
-
|
372
|
+
hash_set_num(ParseInfo pi, Val kval, NumInfo ni) {
|
373
|
+
const char *key = kval->key;
|
374
|
+
int klen = kval->klen;
|
375
|
+
Val parent = stack_peek(&pi->stack);
|
367
376
|
|
368
377
|
WHICH_TYPE:
|
369
378
|
switch (rb_type(parent->val)) {
|
370
379
|
case T_NIL:
|
371
380
|
parent->odd_args = 0; // make sure it is 0 in case not odd
|
372
|
-
if ('^' != *key || !hat_num(pi, parent,
|
381
|
+
if ('^' != *key || !hat_num(pi, parent, kval, ni)) {
|
373
382
|
parent->val = rb_hash_new();
|
374
383
|
goto WHICH_TYPE;
|
375
384
|
}
|
376
385
|
break;
|
377
386
|
case T_HASH:
|
378
|
-
rb_hash_aset(parent->val,
|
387
|
+
rb_hash_aset(parent->val, calc_hash_key(pi, kval, parent->k1), oj_num_as_value(ni));
|
379
388
|
break;
|
380
389
|
case T_OBJECT:
|
381
390
|
if (2 == klen && '^' == *key && 'i' == key[1] &&
|
382
391
|
!ni->infinity && !ni->neg && 1 == ni->div && 0 == ni->exp && 0 != pi->circ_array) { // fixnum
|
383
392
|
oj_circ_array_set(pi->circ_array, parent->val, ni->i);
|
384
393
|
} else {
|
385
|
-
set_obj_ivar(parent,
|
394
|
+
set_obj_ivar(parent, kval, oj_num_as_value(ni));
|
386
395
|
}
|
387
396
|
break;
|
388
397
|
case T_CLASS:
|
@@ -407,8 +416,10 @@ hash_set_num(ParseInfo pi, const char *key, size_t klen, NumInfo ni) {
|
|
407
416
|
}
|
408
417
|
|
409
418
|
static void
|
410
|
-
hash_set_value(ParseInfo pi,
|
411
|
-
|
419
|
+
hash_set_value(ParseInfo pi, Val kval, VALUE value) {
|
420
|
+
const char *key = kval->key;
|
421
|
+
int klen = kval->klen;
|
422
|
+
Val parent = stack_peek(&pi->stack);
|
412
423
|
|
413
424
|
WHICH_TYPE:
|
414
425
|
switch (rb_type(parent->val)) {
|
@@ -424,7 +435,7 @@ hash_set_value(ParseInfo pi, const char *key, size_t klen, VALUE value) {
|
|
424
435
|
if (4 == klen && 's' == *key && 'e' == key[1] && 'l' == key[2] && 'f' == key[3]) {
|
425
436
|
rb_funcall(parent->val, oj_replace_id, 1, value);
|
426
437
|
} else {
|
427
|
-
set_obj_ivar(parent,
|
438
|
+
set_obj_ivar(parent, kval, value);
|
428
439
|
}
|
429
440
|
} else {
|
430
441
|
if (3 <= klen && '^' == *key && '#' == key[1] && T_ARRAY == rb_type(value)) {
|
@@ -437,7 +448,7 @@ hash_set_value(ParseInfo pi, const char *key, size_t klen, VALUE value) {
|
|
437
448
|
}
|
438
449
|
rb_hash_aset(parent->val, *a, a[1]);
|
439
450
|
} else {
|
440
|
-
rb_hash_aset(parent->val,
|
451
|
+
rb_hash_aset(parent->val, calc_hash_key(pi, kval, parent->k1), value);
|
441
452
|
}
|
442
453
|
}
|
443
454
|
break;
|
@@ -445,12 +456,12 @@ hash_set_value(ParseInfo pi, const char *key, size_t klen, VALUE value) {
|
|
445
456
|
if (4 == klen && 's' == *key && 'e' == key[1] && 'l' == key[2] && 'f' == key[3]) {
|
446
457
|
rb_funcall(parent->val, oj_replace_id, 1, value);
|
447
458
|
} else {
|
448
|
-
set_obj_ivar(parent,
|
459
|
+
set_obj_ivar(parent, kval, value);
|
449
460
|
}
|
450
461
|
break;
|
451
462
|
case T_STRING: // for subclassed strings
|
452
463
|
case T_OBJECT:
|
453
|
-
set_obj_ivar(parent,
|
464
|
+
set_obj_ivar(parent, kval, value);
|
454
465
|
break;
|
455
466
|
case T_CLASS:
|
456
467
|
if (0 == parent->odd_args) {
|
data/ext/oj/oj.c
CHANGED
@@ -62,6 +62,7 @@ ID oj_file_id;
|
|
62
62
|
ID oj_fileno_id;
|
63
63
|
ID oj_ftype_id;
|
64
64
|
ID oj_hash_end_id;
|
65
|
+
ID oj_hash_key_id;
|
65
66
|
ID oj_hash_set_id;
|
66
67
|
ID oj_hash_start_id;
|
67
68
|
ID oj_iconv_id;
|
@@ -180,7 +181,7 @@ static VALUE define_mimic_json(int argc, VALUE *argv, VALUE self);
|
|
180
181
|
/* call-seq: default_options() => Hash
|
181
182
|
*
|
182
183
|
* Returns the default load and dump options as a Hash. The options are
|
183
|
-
* - indent: [Fixnum] number of spaces to indent each element in an JSON document
|
184
|
+
* - indent: [Fixnum] number of spaces to indent each element in an JSON document, zero is no newline between JSON elements, negative indicates no newline between top level JSON elements in a stream
|
184
185
|
* - circular: [true|false|nil] support circular references while dumping
|
185
186
|
* - auto_define: [true|false|nil] automatically define classes if they do not exist
|
186
187
|
* - symbol_keys: [true|false|nil] use symbols instead of strings for hash keys
|
@@ -1959,6 +1960,7 @@ void Init_oj() {
|
|
1959
1960
|
oj_fileno_id = rb_intern("fileno");
|
1960
1961
|
oj_ftype_id = rb_intern("ftype");
|
1961
1962
|
oj_hash_end_id = rb_intern("hash_end");
|
1963
|
+
oj_hash_key_id = rb_intern("hash_key");
|
1962
1964
|
oj_hash_set_id = rb_intern("hash_set");
|
1963
1965
|
oj_hash_start_id = rb_intern("hash_start");
|
1964
1966
|
oj_iconv_id = rb_intern("iconv");
|
data/ext/oj/oj.h
CHANGED
data/ext/oj/parse.c
CHANGED
@@ -48,7 +48,7 @@
|
|
48
48
|
#define NUM_MAX (FIXNUM_MAX >> 8)
|
49
49
|
#endif
|
50
50
|
#define EXP_MAX 1023
|
51
|
-
#define DEC_MAX
|
51
|
+
#define DEC_MAX 15
|
52
52
|
|
53
53
|
static void
|
54
54
|
next_non_white(ParseInfo pi) {
|
@@ -110,8 +110,8 @@ add_value(ParseInfo pi, VALUE rval) {
|
|
110
110
|
parent->next = NEXT_ARRAY_COMMA;
|
111
111
|
break;
|
112
112
|
case NEXT_HASH_VALUE:
|
113
|
-
pi->hash_set_value(pi, parent
|
114
|
-
if (0 != parent->key && (parent->key < pi->json || pi->cur < parent->key)) {
|
113
|
+
pi->hash_set_value(pi, parent, rval);
|
114
|
+
if (0 != parent->key && 0 < parent->klen && (parent->key < pi->json || pi->cur < parent->key)) {
|
115
115
|
xfree((char*)parent->key);
|
116
116
|
parent->key = 0;
|
117
117
|
}
|
@@ -295,15 +295,19 @@ read_escaped_str(ParseInfo pi, const char *start) {
|
|
295
295
|
break;
|
296
296
|
case NEXT_HASH_NEW:
|
297
297
|
case NEXT_HASH_KEY:
|
298
|
-
|
299
|
-
|
300
|
-
|
298
|
+
if (Qundef == (parent->key_val = pi->hash_key(pi, buf.head, buf_len(&buf)))) {
|
299
|
+
parent->key = strdup(buf.head);
|
300
|
+
parent->klen = buf_len(&buf);
|
301
|
+
} else {
|
302
|
+
parent->key = "";
|
303
|
+
parent->klen = 0;
|
304
|
+
}
|
301
305
|
parent->k1 = *start;
|
302
306
|
parent->next = NEXT_HASH_COLON;
|
303
307
|
break;
|
304
308
|
case NEXT_HASH_VALUE:
|
305
|
-
pi->hash_set_cstr(pi, parent
|
306
|
-
if (0 != parent->key && (parent->key < pi->json || pi->cur < parent->key)) {
|
309
|
+
pi->hash_set_cstr(pi, parent, buf.head, buf_len(&buf), start);
|
310
|
+
if (0 != parent->key && 0 < parent->klen && (parent->key < pi->json || pi->cur < parent->key)) {
|
307
311
|
xfree((char*)parent->key);
|
308
312
|
parent->key = 0;
|
309
313
|
}
|
@@ -350,14 +354,19 @@ read_str(ParseInfo pi) {
|
|
350
354
|
break;
|
351
355
|
case NEXT_HASH_NEW:
|
352
356
|
case NEXT_HASH_KEY:
|
353
|
-
parent->
|
354
|
-
|
357
|
+
if (Qundef == (parent->key_val = pi->hash_key(pi, str, pi->cur - str))) {
|
358
|
+
parent->key = str;
|
359
|
+
parent->klen = pi->cur - str;
|
360
|
+
} else {
|
361
|
+
parent->key = "";
|
362
|
+
parent->klen = 0;
|
363
|
+
}
|
355
364
|
parent->k1 = *str;
|
356
365
|
parent->next = NEXT_HASH_COLON;
|
357
366
|
break;
|
358
367
|
case NEXT_HASH_VALUE:
|
359
|
-
pi->hash_set_cstr(pi, parent
|
360
|
-
if (0 != parent->key && (parent->key < pi->json || pi->cur < parent->key)) {
|
368
|
+
pi->hash_set_cstr(pi, parent, str, pi->cur - str, str);
|
369
|
+
if (0 != parent->key && 0 < parent->klen && (parent->key < pi->json || pi->cur < parent->key)) {
|
361
370
|
xfree((char*)parent->key);
|
362
371
|
parent->key = 0;
|
363
372
|
}
|
@@ -487,8 +496,8 @@ read_num(ParseInfo pi) {
|
|
487
496
|
parent->next = NEXT_ARRAY_COMMA;
|
488
497
|
break;
|
489
498
|
case NEXT_HASH_VALUE:
|
490
|
-
pi->hash_set_num(pi, parent
|
491
|
-
if (0 != parent->key && (parent->key < pi->json || pi->cur < parent->key)) {
|
499
|
+
pi->hash_set_num(pi, parent, &ni);
|
500
|
+
if (0 != parent->key && 0 < parent->klen && (parent->key < pi->json || pi->cur < parent->key)) {
|
492
501
|
xfree((char*)parent->key);
|
493
502
|
parent->key = 0;
|
494
503
|
}
|
@@ -702,13 +711,13 @@ oj_num_as_value(NumInfo ni) {
|
|
702
711
|
rnum = rb_funcall(rnum, rb_intern("to_f"), 0);
|
703
712
|
}
|
704
713
|
} else {
|
705
|
-
double d = (double)ni->i + (double)ni->num /
|
714
|
+
double d = (double)ni->i + (double)ni->num * (1.0L / ni->div);
|
706
715
|
|
707
716
|
if (ni->neg) {
|
708
717
|
d = -d;
|
709
718
|
}
|
710
719
|
if (0 != ni->exp) {
|
711
|
-
d *= pow(10.
|
720
|
+
d *= pow(10.0L, ni->exp);
|
712
721
|
}
|
713
722
|
rnum = rb_float_new(d);
|
714
723
|
}
|
data/ext/oj/parse.h
CHANGED
@@ -72,9 +72,10 @@ typedef struct _ParseInfo {
|
|
72
72
|
VALUE proc;
|
73
73
|
VALUE (*start_hash)(struct _ParseInfo *pi);
|
74
74
|
void (*end_hash)(struct _ParseInfo *pi);
|
75
|
-
|
76
|
-
void (*
|
77
|
-
void (*
|
75
|
+
VALUE (*hash_key)(struct _ParseInfo *pi, const char *key, size_t klen);
|
76
|
+
void (*hash_set_cstr)(struct _ParseInfo *pi, Val kval, const char *str, size_t len, const char *orig);
|
77
|
+
void (*hash_set_num)(struct _ParseInfo *pi, Val kval, NumInfo ni);
|
78
|
+
void (*hash_set_value)(struct _ParseInfo *pi, Val kval, VALUE value);
|
78
79
|
|
79
80
|
VALUE (*start_array)(struct _ParseInfo *pi);
|
80
81
|
void (*end_array)(struct _ParseInfo *pi);
|
data/ext/oj/scp.c
CHANGED
@@ -60,16 +60,21 @@ static void
|
|
60
60
|
noop_add_num(ParseInfo pi, NumInfo ni) {
|
61
61
|
}
|
62
62
|
|
63
|
+
static VALUE
|
64
|
+
noop_hash_key(struct _ParseInfo *pi, const char *key, size_t klen) {
|
65
|
+
return Qundef;
|
66
|
+
}
|
67
|
+
|
63
68
|
static void
|
64
|
-
noop_hash_set_cstr(ParseInfo pi,
|
69
|
+
noop_hash_set_cstr(ParseInfo pi, Val kval, const char *str, size_t len, const char *orig) {
|
65
70
|
}
|
66
71
|
|
67
72
|
static void
|
68
|
-
noop_hash_set_num(ParseInfo pi,
|
73
|
+
noop_hash_set_num(ParseInfo pi, Val kval, NumInfo ni) {
|
69
74
|
}
|
70
75
|
|
71
76
|
static void
|
72
|
-
noop_hash_set_value(ParseInfo pi,
|
77
|
+
noop_hash_set_value(ParseInfo pi, Val kval, VALUE value) {
|
73
78
|
}
|
74
79
|
|
75
80
|
static void
|
@@ -123,32 +128,40 @@ end_array(ParseInfo pi) {
|
|
123
128
|
}
|
124
129
|
|
125
130
|
static VALUE
|
126
|
-
|
127
|
-
volatile VALUE rkey =
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
rkey =
|
131
|
+
calc_hash_key(ParseInfo pi, Val kval) {
|
132
|
+
volatile VALUE rkey = kval->key_val;
|
133
|
+
|
134
|
+
if (Qundef == rkey) {
|
135
|
+
rkey = rb_str_new(kval->key, kval->klen);
|
136
|
+
rkey = oj_encode(rkey);
|
137
|
+
if (Yes == pi->options.sym_key) {
|
138
|
+
rkey = rb_str_intern(rkey);
|
139
|
+
}
|
132
140
|
}
|
133
141
|
return rkey;
|
134
142
|
}
|
135
143
|
|
144
|
+
static VALUE
|
145
|
+
hash_key(struct _ParseInfo *pi, const char *key, size_t klen) {
|
146
|
+
return rb_funcall(pi->handler, oj_hash_key_id, 1, rb_str_new(key, klen));
|
147
|
+
}
|
148
|
+
|
136
149
|
static void
|
137
|
-
hash_set_cstr(ParseInfo pi,
|
150
|
+
hash_set_cstr(ParseInfo pi, Val kval, const char *str, size_t len, const char *orig) {
|
138
151
|
volatile VALUE rstr = rb_str_new(str, len);
|
139
152
|
|
140
153
|
rstr = oj_encode(rstr);
|
141
|
-
rb_funcall(pi->handler, oj_hash_set_id, 3, stack_peek(&pi->stack)->val,
|
154
|
+
rb_funcall(pi->handler, oj_hash_set_id, 3, stack_peek(&pi->stack)->val, calc_hash_key(pi, kval), rstr);
|
142
155
|
}
|
143
156
|
|
144
157
|
static void
|
145
|
-
hash_set_num(ParseInfo pi,
|
146
|
-
rb_funcall(pi->handler, oj_hash_set_id, 3, stack_peek(&pi->stack)->val,
|
158
|
+
hash_set_num(ParseInfo pi, Val kval, NumInfo ni) {
|
159
|
+
rb_funcall(pi->handler, oj_hash_set_id, 3, stack_peek(&pi->stack)->val, calc_hash_key(pi, kval), oj_num_as_value(ni));
|
147
160
|
}
|
148
161
|
|
149
162
|
static void
|
150
|
-
hash_set_value(ParseInfo pi,
|
151
|
-
rb_funcall(pi->handler, oj_hash_set_id, 3, stack_peek(&pi->stack)->val,
|
163
|
+
hash_set_value(ParseInfo pi, Val kval, VALUE value) {
|
164
|
+
rb_funcall(pi->handler, oj_hash_set_id, 3, stack_peek(&pi->stack)->val, calc_hash_key(pi, kval), value);
|
152
165
|
}
|
153
166
|
|
154
167
|
static void
|
@@ -187,6 +200,7 @@ oj_sc_parse(int argc, VALUE *argv, VALUE self) {
|
|
187
200
|
|
188
201
|
pi.start_hash = rb_respond_to(pi.handler, oj_hash_start_id) ? start_hash : noop_start;
|
189
202
|
pi.end_hash = rb_respond_to(pi.handler, oj_hash_end_id) ? end_hash : noop_end;
|
203
|
+
pi.hash_key = rb_respond_to(pi.handler, oj_hash_key_id) ? hash_key : noop_hash_key;
|
190
204
|
pi.start_array = rb_respond_to(pi.handler, oj_array_start_id) ? start_array : noop_start;
|
191
205
|
pi.end_array = rb_respond_to(pi.handler, oj_array_end_id) ? end_array : noop_end;
|
192
206
|
if (rb_respond_to(pi.handler, oj_hash_set_id)) {
|