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 34using std::locale; 35using std::string; 36using std::vector; 37using std::istringstream; 38using std::istream_iterator; 39 40namespace de 41{ 42namespace 43{ 44 45// Always use locale::classic to ensure consistent behavior in all environments. 46 47struct ToLower 48{ 49 const locale& loc; 50 ToLower (void) : loc(locale::classic()) {} 51 char operator() (char c) { return std::tolower(c, loc); } 52}; 53 54struct 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 64string 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 72string 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 80string 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 90vector<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. 110std::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 117bool beginsWith (const std::string& s, const std::string& prefix) 118{ 119 return deStringBeginsWith(s.c_str(), prefix.c_str()) == DE_TRUE; 120} 121 122bool 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 133char toUpper (char c) 134{ 135 return std::toupper(c, std::locale::classic()); 136} 137 138char toLower (char c) 139{ 140 return std::tolower(c, std::locale::classic()); 141} 142 143bool isUpper (char c) 144{ 145 return std::isupper(c, std::locale::classic()); 146} 147 148bool isLower (char c) 149{ 150 return std::islower(c, std::locale::classic()); 151} 152 153bool isDigit (char c) 154{ 155 return std::isdigit(c, std::locale::classic()); 156} 157 158void 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