@@ -26,6 +26,15 @@ cdef extern from "jv.h":
2626 int jv_invalid_has_msg(jv)
2727 char * jv_string_value(jv)
2828 jv jv_dump_string(jv, int flags)
29+ int jv_is_integer(jv)
30+ double jv_number_value(jv)
31+ int jv_array_length(jv)
32+ jv jv_array_get(jv, int )
33+ int jv_object_iter(jv)
34+ int jv_object_iter_next(jv, int )
35+ int jv_object_iter_valid(jv, int )
36+ jv jv_object_iter_key(jv, int )
37+ jv jv_object_iter_value(jv, int )
2938
3039 cdef struct jv_parser:
3140 pass
@@ -51,6 +60,52 @@ cdef extern from "jq.h":
5160 void jq_get_error_cb(jq_state * , jq_err_cb * , void ** )
5261
5362
63+ cdef object _jv_to_python(jv value):
64+ """ Unpack a jv value into a Python value"""
65+ cdef jv_kind kind = jv_get_kind(value)
66+ cdef int idx
67+ cdef jv idx_key
68+ cdef jv idx_value
69+ cdef object python_value
70+
71+ if kind == JV_KIND_INVALID:
72+ raise ValueError (" Invalid value" )
73+ elif kind == JV_KIND_NULL:
74+ python_value = None
75+ elif kind == JV_KIND_FALSE:
76+ python_value = False
77+ elif kind == JV_KIND_TRUE:
78+ python_value = True
79+ elif kind == JV_KIND_NUMBER:
80+ if jv_is_integer(value):
81+ python_value = int (jv_number_value(value))
82+ else :
83+ python_value = float (jv_number_value(value))
84+ elif kind == JV_KIND_STRING:
85+ python_value = jv_string_value(value).decode(" utf-8" )
86+ elif kind == JV_KIND_ARRAY:
87+ python_value = []
88+ for idx in range (0 , jv_array_length(jv_copy(value))):
89+ idx_value = jv_array_get(jv_copy(value), idx)
90+ python_value.append(_jv_to_python(idx_value))
91+ elif kind == JV_KIND_OBJECT:
92+ python_value = {}
93+ idx = jv_object_iter(value)
94+ while jv_object_iter_valid(value, idx):
95+ idx_key = jv_object_iter_key(value, idx)
96+ idx_value = jv_object_iter_value(value, idx)
97+ try :
98+ python_value[jv_string_value(idx_key).decode(" utf-8" )] = \
99+ _jv_to_python(idx_value)
100+ finally :
101+ jv_free(idx_key)
102+ idx = jv_object_iter_next(value, idx)
103+ else :
104+ raise ValueError (" Invalid value kind: " + str (kind))
105+ jv_free(value)
106+ return python_value
107+
108+
54109def compile (object program ):
55110 cdef object program_bytes = program.encode(" utf8" )
56111 return _Program(program_bytes)
@@ -239,21 +294,34 @@ cdef class _ResultIterator(object):
239294 return self
240295
241296 def __next__ (self ):
242- return json.loads(self ._next_string())
297+ cdef jv value
298+ self ._next_jv(& value)
299+ return _jv_to_python(value)
243300
244301 cdef unicode _next_string(self ):
245302 cdef int dumpopts = 0
303+ cdef jv value
304+ cdef jv dump
305+
306+ self ._next_jv(& value)
307+ dump = jv_dump_string(value, dumpopts)
308+ try :
309+ string = jv_string_value(dump).decode(" utf8" )
310+ finally :
311+ jv_free(dump)
312+
313+ return string
314+
315+ cdef int _next_jv(self , jv * presult) except 1 :
246316 while True :
247317 if not self ._ready:
248318 self ._ready_next_input()
249319 self ._ready = True
250320
251321 result = jq_next(self ._jq)
252322 if jv_is_valid(result):
253- dumped = jv_dump_string(result, dumpopts)
254- value = jv_string_value(dumped).decode(" utf8" )
255- jv_free(dumped)
256- return value
323+ presult[0 ] = result
324+ return 0
257325 elif jv_invalid_has_msg(jv_copy(result)):
258326 error_message = jv_invalid_get_msg(result)
259327 message = jv_string_value(error_message).decode(" utf8" )
0 commit comments