diff --git a/ltm/include/ltm/common.h b/ltm/include/ltm/common.h index b8d7c21..d3fd9f9 100644 --- a/ltm/include/ltm/common.h +++ b/ltm/include/ltm/common.h @@ -1,8 +1,26 @@ #ifndef 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 { ltm_err_ok = 0, + ltm_invalid_template, + ltm_failed_alloc, } ltm_err; #endif diff --git a/ltm/include/ltm/template.h b/ltm/include/ltm/template.h index 1d71e14..ceb7396 100644 --- a/ltm/include/ltm/template.h +++ b/ltm/include/ltm/template.h @@ -8,23 +8,23 @@ /** * Represents a compiled template */ -typedef struct lnm_template lnm_template; +typedef struct ltm_template ltm_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 */ -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. * - * @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 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 diff --git a/ltm/src/_include/ltm/template_internal.h b/ltm/src/_include/ltm/template_internal.h new file mode 100644 index 0000000..d20c606 --- /dev/null +++ b/ltm/src/_include/ltm/template_internal.h @@ -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 diff --git a/ltm/src/ltm_template.c b/ltm/src/ltm_template.c deleted file mode 100644 index 870f876..0000000 --- a/ltm/src/ltm_template.c +++ /dev/null @@ -1,11 +0,0 @@ -#include - -#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) { - -} diff --git a/ltm/src/ltm_template_compile.c b/ltm/src/ltm_template_compile.c new file mode 100644 index 0000000..fe62181 --- /dev/null +++ b/ltm/src/ltm_template_compile.c @@ -0,0 +1,92 @@ +#include + +#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)); +}