ruby-jq 0.1.1 → 0.1.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 +8 -8
- data/ext/jq_core.c +32 -22
- data/ext/jq_core.h +1 -0
- data/lib/jq/parser.rb +10 -4
- data/lib/jq/version.rb +1 -1
- data/spec/jq_spec.rb +116 -0
- data/spec/spec_helper.rb +1 -0
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
3
|
metadata.gz: !binary |-
|
4
|
-
|
4
|
+
OTUzMDNjM2E5MDlmYzBlZWNkZjYwOTJiN2M3MzcyZmZlYzNhZDQxZA==
|
5
5
|
data.tar.gz: !binary |-
|
6
|
-
|
6
|
+
MDUyMzQ0MjBiMjcxZjU0MWRiYWExOTA2ODljN2IwZTY1MTUyZTM2ZQ==
|
7
7
|
SHA512:
|
8
8
|
metadata.gz: !binary |-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
NGVlNTM5MGRkZDg2ODI1ZjljY2JlMTI2OWQwZjE2ODczMmE4NzVhNDViOTA5
|
10
|
+
MDBlMDcxMjA4NWI2MzRlYWUwYmUwZDE2OGQ5MTk5MjgyY2M5NjU2NzlhMWU2
|
11
|
+
YzZhMzdhNWM2NGU3MTAxZTZlMjEyMzIyZTJjNmQxYTlkOTAzNTM=
|
12
12
|
data.tar.gz: !binary |-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
ZTRhMWFjZjQxZGFjNzEzZDBmY2FmMTNiYjAzNzQ1YjQwYjMxY2RiZjU1Y2Yz
|
14
|
+
YjI2YTMwMzNlMDcyNjliZmVjYzg2OGQwNDFkZTg2OWRiNWE4NjI2MDAwODcz
|
15
|
+
N2QzZGYzZTYwNjNiOTJhNTAxM2Q3MzMxNTg4NWRhMzdlODM0OWI=
|
data/ext/jq_core.c
CHANGED
@@ -10,6 +10,7 @@ static VALUE rb_jq_alloc(VALUE klass) {
|
|
10
10
|
struct jq_container *p;
|
11
11
|
p = ALLOC(struct jq_container);
|
12
12
|
p->jq = NULL;
|
13
|
+
p->parser = NULL;
|
13
14
|
p->closed = 1;
|
14
15
|
return Data_Wrap_Struct(klass, 0, rb_jq_free, p);
|
15
16
|
}
|
@@ -35,6 +36,7 @@ static VALUE rb_jq_initialize(VALUE self, VALUE program) {
|
|
35
36
|
}
|
36
37
|
|
37
38
|
p->jq = jq;
|
39
|
+
p->parser = NULL;
|
38
40
|
p->closed = 0;
|
39
41
|
|
40
42
|
return Qnil;
|
@@ -46,6 +48,8 @@ static VALUE rb_jq_close(VALUE self) {
|
|
46
48
|
|
47
49
|
if (!p->closed) {
|
48
50
|
jq_teardown(&p->jq);
|
51
|
+
p->jq = NULL;
|
52
|
+
p->parser = NULL;
|
49
53
|
p->closed = 1;
|
50
54
|
}
|
51
55
|
|
@@ -65,40 +69,27 @@ static void jq_process(jq_state *jq, jv value, VALUE (*proc)(), int *status) {
|
|
65
69
|
jv_free(result);
|
66
70
|
}
|
67
71
|
|
68
|
-
static void jq_parse(jq_state *jq,
|
69
|
-
struct jv_parser* parser = jv_parser_new();
|
72
|
+
static void jq_parse(jq_state *jq, struct jv_parser *parser, VALUE (*proc)(), int *status, VALUE *errmsg) {
|
70
73
|
jv value;
|
71
|
-
int status = 0, error = 0;
|
72
|
-
VALUE errmsg;
|
73
74
|
|
74
|
-
|
75
|
-
|
76
|
-
while (jv_is_valid((value = jv_parser_next(parser))) && status == 0) {
|
77
|
-
jq_process(jq, value, proc, &status);
|
75
|
+
while (jv_is_valid((value = jv_parser_next(parser))) && *status == 0) {
|
76
|
+
jq_process(jq, value, proc, status);
|
78
77
|
}
|
79
78
|
|
80
79
|
if (jv_invalid_has_msg(jv_copy(value))) {
|
81
80
|
jv msg = jv_invalid_get_msg(value);
|
82
|
-
|
83
|
-
errmsg = rb_str_new2(jv_string_value(msg));
|
81
|
+
*errmsg = rb_str_new2(jv_string_value(msg));
|
84
82
|
jv_free(msg);
|
85
83
|
} else {
|
86
84
|
jv_free(value);
|
87
85
|
}
|
88
|
-
|
89
|
-
jv_parser_free(parser);
|
90
|
-
|
91
|
-
if (status != 0) {
|
92
|
-
rb_jump_tag(status);
|
93
|
-
}
|
94
|
-
|
95
|
-
if (error) {
|
96
|
-
rb_raise(rb_eJQ_Error, "%s", RSTRING_PTR(errmsg));
|
97
|
-
}
|
98
86
|
}
|
99
87
|
|
100
|
-
static VALUE rb_jq_update(VALUE self, VALUE buf, VALUE
|
88
|
+
static VALUE rb_jq_update(VALUE self, VALUE buf, VALUE v_is_partial) {
|
101
89
|
struct jq_container *p;
|
90
|
+
int is_partial = v_is_partial ? 1 : 0;
|
91
|
+
int status = 0;
|
92
|
+
VALUE errmsg = Qnil;
|
102
93
|
|
103
94
|
if (!rb_block_given_p()) {
|
104
95
|
rb_raise(rb_eArgError, "no block given");
|
@@ -106,7 +97,26 @@ static VALUE rb_jq_update(VALUE self, VALUE buf, VALUE is_partial) {
|
|
106
97
|
|
107
98
|
Data_Get_Struct(self, struct jq_container, p);
|
108
99
|
Check_Type(buf, T_STRING);
|
109
|
-
|
100
|
+
|
101
|
+
if (!p->parser) {
|
102
|
+
p->parser = jv_parser_new();
|
103
|
+
}
|
104
|
+
|
105
|
+
jv_parser_set_buf(p->parser, RSTRING_PTR(buf), RSTRING_LEN(buf), is_partial);
|
106
|
+
jq_parse(p->jq, p->parser, rb_yield, &status, &errmsg);
|
107
|
+
|
108
|
+
if (!is_partial) {
|
109
|
+
jv_parser_free(p->parser);
|
110
|
+
p->parser = NULL;
|
111
|
+
}
|
112
|
+
|
113
|
+
if (status != 0) {
|
114
|
+
rb_jump_tag(status);
|
115
|
+
}
|
116
|
+
|
117
|
+
if (!NIL_P(errmsg)) {
|
118
|
+
rb_raise(rb_eJQ_Error, "%s", RSTRING_PTR(errmsg));
|
119
|
+
}
|
110
120
|
|
111
121
|
return Qnil;
|
112
122
|
}
|
data/ext/jq_core.h
CHANGED
data/lib/jq/parser.rb
CHANGED
@@ -1,18 +1,20 @@
|
|
1
1
|
require 'jq_core'
|
2
2
|
require 'json'
|
3
|
+
require 'tempfile'
|
4
|
+
require 'stringio'
|
3
5
|
|
4
6
|
class JQ::Parser
|
5
7
|
BUFSIZ = 4096
|
6
8
|
|
7
9
|
def initialize(src, options = {})
|
8
|
-
@src =
|
10
|
+
@src = kind_of_io?(src) ? src : src.to_s
|
9
11
|
@options = {
|
10
12
|
:parse_json => true,
|
11
13
|
}.merge(options)
|
12
14
|
end
|
13
15
|
|
14
16
|
def search(program, &block)
|
15
|
-
@src.rewind if @src
|
17
|
+
@src.rewind if kind_of_io?(@src)
|
16
18
|
retval = nil
|
17
19
|
|
18
20
|
if block
|
@@ -30,9 +32,9 @@ class JQ::Parser
|
|
30
32
|
end
|
31
33
|
|
32
34
|
jq(program) do |jq_core|
|
33
|
-
if @src
|
35
|
+
if kind_of_io?(@src)
|
34
36
|
while buf = @src.read(BUFSIZ)
|
35
|
-
jq_core.update(buf,
|
37
|
+
jq_core.update(buf, !@src.eof?, &block)
|
36
38
|
end
|
37
39
|
else
|
38
40
|
jq_core.update(@src, false, &block)
|
@@ -61,4 +63,8 @@ class JQ::Parser
|
|
61
63
|
str
|
62
64
|
end
|
63
65
|
end
|
66
|
+
|
67
|
+
def kind_of_io?(obj)
|
68
|
+
[IO, Tempfile, StringIO].any? {|c| obj.kind_of?(c) }
|
69
|
+
end
|
64
70
|
end
|
data/lib/jq/version.rb
CHANGED
data/spec/jq_spec.rb
CHANGED
@@ -92,6 +92,114 @@ describe JQ do
|
|
92
92
|
end
|
93
93
|
end
|
94
94
|
|
95
|
+
it 'read from file' do
|
96
|
+
Tempfile.open("ruby-jq.spec.#{$$}") do |src|
|
97
|
+
src.puts(<<-EOS)
|
98
|
+
{
|
99
|
+
"glossary": {
|
100
|
+
"title": "example glossary",
|
101
|
+
"GlossDiv": {
|
102
|
+
"title": "S",
|
103
|
+
"GlossList": {
|
104
|
+
"GlossEntry": {
|
105
|
+
"ID": "SGML",
|
106
|
+
"SortAs": "SGML",
|
107
|
+
"GlossTerm": "Standard Generalized Markup Language",
|
108
|
+
"Acronym": "SGML",
|
109
|
+
"Abbrev": "ISO 8879:1986",
|
110
|
+
"GlossDef": {
|
111
|
+
"para": "A meta-markup language, used to create markup languages such as DocBook.",
|
112
|
+
"GlossSeeAlso": ["GML", "XML"]
|
113
|
+
},
|
114
|
+
"GlossSee": "markup"
|
115
|
+
}
|
116
|
+
}
|
117
|
+
}
|
118
|
+
}
|
119
|
+
}
|
120
|
+
EOS
|
121
|
+
|
122
|
+
expected = {
|
123
|
+
"glossary"=>
|
124
|
+
{"GlossDiv"=>
|
125
|
+
{"GlossList"=>
|
126
|
+
{"GlossEntry"=>
|
127
|
+
{"GlossSee"=>"markup",
|
128
|
+
"GlossDef"=>
|
129
|
+
{"GlossSeeAlso"=>["GML", "XML"],
|
130
|
+
"para"=>
|
131
|
+
"A meta-markup language, used to create markup languages such as DocBook."},
|
132
|
+
"Abbrev"=>"ISO 8879:1986",
|
133
|
+
"Acronym"=>"SGML",
|
134
|
+
"GlossTerm"=>"Standard Generalized Markup Language",
|
135
|
+
"SortAs"=>"SGML",
|
136
|
+
"ID"=>"SGML"}},
|
137
|
+
"title"=>"S"},
|
138
|
+
"title"=>"example glossary"}}
|
139
|
+
|
140
|
+
expect(JQ(src).search('.')).to eq([expected])
|
141
|
+
|
142
|
+
JQ(src).search('.') do |value|
|
143
|
+
expect(value).to eq(expected)
|
144
|
+
end
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
it 'read from file (> 4096)' do
|
149
|
+
Tempfile.open("ruby-jq.spec.#{$$}") do |src|
|
150
|
+
src.puts('[' + (1..10).map { (<<-EOS) }.join(',') + ']')
|
151
|
+
{
|
152
|
+
"glossary": {
|
153
|
+
"title": "example glossary",
|
154
|
+
"GlossDiv": {
|
155
|
+
"title": "S",
|
156
|
+
"GlossList": {
|
157
|
+
"GlossEntry": {
|
158
|
+
"ID": "SGML",
|
159
|
+
"SortAs": "SGML",
|
160
|
+
"GlossTerm": "Standard Generalized Markup Language",
|
161
|
+
"Acronym": "SGML",
|
162
|
+
"Abbrev": "ISO 8879:1986",
|
163
|
+
"GlossDef": {
|
164
|
+
"para": "A meta-markup language, used to create markup languages such as DocBook.",
|
165
|
+
"GlossSeeAlso": ["GML", "XML"]
|
166
|
+
},
|
167
|
+
"GlossSee": "markup"
|
168
|
+
}
|
169
|
+
}
|
170
|
+
}
|
171
|
+
}
|
172
|
+
}
|
173
|
+
EOS
|
174
|
+
|
175
|
+
expected = (1..10).map do
|
176
|
+
{
|
177
|
+
"glossary"=>
|
178
|
+
{"GlossDiv"=>
|
179
|
+
{"GlossList"=>
|
180
|
+
{"GlossEntry"=>
|
181
|
+
{"GlossSee"=>"markup",
|
182
|
+
"GlossDef"=>
|
183
|
+
{"GlossSeeAlso"=>["GML", "XML"],
|
184
|
+
"para"=>
|
185
|
+
"A meta-markup language, used to create markup languages such as DocBook."},
|
186
|
+
"Abbrev"=>"ISO 8879:1986",
|
187
|
+
"Acronym"=>"SGML",
|
188
|
+
"GlossTerm"=>"Standard Generalized Markup Language",
|
189
|
+
"SortAs"=>"SGML",
|
190
|
+
"ID"=>"SGML"}},
|
191
|
+
"title"=>"S"},
|
192
|
+
"title"=>"example glossary"}}
|
193
|
+
end
|
194
|
+
|
195
|
+
expect(JQ(src).search('.')).to eq([expected])
|
196
|
+
|
197
|
+
JQ(src).search('.') do |value|
|
198
|
+
expect(value).to eq(expected)
|
199
|
+
end
|
200
|
+
end
|
201
|
+
end
|
202
|
+
|
95
203
|
it 'parse_json => false' do
|
96
204
|
src = <<-EOS
|
97
205
|
{
|
@@ -150,4 +258,12 @@ describe JQ do
|
|
150
258
|
JQ('{}').search('...')
|
151
259
|
}.to raise_error(JQ::Error)
|
152
260
|
end
|
261
|
+
|
262
|
+
it 'runtime error' do
|
263
|
+
expect {
|
264
|
+
JQ('{}').search('.') do |value|
|
265
|
+
raise 'runtime error'
|
266
|
+
end
|
267
|
+
}.to raise_error(RuntimeError)
|
268
|
+
end
|
153
269
|
end
|
data/spec/spec_helper.rb
CHANGED