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 
57 QT_BEGIN_NAMESPACE
58 
59 template <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 
isSpaceQStringAlgorithms66     static inline bool isSpace(char ch) { return ascii_isspace(ch); }
isSpaceQStringAlgorithms67     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 
trimmed_helper_inplaceQStringAlgorithms73     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 
trimmed_helper_inplaceQStringAlgorithms83     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 
trimmed_helper_positionsQStringAlgorithms90     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 
trimmed_helperQStringAlgorithms100     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 
simplified_helperQStringAlgorithms113     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 
150 QT_END_NAMESPACE
151 
152 #endif // QSTRINGALGORITHMS_P_H
153