line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
/***************************************************************************
|
2
|
|
|
|
|
|
|
copyright : (C) 2021 - 2021 by Dongxu Ma
|
3
|
|
|
|
|
|
|
email : dongxu@cpan.org
|
4
|
|
|
|
|
|
|
|
5
|
|
|
|
|
|
|
This library is free software; you can redistribute it and/or modify
|
6
|
|
|
|
|
|
|
it under MIT license. Refer to LICENSE within the package root folder
|
7
|
|
|
|
|
|
|
for full copyright.
|
8
|
|
|
|
|
|
|
|
9
|
|
|
|
|
|
|
***************************************************************************/
|
10
|
|
|
|
|
|
|
|
11
|
|
|
|
|
|
|
#define PERL_NO_GET_CONTEXT
|
12
|
|
|
|
|
|
|
#include "EXTERN.h"
|
13
|
|
|
|
|
|
|
#include "perl.h"
|
14
|
|
|
|
|
|
|
#include "XSUB.h"
|
15
|
|
|
|
|
|
|
|
16
|
|
|
|
|
|
|
#include "ppport.h"
|
17
|
|
|
|
|
|
|
|
18
|
|
|
|
|
|
|
#include
|
19
|
|
|
|
|
|
|
|
20
|
|
|
|
|
|
|
#include "jq.h"
|
21
|
|
|
|
|
|
|
#include "jv.h"
|
22
|
|
|
|
|
|
|
// TODO: get version from Alien::LibJQ cflags
|
23
|
|
|
|
|
|
|
#define JQ_VERSION "1.6"
|
24
|
|
|
|
|
|
|
|
25
|
|
|
|
|
|
|
// utility functions for type marshaling
|
26
|
|
|
|
|
|
|
// they are not XS code
|
27
|
542
|
|
|
|
|
|
jv my_jv_input(pTHX_ void * arg) {
|
28
|
542
|
50
|
|
|
|
|
if (arg == NULL) {
|
29
|
0
|
|
|
|
|
|
return jv_null();
|
30
|
|
|
|
|
|
|
}
|
31
|
|
|
|
|
|
|
SV * const p_sv = arg;
|
32
|
542
|
50
|
|
|
|
|
SvGETMAGIC(p_sv);
|
33
|
542
|
100
|
|
|
|
|
if (SvTYPE(p_sv) == SVt_NULL || (SvTYPE(p_sv) < SVt_PVAV && !SvOK(p_sv))) {
|
|
|
50
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
34
|
|
|
|
|
|
|
// undef or JSON::null()
|
35
|
8
|
|
|
|
|
|
return jv_null();
|
36
|
|
|
|
|
|
|
}
|
37
|
534
|
100
|
|
|
|
|
else if (SvROK(p_sv) && SvTYPE(SvRV(p_sv)) == SVt_IV) {
|
|
|
100
|
|
|
|
|
|
38
|
|
|
|
|
|
|
// boolean: \0 or \1, equilvalent of $JSON::PP::true, $JSON::PP::false
|
39
|
|
|
|
|
|
|
//fprintf(stderr, "got boolean value: %s\n", SvTRUE(SvRV(p_sv)) ? "True" : "False");
|
40
|
2
|
50
|
|
|
|
|
return jv_bool((bool)SvTRUE(SvRV(p_sv)));
|
|
|
50
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
41
|
|
|
|
|
|
|
}
|
42
|
532
|
100
|
|
|
|
|
else if (SvROK(p_sv) && sv_derived_from(p_sv, "JSON::PP::Boolean")) {
|
|
|
100
|
|
|
|
|
|
43
|
|
|
|
|
|
|
// boolean: $JSON::PP::true and $JSON::PP::false
|
44
|
15
|
50
|
|
|
|
|
return jv_bool((bool)SvTRUE(SvRV(p_sv)));
|
|
|
50
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
45
|
|
|
|
|
|
|
}
|
46
|
517
|
100
|
|
|
|
|
else if (SvIOK(p_sv)) {
|
47
|
|
|
|
|
|
|
// integer, use perl's 'native size', see https://perldoc.perl.org/perlguts#What-is-an-%22IV%22?
|
48
|
33
|
50
|
|
|
|
|
return jv_number(SvIV(p_sv));
|
49
|
|
|
|
|
|
|
}
|
50
|
484
|
50
|
|
|
|
|
else if (SvUOK(p_sv)) {
|
51
|
|
|
|
|
|
|
// unsigned int
|
52
|
0
|
0
|
|
|
|
|
return jv_number(SvUV(p_sv));
|
53
|
|
|
|
|
|
|
}
|
54
|
484
|
100
|
|
|
|
|
else if (SvNOK(p_sv)) {
|
55
|
|
|
|
|
|
|
// double
|
56
|
6
|
50
|
|
|
|
|
return jv_number(SvNV(p_sv));
|
57
|
|
|
|
|
|
|
}
|
58
|
478
|
100
|
|
|
|
|
else if (SvPOK(p_sv)) {
|
59
|
|
|
|
|
|
|
// string
|
60
|
|
|
|
|
|
|
STRLEN len;
|
61
|
313
|
50
|
|
|
|
|
char * p_pv = SvUTF8(p_sv) ? SvPVutf8(p_sv, len) : SvPV(p_sv, len);
|
|
|
0
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
62
|
|
|
|
|
|
|
//fprintf(stderr, "my_jv_input() got string: %s\n", p_pv);
|
63
|
313
|
|
|
|
|
|
return jv_string_sized(p_pv, len);
|
64
|
|
|
|
|
|
|
}
|
65
|
165
|
50
|
|
|
|
|
else if (SvROK(p_sv) && SvTYPE(SvRV(p_sv)) == SVt_PVAV) {
|
|
|
100
|
|
|
|
|
|
66
|
|
|
|
|
|
|
// array
|
67
|
76
|
|
|
|
|
|
jv jval = jv_array();
|
68
|
76
|
|
|
|
|
|
AV * p_av = (AV *)SvRV(p_sv);
|
69
|
76
|
|
|
|
|
|
SSize_t len = av_len(p_av);
|
70
|
76
|
100
|
|
|
|
|
if (len < 0) {
|
71
|
1
|
|
|
|
|
|
return jval;
|
72
|
|
|
|
|
|
|
}
|
73
|
|
|
|
|
|
|
SSize_t i;
|
74
|
290
|
100
|
|
|
|
|
for (i = 0; i <= len; i++) {
|
75
|
215
|
|
|
|
|
|
jval = jv_array_append(jval, my_jv_input(aTHX_ *av_fetch(p_av, i, 0)));
|
76
|
|
|
|
|
|
|
}
|
77
|
76
|
|
|
|
|
|
return jval;
|
78
|
|
|
|
|
|
|
}
|
79
|
89
|
50
|
|
|
|
|
else if (SvROK(p_sv) && SvTYPE(SvRV(p_sv)) == SVt_PVHV) {
|
|
|
50
|
|
|
|
|
|
80
|
|
|
|
|
|
|
// hash
|
81
|
89
|
|
|
|
|
|
jv jval = jv_object();
|
82
|
89
|
|
|
|
|
|
HV * p_hv = (HV *)SvRV(p_sv);
|
83
|
89
|
|
|
|
|
|
I32 len = hv_iterinit(p_hv);
|
84
|
|
|
|
|
|
|
I32 i;
|
85
|
152
|
100
|
|
|
|
|
for (i = 0; i < len; i++) {
|
86
|
63
|
|
|
|
|
|
char * key = NULL;
|
87
|
63
|
|
|
|
|
|
I32 klen = 0;
|
88
|
63
|
|
|
|
|
|
SV * val = hv_iternextsv(p_hv, &key, &klen);
|
89
|
63
|
|
|
|
|
|
jval = jv_object_set(jval, jv_string_sized(key, klen), my_jv_input(aTHX_ val));
|
90
|
|
|
|
|
|
|
}
|
91
|
89
|
|
|
|
|
|
return jval;
|
92
|
|
|
|
|
|
|
}
|
93
|
|
|
|
|
|
|
else {
|
94
|
|
|
|
|
|
|
// not supported
|
95
|
0
|
|
|
|
|
|
croak("cannot convert perl object to json format: SvTYPE == %i", SvTYPE(p_sv));
|
96
|
|
|
|
|
|
|
}
|
97
|
|
|
|
|
|
|
// NOREACH
|
98
|
|
|
|
|
|
|
}
|
99
|
|
|
|
|
|
|
|
100
|
135
|
|
|
|
|
|
void * my_jv_output(pTHX_ jv jval) {
|
101
|
135
|
|
|
|
|
|
jv_kind kind = jv_get_kind(jval);
|
102
|
135
|
100
|
|
|
|
|
if (kind == JV_KIND_NULL) {
|
103
|
|
|
|
|
|
|
// null
|
104
|
6
|
|
|
|
|
|
return newSV(0);
|
105
|
|
|
|
|
|
|
}
|
106
|
129
|
100
|
|
|
|
|
else if (kind == JV_KIND_FALSE) {
|
107
|
|
|
|
|
|
|
// boolean: false
|
108
|
|
|
|
|
|
|
// NOTE: get_sv("JSON::PP::false") doesn't work
|
109
|
4
|
|
|
|
|
|
SV * sv_false = newSV(0);
|
110
|
|
|
|
|
|
|
//fprintf(stderr, "set boolean: False\n");
|
111
|
4
|
|
|
|
|
|
return sv_setref_iv(sv_false, "JSON::PP::Boolean", 0);
|
112
|
|
|
|
|
|
|
}
|
113
|
125
|
100
|
|
|
|
|
else if (kind == JV_KIND_TRUE) {
|
114
|
|
|
|
|
|
|
// boolean: true
|
115
|
7
|
|
|
|
|
|
SV * sv_true = newSV(0);
|
116
|
|
|
|
|
|
|
//fprintf(stderr, "set boolean: True\n");
|
117
|
7
|
|
|
|
|
|
return sv_setref_iv(sv_true, "JSON::PP::Boolean", 1);
|
118
|
|
|
|
|
|
|
}
|
119
|
118
|
100
|
|
|
|
|
else if (kind == JV_KIND_NUMBER) {
|
120
|
|
|
|
|
|
|
// number
|
121
|
39
|
|
|
|
|
|
double val = jv_number_value(jval);
|
122
|
39
|
|
|
|
|
|
SV * p_sv = newSV(0);
|
123
|
39
|
100
|
|
|
|
|
if (jv_is_integer(jval)) {
|
124
|
34
|
|
|
|
|
|
sv_setiv(p_sv, val);
|
125
|
|
|
|
|
|
|
}
|
126
|
|
|
|
|
|
|
else {
|
127
|
5
|
|
|
|
|
|
sv_setnv(p_sv, val);
|
128
|
|
|
|
|
|
|
}
|
129
|
|
|
|
|
|
|
return p_sv;
|
130
|
|
|
|
|
|
|
}
|
131
|
79
|
100
|
|
|
|
|
else if (kind == JV_KIND_STRING) {
|
132
|
|
|
|
|
|
|
// string
|
133
|
|
|
|
|
|
|
//fprintf(stderr, "my_jv_output() got string: %s\n", jv_string_value(jval));
|
134
|
|
|
|
|
|
|
//return newSVpvn(jv_string_value(jval), jv_string_length_bytes(jval));
|
135
|
|
|
|
|
|
|
// NOTE: this might introduce unicode bug..
|
136
|
44
|
|
|
|
|
|
return newSVpvf("%s", jv_string_value(jval));
|
137
|
|
|
|
|
|
|
}
|
138
|
35
|
100
|
|
|
|
|
else if (kind == JV_KIND_ARRAY) {
|
139
|
|
|
|
|
|
|
// array
|
140
|
13
|
|
|
|
|
|
AV * p_av = newAV();
|
141
|
13
|
|
|
|
|
|
SSize_t len = (SSize_t)jv_array_length(jv_copy(jval));
|
142
|
13
|
|
|
|
|
|
av_extend(p_av, len - 1);
|
143
|
|
|
|
|
|
|
SSize_t i;
|
144
|
41
|
100
|
|
|
|
|
for (i = 0; i < len; i++) {
|
145
|
28
|
|
|
|
|
|
jv val = jv_array_get(jv_copy(jval), i);
|
146
|
28
|
|
|
|
|
|
av_push(p_av, (SV *)my_jv_output(aTHX_ val));
|
147
|
28
|
|
|
|
|
|
jv_free(val);
|
148
|
|
|
|
|
|
|
}
|
149
|
13
|
|
|
|
|
|
return newRV_noinc((SV *)p_av);
|
150
|
|
|
|
|
|
|
}
|
151
|
22
|
50
|
|
|
|
|
else if (kind == JV_KIND_OBJECT) {
|
152
|
|
|
|
|
|
|
// hash
|
153
|
22
|
|
|
|
|
|
HV * p_hv = newHV();
|
154
|
22
|
|
|
|
|
|
int iter = jv_object_iter(jval);
|
155
|
59
|
100
|
|
|
|
|
while (jv_object_iter_valid(jval, iter)) {
|
156
|
37
|
|
|
|
|
|
jv key = jv_object_iter_key(jval, iter);
|
157
|
37
|
|
|
|
|
|
jv val = jv_object_iter_value(jval, iter);
|
158
|
37
|
50
|
|
|
|
|
if (jv_get_kind(key) != JV_KIND_STRING) {
|
159
|
0
|
|
|
|
|
|
croak("cannot take non-string type as hash key: JV_KIND == %i", jv_get_kind(key));
|
160
|
|
|
|
|
|
|
}
|
161
|
37
|
|
|
|
|
|
const char * k = jv_string_value(key);
|
162
|
37
|
|
|
|
|
|
int klen = jv_string_length_bytes(key);
|
163
|
37
|
|
|
|
|
|
SV * v = (SV *)my_jv_output(aTHX_ val);
|
164
|
37
|
|
|
|
|
|
hv_store(p_hv, k, klen, v, 0);
|
165
|
37
|
|
|
|
|
|
jv_free(key);
|
166
|
37
|
|
|
|
|
|
jv_free(val);
|
167
|
37
|
|
|
|
|
|
iter = jv_object_iter_next(jval, iter);
|
168
|
|
|
|
|
|
|
}
|
169
|
22
|
|
|
|
|
|
return newRV_noinc((SV *)p_hv);
|
170
|
|
|
|
|
|
|
}
|
171
|
|
|
|
|
|
|
else {
|
172
|
0
|
|
|
|
|
|
croak("un-supported jv object type: JV_KIND == %i", kind);
|
173
|
|
|
|
|
|
|
}
|
174
|
|
|
|
|
|
|
// NOREACH
|
175
|
|
|
|
|
|
|
}
|
176
|
|
|
|
|
|
|
|
177
|
2
|
|
|
|
|
|
static void my_error_cb(void * errors, jv jerr) {
|
178
|
|
|
|
|
|
|
dTHX;
|
179
|
|
|
|
|
|
|
// original jerr will be freed by jq engine
|
180
|
2
|
|
|
|
|
|
jerr = jv_copy(jerr);
|
181
|
2
|
|
|
|
|
|
av_push((AV *)errors, newSVpvn(jv_string_value(jerr), jv_string_length_bytes(jerr)));
|
182
|
2
|
|
|
|
|
|
}
|
183
|
|
|
|
|
|
|
|
184
|
0
|
|
|
|
|
|
static void my_debug_cb(void * data, jv input) {
|
185
|
|
|
|
|
|
|
dTHX;
|
186
|
0
|
|
|
|
|
|
int dumpopts = *(int *)data;
|
187
|
0
|
|
|
|
|
|
jv_dumpf(JV_ARRAY(jv_string("DEBUG:"), input), stderr, dumpopts);
|
188
|
0
|
|
|
|
|
|
fprintf(stderr, "\n");
|
189
|
0
|
|
|
|
|
|
}
|
190
|
|
|
|
|
|
|
|
191
|
162
|
|
|
|
|
|
static inline void assert_isa(pTHX_ SV * self) {
|
192
|
162
|
50
|
|
|
|
|
if (!sv_isa(self, "JSON::JQ")) {
|
193
|
0
|
|
|
|
|
|
croak("self is not a JSON::JQ object");
|
194
|
|
|
|
|
|
|
}
|
195
|
162
|
|
|
|
|
|
}
|
196
|
|
|
|
|
|
|
|
197
|
|
|
|
|
|
|
// copied from main.c
|
198
|
0
|
|
|
|
|
|
static const char *skip_shebang(const char *p) {
|
199
|
0
|
0
|
|
|
|
|
if (strncmp(p, "#!", sizeof("#!") - 1) != 0)
|
200
|
|
|
|
|
|
|
return p;
|
201
|
0
|
|
|
|
|
|
const char *n = strchr(p, '\n');
|
202
|
0
|
0
|
|
|
|
|
if (n == NULL || n[1] != '#')
|
|
|
0
|
|
|
|
|
|
203
|
|
|
|
|
|
|
return p;
|
204
|
0
|
|
|
|
|
|
n = strchr(n + 1, '\n');
|
205
|
0
|
0
|
|
|
|
|
if (n == NULL || n[1] == '#' || n[1] == '\0' || n[-1] != '\\' || n[-2] == '\\')
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
206
|
|
|
|
|
|
|
return p;
|
207
|
0
|
|
|
|
|
|
n = strchr(n + 1, '\n');
|
208
|
0
|
0
|
|
|
|
|
if (n == NULL)
|
209
|
|
|
|
|
|
|
return p;
|
210
|
0
|
|
|
|
|
|
return n+1;
|
211
|
|
|
|
|
|
|
}
|
212
|
|
|
|
|
|
|
|
213
|
|
|
|
|
|
|
MODULE = JSON::JQ PACKAGE = JSON::JQ
|
214
|
|
|
|
|
|
|
|
215
|
|
|
|
|
|
|
PROTOTYPES: DISABLE
|
216
|
|
|
|
|
|
|
|
217
|
|
|
|
|
|
|
int
|
218
|
|
|
|
|
|
|
JV_PRINT_INDENT_FLAGS(n)
|
219
|
|
|
|
|
|
|
int n
|
220
|
|
|
|
|
|
|
CODE:
|
221
|
51
|
50
|
|
|
|
|
RETVAL = JV_PRINT_INDENT_FLAGS(n);
|
|
|
50
|
|
|
|
|
|
222
|
|
|
|
|
|
|
OUTPUT:
|
223
|
|
|
|
|
|
|
RETVAL
|
224
|
|
|
|
|
|
|
|
225
|
|
|
|
|
|
|
void
|
226
|
|
|
|
|
|
|
_init(self)
|
227
|
|
|
|
|
|
|
HV * self
|
228
|
|
|
|
|
|
|
INIT:
|
229
|
|
|
|
|
|
|
jq_state * _jq = NULL;
|
230
|
|
|
|
|
|
|
SV * sv_jq;
|
231
|
|
|
|
|
|
|
HV * hv_attr;
|
232
|
|
|
|
|
|
|
char * script;
|
233
|
|
|
|
|
|
|
AV * av_err;
|
234
|
|
|
|
|
|
|
int compiled = 0;
|
235
|
|
|
|
|
|
|
CODE:
|
236
|
51
|
|
|
|
|
|
assert_isa(aTHX_ ST(0));
|
237
|
|
|
|
|
|
|
// step 1. initialize
|
238
|
51
|
|
|
|
|
|
_jq = jq_init();
|
239
|
51
|
50
|
|
|
|
|
if (_jq == NULL) {
|
240
|
0
|
|
|
|
|
|
croak("cannot malloc jq engine");
|
241
|
|
|
|
|
|
|
}
|
242
|
|
|
|
|
|
|
else {
|
243
|
51
|
|
|
|
|
|
sv_jq = newSV(0);
|
244
|
51
|
|
|
|
|
|
sv_setiv(sv_jq, PTR2IV(_jq));
|
245
|
51
|
|
|
|
|
|
SvREADONLY_on(sv_jq);
|
246
|
51
|
|
|
|
|
|
hv_stores(self, "_jq", sv_jq);
|
247
|
|
|
|
|
|
|
}
|
248
|
|
|
|
|
|
|
// step 2. set error and debug callbacks
|
249
|
51
|
|
|
|
|
|
av_err = (AV *)SvRV(*hv_fetchs(self, "_errors", 0));
|
250
|
51
|
|
|
|
|
|
jq_set_error_cb(_jq, my_error_cb, av_err);
|
251
|
51
|
50
|
|
|
|
|
int dumpopts = (int)SvIV(*hv_fetchs(self, "_dumpopts", 0));
|
252
|
51
|
|
|
|
|
|
jq_set_debug_cb(_jq, my_debug_cb, &dumpopts);
|
253
|
|
|
|
|
|
|
// step 3. set initial attributes
|
254
|
51
|
|
|
|
|
|
hv_attr = (HV *)SvRV(*hv_fetchs(self, "_attribute", 0));
|
255
|
51
|
|
|
|
|
|
I32 len = hv_iterinit(hv_attr);
|
256
|
|
|
|
|
|
|
I32 i;
|
257
|
204
|
100
|
|
|
|
|
for (i = 0; i < len; i++) {
|
258
|
153
|
|
|
|
|
|
char * key = NULL;
|
259
|
153
|
|
|
|
|
|
I32 klen = 0;
|
260
|
153
|
|
|
|
|
|
SV * val = hv_iternextsv(hv_attr, &key, &klen);
|
261
|
153
|
|
|
|
|
|
jq_set_attr(_jq, jv_string_sized(key, klen), my_jv_input(aTHX_ val));
|
262
|
|
|
|
|
|
|
}
|
263
|
|
|
|
|
|
|
// set JQ_VERSION
|
264
|
51
|
|
|
|
|
|
jq_set_attr(_jq, jv_string("VERSION_DIR"), jv_string(JQ_VERSION));
|
265
|
|
|
|
|
|
|
// step 4. compile
|
266
|
51
|
|
|
|
|
|
jv args = my_jv_input(aTHX_ *hv_fetchs(self, "variable", 0));
|
267
|
51
|
50
|
|
|
|
|
if (hv_exists(self, "script_file", 11)) {
|
268
|
0
|
0
|
|
|
|
|
jv data = jv_load_file(SvPV_nolen(*hv_fetchs(self, "script_file", 0)), 1);
|
269
|
0
|
0
|
|
|
|
|
if (!jv_is_valid(data)) {
|
270
|
0
|
|
|
|
|
|
data = jv_invalid_get_msg(data);
|
271
|
0
|
|
|
|
|
|
my_error_cb(av_err, data);
|
272
|
0
|
|
|
|
|
|
jv_free(data);
|
273
|
0
|
|
|
|
|
|
XSRETURN_NO;
|
274
|
|
|
|
|
|
|
}
|
275
|
0
|
|
|
|
|
|
compiled = jq_compile_args(_jq, skip_shebang(jv_string_value(data)), args);
|
276
|
0
|
|
|
|
|
|
jv_free(data);
|
277
|
|
|
|
|
|
|
}
|
278
|
|
|
|
|
|
|
else {
|
279
|
51
|
50
|
|
|
|
|
script = SvPV_nolen(*hv_fetchs(self, "script", 0));
|
280
|
51
|
|
|
|
|
|
compiled = jq_compile_args(_jq, script, args);
|
281
|
|
|
|
|
|
|
|
282
|
|
|
|
|
|
|
}
|
283
|
51
|
100
|
|
|
|
|
if (compiled) {
|
284
|
50
|
50
|
|
|
|
|
if (SvTRUE(get_sv("JSON::JQ::DUMP_DISASM", 0))) {
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
285
|
0
|
|
|
|
|
|
jq_dump_disassembly(_jq, 0);
|
286
|
|
|
|
|
|
|
printf("\n");
|
287
|
|
|
|
|
|
|
}
|
288
|
50
|
|
|
|
|
|
XSRETURN_YES;
|
289
|
|
|
|
|
|
|
}
|
290
|
|
|
|
|
|
|
else {
|
291
|
|
|
|
|
|
|
// args freed by jq engine
|
292
|
|
|
|
|
|
|
//jv_free(args);
|
293
|
|
|
|
|
|
|
// jq_teardown(&_jq); // no need to call destructor here, DESTROY will do
|
294
|
1
|
|
|
|
|
|
XSRETURN_NO;
|
295
|
|
|
|
|
|
|
}
|
296
|
|
|
|
|
|
|
|
297
|
|
|
|
|
|
|
int
|
298
|
|
|
|
|
|
|
_process(self, sv_input, av_output)
|
299
|
|
|
|
|
|
|
HV * self
|
300
|
|
|
|
|
|
|
SV * sv_input
|
301
|
|
|
|
|
|
|
AV * av_output
|
302
|
|
|
|
|
|
|
INIT:
|
303
|
|
|
|
|
|
|
jq_state * _jq = NULL;
|
304
|
|
|
|
|
|
|
SV * sv_jq;
|
305
|
|
|
|
|
|
|
AV * av_err;
|
306
|
|
|
|
|
|
|
CODE:
|
307
|
60
|
|
|
|
|
|
assert_isa(aTHX_ ST(0));
|
308
|
60
|
|
|
|
|
|
sv_jq = *hv_fetchs(self, "_jq", 0);
|
309
|
60
|
50
|
|
|
|
|
_jq = INT2PTR(jq_state *, SvIV(sv_jq));
|
310
|
60
|
|
|
|
|
|
jv jv_input = my_jv_input(aTHX_ sv_input);
|
311
|
60
|
50
|
|
|
|
|
int jq_flags = (int)SvIV(*hv_fetchs(self, "jq_flags", 0));
|
312
|
|
|
|
|
|
|
// logic from process() in main.c
|
313
|
60
|
|
|
|
|
|
jq_start(_jq, jv_input, jq_flags);
|
314
|
|
|
|
|
|
|
jv result;
|
315
|
|
|
|
|
|
|
// clear previous call errors
|
316
|
60
|
|
|
|
|
|
av_err = (AV *)SvRV(*hv_fetchs(self, "_errors", 0));
|
317
|
60
|
|
|
|
|
|
av_clear(av_err);
|
318
|
|
|
|
|
|
|
int ret = 14;
|
319
|
320
|
100
|
|
|
|
|
while (jv_is_valid(result = jq_next(_jq))) {
|
320
|
70
|
|
|
|
|
|
av_push(av_output, (SV *)my_jv_output(aTHX_ result));
|
321
|
130
|
50
|
|
|
|
|
if (jv_get_kind(result) == JV_KIND_FALSE || jv_get_kind(result) == JV_KIND_NULL) {
|
|
|
100
|
|
|
|
|
|
322
|
|
|
|
|
|
|
ret = 11;
|
323
|
|
|
|
|
|
|
}
|
324
|
|
|
|
|
|
|
else {
|
325
|
|
|
|
|
|
|
ret = 0;
|
326
|
|
|
|
|
|
|
}
|
327
|
|
|
|
|
|
|
//jv_free(result);
|
328
|
|
|
|
|
|
|
}
|
329
|
60
|
50
|
|
|
|
|
if (jq_halted(_jq)) {
|
330
|
|
|
|
|
|
|
// jq program invoked `halt` or `halt_error`
|
331
|
0
|
|
|
|
|
|
jv exit_code = jq_get_exit_code(_jq);
|
332
|
0
|
0
|
|
|
|
|
if (!jv_get_kind(exit_code)) {
|
333
|
|
|
|
|
|
|
ret = 0;
|
334
|
|
|
|
|
|
|
}
|
335
|
0
|
0
|
|
|
|
|
else if (jv_get_kind(exit_code) == JV_KIND_NUMBER) {
|
336
|
0
|
|
|
|
|
|
ret = jv_number_value(exit_code);
|
337
|
|
|
|
|
|
|
}
|
338
|
|
|
|
|
|
|
else {
|
339
|
|
|
|
|
|
|
ret = 5;
|
340
|
|
|
|
|
|
|
}
|
341
|
0
|
|
|
|
|
|
jv_free(exit_code);
|
342
|
0
|
|
|
|
|
|
jv error_message = jq_get_error_message(_jq);
|
343
|
0
|
0
|
|
|
|
|
if (jv_get_kind(error_message) == JV_KIND_STRING) {
|
344
|
0
|
|
|
|
|
|
my_error_cb(av_err, error_message);
|
345
|
|
|
|
|
|
|
}
|
346
|
0
|
0
|
|
|
|
|
else if (jv_get_kind(error_message) == JV_KIND_NULL) {
|
347
|
|
|
|
|
|
|
// halt with no output
|
348
|
|
|
|
|
|
|
}
|
349
|
0
|
0
|
|
|
|
|
else if (jv_is_valid(error_message)) {
|
350
|
0
|
|
|
|
|
|
error_message = jv_dump_string(jv_copy(error_message), 0);
|
351
|
0
|
|
|
|
|
|
my_error_cb(av_err, error_message);
|
352
|
|
|
|
|
|
|
}
|
353
|
|
|
|
|
|
|
else {
|
354
|
|
|
|
|
|
|
// no message; use --debug-trace to see a message
|
355
|
|
|
|
|
|
|
}
|
356
|
0
|
|
|
|
|
|
jv_free(error_message);
|
357
|
|
|
|
|
|
|
}
|
358
|
60
|
50
|
|
|
|
|
else if (jv_invalid_has_msg(jv_copy(result))) {
|
359
|
|
|
|
|
|
|
// uncaught jq exception
|
360
|
0
|
|
|
|
|
|
jv msg = jv_invalid_get_msg(jv_copy(result));
|
361
|
|
|
|
|
|
|
//jv input_pos = jq_util_input_get_position(_jq);
|
362
|
0
|
0
|
|
|
|
|
if (jv_get_kind(msg) == JV_KIND_STRING) {
|
363
|
|
|
|
|
|
|
//av_push(av_err, newSVpvf("jq: error (at %s): %s", jv_string_value(input_pos), jv_string_value(msg)));
|
364
|
0
|
|
|
|
|
|
av_push(av_err, newSVpvf("jq: error: %s", jv_string_value(msg)));
|
365
|
|
|
|
|
|
|
}
|
366
|
|
|
|
|
|
|
else {
|
367
|
0
|
|
|
|
|
|
msg = jv_dump_string(msg, 0);
|
368
|
|
|
|
|
|
|
//av_push(av_err, newSVpvf("jq: error (at %s) (not a string): %s", jv_string_value(input_pos), jv_string_value(msg)));
|
369
|
0
|
|
|
|
|
|
av_push(av_err, newSVpvf("jq: error (not a string): %s", jv_string_value(msg)));
|
370
|
|
|
|
|
|
|
}
|
371
|
|
|
|
|
|
|
ret = 5;
|
372
|
|
|
|
|
|
|
//jv_free(input_pos);
|
373
|
0
|
|
|
|
|
|
jv_free(msg);
|
374
|
|
|
|
|
|
|
}
|
375
|
60
|
|
|
|
|
|
jv_free(result);
|
376
|
|
|
|
|
|
|
RETVAL = ret;
|
377
|
|
|
|
|
|
|
OUTPUT:
|
378
|
|
|
|
|
|
|
RETVAL
|
379
|
|
|
|
|
|
|
|
380
|
|
|
|
|
|
|
void
|
381
|
|
|
|
|
|
|
DESTROY(self)
|
382
|
|
|
|
|
|
|
HV * self
|
383
|
|
|
|
|
|
|
INIT:
|
384
|
51
|
|
|
|
|
|
jq_state * _jq = NULL;
|
385
|
|
|
|
|
|
|
SV * sv_jq;
|
386
|
|
|
|
|
|
|
CODE:
|
387
|
51
|
|
|
|
|
|
assert_isa(aTHX_ ST(0));
|
388
|
51
|
|
|
|
|
|
sv_jq = *hv_fetchs(self, "_jq", 0);
|
389
|
51
|
50
|
|
|
|
|
_jq = INT2PTR(jq_state *, SvIV(sv_jq));
|
390
|
51
|
50
|
|
|
|
|
if (_jq != NULL) {
|
391
|
51
|
50
|
|
|
|
|
if (SvTRUE(get_sv("JSON::JQ::DEBUG", 0))) {
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
392
|
0
|
|
|
|
|
|
fprintf(stderr, "destroying jq object: %p\n", _jq);
|
393
|
|
|
|
|
|
|
}
|
394
|
51
|
|
|
|
|
|
jq_teardown(&_jq);
|
395
|
|
|
|
|
|
|
}
|