cleaned up interfaces and unused code

This commit is contained in:
cozis
2023-09-10 01:31:23 +02:00
parent 69f99e07b5
commit af635e7389
3 changed files with 149 additions and 186 deletions
+15 -55
View File
@@ -23,47 +23,27 @@ struct eval_context_t {
wrap_t pool[TINYTEMPLATE_MAX_ITER_DEPTH];
};
static bool query_json_array(void *data,
tinytemplate_type_t *type,
tinytemplate_value_t *value);
static bool query_json_array(void *data, tinytemplate_value_t *value);
static bool query_json_object(void *data, const char *key, size_t len,
tinytemplate_type_t *type,
tinytemplate_value_t *value);
static void convert_json_object(eval_context_t *context,
xj_value *child,
tinytemplate_type_t *type,
static void convert_json_object(eval_context_t *context, xj_value *child,
tinytemplate_value_t *value)
{
switch (child->type) {
case XJ_NULL:
*type = TINYTEMPLATE_TYPE_INT;
value->as_int = 0;
break;
case XJ_INT:
*type = TINYTEMPLATE_TYPE_INT;
value->as_int = child->as_int;
break;
case XJ_FLOAT:
*type = TINYTEMPLATE_TYPE_INT;
value->as_float = child->as_float;
break;
case XJ_BOOL:
*type = TINYTEMPLATE_TYPE_INT;
value->as_int = child->as_bool;
break;
case XJ_NULL : tinytemplate_set_int(value, 0); break;
case XJ_INT : tinytemplate_set_int(value, child->as_int); break;
case XJ_FLOAT: tinytemplate_set_float(value, child->as_float); break;
case XJ_BOOL : tinytemplate_set_int(value, child->as_bool); break;
case XJ_OBJECT: tinytemplate_set_dict(value, child, query_json_object); break;
case XJ_STRING: tinytemplate_set_string(value, child->as_string, child->size); break;
case XJ_ARRAY:
{
wrap_t *wrap = context->free;
*type = TINYTEMPLATE_TYPE_ARRAY;
value->as_array.data = wrap;
value->as_array.next = query_json_array;
tinytemplate_set_array(value, wrap, query_json_array);
if (wrap) {
context->free = wrap->next;
wrap->value = child->as_array;
@@ -71,29 +51,15 @@ static void convert_json_object(eval_context_t *context,
}
break;
}
case XJ_OBJECT:
*type = TINYTEMPLATE_TYPE_DICT;
value->as_dict.data = child;
value->as_dict.get = query_json_object;
break;
case XJ_STRING:
*type = TINYTEMPLATE_TYPE_STRING;
value->as_string.str = child->as_string;
value->as_string.len = child->size;
break;
}
}
static bool query_json_array(void *data,
tinytemplate_type_t *type,
tinytemplate_value_t *value)
static bool query_json_array(void *data, tinytemplate_value_t *value)
{
wrap_t *wrap = data;
if (wrap->value) {
convert_json_object(wrap->context, wrap->value, type, value);
convert_json_object(wrap->context, wrap->value, value);
wrap->value = wrap->value->next;
return true;
}
@@ -101,8 +67,7 @@ static bool query_json_array(void *data,
}
static bool query_json_object(void *data, const char *key, size_t len,
tinytemplate_type_t *type,
tinytemplate_value_t *value)
tinytemplate_value_t *value)
{
wrap_t *wrap = data;
@@ -118,27 +83,22 @@ static bool query_json_object(void *data, const char *key, size_t len,
if (!child)
return false;
convert_json_object(wrap->context, child, type, value);
convert_json_object(wrap->context, child, value);
return true;
}
static void callback(void *userp, const char *lbl, size_t lbllen,
const char *str, size_t len)
static void callback(void *userp, const char *str, size_t len)
{
(void) lbl;
(void) lbllen;
eval_context_t *context = userp;
fwrite(str, 1, len, context->stream);
}
static bool query_root_json_object(void *data, const char *key, size_t len,
tinytemplate_type_t *type,
tinytemplate_value_t *value)
{
eval_context_t *context = data;
if (context->params.value)
return query_json_object(&context->params, key, len, type, value);
return query_json_object(&context->params, key, len, value);
else
return false;
}
+115 -124
View File
@@ -73,7 +73,6 @@ typedef enum {
OPCODE_NEXT,
OPCODE_CHLD,
OPCODE_IDX,
OPCODE_BLOCK,
} opcode_t;
// Represents a substring of the template
@@ -86,7 +85,6 @@ typedef enum {
SCOPE_IF,
SCOPE_IF_ELSE,
SCOPE_FOR,
SCOPE_BLOCK,
} scope_type_t;
typedef struct {
@@ -99,7 +97,6 @@ typedef struct {
slice_t for_child_label;
slice_t for_index_label;
slice_t block_name;
} scope_t;
typedef struct {
@@ -140,7 +137,6 @@ typedef enum {
TOKEN_KWORD_FOR,
TOKEN_KWORD_ELSE,
TOKEN_KWORD_END,
TOKEN_KWORD_BLOCK,
TOKEN_OPER_MOD,
} token_t;
@@ -198,7 +194,6 @@ append_instr(compile_state_t *state,
case OPCODE_GETS:
case OPCODE_PUSHV:
case OPCODE_PUSHS:
case OPCODE_BLOCK:
instr->operands[0].as_size = va_arg(operands, size_t);
instr->operands[1].as_size = va_arg(operands, size_t);
break;
@@ -255,11 +250,58 @@ static bool is_printable(char c)
&& (unsigned char) c <= 126;
}
static bool
follows_digit(scanner_t *s)
{
return s->cur < s->len && is_digit(s->src[s->cur]);
}
static bool
follows_alpha(scanner_t *s)
{
return s->cur < s->len && is_alpha(s->src[s->cur]);
}
static bool
follows_space(scanner_t *s)
{
return s->cur < s->len && is_space(s->src[s->cur]);
}
static bool
follows_char(scanner_t *s, char c)
{
return s->cur < s->len && s->src[s->cur] == c;
}
static bool
follows_pair(scanner_t *s, char pair[static 2])
{
return s->cur+1 < s->len
&& s->src[s->cur+0] == pair[0]
&& s->src[s->cur+1] == pair[1];
}
static bool
consume_pair(scanner_t *s, char pair[static 2])
{
bool ok = follows_pair(s, pair);
if (ok) s->cur += 2;
return ok;
}
static void
consume_spaces(scanner_t *s)
{
while (follows_space(s))
s->cur++;
}
static token_t
next_token_int(scanner_t *scanner, slice_t *slice,
token_payload_t *payload)
{
assert(scanner->cur < scanner->len && is_digit(scanner->src[scanner->cur]));
assert(follows_digit(scanner));
size_t offset = scanner->cur;
@@ -272,7 +314,7 @@ next_token_int(scanner_t *scanner, slice_t *slice,
break;
}
buf = buf * 10 + d;
} while (scanner->cur < scanner->len && is_digit(scanner->src[scanner->cur]));
} while (follows_digit(scanner));
if (slice) {
slice->offset = offset;
@@ -291,7 +333,7 @@ next_token_float(scanner_t *scanner, slice_t *slice,
// The caller made sure that follows a float:
// a string of digits followed by a dot and
// another string of digits.
assert(scanner->cur < scanner->len && is_digit(scanner->src[scanner->cur]));
assert(follows_digit(scanner));
size_t offset = scanner->cur;
@@ -308,7 +350,7 @@ next_token_float(scanner_t *scanner, slice_t *slice,
q /= 10;
int d = scanner->src[scanner->cur++] - '0';
buf += d * q;
} while (scanner->cur < scanner->len && is_digit(scanner->src[scanner->cur]));
} while (follows_digit(scanner));
if (slice) {
slice->offset = offset;
@@ -325,7 +367,7 @@ next_token_numeric(scanner_t *scanner, slice_t *slice,
token_payload_t *payload)
{
// Scanner points to a digit
assert(scanner->cur < scanner->len && is_digit(scanner->src[scanner->cur]));
assert(follows_digit(scanner));
// Is it a float or an int? Check if at the end
// of the first sequence of digit there's a dot
@@ -346,12 +388,12 @@ next_token_kword_or_ident(scanner_t *scanner, slice_t *slice,
{
(void) payload;
assert(scanner->cur < scanner->len && is_alpha(scanner->src[scanner->cur]));
assert(follows_alpha(scanner));
size_t offset = scanner->cur;
do
scanner->cur++;
while (scanner->cur < scanner->len && is_alpha(scanner->src[scanner->cur]));
while (follows_alpha(scanner));
size_t length = scanner->cur - offset;
if (slice) {
@@ -380,11 +422,6 @@ next_token_kword_or_ident(scanner_t *scanner, slice_t *slice,
if (!strncmp(scanner->src + offset, "else", length))
return TOKEN_KWORD_ELSE;
break;
case 5: // block
if (!strncmp(scanner->src + offset, "block", length))
return TOKEN_KWORD_BLOCK;
break;
}
return TOKEN_IDENT;
@@ -394,8 +431,7 @@ static token_t
next_token(scanner_t *scanner, slice_t *slice,
token_payload_t *payload)
{
while (scanner->cur < scanner->len && is_space(scanner->src[scanner->cur]))
scanner->cur++;
consume_spaces(scanner);
if (scanner->cur == scanner->len) {
if (slice) {
@@ -709,11 +745,7 @@ expr_block(scanner_t *scanner,
append_instr(state, OPCODE_WRTOP);
append_instr(state, OPCODE_POP, 1);
if (scanner->cur+1 < scanner->len
&& scanner->src[scanner->cur+0] == '}'
&& scanner->src[scanner->cur+1] == '}')
scanner->cur += 2;
else {
if (!consume_pair(scanner, "}}")) {
report(error, "No closing [}}] after expression block");
return ESYNTAX;
}
@@ -726,12 +758,8 @@ close_construct(scanner_t *scanner,
const char *block_name)
{
// Consume the following "%}"
while (scanner->cur < scanner->len && is_space(scanner->src[scanner->cur]))
scanner->cur++;
if (scanner->cur+1 < scanner->len && scanner->src[scanner->cur] == '%' && scanner->src[scanner->cur+1] == '}')
scanner->cur += 2;
else {
consume_spaces(scanner);
if (!consume_pair(scanner, "%}")) {
report(error, "Missing closing %%} in {%% %s %%} block", block_name);
return ESYNTAX;
}
@@ -824,41 +852,6 @@ iteration_construct_start(scanner_t *scanner,
return DONE;
}
static status_t
block_construct_start(scanner_t *scanner,
compile_state_t *state,
error_t *error)
{
// This function is called after "{% block" is parsed
assert(scanner->src[scanner->cur-5] == 'b'
&& scanner->src[scanner->cur-4] == 'l'
&& scanner->src[scanner->cur-3] == 'o'
&& scanner->src[scanner->cur-2] == 'c'
&& scanner->src[scanner->cur-1] == 'k');
if (state->scope_depth == TINYTEMPLATE_MAX_SCOPE_DEPTH) {
report(error, "Scope depth limit reached");
return ESCOPE;
}
slice_t label;
if (next_token(scanner, &label, NULL) != TOKEN_IDENT) {
report(error, "Missing block label");
return ESYNTAX;
}
append_instr(state, OPCODE_BLOCK, label.offset, label.length);
tinytemplate_status_t status;
if ((status = close_construct(scanner, error, "block")) != DONE)
return status;
state->scope_stack[state->scope_depth].type = SCOPE_BLOCK;
state->scope_stack[state->scope_depth].block_name = label;
state->scope_depth++;
return DONE;
}
static void
resolve_scope(compile_state_t *state)
{
@@ -888,17 +881,6 @@ resolve_scope(compile_state_t *state)
instr = state->program + scope->if_jump;
instr->operands[0].as_size = state->num_instr;
break;
case SCOPE_BLOCK:
{
// Get parent block name
slice_t parent_label = {0, 0};
for (int i = state->scope_depth-2; i >= 0; i--)
if (state->scope_stack[i].type == SCOPE_BLOCK)
parent_label = state->scope_stack[i].block_name;
append_instr(state, OPCODE_BLOCK, parent_label.offset, parent_label.length);
break;
}
}
state->scope_depth--;
@@ -958,10 +940,6 @@ construct_else(scanner_t *scanner,
case SCOPE_FOR:
report(error, "Bad {%% else %%} coupled with {%% for .. %%}");
return ESEMANT;
case SCOPE_BLOCK:
report(error, "Bad {%% else %%} coupled with {%% block .. %%}");
return ESEMANT;
}
return DONE;
@@ -980,7 +958,6 @@ control_flow_block(scanner_t *scanner,
case TOKEN_KWORD_FOR: return iteration_construct_start(scanner, state, error);
case TOKEN_KWORD_END: return construct_end(scanner, state, error);
case TOKEN_KWORD_ELSE: return construct_else(scanner, state, error);
case TOKEN_KWORD_BLOCK: return block_construct_start(scanner, state, error);
default:
report(error, "Bad token [%.*s] after [{%%]",
(int) slice.length, scanner->src + slice.offset);
@@ -1024,7 +1001,7 @@ tinytemplate_compile(const char *src, size_t len,
size_t raw_off = scanner.cur; // Start offset of the raw block
while (scanner.cur < scanner.len) {
// Look for a "{" or the end
while (scanner.cur < scanner.len && scanner.src[scanner.cur] != '{')
while (follows_char(&scanner, '{'))
scanner.cur++;
// If the end wasn't reached (a "{" was found)
@@ -1076,15 +1053,15 @@ tinytemplate_compile(const char *src, size_t len,
static bool
value_can_be_considered_true(tinytemplate_type_t type,
tinytemplate_value_t value)
tinytemplate_union_t data)
{
switch (type) {
case TINYTEMPLATE_TYPE_INT:
return value.as_int != 0;
return data.as_int != 0;
case TINYTEMPLATE_TYPE_FLOAT:
return value.as_float != 0;
return data.as_float != 0;
default:
return false;
@@ -1094,14 +1071,14 @@ value_can_be_considered_true(tinytemplate_type_t type,
typedef struct {
tinytemplate_array_t iter;
tinytemplate_value_t child;
tinytemplate_type_t ctype;
size_t next_index;
} iter_state_t;
status_t
tinytemplate_eval(const char *src, const instr_t *program, void *userp,
tinytemplate_getter_t params,
tinytemplate_callback_t callback, char *errmsg, size_t errmax)
tinytemplate_eval(const char *src, const instr_t *program,
void *userp, tinytemplate_getter_t params,
tinytemplate_callback_t callback,
char *errmsg, size_t errmax)
{
error_t error = {.dst=errmsg, .max=errmax};
@@ -1109,11 +1086,9 @@ tinytemplate_eval(const char *src, const instr_t *program, void *userp,
size_t iter_depth = 0;
tinytemplate_type_t types[TINYTEMPLATE_MAX_EXPR_DEPTH];
tinytemplate_value_t stack[TINYTEMPLATE_MAX_EXPR_DEPTH];
tinytemplate_union_t stack[TINYTEMPLATE_MAX_EXPR_DEPTH];
size_t stack_depth = 0;
slice_t label = {0, 0};
bool done = false;
int index = 0;
while (!done) {
@@ -1128,13 +1103,6 @@ tinytemplate_eval(const char *src, const instr_t *program, void *userp,
done = true;
break;
case OPCODE_BLOCK:
label = (slice_t) {
.offset = instr->operands[0].as_size,
.length = instr->operands[1].as_size,
};
break;
case OPCODE_ITER:
assert(stack_depth > 0); // ITER excepts a value on the stack
// as an iteration target
@@ -1157,12 +1125,9 @@ tinytemplate_eval(const char *src, const instr_t *program, void *userp,
// be run outside of an iteration.
iter_state_t *top_iter = &iter_stack[iter_depth-1];
tinytemplate_type_t type;
tinytemplate_value_t value;
if (top_iter->iter.next(top_iter->iter.data, &type, &value)) {
if (top_iter->iter.next(top_iter->iter.data, &value)) {
top_iter->child = value;
top_iter->ctype = type;
top_iter->next_index++;
} else {
index = instr->operands[0].as_size;
@@ -1191,8 +1156,8 @@ tinytemplate_eval(const char *src, const instr_t *program, void *userp,
assert(iter->next_index > 0); // CHLD can only be executed after
// the iteration started.
stack[stack_depth] = iter->child;
types[stack_depth] = iter->ctype;
stack[stack_depth] = iter->child.data;
types[stack_depth] = iter->child.type;
stack_depth++;
break;
}
@@ -1237,14 +1202,13 @@ tinytemplate_eval(const char *src, const instr_t *program, void *userp,
size_t offset = instr->operands[0].as_size;
size_t length = instr->operands[1].as_size;
tinytemplate_type_t type;
tinytemplate_value_t value;
if (!stack[stack_depth-1].as_dict.get(stack[stack_depth-1].as_dict.data, src + offset, length, &type, &value)) {
if (!stack[stack_depth-1].as_dict.get(stack[stack_depth-1].as_dict.data, src + offset, length, &value)) {
report(&error, "Key %.*s not in dict", (int) length, src + offset);
return ESYMBOL;
}
types[stack_depth-1] = type;
stack[stack_depth-1] = value;
types[stack_depth-1] = value.type;
stack[stack_depth-1] = value.data;
break;
}
@@ -1279,11 +1243,10 @@ tinytemplate_eval(const char *src, const instr_t *program, void *userp,
size_t varname_offset = instr->operands[0].as_size;
size_t varname_length = instr->operands[1].as_size;
tinytemplate_type_t type;
tinytemplate_value_t value;
if (params(userp, src + varname_offset, varname_length, &type, &value)) {
types[stack_depth] = type;
stack[stack_depth] = value;
if (params(userp, src + varname_offset, varname_length, &value)) {
types[stack_depth] = value.type;
stack[stack_depth] = value.data;
stack_depth++;
} else {
report(&error, "Undefined variable [%.*s]",
@@ -1310,8 +1273,7 @@ tinytemplate_eval(const char *src, const instr_t *program, void *userp,
{
size_t offset = instr->operands[0].as_size;
size_t length = instr->operands[1].as_size;
callback(userp, src + label.offset, label.length,
src + offset, length);
callback(userp, src + offset, length);
break;
}
@@ -1326,8 +1288,7 @@ tinytemplate_eval(const char *src, const instr_t *program, void *userp,
char text[128];
int num = snprintf(text, sizeof(text), "%lld", stack[stack_depth-1].as_int);
assert(num > 0);
callback(userp, src + label.offset, label.length,
text, (size_t) num);
callback(userp, text, (size_t) num);
break;
}
@@ -1336,15 +1297,12 @@ tinytemplate_eval(const char *src, const instr_t *program, void *userp,
char text[128];
int num = snprintf(text, sizeof(text), "%lf", stack[stack_depth-1].as_float);
assert(num > 0);
callback(userp, src + label.offset, label.length,
text, (size_t) num);
callback(userp, text, (size_t) num);
break;
}
case TINYTEMPLATE_TYPE_STRING:
callback(userp, src + label.offset, label.length,
stack[stack_depth-1].as_string.str,
stack[stack_depth-1].as_string.len);
callback(userp, stack[stack_depth-1].as_string.str, stack[stack_depth-1].as_string.len);
break;
default:
@@ -1358,7 +1316,7 @@ tinytemplate_eval(const char *src, const instr_t *program, void *userp,
assert(stack_depth > 0);
stack_depth--;
break;
// This will be useful from here on
#define PAIR(x, y) ((unsigned char) (x) | ((unsigned char) (y) << 8))
@@ -1671,4 +1629,37 @@ tinytemplate_eval(const char *src, const instr_t *program, void *userp,
}
}
return DONE;
}
void tinytemplate_set_int(tinytemplate_value_t *dst, int64_t value)
{
dst->type = TINYTEMPLATE_TYPE_INT;
dst->data.as_int = value;
}
void tinytemplate_set_float(tinytemplate_value_t *dst, float value)
{
dst->type = TINYTEMPLATE_TYPE_FLOAT;
dst->data.as_float = value;
}
void tinytemplate_set_string(tinytemplate_value_t *dst, const char *str, size_t len)
{
dst->type = TINYTEMPLATE_TYPE_STRING;
dst->data.as_string.str = str;
dst->data.as_string.len = len;
}
void tinytemplate_set_array(tinytemplate_value_t *dst, void *data, tinytemplate_nextcallback_t next)
{
dst->type = TINYTEMPLATE_TYPE_ARRAY;
dst->data.as_array.data = data;
dst->data.as_array.next = next;
}
void tinytemplate_set_dict(tinytemplate_value_t *dst, void *data, tinytemplate_getter_t get)
{
dst->type = TINYTEMPLATE_TYPE_DICT;
dst->data.as_dict.data = data;
dst->data.as_dict.get = get;
}
+19 -7
View File
@@ -25,11 +25,11 @@ typedef enum {
TINYTEMPLATE_TYPE_STRING,
} tinytemplate_type_t;
typedef union tinytemplate_value_t tinytemplate_value_t;
typedef struct tinytemplate_value_t tinytemplate_value_t;
typedef bool (*tinytemplate_nextcallback_t)(void*, tinytemplate_type_t*, tinytemplate_value_t*);
typedef bool (*tinytemplate_getter_t)(void*, const char*, size_t, tinytemplate_type_t*, tinytemplate_value_t*);
typedef void (*tinytemplate_callback_t)(void *userp, const char *lbl, size_t lblen, const char *str, size_t len);
typedef bool (*tinytemplate_nextcallback_t)(void*, tinytemplate_value_t*);
typedef bool (*tinytemplate_getter_t)(void*, const char*, size_t, tinytemplate_value_t*);
typedef void (*tinytemplate_callback_t)(void *userp, const char *str, size_t len);
typedef struct {
void *data;
@@ -46,12 +46,17 @@ typedef struct {
size_t len;
} tinytemplate_string_t;
union tinytemplate_value_t {
typedef union {
int64_t as_int;
double as_float;
tinytemplate_dict_t as_dict;
tinytemplate_array_t as_array;
tinytemplate_dict_t as_dict;
tinytemplate_array_t as_array;
tinytemplate_string_t as_string;
} tinytemplate_union_t;
struct tinytemplate_value_t {
tinytemplate_type_t type;
tinytemplate_union_t data;
};
typedef struct {
@@ -86,4 +91,11 @@ tinytemplate_compile(const char *src, size_t len,
tinytemplate_instr_t *program,
size_t max_instr, size_t *num_instr,
char *errmsg, size_t errmax);
void tinytemplate_set_int(tinytemplate_value_t *dst, int64_t value);
void tinytemplate_set_float(tinytemplate_value_t *dst, float value);
void tinytemplate_set_string(tinytemplate_value_t *dst, const char *str, size_t len);
void tinytemplate_set_array(tinytemplate_value_t *dst, void *data, tinytemplate_nextcallback_t next);
void tinytemplate_set_dict(tinytemplate_value_t *dst, void *data, tinytemplate_getter_t get);
#endif