add .gitignore
[tedtools.git] / template.h
index 0e12052..97e9070 100644 (file)
  */
 
 /******************************************************************************
+ *                         Html template library                              *
+ ******************************************************************************
+ ******************************************************************************
  *                                  SYNTAX                                    *
  ******************************************************************************
- * <% EXPRESSION , "FORMAT"] [# "DEFAULTVALUE"] [|(h|u)]%>
+ * <% EXPRESSION [, "FORMAT"] [# "DEFAULTVALUE"] [|(h|u)]%>
  *    - format value should be as in strftime for time value and printf
  *      for all other. Currently, bool values have only "true"/"false"
  *      string values
  * <@IF EXPRESSION @>
- * <@ELSE@>
+ * [<@ ELSE IF EXPRESSION | ELSIF EXPRESSION @>]
+ * [ <@ELSE@> ] 
  * <@ENDIF@>
  *
  * Expression is classical with support following:
  *      C-level.
  *
  * <@LOOP MARKNAME@>
+ *             [ <@ SELF @> ]
  * <@ENDLOOP@>
  * Loop has predefined variables:
  *    __FIRST   - true for first iteration
  *    __LAST    - true for last iteration
  *    __COUNTER - iteration's number
+ *    __LEVEL  - level of nested loop (root == 0)
  *    __SIZE    - number of iterations
  *    __ODD     - true for odd iteraion
  *    __EVEN    - true for even iteraion
@@ -74,7 +80,7 @@
  * <# comment #>
  *
  ******************************************************************************
- *                                C-Interface
+ *                                C-Interface                                 *
  ******************************************************************************
  * - setTemplateValueInt
  *   setTemplateValueString
  *  setTemplateValueBool("outerLoop.var1");
  *     addTemplateRow("innerLoop");
  *  setTemplateValueBool("outerLoop.innerLoop.var2");
+ * - addTemplateNestedLoop
+ *   returnTemplateNestedLoop
+ *   Manage self-nested loops ( ie tree-like structures ).
+ *      Loop's template should contains one <@ SELF @> pointer.
+ *
+ * Examplaes of usage are in data/template.html used for test.
+ *
+ ******************************************************************************
+ *                               Memory management                            * 
+ ******************************************************************************
+ * Unfortunatly, I'm too lazy to unify memory usage by several pieces
+ * in library. So, library uses mixed plain malloc and memory context
+ * concepts (tmalloc.h).
+ * To work with library it's needed to allocate persistent memory context
+ * for initTemplate().
+ * To work with template it's needed to get template's instance by 
+ * newTemplateInstance() call with separated memory context. In any time
+ * that memory context can be reseted or freeed and it will be enough
+ * to free template's instance.
  * 
  ******************************************************************************/
 
