feat(ltm): wip compile
parent
5df1ea8309
commit
95788f22e3
|
@ -1,8 +1,26 @@
|
||||||
#ifndef LTM_COMMON
|
#ifndef LTM_COMMON
|
||||||
#define LTM_COMMON
|
#define LTM_COMMON
|
||||||
|
|
||||||
|
#define LTM_RES(x) \
|
||||||
|
{ \
|
||||||
|
ltm_err res = x; \
|
||||||
|
if (res != ltm_err_ok) \
|
||||||
|
return res; \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define LTM_RES2(x, e) \
|
||||||
|
{ \
|
||||||
|
ltm_err res = x; \
|
||||||
|
if (res != ltm_err_ok) { \
|
||||||
|
e; \
|
||||||
|
return res; \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
|
||||||
typedef enum ltm_err {
|
typedef enum ltm_err {
|
||||||
ltm_err_ok = 0,
|
ltm_err_ok = 0,
|
||||||
|
ltm_invalid_template,
|
||||||
|
ltm_failed_alloc,
|
||||||
} ltm_err;
|
} ltm_err;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -8,23 +8,23 @@
|
||||||
/**
|
/**
|
||||||
* Represents a compiled template
|
* Represents a compiled template
|
||||||
*/
|
*/
|
||||||
typedef struct lnm_template lnm_template;
|
typedef struct ltm_template ltm_template;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Compile the given template.
|
* Compile the given template.
|
||||||
*
|
*
|
||||||
* @param out where to store pointer to newly allocated `lnm_template`
|
* @param out where to store pointer to newly allocated `ltm_template`
|
||||||
* @param template nul-terminated string containing the template
|
* @param template nul-terminated string containing the template
|
||||||
*/
|
*/
|
||||||
ltm_err lnm_template_compile(lnm_template **out, const char *template);
|
ltm_err ltm_template_compile(ltm_template **out, const char *template);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Compile the given template with a given length.
|
* Compile the given template with a given length.
|
||||||
*
|
*
|
||||||
* @param out where to store pointer to newly allocated `lnm_template`
|
* @param out where to store pointer to newly allocated `ltm_template`
|
||||||
* @param template char buffer containing the template
|
* @param template char buffer containing the template
|
||||||
* @param len length of the char buffer
|
* @param len length of the char buffer
|
||||||
*/
|
*/
|
||||||
ltm_err lnm_template_compile_n(lnm_template **out, const char *template, size_t len);
|
ltm_err ltm_template_compile_n(ltm_template **out, const char *template, size_t len);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -0,0 +1,68 @@
|
||||||
|
#ifndef LTM_TEMPLATE_INTERNAL
|
||||||
|
#define LTM_TEMPLATE_INTERNAL
|
||||||
|
|
||||||
|
#include "ltm/template.h"
|
||||||
|
|
||||||
|
typedef enum ltm_placeholder_type {
|
||||||
|
ltm_placeholder_type_var = 0,
|
||||||
|
ltm_placeholder_type_loop_start,
|
||||||
|
ltm_placeholder_type_loop_end,
|
||||||
|
} ltm_placeholder_type;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Internal struct used when compiling templates
|
||||||
|
*/
|
||||||
|
typedef struct ltm_placeholder {
|
||||||
|
const char *start;
|
||||||
|
const char *end;
|
||||||
|
const char *name;
|
||||||
|
ltm_placeholder_type type;
|
||||||
|
} ltm_placeholder;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The type of a template block
|
||||||
|
*/
|
||||||
|
typedef enum ltm_template_block_type {
|
||||||
|
ltm_template_block_type_literal = 0,
|
||||||
|
ltm_template_block_type_var,
|
||||||
|
ltm_template_block_type_loop,
|
||||||
|
} ltm_template_block_type;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A block in a template.
|
||||||
|
*/
|
||||||
|
typedef struct ltm_template_block {
|
||||||
|
ltm_template_block_type type;
|
||||||
|
union {
|
||||||
|
ltm_template *template;
|
||||||
|
const char *s;
|
||||||
|
} data;
|
||||||
|
size_t len;
|
||||||
|
} ltm_template_block;
|
||||||
|
|
||||||
|
typedef struct ltm_template_block_name {
|
||||||
|
struct {
|
||||||
|
const char *s;
|
||||||
|
size_t len;
|
||||||
|
} name;
|
||||||
|
size_t index;
|
||||||
|
} ltm_template_block_name;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a compiled template. A template consists of a list of blocks, of
|
||||||
|
* which some have names that can be indexed (e.g. variables, loops).
|
||||||
|
*/
|
||||||
|
struct ltm_template {
|
||||||
|
struct {
|
||||||
|
ltm_template_block *arr;
|
||||||
|
size_t len;
|
||||||
|
} blocks;
|
||||||
|
struct {
|
||||||
|
ltm_template_block_name *arr;
|
||||||
|
size_t len;
|
||||||
|
} names;
|
||||||
|
};
|
||||||
|
|
||||||
|
ltm_err ltm_template_init(ltm_template **out);
|
||||||
|
|
||||||
|
#endif
|
|
@ -1,11 +0,0 @@
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include "ltm/template.h"
|
|
||||||
|
|
||||||
ltm_err lnm_template_compile(lnm_template **out, const char *template) {
|
|
||||||
return lnm_template_compile_n(out, template, strlen(template));
|
|
||||||
}
|
|
||||||
|
|
||||||
ltm_err lnm_template_compile_n(lnm_template **out, const char *template, size_t len) {
|
|
||||||
|
|
||||||
}
|
|
|
@ -0,0 +1,92 @@
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "ltm/common.h"
|
||||||
|
#include "ltm/template.h"
|
||||||
|
#include "ltm/template_internal.h"
|
||||||
|
|
||||||
|
ltm_err ltm_template_init(ltm_template **out) {
|
||||||
|
ltm_template *template = calloc(1, sizeof(ltm_template));
|
||||||
|
|
||||||
|
if (template == NULL) {
|
||||||
|
return ltm_failed_alloc;
|
||||||
|
}
|
||||||
|
|
||||||
|
*out = template;
|
||||||
|
|
||||||
|
return ltm_err_ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
ltm_err ltm_template_next_placeholder(ltm_placeholder *ph, const char *s, size_t len) {
|
||||||
|
ph->start = memchr(s, '{', len - 1);
|
||||||
|
|
||||||
|
if ((ph->start != NULL) && (ph->start[1] == '{')) {
|
||||||
|
size_t new_len = len - (ph->start - s);
|
||||||
|
|
||||||
|
ph->end = memchr(ph->start + 2, '}', new_len - 3);
|
||||||
|
|
||||||
|
// Non-terminated placeholders aren't valid
|
||||||
|
if ((ph->end == NULL) || (ph->end[1] != '}')) {
|
||||||
|
return ltm_invalid_template;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ph->end = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ltm_err_ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
ltm_err ltm_template_compile_n(ltm_template **out, const char *s, size_t len) {
|
||||||
|
ltm_template *template;
|
||||||
|
LTM_RES(ltm_template_init(&template));
|
||||||
|
|
||||||
|
const char *start, *end;
|
||||||
|
|
||||||
|
while (((start = memchr(s, '{', len - 1)) != NULL) && (start[1] == '{')) {
|
||||||
|
size_t new_len = len - (start - s);
|
||||||
|
|
||||||
|
// Non-terminated placeholders aren't valid
|
||||||
|
if (((end = memchr(start + 2, '}', new_len - 3)) == NULL) || (end[1] != '}')) {
|
||||||
|
return ltm_invalid_template;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO actually parse placeholders
|
||||||
|
const char *word = start + 2;
|
||||||
|
|
||||||
|
while ((*word == ' ') && (word != end)) {
|
||||||
|
word++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The placeholder is empty
|
||||||
|
if (word == end) {
|
||||||
|
return ltm_invalid_template;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *word2 = word;
|
||||||
|
|
||||||
|
while ((*word2 != ' ') && (word2 != end)) {
|
||||||
|
word2++;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t word_len = word2 - word;
|
||||||
|
|
||||||
|
if (word2 != end) {
|
||||||
|
while ((*word2 == ' ') && (word2 != end)) {
|
||||||
|
word2++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Only one word, so it's a variable
|
||||||
|
if (word2 == end) {
|
||||||
|
// TODO register variable block
|
||||||
|
}
|
||||||
|
|
||||||
|
len = len - (end + 2 - s);
|
||||||
|
s = end + 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ltm_err_ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
ltm_err ltm_template_compile(ltm_template **out, const char *template) {
|
||||||
|
return ltm_template_compile_n(out, template, strlen(template));
|
||||||
|
}
|
Loading…
Reference in New Issue