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::locale;
35 using std::string;
36 using std::vector;
37 using std::istringstream;
38 using std::istream_iterator;
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::__anon68e20e3e0111::ToLower50 ToLower (void) : loc(locale::classic()) {}
operator ()de::__anon68e20e3e0111::ToLower51 char operator() (char c) { return std::tolower(c, loc); }
52 };
53
54 struct ToUpper
55 {
56 const locale& loc;
ToUpperde::__anon68e20e3e0111::ToUpper57 ToUpper (void) : loc(locale::classic()) {}
operator ()de::__anon68e20e3e0111::ToUpper58 char operator() (char c) { return std::toupper(c, loc); }
59 };
60
61 } // anonymous
62
63 //! Convert string to lowercase using the classic "C" locale
toLower(const string & str)64 string toLower (const string& str)
65 {
66 string ret;
67 std::transform(str.begin(), str.end(), std::inserter(ret, ret.begin()), ToLower());
68 return ret;
69 }
70
71 //! Convert string to uppercase using the classic "C" locale
toUpper(const string & str)72 string toUpper (const string& str)
73 {
74 string ret;
75 std::transform(str.begin(), str.end(), std::inserter(ret, ret.begin()), ToUpper());
76 return ret;
77 }
78
79 //! Convert string's first character to uppercase using the classic "C" locale
capitalize(const string & str)80 string capitalize (const string& str)
81 {
82 if (str.empty())
83 return str;
84 return ToUpper()(str[0]) + str.substr(1);
85 }
86
87 //! Split a string into tokens. If `delim` is `'\0'`, separate by spans of
88 //! whitespace. Otherwise use a single character `delim` as the separator.
89
splitString(const string & s,char delim)90 vector<string> splitString (const string& s, char delim)
91 {
92 istringstream tokenStream(s);
93
94 if (delim == '\0')
95 return vector<string>(istream_iterator<string>(tokenStream),
96 istream_iterator<string>());
97 else
98 {
99 vector<string> ret;
100 string token;
101
102 while (std::getline(tokenStream, token, delim))
103 ret.push_back(token);
104
105 return ret;
106 }
107 }
108
109 //! Convert floating-point value to string with fixed number of fractional decimals.
floatToString(float val,int precision)110 std::string floatToString (float val, int precision)
111 {
112 std::ostringstream s;
113 s << std::fixed << std::setprecision(precision) << val;
114 return s.str();
115 }
116
beginsWith(const std::string & s,const std::string & prefix)117 bool beginsWith (const std::string& s, const std::string& prefix)
118 {
119 return deStringBeginsWith(s.c_str(), prefix.c_str()) == DE_TRUE;
120 }
121
endsWith(const std::string & s,const std::string & suffix)122 bool endsWith (const std::string& s, const std::string& suffix)
123 {
124 if (suffix.length() > s.length())
125 return false;
126 else
127 {
128 const std::string::size_type offset = s.length() - suffix.length();
129 return s.find(suffix, offset) == offset;
130 }
131 }
132
toUpper(char c)133 char toUpper (char c)
134 {
135 return std::toupper(c, std::locale::classic());
136 }
137
toLower(char c)138 char toLower (char c)
139 {
140 return std::tolower(c, std::locale::classic());
141 }
142
isUpper(char c)143 bool isUpper (char c)
144 {
145 return std::isupper(c, std::locale::classic());
146 }
147
isLower(char c)148 bool isLower (char c)
149 {
150 return std::islower(c, std::locale::classic());
151 }
152
isDigit(char c)153 bool isDigit (char c)
154 {
155 return std::isdigit(c, std::locale::classic());
156 }
157
StringUtil_selfTest(void)158 void StringUtil_selfTest (void)
159 {
160
161 DE_TEST_ASSERT(toString(42) == "42");
162 DE_TEST_ASSERT(toString("foo") == "foo");
163 DE_TEST_ASSERT(toLower("FooBar") == "foobar");
164 DE_TEST_ASSERT(toUpper("FooBar") == "FOOBAR");
165
166 {
167 vector <string> tokens(splitString(" foo bar\n\tbaz "));
168 DE_TEST_ASSERT(tokens.size() == 3);
169 DE_TEST_ASSERT(tokens[0] == "foo");
170 DE_TEST_ASSERT(tokens[1] == "bar");
171 DE_TEST_ASSERT(tokens[2] == "baz");
172 }
173
174 DE_TEST_ASSERT(floatToString(4, 1) == "4.0");
175
176 DE_TEST_ASSERT(beginsWith("foobar", "foobar"));
177 DE_TEST_ASSERT(beginsWith("foobar", "foo"));
178 DE_TEST_ASSERT(beginsWith("foobar", "f"));
179 DE_TEST_ASSERT(beginsWith("foobar", ""));
180 DE_TEST_ASSERT(beginsWith("", ""));
181 DE_TEST_ASSERT(!beginsWith("foobar", "bar"));
182 DE_TEST_ASSERT(!beginsWith("foobar", "foobarbaz"));
183 DE_TEST_ASSERT(!beginsWith("", "foo"));
184
185 DE_TEST_ASSERT(endsWith("foobar", "foobar"));
186 DE_TEST_ASSERT(endsWith("foobar", "bar"));
187 DE_TEST_ASSERT(endsWith("foobar", "r"));
188 DE_TEST_ASSERT(endsWith("foobar", ""));
189 DE_TEST_ASSERT(endsWith("", ""));
190 DE_TEST_ASSERT(!endsWith("foobar", "foo"));
191 DE_TEST_ASSERT(!endsWith("foobar", "bazfoobar"));
192 DE_TEST_ASSERT(!endsWith("foobar", "foobarbaz"));
193 DE_TEST_ASSERT(!endsWith("", "foo"));
194
195 DE_TEST_ASSERT(toUpper('a') == 'A');
196 DE_TEST_ASSERT(toUpper('A') == 'A');
197 DE_TEST_ASSERT(toLower('a') == 'a');
198 DE_TEST_ASSERT(toLower('A') == 'a');
199 DE_TEST_ASSERT(isUpper('A'));
200 DE_TEST_ASSERT(!isUpper('a'));
201 DE_TEST_ASSERT(isLower('a'));
202 DE_TEST_ASSERT(!isLower('A'));
203 DE_TEST_ASSERT(isDigit('0'));
204 DE_TEST_ASSERT(!isDigit('a'));
205 }
206
207 } // de
208