1 /*
2 SPDX-FileCopyrightText: 2007-2009 Sergio Pistone <sergio_pistone@yahoo.com.ar>
3 SPDX-FileCopyrightText: 2010-2019 Mladen Milinkovic <max@smoothware.net>
4
5 SPDX-License-Identifier: GPL-2.0-or-later
6 */
7
8 #ifndef SSTRING_H
9 #define SSTRING_H
10
11 #include <string.h>
12
13 #include <QString>
14 #include <QRegExp>
15 #include <QList>
16 #include <QColor>
17 #include <QDataStream>
18
19 #include <QDebug>
20
21 void * memset_n(void *ptr, int value, size_t length, size_t size);
22
23 namespace SubtitleComposer {
24 class SString;
25
26 class SStringList : public QList<SString>
27 {
28 public:
29 SStringList();
30 SStringList(const SString &str);
31 SStringList(const SStringList &list);
32 SStringList(const QList<SString> &list);
33 SStringList(const QStringList &list);
34 SStringList(const QList<QString> &list);
35
36 SString join(const SString &sep) const;
37
38 SStringList& operator=(const SStringList& other) = default;
39 };
40
41 class SString : public QString
42 {
43 public:
44 typedef enum {
45 Bold = 0x1,
46 Italic = 0x2,
47 Underline = 0x4,
48 StrikeThrough = 0x8,
49 Color = 0x10,
50 AllStyles = Bold | Italic | Underline | StrikeThrough | Color
51 } StyleFlag;
52
53 typedef enum {
54 Compact,
55 Verbose
56 } RichOutputMode;
57
58 SString(const QString &string = QString(), int styleFlags = 0, QRgb styleColor = 0); // krazy:exclude=c++/explicit
59 SString(const SString &sstring);
60 SString & operator=(const SString &sstring);
61
62 ~SString();
63
string()64 inline QString string() const { return *this; }
65 void setString(const QString &string, int styleFlags = 0, QRgb styleColor = 0); // always clears all the style flags
66
67 QString richString(RichOutputMode mode = Compact) const;
68 SString & setRichString(const QString &string);
69
70 int styleFlagsAt(int index) const;
71 void setStyleFlagsAt(int index, int styleFlags) const;
72 QRgb styleColorAt(int index) const;
73 void setStyleColorAt(int index, QRgb rgbColor) const;
74
75 int cummulativeStyleFlags() const;
76 bool hasStyleFlags(int styleFlags) const;
77 SString & setStyleFlags(int index, int len, int styleFlags);
78 SString & setStyleFlags(int index, int len, int styleFlags, bool on);
79 SString & setStyleColor(int index, int len, QRgb color);
80
81 void clear();
82
83 SString & insert(int index, QChar ch);
84 SString & insert(int index, const QString &str);
85 SString & insert(int index, const SString &str);
86 SString & append(QChar ch);
87 SString & append(const QString &str);
88 SString & append(const SString &str);
89 SString & prepend(QChar ch);
90 SString & prepend(const QString &str);
91 SString & prepend(const SString &str);
92 SString & operator+=(QChar ch);
93 SString & operator+=(const QString &str);
94 SString & operator+=(const SString &str);
95
96 SString & remove(int index, int len);
97 SString & remove(const QString &str, Qt::CaseSensitivity cs = Qt::CaseSensitive);
98 SString & remove(QChar ch, Qt::CaseSensitivity cs = Qt::CaseSensitive);
99 SString & remove(const QRegExp &rx);
100
101 SString & replace(int index, int len, const QString &replacement);
102 SString & replace(int index, int len, const SString &replacement);
103 SString & replace(const QString &before, const QString &after, Qt::CaseSensitivity cs = Qt::CaseSensitive);
104 SString & replace(const QString &before, const SString &after, Qt::CaseSensitivity cs = Qt::CaseSensitive);
105 SString & replace(QChar before, QChar after, Qt::CaseSensitivity cs = Qt::CaseSensitive);
106 SString & replace(QChar ch, const QString &after, Qt::CaseSensitivity cs = Qt::CaseSensitive);
107 SString & replace(QChar ch, const SString &after, Qt::CaseSensitivity cs = Qt::CaseSensitive);
108 SString & replace(const QRegExp ®Exp, const QString &replacement);
109 SString & replace(const QRegExp ®Exp, const SString &replacement);
110 SString & replace(const QRegularExpression ®Exp, const QString &replacement);
111 SString & replace(const QRegularExpression ®Exp, const SString &replacement, bool styleFromReplacement=true);
112
113 SStringList split(const QString &sep, QString::SplitBehavior behavior = QString::KeepEmptyParts, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
114 SStringList split(const QChar &sep, QString::SplitBehavior behavior = QString::KeepEmptyParts, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
115 SStringList split(const QRegExp &sep, QString::SplitBehavior behavior = QString::KeepEmptyParts) const;
116
117 SString left(int len) const;
118 SString right(int len) const;
119 SString mid(int index, int len = -1) const;
120
121 SString toLower() const;
122 SString toUpper() const;
123 SString toTitleCase(bool lowerFirst) const;
124 SString toSentenceCase(bool lowerFirst, bool *cont) const;
125
126 SString simplified() const;
127 SString trimmed() const;
128
129 static void simplifyWhiteSpace(QString &text);
130 void simplifyWhiteSpace();
131
132 bool operator==(const SString &sstring) const;
133 bool operator!=(const SString &sstring) const;
134
135 friend inline QDataStream & operator<<(QDataStream &stream, const SString &string);
136 friend inline QDataStream & operator>>(QDataStream &stream, SString &string);
137
length()138 inline int length() const { return QString::length(); }
139
140 private:
141 char * detachFlags();
142 QRgb * detachColors();
143 void setMinFlagsCapacity(int capacity);
144
145 int length(int index, int len) const;
146
147 private:
148 char *m_styleFlags;
149 QRgb *m_styleColors;
150 int m_capacity;
151 };
152
153 inline int
styleFlagsAt(int index)154 SString::styleFlagsAt(int index) const
155 {
156 return index < 0 || index >= length() ? 0 : m_styleFlags[index];
157 }
158
159 inline void
setStyleFlagsAt(int index,int styleFlags)160 SString::setStyleFlagsAt(int index, int styleFlags) const
161 {
162 if(index < 0 || index >= length())
163 return;
164 m_styleFlags[index] = styleFlags;
165 }
166
167 inline QRgb
styleColorAt(int index)168 SString::styleColorAt(int index) const
169 {
170 return index < 0 || index >= length() || (m_styleFlags[index] & SString::Color) == 0 ? 0 : m_styleColors[index];
171 }
172
173 inline void
setStyleColorAt(int index,QRgb rgbColor)174 SString::setStyleColorAt(int index, QRgb rgbColor) const
175 {
176 if(index < 0 || index >= length())
177 return;
178 if(rgbColor == 0)
179 m_styleFlags[index] &= ~SString::Color;
180 else
181 m_styleFlags[index] |= SString::Color;
182 m_styleColors[index] = rgbColor;
183 }
184
185 inline SString &
append(QChar ch)186 SString::append(QChar ch)
187 {
188 return insert(length(), ch);
189 }
190
191 inline SString &
append(const QString & str)192 SString::append(const QString &str)
193 {
194 return insert(length(), str);
195 }
196
197 inline SString &
append(const SString & str)198 SString::append(const SString &str)
199 {
200 return insert(length(), str);
201 }
202
203 inline SString &
prepend(QChar ch)204 SString::prepend(QChar ch)
205 {
206 return insert(0, ch);
207 }
208
209 inline SString &
prepend(const QString & str)210 SString::prepend(const QString &str)
211 {
212 return insert(0, str);
213 }
214
215 inline SString &
prepend(const SString & str)216 SString::prepend(const SString &str)
217 {
218 return insert(0, str);
219 }
220
221 inline SString &
222 SString::operator+=(const QChar ch)
223 {
224 return append(ch);
225 }
226
227 inline SString &
228 SString::operator+=(const QString &str)
229 {
230 return append(str);
231 }
232
233 inline SString &
234 SString::operator+=(const SString &str)
235 {
236 return append(str);
237 }
238
239 inline SString &
remove(int index,int len)240 SString::remove(int index, int len)
241 {
242 return replace(index, len, QString());
243 }
244
245 inline SString &
remove(const QString & str,Qt::CaseSensitivity cs)246 SString::remove(const QString &str, Qt::CaseSensitivity cs)
247 {
248 return replace(str, QString(), cs);
249 }
250
251 inline SString &
remove(QChar ch,Qt::CaseSensitivity cs)252 SString::remove(QChar ch, Qt::CaseSensitivity cs)
253 {
254 return replace(ch, QString(), cs);
255 }
256
257 inline SString &
remove(const QRegExp & rx)258 SString::remove(const QRegExp &rx)
259 {
260 return replace(rx, QString());
261 }
262
263 inline bool
264 SString::operator==(const SString &sstring) const
265 {
266 return !operator!=(sstring);
267 }
268
269 inline int
length(int index,int len)270 SString::length(int index, int len) const
271 {
272 return len < 0 || (index + len) > length() ? length() - index : len;
273 }
274
275 inline QDataStream &
276 operator<<(QDataStream &stream, const SubtitleComposer::SString &string) {
277 stream << static_cast<const QString &>(string);
278 stream.writeRawData(string.m_styleFlags, string.length() * sizeof(*string.m_styleFlags));
279 stream.writeRawData(reinterpret_cast<const char *>(string.m_styleColors), string.length() * sizeof(*string.m_styleColors));
280
281 return stream;
282 }
283
284 inline QDataStream &
285 operator>>(QDataStream &stream, SubtitleComposer::SString &string) {
286 stream >> static_cast<QString &>(string);
287 string.setMinFlagsCapacity(string.size());
288 stream.readRawData(string.m_styleFlags, string.length() * sizeof(*string.m_styleFlags));
289 stream.readRawData(reinterpret_cast<char *>(string.m_styleColors), string.length() * sizeof(*string.m_styleColors));
290
291 return stream;
292 }
293 }
294
295 #endif
296