File indexing completed on 2025-02-09 04:28:40
0001 /* 0002 This file is part of the KTextTemplate library 0003 0004 SPDX-FileCopyrightText: 2009, 2010 Stephen Kelly <steveire@gmail.com> 0005 0006 SPDX-License-Identifier: LGPL-2.1-or-later 0007 0008 */ 0009 0010 #ifndef KTEXTTEMPLATE_SAFESTRING_H 0011 #define KTEXTTEMPLATE_SAFESTRING_H 0012 0013 #include "ktexttemplate_export.h" 0014 0015 #include <QString> 0016 #include <QVariant> 0017 0018 namespace KTextTemplate 0019 { 0020 0021 /// @headerfile safestring.h <KTextTemplate/SafeString> 0022 0023 /** 0024 @brief A QString wrapper class for containing whether a string is safe or 0025 needs to be escaped. 0026 0027 This allows lazy escaping of strings. Otherwise a string may be escaped 0028 multiple times where it should only be escaped once. 0029 0030 The **%SafeString** class itself provides information about whether a string 0031 is safe from further escaping through the @ref isSafe method. The actual 0032 string content held by the **%SafeString** instance is available through the 0033 @ref get method. The @ref get method returns a QString subclass which should 0034 be used like any other QString. The difference is that all methods on 0035 NestedString return a **%SafeString** instead of a QString. 0036 0037 @code 0038 SafeString s("this & that", SafeString::IsSafe); 0039 s.get().replace( "this", "these" ).toUpper(); 0040 0041 qDebug() << s.get() << s.isSafe(); // outputs "these & that" false 0042 @endcode 0043 0044 Note that most operations on strings make the string unsafe. For example, 0045 while <tt>"K & R"</tt> is safe, using replace("m", "n") will result in 0046 <tt>"K &anp; R"</tt>, which is unsafe. Likewise using upper() will return 0047 <tt>"K & R"</tt>, which is unsafe. Because the **%SafeString** can not 0048 determine whether a method call with particular arguments will change 0049 a **%SafeString** from being safe to being unsafe, any operation which can 0050 possibly make the string unsafe does cause the string to become unsafe. It is 0051 then up to the caller to restore safe-ness if needed. 0052 0053 NestedString has overloads for SafeStrings whereever appropriate so that 0054 strings remain marked as safe where possible. 0055 0056 For example: 0057 0058 @code 0059 SafeString s1("this & that", SafeString::IsSafe); 0060 s2 = s1; 0061 s1.append( QString( " & the other" ) ); 0062 // s1 is now "this & that & the other" and is unsafe. 0063 0064 SafeString s3(" Wobl & Bob", SafeString::IsSafe); 0065 s2.append(s3); 0066 // Both s2 and s3 are safe, and append is a safe operation, so s2 0067 // is still safe 0068 @endcode 0069 0070 @see @ref autoescaping 0071 @see OutputStream::escape 0072 0073 The **%SafeString** class has appropriate operator overloads to make it 0074 convenient to use in methods returning a QVariant, such as Filter::doFilter, 0075 or as a QString. Note that a raw QString is essentially the same 0076 as a **%SafeString** which is marked as unsafe. 0077 0078 @author Stephen Kelly <steveire@gmail.com> 0079 */ 0080 class KTEXTTEMPLATE_EXPORT SafeString 0081 { 0082 public: 0083 /** 0084 Possible safety states of a **%SafeString** 0085 */ 0086 enum Safety { 0087 IsSafe, ///< The string is safe and requires no further escaping 0088 IsNotSafe ///< The string is not safe. It will be escaped before being 0089 /// added to the output of rendering. 0090 }; 0091 0092 /** 0093 Constructs an empty **%SafeString**. 0094 */ 0095 SafeString(); 0096 0097 /** 0098 Copy constructor 0099 */ 0100 SafeString(const SafeString &safeString); 0101 0102 /** 0103 Constructs a **%SafeString** with the content @p str whose safety is given 0104 by @p safe. 0105 */ 0106 SafeString(const QString &str, bool safe); 0107 0108 /** 0109 Constructs a **%SafeString** with the content @p str whose safety is given 0110 by @p safety. 0111 */ 0112 /* implicit */ SafeString(const QString &str, 0113 Safety safety = IsNotSafe); // krazy:exclude=explicit 0114 0115 /** 0116 Destructor 0117 */ 0118 ~SafeString(); 0119 0120 #ifndef K_DOXYGEN 0121 /** 0122 Set whether the string should be escaped. 0123 */ 0124 void setNeedsEscape(bool needsEscape); 0125 #endif 0126 0127 /** 0128 Whether the string needs to be escaped. 0129 */ 0130 bool needsEscape() const; 0131 0132 /** 0133 Whether the string is safe. 0134 */ 0135 bool isSafe() const; 0136 0137 #ifndef K_DOXYGEN 0138 /** 0139 Set whether the string is safe. 0140 */ 0141 void setSafety(Safety safety); 0142 #endif 0143 0144 /** 0145 @brief The NestedString is a QString whose methods always return a 0146 SafeString 0147 0148 This class is largely an implementation detail. See the SafeString 0149 documentation for details. 0150 */ 0151 class KTEXTTEMPLATE_EXPORT NestedString : public QString 0152 { 0153 #ifndef K_DOXYGEN 0154 friend class SafeString; 0155 SafeString *m_safeString; 0156 0157 public: 0158 explicit NestedString(SafeString *safeString); 0159 NestedString(const QString &content, SafeString *safeString); 0160 0161 SafeString &append(const SafeString &str); 0162 SafeString &append(const QString &str); 0163 SafeString &append(const QLatin1String &str); 0164 #ifndef QT_NO_CAST_FROM_ASCII 0165 SafeString &append(const QByteArray &ba) 0166 { 0167 QString::append(ba); 0168 m_safeString->m_safety = IsNotSafe; 0169 return *m_safeString; 0170 } 0171 0172 SafeString &append(const char *str) 0173 { 0174 QString::append(str); 0175 m_safeString->m_safety = IsNotSafe; 0176 return *m_safeString; 0177 } 0178 #endif 0179 SafeString &append(const QChar ch); 0180 0181 SafeString &fill(QChar ch, int size = -1); 0182 0183 SafeString &insert(int position, const SafeString &str); 0184 SafeString &insert(int position, const QString &str); 0185 SafeString &insert(int position, const QLatin1String &str); 0186 SafeString &insert(int position, const QChar *unicode, int size); 0187 SafeString &insert(int position, QChar ch); 0188 0189 SafeString left(int n) const; 0190 SafeString leftJustified(int width, QChar fill = QLatin1Char(' '), bool truncate = {}) const; 0191 SafeString mid(int position, int n = -1) const; 0192 0193 SafeString normalized(NormalizationForm mode) const; 0194 SafeString normalized(NormalizationForm mode, QChar::UnicodeVersion version) const; 0195 0196 SafeString &prepend(const SafeString &str); 0197 SafeString &prepend(const QString &str); 0198 SafeString &prepend(const QLatin1String &str); 0199 #ifndef QT_NO_CAST_FROM_ASCII 0200 SafeString &prepend(const QByteArray &ba) 0201 { 0202 QString::prepend(ba); 0203 m_safeString->m_safety = IsNotSafe; 0204 return *m_safeString; 0205 } 0206 0207 SafeString &prepend(const char *str) 0208 { 0209 QString::prepend(str); 0210 m_safeString->m_safety = IsNotSafe; 0211 return *m_safeString; 0212 } 0213 #endif 0214 SafeString &prepend(QChar ch); 0215 0216 void push_back(const SafeString &other); 0217 void push_front(const SafeString &other); 0218 0219 SafeString &remove(int position, int n); 0220 SafeString &remove(QChar ch, Qt::CaseSensitivity cs = Qt::CaseSensitive); 0221 SafeString &remove(const SafeString &str, Qt::CaseSensitivity cs = Qt::CaseSensitive); 0222 SafeString &remove(const QString &str, Qt::CaseSensitivity cs = Qt::CaseSensitive); 0223 SafeString &remove(const QRegularExpression &rx); 0224 SafeString repeated(int times) const; 0225 SafeString &replace(int position, int n, const SafeString &after); 0226 SafeString &replace(int position, int n, const QString &after); 0227 SafeString &replace(int position, int n, const QChar *unicode, int size); 0228 SafeString &replace(int position, int n, QChar after); 0229 SafeString &replace(const SafeString &before, const SafeString &after, Qt::CaseSensitivity cs = Qt::CaseSensitive); 0230 SafeString &replace(const QString &before, const SafeString &after, Qt::CaseSensitivity cs = Qt::CaseSensitive); 0231 SafeString &replace(const SafeString &before, const QString &after, Qt::CaseSensitivity cs = Qt::CaseSensitive); 0232 SafeString &replace(const QString &before, const QString &after, Qt::CaseSensitivity cs = Qt::CaseSensitive); 0233 SafeString &replace(const QChar *before, int blen, const QChar *after, int alen, Qt::CaseSensitivity cs = Qt::CaseSensitive); 0234 SafeString &replace(QChar ch, const SafeString &after, Qt::CaseSensitivity cs = Qt::CaseSensitive); 0235 SafeString &replace(QChar ch, const QString &after, Qt::CaseSensitivity cs = Qt::CaseSensitive); 0236 SafeString &replace(QChar before, QChar after, Qt::CaseSensitivity cs = Qt::CaseSensitive); 0237 SafeString &replace(const QLatin1String &before, const QLatin1String &after, Qt::CaseSensitivity cs = Qt::CaseSensitive); 0238 SafeString &replace(const QLatin1String &before, const SafeString &after, Qt::CaseSensitivity cs = Qt::CaseSensitive); 0239 SafeString &replace(const QLatin1String &before, const QString &after, Qt::CaseSensitivity cs = Qt::CaseSensitive); 0240 SafeString &replace(const SafeString &before, const QLatin1String &after, Qt::CaseSensitivity cs = Qt::CaseSensitive); 0241 SafeString &replace(const QString &before, const QLatin1String &after, Qt::CaseSensitivity cs = Qt::CaseSensitive); 0242 SafeString &replace(QChar c, const QLatin1String &after, Qt::CaseSensitivity cs = Qt::CaseSensitive); 0243 SafeString &replace(const QRegularExpression &rx, const SafeString &after); 0244 SafeString &replace(const QRegularExpression &rx, const QString &after); 0245 0246 SafeString right(int n) const; 0247 SafeString rightJustified(int width, QChar fill = QLatin1Char(' '), bool truncate = {}) const; 0248 0249 SafeString section(QChar sep, int start, int end = -1, SectionFlags flags = SectionDefault) const; 0250 SafeString section(const SafeString &sep, int start, int end = -1, SectionFlags flags = SectionDefault) const; 0251 SafeString section(const QString &sep, int start, int end = -1, SectionFlags flags = SectionDefault) const; 0252 SafeString section(const QRegularExpression ®, int start, int end = -1, SectionFlags flags = SectionDefault) const; 0253 SafeString &setNum(int n, int base = 10); 0254 SafeString &setNum(uint n, int base = 10); 0255 SafeString &setNum(long n, int base = 10); 0256 SafeString &setNum(ulong n, int base = 10); 0257 SafeString &setNum(qlonglong n, int base = 10); 0258 SafeString &setNum(qulonglong n, int base = 10); 0259 SafeString &setNum(short n, int base = 10); 0260 SafeString &setNum(ushort n, int base = 10); 0261 SafeString &setNum(double n, char format = 'g', int precision = 6); 0262 SafeString &setNum(float n, char format = 'g', int precision = 6); 0263 SafeString &setUnicode(const QChar *unicode, int size); 0264 SafeString &setUtf16(const ushort *unicode, int size); 0265 SafeString simplified() const; 0266 0267 QStringList split(const SafeString &sep, Qt::SplitBehavior behavior = Qt::KeepEmptyParts, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; 0268 QStringList split(const QString &sep, Qt::SplitBehavior behavior = Qt::KeepEmptyParts, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; 0269 QStringList split(const QChar &sep, Qt::SplitBehavior behavior = Qt::KeepEmptyParts, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; 0270 QStringList split(const QRegularExpression &rx, Qt::SplitBehavior behavior = Qt::KeepEmptyParts) const; 0271 0272 SafeString toLower() const; 0273 SafeString toUpper() const; 0274 SafeString trimmed() const; 0275 0276 void chop(int n); 0277 #endif 0278 }; 0279 0280 /** 0281 Returns the String held by this **%SafeString** 0282 */ 0283 const NestedString &get() const 0284 { 0285 return m_nestedString; 0286 } 0287 0288 /** 0289 Returns the String held by this **%SafeString** 0290 */ 0291 NestedString &get() 0292 { 0293 return m_nestedString; 0294 } 0295 0296 /** 0297 Convenience operator for treating a **%SafeString** like a QString. 0298 */ 0299 operator QString() const 0300 { 0301 return m_nestedString; 0302 } 0303 0304 /** 0305 Assignment operator. 0306 */ 0307 SafeString &operator=(const SafeString &str); 0308 0309 /** 0310 Returns a concatenation of this with @p str. 0311 0312 The result is not safe because str is not safe. 0313 */ 0314 SafeString operator+(const QString &str); 0315 0316 /** 0317 Returns a concatenation of this with @p str. 0318 0319 The result is safe if both this and str are safe. 0320 */ 0321 SafeString operator+(const SafeString &str); 0322 0323 /** 0324 Appends the content of @p str to this. 0325 0326 The result is not safe because @p str is not safe. 0327 */ 0328 SafeString &operator+=(const QString &str); 0329 0330 /** 0331 Appends the content of @p str to this. 0332 0333 The result is safe if both this and @p str are safe. 0334 */ 0335 SafeString &operator+=(const SafeString &str); 0336 0337 /** 0338 Returns true if the content of @p other matches the content of this. 0339 0340 Safeness and needing escaping are not accounted for in the comparison. 0341 */ 0342 bool operator==(const SafeString &other) const; 0343 0344 /** 0345 Returns true if the content of @p other matches the content of this. 0346 0347 Safeness and needing escaping are not accounted for in the comparison. 0348 */ 0349 bool operator==(const QString &other) const; 0350 0351 /** 0352 Convenience operator for storing a **%SafeString** in a QVariant. 0353 */ 0354 operator QVariant() const 0355 { 0356 return QVariant::fromValue(*this); 0357 } 0358 0359 private: 0360 #ifndef K_DOXYGEN 0361 NestedString m_nestedString; 0362 #endif 0363 Safety m_safety; 0364 bool m_needsescape; 0365 }; 0366 } 0367 0368 Q_DECLARE_METATYPE(KTextTemplate::SafeString) 0369 0370 #endif