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