1/****************************************************************************
2**
3** Copyright (C) 2016 Intel Corporation.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the QtCore module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU Lesser General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU Lesser
19** General Public License version 3 as published by the Free Software
20** Foundation and appearing in the file LICENSE.LGPL3 included in the
21** packaging of this file. Please review the following information to
22** ensure the GNU Lesser General Public License version 3 requirements
23** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24**
25** GNU General Public License Usage
26** Alternatively, this file may be used under the terms of the GNU
27** General Public License version 2.0 or (at your option) the GNU General
28** Public license version 3 or any later version approved by the KDE Free
29** Qt Foundation. The licenses are as published by the Free Software
30** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31** included in the packaging of this file. Please review the following
32** information to ensure the GNU General Public License requirements will
33** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34** https://www.gnu.org/licenses/gpl-3.0.html.
35**
36** $QT_END_LICENSE$
37**
38****************************************************************************/
39
40#ifndef QSTRINGALGORITHMS_P_H
41#define QSTRINGALGORITHMS_P_H
42
43//
44// W A R N I N G
45// -------------
46//
47// This file is not part of the Qt API. It exists for the convenience
48// of internal files. This header file may change from version to version
49// without notice, or even be removed.
50//
51// We mean it.
52//
53
54#include "qstring.h"
55#include "qlocale_p.h" // for ascii_isspace
56
57QT_BEGIN_NAMESPACE
58
59template <typename StringType> struct QStringAlgorithms
60{
61 typedef typename StringType::value_type Char;
62 typedef typename StringType::size_type size_type;
63 typedef typename std::remove_cv<StringType>::type NakedStringType;
64 static const bool isConst = std::is_const<StringType>::value;
65
66 static inline bool isSpace(char ch) { return ascii_isspace(ch); }
67 static inline bool isSpace(QChar ch) { return ch.isSpace(); }
68
69 // Surrogate pairs are not handled in either of the functions below. That is
70 // not a problem because there are no space characters (Zs, Zl, Zp) outside the
71 // Basic Multilingual Plane.
72
73 static inline StringType trimmed_helper_inplace(NakedStringType &str, const Char *begin, const Char *end)
74 {
75 // in-place trimming:
76 Char *data = const_cast<Char *>(str.cbegin());
77 if (begin != data)
78 memmove(data, begin, (end - begin) * sizeof(Char));
79 str.resize(end - begin);
80 return std::move(str);
81 }
82
83 static inline StringType trimmed_helper_inplace(const NakedStringType &, const Char *, const Char *)
84 {
85 // can't happen
86 Q_UNREACHABLE();
87 return StringType();
88 }
89
90 static inline void trimmed_helper_positions(const Char *&begin, const Char *&end)
91 {
92 // skip white space from end
93 while (begin < end && isSpace(end[-1]))
94 --end;
95 // skip white space from start
96 while (begin < end && isSpace(*begin))
97 begin++;
98 }
99
100 static inline StringType trimmed_helper(StringType &str)
101 {
102 const Char *begin = str.cbegin();
103 const Char *end = str.cend();
104 trimmed_helper_positions(begin, end);
105
106 if (begin == str.cbegin() && end == str.cend())
107 return str;
108 if (!isConst && str.isDetached())
109 return trimmed_helper_inplace(str, begin, end);
110 return StringType(begin, end - begin);
111 }
112
113 static inline StringType simplified_helper(StringType &str)
114 {
115 if (str.isEmpty())
116 return str;
117 const Char *src = str.cbegin();
118 const Char *end = str.cend();
119 NakedStringType result = isConst || !str.isDetached() ?
120 StringType(str.size(), Qt::Uninitialized) :
121 std::move(str);
122
123 Char *dst = const_cast<Char *>(result.cbegin());
124 Char *ptr = dst;
125 bool unmodified = true;
126 forever {
127 while (src != end && isSpace(*src))
128 ++src;
129 while (src != end && !isSpace(*src))
130 *ptr++ = *src++;
131 if (src == end)
132 break;
133 if (*src != QChar::Space)
134 unmodified = false;
135 *ptr++ = QChar::Space;
136 }
137 if (ptr != dst && ptr[-1] == QChar::Space)
138 --ptr;
139
140 int newlen = ptr - dst;
141 if (isConst && newlen == str.size() && unmodified) {
142 // nothing happened, return the original
143 return str;
144 }
145 result.resize(newlen);
146 return result;
147 }
148};
149
150QT_END_NAMESPACE
151
152#endif // QSTRINGALGORITHMS_P_H
153