1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#include <qstringlist.h>
5#include <qset.h>
6#if QT_CONFIG(regularexpression)
7# include <qregularexpression.h>
8#endif
9#include <private/qduplicatetracker_p.h>
10
11#include <algorithm>
12QT_BEGIN_NAMESPACE
13
14/*! \typedef QStringListIterator
15 \relates QStringList
16
17 The QStringListIterator type definition provides a Java-style const
18 iterator for QStringList.
19
20 QStringList provides both \l{Java-style iterators} and
21 \l{STL-style iterators}. The Java-style const iterator is simply
22 a type definition for QListIterator<QString>.
23
24 \sa QMutableStringListIterator, QStringList::const_iterator
25*/
26
27/*! \typedef QMutableStringListIterator
28 \relates QStringList
29
30 The QStringListIterator type definition provides a Java-style
31 non-const iterator for QStringList.
32
33 QStringList provides both \l{Java-style iterators} and
34 \l{STL-style iterators}. The Java-style non-const iterator is
35 simply a type definition for QMutableListIterator<QString>.
36
37 \sa QStringListIterator, QStringList::iterator
38*/
39
40/*!
41 \class QStringList
42 \inmodule QtCore
43 \brief The QStringList class provides a list of strings.
44
45 \ingroup tools
46 \ingroup shared
47 \ingroup string-processing
48
49 \reentrant
50
51 QStringList inherits from QList<QString>. Like QList, QStringList is
52 \l{implicitly shared}. It provides fast index-based access as well as fast
53 insertions and removals. Passing string lists as value parameters is both
54 fast and safe.
55
56 All of QList's functionality also applies to QStringList. For example, you
57 can use isEmpty() to test whether the list is empty, and you can call
58 functions like append(), prepend(), insert(), replace(), removeAll(),
59 removeAt(), removeFirst(), removeLast(), and removeOne() to modify a
60 QStringList. In addition, QStringList provides a few convenience
61 functions that make handling lists of strings easier:
62
63 \tableofcontents
64
65 \section1 Initializing
66
67 The default constructor creates an empty list. You can use the
68 initializer-list constructor to create a list with elements:
69
70 \snippet qstringlist/main.cpp 0a
71
72 \section1 Adding Strings
73
74 Strings can be added to a list using the \l
75 {QList::insert()}{insert()}, \l
76 {QList::append()}{append()}, \l
77 {QList::operator+=()}{operator+=()} and \l
78 {operator<<()} functions.
79
80 \l{operator<<()} can be used to
81 conveniently add multiple elements to a list:
82
83 \snippet qstringlist/main.cpp 0b
84
85 \section1 Iterating Over the Strings
86
87 See \l {Iterating over Containers}.
88
89 \section1 Manipulating the Strings
90
91 QStringList provides several functions allowing you to manipulate
92 the contents of a list. You can concatenate all the strings in a
93 string list into a single string (with an optional separator)
94 using the join() function. For example:
95
96 \snippet qstringlist/main.cpp 4
97
98 The argument to join can be a single character or a string.
99
100 To break up a string into a string list, use the QString::split()
101 function:
102
103 \snippet qstringlist/main.cpp 6
104
105 The argument to split can be a single character, a string or a
106 QRegularExpression.
107
108 In addition, the \l {QStringList::operator+()}{operator+()}
109 function allows you to concatenate two string lists into one. To
110 sort a string list, use the sort() function.
111
112 QString list also provides the filter() function which lets you
113 to extract a new list which contains only those strings which
114 contain a particular substring (or match a particular regular
115 expression):
116
117 \snippet qstringlist/main.cpp 7
118
119 The contains() function tells you whether the list contains a
120 given string, while the indexOf() function returns the index of
121 the first occurrence of the given string. The lastIndexOf()
122 function on the other hand, returns the index of the last
123 occurrence of the string.
124
125 Finally, the replaceInStrings() function calls QString::replace()
126 on each string in the string list in turn. For example:
127
128 \snippet qstringlist/main.cpp 8
129
130 \sa QString
131*/
132
133/*!
134 \fn QStringList::QStringList(const QString &str)
135
136 Constructs a string list that contains the given string, \a
137 str. Longer lists are easily created like this:
138
139 \snippet qstringlist/main.cpp 9
140
141 \sa append()
142*/
143
144/*!
145 \fn QStringList::QStringList(const QList<QString> &other)
146
147 Constructs a copy of \a other.
148
149 This operation takes \l{constant time}, because QStringList is
150 \l{implicitly shared}. This makes returning a QStringList from a
151 function very fast. If a shared instance is modified, it will be
152 copied (copy-on-write), and that takes \l{linear time}.
153
154 \sa operator=()
155*/
156
157/*!
158 \fn QStringList::QStringList(QList<QString> &&other)
159 \overload
160 \since 5.4
161
162 Move-constructs from QList<QString>.
163
164 After a successful construction, \a other will be empty.
165*/
166
167/*!
168 \fn QStringList &QStringList::operator=(const QList<QString> &other)
169 \since 5.4
170
171 Copy assignment operator from QList<QString>. Assigns the \a other
172 list of strings to this string list.
173
174 After the operation, \a other and \c *this will be equal.
175*/
176
177/*!
178 \fn QStringList &QStringList::operator=(QList<QString> &&other)
179 \overload
180 \since 5.4
181
182 Move assignment operator from QList<QString>. Moves the \a other
183 list of strings to this string list.
184
185 After the operation, \a other will be empty.
186*/
187
188/*!
189 \fn void QStringList::sort(Qt::CaseSensitivity cs)
190
191 Sorts the list of strings in ascending order.
192 If \a cs is \l Qt::CaseSensitive (the default), the string comparison
193 is case sensitive; otherwise the comparison is case insensitive.
194
195 Sorting is performed using the STL's std::sort() algorithm,
196 which averages \l{linear-logarithmic time}, i.e. O(\e{n} log \e{n}).
197
198 If you want to sort your strings in an arbitrary order, consider
199 using the QMap class. For example, you could use a QMap<QString,
200 QString> to create a case-insensitive ordering (e.g. with the keys
201 being lower-case versions of the strings, and the values being the
202 strings), or a QMap<int, QString> to sort the strings by some
203 integer index.
204*/
205
206namespace {
207struct CaseInsensitiveLessThan {
208 typedef bool result_type;
209 result_type operator()(const QString &s1, const QString &s2) const
210 {
211 return s1.compare(s: s2, cs: Qt::CaseInsensitive) < 0;
212 }
213};
214}
215
216void QtPrivate::QStringList_sort(QStringList *that, Qt::CaseSensitivity cs)
217{
218 if (cs == Qt::CaseSensitive)
219 std::sort(first: that->begin(), last: that->end());
220 else
221 std::sort(first: that->begin(), last: that->end(), comp: CaseInsensitiveLessThan());
222}
223
224
225/*!
226 \fn QStringList QStringList::filter(const QString &str, Qt::CaseSensitivity cs) const
227
228 Returns a list of all the strings containing the substring \a str.
229
230 If \a cs is \l Qt::CaseSensitive (the default), the string
231 comparison is case sensitive; otherwise the comparison is case
232 insensitive.
233
234 \snippet qstringlist/main.cpp 5
235 \snippet qstringlist/main.cpp 10
236
237 This is equivalent to
238
239 \snippet qstringlist/main.cpp 11
240 \snippet qstringlist/main.cpp 12
241
242 \sa contains()
243*/
244
245/*!
246 \fn QStringList QStringList::filter(QStringView str, Qt::CaseSensitivity cs) const
247 \overload
248 \since 5.14
249*/
250QStringList QtPrivate::QStringList_filter(const QStringList *that, QStringView str,
251 Qt::CaseSensitivity cs)
252{
253 QStringMatcher matcher(str, cs);
254 QStringList res;
255 for (qsizetype i = 0; i < that->size(); ++i)
256 if (matcher.indexIn(str: that->at(i)) != -1)
257 res << that->at(i);
258 return res;
259}
260
261template<typename T>
262static bool stringList_contains(const QStringList &stringList, const T &str, Qt::CaseSensitivity cs)
263{
264 for (const auto &string : stringList) {
265 if (string.size() == str.size() && string.compare(str, cs) == 0)
266 return true;
267 }
268 return false;
269}
270
271
272/*!
273 \fn bool QStringList::contains(const QString &str, Qt::CaseSensitivity cs) const
274
275 Returns \c true if the list contains the string \a str; otherwise
276 returns \c false. The search is case insensitive if \a cs is
277 Qt::CaseInsensitive; the search is case sensitive by default.
278
279 \sa indexOf(), lastIndexOf(), QString::contains()
280 */
281
282/*!
283 \fn bool QStringList::contains(QStringView str, Qt::CaseSensitivity cs) const
284 \overload
285 \since 5.12
286
287 Returns \c true if the list contains the string \a str; otherwise
288 returns \c false. The search is case insensitive if \a cs is
289 Qt::CaseInsensitive; the search is case sensitive by default.
290 */
291bool QtPrivate::QStringList_contains(const QStringList *that, QStringView str,
292 Qt::CaseSensitivity cs)
293{
294 return stringList_contains(stringList: *that, str, cs);
295}
296
297/*!
298 \fn bool QStringList::contains(QLatin1StringView str, Qt::CaseSensitivity cs) const
299 \overload
300 \since 5.10
301
302 Returns \c true if the list contains the Latin-1 string viewed by \a str; otherwise
303 returns \c false. The search is case insensitive if \a cs is Qt::CaseInsensitive;
304 the search is case sensitive by default.
305
306 \sa indexOf(), lastIndexOf(), QString::contains()
307 */
308bool QtPrivate::QStringList_contains(const QStringList *that, QLatin1StringView str,
309 Qt::CaseSensitivity cs)
310{
311 return stringList_contains(stringList: *that, str, cs);
312}
313
314
315#if QT_CONFIG(regularexpression)
316/*!
317 \fn QStringList QStringList::filter(const QRegularExpression &re) const
318 \overload
319 \since 5.0
320
321 Returns a list of all the strings that match the regular
322 expression \a re.
323*/
324QStringList QtPrivate::QStringList_filter(const QStringList *that, const QRegularExpression &re)
325{
326 QStringList res;
327 for (qsizetype i = 0; i < that->size(); ++i) {
328 if (that->at(i).contains(re))
329 res << that->at(i);
330 }
331 return res;
332}
333#endif // QT_CONFIG(regularexpression)
334
335/*!
336 \fn QStringList &QStringList::replaceInStrings(const QString &before, const QString &after, Qt::CaseSensitivity cs)
337
338 Returns a string list where every string has had the \a before
339 text replaced with the \a after text wherever the \a before text
340 is found. The \a before text is matched case-sensitively or not
341 depending on the \a cs flag.
342
343 For example:
344
345 \snippet qstringlist/main.cpp 5
346 \snippet qstringlist/main.cpp 13
347
348 \sa QString::replace()
349*/
350
351/*!
352 \fn QStringList &QStringList::replaceInStrings(QStringView before, const QString &after, Qt::CaseSensitivity cs)
353 \overload
354 \since 5.14
355*/
356
357/*!
358 \fn QStringList &QStringList::replaceInStrings(const QString &before, QStringView after, Qt::CaseSensitivity cs)
359 \overload
360 \since 5.14
361*/
362
363/*!
364 \fn QStringList &QStringList::replaceInStrings(QStringView before, QStringView after, Qt::CaseSensitivity cs)
365 \overload
366 \since 5.14
367*/
368void QtPrivate::QStringList_replaceInStrings(QStringList *that, QStringView before,
369 QStringView after, Qt::CaseSensitivity cs)
370{
371 for (qsizetype i = 0; i < that->size(); ++i)
372 (*that)[i].replace(before: before.data(), blen: before.size(), after: after.data(), alen: after.size(), cs);
373}
374
375#if QT_CONFIG(regularexpression)
376/*!
377 \fn QStringList &QStringList::replaceInStrings(const QRegularExpression &re, const QString &after)
378 \overload
379 \since 5.0
380
381 Replaces every occurrence of the regular expression \a re, in each of the
382 string lists's strings, with \a after. Returns a reference to the string
383 list.
384
385 For example:
386
387 \snippet qstringlist/main.cpp 5
388 \snippet qstringlist/main.cpp 16
389
390 For regular expressions that contain capturing groups,
391 occurrences of \b{\\1}, \b{\\2}, ..., in \a after are
392 replaced with the string captured by the corresponding capturing group.
393
394 For example:
395
396 \snippet qstringlist/main.cpp 5
397 \snippet qstringlist/main.cpp 17
398*/
399void QtPrivate::QStringList_replaceInStrings(QStringList *that, const QRegularExpression &re, const QString &after)
400{
401 for (qsizetype i = 0; i < that->size(); ++i)
402 (*that)[i].replace(re, after);
403}
404#endif // QT_CONFIG(regularexpression)
405
406static qsizetype accumulatedSize(const QStringList &list, qsizetype seplen)
407{
408 qsizetype result = 0;
409 if (!list.isEmpty()) {
410 for (const auto &e : list)
411 result += e.size() + seplen;
412 result -= seplen;
413 }
414 return result;
415}
416
417/*!
418 \fn QString QStringList::join(const QString &separator) const
419
420 Joins all the string list's strings into a single string with each
421 element separated by the given \a separator (which can be an
422 empty string).
423
424 \sa QString::split()
425*/
426
427/*!
428 \fn QString QStringList::join(QChar separator) const
429 \since 5.0
430 \overload join()
431*/
432QString QtPrivate::QStringList_join(const QStringList *that, const QChar *sep, qsizetype seplen)
433{
434 const qsizetype totalLength = accumulatedSize(list: *that, seplen);
435 const qsizetype size = that->size();
436
437 QString res;
438 if (totalLength == 0)
439 return res;
440 res.reserve(asize: totalLength);
441 for (qsizetype i = 0; i < size; ++i) {
442 if (i)
443 res.append(uc: sep, len: seplen);
444 res += that->at(i);
445 }
446 return res;
447}
448
449/*!
450 \fn QString QStringList::join(QLatin1StringView separator) const
451 \since 5.8
452 \overload join()
453*/
454QString QtPrivate::QStringList_join(const QStringList &list, QLatin1StringView sep)
455{
456 QString result;
457 if (!list.isEmpty()) {
458 result.reserve(asize: accumulatedSize(list, seplen: sep.size()));
459 const auto end = list.end();
460 auto it = list.begin();
461 result += *it;
462 while (++it != end) {
463 result += sep;
464 result += *it;
465 }
466 }
467 return result;
468}
469
470/*!
471 \fn QString QStringList::join(QStringView separator) const
472 \overload
473 \since 5.14
474*/
475QString QtPrivate::QStringList_join(const QStringList *that, QStringView sep)
476{
477 return QStringList_join(that, sep: sep.data(), seplen: sep.size());
478}
479
480/*!
481 \fn QStringList QStringList::operator+(const QStringList &other) const
482
483 Returns a string list that is the concatenation of this string
484 list with the \a other string list.
485
486 \sa append()
487*/
488
489/*!
490 \fn QStringList &QStringList::operator<<(const QString &str)
491
492 Appends the given string, \a str, to this string list and returns
493 a reference to the string list.
494
495 \sa append()
496*/
497
498/*!
499 \fn QStringList &QStringList::operator<<(const QStringList &other)
500
501 \overload
502
503 Appends the \a other string list to the string list and returns a reference to
504 the latter string list.
505*/
506
507/*!
508 \fn QStringList &QStringList::operator<<(const QList<QString> &other)
509 \since 5.4
510
511 \overload
512
513 Appends the \a other string list to the string list and returns a reference to
514 the latter string list.
515*/
516
517#if QT_CONFIG(regularexpression)
518/*!
519 \fn qsizetype QStringList::indexOf(const QRegularExpression &re, qsizetype from) const
520 \overload
521 \since 5.0
522
523 Returns the index position of the first exact match of \a re in
524 the list, searching forward from index position \a from. Returns
525 -1 if no item matched.
526
527 \sa lastIndexOf()
528*/
529qsizetype QtPrivate::QStringList_indexOf(const QStringList *that, const QRegularExpression &re, qsizetype from)
530{
531 if (from < 0)
532 from = qMax(a: from + that->size(), b: qsizetype(0));
533
534 QString exactPattern = QRegularExpression::anchoredPattern(expression: re.pattern());
535 QRegularExpression exactRe(exactPattern, re.patternOptions());
536
537 for (qsizetype i = from; i < that->size(); ++i) {
538 QRegularExpressionMatch m = exactRe.match(subject: that->at(i));
539 if (m.hasMatch())
540 return i;
541 }
542 return -1;
543}
544
545/*!
546 \fn qsizetype QStringList::lastIndexOf(const QRegularExpression &re, qsizetype from) const
547 \overload
548 \since 5.0
549
550 Returns the index position of the last exact match of \a re in
551 the list, searching backward from index position \a from. If \a
552 from is -1 (the default), the search starts at the last item.
553 Returns -1 if no item matched.
554
555 \sa indexOf()
556*/
557qsizetype QtPrivate::QStringList_lastIndexOf(const QStringList *that, const QRegularExpression &re, qsizetype from)
558{
559 if (from < 0)
560 from += that->size();
561 else if (from >= that->size())
562 from = that->size() - 1;
563
564 QString exactPattern = QRegularExpression::anchoredPattern(expression: re.pattern());
565 QRegularExpression exactRe(exactPattern, re.patternOptions());
566
567 for (qsizetype i = from; i >= 0; --i) {
568 QRegularExpressionMatch m = exactRe.match(subject: that->at(i));
569 if (m.hasMatch())
570 return i;
571 }
572 return -1;
573}
574#endif // QT_CONFIG(regularexpression)
575
576/*!
577 \fn qsizetype QStringList::removeDuplicates()
578
579 \since 4.5
580
581 This function removes duplicate entries from a list.
582 The entries do not have to be sorted. They will retain their
583 original order.
584
585 Returns the number of removed entries.
586*/
587qsizetype QtPrivate::QStringList_removeDuplicates(QStringList *that)
588{
589 QDuplicateTracker<QString> seen(that->size());
590 return that->removeIf(pred: [&](const QString &s) { return seen.hasSeen(s); });
591}
592
593QT_END_NAMESPACE
594

source code of qtbase/src/corelib/text/qstringlist.cpp