1// Copyright (C) 2016 Intel Corporation.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#ifndef QSTRINGALGORITHMS_P_H
5#define QSTRINGALGORITHMS_P_H
6
7//
8// W A R N I N G
9// -------------
10//
11// This file is not part of the Qt API. It exists for the convenience
12// of internal files. This header file may change from version to version
13// without notice, or even be removed.
14//
15// We mean it.
16//
17
18#include "qstring.h"
19#include "qlocale_p.h" // for ascii_isspace
20
21QT_BEGIN_NAMESPACE
22
23template <typename StringType> struct QStringAlgorithms
24{
25 typedef typename StringType::value_type Char;
26 typedef typename StringType::size_type size_type;
27 typedef typename std::remove_cv<StringType>::type NakedStringType;
28 static const bool isConst = std::is_const<StringType>::value;
29
30 static inline bool isSpace(char ch) { return ascii_isspace(c: ch); }
31 static inline bool isSpace(QChar ch) { return ch.isSpace(); }
32
33 // Surrogate pairs are not handled in either of the functions below. That is
34 // not a problem because there are no space characters (Zs, Zl, Zp) outside the
35 // Basic Multilingual Plane.
36
37 static inline StringType trimmed_helper_inplace(NakedStringType &str, const Char *begin, const Char *end)
38 {
39 // in-place trimming:
40 Char *data = const_cast<Char *>(str.cbegin());
41 if (begin != data)
42 memmove(data, begin, (end - begin) * sizeof(Char));
43 str.resize(end - begin);
44 return std::move(str);
45 }
46
47 static inline StringType trimmed_helper_inplace(const NakedStringType &, const Char *, const Char *)
48 {
49 // can't happen
50 Q_UNREACHABLE_RETURN(StringType());
51 }
52
53 struct TrimPositions {
54 const Char *begin;
55 const Char *end;
56 };
57 // Returns {begin, end} where:
58 // - "begin" refers to the first non-space character
59 // - if there is a sequence of one or more space chacaters at the end,
60 // "end" refers to the first character in that sequence, otherwise
61 // "end" is str.cend()
62 [[nodiscard]] static TrimPositions trimmed_helper_positions(const StringType &str)
63 {
64 const Char *begin = str.cbegin();
65 const Char *end = str.cend();
66 // skip white space from end
67 while (begin < end && isSpace(end[-1]))
68 --end;
69 // skip white space from start
70 while (begin < end && isSpace(*begin))
71 begin++;
72 return {begin, end};
73 }
74
75 static inline StringType trimmed_helper(StringType &str)
76 {
77 const auto [begin, end] = trimmed_helper_positions(str);
78 if (begin == str.cbegin() && end == str.cend())
79 return str;
80 if (!isConst && str.isDetached())
81 return trimmed_helper_inplace(str, begin, end);
82 return StringType(begin, end - begin);
83 }
84
85 static inline StringType simplified_helper(StringType &str)
86 {
87 if (str.isEmpty())
88 return str;
89 const Char *src = str.cbegin();
90 const Char *end = str.cend();
91 NakedStringType result = isConst || !str.isDetached() ?
92 StringType(str.size(), Qt::Uninitialized) :
93 std::move(str);
94
95 Char *dst = const_cast<Char *>(result.cbegin());
96 Char *ptr = dst;
97 bool unmodified = true;
98 while (true) {
99 while (src != end && isSpace(*src))
100 ++src;
101 while (src != end && !isSpace(*src))
102 *ptr++ = *src++;
103 if (src == end)
104 break;
105 if (*src != QChar::Space)
106 unmodified = false;
107 *ptr++ = QChar::Space;
108 }
109 if (ptr != dst && ptr[-1] == QChar::Space)
110 --ptr;
111
112 qsizetype newlen = ptr - dst;
113 if (isConst && newlen == str.size() && unmodified) {
114 // nothing happened, return the original
115 return str;
116 }
117 result.resize(newlen);
118 return result;
119 }
120};
121
122QT_END_NAMESPACE
123
124#endif // QSTRINGALGORITHMS_P_H
125

Provided by KDAB

Privacy Policy
Learn Advanced QML with KDAB
Find out more

source code of qtbase/src/corelib/text/qstringalgorithms_p.h