1/*
2 This file is part of the Grantlee 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#ifndef GRANTLEE_SAFESTRING_H
22#define GRANTLEE_SAFESTRING_H
23
24#include "grantlee_core_export.h"
25
26#include <QtCore/QString>
27#include <QtCore/QVariant>
28
29namespace Grantlee
30{
31
32/// @headerfile safestring.h grantlee/safestring.h
33
34/**
35 @brief A QString wrapper class for containing whether a string is safe or needs to be escaped.
36
37 This allows lazy escaping of strings. Otherwise a string may be escaped multiple times where it
38 should only be escaped once.
39
40 The SafeString class itself provides information about whether a string is safe from further escaping through the isSafe method. The actual string content held by the SafeString instance is available through the get() method. The get() method returns a QString subclass which should be used like any other QString. The difference is that all methods on NestedString return a SafeString instead of a QString.
41
42 @code
43 SafeString s("this & that", SafeString::IsSafe);
44 s.get().replace( "this", "these" ).toUpper();
45
46 qDebug() << s.get() << s.isSafe(); // outputs "these & that" false
47 @endcode
48
49 Note that most operations on strings make the string unsafe. For example, while <tt>"K &amp; R"</tt> is safe, using replace("m", "n") will result in <tt>"K &anp; R"</tt>, which is unsafe. Likewise using upper() will return <tt>"K &AMP; R"</tt>, which is unsafe. Because the SafeString can not determine whether a method call with particular arguments will change a SafeString from being safe to being unsafe, any operation which can possibly make the string unsafe does cause the string to become unsafe. It is then up to the caller to restore safe-ness if needed.
50
51 NestedString has overloads for SafeStrings whereever appropriate so that strings remain marked as safe where possible.
52
53 For example:
54
55 @code
56 SafeString s1("this & that", SafeString::IsSafe);
57 s2 = s1;
58 s1.append( QString( " & the other" ) );
59 // s1 is now "this & that & the other" and is unsafe.
60
61 SafeString s3(" Wobl & Bob", SafeString::IsSafe);
62 s2.append(s3);
63 // Both s2 and s3 are safe, and append is a safe operation, so s2 is still safe
64 @endcode
65
66 @see @ref autoescaping
67 @see OutputStream::escape
68
69 SafeString has appropriate operator overloads to make it convenient to use in methods returning a QVariant, such as Filter::doFilter, or as a QString. Note that a raw QString is essentially the same as a SafeString which is marked as unsafe.
70
71 @author Stephen Kelly <steveire@gmail.com>
72*/
73class GRANTLEE_CORE_EXPORT SafeString
74{
75public:
76 /**
77 Possible safety states of a SafeString
78 */
79 enum Safety {
80 IsSafe, ///< The string is safe and requires no further escaping
81 IsNotSafe ///< The string is not safe. It will be escaped before being added to the output of rendering.
82 };
83
84 /**
85 Constructs an empty SafeString.
86 */
87 SafeString();
88
89 /**
90 Copy constructor
91 */
92 SafeString( const SafeString &safeString );
93
94 /**
95 Constructs a SafeString with the content @p str whose safety is given by @p safe.
96 */
97 SafeString( const QString &str, bool safe );
98
99 /**
100 Constructs a SafeString with the content @p str whose safety is given by @p safety.
101 */
102 /* implicit */ SafeString( const QString &str, Safety safety = IsNotSafe ); // krazy:exclude=explicit
103
104 /**
105 Destructor
106 */
107 ~SafeString();
108
109#ifndef Q_QDOC
110 /**
111 Set whether the string should be escaped.
112 */
113 void setNeedsEscape( bool needsEscape );
114#endif
115
116 /**
117 Whether the string needs to be escaped.
118 */
119 bool needsEscape() const;
120
121 /**
122 Whether the string is safe.
123 */
124 bool isSafe() const;
125
126#ifndef Q_QDOC
127 /**
128 Set whether the string is safe.
129 */
130 void setSafety( Safety safety );
131#endif
132
133 /**
134 @brief The NestedString is a QString whose methods always return a SafeString
135
136 This class is largely an implementation detail. See the SafeString documentation for details.
137 */
138 class GRANTLEE_CORE_EXPORT NestedString : public QString
139 {
140#ifndef Q_QDOC
141 friend class SafeString;
142 SafeString *m_safeString;
143 public:
144 NestedString( SafeString *safeString );
145 NestedString( const QString &content, SafeString *safeString );
146
147 SafeString& append( const SafeString &str );
148 SafeString& append( const QString &str );
149 SafeString& append( const QStringRef &reference );
150 SafeString& append( const QLatin1String &str );
151 // BIC: Use QT_NO_CAST_FROM_ASCII instead.
152#ifndef GRANTLEE_NO_CAST_FROM_ASCII
153 SafeString& append( const QByteArray &ba );
154 SafeString& append( const char *str );
155#endif
156 SafeString& append( const QChar ch );
157
158 SafeString& fill( QChar ch, int size = -1 );
159
160 SafeString& insert( int position, const SafeString &str );
161 SafeString& insert( int position, const QString &str );
162 SafeString& insert( int position, const QLatin1String &str );
163 SafeString& insert( int position, const QChar *unicode, int size );
164 SafeString& insert( int position, QChar ch );
165
166 SafeString left( int n ) const;
167 SafeString leftJustified( int width, QChar fill = QLatin1Char( ' ' ), bool truncate = false ) const;
168 SafeString mid( int position, int n = -1 ) const;
169
170 SafeString normalized( NormalizationForm mode ) const;
171 SafeString normalized( NormalizationForm mode, QChar::UnicodeVersion version ) const;
172
173 SafeString& prepend( const SafeString &str );
174 SafeString& prepend( const QString &str );
175 SafeString& prepend( const QLatin1String &str );
176#ifndef GRANTLEE_NO_CAST_FROM_ASCII
177 SafeString& prepend( const QByteArray &ba );
178 SafeString& prepend( const char *str );
179#endif
180 SafeString& prepend( QChar ch );
181
182 void push_back( const SafeString& other );
183 void push_front( const SafeString& other );
184
185 SafeString& remove( int position, int n );
186 SafeString& remove( QChar ch, Qt::CaseSensitivity cs = Qt::CaseSensitive );
187 SafeString& remove( const SafeString &str, Qt::CaseSensitivity cs = Qt::CaseSensitive );
188 SafeString& remove( const QString &str, Qt::CaseSensitivity cs = Qt::CaseSensitive );
189 SafeString& remove( const QRegExp &rx );
190 SafeString repeated( int times ) const;
191 SafeString& replace( int position, int n, const SafeString &after );
192 SafeString& replace( int position, int n, const QString &after );
193 SafeString& replace( int position, int n, const QChar *unicode, int size );
194 SafeString& replace( int position, int n, QChar after );
195 SafeString& replace( const SafeString &before, const SafeString &after, Qt::CaseSensitivity cs = Qt::CaseSensitive );
196 SafeString& replace( const QString &before, const SafeString &after, Qt::CaseSensitivity cs = Qt::CaseSensitive );
197 SafeString& replace( const SafeString &before, const QString &after, Qt::CaseSensitivity cs = Qt::CaseSensitive );
198 SafeString& replace( const QString &before, const QString &after, Qt::CaseSensitivity cs = Qt::CaseSensitive );
199 SafeString& replace( const QChar *before, int blen, const QChar *after, int alen, Qt::CaseSensitivity cs = Qt::CaseSensitive );
200 SafeString& replace( QChar ch, const SafeString &after, Qt::CaseSensitivity cs = Qt::CaseSensitive );
201 SafeString& replace( QChar ch, const QString &after, Qt::CaseSensitivity cs = Qt::CaseSensitive );
202 SafeString& replace( QChar before, QChar after, Qt::CaseSensitivity cs = Qt::CaseSensitive );
203 SafeString& replace( const QLatin1String &before, const QLatin1String &after, Qt::CaseSensitivity cs = Qt::CaseSensitive );
204 SafeString& replace( const QLatin1String &before, const SafeString &after, Qt::CaseSensitivity cs = Qt::CaseSensitive );
205 SafeString& replace( const QLatin1String &before, const QString &after, Qt::CaseSensitivity cs = Qt::CaseSensitive );
206 SafeString& replace( const SafeString &before, const QLatin1String &after, Qt::CaseSensitivity cs = Qt::CaseSensitive );
207 SafeString& replace( const QString &before, const QLatin1String &after, Qt::CaseSensitivity cs = Qt::CaseSensitive );
208 SafeString& replace( QChar c, const QLatin1String &after, Qt::CaseSensitivity cs = Qt::CaseSensitive );
209 SafeString& replace( const QRegExp &rx, const SafeString &after );
210 SafeString& replace( const QRegExp &rx, const QString &after );
211
212 SafeString right( int n ) const;
213 SafeString rightJustified( int width, QChar fill = QLatin1Char( ' ' ), bool truncate = false ) const;
214
215 SafeString section( QChar sep, int start, int end = -1, SectionFlags flags = SectionDefault ) const;
216 SafeString section( const SafeString& sep, int start, int end = -1, SectionFlags flags = SectionDefault ) const;
217 SafeString section( const QString& sep, int start, int end = -1, SectionFlags flags = SectionDefault ) const;
218 SafeString section( const QRegExp& reg, int start, int end = -1, SectionFlags flags = SectionDefault ) const;
219 SafeString& setNum( int n, int base = 10 );
220 SafeString& setNum( uint n, int base = 10 );
221 SafeString& setNum( long n, int base = 10 );
222 SafeString& setNum( ulong n, int base = 10 );
223 SafeString& setNum( qlonglong n, int base = 10 );
224 SafeString& setNum( qulonglong n, int base = 10 );
225 SafeString& setNum( short n, int base = 10 );
226 SafeString& setNum( ushort n, int base = 10 );
227 SafeString& setNum( double n, char format = 'g', int precision = 6 );
228 SafeString& setNum( float n, char format = 'g', int precision = 6 );
229 SafeString& setUnicode( const QChar * unicode, int size );
230 SafeString& setUtf16( const ushort * unicode, int size );
231 SafeString simplified() const;
232
233 QStringList split( const SafeString& sep, SplitBehavior behavior = KeepEmptyParts, Qt::CaseSensitivity cs = Qt::CaseSensitive ) const;
234 QStringList split( const QString& sep, SplitBehavior behavior = KeepEmptyParts, Qt::CaseSensitivity cs = Qt::CaseSensitive ) const;
235 QStringList split( const QChar & sep, SplitBehavior behavior = KeepEmptyParts, Qt::CaseSensitivity cs = Qt::CaseSensitive ) const;
236 QStringList split( const QRegExp & rx, SplitBehavior behavior = KeepEmptyParts ) const;
237
238 SafeString toLower() const;
239 SafeString toUpper() const;
240 SafeString trimmed() const;
241
242 void chop( int n );
243#endif
244 };
245
246 /**
247 Returns the String held by this SafeString
248 */
249 const NestedString& get() const {
250 return m_nestedString;
251 }
252
253 /**
254 Returns the String held by this SafeString
255 */
256 NestedString& get() {
257 return m_nestedString;
258 }
259
260 /**
261 Convenience operator for treating a SafeString like a QString.
262 */
263 operator QString() const {
264 return m_nestedString;
265 }
266
267 /**
268 Assignment operator.
269 */
270 SafeString &operator=( const SafeString &str );
271
272 /**
273 Returns a concatenation of this with @p str.
274
275 The result is not safe because str is not safe.
276 */
277 SafeString operator+( const QString &str );
278
279 /**
280 Returns a concatenation of this with @p str.
281
282 The result is safe if both this and str are safe.
283 */
284 SafeString operator+( const SafeString &str );
285
286 /**
287 Appends the content of @p str to this.
288
289 The result is not safe because @p str is not safe.
290 */
291 SafeString &operator+=( const QString &str );
292
293 /**
294 Appends the content of @p str to this.
295
296 The result is safe if both this and @p str are safe.
297 */
298 SafeString &operator+=( const SafeString &str );
299
300 /**
301 Returns true if the content of @p other matches the content of this.
302
303 Safeness and needing escaping are not accounted for in the comparison.
304 */
305 bool operator==( const SafeString &other ) const;
306
307 /**
308 Returns true if the content of @p other matches the content of this.
309
310 Safeness and needing escaping are not accounted for in the comparison.
311 */
312 bool operator==( const QString &other ) const;
313
314 /**
315 Convenience operator for storing a SafeString in a QVariant.
316 */
317 operator QVariant() const {
318 return QVariant::fromValue( *this );
319 }
320
321private:
322#ifndef Q_QDOC
323 NestedString m_nestedString;
324#endif
325 Safety m_safety;
326 bool m_needsescape;
327};
328
329}
330
331Q_DECLARE_METATYPE( Grantlee::SafeString )
332
333#endif
334
335