@@ -121,6 +146,8 @@ typedef     enum TemplateNodeType {
        ExpressionNode,
        PrintNode,
        ConstNode,
+       NestNode,
+       LoopData,
 
        /* value's types of variables */
        valueInt = 200, /* smallest of any values type */
@@ -141,13 +168,16 @@ typedef   enum TemplateNodeType {
 #define TND___SIZE                     (0x0040)
 #define TND___ODD                      (0x0080)
 #define TND___EVEN                     (0x0100)
+#define TND___LEVEL                    (0x0200)
 
-#define TND_DEFINED                    (0x0200)
+#define TND_DEFINED                    (0x0400)
 
-#define TND__SPECIALMASK       (TND___FIRST | TND___LAST | TND___COUNTER | TND___SIZE | TND___ODD | TND___EVEN)
+#define TND__SPECIALMASK       (TND___FIRST | TND___LAST | TND___COUNTER | TND___SIZE | TND___ODD | TND___EVEN | TND___LEVEL)
 
 typedef struct TemplateData *Template;
 
+typedef struct TemplateInstanceData *TemplateInstance;
+
 typedef struct TemplateNodeData *TemplateNode;
 
 typedef struct VariableValueData * VariableValue;
@@ -155,7 +185,7 @@ typedef struct VariableValueData {
        TemplateNodeType        type; /* should be first, see resetTemplate/freeTemplate */
        int                                     flags;
        union {
-               int                             intValue;
+               int64_t                 intValue;
                char                    *stringValue;
                time_t                  timeValue;
                int                             boolValue;
@@ -170,15 +200,44 @@ typedef struct executeFunctionDescData *executeFunctionDesc;
 typedef struct executeFunctionDescData {
        char                    *name;
        int                             nargs; /* -1 - variable number */
-       VariableValue   (*execFn)(Template, int, VariableValue*);
+       VariableValue   (*execFn)(TemplateInstance, int, VariableValue*);
 } executeFunctionDescData;
 
 typedef struct LoopInstanceData * LoopInstance;
+
+typedef struct LoopRowData *LoopRow;
+
+typedef struct LoopRowData {
+       TemplateNode            loop;
+       LoopInstance            nestedInstance;
+       LoopRow                         nextCell;
+       VariableValueData       varvals[1];
+} LoopRowData;
+#define LRDHDRSZ       (offsetof(LoopRowData, varvals))
+
 typedef struct LoopInstanceData {
        int                             nrow;
-       GList                   *rowValues;
+       LoopInstance    upperInstance;
+
+       LoopInstance    nextCell;
+       LoopRow                 headList;
+       LoopRow                 tailList;
+       /* GList                        *rowValues; */ /*list of LoopRow */
 } LoopInstanceData;
 
+typedef struct LoopTemplateInstanceData *LoopTemplateInstance;
+typedef struct LoopTemplateInstanceData {
+       TemplateNodeType        type; /* LoopData */
+       TemplateNode            loopNode;
+       LoopRow                         lastRow;
+       LoopInstance            currentInstance;
+       LoopInstance            headList;
+       LoopInstance            tailList;
+       /*GList                         *listInstance;*/
+}      LoopTemplateInstanceData;
+
+typedef long Offset; 
+
 typedef struct  TemplateNodeData {
        TemplateNodeType        type; /* should be first, see resetTemplate/freeTemplate */
 
@@ -193,7 +252,8 @@ typedef struct  TemplateNodeData {
                struct {
                        char                    *varName;
                        int                             varNameLength;
-                       VariableValue   value;
+                       Offset                  varValueOffset;
+                       /* VariableValue        value; */
                        int                             flags;
                } variable;
 
@@ -203,8 +263,7 @@ typedef struct  TemplateNodeData {
                        int                                     nargs;
                        char                            *functionName;
                        executeFunctionDesc     function;
-                       GList                           *argsNode; /* list of nodes after parsing 
-                                                                                               but before compile */   
+                       GList                           *argsNode; /* list of arguments nodes */ 
                } expression;
 
                /* ConstNode */
@@ -221,15 +280,22 @@ typedef struct  TemplateNodeData {
                /* IncludeNode */
                char    *includeFile;
 
+               /* NestNode */
+               struct {
+                       TemplateNode    loop;
+                       LoopRow                 savedRowData;
+                       GList                   *childrenLoopAfterSelf; 
+               } nest;
+
                /* LoopNode */
                struct {
                        char                    *varName;
                        int                     varNameLength;
                        TemplateNode    bodyNode;
-                       int                             counter;
-                       GList                   *childrenLoop;  /* to reset instance  */
+                       TemplateNode    selfNode; /* pointer to self-nested plase to insert */
+                       GList                   *childrenLoop;  /* to reset loop's instance  */
                        GList                   *listVarValues; /* list of loop variables */
-                       GList                   *listInstance;
+                       Offset                  loopDataOffset;
                } loop;
 
                /* ConditionNode */
@@ -259,13 +325,22 @@ typedef struct TemplateData {
        urlEscapeFn                     urlEscape;
        htmlEscapeFn            htmlEscape;
        executeFunctionDesc functions;
+
+       Offset                          templateInstanceSize;
+       char                            *templateInstance;
 } TemplateData;
 
+typedef struct TemplateInstanceData {
+       Template                        tmpl;
+       MemoryContext           *templateContext;
+       char                            instanceData[1];
+} TemplateInstanceData;
+
 int parseTemplateFile(Template tmpl, char* filename );  /* return non-zero if error */
 int initTemplate( Template tmpl, MemoryContext *mc, executeFunctionDesc functions, char *basedir, char *filename );
 void freeTemplate( Template tmpl );
-void resetTemplate( Template tmpl );
-int printTemplate( Template tmpl );
+TemplateInstance       newTemplateInstance(Template tmpl, MemoryContext *mc);
+int printTemplate( TemplateInstance tmpl );
 
 #define TVAR_OK                        (0)
 #define TVAR_NOTFOUND  (1)
@@ -273,13 +348,14 @@ int printTemplate( Template tmpl );
 #define TVAR_NOROW             (3)
 #define TVAR_LOOPMARK  (4)
 
-int setTemplateValueInt( Template tmpl, char * key, int val );
-int setTemplateValueString( Template tmpl, char * key, char * val );
-int setTemplateValueTime( Template tmpl, char * key, time_t val );
-int setTemplateValueBool( Template tmpl, char * key, int val );
-int setTemplateValueUndefined( Template tmpl, char * key );
-int setTemplateValueDouble( Template tmpl, char * key, double val );
-int addTemplateRow( Template tmpl, char * key );
-
+int setTemplateValueInt( TemplateInstance tmpl, char * key, int64_t val );
+int setTemplateValueString( TemplateInstance tmpl, char * key, char * val );
+int setTemplateValueTime( TemplateInstance tmpl, char * key, time_t val );
+int setTemplateValueBool( TemplateInstance tmpl, char * key, int val );
+int setTemplateValueUndefined( TemplateInstance tmpl, char * key );
+int setTemplateValueDouble( TemplateInstance tmpl, char * key, double val );
+int addTemplateRow( TemplateInstance tmpl, char * key );
+int addTemplateNestedLoop( TemplateInstance tmpl, char * key);
+int returnTemplateNestedLoop( TemplateInstance tmpl, char * key);
 void dumpTemplate( Template tmpl );
 #endif