add .gitignore
[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 IF EXPRESSION | ELSIF EXPRESSION @>]
42  * [ <@ELSE@> ] 
43  * <@ENDIF@>
44  *
45  * Expression is classical with support following:
46  *    -  ['^'] VARNAME     
47  *              variable defined from C-code. Mark '^' means global 
48  *       variable, not local in loop.
49  *    -  expression (+|-|*|/|%) expression
50  *               ariphmetic operations
51  *    -  expression ( || | && ) expression
52  *               ! expression
53  *       logical OR, AND and NOT
54  *    - expression ( < | <= | == | >= | > | != | <> ) expression 
55  *              compare expression
56  *    - LENGTH(expression)
57  *      computes length of string
58  *    - DEFINED(expression)
59  *      returns true if expression is defined
60  *        - expression ? expression : expression
61  *    - ( expression )
62  *    - USERDEFINEDFUNCTION( [expression[,expression[...]]] )
63  *      User defined function call. Function should be defined at 
64  *      C-level.
65  *
66  * <@LOOP MARKNAME@>
67  *              [ <@ SELF @> ]
68  * <@ENDLOOP@>
69  * Loop has predefined variables:
70  *    __FIRST   - true for first iteration
71  *    __LAST    - true for last iteration
72  *    __COUNTER - iteration's number
73  *    __LEVEL   - level of nested loop (root == 0)
74  *    __SIZE    - number of iterations
75  *    __ODD     - true for odd iteraion
76  *    __EVEN    - true for even iteraion
77  *
78  * <& FILENAME &>
79  *
80  * <# comment #>
81  *
82  ******************************************************************************
83  *                                C-Interface                                 *
84  ******************************************************************************
85  * - setTemplateValueInt
86  *   setTemplateValueString
87  *   setTemplateValueTime
88  *   setTemplateValueBool
89  *   setTemplateValueDouble
90  *   setTemplateValueUndefined
91  *   Sets varibale's value
92  * - addTemplateRow
93  *   Add one iteration to the pointed loop. Local variable in loop should 
94  *   pointed with predecence loop's mark(s) separated by dot. Example:
95  *       HTML:
96  *   <@Loop outerLoop@>
97  *              <% var1 %>
98  *      <@Loop innerLoop@>
99  *                      <% var2 %>
100  *              <@endloop@>
101  *       <@endloop@>
102  *      C:
103  *      addTemplateRow("outerLoop");
104  *  setTemplateValueBool("outerLoop.var1");
105  *      addTemplateRow("innerLoop");
106  *  setTemplateValueBool("outerLoop.innerLoop.var2");
107  * - addTemplateNestedLoop
108  *   returnTemplateNestedLoop
109  *   Manage self-nested loops ( ie tree-like structures ).
110  *       Loop's template should contains one <@ SELF @> pointer.
111  *
112  * Examplaes of usage are in data/template.html used for test.
113  *
114  ******************************************************************************
115  *                               Memory management                            * 
116  ******************************************************************************
117  * Unfortunatly, I'm too lazy to unify memory usage by several pieces
118  * in library. So, library uses mixed plain malloc and memory context
119  * concepts (tmalloc.h).
120  * To work with library it's needed to allocate persistent memory context
121  * for initTemplate().
122  * To work with template it's needed to get template's instance by 
123  * newTemplateInstance() call with separated memory context. In any time
124  * that memory context can be reseted or freeed and it will be enough
125  * to free template's instance.
126  * 
127  ******************************************************************************/
128
129 #ifndef __TEMPLATE_H__
130 #define __TEMPLATE_H__
131
132 #include <sys/types.h>
133 #include <time.h>
134 #include "glist.h"
135 #include "sfxstr.h"
136 #include "tmalloc.h"
137
138 typedef enum TemplateNodeType {
139         /* node tree types */
140         TextNode = 100,
141         VariableNode,
142         IncludeNode,
143         LoopNode,
144         ConditionNode,
145         CollectionNode,
146         ExpressionNode,
147         PrintNode,
148         ConstNode,
149         NestNode,
150         LoopData,
151
152         /* value's types of variables */
153         valueInt = 200, /* smallest of any values type */
154         valueString,
155         valueTime,
156         valueBool,
157         valueDouble,
158         valuePointer
159 } TemplateNodeType;
160
161 #define TND_HTMLESCAPE          (0x0001)
162 #define TND_URLESCAPE           (0x0002)
163 #define TND_GLOBAL                      (0x0004)
164
165 #define TND___FIRST                     (0x0008)
166 #define TND___LAST                      (0x0010)
167 #define TND___COUNTER           (0x0020)
168 #define TND___SIZE                      (0x0040)
169 #define TND___ODD                       (0x0080)
170 #define TND___EVEN                      (0x0100)
171 #define TND___LEVEL                     (0x0200)
172
173 #define TND_DEFINED                     (0x0400)
174
175 #define TND__SPECIALMASK        (TND___FIRST | TND___LAST | TND___COUNTER | TND___SIZE | TND___ODD | TND___EVEN | TND___LEVEL)
176
177 typedef struct TemplateData *Template;
178
179 typedef struct TemplateInstanceData *TemplateInstance;
180
181 typedef struct TemplateNodeData *TemplateNode;
182
183 typedef struct VariableValueData * VariableValue;
184 typedef struct VariableValueData {
185         TemplateNodeType        type; /* should be first, see resetTemplate/freeTemplate */
186         int                                     flags;
187         union {
188                 int64_t                 intValue;
189                 char                    *stringValue;
190                 time_t                  timeValue;
191                 int                             boolValue;
192                 double                  doubleValue;
193                 VariableValue   ptrValue; /* special value to handle loop variables,
194                                                                          points to members of loopValues */
195         } value;
196 } VariableValueData;
197
198
199 typedef struct executeFunctionDescData *executeFunctionDesc;
200 typedef struct executeFunctionDescData {
201         char                    *name;
202         int                             nargs; /* -1 - variable number */
203         VariableValue   (*execFn)(TemplateInstance, int, VariableValue*);
204 } executeFunctionDescData;
205
206 typedef struct LoopInstanceData * LoopInstance;
207
208 typedef struct LoopRowData *LoopRow;
209
210 typedef struct LoopRowData {
211         TemplateNode            loop;
212         LoopInstance            nestedInstance;
213         LoopRow                         nextCell;
214         VariableValueData       varvals[1];
215 } LoopRowData;
216 #define LRDHDRSZ        (offsetof(LoopRowData, varvals))
217
218 typedef struct LoopInstanceData {
219         int                             nrow;
220         LoopInstance    upperInstance;
221
222         LoopInstance    nextCell;
223         LoopRow                 headList;
224         LoopRow                 tailList;
225         /* GList                        *rowValues; */ /*list of LoopRow */
226 } LoopInstanceData;
227
228 typedef struct LoopTemplateInstanceData *LoopTemplateInstance;
229 typedef struct LoopTemplateInstanceData {
230         TemplateNodeType        type; /* LoopData */
231         TemplateNode            loopNode;
232         LoopRow                         lastRow;
233         LoopInstance            currentInstance;
234         LoopInstance            headList;
235         LoopInstance            tailList;
236         /*GList                         *listInstance;*/
237 }       LoopTemplateInstanceData;
238
239 typedef long Offset; 
240
241 typedef struct  TemplateNodeData {
242         TemplateNodeType        type; /* should be first, see resetTemplate/freeTemplate */
243
244         union {
245                 /* TextNode */
246                 struct {
247                         char    *value;
248                         int             valueLength;
249                 } text;
250
251                 /* VariableNode */
252                 struct {
253                         char                    *varName;
254                         int                             varNameLength;
255                         Offset                  varValueOffset;
256                         /* VariableValue        value; */
257                         int                             flags;
258                 } variable;
259
260                 /* ExpressionNode */
261                 struct {
262                         VariableValue           *argsValue;
263                         int                                     nargs;
264                         char                            *functionName;
265                         executeFunctionDesc     function;
266                         GList                           *argsNode; /* list of arguments nodes */ 
267                 } expression;
268
269                 /* ConstNode */
270                 VariableValueData               value;
271
272                 /* PrintNode */
273                 struct {
274                         TemplateNode    expressionNode;
275                         char                    *formatValue;
276                         char                    *defaultValue;
277                         int                             flags;
278                 } print; 
279
280                 /* IncludeNode */
281                 char    *includeFile;
282
283                 /* NestNode */
284                 struct {
285                         TemplateNode    loop;
286                         LoopRow                 savedRowData;
287                         GList                   *childrenLoopAfterSelf; 
288                 } nest;
289
290                 /* LoopNode */
291                 struct {
292                         char                    *varName;
293                         int                     varNameLength;
294                         TemplateNode    bodyNode;
295                         TemplateNode    selfNode; /* pointer to self-nested plase to insert */
296                         GList                   *childrenLoop;  /* to reset loop's instance  */
297                         GList                   *listVarValues; /* list of loop variables */
298                         Offset                  loopDataOffset;
299                 } loop;
300
301                 /* ConditionNode */
302                 struct {
303                         TemplateNode    expressionNode;
304                         TemplateNode    ifNode;
305                         TemplateNode    elseNode;
306                 } condition;
307
308                 /* CollectionNode */
309                 GList   *children;
310         } nodeData;
311         
312 } TemplateNodeData;
313
314 /* prints result */
315 typedef void  (*outFn)(char *, int);
316
317 typedef char*   (*urlEscapeFn)(char *, int * /* in/out */);
318 typedef char*   (*htmlEscapeFn)(char *, int * /* in/out */);
319
320 typedef struct TemplateData {
321         TemplateNode            tree;
322         MemoryContext           *templateContext;
323         SFSTree                         variables;
324         outFn                           printString;
325         urlEscapeFn                     urlEscape;
326         htmlEscapeFn            htmlEscape;
327         executeFunctionDesc functions;
328
329         Offset                          templateInstanceSize;
330         char                            *templateInstance;
331 } TemplateData;
332
333 typedef struct TemplateInstanceData {
334         Template                        tmpl;
335         MemoryContext           *templateContext;
336         char                            instanceData[1];
337 } TemplateInstanceData;
338
339 int parseTemplateFile(Template tmpl, char* filename );  /* return non-zero if error */
340 int initTemplate( Template tmpl, MemoryContext *mc, executeFunctionDesc functions, char *basedir, char *filename );
341 void freeTemplate( Template tmpl );
342 TemplateInstance        newTemplateInstance(Template tmpl, MemoryContext *mc);
343 int printTemplate( TemplateInstance tmpl );
344
345 #define TVAR_OK                 (0)
346 #define TVAR_NOTFOUND   (1)
347 #define TVAR_FORBIDDEN  (2)
348 #define TVAR_NOROW              (3)
349 #define TVAR_LOOPMARK   (4)
350
351 int setTemplateValueInt( TemplateInstance tmpl, char * key, int64_t val );
352 int setTemplateValueString( TemplateInstance tmpl, char * key, char * val );
353 int setTemplateValueTime( TemplateInstance tmpl, char * key, time_t val );
354 int setTemplateValueBool( TemplateInstance tmpl, char * key, int val );
355 int setTemplateValueUndefined( TemplateInstance tmpl, char * key );
356 int setTemplateValueDouble( TemplateInstance tmpl, char * key, double val );
357 int addTemplateRow( TemplateInstance tmpl, char * key );
358 int addTemplateNestedLoop( TemplateInstance tmpl, char * key);
359 int returnTemplateNestedLoop( TemplateInstance tmpl, char * key);
360 void dumpTemplate( Template tmpl );
361 #endif