* 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
* 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 persitent memory context
- * for initTemplate() call and temprorary memory context for usual work.
- * after printTemplate is called it's needed to call resetTemplate() and
- * then resetMemoryContext() for second context.
+ * 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.
*
******************************************************************************/
ExpressionNode,
PrintNode,
ConstNode,
+ NestNode,
+ LoopData,
/* value's types of variables */
valueInt = 200, /* smallest of any values type */
#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;
TemplateNodeType type; /* should be first, see resetTemplate/freeTemplate */
int flags;
union {
- int intValue;
+ int64_t intValue;
char *stringValue;
time_t timeValue;
int boolValue;
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 */
struct {
char *varName;
int varNameLength;
- VariableValue value;
+ Offset varValueOffset;
+ /* VariableValue value; */
int flags;
} variable;
int nargs;
char *functionName;
executeFunctionDesc function;
- GList *argsNode; /* list of nodes after parsing
- but before compile */
+ GList *argsNode; /* list of arguments nodes */
} expression;
/* ConstNode */
/* 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 */
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)
#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