Introduce template instance concept to simplify freeing memory
[tedtools.git] / template.h
1 /*
2  * Copyright (c) 2008 Teodor Sigaev <teodor@sigaev.ru>
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *        notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *        notice, this list of conditions and the following disclaimer in the
12  *        documentation and/or other materials provided with the distribution.
13  * 3. Neither the name of the author nor the names of any co-contributors
14  *        may be used to endorse or promote products derived from this software
15  *        without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY CONTRIBUTORS ``AS IS'' AND ANY EXPRESS
18  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED. IN NO EVENT SHALL CONTRIBUTORS BE LIABLE FOR ANY
21  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
23  * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
25  * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
26  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
27  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  */
29
30 /******************************************************************************
31  *                         Html template library                              *
32  ******************************************************************************
33  ******************************************************************************
34  *                                  SYNTAX                                    *
35  ******************************************************************************
36  * <% EXPRESSION , "FORMAT"] [# "DEFAULTVALUE"] [|(h|u)]%>
37  *    - format value should be as in strftime for time value and printf
38  *      for all other. Currently, bool values have only "true"/"false"
39  *      string values
40  * <@IF EXPRESSION @>
41  * [ <@ELSE@> ] 
42  * <@ENDIF@>
43  *
44  * Expression is classical with support following:
45  *    -  ['^'] VARNAME     
46  *              variable defined from C-code. Mark '^' means global 
47  *       variable, not local in loop.
48  *    -  expression (+|-|*|/|%) expression
49  *               ariphmetic operations
50  *    -  expression ( || | && ) expression
51  *               ! expression
52  *       logical OR, AND and NOT
53  *    - expression ( < | <= | == | >= | > | != | <> ) expression 
54  *              compare expression
55  *    - LENGTH(expression)
56  *      computes length of string
57  *    - DEFINED(expression)
58  *      returns true if expression is defined
59  *        - expression ? expression : expression
60  *    - ( expression )
61  *    - USERDEFINEDFUNCTION( [expression[,expression[...]]] )
62  *      User defined function call. Function should be defined at 
63  *      C-level.
64  *
65  * <@LOOP MARKNAME@>
66  *              [ <@ SELF @> ]
67  * <@ENDLOOP@>
68  * Loop has predefined variables:
69  *    __FIRST   - true for first iteration
70  *    __LAST    - true for last iteration
71  *    __COUNTER - iteration's number
72  *    __SIZE    - number of iterations
73  *    __ODD     - true for odd iteraion
74  *    __EVEN    - true for even iteraion
75  *
76  * <& FILENAME &>
77  *
78  * <# comment #>
79  *
80  ******************************************************************************
81  *                                C-Interface                                 *
82  ******************************************************************************
83  * - setTemplateValueInt
84  *   setTemplateValueString
85  *   setTemplateValueTime
86  *   setTemplateValueBool
87  *   setTemplateValueDouble
88  *   setTemplateValueUndefined
89  *   Sets varibale's value
90  * - addTemplateRow
91  *   Add one iteration to the pointed loop. Local variable in loop should 
92  *   pointed with predecence loop's mark(s) separated by dot. Example:
93  *       HTML:
94  *   <@Loop outerLoop@>
95  *              <% var1 %>
96  *      <@Loop innerLoop@>
97  *                      <% var2 %>
98  *              <@endloop@>
99  *       <@endloop@>
100  *      C:
101  *      addTemplateRow("outerLoop");
102  *  setTemplateValueBool("outerLoop.var1");
103  *      addTemplateRow("innerLoop");
104  *  setTemplateValueBool("outerLoop.innerLoop.var2");
105  * - addTemplateNestedLoop
106  *   returnTemplateNestedLoop
107  *   Manage self-nested loops ( ie tree-like structures ).
108  *       Loop's template should contains one <@ SELF @> pointer.
109  *
110  * Examplaes of usage are in data/template.html used for test.
111  *
112  ******************************************************************************
113  *                               Memory management                            * 
114  ******************************************************************************
115  * Unfortunatly, I'm too lazy to unify memory usage by several pieces
116  * in library. So, library uses mixed plain malloc and memory context
117  * concepts (tmalloc.h).
118  * To work with library it's needed to allocate persistent memory context
119  * for initTemplate().
120  * To work with template it's needed to get template's instance by 
121  * newTemplateInstance() call with separated memory context. In any time
122  * that memory context can be reseted or freeed and it will be enough
123  * to free template's instance.
124  * 
125  ******************************************************************************/
126
127 #ifndef __TEMPLATE_H__
128 #define __TEMPLATE_H__
129
130 #include <sys/types.h>
131 #include <time.h>
132 #include "glist.h"
133 #include "sfxstr.h"
134 #include "tmalloc.h"
135
136 typedef enum TemplateNodeType {
137         /* node tree types */
138         TextNode = 100,
139         VariableNode,
140         IncludeNode,
141         LoopNode,
142         ConditionNode,
143         CollectionNode,
144         ExpressionNode,
145         PrintNode,
146         ConstNode,
147         NestNode,
148         LoopData,
149
150         /* value's types of variables */
151         valueInt = 200, /* smallest of any values type */
152         valueString,
153         valueTime,
154         valueBool,
155         valueDouble,
156         valuePointer
157 } TemplateNodeType;
158
159 #define TND_HTMLESCAPE          (0x0001)
160 #define TND_URLESCAPE           (0x0002)
161 #define TND_GLOBAL                      (0x0004)
162
163 #define TND___FIRST                     (0x0008)
164 #define TND___LAST                      (0x0010)
165 #define TND___COUNTER           (0x0020)
166 #define TND___SIZE                      (0x0040)
167 #define TND___ODD                       (0x0080)
168 #define TND___EVEN                      (0x0100)
169
170 #define TND_DEFINED                     (0x0200)
171
172 #define TND__SPECIALMASK        (TND___FIRST | TND___LAST | TND___COUNTER | TND___SIZE | TND___ODD | TND___EVEN)
173
174 typedef struct TemplateData *Template;
175
176 typedef struct TemplateInstanceData *TemplateInstance;
177
178 typedef struct TemplateNodeData *TemplateNode;
179
180 typedef struct VariableValueData * VariableValue;
181 typedef struct VariableValueData {
182         TemplateNodeType        type; /* should be first, see resetTemplate/freeTemplate */
183         int                                     flags;
184         union {
185                 int                             intValue;
186                 char                    *stringValue;
187                 time_t                  timeValue;
188                 int                             boolValue;
189                 double                  doubleValue;
190                 VariableValue   ptrValue; /* special value to handle loop variables,
191                                                                          points to members of loopValues */
192         } value;
193 } VariableValueData;
194
195
196 typedef struct executeFunctionDescData *executeFunctionDesc;
197 typedef struct executeFunctionDescData {
198         char                    *name;
199         int                             nargs; /* -1 - variable number */
200         VariableValue   (*execFn)(TemplateInstance, int, VariableValue*);
201 } executeFunctionDescData;
202
203 typedef struct LoopInstanceData * LoopInstance;
204
205 typedef struct LoopRowData *LoopRow;
206
207 typedef struct LoopRowData {
208         TemplateNode            loop;
209         LoopInstance            nestedInstance;
210         LoopRow                         nextCell;
211         VariableValueData       varvals[1];
212 } LoopRowData;
213 #define LRDHDRSZ        (offsetof(LoopRowData, varvals))
214
215 typedef struct LoopInstanceData {
216         int                             nrow;
217         LoopInstance    upperInstance;
218
219         LoopInstance    nextCell;
220         LoopRow                 headList;
221         LoopRow                 tailList;
222         /* GList                        *rowValues; */ /*list of LoopRow */
223 } LoopInstanceData;
224
225 typedef struct LoopTemplateInstanceData *LoopTemplateInstance;
226 typedef struct LoopTemplateInstanceData {
227         TemplateNodeType        type; /* LoopData */
228         TemplateNode            loopNode;
229         LoopRow                         lastRow;
230         LoopInstance            currentInstance;
231         LoopInstance            headList;
232         LoopInstance            tailList;
233         /*GList                         *listInstance;*/
234 }       LoopTemplateInstanceData;
235
236 typedef long Offset; 
237
238 typedef struct  TemplateNodeData {
239         TemplateNodeType        type; /* should be first, see resetTemplate/freeTemplate */
240
241         union {
242                 /* TextNode */
243                 struct {
244                         char    *value;
245                         int             valueLength;
246                 } text;
247
248                 /* VariableNode */
249                 struct {
250                         char                    *varName;
251                         int                             varNameLength;
252                         Offset                  varValueOffset;
253                         /* VariableValue        value; */
254                         int                             flags;
255                 } variable;
256
257                 /* ExpressionNode */
258                 struct {
259                         VariableValue           *argsValue;
260                         int                                     nargs;
261                         char                            *functionName;
262                         executeFunctionDesc     function;
263                         GList                           *argsNode; /* list of arguments nodes */ 
264                 } expression;
265
266                 /* ConstNode */
267                 VariableValueData               value;
268
269                 /* PrintNode */
270                 struct {
271                         TemplateNode    expressionNode;
272                         char                    *formatValue;
273                         char                    *defaultValue;
274                         int                             flags;
275                 } print; 
276
277                 /* IncludeNode */
278                 char    *includeFile;
279
280                 /* NestNode */
281                 struct {
282                         TemplateNode    loop;
283                         LoopRow                 savedRowData;
284                         GList                   *childrenLoopAfterSelf; 
285                 } nest;
286
287                 /* LoopNode */
288                 struct {
289                         char                    *varName;
290                         int                     varNameLength;
291                         TemplateNode    bodyNode;
292                         TemplateNode    selfNode; /* pointer to self-nested plase to insert */
293                         GList                   *childrenLoop;  /* to reset loop's instance  */
294                         GList                   *listVarValues; /* list of loop variables */
295                         Offset                  loopDataOffset;
296                 } loop;
297
298                 /* ConditionNode */
299                 struct {
300                         TemplateNode    expressionNode;
301                         TemplateNode    ifNode;
302                         TemplateNode    elseNode;
303                 } condition;
304
305                 /* CollectionNode */
306                 GList   *children;
307         } nodeData;
308         
309 } TemplateNodeData;
310
311 /* prints result */
312 typedef void  (*outFn)(char *, int);
313
314 typedef char*   (*urlEscapeFn)(char *, int * /* in/out */);
315 typedef char*   (*htmlEscapeFn)(char *, int * /* in/out */);
316
317 typedef struct TemplateData {
318         TemplateNode            tree;
319         MemoryContext           *templateContext;
320         SFSTree                         variables;
321         outFn                           printString;
322         urlEscapeFn                     urlEscape;
323         htmlEscapeFn            htmlEscape;
324         executeFunctionDesc functions;
325
326         Offset                          templateInstanceSize;
327         char                            *templateInstance;
328 } TemplateData;
329
330 typedef struct TemplateInstanceData {
331         Template                        tmpl;
332         MemoryContext           *templateContext;
333         char                            instanceData[1];
334 } TemplateInstanceData;
335
336 int parseTemplateFile(Template tmpl, char* filename );  /* return non-zero if error */
337 int initTemplate( Template tmpl, MemoryContext *mc, executeFunctionDesc functions, char *basedir, char *filename );
338 void freeTemplate( Template tmpl );
339 TemplateInstance        newTemplateInstance(Template tmpl, MemoryContext *mc);
340 int printTemplate( TemplateInstance tmpl );
341
342 #define TVAR_OK                 (0)
343 #define TVAR_NOTFOUND   (1)
344 #define TVAR_FORBIDDEN  (2)
345 #define TVAR_NOROW              (3)
346 #define TVAR_LOOPMARK   (4)
347
348 int setTemplateValueInt( TemplateInstance tmpl, char * key, int val );
349 int setTemplateValueString( TemplateInstance tmpl, char * key, char * val );
350 int setTemplateValueTime( TemplateInstance tmpl, char * key, time_t val );
351 int setTemplateValueBool( TemplateInstance tmpl, char * key, int val );
352 int setTemplateValueUndefined( TemplateInstance tmpl, char * key );
353 int setTemplateValueDouble( TemplateInstance tmpl, char * key, double val );
354 int addTemplateRow( TemplateInstance tmpl, char * key );
355 int addTemplateNestedLoop( TemplateInstance tmpl, char * key);
356 int returnTemplateNestedLoop( TemplateInstance tmpl, char * key);
357 void dumpTemplate( Template tmpl );
358 #endif