summaryrefslogtreecommitdiffstats
path: root/src/template.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/template.cpp')
-rw-r--r--src/template.cpp170
1 files changed, 162 insertions, 8 deletions
diff --git a/src/template.cpp b/src/template.cpp
index bc564cc..e3eecf9 100644
--- a/src/template.cpp
+++ b/src/template.cpp
@@ -250,7 +250,7 @@ bool TemplateVariant::toBool() const
result = p->intVal!=0;
break;
case String:
- result = !p->strVal.isEmpty() && p->strVal!="false" && p->strVal!="0";
+ result = !p->strVal.isEmpty(); // && p->strVal!="false" && p->strVal!="0";
break;
case Struct:
result = TRUE;
@@ -758,6 +758,31 @@ class FilterNoWrap
}
};
+//--------------------------------------------------------------------
+
+/** @brief The implementation of the "divisibleby" filter */
+class FilterDivisibleBy
+{
+ public:
+ static TemplateVariant apply(const TemplateVariant &v,const TemplateVariant &n)
+ {
+ printf("FilterDivisibleBy::apply()\n");
+ if (!v.isValid() || !n.isValid())
+ {
+ return TemplateVariant();
+ }
+ if (v.type()==TemplateVariant::Integer && n.type()==TemplateVariant::Integer)
+ {
+ printf("FilterDivisibleBy(%d,%d)=%d",v.toInt(),n.toInt(),(v.toInt()%n.toInt())==0);
+ return TemplateVariant((v.toInt()%n.toInt())==0);
+ }
+ else
+ {
+ return TemplateVariant();
+ }
+ }
+};
+
//--------------------------------------------------------------------
@@ -809,12 +834,14 @@ class TemplateFilterFactory
};
// register a handlers for each filter we support
-static TemplateFilterFactory::AutoRegister<FilterAdd> fAdd("add");
-static TemplateFilterFactory::AutoRegister<FilterPrepend> fPrepend("prepend");
-static TemplateFilterFactory::AutoRegister<FilterLength> fLength("length");
-static TemplateFilterFactory::AutoRegister<FilterDefault> fDefault("default");
-static TemplateFilterFactory::AutoRegister<FilterStripPath> fStripPath("stripPath");
-static TemplateFilterFactory::AutoRegister<FilterNoWrap> fNoWrap("nowrap");
+static TemplateFilterFactory::AutoRegister<FilterAdd> fAdd("add");
+static TemplateFilterFactory::AutoRegister<FilterAdd> fAppend("append");
+static TemplateFilterFactory::AutoRegister<FilterLength> fLength("length");
+static TemplateFilterFactory::AutoRegister<FilterNoWrap> fNoWrap("nowrap");
+static TemplateFilterFactory::AutoRegister<FilterDefault> fDefault("default");
+static TemplateFilterFactory::AutoRegister<FilterPrepend> fPrepend("prepend");
+static TemplateFilterFactory::AutoRegister<FilterStripPath> fStripPath("stripPath");
+static TemplateFilterFactory::AutoRegister<FilterDivisibleBy> fDivisibleBy("divisibleby");
//--------------------------------------------------------------------
@@ -1404,6 +1431,16 @@ class ExpressionParser
m_curToken.id+=s;
p++;
}
+ if (m_curToken.id=="True") // treat true literal as numerical 1
+ {
+ m_curToken.type = ExprToken::Number;
+ m_curToken.num = 1;
+ }
+ else if (m_curToken.id=="False") // treat false literal as numerical 0
+ {
+ m_curToken.type = ExprToken::Number;
+ m_curToken.num = 0;
+ }
}
else if (c=='"' || c=='\'')
{
@@ -2066,7 +2103,7 @@ class TemplateNodeBlock : public TemplateNodeCreator<TemplateNodeBlock>
}
// add 'block.super' variable to allow access to parent block content
TemplateStruct superBlock;
- superBlock.set("super",super.data());
+ superBlock.set("super",TemplateVariant(super.data(),TRUE));
ci->set("block",&superBlock);
// render the overruled block contents
nb->m_nodes.render(ts,c);
@@ -2495,6 +2532,121 @@ class TemplateNodeWith : public TemplateNodeCreator<TemplateNodeWith>
//----------------------------------------------------------
+/** @brief Class representing an 'set' tag in a template */
+class TemplateNodeCycle : public TemplateNodeCreator<TemplateNodeCycle>
+{
+ public:
+ TemplateNodeCycle(TemplateParser *parser,TemplateNode *parent,int line,const QCString &data)
+ : TemplateNodeCreator<TemplateNodeCycle>(parser,parent,line)
+ {
+ TRACE(("{TemplateNodeCycle(%s)\n",data.data()));
+ m_args.setAutoDelete(TRUE);
+ m_index=0;
+ ExpressionParser expParser(parser->templateName(),line);
+ QValueList<QCString> args = split(data," ");
+ QValueListIterator<QCString> it = args.begin();
+ while (it!=args.end())
+ {
+ ExprAst *expr = expParser.parsePrimary(*it);
+ if (expr)
+ {
+ m_args.append(expr);
+ }
+ ++it;
+ }
+ if (m_args.count()<2)
+ {
+ warn(parser->templateName(),line,"expected at least two arguments for cycle command, got %d",m_args.count());
+ }
+ TRACE(("}TemplateNodeCycle(%s)\n",data.data()));
+ }
+ void render(FTextStream &ts, TemplateContext *c)
+ {
+ TemplateContextImpl *ci = dynamic_cast<TemplateContextImpl*>(c);
+ if (m_index<m_args.count())
+ {
+ TemplateVariant v = m_args.at(m_index)->resolve(c);
+ if (v.type()==TemplateVariant::Function)
+ {
+ v = v.call(QValueList<TemplateVariant>());
+ }
+ if (ci->escapeIntf() && !v.raw())
+ {
+ ts << ci->escapeIntf()->escape(v.toString());
+ }
+ else
+ {
+ ts << v.toString();
+ }
+ }
+ if (++m_index==m_args.count()) // wrap around
+ {
+ m_index=0;
+ }
+ }
+ private:
+ uint m_index;
+ QList<ExprAst> m_args;
+};
+
+//----------------------------------------------------------
+
+/** @brief Class representing an 'set' tag in a template */
+class TemplateNodeSet : public TemplateNodeCreator<TemplateNodeSet>
+{
+ struct Mapping
+ {
+ Mapping(const QCString &n,ExprAst *e) : name(n), value(e) {}
+ ~Mapping() { delete value; }
+ QCString name;
+ ExprAst *value;
+ };
+ public:
+ TemplateNodeSet(TemplateParser *parser,TemplateNode *parent,int line,const QCString &data)
+ : TemplateNodeCreator<TemplateNodeSet>(parser,parent,line)
+ {
+ TRACE(("{TemplateNodeSet(%s)\n",data.data()));
+ m_args.setAutoDelete(TRUE);
+ ExpressionParser expParser(parser->templateName(),line);
+ QValueList<QCString> args = split(data," ");
+ QValueListIterator<QCString> it = args.begin();
+ while (it!=args.end())
+ {
+ QCString arg = *it;
+ int j=arg.find('=');
+ if (j>0)
+ {
+ ExprAst *expr = expParser.parsePrimary(arg.mid(j+1));
+ if (expr)
+ {
+ m_args.append(new Mapping(arg.left(j),expr));
+ }
+ }
+ else
+ {
+ warn(parser->templateName(),line,"invalid argument '%s' for with tag",arg.data());
+ }
+ ++it;
+ }
+ TRACE(("}TemplateNodeSet(%s)\n",data.data()));
+ }
+ void render(FTextStream &, TemplateContext *c)
+ {
+ TemplateContextImpl *ci = dynamic_cast<TemplateContextImpl*>(c);
+ QListIterator<Mapping> it(m_args);
+ Mapping *mapping;
+ for (it.toFirst();(mapping=it.current());++it)
+ {
+ TemplateVariant value = mapping->value->resolve(c);
+ ci->set(mapping->name,value);
+ }
+ }
+ private:
+ QList<Mapping> m_args;
+};
+
+//----------------------------------------------------------
+
/** @brief Class representing an 'spaceless' tag in a template */
class TemplateNodeSpaceless : public TemplateNodeCreator<TemplateNodeSpaceless>
{
@@ -2667,9 +2819,11 @@ class TemplateNodeFactory
static TemplateNodeFactory::AutoRegister<TemplateNodeIf> autoRefIf("if");
static TemplateNodeFactory::AutoRegister<TemplateNodeFor> autoRefFor("for");
static TemplateNodeFactory::AutoRegister<TemplateNodeMsg> autoRefMsg("msg");
+static TemplateNodeFactory::AutoRegister<TemplateNodeSet> autoRefSet("set");
static TemplateNodeFactory::AutoRegister<TemplateNodeTree> autoRefTree("recursetree");
static TemplateNodeFactory::AutoRegister<TemplateNodeWith> autoRefWith("with");
static TemplateNodeFactory::AutoRegister<TemplateNodeBlock> autoRefBlock("block");
+static TemplateNodeFactory::AutoRegister<TemplateNodeCycle> autoRefCycle("cycle");
static TemplateNodeFactory::AutoRegister<TemplateNodeExtend> autoRefExtend("extend");
static TemplateNodeFactory::AutoRegister<TemplateNodeCreate> autoRefCreate("create");
static TemplateNodeFactory::AutoRegister<TemplateNodeInclude> autoRefInclude("include");