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 \section1 Initializing
64
65 The default constructor creates an empty list. You can use the
66 initializer-list constructor to create a list with elements:
67
68 \snippet qstringlist/main.cpp 0a
69
70 \section1 Adding Strings
71
72 Strings can be added to a list using the \l
73 {QList::insert()}{insert()}, \l
74 {QList::append()}{append()}, \l
75 {QList::operator+=()}{operator+=()} and \l
76 {operator<<()} functions.
77
78 \l{operator<<()} can be used to
79 conveniently add multiple elements to a list:
80
81 \snippet qstringlist/main.cpp 0b
82
83 \section1 Iterating Over the Strings
84
85 See \l {Iterating over Containers}.
86
87 \section1 Manipulating the Strings
88
89 QStringList provides several functions allowing you to manipulate
90 the contents of a list. You can concatenate all the strings in a
91 string list into a single string (with an optional separator)
92 using the join() function. For example:
93
94 \snippet qstringlist/main.cpp 4
95
96 The argument to join can be a single character or a string.
97
98 To break up a string into a string list, use the QString::split()
99 function:
100
101 \snippet qstringlist/main.cpp 6
102
103 The argument to split can be a single character, a string or a
104 QRegularExpression.
105
106 In addition, the \l {QStringList::operator+()}{operator+()}
107 function allows you to concatenate two string lists into one. To
108 sort a string list, use the sort() function.
109
110 QString list also provides the filter() function which lets you
111 to extract a new list which contains only those strings which
112 contain a particular substring (or match a particular regular
113 expression):
114
115 \snippet qstringlist/main.cpp 7
116
117 The contains() function tells you whether the list contains a
118 given string, while the indexOf() function returns the index of
119 the first occurrence of the given string. The lastIndexOf()
120 function on the other hand, returns the index of the last
121 occurrence of the string.
122
123 Finally, the replaceInStrings() function calls QString::replace()
124 on each string in the string list in turn. For example:
125
126 \snippet qstringlist/main.cpp 8
127
128 \sa QString
129*/
130
131/*!
132 \fn QStringList::QStringList(const QString &str)
133
134 Constructs a string list that contains the given string, \a
135 str. Longer lists are easily created like this:
136
137 \snippet qstringlist/main.cpp 9
138
139 \sa append()
140*/
141
142/*!
143 \fn QStringList::QStringList(const QList<QString> &other)
144
145 Constructs a copy of \a other.
146
147 This operation takes \l{constant time}, because QStringList is
148 \l{implicitly shared}. This makes returning a QStringList from a
149 function very fast. If a shared instance is modified, it will be
150 copied (copy-on-write), and that takes \l{linear time}.
151
152 \sa operator=()
153*/
154
155/*!
156 \fn QStringList::QStringList(QList<QString> &&other)
157 \overload
158 \since 5.4
159
160 Move-constructs from QList<QString>.
161
162 After a successful construction, \a other will be empty.
163*/
164
165/*!
166 \fn QStringList &QStringList::operator=(const QList<QString> &other)
167 \since 5.4
168
169 Copy assignment operator from QList<QString>. Assigns the \a other
170 list of strings to this string list.
171
172 After the operation, \a other and \c *this will be equal.
173*/
174
175/*!
176 \fn QStringList &QStringList::operator=(QList<QString> &&other)
177 \overload
178 \since 5.4
179
180 Move assignment operator from QList<QString>. Moves the \a other
181 list of strings to this string list.
182
183 After the operation, \a other will be empty.
184*/
185
186/*!
187 \fn void QStringList::sort(Qt::CaseSensitivity cs)
188
189 Sorts the list of strings in ascending order.
190
191//! [comparison-case-sensitivity]
192 If \a cs is \l Qt::CaseSensitive (the default), the string comparison
193 is case sensitive; otherwise the comparison is case insensitive.
194//! [comparison-case-sensitivity]
195
196 Sorting is performed using the STL's std::sort() algorithm,
197 which averages \l{linear-logarithmic time}, i.e. O(\e{n} log \e{n}).
198
199 If you want to sort your strings in an arbitrary order, consider
200 using the QMap class. For example, you could use a QMap<QString,
201 QString> to create a case-insensitive ordering (e.g. with the keys
202 being lower-case versions of the strings, and the values being the
203 strings), or a QMap<int, QString> to sort the strings by some
204 integer index.
205*/
206
207void QtPrivate::QStringList_sort(QStringList *that, Qt::CaseSensitivity cs)
208{
209 if (cs == Qt::CaseSensitive) {
210 std::sort(first: that->begin(), last: that->end());
211 } else {
212 auto CISCompare = [](const auto &s1, const auto &s2) {
213 return s1.compare(s2, Qt::CaseInsensitive) < 0;
214 };
215 std::sort(first: that->begin(), last: that->end(), comp: CISCompare);
216 }
217}
218
219
220/*!
221 \fn QStringList QStringList::filter(const QString &str, Qt::CaseSensitivity cs) const
222
223 Returns a list of all the strings containing the substring \a str.
224
225 \include qstringlist.cpp comparison-case-sensitivity
226
227 \snippet qstringlist/main.cpp 5
228 \snippet qstringlist/main.cpp 10
229
230 This is equivalent to
231
232 \snippet qstringlist/main.cpp 11
233 \snippet qstringlist/main.cpp 12
234
235 \sa contains()
236*/
237
238template <typename String>
239static QStringList filter_helper(const QStringList &that, const String &needle, Qt::CaseSensitivity cs)
240{
241 QStringList res;
242 for (const auto &s : that) {
243 if (s.contains(needle, cs))
244 res.append(t: s);
245 }
246 return res;
247}
248
249/*!
250 \fn QStringList QStringList::filter(QStringView str, Qt::CaseSensitivity cs) const
251 \overload
252 \since 5.14
253*/
254QStringList QtPrivate::QStringList_filter(const QStringList *that, QStringView str,
255 Qt::CaseSensitivity cs)
256{
257 return filter_helper(that: *that, needle: str, cs);
258}
259
260/*!
261 \fn QStringList QStringList::filter(const QStringMatcher &matcher) const
262 \since 6.7
263 \overload
264
265 Returns a list of all the strings matched by \a matcher (i.e. for which
266 \c matcher.indexIn() returns an index >= 0).
267
268 Using a QStringMatcher may be faster when searching in large lists and/or
269 in lists with long strings (the best way to find out is benchmarking).
270
271 For example:
272 \snippet qstringlist/main.cpp 18
273
274 \sa contains()
275*/
276
277QStringList QtPrivate::QStringList_filter(const QStringList &that, const QStringMatcher &matcher)
278{
279 QStringList res;
280 for (const auto &s : that) {
281 if (matcher.indexIn(str: s) != -1)
282 res.append(t: s);
283 }
284 return res;
285}
286
287/*!
288 \fn QStringList QStringList::filter(QLatin1StringView str, Qt::CaseSensitivity cs) const
289 \since 6.7
290 \overload
291*/
292
293QStringList QtPrivate::QStringList_filter(const QStringList &that, QLatin1StringView needle,
294 Qt::CaseSensitivity cs)
295{
296 return filter_helper(that, needle, cs);
297}
298
299template<typename T>
300static bool stringList_contains(const QStringList &stringList, const T &str, Qt::CaseSensitivity cs)
301{
302 for (const auto &string : stringList) {
303 if (string.size() == str.size() && string.compare(str, cs) == 0)
304 return true;
305 }
306 return false;
307}
308
309
310/*!
311 \fn bool QStringList::contains(const QString &str, Qt::CaseSensitivity cs) const
312
313 Returns \c true if the list contains the string \a str; otherwise
314 returns \c false.
315
316 \include qstringlist.cpp comparison-case-sensitivity
317
318 \sa indexOf(), lastIndexOf(), QString::contains()
319 */
320
321/*!
322 \fn bool QStringList::contains(QStringView str, Qt::CaseSensitivity cs) const
323 \overload
324 \since 5.12
325
326 Returns \c true if the list contains the string \a str; otherwise
327 returns \c false.
328
329 \include qstringlist.cpp comparison-case-sensitivity
330 */
331bool QtPrivate::QStringList_contains(const QStringList *that, QStringView str,
332 Qt::CaseSensitivity cs)
333{
334 return stringList_contains(stringList: *that, str, cs);
335}
336
337/*!
338 \fn bool QStringList::contains(QLatin1StringView str, Qt::CaseSensitivity cs) const
339 \overload
340 \since 5.10
341
342 Returns \c true if the list contains the Latin-1 string viewed by \a str; otherwise
343 returns \c false.
344
345 \include qstringlist.cpp comparison-case-sensitivity
346
347 \sa indexOf(), lastIndexOf(), QString::contains()
348 */
349bool QtPrivate::QStringList_contains(const QStringList *that, QLatin1StringView str,
350 Qt::CaseSensitivity cs)
351{
352 return stringList_contains(stringList: *that, str, cs);
353}
354
355
356#if QT_CONFIG(regularexpression)
357/*!
358 \fn QStringList QStringList::filter(const QRegularExpression &re) const
359 \overload
360 \since 5.0
361
362 Returns a list of all the strings that match the regular
363 expression \a re.
364*/
365QStringList QtPrivate::QStringList_filter(const QStringList *that, const QRegularExpression &re)
366{
367 QStringList res;
368 for (const auto &str : *that) {
369 if (str.contains(re))
370 res.append(t: str);
371 }
372 return res;
373}
374#endif // QT_CONFIG(regularexpression)
375
376/*!
377 \fn QStringList &QStringList::replaceInStrings(const QString &before, const QString &after, Qt::CaseSensitivity cs)
378
379 Returns a string list where every string has had the \a before
380 text replaced with the \a after text wherever the \a before text
381 is found.
382
383 \note If you use an empty \a before argument, the \a after argument will be
384 inserted \e {before and after} each character of the string.
385
386 \include qstringlist.cpp comparison-case-sensitivity
387
388 For example:
389
390 \snippet qstringlist/main.cpp 5
391 \snippet qstringlist/main.cpp 13
392
393 \sa QString::replace()
394*/
395
396/*!
397 \fn QStringList &QStringList::replaceInStrings(QStringView before, const QString &after, Qt::CaseSensitivity cs)
398 \overload
399 \since 5.14
400*/
401
402/*!
403 \fn QStringList &QStringList::replaceInStrings(const QString &before, QStringView after, Qt::CaseSensitivity cs)
404 \overload
405 \since 5.14
406*/
407
408/*!
409 \fn QStringList &QStringList::replaceInStrings(QStringView before, QStringView after, Qt::CaseSensitivity cs)
410 \overload
411 \since 5.14
412*/
413void QtPrivate::QStringList_replaceInStrings(QStringList *that, QStringView before,
414 QStringView after, Qt::CaseSensitivity cs)
415{
416 // Before potentially detaching "that" list, check if any string contains "before"
417 qsizetype i = -1;
418 for (qsizetype j = 0; j < that->size(); ++j) {
419 if (that->at(i: j).contains(s: before, cs)) {
420 i = j;
421 break;
422 }
423 }
424 if (i == -1)
425 return;
426
427 for (; i < that->size(); ++i)
428 (*that)[i].replace(before: before.data(), blen: before.size(), after: after.data(), alen: after.size(), cs);
429}
430
431#if QT_CONFIG(regularexpression)
432/*!
433 \fn QStringList &QStringList::replaceInStrings(const QRegularExpression &re, const QString &after)
434 \overload
435 \since 5.0
436
437 Replaces every occurrence of the regular expression \a re, in each of the
438 string lists's strings, with \a after. Returns a reference to the string
439 list.
440
441 For example:
442
443 \snippet qstringlist/main.cpp 5
444 \snippet qstringlist/main.cpp 16
445
446 For regular expressions that contain capturing groups,
447 occurrences of \b{\\1}, \b{\\2}, ..., in \a after are
448 replaced with the string captured by the corresponding capturing group.
449
450 For example:
451
452 \snippet qstringlist/main.cpp 5
453 \snippet qstringlist/main.cpp 17
454*/
455void QtPrivate::QStringList_replaceInStrings(QStringList *that, const QRegularExpression &re,
456 const QString &after)
457{
458 // Before potentially detaching "that" list, check if any string contains "before"
459 qsizetype i = -1;
460 for (qsizetype j = 0; j < that->size(); ++j) {
461 if (that->at(i: j).contains(re)) {
462 i = j;
463 break;
464 }
465 }
466 if (i == -1)
467 return;
468
469 for (; i < that->size(); ++i)
470 (*that)[i].replace(re, after);
471}
472#endif // QT_CONFIG(regularexpression)
473
474static qsizetype accumulatedSize(const QStringList &list, qsizetype seplen)
475{
476 qsizetype result = 0;
477 if (!list.isEmpty()) {
478 for (const auto &e : list)
479 result += e.size() + seplen;
480 result -= seplen;
481 }
482 return result;
483}
484
485/*!
486 \fn QString QStringList::join(const QString &separator) const
487
488 Joins all the string list's strings into a single string with each
489 element separated by the given \a separator (which can be an
490 empty string).
491
492 \sa QString::split()
493*/
494
495/*!
496 \fn QString QStringList::join(QChar separator) const
497 \since 5.0
498 \overload join()
499*/
500QString QtPrivate::QStringList_join(const QStringList *that, const QChar *sep, qsizetype seplen)
501{
502 const qsizetype totalLength = accumulatedSize(list: *that, seplen);
503 const qsizetype size = that->size();
504
505 QString res;
506 if (totalLength == 0)
507 return res;
508 res.reserve(asize: totalLength);
509 for (qsizetype i = 0; i < size; ++i) {
510 if (i)
511 res.append(uc: sep, len: seplen);
512 res += that->at(i);
513 }
514 return res;
515}
516
517/*!
518 \fn QString QStringList::join(QLatin1StringView separator) const
519 \since 5.8
520 \overload join()
521*/
522QString QtPrivate::QStringList_join(const QStringList &list, QLatin1StringView sep)
523{
524 QString result;
525 if (!list.isEmpty()) {
526 result.reserve(asize: accumulatedSize(list, seplen: sep.size()));
527 const auto end = list.end();
528 auto it = list.begin();
529 result += *it;
530 while (++it != end) {
531 result += sep;
532 result += *it;
533 }
534 }
535 return result;
536}
537
538/*!
539 \fn QString QStringList::join(QStringView separator) const
540 \overload
541 \since 5.14
542*/
543QString QtPrivate::QStringList_join(const QStringList *that, QStringView sep)
544{
545 return QStringList_join(that, sep: sep.data(), seplen: sep.size());
546}
547
548/*!
549 \fn QStringList QStringList::operator+(const QStringList &other) const
550
551 Returns a string list that is the concatenation of this string
552 list with the \a other string list.
553
554 \sa append()
555*/
556
557/*!
558 \fn QStringList &QStringList::operator<<(const QString &str)
559
560 Appends the given string, \a str, to this string list and returns
561 a reference to the string list.
562
563 \sa append()
564*/
565
566/*!
567 \fn QStringList &QStringList::operator<<(const QStringList &other)
568
569 \overload
570
571 Appends the \a other string list to the string list and returns a reference to
572 the latter string list.
573*/
574
575/*!
576 \fn QStringList &QStringList::operator<<(const QList<QString> &other)
577 \since 5.4
578
579 \overload
580
581 Appends the \a other string list to the string list and returns a reference to
582 the latter string list.
583*/
584
585/*!
586 \fn qsizetype QStringList::indexOf(const QString &str, qsizetype from, Qt::CaseSensitivity cs) const
587 \fn qsizetype QStringList::indexOf(QStringView str, qsizetype from, Qt::CaseSensitivity cs) const
588 \fn qsizetype QStringList::indexOf(QLatin1StringView str, qsizetype from, Qt::CaseSensitivity cs) const
589
590 Returns the index position of the first match of \a str in the list,
591 searching forward from index position \a from. Returns -1 if no item
592 matched.
593
594 \include qstringlist.cpp comparison-case-sensitivity
595
596//! [overloading-base-class-methods]
597 \note The \a cs parameter was added in Qt 6.7, i.e. these methods now overload
598 the methods inherited from the base class. Prior to that these methods only
599 had two parameters. This change is source compatible and existing code should
600 continue to work.
601//! [overloading-base-class-methods]
602
603 \sa lastIndexOf()
604*/
605
606template <typename String>
607qsizetype indexOf_helper(const QStringList &that, String needle, qsizetype from,
608 Qt::CaseSensitivity cs)
609{
610 if (from < 0) // Historical behavior
611 from = qMax(a: from + that.size(), b: 0);
612
613 if (from >= that.size())
614 return -1;
615
616 for (qsizetype i = from; i < that.size(); ++i) {
617 if (needle.compare(that.at(i), cs) == 0)
618 return i;
619 }
620 return -1;
621}
622
623qsizetype QtPrivate::QStringList_indexOf(const QStringList &that, QStringView needle,
624 qsizetype from, Qt::CaseSensitivity cs)
625{
626 return indexOf_helper(that, needle, from, cs);
627}
628
629qsizetype QtPrivate::QStringList_indexOf(const QStringList &that, QLatin1StringView needle,
630 qsizetype from, Qt::CaseSensitivity cs)
631{
632 return indexOf_helper(that, needle, from, cs);
633}
634
635/*!
636 \fn qsizetype QStringList::lastIndexOf(const QString &str, qsizetype from, Qt::CaseSensitivity cs) const
637 \fn qsizetype QStringList::lastIndexOf(QStringView str, qsizetype from, Qt::CaseSensitivity cs) const
638 \fn qsizetype QStringList::lastIndexOf(QLatin1StringView str, qsizetype from, Qt::CaseSensitivity cs) const
639
640 Returns the index position of the last match of \a str in the list,
641 searching backward from index position \a from. If \a from is -1 (the
642 default), the search starts at the last item. Returns -1 if no item
643 matched.
644
645 \include qstringlist.cpp comparison-case-sensitivity
646
647 \include qstringlist.cpp overloading-base-class-methods
648
649 \sa indexOf()
650*/
651
652template <typename String>
653qsizetype lastIndexof_helper(const QStringList &that, String needle, qsizetype from,
654 Qt::CaseSensitivity cs)
655{
656 if (from < 0)
657 from += that.size();
658 else if (from >= that.size())
659 from = that.size() - 1;
660
661 for (qsizetype i = from; i >= 0; --i) {
662 if (needle.compare(that.at(i), cs) == 0)
663 return i;
664 }
665
666 return -1;
667}
668
669qsizetype QtPrivate::QStringList_lastIndexOf(const QStringList &that, QLatin1StringView needle,
670 qsizetype from, Qt::CaseSensitivity cs)
671{
672 return lastIndexof_helper(that, needle, from, cs);
673}
674
675qsizetype QtPrivate::QStringList_lastIndexOf(const QStringList &that, QStringView needle,
676 qsizetype from, Qt::CaseSensitivity cs)
677{
678 return lastIndexof_helper(that, needle, from, cs);
679}
680
681#if QT_CONFIG(regularexpression)
682/*!
683 \fn qsizetype QStringList::indexOf(const QRegularExpression &re, qsizetype from) const
684 \overload
685 \since 5.0
686
687 Returns the index position of the first exact match of \a re in
688 the list, searching forward from index position \a from. Returns
689 -1 if no item matched.
690
691 \sa lastIndexOf()
692*/
693qsizetype QtPrivate::QStringList_indexOf(const QStringList *that, const QRegularExpression &re, qsizetype from)
694{
695 if (from < 0)
696 from = qMax(a: from + that->size(), b: qsizetype(0));
697
698 QString exactPattern = QRegularExpression::anchoredPattern(expression: re.pattern());
699 QRegularExpression exactRe(exactPattern, re.patternOptions());
700
701 for (qsizetype i = from; i < that->size(); ++i) {
702 QRegularExpressionMatch m = exactRe.match(subject: that->at(i));
703 if (m.hasMatch())
704 return i;
705 }
706 return -1;
707}
708
709/*!
710 \fn qsizetype QStringList::lastIndexOf(const QRegularExpression &re, qsizetype from) const
711 \overload
712 \since 5.0
713
714 Returns the index position of the last exact match of \a re in
715 the list, searching backward from index position \a from. If \a
716 from is -1 (the default), the search starts at the last item.
717 Returns -1 if no item matched.
718
719 \sa indexOf()
720*/
721qsizetype QtPrivate::QStringList_lastIndexOf(const QStringList *that, const QRegularExpression &re, qsizetype from)
722{
723 if (from < 0)
724 from += that->size();
725 else if (from >= that->size())
726 from = that->size() - 1;
727
728 QString exactPattern = QRegularExpression::anchoredPattern(expression: re.pattern());
729 QRegularExpression exactRe(exactPattern, re.patternOptions());
730
731 for (qsizetype i = from; i >= 0; --i) {
732 QRegularExpressionMatch m = exactRe.match(subject: that->at(i));
733 if (m.hasMatch())
734 return i;
735 }
736 return -1;
737}
738#endif // QT_CONFIG(regularexpression)
739
740/*!
741 \fn qsizetype QStringList::removeDuplicates()
742
743 \since 4.5
744
745 This function removes duplicate entries from a list.
746 The entries do not have to be sorted. They will retain their
747 original order.
748
749 Returns the number of removed entries.
750*/
751qsizetype QtPrivate::QStringList_removeDuplicates(QStringList *that)
752{
753 QDuplicateTracker<QString> seen(that->size());
754 return that->removeIf(pred: [&](const QString &s) { return seen.hasSeen(s); });
755}
756
757QT_END_NAMESPACE
758

Provided by KDAB

Privacy Policy
Start learning QML with our Intro Training
Find out more

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