1
0
mirror of https://github.com/stedolan/jq.git synced 2024-05-11 05:55:39 +00:00

Make C-coded built-ins take jq_state * argument

This commit is contained in:
Nicolas Williams
2014-07-07 22:49:46 -05:00
parent a68958e5dc
commit d8672e1b2a
2 changed files with 67 additions and 59 deletions

106
builtin.c

@ -30,7 +30,7 @@ static jv type_error2(jv bad1, jv bad2, const char* msg) {
return err;
}
static jv f_plus(jv input, jv a, jv b) {
static jv f_plus(jq_state *jq, jv input, jv a, jv b) {
jv_free(input);
if (jv_get_kind(a) == JV_KIND_NULL) {
jv_free(a);
@ -53,7 +53,7 @@ static jv f_plus(jv input, jv a, jv b) {
}
#define LIBM_DD(name) \
static jv f_ ## name(jv input) { \
static jv f_ ## name(jq_state *jq, jv input) { \
if (jv_get_kind(input) != JV_KIND_NUMBER) { \
return type_error(input, "number required"); \
} \
@ -64,7 +64,7 @@ static jv f_ ## name(jv input) { \
#include "libm.h"
#undef LIBM_DD
static jv f_negate(jv input) {
static jv f_negate(jq_state *jq, jv input) {
if (jv_get_kind(input) != JV_KIND_NUMBER) {
return type_error(input, "cannot be negated");
}
@ -73,7 +73,7 @@ static jv f_negate(jv input) {
return ret;
}
static jv f_startswith(jv a, jv b) {
static jv f_startswith(jq_state *jq, jv a, jv b) {
int alen = jv_string_length_bytes(jv_copy(a));
int blen = jv_string_length_bytes(jv_copy(b));
jv ret;
@ -87,7 +87,7 @@ static jv f_startswith(jv a, jv b) {
return ret;
}
static jv f_endswith(jv a, jv b) {
static jv f_endswith(jq_state *jq, jv a, jv b) {
const char *astr = jv_string_value(a);
const char *bstr = jv_string_value(b);
size_t alen = jv_string_length_bytes(jv_copy(a));
@ -104,8 +104,8 @@ static jv f_endswith(jv a, jv b) {
return ret;
}
static jv f_ltrimstr(jv input, jv left) {
if (jv_get_kind(f_startswith(jv_copy(input), jv_copy(left))) != JV_KIND_TRUE) {
static jv f_ltrimstr(jq_state *jq, jv input, jv left) {
if (jv_get_kind(f_startswith(jq, jv_copy(input), jv_copy(left))) != JV_KIND_TRUE) {
jv_free(left);
return input;
}
@ -120,8 +120,8 @@ static jv f_ltrimstr(jv input, jv left) {
return res;
}
static jv f_rtrimstr(jv input, jv right) {
if (jv_get_kind(f_endswith(jv_copy(input), jv_copy(right))) == JV_KIND_TRUE) {
static jv f_rtrimstr(jq_state *jq, jv input, jv right) {
if (jv_get_kind(f_endswith(jq, jv_copy(input), jv_copy(right))) == JV_KIND_TRUE) {
jv res = jv_string_sized(jv_string_value(input),
jv_string_length_bytes(jv_copy(input)) - jv_string_length_bytes(right));
jv_free(input);
@ -131,7 +131,7 @@ static jv f_rtrimstr(jv input, jv right) {
return input;
}
static jv f_minus(jv input, jv a, jv b) {
static jv f_minus(jq_state *jq, jv input, jv a, jv b) {
jv_free(input);
if (jv_get_kind(a) == JV_KIND_NUMBER && jv_get_kind(b) == JV_KIND_NUMBER) {
return jv_number(jv_number_value(a) - jv_number_value(b));
@ -157,7 +157,7 @@ static jv f_minus(jv input, jv a, jv b) {
}
}
static jv f_multiply(jv input, jv a, jv b) {
static jv f_multiply(jq_state *jq, jv input, jv a, jv b) {
jv_kind ak = jv_get_kind(a);
jv_kind bk = jv_get_kind(b);
jv_free(input);
@ -191,7 +191,7 @@ static jv f_multiply(jv input, jv a, jv b) {
}
}
static jv f_divide(jv input, jv a, jv b) {
static jv f_divide(jq_state *jq, jv input, jv a, jv b) {
jv_free(input);
if (jv_get_kind(a) == JV_KIND_NUMBER && jv_get_kind(b) == JV_KIND_NUMBER) {
return jv_number(jv_number_value(a) / jv_number_value(b));
@ -202,7 +202,7 @@ static jv f_divide(jv input, jv a, jv b) {
}
}
static jv f_mod(jv input, jv a, jv b) {
static jv f_mod(jq_state *jq, jv input, jv a, jv b) {
jv_free(input);
if (jv_get_kind(a) == JV_KIND_NUMBER && jv_get_kind(b) == JV_KIND_NUMBER) {
return jv_number((intmax_t)jv_number_value(a) % (intmax_t)jv_number_value(b));
@ -211,12 +211,12 @@ static jv f_mod(jv input, jv a, jv b) {
}
}
static jv f_equal(jv input, jv a, jv b) {
static jv f_equal(jq_state *jq, jv input, jv a, jv b) {
jv_free(input);
return jv_bool(jv_equal(a, b));
}
static jv f_notequal(jv input, jv a, jv b) {
static jv f_notequal(jq_state *jq, jv input, jv a, jv b) {
jv_free(input);
return jv_bool(!jv_equal(a, b));
}
@ -237,23 +237,23 @@ static jv order_cmp(jv input, jv a, jv b, enum cmp_op op) {
(op == CMP_OP_GREATER && r > 0));
}
static jv f_less(jv input, jv a, jv b) {
static jv f_less(jq_state *jq, jv input, jv a, jv b) {
return order_cmp(input, a, b, CMP_OP_LESS);
}
static jv f_greater(jv input, jv a, jv b) {
static jv f_greater(jq_state *jq, jv input, jv a, jv b) {
return order_cmp(input, a, b, CMP_OP_GREATER);
}
static jv f_lesseq(jv input, jv a, jv b) {
static jv f_lesseq(jq_state *jq, jv input, jv a, jv b) {
return order_cmp(input, a, b, CMP_OP_LESSEQ);
}
static jv f_greatereq(jv input, jv a, jv b) {
static jv f_greatereq(jq_state *jq, jv input, jv a, jv b) {
return order_cmp(input, a, b, CMP_OP_GREATEREQ);
}
static jv f_contains(jv a, jv b) {
static jv f_contains(jq_state *jq, jv a, jv b) {
if (jv_get_kind(a) == jv_get_kind(b)) {
return jv_bool(jv_contains(a, b));
} else {
@ -261,11 +261,11 @@ static jv f_contains(jv a, jv b) {
}
}
static jv f_dump(jv input) {
static jv f_dump(jq_state *jq, jv input) {
return jv_dump_string(input, 0);
}
static jv f_json_parse(jv input) {
static jv f_json_parse(jq_state *jq, jv input) {
if (jv_get_kind(input) != JV_KIND_STRING)
return type_error(input, "only strings can be parsed");
jv res = jv_parse_sized(jv_string_value(input),
@ -274,7 +274,7 @@ static jv f_json_parse(jv input) {
return res;
}
static jv f_tonumber(jv input) {
static jv f_tonumber(jq_state *jq, jv input) {
if (jv_get_kind(input) == JV_KIND_NUMBER) {
return input;
}
@ -288,7 +288,7 @@ static jv f_tonumber(jv input) {
return type_error(input, "cannot be parsed as a number");
}
static jv f_length(jv input) {
static jv f_length(jq_state *jq, jv input) {
if (jv_get_kind(input) == JV_KIND_ARRAY) {
return jv_number(jv_array_length(input));
} else if (jv_get_kind(input) == JV_KIND_OBJECT) {
@ -305,7 +305,7 @@ static jv f_length(jv input) {
}
}
static jv f_tostring(jv input) {
static jv f_tostring(jq_state *jq, jv input) {
if (jv_get_kind(input) == JV_KIND_STRING) {
return input;
} else {
@ -345,7 +345,7 @@ static jv escape_string(jv input, const char* escapings) {
}
static jv f_format(jv input, jv fmt) {
static jv f_format(jq_state *jq, jv input, jv fmt) {
if (jv_get_kind(fmt) != JV_KIND_STRING) {
jv_free(input);
return type_error(fmt, "is not a valid format");
@ -356,7 +356,7 @@ static jv f_format(jv input, jv fmt) {
return jv_dump_string(input, 0);
} else if (!strcmp(fmt_s, "text")) {
jv_free(fmt);
return f_tostring(input);
return f_tostring(jq, input);
} else if (!strcmp(fmt_s, "csv")) {
jv_free(fmt);
if (jv_get_kind(input) != JV_KIND_ARRAY)
@ -397,10 +397,10 @@ static jv f_format(jv input, jv fmt) {
return line;
} else if (!strcmp(fmt_s, "html")) {
jv_free(fmt);
return escape_string(f_tostring(input), "&&amp;\0<&lt;\0>&gt;\0'&apos;\0\"&quot;\0");
return escape_string(f_tostring(jq, input), "&&amp;\0<&lt;\0>&gt;\0'&apos;\0\"&quot;\0");
} else if (!strcmp(fmt_s, "uri")) {
jv_free(fmt);
input = f_tostring(input);
input = f_tostring(jq, input);
int unreserved[128] = {0};
const char* p = CHARS_ALPHANUM "-_.!~*'()";
@ -451,7 +451,7 @@ static jv f_format(jv input, jv fmt) {
return line;
} else if (!strcmp(fmt_s, "base64")) {
jv_free(fmt);
input = f_tostring(input);
input = f_tostring(jq, input);
jv line = jv_string("");
const char b64[64 + 1] = CHARS_ALPHANUM "+/";
const unsigned char* data = (const unsigned char*)jv_string_value(input);
@ -479,7 +479,7 @@ static jv f_format(jv input, jv fmt) {
}
}
static jv f_keys(jv input) {
static jv f_keys(jq_state *jq, jv input) {
if (jv_get_kind(input) == JV_KIND_OBJECT || jv_get_kind(input) == JV_KIND_ARRAY) {
return jv_keys(input);
} else {
@ -487,7 +487,7 @@ static jv f_keys(jv input) {
}
}
static jv f_sort(jv input){
static jv f_sort(jq_state *jq, jv input){
if (jv_get_kind(input) == JV_KIND_ARRAY) {
return jv_sort(input, jv_copy(input));
} else {
@ -495,7 +495,7 @@ static jv f_sort(jv input){
}
}
static jv f_sort_by_impl(jv input, jv keys) {
static jv f_sort_by_impl(jq_state *jq, jv input, jv keys) {
if (jv_get_kind(input) == JV_KIND_ARRAY &&
jv_get_kind(keys) == JV_KIND_ARRAY &&
jv_array_length(jv_copy(input)) == jv_array_length(jv_copy(keys))) {
@ -505,7 +505,7 @@ static jv f_sort_by_impl(jv input, jv keys) {
}
}
static jv f_group_by_impl(jv input, jv keys) {
static jv f_group_by_impl(jq_state *jq, jv input, jv keys) {
if (jv_get_kind(input) == JV_KIND_ARRAY &&
jv_get_kind(keys) == JV_KIND_ARRAY &&
jv_array_length(jv_copy(input)) == jv_array_length(jv_copy(keys))) {
@ -532,7 +532,7 @@ static int f_match_name_iter(const UChar* name, const UChar *name_end, int ngrou
}
static jv f_match(jv input, jv regex, jv modifiers, jv testmode) {
static jv f_match(jq_state *jq, jv input, jv regex, jv modifiers, jv testmode) {
int test = jv_equal(testmode, jv_true());
jv result;
int onigret;
@ -756,30 +756,30 @@ static jv minmax_by(jv values, jv keys, int is_min) {
return ret;
}
static jv f_min(jv x) {
static jv f_min(jq_state *jq, jv x) {
return minmax_by(x, jv_copy(x), 1);
}
static jv f_max(jv x) {
static jv f_max(jq_state *jq, jv x) {
return minmax_by(x, jv_copy(x), 0);
}
static jv f_min_by_impl(jv x, jv y) {
static jv f_min_by_impl(jq_state *jq, jv x, jv y) {
return minmax_by(x, y, 1);
}
static jv f_max_by_impl(jv x, jv y) {
static jv f_max_by_impl(jq_state *jq, jv x, jv y) {
return minmax_by(x, y, 0);
}
static jv f_type(jv input) {
static jv f_type(jq_state *jq, jv input) {
jv out = jv_string(jv_kind_name(jv_get_kind(input)));
jv_free(input);
return out;
}
static jv f_error(jv input, jv msg) {
static jv f_error(jq_state *jq, jv input, jv msg) {
jv_free(input);
return jv_invalid_with_msg(msg);
}
@ -789,7 +789,7 @@ static jv f_error(jv input, jv msg) {
extern const char **environ;
#endif
static jv f_env(jv input) {
static jv f_env(jq_state *jq, jv input) {
jv_free(input);
jv env = jv_object();
const char *var, *val;
@ -804,6 +804,14 @@ static jv f_env(jv input) {
return env;
}
static jv f_string_split(jq_state *jq, jv a, jv b) { return jv_string_split(a, b); }
static jv f_string_explode(jq_state *jq, jv a) { return jv_string_explode(a); }
static jv f_string_implode(jq_state *jq, jv a) { return jv_string_implode(a); }
static jv f_setpath(jq_state *jq, jv a, jv b, jv c) { return jv_setpath(a, b, c); }
static jv f_getpath(jq_state *jq, jv a, jv b) { return jv_getpath(a, b); }
static jv f_delpaths(jq_state *jq, jv a, jv b) { return jv_delpaths(a, b); }
static jv f_has(jq_state *jq, jv a, jv b) { return jv_has(a, b); }
#define LIBM_DD(name) \
{(cfunction_ptr)f_ ## name, "_" #name, 1},
@ -824,13 +832,13 @@ static const struct cfunction function_list[] = {
{(cfunction_ptr)f_endswith, "endswith", 2},
{(cfunction_ptr)f_ltrimstr, "ltrimstr", 2},
{(cfunction_ptr)f_rtrimstr, "rtrimstr", 2},
{(cfunction_ptr)jv_string_split, "split", 2},
{(cfunction_ptr)jv_string_explode, "explode", 1},
{(cfunction_ptr)jv_string_implode, "implode", 1},
{(cfunction_ptr)jv_setpath, "setpath", 3}, // FIXME typechecking
{(cfunction_ptr)jv_getpath, "getpath", 2},
{(cfunction_ptr)jv_delpaths, "delpaths", 2},
{(cfunction_ptr)jv_has, "has", 2},
{(cfunction_ptr)f_string_split, "split", 2},
{(cfunction_ptr)f_string_explode, "explode", 1},
{(cfunction_ptr)f_string_implode, "implode", 1},
{(cfunction_ptr)f_setpath, "setpath", 3}, // FIXME typechecking
{(cfunction_ptr)f_getpath, "getpath", 2},
{(cfunction_ptr)f_delpaths, "delpaths", 2},
{(cfunction_ptr)f_has, "has", 2},
{(cfunction_ptr)f_equal, "_equal", 3},
{(cfunction_ptr)f_notequal, "_notequal", 3},
{(cfunction_ptr)f_less, "_less", 3},

@ -650,17 +650,17 @@ jv jq_next(jq_state *jq) {
in[i] = stack_pop(jq);
}
struct cfunction* function = &frame_current(jq)->bc->globals->cfunctions[*pc++];
typedef jv (*func_1)(jv);
typedef jv (*func_2)(jv,jv);
typedef jv (*func_3)(jv,jv,jv);
typedef jv (*func_4)(jv,jv,jv,jv);
typedef jv (*func_5)(jv,jv,jv,jv,jv);
typedef jv (*func_1)(jq_state*,jv);
typedef jv (*func_2)(jq_state*,jv,jv);
typedef jv (*func_3)(jq_state*,jv,jv,jv);
typedef jv (*func_4)(jq_state*,jv,jv,jv,jv);
typedef jv (*func_5)(jq_state*,jv,jv,jv,jv,jv);
switch (function->nargs) {
case 1: top = ((func_1)function->fptr)(in[0]); break;
case 2: top = ((func_2)function->fptr)(in[0], in[1]); break;
case 3: top = ((func_3)function->fptr)(in[0], in[1], in[2]); break;
case 4: top = ((func_4)function->fptr)(in[0], in[1], in[2], in[3]); break;
case 5: top = ((func_5)function->fptr)(in[0], in[1], in[2], in[3], in[4]); break;
case 1: top = ((func_1)function->fptr)(jq, in[0]); break;
case 2: top = ((func_2)function->fptr)(jq, in[0], in[1]); break;
case 3: top = ((func_3)function->fptr)(jq, in[0], in[1], in[2]); break;
case 4: top = ((func_4)function->fptr)(jq, in[0], in[1], in[2], in[3]); break;
case 5: top = ((func_5)function->fptr)(jq, in[0], in[1], in[2], in[3], in[4]); break;
// FIXME: a) up to 7 arguments (input + 6), b) should assert
// because the compiler should not generate this error.
default: return jv_invalid_with_msg(jv_string("Function takes too many arguments"));