From: teodor Date: Tue, 7 Oct 2008 11:46:38 +0000 (+0000) Subject: Introduce template instance concept to simplify freeing memory X-Git-Url: http://www.sigaev.ru/git/gitweb.cgi?p=tedtools.git;a=commitdiff_plain;h=9029e8cc9a52539819e1a07f4ccddbc75c3b8c2c Introduce template instance concept to simplify freeing memory --- diff --git a/template.c b/template.c index 73d9cc4..b20fb89 100644 --- a/template.c +++ b/template.c @@ -34,6 +34,39 @@ #include "tlog.h" #include "template.h" +/* + * Simple list implementation + */ +#define TListPush(l,c) do { \ + (c)->nextCell = NULL; \ + if ( (l)->tailList == NULL ) { \ + (l)->headList = (l)->tailList = (c); \ + } else { \ + (l)->tailList->nextCell = (c); \ + (l)->tailList = (c); \ + } \ +} while(0) + +#define TListUnShift(l,c) do { \ + (c)->nextCell = (l)->headList; \ + if ( (l)->headList == NULL ) { \ + (l)->headList = (l)->tailList = (c); \ + } else { \ + (l)->headList = (c); \ + } \ +} while(0) + +#define TListShift(l,c) do { \ + (c) = (l)->headList; \ + if ( (c) != NULL ) { \ + (l)->headList = (c)->nextCell; \ + if ( (l)->headList == NULL ) \ + (l)->tailList = NULL; \ + } \ +} while(0) + +#define TListIsEmpty(l) ( (l)->headList == NULL ) + /* * Default operations and functions */ @@ -69,7 +102,7 @@ isVariable(VariableValue value) { } static VariableValue -makeBoolValue(Template tmpl, int v) { +makeBoolValue(TemplateInstance tmpl, int v) { VariableValue outvalue = mcalloc(tmpl->templateContext, sizeof(VariableValueData)); outvalue->type = valueBool; @@ -79,7 +112,7 @@ makeBoolValue(Template tmpl, int v) { } static VariableValue -copyValue(Template tmpl, VariableValue in) { +copyValue(TemplateInstance tmpl, VariableValue in) { VariableValue out= mcalloc(tmpl->templateContext, sizeof(VariableValueData)); if (in) @@ -92,7 +125,7 @@ copyValue(Template tmpl, VariableValue in) { } static VariableValue -isDefinedFn(Template tmpl, int n, VariableValue *vals) { +isDefinedFn(TemplateInstance tmpl, int n, VariableValue *vals) { return makeBoolValue(tmpl, vals[0]->flags & TND_DEFINED ); } @@ -113,7 +146,7 @@ strmblen(char *str) { } static VariableValue -LengthFn(Template tmpl, int n, VariableValue *vals) { +LengthFn(TemplateInstance tmpl, int n, VariableValue *vals) { VariableValue outvalue = NULL; outvalue = copyValue( tmpl, NULL ); @@ -130,27 +163,27 @@ LengthFn(Template tmpl, int n, VariableValue *vals) { } static VariableValue -NotFn(Template tmpl, int n, VariableValue *vals) { +NotFn(TemplateInstance tmpl, int n, VariableValue *vals) { return makeBoolValue(tmpl, !isVariable(vals[0])); } static VariableValue -AndFn(Template tmpl, int n, VariableValue *vals) { +AndFn(TemplateInstance tmpl, int n, VariableValue *vals) { return makeBoolValue(tmpl, isVariable(vals[0]) && isVariable(vals[1]) ); } static VariableValue -OrFn(Template tmpl, int n, VariableValue *vals) { +OrFn(TemplateInstance tmpl, int n, VariableValue *vals) { return makeBoolValue(tmpl, isVariable(vals[0]) || isVariable(vals[1]) ); } static VariableValue -CondFn(Template tmpl, int n, VariableValue *vals) { +CondFn(TemplateInstance tmpl, int n, VariableValue *vals) { return isVariable(vals[0]) ? vals[1] : vals[2]; } static VariableValue -ModFn(Template tmpl, int n, VariableValue *vals) { +ModFn(TemplateInstance tmpl, int n, VariableValue *vals) { VariableValue outvalue = copyValue( tmpl, NULL ); outvalue->type = valueInt; @@ -167,7 +200,7 @@ ModFn(Template tmpl, int n, VariableValue *vals) { } static VariableValue -UnaryMinesFn(Template tmpl, int n, VariableValue *vals) { +UnaryMinesFn(TemplateInstance tmpl, int n, VariableValue *vals) { VariableValue outvalue = copyValue( tmpl, vals[0] ); if (outvalue->type == valueInt) @@ -204,25 +237,25 @@ UnaryMinesFn(Template tmpl, int n, VariableValue *vals) { } static VariableValue -PlusFn(Template tmpl, int n, VariableValue *vals) { +PlusFn(TemplateInstance tmpl, int n, VariableValue *vals) { ARIPHACT(+) return outvalue; } static VariableValue -MinesFn(Template tmpl, int n, VariableValue *vals) { +MinesFn(TemplateInstance tmpl, int n, VariableValue *vals) { ARIPHACT(-) return outvalue; } static VariableValue -MulFn(Template tmpl, int n, VariableValue *vals) { +MulFn(TemplateInstance tmpl, int n, VariableValue *vals) { ARIPHACT(*) return outvalue; } static VariableValue -DivFn(Template tmpl, int n, VariableValue *vals) { +DivFn(TemplateInstance tmpl, int n, VariableValue *vals) { ARIPHACT(/) return outvalue; } @@ -249,37 +282,37 @@ DivFn(Template tmpl, int n, VariableValue *vals) { } static VariableValue -LtFn(Template tmpl, int n, VariableValue *vals) { +LtFn(TemplateInstance tmpl, int n, VariableValue *vals) { CMPACT(<) return outvalue; } static VariableValue -LeFn(Template tmpl, int n, VariableValue *vals) { +LeFn(TemplateInstance tmpl, int n, VariableValue *vals) { CMPACT(<=) return outvalue; } static VariableValue -EqFn(Template tmpl, int n, VariableValue *vals) { +EqFn(TemplateInstance tmpl, int n, VariableValue *vals) { CMPACT(==) return outvalue; } static VariableValue -GeFn(Template tmpl, int n, VariableValue *vals) { +GeFn(TemplateInstance tmpl, int n, VariableValue *vals) { CMPACT(>=) return outvalue; } static VariableValue -GtFn(Template tmpl, int n, VariableValue *vals) { +GtFn(TemplateInstance tmpl, int n, VariableValue *vals) { CMPACT(>) return outvalue; } static VariableValue -NeFn(Template tmpl, int n, VariableValue *vals) { +NeFn(TemplateInstance tmpl, int n, VariableValue *vals) { CMPACT(!=) return outvalue; } @@ -366,12 +399,14 @@ findIncludes(ParseState *state, TemplateNode *node) { *node = tmp.tree; break; case LoopNode: + state->tmpl->templateInstanceSize += sizeof( LoopTemplateInstanceData ); if ( findIncludes(state, &( (*node)->nodeData.loop.bodyNode )) != 0 ) return 1; break; case ConditionNode: if ( findIncludes(state, &( (*node)->nodeData.condition.ifNode )) != 0 || - findIncludes(state, &( (*node)->nodeData.condition.elseNode )) != 0 ) + findIncludes(state, &( (*node)->nodeData.condition.elseNode )) != 0 || + findIncludes(state, &( (*node)->nodeData.condition.expressionNode )) != 0 ) return 1; break; case CollectionNode: @@ -384,10 +419,23 @@ findIncludes(ParseState *state, TemplateNode *node) { GLCELL_DATA(cell) = chld; } break; - case ExpressionNode: /* any expression node can not include files */ + case VariableNode: + state->tmpl->templateInstanceSize += sizeof( VariableValueData ); + break; + case ExpressionNode: + GListForeach(cell, (*node)->nodeData.expression.argsNode) { + TemplateNode chld = (TemplateNode)GLCELL_DATA(cell); + + if ( findIncludes(state, &chld) != 0 ) + return 1; + GLCELL_DATA(cell) = chld; + } + break; case PrintNode: + if ( findIncludes(state, &( (*node)->nodeData.print.expressionNode )) ) + return 1; + break; case ConstNode: - case VariableNode: case TextNode: case NestNode: break; @@ -470,40 +518,47 @@ checkSpecialVariable(int flags, char *varName) { return flags; } -static VariableValue +static Offset findVariable( Template tmpl, TemplateNode loopParentNode, int flags, char *varName, int varNameLength ) { - VariableValue *pvarval; + Offset *pOffset; - if ( (pvarval = SFSFindData(&tmpl->variables, varName, varNameLength)) == NULL ) { - VariableValue pdata = mc0alloc(tmpl->templateContext, sizeof(VariableValueData)); + if ( (pOffset = SFSFindData(&tmpl->variables, varName, varNameLength)) == NULL ) { + Offset offset = tmpl->templateInstanceSize; + VariableValue pdata = (VariableValue)(tmpl->templateInstance + tmpl->templateInstanceSize); SFSDataIO in; in.key = varName; in.keylen = varNameLength; - in.data = &pdata; + in.data = &offset; + + tmpl->templateInstanceSize += sizeof(VariableValueData); SFSAdd(&tmpl->variables, &in); + pdata->flags = 0; + if ( loopParentNode && (flags & TND_GLOBAL) == 0 ) { /* - * copy special flags to support new inform loopParentNode + * copy special flags to support loopParentNode */ pdata->flags |= flags & TND__SPECIALMASK; pdata->type = valuePointer; + pdata->value.ptrValue = NULL; loopParentNode->nodeData.loop.listVarValues = - GListPush( loopParentNode->nodeData.loop.listVarValues, pdata ); + GListPush( loopParentNode->nodeData.loop.listVarValues, (void*)offset ); } - return pdata; + return offset; } - return *pvarval; + return *pOffset; } static int addLoop(Template tmpl, TemplateNode node, TemplateNode loopParentNode) { - SFSDataIO in; + SFSDataIO in; + LoopTemplateInstance lti; if ( SFSFindData(&tmpl->variables, node->nodeData.loop.varName, node->nodeData.loop.varNameLength) != NULL ) { tlog(TL_CRIT,"Loop marked '%s' is already defined", node->nodeData.loop.varName); @@ -512,10 +567,18 @@ addLoop(Template tmpl, TemplateNode node, TemplateNode loopParentNode) { in.key = node->nodeData.loop.varName; in.keylen = node->nodeData.loop.varNameLength; - in.data = &node; + in.data = &tmpl->templateInstanceSize; SFSAdd(&tmpl->variables, &in); + node->nodeData.loop.loopDataOffset = tmpl->templateInstanceSize; + lti = (LoopTemplateInstance)(tmpl->templateInstance + tmpl->templateInstanceSize); + memset(lti, 0, sizeof( LoopTemplateInstanceData )); + lti->type = LoopData; + lti->loopNode = node; + + tmpl->templateInstanceSize += sizeof( LoopTemplateInstanceData ); + if ( loopParentNode ) { loopParentNode->nodeData.loop.childrenLoop = GListPush( loopParentNode->nodeData.loop.childrenLoop, node ); @@ -603,7 +666,7 @@ compileTree( Template tmpl, TemplateNode node, TemplateNode loopParentNode ) { node->nodeData.variable.varName, &node->nodeData.variable.varNameLength); - node->nodeData.variable.value = findVariable( tmpl, loopParentNode, + node->nodeData.variable.varValueOffset = findVariable( tmpl, loopParentNode, node->nodeData.variable.flags, node->nodeData.variable.varName, node->nodeData.variable.varNameLength ); @@ -647,7 +710,7 @@ initTemplate( Template tmpl, MemoryContext *mc, executeFunctionDesc functions, c memset(tmpl, 0, sizeof(TemplateData)); tmpl->templateContext = mc; - SFSInit_dp(&tmpl->variables, sizeof(void*), NULL); + SFSInit_dp(&tmpl->variables, sizeof(Offset), NULL); if ( functions ) { executeFunctionDesc ptr = functions; @@ -667,6 +730,9 @@ initTemplate( Template tmpl, MemoryContext *mc, executeFunctionDesc functions, c if ( (err=recursiveReadTemplate(&state, NULL, filename))!=0 ) return err; + + tmpl->templateInstance = mcalloc( tmpl->templateContext, tmpl->templateInstanceSize ); + tmpl->templateInstanceSize = 0; if ( (err=compileTree( tmpl, tmpl->tree, NULL ))!=0 ) return err; @@ -674,41 +740,9 @@ initTemplate( Template tmpl, MemoryContext *mc, executeFunctionDesc functions, c } /* - * Reset/cleanup + * cleanup */ -void -resetTemplate( Template tmpl ) { - SFSDataIO out; - GListCell *cell; - - SFSIteratorStart( &tmpl->variables ); - - while( SFSIterate( &tmpl->variables, &out ) ) { - VariableValue varval = *(VariableValue*) out.data; - - if ( varval->type >= valueInt ) - varval->flags &= ~TND_DEFINED; - else if ( varval->type == LoopNode ) { - TemplateNode node = (TemplateNode) varval; - - GListForeach( cell, node->nodeData.loop.listVarValues ) { - varval = (VariableValue) GLCELL_DATA(cell); - - if ( varval->type == valuePointer ) - varval->value.ptrValue = NULL; - } - - GListForeach( cell, node->nodeData.loop.listInstance ) { - LoopInstance instance = GLCELL_DATA(cell); - - GListFree(instance->rowValues ); - } - GListTruncate( node->nodeData.loop.listInstance, 0 ); - } - } -} - static void freeNode( TemplateNode node ) { GListCell *cell; @@ -721,13 +755,6 @@ freeNode( TemplateNode node ) { freeNode( node->nodeData.loop.bodyNode ); /* selfNode is somewhere inside bodyNode */ GListFree( node->nodeData.loop.childrenLoop ); GListFree( node->nodeData.loop.listVarValues ); - - GListForeach( cell, node->nodeData.loop.listInstance ) { - LoopInstance instance = GLCELL_DATA(cell); - - GListFree(instance->rowValues ); - } - GListFree( node->nodeData.loop.listInstance ); break; case CollectionNode: GListForeach( cell, node->nodeData.children ) @@ -769,135 +796,174 @@ freeTemplate( Template tmpl ) { * Set value routines */ +TemplateInstance +newTemplateInstance(Template tmpl, MemoryContext *mc) { + TemplateInstance ti; + + if (mc == NULL) + mc = tmpl->templateContext; + + ti = mcalloc(mc, sizeof(TemplateInstanceData) + tmpl->templateInstanceSize); + ti->tmpl = tmpl; + ti->templateContext = mc; + memcpy( ti->instanceData, tmpl->templateInstance, tmpl->templateInstanceSize); + + return ti; +} + static void -newLoopInstance( Template tmpl, TemplateNode node ) { - LoopInstance upper = NULL; +newLoopInstance( TemplateInstance tmpl, TemplateNode node ) { + LoopInstance upper = NULL; + LoopTemplateInstance loopData = (LoopTemplateInstance) + (tmpl->instanceData + node->nodeData.loop.loopDataOffset); - if ( node->nodeData.loop.currentInstance ) - upper = node->nodeData.loop.currentInstance->upperInstance; + if ( loopData->currentInstance ) + upper = loopData->currentInstance->upperInstance; - node->nodeData.loop.currentInstance = + loopData->currentInstance = mc0alloc(tmpl->templateContext, sizeof(LoopInstanceData) ); - node->nodeData.loop.currentInstance->upperInstance = upper; + loopData->currentInstance->upperInstance = upper; - node->nodeData.loop.listInstance = GListPush( - node->nodeData.loop.listInstance, - node->nodeData.loop.currentInstance ); + TListPush( loopData, loopData->currentInstance ); - node->nodeData.loop.lastRow = NULL; + loopData->lastRow = NULL; } int -addTemplateRow( Template tmpl, char * key) { - TemplateNode *pnode, node; +addTemplateRow( TemplateInstance tmpl, char * key) { + Offset *pOffset; + TemplateNode node; + LoopTemplateInstance loopData; char *lkey = strlower(mcstrdup(tmpl->templateContext, key)); GListCell *cell; int i=0, nvar; LoopRow rowData; - pnode = SFSFindData(&tmpl->variables, lkey, 0); + pOffset = SFSFindData(&tmpl->tmpl->variables, lkey, 0); mcfree(lkey); - if ( pnode == NULL ) + if ( pOffset == NULL ) return TVAR_NOTFOUND; - node = *pnode; + loopData = (LoopTemplateInstance)(tmpl->instanceData + *pOffset); - if ( node->type != LoopNode ) + if ( loopData->type != LoopData ) return TVAR_FORBIDDEN; + node = loopData->loopNode; + + tassert( *pOffset == node->nodeData.loop.loopDataOffset ); nvar = GLIST_LENGTH( node->nodeData.loop.listVarValues ); if ( nvar == 0 ) /* loop without vars can not be looped */ return TVAR_NOROW; - if ( GLIST_LENGTH(node->nodeData.loop.listInstance) == 0 ) + if ( TListIsEmpty(loopData) ) newLoopInstance(tmpl, node); GListForeach( cell, node->nodeData.loop.childrenLoop ) newLoopInstance( tmpl, GLCELL_DATA(cell) ); - node->nodeData.loop.lastRow = rowData = mcalloc( tmpl->templateContext, LRDHDRSZ + sizeof(VariableValueData) * nvar ); + loopData->lastRow = rowData = mcalloc( tmpl->templateContext, LRDHDRSZ + sizeof(VariableValueData) * nvar ); rowData->loop = node; rowData->nestedInstance = NULL; GListForeach( cell, node->nodeData.loop.listVarValues ) { - VariableValue vv = GLCELL_DATA(cell); + VariableValue vv = (VariableValue) (tmpl->instanceData + ((Offset)GLCELL_DATA(cell))); vv->value.ptrValue = rowData->varvals + i; rowData->varvals[i].flags = 0; i++; } - node->nodeData.loop.currentInstance->nrow++; - node->nodeData.loop.currentInstance->rowValues = - GListPush( node->nodeData.loop.currentInstance->rowValues, rowData ); + loopData->currentInstance->nrow++; + TListPush( loopData->currentInstance, rowData ); return TVAR_OK; } int -addTemplateNestedLoop( Template tmpl, char * key) { - TemplateNode *pnode, node; +addTemplateNestedLoop( TemplateInstance tmpl, char * key) { + Offset *pOffset; + TemplateNode node; + LoopTemplateInstance loopData; char *lkey = strlower(mcstrdup(tmpl->templateContext, key)); GListCell *cell; - pnode = SFSFindData(&tmpl->variables, lkey, 0); + pOffset = SFSFindData(&tmpl->tmpl->variables, lkey, 0); mcfree(lkey); - if ( pnode == NULL ) + if ( pOffset == NULL ) return TVAR_NOTFOUND; - node = *pnode; + loopData = (LoopTemplateInstance)(tmpl->instanceData + *pOffset); - if ( node->type != LoopNode || node->nodeData.loop.selfNode == 0 ) + if ( loopData->type != LoopData ) return TVAR_FORBIDDEN; + node = loopData->loopNode; - if ( GLIST_LENGTH(node->nodeData.loop.listInstance) == 0 || node->nodeData.loop.lastRow == NULL ) + if ( node->nodeData.loop.selfNode == NULL ) + return TVAR_FORBIDDEN; + + if ( TListIsEmpty(loopData) || loopData->lastRow == NULL ) return TVAR_NOROW; - GListForeach( cell, node->nodeData.loop.childrenLoop ) - ((TemplateNode)GLCELL_DATA(cell))->nodeData.loop.lastRow = NULL; + GListForeach( cell, node->nodeData.loop.childrenLoop ) { + LoopTemplateInstance childData = (LoopTemplateInstance) + (tmpl->instanceData + ((TemplateNode)GLCELL_DATA(cell))->nodeData.loop.loopDataOffset); + + childData->lastRow = NULL; + } - node->nodeData.loop.lastRow->nestedInstance = + loopData->lastRow->nestedInstance = mc0alloc(tmpl->templateContext, sizeof(LoopInstanceData) ); - node->nodeData.loop.lastRow->nestedInstance->upperInstance = - node->nodeData.loop.currentInstance; - node->nodeData.loop.currentInstance = - node->nodeData.loop.lastRow->nestedInstance; - node->nodeData.loop.lastRow = NULL; + loopData->lastRow->nestedInstance->upperInstance = + loopData->currentInstance; + loopData->currentInstance = + loopData->lastRow->nestedInstance; + loopData->lastRow = NULL; return TVAR_OK; } int -returnTemplateNestedLoop( Template tmpl, char * key) { - TemplateNode *pnode, node; +returnTemplateNestedLoop( TemplateInstance tmpl, char * key) { + Offset *pOffset; + TemplateNode node; + LoopTemplateInstance loopData; char *lkey = strlower(mcstrdup(tmpl->templateContext, key)); GListCell *cell; - pnode = SFSFindData(&tmpl->variables, lkey, 0); + pOffset = SFSFindData(&tmpl->tmpl->variables, lkey, 0); mcfree(lkey); - if ( pnode == NULL ) + if ( pOffset == NULL ) return TVAR_NOTFOUND; - node = *pnode; + loopData = (LoopTemplateInstance)(tmpl->instanceData + *pOffset); - if ( node->type != LoopNode || node->nodeData.loop.selfNode == 0 ) + if ( loopData->type != LoopData ) return TVAR_FORBIDDEN; + node = loopData->loopNode; - if ( GLIST_LENGTH(node->nodeData.loop.listInstance) == 0 ) + if ( node->nodeData.loop.selfNode == NULL ) + return TVAR_FORBIDDEN; + + if ( TListIsEmpty(loopData) ) return TVAR_NOROW; - if ( node->nodeData.loop.currentInstance == NULL ) + if ( loopData->currentInstance == NULL ) return TVAR_NOROW; - GListForeach( cell, node->nodeData.loop.childrenLoop ) - ((TemplateNode)GLCELL_DATA(cell))->nodeData.loop.lastRow = NULL; + GListForeach( cell, node->nodeData.loop.childrenLoop ) { + LoopTemplateInstance childData = (LoopTemplateInstance) + (tmpl->instanceData + ((TemplateNode)GLCELL_DATA(cell))->nodeData.loop.loopDataOffset); + + childData->lastRow = NULL; + } - node->nodeData.loop.currentInstance = node->nodeData.loop.currentInstance->upperInstance; - node->nodeData.loop.lastRow = NULL; + loopData->currentInstance = loopData->currentInstance->upperInstance; + loopData->lastRow = NULL; return TVAR_OK; @@ -906,17 +972,18 @@ returnTemplateNestedLoop( Template tmpl, char * key) { static VariableValueData storage; static int -setTemplateValue( Template tmpl, char *key) { - VariableValue *pvarval, varval; +setTemplateValue( TemplateInstance tmpl, char *key) { + Offset *pOffset; + VariableValue varval; char *lkey = strlower(mcstrdup(tmpl->templateContext, key)); - pvarval = SFSFindData(&tmpl->variables, lkey, 0); + pOffset = SFSFindData(&tmpl->tmpl->variables, lkey, 0); mcfree(lkey); - if ( pvarval == NULL ) + if ( pOffset == NULL ) return TVAR_NOTFOUND; - varval = *pvarval; + varval = (VariableValue)(tmpl->instanceData + *pOffset); if ( varval->type != 0 && varval->type < valueInt ) { return TVAR_LOOPMARK; @@ -946,7 +1013,7 @@ setTemplateValue( Template tmpl, char *key) { int -setTemplateValueInt( Template tmpl, char * key, int val ) { +setTemplateValueInt( TemplateInstance tmpl, char * key, int val ) { storage.flags = TND_DEFINED; storage.type = valueInt; storage.value.intValue = val; @@ -954,7 +1021,7 @@ setTemplateValueInt( Template tmpl, char * key, int val ) { } int -setTemplateValueString( Template tmpl, char * key, char * val ) { +setTemplateValueString( TemplateInstance tmpl, char * key, char * val ) { storage.flags = TND_DEFINED; storage.type = valueString; storage.value.stringValue = val; @@ -962,7 +1029,7 @@ setTemplateValueString( Template tmpl, char * key, char * val ) { } int -setTemplateValueTime( Template tmpl, char * key, time_t val ) { +setTemplateValueTime( TemplateInstance tmpl, char * key, time_t val ) { storage.flags = TND_DEFINED; storage.type = valueTime; storage.value.timeValue = val; @@ -970,7 +1037,7 @@ setTemplateValueTime( Template tmpl, char * key, time_t val ) { } int -setTemplateValueBool( Template tmpl, char * key, int val ) { +setTemplateValueBool( TemplateInstance tmpl, char * key, int val ) { storage.flags = TND_DEFINED; storage.type = valueBool; storage.value.boolValue = val; @@ -978,7 +1045,7 @@ setTemplateValueBool( Template tmpl, char * key, int val ) { } int -setTemplateValueDouble( Template tmpl, char * key, double val ) { +setTemplateValueDouble( TemplateInstance tmpl, char * key, double val ) { storage.flags = TND_DEFINED; storage.type = valueDouble; storage.value.boolValue = val; @@ -986,7 +1053,7 @@ setTemplateValueDouble( Template tmpl, char * key, double val ) { } int -setTemplateValueUndefined( Template tmpl, char * key ) { +setTemplateValueUndefined( TemplateInstance tmpl, char * key ) { storage.flags = 0; return setTemplateValue( tmpl, key ); } @@ -996,7 +1063,7 @@ setTemplateValueUndefined( Template tmpl, char * key ) { */ static char * -printVal( Template tmpl, VariableValue value, int *len, char *format ) { +printVal( TemplateInstance tmpl, VariableValue value, int *len, char *format ) { int printedlen; char *res; @@ -1065,7 +1132,7 @@ printVal( Template tmpl, VariableValue value, int *len, char *format ) { static VariableValue -executeExpression( Template tmpl, TemplateNode node ) { +executeExpression( TemplateInstance tmpl, TemplateNode node ) { VariableValue outvalue = NULL; GListCell *cell; int i = 0; @@ -1076,10 +1143,12 @@ executeExpression( Template tmpl, TemplateNode node ) { outvalue = &node->nodeData.value; break; case VariableNode: - if ( node->nodeData.variable.value->type == valuePointer ) - outvalue = node->nodeData.variable.value->value.ptrValue; - else - outvalue = node->nodeData.variable.value; + outvalue = (VariableValue)(tmpl->instanceData + node->nodeData.variable.varValueOffset); + + tassert( (outvalue->flags & TND_DEFINED) == 0 || (outvalue->type >= valueInt && outvalue->type <= valuePointer) ); + + if ( outvalue->type == valuePointer ) + outvalue = outvalue->value.ptrValue; break; case ExpressionNode: GListForeach(cell, node->nodeData.expression.argsNode) @@ -1110,7 +1179,7 @@ executeExpression( Template tmpl, TemplateNode node ) { } static void -printNode( Template tmpl, TemplateNode node, LoopInstance loopInstance ) { +printNode( TemplateInstance tmpl, TemplateNode node, LoopInstance loopInstance ) { GListCell *cell; VariableValue value; int i; @@ -1121,18 +1190,17 @@ printNode( Template tmpl, TemplateNode node, LoopInstance loopInstance ) { switch (node->type) { case LoopNode: { + LoopTemplateInstance loopData = (LoopTemplateInstance) + (tmpl->instanceData + node->nodeData.loop.loopDataOffset); GListCell *cell; LoopInstance instance; if ( loopInstance ) { instance = loopInstance; } else { - cell = GListShift( node->nodeData.loop.listInstance ); - if ( cell == NULL ) + TListShift( loopData, instance ); + if ( instance == NULL ) return; - - instance = GLCELL_DATA(cell); - GListFreeCell( node->nodeData.loop.listInstance, cell ); } for(i=0; inrow;i++) { @@ -1140,12 +1208,10 @@ printNode( Template tmpl, TemplateNode node, LoopInstance loopInstance ) { int j = 0; VariableValue realValue; - cell = GListShift( instance->rowValues ); - rowData = GLCELL_DATA(cell); - GListFreeCell( instance->rowValues, cell ); + TListShift( instance, rowData ); GListForeach( cell, node->nodeData.loop.listVarValues ) { - value = (VariableValue)GLCELL_DATA(cell); + value = (VariableValue) (tmpl->instanceData + ((Offset)GLCELL_DATA(cell))); tassert( value->type == valuePointer ); realValue = value->value.ptrValue = rowData->varvals+j; @@ -1194,8 +1260,6 @@ printNode( Template tmpl, TemplateNode node, LoopInstance loopInstance ) { printNode( tmpl, node->nodeData.loop.bodyNode, NULL ); } - - GListFree( instance->rowValues ); } break; case NestNode: @@ -1213,14 +1277,13 @@ printNode( Template tmpl, TemplateNode node, LoopInstance loopInstance ) { i=0; GListForeach( cell, node->nodeData.nest.childrenLoopAfterSelf) { TemplateNode chld = GLCELL_DATA(cell); - GListCell *cellInstance = GListShift( chld->nodeData.loop.listInstance ); + LoopTemplateInstance loopData = (LoopTemplateInstance) + (tmpl->instanceData + chld->nodeData.loop.loopDataOffset); + LoopInstance cellInstance; - if ( cellInstance == NULL ) - savedChildrenInstance[i++] = NULL; - else { - savedChildrenInstance[i++] = GLCELL_DATA(cellInstance); - GListFreeCell( chld->nodeData.loop.listInstance, cellInstance ); - } + TListShift( loopData, cellInstance ); + + savedChildrenInstance[i++] = cellInstance; } } @@ -1231,7 +1294,8 @@ printNode( Template tmpl, TemplateNode node, LoopInstance loopInstance ) { */ i=0; GListForeach( cell, node->nodeData.nest.loop->nodeData.loop.listVarValues ) { - ((VariableValue)GLCELL_DATA(cell))->value.ptrValue = savedRowData->varvals + i; + value = (VariableValue) (tmpl->instanceData + ((Offset)GLCELL_DATA(cell))); + value->value.ptrValue = savedRowData->varvals + i; i++; } @@ -1239,9 +1303,11 @@ printNode( Template tmpl, TemplateNode node, LoopInstance loopInstance ) { i=0; GListForeach( cell, node->nodeData.nest.childrenLoopAfterSelf) { TemplateNode chld = GLCELL_DATA(cell); + LoopTemplateInstance loopData = (LoopTemplateInstance) + (tmpl->instanceData + chld->nodeData.loop.loopDataOffset); if ( savedChildrenInstance[i] ) - GListUnshift( chld->nodeData.loop.listInstance, savedChildrenInstance[i]); + TListUnShift( loopData, savedChildrenInstance[i] ); i++; } } @@ -1268,22 +1334,22 @@ printNode( Template tmpl, TemplateNode node, LoopInstance loopInstance ) { res = printVal(tmpl, value, &len, node->nodeData.print.formatValue); - if ( (node->nodeData.variable.flags & TND_HTMLESCAPE) && tmpl->htmlEscape ) - res = tmpl->htmlEscape(res, &len); - if ( (node->nodeData.variable.flags & TND_URLESCAPE) && tmpl->urlEscape ) - res = tmpl->urlEscape(res, &len); + if ( (node->nodeData.variable.flags & TND_HTMLESCAPE) && tmpl->tmpl->htmlEscape ) + res = tmpl->tmpl->htmlEscape(res, &len); + if ( (node->nodeData.variable.flags & TND_URLESCAPE) && tmpl->tmpl->urlEscape ) + res = tmpl->tmpl->urlEscape(res, &len); if ( res && len>0 ) { - tmpl->printString( res, len ); + tmpl->tmpl->printString( res, len ); mcfree(res); } } else if ( node->nodeData.print.defaultValue ) { - tmpl->printString( node->nodeData.print.defaultValue, + tmpl->tmpl->printString( node->nodeData.print.defaultValue, strlen( node->nodeData.print.defaultValue ) ); } break; case TextNode: - tmpl->printString( node->nodeData.text.value, node->nodeData.text.valueLength ); + tmpl->tmpl->printString( node->nodeData.text.value, node->nodeData.text.valueLength ); break; case IncludeNode: case VariableNode: @@ -1298,11 +1364,11 @@ printNode( Template tmpl, TemplateNode node, LoopInstance loopInstance ) { } int -printTemplate( Template tmpl ) { - if (!tmpl->printString) +printTemplate( TemplateInstance tmpl ) { + if (!tmpl->tmpl->printString) return 1; - printNode(tmpl, tmpl->tree, NULL); + printNode(tmpl, tmpl->tmpl->tree, NULL); return 0; } diff --git a/template.h b/template.h index 7953de4..cd80d75 100644 --- a/template.h +++ b/template.h @@ -116,9 +116,11 @@ * 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() call and provide temporary memory context for usual work. - * after printTemplate is called it's needed to call resetTemplate() and - * then resetMemoryContext() for second 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. * ******************************************************************************/ @@ -143,6 +145,7 @@ typedef enum TemplateNodeType { PrintNode, ConstNode, NestNode, + LoopData, /* value's types of variables */ valueInt = 200, /* smallest of any values type */ @@ -170,6 +173,8 @@ typedef enum TemplateNodeType { typedef struct TemplateData *Template; +typedef struct TemplateInstanceData *TemplateInstance; + typedef struct TemplateNodeData *TemplateNode; typedef struct VariableValueData * VariableValue; @@ -192,7 +197,7 @@ 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; @@ -202,6 +207,7 @@ typedef struct LoopRowData *LoopRow; typedef struct LoopRowData { TemplateNode loop; LoopInstance nestedInstance; + LoopRow nextCell; VariableValueData varvals[1]; } LoopRowData; #define LRDHDRSZ (offsetof(LoopRowData, varvals)) @@ -209,9 +215,26 @@ typedef struct LoopRowData { typedef struct LoopInstanceData { int nrow; LoopInstance upperInstance; - GList *rowValues; /*list of LoopRow */ + + 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 */ @@ -226,7 +249,8 @@ typedef struct TemplateNodeData { struct { char *varName; int varNameLength; - VariableValue value; + Offset varValueOffset; + /* VariableValue value; */ int flags; } variable; @@ -268,16 +292,7 @@ typedef struct TemplateNodeData { TemplateNode selfNode; /* pointer to self-nested plase to insert */ GList *childrenLoop; /* to reset loop's instance */ GList *listVarValues; /* list of loop variables */ - GList *listInstance; - /* listInstace -+ - +->instance-+ - +->row - | - | - +->row->currentInstance - */ - LoopRow lastRow; - LoopInstance currentInstance; + Offset loopDataOffset; } loop; /* ConditionNode */ @@ -307,13 +322,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) @@ -321,14 +345,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 addTemplateNestedLoop( Template tmpl, char * key); -int returnTemplateNestedLoop( Template tmpl, char * key); +int setTemplateValueInt( TemplateInstance tmpl, char * key, int 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 diff --git a/tmpltest.c b/tmpltest.c index a605f0b..57d4491 100644 --- a/tmpltest.c +++ b/tmpltest.c @@ -57,7 +57,7 @@ outfunc(char *str, int len) { static int counter = 0; static VariableValue -localCounter(Template tmpl, int nargs, VariableValue *args) { +localCounter(TemplateInstance tmpl, int nargs, VariableValue *args) { VariableValue out = tmalloc(sizeof(VariableValue)); out->type = valueInt; @@ -75,6 +75,7 @@ main(int argn, char *argv[]) { MemoryContext *base; char *name = NULL; TemplateData template; + TemplateInstance tinstance; int i,j,k; int cnt=0; executeFunctionDescData funcs[] = { @@ -108,93 +109,94 @@ main(int argn, char *argv[]) { printf("initTemplate: %d\n", initTemplate(&template, base, funcs, ".", name) ); /* dumpTemplate(&template); */ - setTemplateValueInt(&template, "ID", 17); - setTemplateValueUndefined(&template, "emptyID"); - setTemplateValueInt(&template, "zeroid", 0); - setTemplateValueString(&template, "str", "QWERTY"); + tinstance = newTemplateInstance(&template, NULL); - addTemplateRow(&template, "outerLoop"); - setTemplateValueString(&template, "outerLoop.data1", "ha1"); - setTemplateValueUndefined(&template, "outerLoop.data2"); + setTemplateValueInt(tinstance, "ID", 17); + setTemplateValueUndefined(tinstance, "emptyID"); + setTemplateValueInt(tinstance, "zeroid", 0); + setTemplateValueString(tinstance, "str", "QWERTY"); - addTemplateRow(&template, "outerLoop"); - setTemplateValueInt(&template, "outerLoop.data1", 10); - setTemplateValueString(&template, "outerLoop.data2", "WOW"); - addTemplateRow(&template, "outerLoop.innerLoop"); - setTemplateValueString(&template, "outerLoop.innerLoop.camenty", "Number 1"); - addTemplateRow(&template, "outerLoop.innerLoop"); - setTemplateValueString(&template, "outerLoop.innerLoop.camenty", "Number 2"); + addTemplateRow(tinstance, "outerLoop"); + setTemplateValueString(tinstance, "outerLoop.data1", "ha1"); + setTemplateValueUndefined(tinstance, "outerLoop.data2"); - addTemplateRow(&template, "outerLoop"); - setTemplateValueString(&template, "outerLoop.data1", "ha3"); + addTemplateRow(tinstance, "outerLoop"); + setTemplateValueInt(tinstance, "outerLoop.data1", 10); + setTemplateValueString(tinstance, "outerLoop.data2", "WOW"); + addTemplateRow(tinstance, "outerLoop.innerLoop"); + setTemplateValueString(tinstance, "outerLoop.innerLoop.camenty", "Number 1"); + addTemplateRow(tinstance, "outerLoop.innerLoop"); + setTemplateValueString(tinstance, "outerLoop.innerLoop.camenty", "Number 2"); + + addTemplateRow(tinstance, "outerLoop"); + setTemplateValueString(tinstance, "outerLoop.data1", "ha3"); template.printString = outfunc; - printTemplate( &template ); + printTemplate( tinstance ); - resetTemplate(&template); + tinstance = newTemplateInstance(&template, NULL); - setTemplateValueInt(&template, "ID", 23); - setTemplateValueUndefined(&template, "emptyID"); - setTemplateValueInt(&template, "zeroid", 0); - addTemplateRow(&template, "outerLoop"); - setTemplateValueString(&template, "outerLoop.data1", "ha1"); - setTemplateValueInt(&template, "outerLoop.data1", 1234); - setTemplateValueString(&template, "outerLoop.data2", "FOO"); - addTemplateRow(&template, "outerLoop.innerLoop"); - setTemplateValueString(&template, "outerLoop.innerLoop.camenty", "Again 1"); + setTemplateValueInt(tinstance, "ID", 23); + setTemplateValueUndefined(tinstance, "emptyID"); + setTemplateValueInt(tinstance, "zeroid", 0); + addTemplateRow(tinstance, "outerLoop"); + setTemplateValueString(tinstance, "outerLoop.data1", "ha1"); + setTemplateValueInt(tinstance, "outerLoop.data1", 1234); + setTemplateValueString(tinstance, "outerLoop.data2", "FOO"); + addTemplateRow(tinstance, "outerLoop.innerLoop"); + setTemplateValueString(tinstance, "outerLoop.innerLoop.camenty", "Again 1"); for(i=0;i<3;i++) { - addTemplateRow(&template,"selfLoop"); - setTemplateValueInt(&template, "selfLoop.CNT", ++cnt); - setTemplateValueString(&template, "selfLoop.NODE", "outer"); + addTemplateRow(tinstance,"selfLoop"); + setTemplateValueInt(tinstance, "selfLoop.CNT", ++cnt); + setTemplateValueString(tinstance, "selfLoop.NODE", "outer"); if (i<1) { - addTemplateRow(&template,"selfLoop.oneloop"); - setTemplateValueInt(&template, "selfLoop.oneloop.CNT", ++cnt); - setTemplateValueString(&template, "selfLoop.oneloop.NODE", "subloop1"); + addTemplateRow(tinstance,"selfLoop.oneloop"); + setTemplateValueInt(tinstance, "selfLoop.oneloop.CNT", ++cnt); + setTemplateValueString(tinstance, "selfLoop.oneloop.NODE", "subloop1"); } if (i<2) { - addTemplateRow(&template,"selfLoop.oneloop"); - setTemplateValueInt(&template, "selfLoop.oneloop.CNT", ++cnt); - setTemplateValueString(&template, "selfLoop.oneloop.NODE", "subloop2"); + addTemplateRow(tinstance,"selfLoop.oneloop"); + setTemplateValueInt(tinstance, "selfLoop.oneloop.CNT", ++cnt); + setTemplateValueString(tinstance, "selfLoop.oneloop.NODE", "subloop2"); } - addTemplateNestedLoop(&template, "selfLoop"); + addTemplateNestedLoop(tinstance, "selfLoop"); for(j=0;j<2;j++) { - addTemplateRow(&template,"selfLoop"); - setTemplateValueInt(&template, "selfLoop.CNT", ++cnt); - setTemplateValueString(&template, "selfLoop.NODE", "inner"); + addTemplateRow(tinstance,"selfLoop"); + setTemplateValueInt(tinstance, "selfLoop.CNT", ++cnt); + setTemplateValueString(tinstance, "selfLoop.NODE", "inner"); if ( i==1 && j==0 ) { - addTemplateRow(&template,"selfLoop.oneloop"); - setTemplateValueInt(&template, "selfLoop.oneloop.CNT", ++cnt); - setTemplateValueString(&template, "selfLoop.oneloop.NODE", "subloop3"); + addTemplateRow(tinstance,"selfLoop.oneloop"); + setTemplateValueInt(tinstance, "selfLoop.oneloop.CNT", ++cnt); + setTemplateValueString(tinstance, "selfLoop.oneloop.NODE", "subloop3"); } if (i==2 && j==1) { - addTemplateNestedLoop(&template, "selfLoop"); + addTemplateNestedLoop(tinstance, "selfLoop"); for(k=0;k<4;k++) { - addTemplateRow(&template,"selfLoop"); - setTemplateValueInt(&template, "selfLoop.CNT", ++cnt); - setTemplateValueString(&template, "selfLoop.NODE", "innerst"); + addTemplateRow(tinstance,"selfLoop"); + setTemplateValueInt(tinstance, "selfLoop.CNT", ++cnt); + setTemplateValueString(tinstance, "selfLoop.NODE", "innerst"); if ( k==2 ) { - addTemplateRow(&template,"selfLoop.oneloop"); - setTemplateValueInt(&template, "selfLoop.oneloop.CNT", ++cnt); - setTemplateValueString(&template, "selfLoop.oneloop.NODE", "subloop4"); + addTemplateRow(tinstance,"selfLoop.oneloop"); + setTemplateValueInt(tinstance, "selfLoop.oneloop.CNT", ++cnt); + setTemplateValueString(tinstance, "selfLoop.oneloop.NODE", "subloop4"); } } - returnTemplateNestedLoop(&template, "selfLoop"); + returnTemplateNestedLoop(tinstance, "selfLoop"); } } - returnTemplateNestedLoop(&template, "selfLoop"); + returnTemplateNestedLoop(tinstance, "selfLoop"); } fputs("================================================\n", stdout); - printTemplate( &template ); + printTemplate( tinstance ); - resetTemplate(&template); freeTemplate(&template); return 0;