C TemplateS

If you found this page using a search engine, you may be looking for the original libctemplate by Stephen C. Losen

libctemplates is a template expander written for use with HTML. It's goals are to be simple, versitile, and fast. This library started off as a fork of libctemplate, but eventually became a total rewrite. libctemplate, the original, was built primarily for cgi applications. libctemplate was tightly coupled with file streams, while libctemplateS renders templates to strings for use in any application, FastCGI or Kore, for example. If you think libctemplates is missing a feature, feel free to suggest it to alexandermpickering@gmail.com, or, even better, write it yourself and send the patch! You can find instructions on createing and sending git patches here.

Contents

  1. Installation
  2. Usage
  3. Quick refrence
  4. Examples

Installation

Run the make file. libctemplates should compile on any system with a c99 complient c compiler. If you are on linux, run

make; make install

Usage

Just include the ctemplates.h header and make sure you're linking against libctemplates.a, for example:

gcc main.c -lctemplates

Quick refrence

Structs

Functions

struct TMPL_templates* TMPL_alloc_template(char* template_string)

Creates a template from the given string. This can be pretty expensive so try to only do it once for each template you need, and call render() as many times as you need on that template.

void TMPL_free_template(struct TMPL_templates* template)

Frees a previously allocated template.

struct TMPL_varlist* TMPL_alloc_varlist()

Allocates a variable list that you can add variables and loops to.

void TMPL_free_varlist(struct TMPL_varlist* varlist)

Frees a previously allocated varlist, and any loops that have been added.

struct TMPL_loop* TMPL_alloc_loop()

Allocates a loop that you can add varlists to.

void TMPL_free_loop(struct TMPL_loop* loop)

Frees a previously allocated loop, and any varlists that have been added.

void TMPL_add_var_to_varlist(struct TMPL_varlist* vl, char* name, char* value)  

Adds a variable to a variable list

void TMPL_add_loop_to_varlist(struct TMPL_varlist* vl,char* name,struct TMPL_loop* loop)  

Adds a loop to a varlist

void TMPL_add_varlist_to_loop(struct TMPL_loop* l, struct TMPL_varlist* vl)  

Adds a varlist that should be used one iteration through the loop

char* TMPL_render(struct TMPL_templates* t, struct TMPL_varlist* vl)  

Turns a template and varlist into a string. the returned char* should NOT be freed. The returned char* is only valid until TMPL_render() is called again. If you need it even after TMPL_render() is called, copy it.

Examples

Hello, World!

At it's most simple, libctemplates just copies whatever template you give it. For example:

main.c

#include <ctemplate.h>
#include <stdio.h>
#include <stdlib.h>

char* template = "Hello, world!";

int main(){
    struct TMPL_templates* t = TMPL_alloc_template(template);
    if(t == NULL){
        printf("Failed to compile\n");
        exit(-1);
    }
    struct TMPL_varlist* vl = TMPL_alloc_varlist();
    char* output = TMPL_render(t,vl);
    printf("Output: %s\n",output);
    TMPL_free_varlist(vl);
    TMPL_free_template(t);
    return 0;
}

output

Output: Hello, world!

Variable substitution

template.html

Value is:<TMPL_VAR name="varname" default="optional default">

main.c

#include <ctemplate.h>

int main(){
    /* 
    It usually helps to seperate the template from the
    C code. It does mean to need to read in a file though.
    Try to only call TMPL_alloc_template once for each
    template you have, and then use TMPL_render() whenever
    you need to use them.
    */
    FILE* fp = fopen("template.html","r");
    if(fp == NULL){
        printf("Failed to open file!\n");
        exit(-1);
    }
    fseek(fp,0,SEEK_END);
    size_t file_len = ftell(fp);
    char template[file_len];
    fread(template,sizeof(char),file_len,fp);

    struct TMPL_templates* t;
    struct TMPL_varlist* vl;

    /*
    Render the template without a variable named "varname"
    This will use the variable's default, if it has one.
    If the variable has no default, and is not supplied a value,
    it errors, and stores a message that can be retrived with
    TMPL_get_error(...)
    */
    t = TMPL_alloc_template(template);
    vl = TMPL_alloc_varlist();
    char* without_variable = TMPL_render(t,vl);
    printf("Without variable: %s\n",without_variable);
    TMPL_free_template(t);
    TMPL_free_varlist(vl);

    /*
    Now render a template with a variable, use the
    TMPL_add_var_to_varlist(...) to supply the template with
    variables.
    */
    t = TMPL_alloc_template(template);
    vl = TMPL_alloc_varlist();
    TMPL_add_var_to_varlist(vl,"varname","Hello, world!");
    char* with_variable = TMPL_render(t,vl);
    printf("With variable:%s\n",with_variable);
    TMPL_free_template(t);
    TMPL_free_varlist(vl);

    return 0;
}

