Cutelee  6.1.0
range.cpp
1 /*
2  This file is part of the Cutelee template system.
3 
4  Copyright (c) 2009,2010 Stephen Kelly <steveire@gmail.com>
5 
6  This library is free software; you can redistribute it and/or
7  modify it under the terms of the GNU Lesser General Public
8  License as published by the Free Software Foundation; either version
9  2.1 of the Licence, or (at your option) any later version.
10 
11  This library is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  Lesser General Public License for more details.
15 
16  You should have received a copy of the GNU Lesser General Public
17  License along with this library. If not, see <http://www.gnu.org/licenses/>.
18 
19 */
20 
21 #include "range.h"
22 
23 #include "engine.h"
24 #include "exception.h"
25 #include "parser.h"
26 #include "util.h"
27 
28 RangeNodeFactory::RangeNodeFactory() {}
29 
31  Parser *p) const
32 {
33  auto expr = smartSplit(tagContent);
34 
35  expr.takeAt(0);
36  auto numArgs = expr.size();
37  if (numArgs != 1) {
38  if (numArgs <= 2) {
39  throw Cutelee::Exception(
40  TagSyntaxError,
41  QStringLiteral("'range' tag requires at least three arguments"));
42  }
43 
44  if (expr.at(numArgs - 2) != QStringLiteral("as")) {
45  throw Cutelee::Exception(
46  TagSyntaxError, QStringLiteral("Invalid arguments to 'range' tag"));
47  }
48  }
49 
50  const auto name = (numArgs > 2) ? expr.at(numArgs - 1) : QString();
51  if (numArgs > 2)
52  numArgs -= 2;
53 
54  RangeNode *n = 0;
55 
56  switch (numArgs) {
57  case 1:
58  n = new RangeNode(name, FilterExpression(QChar::fromLatin1('0'), p),
59  FilterExpression(expr.first(), p), p);
60  break;
61  case 2:
62  n = new RangeNode(name, FilterExpression(expr.first(), p),
63  FilterExpression(expr.at(1), p), p);
64  break;
65  case 3:
66  n = new RangeNode(name, FilterExpression(expr.first(), p),
67  FilterExpression(expr.at(1), p),
68  FilterExpression(expr.at(2), p), p);
69  break;
70  default:
71  return 0;
72  }
73 
74  auto list = p->parse(n, QStringLiteral("endrange"));
75  p->removeNextToken();
76 
77  n->setNodeList(list);
78  return n;
79 }
80 
81 RangeNode::RangeNode(const QString &name,
82  const FilterExpression &startExpression,
83  const FilterExpression &stopExpression, QObject *parent)
84  : Node(parent), m_name(name), m_startExpression(startExpression),
85  m_stopExpression(stopExpression)
86 {
87 }
88 
89 RangeNode::RangeNode(const QString &name,
90  const FilterExpression &startExpression,
91  const FilterExpression &stopExpression,
92  const FilterExpression &stepExpression, QObject *parent)
93  : Node(parent), m_name(name), m_startExpression(startExpression),
94  m_stopExpression(stopExpression), m_stepExpression(stepExpression)
95 {
96 }
97 
98 void RangeNode::setNodeList(const NodeList &list) { m_list = list; }
99 
100 void RangeNode::render(OutputStream *stream, Context *c) const
101 {
102  int start;
103  int stop;
104  int step;
105 
106  start = m_startExpression.resolve(c).value<int>();
107  stop = m_stopExpression.resolve(c).value<int>();
108 
109  if (m_stepExpression.isValid()) {
110  step = m_stepExpression.resolve(c).value<int>();
111  } else {
112  step = 1;
113  }
114 
115  const auto insertContext = !m_name.isEmpty();
116 
117  Q_ASSERT(start < stop);
118 
119  for (auto i = start; i < stop; i += step) {
120  if (insertContext) {
121  c->push();
122  c->insert(m_name, i);
123  }
124  m_list.render(stream, c);
125  if (insertContext)
126  c->pop();
127  }
128 }
Q_INVOKABLE QStringList smartSplit(const QString &str) const
Definition: node.cpp:202
The Context class holds the context to render a Template with.
Definition: context.h:119
void insert(const QString &name, QObject *object)
Definition: context.cpp:145
An exception for use when implementing template tags.
Definition: exception.h:85
A FilterExpression object represents a filter expression in a template.
QVariant resolve(OutputStream *stream, Context *c) const
A list of Nodes with some convenience API for rendering them.
Definition: node.h:148
void render(OutputStream *stream, Context *c) const
Definition: node.cpp:177
Base class for all nodes.
Definition: node.h:78
The OutputStream class is used to render templates to a QTextStream.
Definition: outputstream.h:81
The Parser class processes a string template into a tree of nodes.
Definition: parser.h:49
NodeList parse(Node *parent, const QStringList &stopAt={})
Definition: parser.cpp:180
void removeNextToken()
Definition: parser.cpp:297
Node * getNode(const QString &tagContent, Parser *p) const override
Definition: range.cpp:30
void render(OutputStream *stream, Context *c) const override
Definition: range.cpp:100
Utility functions used throughout Cutelee.