oj 2.9.8 → 2.9.9
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.
- data/README.md +20 -1
- data/ext/oj/compat.c +2 -0
- data/ext/oj/dump.c +1 -1
- data/ext/oj/object.c +3 -2
- data/ext/oj/oj.c +8 -1
- data/ext/oj/oj.h +3 -0
- data/ext/oj/parse.c +2 -7
- data/ext/oj/parse.h +1 -1
- data/ext/oj/reader.c +17 -24
- data/ext/oj/saj.c +8 -28
- data/ext/oj/scp.c +27 -106
- data/ext/oj/sparse.c +0 -2
- data/ext/oj/strict.c +2 -0
- data/lib/oj/version.rb +1 -1
- data/test/bug.rb +50 -39
- data/test/perf1.rb +64 -0
- data/test/perf2.rb +76 -0
- data/test/perf_obj_old.rb +213 -0
- data/test/test_object.rb +10 -0
- data/test/test_scp.rb +22 -0
- data/test/test_various.rb +1 -1
- metadata +104 -87
- checksums.yaml +0 -7
- data/test/io.rb +0 -48
- data/test/struct.rb +0 -29
- data/test/zip.rb +0 -34
data/README.md
CHANGED
@@ -26,7 +26,26 @@ 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.9.
|
29
|
+
### Current Release 2.9.9
|
30
|
+
|
31
|
+
- Missed a character map entry. / in ascii mode is now output as / and not \/
|
32
|
+
|
33
|
+
- Fixed SC parser to not treat all IO that respond to fileno as a file. It not
|
34
|
+
checks stat and asks if it is a file.
|
35
|
+
|
36
|
+
- Tightened object parsing of non-string hash keys so that just "^#x" is parsed
|
37
|
+
as a hash pair and not "~#x".
|
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
|
30
49
|
|
31
50
|
- Changed escaping back to previous release and added a new escape mode.
|
32
51
|
|
data/ext/oj/compat.c
CHANGED
@@ -90,6 +90,7 @@ oj_compat_parse(int argc, VALUE *argv, VALUE self) {
|
|
90
90
|
struct _ParseInfo pi;
|
91
91
|
|
92
92
|
pi.options = oj_default_options;
|
93
|
+
pi.handler = Qnil;
|
93
94
|
oj_set_compat_callbacks(&pi);
|
94
95
|
|
95
96
|
if (T_STRING == rb_type(*argv)) {
|
@@ -104,6 +105,7 @@ oj_compat_parse_cstr(int argc, VALUE *argv, char *json, size_t len) {
|
|
104
105
|
struct _ParseInfo pi;
|
105
106
|
|
106
107
|
pi.options = oj_default_options;
|
108
|
+
pi.handler = Qnil;
|
107
109
|
oj_set_strict_callbacks(&pi);
|
108
110
|
pi.end_hash = end_hash;
|
109
111
|
pi.hash_set_cstr = hash_set_cstr;
|
data/ext/oj/dump.c
CHANGED
@@ -137,7 +137,7 @@ static char hibit_friendly_chars[256] = "\
|
|
137
137
|
// bytes per character in the output. That makes this conservative.
|
138
138
|
static char ascii_friendly_chars[256] = "\
|
139
139
|
66666666222622666666666666666666\
|
140
|
-
|
140
|
+
11211111111111111111111111111111\
|
141
141
|
11111111111111111111111111112111\
|
142
142
|
11111111111111111111111111111116\
|
143
143
|
33333333333333333333333333333333\
|
data/ext/oj/object.c
CHANGED
@@ -420,7 +420,6 @@ hash_set_value(ParseInfo pi, const char *key, size_t klen, VALUE value) {
|
|
420
420
|
}
|
421
421
|
break;
|
422
422
|
case T_HASH:
|
423
|
-
|
424
423
|
if (rb_cHash != rb_obj_class(parent->val)) {
|
425
424
|
if (4 == klen && 's' == *key && 'e' == key[1] && 'l' == key[2] && 'f' == key[3]) {
|
426
425
|
rb_funcall(parent->val, oj_replace_id, 1, value);
|
@@ -428,7 +427,7 @@ hash_set_value(ParseInfo pi, const char *key, size_t klen, VALUE value) {
|
|
428
427
|
set_obj_ivar(parent, key, klen, value);
|
429
428
|
}
|
430
429
|
} else {
|
431
|
-
if (3 <= klen && '#' == key[1] && T_ARRAY == rb_type(value)) {
|
430
|
+
if (3 <= klen && '^' == *key && '#' == key[1] && T_ARRAY == rb_type(value)) {
|
432
431
|
long len = RARRAY_LEN(value);
|
433
432
|
VALUE *a = RARRAY_PTR(value);
|
434
433
|
|
@@ -551,6 +550,7 @@ oj_object_parse(int argc, VALUE *argv, VALUE self) {
|
|
551
550
|
struct _ParseInfo pi;
|
552
551
|
|
553
552
|
pi.options = oj_default_options;
|
553
|
+
pi.handler = Qnil;
|
554
554
|
oj_set_object_callbacks(&pi);
|
555
555
|
|
556
556
|
if (T_STRING == rb_type(*argv)) {
|
@@ -565,6 +565,7 @@ oj_object_parse_cstr(int argc, VALUE *argv, char *json, size_t len) {
|
|
565
565
|
struct _ParseInfo pi;
|
566
566
|
|
567
567
|
pi.options = oj_default_options;
|
568
|
+
pi.handler = Qnil;
|
568
569
|
oj_set_strict_callbacks(&pi);
|
569
570
|
pi.end_hash = end_hash;
|
570
571
|
pi.start_hash = start_hash;
|
data/ext/oj/oj.c
CHANGED
@@ -58,7 +58,9 @@ ID oj_array_end_id;
|
|
58
58
|
ID oj_array_start_id;
|
59
59
|
ID oj_as_json_id;
|
60
60
|
ID oj_error_id;
|
61
|
+
ID oj_file_id;
|
61
62
|
ID oj_fileno_id;
|
63
|
+
ID oj_ftype_id;
|
62
64
|
ID oj_hash_end_id;
|
63
65
|
ID oj_hash_set_id;
|
64
66
|
ID oj_hash_start_id;
|
@@ -71,6 +73,7 @@ ID oj_pos_id;
|
|
71
73
|
ID oj_read_id;
|
72
74
|
ID oj_readpartial_id;
|
73
75
|
ID oj_replace_id;
|
76
|
+
ID oj_stat_id;
|
74
77
|
ID oj_string_id;
|
75
78
|
ID oj_to_hash_id;
|
76
79
|
ID oj_to_json_id;
|
@@ -353,7 +356,7 @@ set_def_opts(VALUE self, VALUE opts) {
|
|
353
356
|
} else if (ascii_sym == v) {
|
354
357
|
oj_default_options.escape_mode = ASCIIEsc;
|
355
358
|
} else {
|
356
|
-
rb_raise(rb_eArgError, ":encoding must be :json, :
|
359
|
+
rb_raise(rb_eArgError, ":encoding must be :json, :xss_safe, or :ascii.");
|
357
360
|
}
|
358
361
|
|
359
362
|
v = rb_hash_lookup(opts, bigdecimal_load_sym);
|
@@ -715,6 +718,7 @@ load_file(int argc, VALUE *argv, VALUE self) {
|
|
715
718
|
}
|
716
719
|
Check_Type(*argv, T_STRING);
|
717
720
|
pi.options = oj_default_options;
|
721
|
+
pi.handler = Qnil;
|
718
722
|
if (2 <= argc) {
|
719
723
|
VALUE ropts = argv[1];
|
720
724
|
VALUE v;
|
@@ -1951,7 +1955,9 @@ void Init_oj() {
|
|
1951
1955
|
oj_array_start_id = rb_intern("array_start");
|
1952
1956
|
oj_as_json_id = rb_intern("as_json");
|
1953
1957
|
oj_error_id = rb_intern("error");
|
1958
|
+
oj_file_id = rb_intern("file?");
|
1954
1959
|
oj_fileno_id = rb_intern("fileno");
|
1960
|
+
oj_ftype_id = rb_intern("ftype");
|
1955
1961
|
oj_hash_end_id = rb_intern("hash_end");
|
1956
1962
|
oj_hash_set_id = rb_intern("hash_set");
|
1957
1963
|
oj_hash_start_id = rb_intern("hash_start");
|
@@ -1964,6 +1970,7 @@ void Init_oj() {
|
|
1964
1970
|
oj_read_id = rb_intern("read");
|
1965
1971
|
oj_readpartial_id = rb_intern("readpartial");
|
1966
1972
|
oj_replace_id = rb_intern("replace");
|
1973
|
+
oj_stat_id = rb_intern("stat");
|
1967
1974
|
oj_string_id = rb_intern("string");
|
1968
1975
|
oj_to_hash_id = rb_intern("to_hash");
|
1969
1976
|
oj_to_json_id = rb_intern("to_json");
|
data/ext/oj/oj.h
CHANGED
@@ -255,7 +255,9 @@ extern ID oj_array_end_id;
|
|
255
255
|
extern ID oj_array_start_id;
|
256
256
|
extern ID oj_as_json_id;
|
257
257
|
extern ID oj_error_id;
|
258
|
+
extern ID oj_file_id;
|
258
259
|
extern ID oj_fileno_id;
|
260
|
+
extern ID oj_ftype_id;
|
259
261
|
extern ID oj_hash_end_id;
|
260
262
|
extern ID oj_hash_set_id;
|
261
263
|
extern ID oj_hash_start_id;
|
@@ -268,6 +270,7 @@ extern ID oj_pos_id;
|
|
268
270
|
extern ID oj_read_id;
|
269
271
|
extern ID oj_readpartial_id;
|
270
272
|
extern ID oj_replace_id;
|
273
|
+
extern ID oj_stat_id;
|
271
274
|
extern ID oj_string_id;
|
272
275
|
extern ID oj_to_hash_id;
|
273
276
|
extern ID oj_to_json_id;
|
data/ext/oj/parse.c
CHANGED
@@ -766,7 +766,6 @@ oj_pi_parse(int argc, VALUE *argv, ParseInfo pi, char *json, size_t len, int yie
|
|
766
766
|
} else {
|
767
767
|
pi->proc = Qundef;
|
768
768
|
}
|
769
|
-
pi->cbc = (void*)0;
|
770
769
|
if (0 != json) {
|
771
770
|
pi->json = json;
|
772
771
|
pi->end = json + len;
|
@@ -778,17 +777,13 @@ oj_pi_parse(int argc, VALUE *argv, ParseInfo pi, char *json, size_t len, int yie
|
|
778
777
|
} else {
|
779
778
|
VALUE clas = rb_obj_class(input);
|
780
779
|
volatile VALUE s;
|
781
|
-
#if !IS_WINDOWS
|
782
|
-
int fd;
|
783
|
-
#endif
|
784
780
|
|
785
781
|
if (oj_stringio_class == clas) {
|
786
782
|
s = rb_funcall2(input, oj_string_id, 0, 0);
|
787
783
|
oj_pi_set_input_str(pi, s);
|
788
784
|
#if !IS_WINDOWS
|
789
|
-
} else if (
|
790
|
-
|
791
|
-
0 != (fd = FIX2INT(s))) {
|
785
|
+
} else if (rb_cFile == clas && 0 == FIX2INT(rb_funcall(input, oj_pos_id, 0))) {
|
786
|
+
int fd = FIX2INT(rb_funcall(input, oj_fileno_id, 0));
|
792
787
|
ssize_t cnt;
|
793
788
|
size_t len = lseek(fd, 0, SEEK_END);
|
794
789
|
|
data/ext/oj/parse.h
CHANGED
data/ext/oj/reader.c
CHANGED
@@ -55,6 +55,10 @@ static int read_from_str(Reader reader);
|
|
55
55
|
|
56
56
|
void
|
57
57
|
oj_reader_init(Reader reader, VALUE io, int fd) {
|
58
|
+
VALUE io_class = rb_obj_class(io);
|
59
|
+
VALUE stat;
|
60
|
+
VALUE ftype;
|
61
|
+
|
58
62
|
reader->head = reader->base;
|
59
63
|
*((char*)reader->head) = '\0';
|
60
64
|
reader->end = reader->head + sizeof(reader->base) - BUF_PAD;
|
@@ -69,13 +73,13 @@ oj_reader_init(Reader reader, VALUE io, int fd) {
|
|
69
73
|
if (0 != fd) {
|
70
74
|
reader->read_func = read_from_fd;
|
71
75
|
reader->fd = fd;
|
72
|
-
} else if (rb_cString ==
|
76
|
+
} else if (rb_cString == io_class) {
|
73
77
|
reader->read_func = read_from_str;
|
74
78
|
reader->in_str = StringValuePtr(io);
|
75
79
|
reader->head = (char*)reader->in_str;
|
76
80
|
reader->tail = reader->head;
|
77
81
|
reader->read_end = reader->head + RSTRING_LEN(io);
|
78
|
-
} else if (oj_stringio_class ==
|
82
|
+
} else if (oj_stringio_class == io_class) {
|
79
83
|
VALUE s = rb_funcall2(io, oj_string_id, 0, 0);
|
80
84
|
|
81
85
|
reader->read_func = read_from_str;
|
@@ -83,30 +87,19 @@ oj_reader_init(Reader reader, VALUE io, int fd) {
|
|
83
87
|
reader->head = (char*)reader->in_str;
|
84
88
|
reader->tail = reader->head;
|
85
89
|
reader->read_end = reader->head + RSTRING_LEN(s);
|
90
|
+
} else if (rb_cFile == io_class &&
|
91
|
+
Qnil != (stat = rb_funcall(io, oj_stat_id, 0)) &&
|
92
|
+
Qnil != (ftype = rb_funcall(stat, oj_ftype_id, 0)) &&
|
93
|
+
0 == strcmp("file", StringValuePtr(ftype)) &&
|
94
|
+
0 == FIX2INT(rb_funcall(io, oj_pos_id, 0))) {
|
95
|
+
reader->read_func = read_from_fd;
|
96
|
+
reader->fd = FIX2INT(rb_funcall(io, oj_fileno_id, 0));
|
86
97
|
} else if (rb_respond_to(io, oj_readpartial_id)) {
|
87
|
-
|
88
|
-
|
89
|
-
if (rb_respond_to(io, oj_fileno_id) && Qnil != (rfd = rb_funcall(io, oj_fileno_id, 0)) &&
|
90
|
-
rb_respond_to(io, oj_pos_id) && 0 == FIX2INT(rb_funcall(io, oj_pos_id, 0))) {
|
91
|
-
|
92
|
-
reader->read_func = read_from_fd;
|
93
|
-
reader->fd = FIX2INT(rfd);
|
94
|
-
} else {
|
95
|
-
reader->read_func = read_from_io_partial;
|
96
|
-
reader->io = io;
|
97
|
-
}
|
98
|
+
reader->read_func = read_from_io_partial;
|
99
|
+
reader->io = io;
|
98
100
|
} else if (rb_respond_to(io, oj_read_id)) {
|
99
|
-
|
100
|
-
|
101
|
-
if (rb_respond_to(io, oj_fileno_id) && Qnil != (rfd = rb_funcall(io, oj_fileno_id, 0)) &&
|
102
|
-
rb_respond_to(io, oj_pos_id) && 0 == FIX2INT(rb_funcall(io, oj_pos_id, 0))) {
|
103
|
-
|
104
|
-
reader->read_func = read_from_fd;
|
105
|
-
reader->fd = FIX2INT(rfd);
|
106
|
-
} else {
|
107
|
-
reader->read_func = read_from_io;
|
108
|
-
reader->io = io;
|
109
|
-
}
|
101
|
+
reader->read_func = read_from_io;
|
102
|
+
reader->io = io;
|
110
103
|
} else {
|
111
104
|
rb_raise(rb_eException, "parser io argument must respond to readpartial() or read().\n");
|
112
105
|
}
|
data/ext/oj/saj.c
CHANGED
@@ -627,22 +627,6 @@ read_quoted_value(ParseInfo pi) {
|
|
627
627
|
return value;
|
628
628
|
}
|
629
629
|
|
630
|
-
inline static int
|
631
|
-
respond_to(VALUE obj, ID method) {
|
632
|
-
#ifdef JRUBY_RUBY
|
633
|
-
/* There is a bug in JRuby where rb_respond_to() returns true (1) even if
|
634
|
-
* a method is private. */
|
635
|
-
{
|
636
|
-
VALUE args[1];
|
637
|
-
|
638
|
-
*args = ID2SYM(method);
|
639
|
-
return (Qtrue == rb_funcall2(obj, rb_intern("respond_to?"), 1, args));
|
640
|
-
}
|
641
|
-
#else
|
642
|
-
return rb_respond_to(obj, method);
|
643
|
-
#endif
|
644
|
-
}
|
645
|
-
|
646
630
|
static void
|
647
631
|
saj_parse(VALUE handler, char *json) {
|
648
632
|
volatile VALUE obj = Qnil;
|
@@ -675,12 +659,12 @@ saj_parse(VALUE handler, char *json) {
|
|
675
659
|
}
|
676
660
|
#endif
|
677
661
|
pi.handler = handler;
|
678
|
-
pi.has_hash_start =
|
679
|
-
pi.has_hash_end =
|
680
|
-
pi.has_array_start =
|
681
|
-
pi.has_array_end =
|
682
|
-
pi.has_add_value =
|
683
|
-
pi.has_error =
|
662
|
+
pi.has_hash_start = rb_respond_to(handler, oj_hash_start_id);
|
663
|
+
pi.has_hash_end = rb_respond_to(handler, oj_hash_end_id);
|
664
|
+
pi.has_array_start = rb_respond_to(handler, oj_array_start_id);
|
665
|
+
pi.has_array_end = rb_respond_to(handler, oj_array_end_id);
|
666
|
+
pi.has_add_value = rb_respond_to(handler, oj_add_value_id);
|
667
|
+
pi.has_error = rb_respond_to(handler, oj_error_id);
|
684
668
|
read_next(&pi, 0);
|
685
669
|
next_non_white(&pi);
|
686
670
|
if ('\0' != *pi.s) {
|
@@ -716,9 +700,6 @@ oj_saj_parse(int argc, VALUE *argv, VALUE self) {
|
|
716
700
|
} else {
|
717
701
|
VALUE clas = rb_obj_class(input);
|
718
702
|
volatile VALUE s;
|
719
|
-
#if !IS_WINDOWS
|
720
|
-
int fd;
|
721
|
-
#endif
|
722
703
|
|
723
704
|
if (oj_stringio_class == clas) {
|
724
705
|
s = rb_funcall2(input, oj_string_id, 0, 0);
|
@@ -726,9 +707,8 @@ oj_saj_parse(int argc, VALUE *argv, VALUE self) {
|
|
726
707
|
json = ALLOC_N(char, len);
|
727
708
|
strcpy(json, rb_string_value_cstr((VALUE*)&s));
|
728
709
|
#if !IS_WINDOWS
|
729
|
-
} else if (
|
730
|
-
|
731
|
-
0 != (fd = FIX2INT(s))) {
|
710
|
+
} else if (rb_cFile == clas && 0 == FIX2INT(rb_funcall(input, oj_pos_id, 0))) {
|
711
|
+
int fd = FIX2INT(rb_funcall(input, oj_fileno_id, 0));
|
732
712
|
ssize_t cnt;
|
733
713
|
|
734
714
|
len = lseek(fd, 0, SEEK_END);
|
data/ext/oj/scp.c
CHANGED
@@ -39,22 +39,6 @@
|
|
39
39
|
#include "parse.h"
|
40
40
|
#include "encode.h"
|
41
41
|
|
42
|
-
inline static int
|
43
|
-
respond_to(VALUE obj, ID method) {
|
44
|
-
#ifdef JRUBY_RUBY
|
45
|
-
/* There is a bug in JRuby where rb_respond_to() returns true (1) even if
|
46
|
-
* a method is private. */
|
47
|
-
{
|
48
|
-
VALUE args[1];
|
49
|
-
|
50
|
-
*args = ID2SYM(method);
|
51
|
-
return (Qtrue == rb_funcall2(obj, rb_intern("respond_to?"), 1, args));
|
52
|
-
}
|
53
|
-
#else
|
54
|
-
return rb_respond_to(obj, method);
|
55
|
-
#endif
|
56
|
-
}
|
57
|
-
|
58
42
|
static VALUE
|
59
43
|
noop_start(ParseInfo pi) {
|
60
44
|
return Qnil;
|
@@ -102,7 +86,7 @@ noop_array_append_value(ParseInfo pi, VALUE value) {
|
|
102
86
|
|
103
87
|
static void
|
104
88
|
add_value(ParseInfo pi, VALUE val) {
|
105
|
-
rb_funcall(
|
89
|
+
rb_funcall(pi->handler, oj_add_value_id, 1, val);
|
106
90
|
}
|
107
91
|
|
108
92
|
static void
|
@@ -110,32 +94,32 @@ add_cstr(ParseInfo pi, const char *str, size_t len, const char *orig) {
|
|
110
94
|
volatile VALUE rstr = rb_str_new(str, len);
|
111
95
|
|
112
96
|
rstr = oj_encode(rstr);
|
113
|
-
rb_funcall(
|
97
|
+
rb_funcall(pi->handler, oj_add_value_id, 1, rstr);
|
114
98
|
}
|
115
99
|
|
116
100
|
static void
|
117
101
|
add_num(ParseInfo pi, NumInfo ni) {
|
118
|
-
rb_funcall(
|
102
|
+
rb_funcall(pi->handler, oj_add_value_id, 1, oj_num_as_value(ni));
|
119
103
|
}
|
120
104
|
|
121
105
|
static VALUE
|
122
106
|
start_hash(ParseInfo pi) {
|
123
|
-
return rb_funcall(
|
107
|
+
return rb_funcall(pi->handler, oj_hash_start_id, 0);
|
124
108
|
}
|
125
109
|
|
126
110
|
static void
|
127
111
|
end_hash(ParseInfo pi) {
|
128
|
-
rb_funcall(
|
112
|
+
rb_funcall(pi->handler, oj_hash_end_id, 0);
|
129
113
|
}
|
130
114
|
|
131
115
|
static VALUE
|
132
116
|
start_array(ParseInfo pi) {
|
133
|
-
return rb_funcall(
|
117
|
+
return rb_funcall(pi->handler, oj_array_start_id, 0);
|
134
118
|
}
|
135
119
|
|
136
120
|
static void
|
137
121
|
end_array(ParseInfo pi) {
|
138
|
-
rb_funcall(
|
122
|
+
rb_funcall(pi->handler, oj_array_end_id, 0);
|
139
123
|
}
|
140
124
|
|
141
125
|
static VALUE
|
@@ -154,17 +138,17 @@ hash_set_cstr(ParseInfo pi, const char *key, size_t klen, const char *str, size_
|
|
154
138
|
volatile VALUE rstr = rb_str_new(str, len);
|
155
139
|
|
156
140
|
rstr = oj_encode(rstr);
|
157
|
-
rb_funcall(
|
141
|
+
rb_funcall(pi->handler, oj_hash_set_id, 3, stack_peek(&pi->stack)->val, hash_key(pi, key, klen), rstr);
|
158
142
|
}
|
159
143
|
|
160
144
|
static void
|
161
145
|
hash_set_num(ParseInfo pi, const char *key, size_t klen, NumInfo ni) {
|
162
|
-
rb_funcall(
|
146
|
+
rb_funcall(pi->handler, oj_hash_set_id, 3, stack_peek(&pi->stack)->val, hash_key(pi, key, klen), oj_num_as_value(ni));
|
163
147
|
}
|
164
148
|
|
165
149
|
static void
|
166
150
|
hash_set_value(ParseInfo pi, const char *key, size_t klen, VALUE value) {
|
167
|
-
rb_funcall(
|
151
|
+
rb_funcall(pi->handler, oj_hash_set_id, 3, stack_peek(&pi->stack)->val, hash_key(pi, key, klen), value);
|
168
152
|
}
|
169
153
|
|
170
154
|
static void
|
@@ -172,41 +156,24 @@ array_append_cstr(ParseInfo pi, const char *str, size_t len, const char *orig) {
|
|
172
156
|
volatile VALUE rstr = rb_str_new(str, len);
|
173
157
|
|
174
158
|
rstr = oj_encode(rstr);
|
175
|
-
rb_funcall(
|
159
|
+
rb_funcall(pi->handler, oj_array_append_id, 2, stack_peek(&pi->stack)->val, rstr);
|
176
160
|
}
|
177
161
|
|
178
162
|
static void
|
179
163
|
array_append_num(ParseInfo pi, NumInfo ni) {
|
180
|
-
rb_funcall(
|
164
|
+
rb_funcall(pi->handler, oj_array_append_id, 2, stack_peek(&pi->stack)->val, oj_num_as_value(ni));
|
181
165
|
}
|
182
166
|
|
183
167
|
static void
|
184
168
|
array_append_value(ParseInfo pi, VALUE value) {
|
185
|
-
rb_funcall(
|
186
|
-
}
|
187
|
-
|
188
|
-
static VALUE
|
189
|
-
protect_parse(VALUE pip) {
|
190
|
-
oj_parse2((ParseInfo)pip);
|
191
|
-
|
192
|
-
return Qnil;
|
169
|
+
rb_funcall(pi->handler, oj_array_append_id, 2, stack_peek(&pi->stack)->val, value);
|
193
170
|
}
|
194
171
|
|
195
172
|
VALUE
|
196
173
|
oj_sc_parse(int argc, VALUE *argv, VALUE self) {
|
197
174
|
struct _ParseInfo pi;
|
198
|
-
|
199
|
-
|
200
|
-
VALUE handler;
|
201
|
-
volatile VALUE wrapped_stack;
|
202
|
-
int line = 0;
|
203
|
-
|
204
|
-
if (argc < 2) {
|
205
|
-
rb_raise(rb_eArgError, "Wrong number of arguments to saj_parse.");
|
206
|
-
}
|
207
|
-
handler = *argv;;
|
208
|
-
input = argv[1];
|
209
|
-
pi.json = 0;
|
175
|
+
VALUE input = argv[1];
|
176
|
+
|
210
177
|
pi.options = oj_default_options;
|
211
178
|
if (3 == argc) {
|
212
179
|
oj_parse_options(argv[2], &pi.options);
|
@@ -216,13 +183,13 @@ oj_sc_parse(int argc, VALUE *argv, VALUE self) {
|
|
216
183
|
} else {
|
217
184
|
pi.proc = Qundef;
|
218
185
|
}
|
219
|
-
pi.
|
186
|
+
pi.handler = *argv;
|
220
187
|
|
221
|
-
pi.start_hash =
|
222
|
-
pi.end_hash =
|
223
|
-
pi.start_array =
|
224
|
-
pi.end_array =
|
225
|
-
if (
|
188
|
+
pi.start_hash = rb_respond_to(pi.handler, oj_hash_start_id) ? start_hash : noop_start;
|
189
|
+
pi.end_hash = rb_respond_to(pi.handler, oj_hash_end_id) ? end_hash : noop_end;
|
190
|
+
pi.start_array = rb_respond_to(pi.handler, oj_array_start_id) ? start_array : noop_start;
|
191
|
+
pi.end_array = rb_respond_to(pi.handler, oj_array_end_id) ? end_array : noop_end;
|
192
|
+
if (rb_respond_to(pi.handler, oj_hash_set_id)) {
|
226
193
|
pi.hash_set_value = hash_set_value;
|
227
194
|
pi.hash_set_cstr = hash_set_cstr;
|
228
195
|
pi.hash_set_num = hash_set_num;
|
@@ -233,7 +200,7 @@ oj_sc_parse(int argc, VALUE *argv, VALUE self) {
|
|
233
200
|
pi.hash_set_num = noop_hash_set_num;
|
234
201
|
pi.expect_value = 0;
|
235
202
|
}
|
236
|
-
if (
|
203
|
+
if (rb_respond_to(pi.handler, oj_array_append_id)) {
|
237
204
|
pi.array_append_value = array_append_value;
|
238
205
|
pi.array_append_cstr = array_append_cstr;
|
239
206
|
pi.array_append_num = array_append_num;
|
@@ -244,7 +211,7 @@ oj_sc_parse(int argc, VALUE *argv, VALUE self) {
|
|
244
211
|
pi.array_append_num = noop_array_append_num;
|
245
212
|
pi.expect_value = 0;
|
246
213
|
}
|
247
|
-
if (
|
214
|
+
if (rb_respond_to(pi.handler, oj_add_value_id)) {
|
248
215
|
pi.add_cstr = add_cstr;
|
249
216
|
pi.add_num = add_num;
|
250
217
|
pi.add_value = add_value;
|
@@ -255,56 +222,10 @@ oj_sc_parse(int argc, VALUE *argv, VALUE self) {
|
|
255
222
|
pi.add_value = noop_add_value;
|
256
223
|
pi.expect_value = 0;
|
257
224
|
}
|
258
|
-
|
259
|
-
|
225
|
+
|
226
|
+
if (T_STRING == rb_type(input)) {
|
227
|
+
return oj_pi_parse(argc - 1, argv + 1, &pi, 0, 0, 1);
|
260
228
|
} else {
|
261
|
-
|
262
|
-
volatile VALUE s;
|
263
|
-
#if !IS_WINDOWS
|
264
|
-
int fd;
|
265
|
-
#endif
|
266
|
-
if (oj_stringio_class == clas) {
|
267
|
-
s = rb_funcall2(input, oj_string_id, 0, 0);
|
268
|
-
oj_pi_set_input_str(&pi, s);
|
269
|
-
#if !IS_WINDOWS
|
270
|
-
// JRuby gets confused with what is the real fileno.
|
271
|
-
} else if (rb_respond_to(input, oj_fileno_id) &&
|
272
|
-
Qnil != (s = rb_funcall(input, oj_fileno_id, 0)) &&
|
273
|
-
0 != (fd = FIX2INT(s))) {
|
274
|
-
ssize_t cnt;
|
275
|
-
size_t len = lseek(fd, 0, SEEK_END);
|
276
|
-
|
277
|
-
lseek(fd, 0, SEEK_SET);
|
278
|
-
buf = ALLOC_N(char, len + 1);
|
279
|
-
buf[len] = '\0';
|
280
|
-
pi.json = buf;
|
281
|
-
pi.end = buf + len;
|
282
|
-
if (0 >= (cnt = read(fd, (char*)pi.json, len)) || cnt != (ssize_t)len) {
|
283
|
-
if (0 != buf) {
|
284
|
-
xfree(buf);
|
285
|
-
}
|
286
|
-
rb_raise(rb_eIOError, "failed to read from IO Object.");
|
287
|
-
}
|
288
|
-
#endif
|
289
|
-
} else if (rb_respond_to(input, oj_read_id)) {
|
290
|
-
s = rb_funcall2(input, oj_read_id, 0, 0);
|
291
|
-
oj_pi_set_input_str(&pi, s);
|
292
|
-
} else {
|
293
|
-
rb_raise(rb_eArgError, "saj_parse() expected a String or IO Object.");
|
294
|
-
}
|
295
|
-
}
|
296
|
-
wrapped_stack = oj_stack_init(&pi.stack);
|
297
|
-
rb_protect(protect_parse, (VALUE)&pi, &line);
|
298
|
-
DATA_PTR(wrapped_stack) = NULL;
|
299
|
-
if (0 != buf) {
|
300
|
-
xfree(buf);
|
229
|
+
return oj_pi_sparse(argc - 1, argv + 1, &pi, 0);
|
301
230
|
}
|
302
|
-
stack_cleanup(&pi.stack);
|
303
|
-
if (0 != line) {
|
304
|
-
rb_jump_tag(line);
|
305
|
-
}
|
306
|
-
if (err_has(&pi.err)) {
|
307
|
-
oj_err_raise(&pi.err);
|
308
|
-
}
|
309
|
-
return Qnil;
|
310
231
|
}
|