208 lines
5.2 KiB
C++
208 lines
5.2 KiB
C++
/*-------------------------------------------------------------------------
|
|
* drawElements C++ Base Library
|
|
* -----------------------------
|
|
*
|
|
* Copyright 2014 The Android Open Source Project
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*
|
|
*//*!
|
|
* \file
|
|
* \brief String utilities.
|
|
*//*--------------------------------------------------------------------*/
|
|
|
|
#include "deStringUtil.hpp"
|
|
#include "deString.h"
|
|
|
|
#include <algorithm>
|
|
#include <iterator>
|
|
#include <sstream>
|
|
#include <locale>
|
|
#include <iomanip>
|
|
#include <cctype>
|
|
|
|
using std::locale;
|
|
using std::string;
|
|
using std::vector;
|
|
using std::istringstream;
|
|
using std::istream_iterator;
|
|
|
|
namespace de
|
|
{
|
|
namespace
|
|
{
|
|
|
|
// Always use locale::classic to ensure consistent behavior in all environments.
|
|
|
|
struct ToLower
|
|
{
|
|
const locale& loc;
|
|
ToLower (void) : loc(locale::classic()) {}
|
|
char operator() (char c) { return std::tolower(c, loc); }
|
|
};
|
|
|
|
struct ToUpper
|
|
{
|
|
const locale& loc;
|
|
ToUpper (void) : loc(locale::classic()) {}
|
|
char operator() (char c) { return std::toupper(c, loc); }
|
|
};
|
|
|
|
} // anonymous
|
|
|
|
//! Convert string to lowercase using the classic "C" locale
|
|
string toLower (const string& str)
|
|
{
|
|
string ret;
|
|
std::transform(str.begin(), str.end(), std::inserter(ret, ret.begin()), ToLower());
|
|
return ret;
|
|
}
|
|
|
|
//! Convert string to uppercase using the classic "C" locale
|
|
string toUpper (const string& str)
|
|
{
|
|
string ret;
|
|
std::transform(str.begin(), str.end(), std::inserter(ret, ret.begin()), ToUpper());
|
|
return ret;
|
|
}
|
|
|
|
//! Convert string's first character to uppercase using the classic "C" locale
|
|
string capitalize (const string& str)
|
|
{
|
|
if (str.empty())
|
|
return str;
|
|
return ToUpper()(str[0]) + str.substr(1);
|
|
}
|
|
|
|
//! Split a string into tokens. If `delim` is `'\0'`, separate by spans of
|
|
//! whitespace. Otherwise use a single character `delim` as the separator.
|
|
|
|
vector<string> splitString (const string& s, char delim)
|
|
{
|
|
istringstream tokenStream(s);
|
|
|
|
if (delim == '\0')
|
|
return vector<string>(istream_iterator<string>(tokenStream),
|
|
istream_iterator<string>());
|
|
else
|
|
{
|
|
vector<string> ret;
|
|
string token;
|
|
|
|
while (std::getline(tokenStream, token, delim))
|
|
ret.push_back(token);
|
|
|
|
return ret;
|
|
}
|
|
}
|
|
|
|
//! Convert floating-point value to string with fixed number of fractional decimals.
|
|
std::string floatToString (float val, int precision)
|
|
{
|
|
std::ostringstream s;
|
|
s << std::fixed << std::setprecision(precision) << val;
|
|
return s.str();
|
|
}
|
|
|
|
bool beginsWith (const std::string& s, const std::string& prefix)
|
|
{
|
|
return deStringBeginsWith(s.c_str(), prefix.c_str()) == DE_TRUE;
|
|
}
|
|
|
|
bool endsWith (const std::string& s, const std::string& suffix)
|
|
{
|
|
if (suffix.length() > s.length())
|
|
return false;
|
|
else
|
|
{
|
|
const std::string::size_type offset = s.length() - suffix.length();
|
|
return s.find(suffix, offset) == offset;
|
|
}
|
|
}
|
|
|
|
char toUpper (char c)
|
|
{
|
|
return std::toupper(c, std::locale::classic());
|
|
}
|
|
|
|
char toLower (char c)
|
|
{
|
|
return std::tolower(c, std::locale::classic());
|
|
}
|
|
|
|
bool isUpper (char c)
|
|
{
|
|
return std::isupper(c, std::locale::classic());
|
|
}
|
|
|
|
bool isLower (char c)
|
|
{
|
|
return std::islower(c, std::locale::classic());
|
|
}
|
|
|
|
bool isDigit (char c)
|
|
{
|
|
return std::isdigit(c, std::locale::classic());
|
|
}
|
|
|
|
void StringUtil_selfTest (void)
|
|
{
|
|
|
|
DE_TEST_ASSERT(toString(42) == "42");
|
|
DE_TEST_ASSERT(toString("foo") == "foo");
|
|
DE_TEST_ASSERT(toLower("FooBar") == "foobar");
|
|
DE_TEST_ASSERT(toUpper("FooBar") == "FOOBAR");
|
|
|
|
{
|
|
vector <string> tokens(splitString(" foo bar\n\tbaz "));
|
|
DE_TEST_ASSERT(tokens.size() == 3);
|
|
DE_TEST_ASSERT(tokens[0] == "foo");
|
|
DE_TEST_ASSERT(tokens[1] == "bar");
|
|
DE_TEST_ASSERT(tokens[2] == "baz");
|
|
}
|
|
|
|
DE_TEST_ASSERT(floatToString(4, 1) == "4.0");
|
|
|
|
DE_TEST_ASSERT(beginsWith("foobar", "foobar"));
|
|
DE_TEST_ASSERT(beginsWith("foobar", "foo"));
|
|
DE_TEST_ASSERT(beginsWith("foobar", "f"));
|
|
DE_TEST_ASSERT(beginsWith("foobar", ""));
|
|
DE_TEST_ASSERT(beginsWith("", ""));
|
|
DE_TEST_ASSERT(!beginsWith("foobar", "bar"));
|
|
DE_TEST_ASSERT(!beginsWith("foobar", "foobarbaz"));
|
|
DE_TEST_ASSERT(!beginsWith("", "foo"));
|
|
|
|
DE_TEST_ASSERT(endsWith("foobar", "foobar"));
|
|
DE_TEST_ASSERT(endsWith("foobar", "bar"));
|
|
DE_TEST_ASSERT(endsWith("foobar", "r"));
|
|
DE_TEST_ASSERT(endsWith("foobar", ""));
|
|
DE_TEST_ASSERT(endsWith("", ""));
|
|
DE_TEST_ASSERT(!endsWith("foobar", "foo"));
|
|
DE_TEST_ASSERT(!endsWith("foobar", "bazfoobar"));
|
|
DE_TEST_ASSERT(!endsWith("foobar", "foobarbaz"));
|
|
DE_TEST_ASSERT(!endsWith("", "foo"));
|
|
|
|
DE_TEST_ASSERT(toUpper('a') == 'A');
|
|
DE_TEST_ASSERT(toUpper('A') == 'A');
|
|
DE_TEST_ASSERT(toLower('a') == 'a');
|
|
DE_TEST_ASSERT(toLower('A') == 'a');
|
|
DE_TEST_ASSERT(isUpper('A'));
|
|
DE_TEST_ASSERT(!isUpper('a'));
|
|
DE_TEST_ASSERT(isLower('a'));
|
|
DE_TEST_ASSERT(!isLower('A'));
|
|
DE_TEST_ASSERT(isDigit('0'));
|
|
DE_TEST_ASSERT(!isDigit('a'));
|
|
}
|
|
|
|
} // de
|