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::__anonf63ff4d30111::ToLower50 					ToLower 	(void) : loc(locale::classic()) {}
operator ()de::__anonf63ff4d30111::ToLower51 	char			operator()	(char c) { return std::tolower(c, loc); }
52 };
53 
54 struct ToUpper
55 {
56 	const locale&	loc;
ToUpperde::__anonf63ff4d30111::ToUpper57 					ToUpper 	(void) : loc(locale::classic()) {}
operator ()de::__anonf63ff4d30111::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