Cutelee 6.1.0
node.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 "node.h"
22
23#include "metaenumvariable_p.h"
24#include "nodebuiltins_p.h"
25#include "template.h"
26#include "util.h"
27
28#include <QtCore/QRegularExpressionMatchIterator>
29
30using namespace Cutelee;
31
32namespace Cutelee
33{
34
36{
37 NodePrivate(Node *node) : q_ptr(node) {}
38 Q_DECLARE_PUBLIC(Node)
39 Node *const q_ptr;
40};
41
43{
44 AbstractNodeFactoryPrivate(AbstractNodeFactory *factory) : q_ptr(factory)
45 {
46#if defined(Q_CC_MSVC)
47// MSVC doesn't like static string concatenations like L"foo" "bar", as
48// results from QStringLiteral, so use QLatin1String here instead.
49#define STRING_LITERAL QLatin1String
50#else
51#define STRING_LITERAL QStringLiteral
52#endif
53 smartSplitRe = QRegularExpression(
54 STRING_LITERAL("(" // match
55 "(?:[^\\s\\\'\\\"]*" // things that are not whitespace or
56 // escaped quote chars
57 "(?:" // followed by
58 "(?:\"" // Either a quote starting with "
59 "(?:[^\"\\\\]|\\\\.)*\"" // followed by anything that is
60 // not the end of the quote
61 "|\'" // Or a quote starting with '
62 "(?:[^\'\\\\]|\\\\.)*\'" // followed by anything that is
63 // not the end of the quote
64 ")" // (End either)
65 "[^\\s\'\"]*" // To the start of the next such fragment
66 ")+" // Perform multiple matches of the above.
67 ")" // End of quoted string handling.
68 "|\\S+" // Apart from quoted strings, match
69 // non-whitespace fragments also
70 ")" // End match
71 ));
72
73#undef STRING_LITERAL
74 }
75
76 Q_DECLARE_PUBLIC(AbstractNodeFactory)
77 AbstractNodeFactory *const q_ptr;
78
79public:
80 QRegularExpression smartSplitRe;
81};
82}
83
84Node::Node(QObject *parent) : QObject(parent), d_ptr(new NodePrivate(this)) {}
85
86Node::~Node() { delete d_ptr; }
87
89 Context *c) const
90{
91 Cutelee::SafeString inputString;
92 if (input.userType() == qMetaTypeId<QVariantList>()) {
93 inputString = toString(input.value<QVariantList>());
94 } else if (input.userType() == qMetaTypeId<MetaEnumVariable>()) {
95 const auto mev = input.value<MetaEnumVariable>();
96 if (mev.value >= 0)
97 (*stream) << QString::number(mev.value);
98 } else {
99 inputString = getSafeString(input);
100 }
101 if (c->autoEscape() && !inputString.isSafe())
102 inputString.setNeedsEscape(true);
103
104 (*stream) << inputString;
105}
106
107TemplateImpl *Node::containerTemplate() const
108{
109 auto _parent = parent();
110 auto ti = qobject_cast<TemplateImpl *>(_parent);
111 while (_parent && !ti) {
112 _parent = _parent->parent();
113 ti = qobject_cast<TemplateImpl *>(_parent);
114 }
115 Q_ASSERT(ti);
116 return ti;
117}
118
119NodeList::NodeList() : QList<Cutelee::Node *>(), m_containsNonText(false) {}
120
121NodeList::NodeList(const NodeList &list) : QList<Cutelee::Node *>(list)
122{
123 m_containsNonText = list.m_containsNonText;
124}
125
126NodeList &NodeList::operator=(const NodeList &list)
127{
128 static_cast<QList<Cutelee::Node *> &>(*this)
129 = static_cast<QList<Cutelee::Node *>>(list);
130 m_containsNonText = list.m_containsNonText;
131 return *this;
132}
133
134NodeList::NodeList(const QList<Cutelee::Node *> &list)
135 : QList<Cutelee::Node *>(list)
136{
137 for (Cutelee::Node *node : list) {
138 auto textNode = qobject_cast<TextNode *>(node);
139 if (!textNode) {
140 m_containsNonText = true;
141 return;
142 }
143 }
144 m_containsNonText = false;
145}
146
148
150{
151 if (!m_containsNonText) {
152 auto textNode = qobject_cast<TextNode *>(node);
153 if (!textNode)
154 m_containsNonText = true;
155 }
156
157 QList<Cutelee::Node *>::append(node);
158}
159
160void NodeList::append(const QList<Cutelee::Node *> &nodeList)
161{
162 if (!m_containsNonText) {
163 for (const Cutelee::Node *node : nodeList) {
164 auto textNode = qobject_cast<const TextNode *>(node);
165 if (!textNode) {
166 m_containsNonText = true;
167 break;
168 }
169 }
170 }
171
172 QList<Cutelee::Node *>::append(nodeList);
173}
174
175bool NodeList::containsNonText() const { return m_containsNonText; }
176
177void NodeList::render(OutputStream *stream, Context *c) const
178{
179 for (auto i = 0; i < this->size(); ++i) {
180 this->at(i)->render(stream, c);
181 }
182}
183
185 : QObject(parent), d_ptr(new AbstractNodeFactoryPrivate(this))
186{
187}
188
190
191QList<FilterExpression>
193 Parser *p) const
194{
195 QList<FilterExpression> fes;
196 for (auto &varString : list) {
197 fes << FilterExpression(varString, p);
198 }
199 return fes;
200}
201
202QStringList AbstractNodeFactory::smartSplit(const QString &str) const
203{
204 Q_D(const AbstractNodeFactory);
205 QStringList l;
206
207 auto i = d->smartSplitRe.globalMatch(str);
208 while (i.hasNext()) {
209 auto match = i.next();
210 l.append(match.captured());
211 }
212
213 return l;
214}
Base class for all NodeFactories.
Definition node.h:300
~AbstractNodeFactory() override
Definition node.cpp:189
AbstractNodeFactory(QObject *parent={})
Definition node.cpp:184
QList< FilterExpression > getFilterExpressionList(const QStringList &list, Parser *p) const
Definition node.cpp:192
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
A FilterExpression object represents a filter expression in a template.
A list of Nodes with some convenience API for rendering them.
Definition node.h:148
bool containsNonText() const
Definition node.cpp:175
void render(OutputStream *stream, Context *c) const
Definition node.cpp:177
void append(Cutelee::Node *node)
Definition node.cpp:149
Base class for all nodes.
Definition node.h:78
void streamValueInContext(OutputStream *stream, const QVariant &input, Cutelee::Context *c) const
Definition node.cpp:88
TemplateImpl * containerTemplate() const
Definition node.cpp:107
~Node() override
Definition node.cpp:86
Node(QObject *parent={})
Definition node.cpp:84
The OutputStream class is used to render templates to a QTextStream.
The Parser class processes a string template into a tree of nodes.
Definition parser.h:49
A QString wrapper class for containing whether a string is safe or needs to be escaped.
Definition safestring.h:92
bool isSafe() const
The Cutelee namespace holds all public Cutelee API.
Definition Mainpage.dox:8
Cutelee::SafeString getSafeString(const QVariant &input)
Definition util.cpp:108
Utility functions used throughout Cutelee.