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
26 #include <algorithm>
27 #include <iterator>
28 #include <sstream>
29 #include <locale>
30 #include <iomanip>
31 #include <cctype>
32
33 using std::locale;
34 using std::string;
35 using std::vector;
36 using std::istringstream;
37 using std::istream_iterator;
38
39 namespace de
40 {
41 namespace
42 {
43
44 // Always use locale::classic to ensure consistent behavior in all environments.
45
46 struct ToLower
47 {
48 const locale& loc;
ToLowerde::__anon3cb02d0a0111::ToLower49 ToLower (void) : loc(locale::classic()) {}
operator ()de::__anon3cb02d0a0111::ToLower50 char operator() (char c) { return std::tolower(c, loc); }
51 };
52
53 struct ToUpper
54 {
55 const locale& loc;
ToUpperde::__anon3cb02d0a0111::ToUpper56 ToUpper (void) : loc(locale::classic()) {}
operator ()de::__anon3cb02d0a0111::ToUpper57 char operator() (char c) { return std::toupper(c, loc); }
58 };
59
60 } // anonymous
61
62 //! Convert string to lowercase using the classic "C" locale
toLower(const string & str)63 string toLower (const string& str)
64 {
65 string ret;
66 std::transform(str.begin(), str.end(), std::inserter(ret, ret.begin()), ToLower());
67 return ret;
68 }
69
70 //! Convert string to uppercase using the classic "C" locale
toUpper(const string & str)71 string toUpper (const string& str)
72 {
73 string ret;
74 std::transform(str.begin(), str.end(), std::inserter(ret, ret.begin()), ToUpper());
75 return ret;
76 }
77
78 //! Convert string's first character to uppercase using the classic "C" locale
capitalize(const string & str)79 string capitalize (const string& str)
80 {
81 if (str.empty())
82 return str;
83 return ToUpper()(str[0]) + str.substr(1);
84 }
85
86 //! Split a string into tokens. If `delim` is `'\0'`, separate by spans of
87 //! whitespace. Otherwise use a single character `delim` as the separator.
88
splitString(const string & s,char delim)89 vector<string> splitString (const string& s, char delim)
90 {
91 istringstream tokenStream(s);
92
93 if (delim == '\0')
94 return vector<string>(istream_iterator<string>(tokenStream),
95 istream_iterator<string>());
96 else
97 {
98 vector<string> ret;
99 string token;
100
101 while (std::getline(tokenStream, token, delim))
102 ret.push_back(token);
103
104 return ret;
105 }
106 }
107
108 //! Convert floating-point value to string with fixed number of fractional decimals.
floatToString(float val,int precision)109 std::string floatToString (float val, int precision)
110 {
111 std::ostringstream s;
112 s << std::fixed << std::setprecision(precision) << val;
113 return s.str();
114 }
115
toUpper(char c)116 char toUpper (char c)
117 {
118 return std::toupper(c, std::locale::classic());
119 }
120
toLower(char c)121 char toLower (char c)
122 {
123 return std::tolower(c, std::locale::classic());
124 }
125
isUpper(char c)126 bool isUpper (char c)
127 {
128 return std::isupper(c, std::locale::classic());
129 }
130
isLower(char c)131 bool isLower (char c)
132 {
133 return std::islower(c, std::locale::classic());
134 }
135
isDigit(char c)136 bool isDigit (char c)
137 {
138 return std::isdigit(c, std::locale::classic());
139 }
140
StringUtil_selfTest(void)141 void StringUtil_selfTest (void)
142 {
143
144 DE_TEST_ASSERT(toString(42) == "42");
145 DE_TEST_ASSERT(toString("foo") == "foo");
146 DE_TEST_ASSERT(toLower("FooBar") == "foobar");
147 DE_TEST_ASSERT(toUpper("FooBar") == "FOOBAR");
148
149 {
150 vector <string> tokens(splitString(" foo bar\n\tbaz "));
151 DE_TEST_ASSERT(tokens.size() == 3);
152 DE_TEST_ASSERT(tokens[0] == "foo");
153 DE_TEST_ASSERT(tokens[1] == "bar");
154 DE_TEST_ASSERT(tokens[2] == "baz");
155 }
156
157 DE_TEST_ASSERT(floatToString(4, 1) == "4.0");
158
159 DE_TEST_ASSERT(toUpper('a') == 'A');
160 DE_TEST_ASSERT(toUpper('A') == 'A');
161 DE_TEST_ASSERT(toLower('a') == 'a');
162 DE_TEST_ASSERT(toLower('A') == 'a');
163 DE_TEST_ASSERT(isUpper('A'));
164 DE_TEST_ASSERT(!isUpper('a'));
165 DE_TEST_ASSERT(isLower('a'));
166 DE_TEST_ASSERT(!isLower('A'));
167 DE_TEST_ASSERT(isDigit('0'));
168 DE_TEST_ASSERT(!isDigit('a'));
169 }
170
171 } // de
172