xref: /aosp_15_r20/external/deqp/framework/delibs/decpp/deStringUtil.cpp (revision 35238bce31c2a825756842865a792f8cf7f89930)
1*35238bceSAndroid Build Coastguard Worker /*-------------------------------------------------------------------------
2*35238bceSAndroid Build Coastguard Worker  * drawElements C++ Base Library
3*35238bceSAndroid Build Coastguard Worker  * -----------------------------
4*35238bceSAndroid Build Coastguard Worker  *
5*35238bceSAndroid Build Coastguard Worker  * Copyright 2014 The Android Open Source Project
6*35238bceSAndroid Build Coastguard Worker  *
7*35238bceSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
8*35238bceSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
9*35238bceSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
10*35238bceSAndroid Build Coastguard Worker  *
11*35238bceSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
12*35238bceSAndroid Build Coastguard Worker  *
13*35238bceSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
14*35238bceSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
15*35238bceSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16*35238bceSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
17*35238bceSAndroid Build Coastguard Worker  * limitations under the License.
18*35238bceSAndroid Build Coastguard Worker  *
19*35238bceSAndroid Build Coastguard Worker  *//*!
20*35238bceSAndroid Build Coastguard Worker  * \file
21*35238bceSAndroid Build Coastguard Worker  * \brief String utilities.
22*35238bceSAndroid Build Coastguard Worker  *//*--------------------------------------------------------------------*/
23*35238bceSAndroid Build Coastguard Worker 
24*35238bceSAndroid Build Coastguard Worker #include "deStringUtil.hpp"
25*35238bceSAndroid Build Coastguard Worker #include "deString.h"
26*35238bceSAndroid Build Coastguard Worker 
27*35238bceSAndroid Build Coastguard Worker #include <algorithm>
28*35238bceSAndroid Build Coastguard Worker #include <iterator>
29*35238bceSAndroid Build Coastguard Worker #include <sstream>
30*35238bceSAndroid Build Coastguard Worker #include <locale>
31*35238bceSAndroid Build Coastguard Worker #include <iomanip>
32*35238bceSAndroid Build Coastguard Worker #include <cctype>
33*35238bceSAndroid Build Coastguard Worker 
34*35238bceSAndroid Build Coastguard Worker using std::istream_iterator;
35*35238bceSAndroid Build Coastguard Worker using std::istringstream;
36*35238bceSAndroid Build Coastguard Worker using std::locale;
37*35238bceSAndroid Build Coastguard Worker using std::string;
38*35238bceSAndroid Build Coastguard Worker using std::vector;
39*35238bceSAndroid Build Coastguard Worker 
40*35238bceSAndroid Build Coastguard Worker namespace de
41*35238bceSAndroid Build Coastguard Worker {
42*35238bceSAndroid Build Coastguard Worker namespace
43*35238bceSAndroid Build Coastguard Worker {
44*35238bceSAndroid Build Coastguard Worker 
45*35238bceSAndroid Build Coastguard Worker // Always use locale::classic to ensure consistent behavior in all environments.
46*35238bceSAndroid Build Coastguard Worker 
47*35238bceSAndroid Build Coastguard Worker struct ToLower
48*35238bceSAndroid Build Coastguard Worker {
49*35238bceSAndroid Build Coastguard Worker     const locale &loc;
ToLowerde::__anonf879c5c90111::ToLower50*35238bceSAndroid Build Coastguard Worker     ToLower(void) : loc(locale::classic())
51*35238bceSAndroid Build Coastguard Worker     {
52*35238bceSAndroid Build Coastguard Worker     }
operator ()de::__anonf879c5c90111::ToLower53*35238bceSAndroid Build Coastguard Worker     char operator()(char c)
54*35238bceSAndroid Build Coastguard Worker     {
55*35238bceSAndroid Build Coastguard Worker         return std::tolower(c, loc);
56*35238bceSAndroid Build Coastguard Worker     }
57*35238bceSAndroid Build Coastguard Worker };
58*35238bceSAndroid Build Coastguard Worker 
59*35238bceSAndroid Build Coastguard Worker struct ToUpper
60*35238bceSAndroid Build Coastguard Worker {
61*35238bceSAndroid Build Coastguard Worker     const locale &loc;
ToUpperde::__anonf879c5c90111::ToUpper62*35238bceSAndroid Build Coastguard Worker     ToUpper(void) : loc(locale::classic())
63*35238bceSAndroid Build Coastguard Worker     {
64*35238bceSAndroid Build Coastguard Worker     }
operator ()de::__anonf879c5c90111::ToUpper65*35238bceSAndroid Build Coastguard Worker     char operator()(char c)
66*35238bceSAndroid Build Coastguard Worker     {
67*35238bceSAndroid Build Coastguard Worker         return std::toupper(c, loc);
68*35238bceSAndroid Build Coastguard Worker     }
69*35238bceSAndroid Build Coastguard Worker };
70*35238bceSAndroid Build Coastguard Worker 
71*35238bceSAndroid Build Coastguard Worker } // namespace
72*35238bceSAndroid Build Coastguard Worker 
73*35238bceSAndroid Build Coastguard Worker //! Convert string to lowercase using the classic "C" locale
toLower(const string & str)74*35238bceSAndroid Build Coastguard Worker string toLower(const string &str)
75*35238bceSAndroid Build Coastguard Worker {
76*35238bceSAndroid Build Coastguard Worker     string ret;
77*35238bceSAndroid Build Coastguard Worker     std::transform(str.begin(), str.end(), std::inserter(ret, ret.begin()), ToLower());
78*35238bceSAndroid Build Coastguard Worker     return ret;
79*35238bceSAndroid Build Coastguard Worker }
80*35238bceSAndroid Build Coastguard Worker 
81*35238bceSAndroid Build Coastguard Worker //! Convert string to uppercase using the classic "C" locale
toUpper(const string & str)82*35238bceSAndroid Build Coastguard Worker string toUpper(const string &str)
83*35238bceSAndroid Build Coastguard Worker {
84*35238bceSAndroid Build Coastguard Worker     string ret;
85*35238bceSAndroid Build Coastguard Worker     std::transform(str.begin(), str.end(), std::inserter(ret, ret.begin()), ToUpper());
86*35238bceSAndroid Build Coastguard Worker     return ret;
87*35238bceSAndroid Build Coastguard Worker }
88*35238bceSAndroid Build Coastguard Worker 
89*35238bceSAndroid Build Coastguard Worker //! Convert string's first character to uppercase using the classic "C" locale
capitalize(const string & str)90*35238bceSAndroid Build Coastguard Worker string capitalize(const string &str)
91*35238bceSAndroid Build Coastguard Worker {
92*35238bceSAndroid Build Coastguard Worker     if (str.empty())
93*35238bceSAndroid Build Coastguard Worker         return str;
94*35238bceSAndroid Build Coastguard Worker     return ToUpper()(str[0]) + str.substr(1);
95*35238bceSAndroid Build Coastguard Worker }
96*35238bceSAndroid Build Coastguard Worker 
97*35238bceSAndroid Build Coastguard Worker //! Split a string into tokens. If `delim` is `'\0'`, separate by spans of
98*35238bceSAndroid Build Coastguard Worker //! whitespace. Otherwise use a single character `delim` as the separator.
99*35238bceSAndroid Build Coastguard Worker 
splitString(const string & s,char delim)100*35238bceSAndroid Build Coastguard Worker vector<string> splitString(const string &s, char delim)
101*35238bceSAndroid Build Coastguard Worker {
102*35238bceSAndroid Build Coastguard Worker     istringstream tokenStream(s);
103*35238bceSAndroid Build Coastguard Worker 
104*35238bceSAndroid Build Coastguard Worker     if (delim == '\0')
105*35238bceSAndroid Build Coastguard Worker         return vector<string>(istream_iterator<string>(tokenStream), istream_iterator<string>());
106*35238bceSAndroid Build Coastguard Worker     else
107*35238bceSAndroid Build Coastguard Worker     {
108*35238bceSAndroid Build Coastguard Worker         vector<string> ret;
109*35238bceSAndroid Build Coastguard Worker         string token;
110*35238bceSAndroid Build Coastguard Worker 
111*35238bceSAndroid Build Coastguard Worker         while (std::getline(tokenStream, token, delim))
112*35238bceSAndroid Build Coastguard Worker             ret.push_back(token);
113*35238bceSAndroid Build Coastguard Worker 
114*35238bceSAndroid Build Coastguard Worker         return ret;
115*35238bceSAndroid Build Coastguard Worker     }
116*35238bceSAndroid Build Coastguard Worker }
117*35238bceSAndroid Build Coastguard Worker 
118*35238bceSAndroid Build Coastguard Worker //! Convert floating-point value to string with fixed number of fractional decimals.
floatToString(float val,int precision)119*35238bceSAndroid Build Coastguard Worker std::string floatToString(float val, int precision)
120*35238bceSAndroid Build Coastguard Worker {
121*35238bceSAndroid Build Coastguard Worker     std::ostringstream s;
122*35238bceSAndroid Build Coastguard Worker     s << std::fixed << std::setprecision(precision) << val;
123*35238bceSAndroid Build Coastguard Worker     return s.str();
124*35238bceSAndroid Build Coastguard Worker }
125*35238bceSAndroid Build Coastguard Worker 
beginsWith(const std::string & s,const std::string & prefix)126*35238bceSAndroid Build Coastguard Worker bool beginsWith(const std::string &s, const std::string &prefix)
127*35238bceSAndroid Build Coastguard Worker {
128*35238bceSAndroid Build Coastguard Worker     return deStringBeginsWith(s.c_str(), prefix.c_str()) == true;
129*35238bceSAndroid Build Coastguard Worker }
130*35238bceSAndroid Build Coastguard Worker 
endsWith(const std::string & s,const std::string & suffix)131*35238bceSAndroid Build Coastguard Worker bool endsWith(const std::string &s, const std::string &suffix)
132*35238bceSAndroid Build Coastguard Worker {
133*35238bceSAndroid Build Coastguard Worker     if (suffix.length() > s.length())
134*35238bceSAndroid Build Coastguard Worker         return false;
135*35238bceSAndroid Build Coastguard Worker     else
136*35238bceSAndroid Build Coastguard Worker     {
137*35238bceSAndroid Build Coastguard Worker         const std::string::size_type offset = s.length() - suffix.length();
138*35238bceSAndroid Build Coastguard Worker         return s.find(suffix, offset) == offset;
139*35238bceSAndroid Build Coastguard Worker     }
140*35238bceSAndroid Build Coastguard Worker }
141*35238bceSAndroid Build Coastguard Worker 
toUpper(char c)142*35238bceSAndroid Build Coastguard Worker char toUpper(char c)
143*35238bceSAndroid Build Coastguard Worker {
144*35238bceSAndroid Build Coastguard Worker     return std::toupper(c, std::locale::classic());
145*35238bceSAndroid Build Coastguard Worker }
146*35238bceSAndroid Build Coastguard Worker 
toLower(char c)147*35238bceSAndroid Build Coastguard Worker char toLower(char c)
148*35238bceSAndroid Build Coastguard Worker {
149*35238bceSAndroid Build Coastguard Worker     return std::tolower(c, std::locale::classic());
150*35238bceSAndroid Build Coastguard Worker }
151*35238bceSAndroid Build Coastguard Worker 
isUpper(char c)152*35238bceSAndroid Build Coastguard Worker bool isUpper(char c)
153*35238bceSAndroid Build Coastguard Worker {
154*35238bceSAndroid Build Coastguard Worker     return std::isupper(c, std::locale::classic());
155*35238bceSAndroid Build Coastguard Worker }
156*35238bceSAndroid Build Coastguard Worker 
isLower(char c)157*35238bceSAndroid Build Coastguard Worker bool isLower(char c)
158*35238bceSAndroid Build Coastguard Worker {
159*35238bceSAndroid Build Coastguard Worker     return std::islower(c, std::locale::classic());
160*35238bceSAndroid Build Coastguard Worker }
161*35238bceSAndroid Build Coastguard Worker 
isDigit(char c)162*35238bceSAndroid Build Coastguard Worker bool isDigit(char c)
163*35238bceSAndroid Build Coastguard Worker {
164*35238bceSAndroid Build Coastguard Worker     return std::isdigit(c, std::locale::classic());
165*35238bceSAndroid Build Coastguard Worker }
166*35238bceSAndroid Build Coastguard Worker 
StringUtil_selfTest(void)167*35238bceSAndroid Build Coastguard Worker void StringUtil_selfTest(void)
168*35238bceSAndroid Build Coastguard Worker {
169*35238bceSAndroid Build Coastguard Worker 
170*35238bceSAndroid Build Coastguard Worker     DE_TEST_ASSERT(toString(42) == "42");
171*35238bceSAndroid Build Coastguard Worker     DE_TEST_ASSERT(toString("foo") == "foo");
172*35238bceSAndroid Build Coastguard Worker     DE_TEST_ASSERT(toLower("FooBar") == "foobar");
173*35238bceSAndroid Build Coastguard Worker     DE_TEST_ASSERT(toUpper("FooBar") == "FOOBAR");
174*35238bceSAndroid Build Coastguard Worker 
175*35238bceSAndroid Build Coastguard Worker     {
176*35238bceSAndroid Build Coastguard Worker         vector<string> tokens(splitString(" foo bar\n\tbaz   "));
177*35238bceSAndroid Build Coastguard Worker         DE_TEST_ASSERT(tokens.size() == 3);
178*35238bceSAndroid Build Coastguard Worker         DE_TEST_ASSERT(tokens[0] == "foo");
179*35238bceSAndroid Build Coastguard Worker         DE_TEST_ASSERT(tokens[1] == "bar");
180*35238bceSAndroid Build Coastguard Worker         DE_TEST_ASSERT(tokens[2] == "baz");
181*35238bceSAndroid Build Coastguard Worker     }
182*35238bceSAndroid Build Coastguard Worker 
183*35238bceSAndroid Build Coastguard Worker     DE_TEST_ASSERT(floatToString(4, 1) == "4.0");
184*35238bceSAndroid Build Coastguard Worker 
185*35238bceSAndroid Build Coastguard Worker     DE_TEST_ASSERT(beginsWith("foobar", "foobar"));
186*35238bceSAndroid Build Coastguard Worker     DE_TEST_ASSERT(beginsWith("foobar", "foo"));
187*35238bceSAndroid Build Coastguard Worker     DE_TEST_ASSERT(beginsWith("foobar", "f"));
188*35238bceSAndroid Build Coastguard Worker     DE_TEST_ASSERT(beginsWith("foobar", ""));
189*35238bceSAndroid Build Coastguard Worker     DE_TEST_ASSERT(beginsWith("", ""));
190*35238bceSAndroid Build Coastguard Worker     DE_TEST_ASSERT(!beginsWith("foobar", "bar"));
191*35238bceSAndroid Build Coastguard Worker     DE_TEST_ASSERT(!beginsWith("foobar", "foobarbaz"));
192*35238bceSAndroid Build Coastguard Worker     DE_TEST_ASSERT(!beginsWith("", "foo"));
193*35238bceSAndroid Build Coastguard Worker 
194*35238bceSAndroid Build Coastguard Worker     DE_TEST_ASSERT(endsWith("foobar", "foobar"));
195*35238bceSAndroid Build Coastguard Worker     DE_TEST_ASSERT(endsWith("foobar", "bar"));
196*35238bceSAndroid Build Coastguard Worker     DE_TEST_ASSERT(endsWith("foobar", "r"));
197*35238bceSAndroid Build Coastguard Worker     DE_TEST_ASSERT(endsWith("foobar", ""));
198*35238bceSAndroid Build Coastguard Worker     DE_TEST_ASSERT(endsWith("", ""));
199*35238bceSAndroid Build Coastguard Worker     DE_TEST_ASSERT(!endsWith("foobar", "foo"));
200*35238bceSAndroid Build Coastguard Worker     DE_TEST_ASSERT(!endsWith("foobar", "bazfoobar"));
201*35238bceSAndroid Build Coastguard Worker     DE_TEST_ASSERT(!endsWith("foobar", "foobarbaz"));
202*35238bceSAndroid Build Coastguard Worker     DE_TEST_ASSERT(!endsWith("", "foo"));
203*35238bceSAndroid Build Coastguard Worker 
204*35238bceSAndroid Build Coastguard Worker     DE_TEST_ASSERT(toUpper('a') == 'A');
205*35238bceSAndroid Build Coastguard Worker     DE_TEST_ASSERT(toUpper('A') == 'A');
206*35238bceSAndroid Build Coastguard Worker     DE_TEST_ASSERT(toLower('a') == 'a');
207*35238bceSAndroid Build Coastguard Worker     DE_TEST_ASSERT(toLower('A') == 'a');
208*35238bceSAndroid Build Coastguard Worker     DE_TEST_ASSERT(isUpper('A'));
209*35238bceSAndroid Build Coastguard Worker     DE_TEST_ASSERT(!isUpper('a'));
210*35238bceSAndroid Build Coastguard Worker     DE_TEST_ASSERT(isLower('a'));
211*35238bceSAndroid Build Coastguard Worker     DE_TEST_ASSERT(!isLower('A'));
212*35238bceSAndroid Build Coastguard Worker     DE_TEST_ASSERT(isDigit('0'));
213*35238bceSAndroid Build Coastguard Worker     DE_TEST_ASSERT(!isDigit('a'));
214*35238bceSAndroid Build Coastguard Worker }
215*35238bceSAndroid Build Coastguard Worker 
216*35238bceSAndroid Build Coastguard Worker } // namespace de
217