From 69f99e07b5e45cc2bd6ecdae9244e97694aebb14 Mon Sep 17 00:00:00 2001 From: cozis Date: Thu, 29 Jun 2023 20:15:03 +0200 Subject: [PATCH] more docs --- README.md | 93 +++++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 83 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index a490cb4..af1cd14 100644 --- a/README.md +++ b/README.md @@ -26,6 +26,9 @@ Here's how it looks: if you've already used some templating engines, then this won't blow your mind. +## Template language features +The templating language is extremely simple. You can use "if .. else" and "for" constructs but can't define new wariables or mutate already defined ones. TinyTemplate only behaves as a view of data provided by the parent application so it doesn't need to do any processing. + ## Build To build it you run ```sh @@ -34,20 +37,90 @@ make which will generate the `tt` file, the command-line utility. ## Embed -If you want to embed TinyTemplate in your own C project, -just pop `tinytemplate.c` and `tinytemplate.h` in you own -source tree and compile then as they were your own. +If you want to embed TinyTemplate in your own C project, just pop `tinytemplate.c` and `tinytemplate.h` in you own source tree and compile them as they were your own. ## Command-line usage -The `tt` utility gets the template string from stdin and writes the evaluated version to stdout. Any errors are -reported to stderr, as you would expect. To provide any -parameters to the template, you can specify a json file -containing them. Here's an example usage which transforms -a template into an HTML page +The `tt` utility gets the template string from stdin and writes the evaluated version to stdout. Any errors are reported to stderr, as you would expect. To provide any parameters to the template, you can specify a json file containing them. Here's an example usage which transforms a template into an HTML page ```sh cat page.tt | ./tt params.json > page.html ``` -## Internals -TinyTemplate works by compiling a template string into a bytecode program, and then evaluating the program to generate the output. (TODO) \ No newline at end of file +## Library usage +TinyTemplate works by compiling a template string into a bytecode program, and then evaluating the program to generate the output. The library only exports two functions: + +```c +tinytemplate_status_t +tinytemplate_eval(const char *src, const tinytemplate_instr_t *program, + void *userp, tinytemplate_getter_t params, + tinytemplate_callback_t callback, + char *errmsg, size_t errmax); + +tinytemplate_status_t +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); +``` + +First you need to compile the template into a program and then you can evaluate it by executing the program. + +### Compilation +The compilation function expects a source string of the template through `src` and with length in bytes `len`. The string doesn't need to be zero-terminated. The program will be compilated by writing its instructions in the `program` buffer. The `program` array is assumed to have space for a maximum of `max_instr` instructions. If more space would be required to memorize the program, the compilation fails returning the status code `TINYTEMPLATE_STATUS_EMEMORY`. At that point the caller program can either abort or try again with a bigger buffer. If compilation succeded, then the number of instruction is written to the variable `num_instr`. A status code of the compilation is returned through the main return value. The status `TINYTEMPLATE_STATUS_DONE` means all went well, while all other status codes refer to a specific error that occurred. If the compilation failed, an error message is written to the caller-provided buffer `errmsg` whith size `errmax`. + +Here's an example of how you would use this function: +```c +int main(void) +{ + char message[128]; + tinytemplate_instr_t program[32]; + tinytemplate_status_t status; + + static const char text[] = "Hello, my name is {{name}}!"; + + size_t num_instr; + size_t max_instr = sizeof(program) / sizeof(program[0]); + status = tinytemplate_compile(text, sizeof(text)-1, program, max_instr, + NULL, message, sizeof(message)); + if (status != TINYTEMPLATE_STATUS_DONE) { + fprintf(stderr, "Error: %s", message); + return -1; + } + + fprintf(stdout, "Program compiled to %ld instructions!\n", num_instr); + return 0; +} +``` + +### Evaluation +To evaluate a program you need to provide both the program and the source string of the template. Also the caller must specify two callbacks: `params` and `callback`. The `params` callback, which has the following interface: +```c +bool params(void *data, const char *key, size_t len, + tinytemplate_type_t *type, + tinytemplate_value_t *value); +``` +provides the values of the parameters references by the template. For example if defining the parameter template as following: +```c +bool params(void *data, const char *key, size_t len, + tinytemplate_type_t *type, + tinytemplate_value_t *value) +{ + if (len == 3 && !strncmp(key, "age", len)) { + *type = TINYTEMPLATE_TYPE_INT; + value->as_int = 24; + return true; + } + return false; +} +``` +the value `24` will be associated to the parameter `age`. All other parameters will be undefined. + +The other callback `callback` is used by TinyTemplate to output the result of the evaluation. Instead of evaluating the result to a buffer and then returning a single pointer, it calls this function to notify the caller that some bytes should be written to output. This function usually writes the bytes provided by the library to a caller-owned buffer. Here's an example callback that redirects the evaluation result to `stdout` +```c +void callback(void *data, const char *lbl, size_t lbllen, + const char *str, size_t len) +{ + fwrite(str, 1, len, stdout); +} +``` +The argument `data` of the two callbacks is always the pointer provided to the `tinytemplate_eval` function through `userp`. \ No newline at end of file