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; 50 ToLower (void) : loc(locale::classic()) {} 51 char operator() (char c) { return std::tolower(c, loc); } 52 }; 53 54 struct ToUpper 55 { 56 const locale& loc; 57 ToUpper (void) : loc(locale::classic()) {} 58 char operator() (char c) { return std::toupper(c, loc); } 59 }; 60 61 } // anonymous 62 63 //! Convert string to lowercase using the classic "C" locale 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 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 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 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. 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 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 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 133 char toUpper (char c) 134 { 135 return std::toupper(c, std::locale::classic()); 136 } 137 138 char toLower (char c) 139 { 140 return std::tolower(c, std::locale::classic()); 141 } 142 143 bool isUpper (char c) 144 { 145 return std::isupper(c, std::locale::classic()); 146 } 147 148 bool isLower (char c) 149 { 150 return std::islower(c, std::locale::classic()); 151 } 152 153 bool isDigit (char c) 154 { 155 return std::isdigit(c, std::locale::classic()); 156 } 157 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