aboutsummaryrefslogtreecommitdiff
path: root/README.md
blob: 043aca3bed05730068dba1f68db24236c42dcf5b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
# C TemplateS

If you found this page using a search engine, you may be looking for the
original [libctemplate](http://libctemplate.sourceforge.net) by Stephen C. Losen

libctemplates is a template expander written for use with HTML. It's goals are
to be simple, versatile, 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 libctemplate**S** renders templates to 
strings for use in any application, FastCGI or [Kore](kore.io), for example.
If you think libctemplates is missing a feature, feel free to suggest it to
[alex@cogarr.net](mailto://alex@cogarr.net),
or, even better, write it yourself and send the patch! You can find
instructions on creating and sending git patches [here](http://cogarr.net/source/cgit.cgi/?p=about).

## Contents

1. [Installation](#Installation)
2. [Usage](#Usage)
3. [Quick reference](#Quick refrence)
4. [Examples](#Examples)

<section id="Installation"></section>
## Installation

Run the make file. libctemplates should compile on any system with a c99
complaint c compiler. If you are on linux, cd into the root directory and run

	make && make install

<section id="Usage"></section>
## Usage

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

	gcc main.c -lctemplates

<section id="Quick refrence"></section>
## Quick reference

### Structs

* struct TMPL\_templates  
  Holds a template
* struct TMPL\_varlist  
  Holds a list of variables to be used when rendering a template.
  Loops can be held in a varlist, and varlists can be held in loops.
* struct TMPL\_loop  
  Used to define things to loop through in a varlist.

### 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. If there was a problem building
the template, the returned `template->error` will be non-zero, and you can
retrive an error message with `TMPL_err()`

	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, size_t* length)  

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. The length of the returned string is put into `length` to help in copying.

### Templating tags

	<TMPL_VAR name="variable_name" default="default_value">

Substitutes a variable, with an optional default value.

Prints the variable named "variable\_name" in it's place, if no variable named "variable\_name" is found, the default printed. If there is not variable name, and no default value, an error is logged, and it is expanded to an empty string. (If you need to have nothing printed when the variable does not exist, you should use `default=""` to keep the error log clean.

	<TMPL_IF name="variable_name" value="check_value">
	:
	<TMPL_ELSEIF name="variable_name" value="check_value">
	:
	<TMPL_ELSE>
	:
	<TMPL_END>

Branching statements, checks if a variable is equal to a constant value.

Checks if the variable "variable\_name" contains the string "check\_value". There is currently no way to check if two variables are equal. Elseif and Else clauses are optional. All `TMPL_IF` statements must be closed with `TMPL_END`. You can use `TMPL_IF` and `TMPL_ELSEIF` to check for a variable's existence by not specifying a `value` parameter.

	<TMPL_LOOP name="loop_name">
	:
	<TMPL_END>

Loop statements, I bet you can't figure out what this does.

Loops through a loop named "loop\_name", each iteration through the loop, only the varlist added to the loop is visible. That is, no other varlist, even the parent varlist, is visible while inside the loop.

<section id="Examples"></section>
## 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();
		size_t dummy;
		char* output = TMPL_render(t,vl,&dummy);
		printf("Output: %s\n",output);
		printf("Length: %d\n",(int)dummy);
		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. You 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 subsitutes an empty string and logs an error message. You
		can check for error messages by checking if template->error is
		non-zero. You can retrive error messages with TMPL_get_error()
		*/
		t = TMPL_alloc_template(template);
		vl = TMPL_alloc_varlist();
		size_t dummy;
		char* without_variable = TMPL_render(t,vl,&dummy);
		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!");
		size_t dummy;
		char* with_variable = TMPL_render(t,vl,&dummy);
		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();
		size_t dummy;
		char* without_variable = TMPL_render(t,vl,&dummy);
		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");
		size_t dummy;
		char* with_one = TMPL_render(t,vl,&dummy);
		printf("With 1 variable:\n%s\n",with_one);

		/*
		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 accessible 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);
		size_t size;
		char* output = TMPL_render(t,vl,&size);
		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!

<!-- Some styling, make it pretty! -->
<style>
body,html{
	line-height:1.2;
	font-size:18;
	color:#333;
}
pre{
	background-color:#eee;
	padding:10;
	border-radius:5;
}
</style>