output

Without variable:
Value is:optional default


With variable:
Value is:Hello, world!

If/Elseif/Else

If and elseif statements check if strings are the same. They do a strcmp(), so be mindful not to use really long strings if you don't need them.

template.html

What happened:
<TMPL_IF name="varname" value="1234">
    "varname" was "1234"
<TMPL_ELSEIF name="var2" value="pass">
    "var2" was "pass"
<TMPL_ELSE>
    "varname" was not "1234", and "var2" was not "pass"
<TMPL_END>

main.c

#include <stdlib.h>
#include <stdio.h>
#include <ctemplate.h>

int main(){
    /* 
    Same as before, just read a file in
    */
    FILE* fp = fopen("template.html","r");
    if(fp == NULL){
        printf("Failed to open file!\n");
        exit(-1);
    }
    fseek(fp,0,SEEK_END);
    size_t file_len = ftell(fp);
    rewind(fp);
    char template[file_len];
    fread(template,sizeof(char),file_len,fp);

    /*
    No need to rebuild the template each time,
    just alloc it once.
    */
    struct TMPL_templates* t = TMPL_alloc_template(template);
    struct TMPL_varlist* vl;

    /*
    If the variable the "if" or "elseif" is looking for dosn't exist,
    the condition is considered false.
    */
    vl = TMPL_alloc_varlist();
    char* without_variable = TMPL_render(t,vl);
    printf("Without variable:\n%s\n",without_variable);

    /*
    Add a variable to make the second condition true, and reprint
    After we call TMPL_render() again, whatever pointer it returned
    last time may have been freed. Be sure to copy it into your own
    buffer if you still need it.
    */
    TMPL_add_var_to_varlist(vl,"var2","pass");
    char* with_one = TMPL_render(t,vl);
    printf("With 1 variable:\n%s\n",TMPL_render(t,vl));

    /*
    Always be sure to free things!
    */
    TMPL_free_varlist(vl);
    TMPL_free_template(t);

    return 0;
}

output

Without variable:

What happened:

    "varname" was not "1234", and "var2" was not "pass"



With 1 variable:

What happened:

    "var2" was "pass"

Notice that the tabs in the template are preserved in the output. This is not a minifier! Just a template expander!

Loops

Loops are special in libctemplates, loops each have their own namespace, and only variables that have been added to the namespace are acessable in the loop.

template.html

What happened:
<TMPL_LOOP name="myloop">
    This time through the loop, my variable is <TMPL_VAR name="loopvar">
<TMPL_END>

main.c

#include <stdlib.h>
#include <stdio.h>
#include <ctemplate.h>

int main(){
    /* 
    Same as before
    */
    FILE* fp = fopen("template.html","r");
    if(fp == NULL){
        printf("Failed to open file!\n");
        exit(-1);
    }
    fseek(fp,0,SEEK_END);
    size_t file_len = ftell(fp);
    rewind(fp);
    char template[file_len];
    fread(template,sizeof(char),file_len,fp);

    /*
    Same as before
    */
    struct TMPL_templates* t = TMPL_alloc_template(template);
    struct TMPL_varlist* vl = TMPL_alloc_varlist();

    /*
    Now create a loop variable and add some things to it.
    This is usually not as verbose as it looks here, since you'll
    usually do this in a C loop.
    */
    struct TMPL_loop* loop = TMPL_alloc_loop();

    struct TMPL_varlist* first = TMPL_alloc_varlist();
    TMPL_add_var_to_varlist(first,"loopvar","first");
    TMPL_add_varlist_to_loop(loop,first);

    struct TMPL_varlist* second = TMPL_alloc_varlist();
    TMPL_add_var_to_varlist(second,"loopvar","second");
    TMPL_add_varlist_to_loop(loop,second);

    struct TMPL_varlist* third = TMPL_alloc_varlist();
    TMPL_add_var_to_varlist(third,"loopvar","third");
    TMPL_add_varlist_to_loop(loop,third);

    /*
    Remember to add the loop to the varlist you'll eventually
    pass to TMPL_render() with the correct name.
    */
    TMPL_add_loop_to_varlist(vl,"myloop",loop);

    char* output = TMPL_render(t,vl);
    printf("Output:\n%s\n",output);

    /*
    When freeing a varlist, any loops it has are automatically
    also freed. When freeing a loop, any varlists it contains
    are also automatically freed. This means you only need to
    free your top-level varlist!
    */
    TMPL_free_varlist(vl);
    TMPL_free_template(t);
}

output

Output:
What happened:
This time through the loop, my variable is first
This time through the loop, my variable is second
This time through the loop, my variable is theird
Done!