X-Git-Url: http://sigaev.ru/git/gitweb.cgi?p=tedtools.git;a=blobdiff_plain;f=template.h;h=97e9070c0413ec535629741868843017b250ade7;hp=9b45bea967e68b6d617a6298b5196d75a67b6e46;hb=HEAD;hpb=b99712a22de6fb3f45b36580e63596aac7e6061c diff --git a/template.h b/template.h index 9b45bea..97e9070 100644 --- a/template.h +++ b/template.h @@ -28,25 +28,102 @@ */ /****************************************************************************** + * Html template library * + ****************************************************************************** + ****************************************************************************** * SYNTAX * ****************************************************************************** - * <% [^]VARNAME[, "FORMAT"] [||"DEFAULTVALUE"] [|(h|u)]%> - * - '^' mark means global variable. + * <% 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 [NOT] [DEFINED] [^]VARNAME@> - * <@ELSE@> + * <@IF EXPRESSION @> + * [<@ ELSE IF EXPRESSION | ELSIF EXPRESSION @>] + * [ <@ELSE@> ] * <@ENDIF@> * - * <@LOOP MARKNAME@> + * Expression is classical with support following: + * - ['^'] VARNAME + * variable defined from C-code. Mark '^' means global + * variable, not local in loop. + * - expression (+|-|*|/|%) expression + * ariphmetic operations + * - expression ( || | && ) expression + * ! expression + * logical OR, AND and NOT + * - expression ( < | <= | == | >= | > | != | <> ) expression + * compare expression + * - LENGTH(expression) + * computes length of string + * - DEFINED(expression) + * returns true if expression is defined + * - expression ? expression : expression + * - ( expression ) + * - USERDEFINEDFUNCTION( [expression[,expression[...]]] ) + * User defined function call. Function should be defined at + * 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 * * <& FILENAME &> * * <# comment #> * + ****************************************************************************** + * C-Interface * + ****************************************************************************** + * - setTemplateValueInt + * setTemplateValueString + * setTemplateValueTime + * setTemplateValueBool + * setTemplateValueDouble + * setTemplateValueUndefined + * Sets varibale's value + * - addTemplateRow + * Add one iteration to the pointed loop. Local variable in loop should + * pointed with predecence loop's mark(s) separated by dot. Example: + * HTML: + * <@Loop outerLoop@> + * <% var1 %> + * <@Loop innerLoop@> + * <% var2 %> + * <@endloop@> + * <@endloop@> + * C: + * addTemplateRow("outerLoop"); + * 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. + * ******************************************************************************/ #ifndef __TEMPLATE_H__ @@ -56,6 +133,7 @@ #include #include "glist.h" #include "sfxstr.h" +#include "tmalloc.h" typedef enum TemplateNodeType { /* node tree types */ @@ -65,6 +143,11 @@ typedef enum TemplateNodeType { LoopNode, ConditionNode, CollectionNode, + ExpressionNode, + PrintNode, + ConstNode, + NestNode, + LoopData, /* value's types of variables */ valueInt = 200, /* smallest of any values type */ @@ -75,20 +158,26 @@ typedef enum TemplateNodeType { valuePointer } TemplateNodeType; -#define TND_DEFINED (0x0001) -#define TND_NOT (0x0002) -#define TND_HTMLESCAPE (0x0004) -#define TND_URLESCAPE (0x0008) -#define TND_GLOBAL (0x0010) -#define TND___FIRST (0x0020) -#define TND___LAST (0x0040) -#define TND___COUNTER (0x0080) -#define TND___SIZE (0x0100) -#define TND___ODD (0x0200) -#define TND___EVEN (0x0400) - -#define TND__SPECIALMASK (TND___FIRST | TND___LAST | TND___COUNTER | TND___SIZE | TND___ODD | TND___EVEN) -struct TemplateNodeData; +#define TND_HTMLESCAPE (0x0001) +#define TND_URLESCAPE (0x0002) +#define TND_GLOBAL (0x0004) + +#define TND___FIRST (0x0008) +#define TND___LAST (0x0010) +#define TND___COUNTER (0x0020) +#define TND___SIZE (0x0040) +#define TND___ODD (0x0080) +#define TND___EVEN (0x0100) +#define TND___LEVEL (0x0200) + +#define TND_DEFINED (0x0400) + +#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; @@ -96,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; @@ -106,12 +195,49 @@ typedef struct VariableValueData { } value; } VariableValueData; + +typedef struct executeFunctionDescData *executeFunctionDesc; +typedef struct executeFunctionDescData { + char *name; + int nargs; /* -1 - variable number */ + 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 */ @@ -126,32 +252,55 @@ typedef struct TemplateNodeData { struct { char *varName; int varNameLength; - VariableValue value; + Offset varValueOffset; + /* VariableValue value; */ int flags; - char *formatValue; - char *defaultValue; } variable; + /* ExpressionNode */ + struct { + VariableValue *argsValue; + int nargs; + char *functionName; + executeFunctionDesc function; + GList *argsNode; /* list of arguments nodes */ + } expression; + + /* ConstNode */ + VariableValueData value; + + /* PrintNode */ + struct { + TemplateNode expressionNode; + char *formatValue; + char *defaultValue; + int flags; + } print; + /* 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 */ struct { - int flags; - char *varName; - int varNameLength; - VariableValue value; + TemplateNode expressionNode; TemplateNode ifNode; TemplateNode elseNode; } condition; @@ -169,21 +318,29 @@ typedef char* (*urlEscapeFn)(char *, int * /* in/out */); typedef char* (*htmlEscapeFn)(char *, int * /* in/out */); typedef struct TemplateData { - TemplateNode tree; - MemoryContext *templateContext; - SFSTree variables; - outFn printString; - urlEscapeFn urlEscape; - htmlEscapeFn htmlEscape; + TemplateNode tree; + MemoryContext *templateContext; + SFSTree variables; + outFn printString; + urlEscapeFn urlEscape; + htmlEscapeFn htmlEscape; + executeFunctionDesc functions; + + Offset templateInstanceSize; + char *templateInstance; } TemplateData; -typedef struct TemplateData *Template; +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, char *basedir, char *filename ); +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) @@ -191,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