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