238 lines
6.4 KiB
C++
238 lines
6.4 KiB
C++
/*
|
|
* Copyright (C) 2016 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.
|
|
*/
|
|
|
|
#include "StringHelper.h"
|
|
|
|
#include <sstream>
|
|
#include <regex>
|
|
|
|
#include <android-base/macros.h>
|
|
#include <android-base/logging.h>
|
|
|
|
#define UPPERCASE "[A-Z0-9]+"
|
|
#define LOWERCASE "[a-z0-9]+"
|
|
#define CAPCASE "[A-Z0-9][a-z0-9]*"
|
|
static const std::regex kStartUppercase("^" UPPERCASE);
|
|
static const std::regex kStartLowercase("^" LOWERCASE);
|
|
static const std::regex kStartCapcase("^" CAPCASE);
|
|
|
|
namespace android {
|
|
|
|
std::string StringHelper::Uppercase(const std::string &in) {
|
|
std::string out{in};
|
|
|
|
for (auto &ch : out) {
|
|
ch = toupper(ch);
|
|
}
|
|
|
|
return out;
|
|
}
|
|
|
|
std::string StringHelper::Lowercase(const std::string &in) {
|
|
std::string out{in};
|
|
|
|
for (auto &ch : out) {
|
|
ch = tolower(ch);
|
|
}
|
|
|
|
return out;
|
|
}
|
|
|
|
std::string StringHelper::Capitalize(const std::string &in) {
|
|
std::string out{in};
|
|
|
|
if(!out.empty()) {
|
|
out[0] = toupper(out[0]);
|
|
}
|
|
|
|
return out;
|
|
}
|
|
|
|
void StringHelper::Tokenize(const std::string &in,
|
|
std::vector<std::string> *vec) {
|
|
|
|
std::smatch match;
|
|
if (in.empty()) {
|
|
vec->clear();
|
|
return;
|
|
}
|
|
std::string copy(in);
|
|
vec->clear();
|
|
std::vector<std::string> matches;
|
|
|
|
copy = RTrimAll(copy, "_");
|
|
while(!copy.empty()) {
|
|
copy = LTrimAll(copy, "_");
|
|
if (std::regex_search(copy, match, kStartLowercase))
|
|
matches.push_back(match.str(0));
|
|
if (std::regex_search(copy, match, kStartCapcase))
|
|
matches.push_back(match.str(0));
|
|
if (std::regex_search(copy, match, kStartUppercase))
|
|
matches.push_back(match.str(0));
|
|
if (!matches.empty()) {
|
|
std::string &maxmatch = matches[0];
|
|
for (std::string &match : matches)
|
|
if(match.length() > maxmatch.length())
|
|
maxmatch = match;
|
|
vec->push_back(maxmatch);
|
|
copy = copy.substr(maxmatch.length());
|
|
matches.clear();
|
|
continue;
|
|
}
|
|
LOG(WARNING) << "Could not stylize \"" << in << "\"";
|
|
// don't know what to do, so push back the rest of the string.
|
|
vec->push_back(copy);
|
|
}
|
|
}
|
|
|
|
std::string StringHelper::ToCamelCase(const std::string &in) {
|
|
std::vector<std::string> components;
|
|
Tokenize(in, &components);
|
|
if (components.empty()) {
|
|
if (!in.empty())
|
|
LOG(WARNING) << "Could not stylize \"" << in << "\"";
|
|
return in;
|
|
}
|
|
components[0] = Lowercase(components[0]);
|
|
for (size_t i = 1; i < components.size(); i++) {
|
|
components[i] = Capitalize(components[i]);
|
|
}
|
|
return JoinStrings(components, "");
|
|
}
|
|
|
|
std::string StringHelper::ToPascalCase(const std::string &in) {
|
|
std::vector<std::string> components;
|
|
Tokenize(in, &components);
|
|
for (size_t i = 0; i < components.size(); i++) {
|
|
components[i] = Capitalize(components[i]);
|
|
}
|
|
return JoinStrings(components, "");
|
|
}
|
|
|
|
std::string StringHelper::ToUpperSnakeCase(const std::string &in) {
|
|
std::vector<std::string> components;
|
|
Tokenize(in, &components);
|
|
for (size_t i = 0; i < components.size(); i++) {
|
|
components[i] = Uppercase(components[i]);
|
|
}
|
|
return JoinStrings(components, "_");
|
|
}
|
|
|
|
std::string StringHelper::ToLowerSnakeCase(const std::string &in) {
|
|
std::vector<std::string> components;
|
|
Tokenize(in, &components);
|
|
for (size_t i = 0; i < components.size(); i++) {
|
|
components[i] = Lowercase(components[i]);
|
|
}
|
|
return JoinStrings(components, "_");
|
|
}
|
|
|
|
std::string StringHelper::ToCase(StringHelper::Case c, const std::string &in) {
|
|
switch(c) {
|
|
case kCamelCase:
|
|
return ToCamelCase(in);
|
|
case kPascalCase:
|
|
return ToPascalCase(in);
|
|
case kUpperSnakeCase:
|
|
return ToUpperSnakeCase(in);
|
|
case kLowerSnakeCase:
|
|
return ToLowerSnakeCase(in);
|
|
case kNoCase:
|
|
return in;
|
|
}
|
|
LOG(FATAL) << "Should not reach here.";
|
|
return in;
|
|
}
|
|
|
|
bool StringHelper::EndsWith(const std::string &in, const std::string &suffix) {
|
|
return in.size() >= suffix.size() &&
|
|
in.substr(in.size() - suffix.size()) == suffix;
|
|
}
|
|
|
|
bool StringHelper::StartsWith(const std::string &in, const std::string &prefix) {
|
|
return in.size() >= prefix.size() &&
|
|
in.substr(0, prefix.size()) == prefix;
|
|
}
|
|
|
|
std::string StringHelper::RTrim(const std::string &in, const std::string &suffix) {
|
|
if (EndsWith(in, suffix)) {
|
|
return in.substr(0, in.size() - suffix.size());
|
|
}
|
|
|
|
return in;
|
|
}
|
|
|
|
std::string StringHelper::LTrim(const std::string &in, const std::string &prefix) {
|
|
if (StartsWith(in, prefix)) {
|
|
return in.substr(prefix.size());
|
|
}
|
|
|
|
return in;
|
|
}
|
|
|
|
std::string StringHelper::RTrimAll(const std::string &in, const std::string &suffix) {
|
|
std::string copy(in);
|
|
while (EndsWith(copy, suffix)) {
|
|
copy = copy.substr(0, copy.size() - suffix.size());
|
|
}
|
|
|
|
return copy;
|
|
}
|
|
|
|
std::string StringHelper::LTrimAll(const std::string &in, const std::string &prefix) {
|
|
std::string copy(in);
|
|
while (StartsWith(copy, prefix)) {
|
|
copy = copy.substr(prefix.size());
|
|
}
|
|
|
|
return copy;
|
|
}
|
|
|
|
void StringHelper::SplitString(
|
|
const std::string &s, char c, std::vector<std::string> *components) {
|
|
components->clear();
|
|
|
|
size_t startPos = 0;
|
|
size_t matchPos;
|
|
while ((matchPos = s.find(c, startPos)) != std::string::npos) {
|
|
components->push_back(s.substr(startPos, matchPos - startPos));
|
|
startPos = matchPos + 1;
|
|
}
|
|
|
|
if (startPos <= s.length()) {
|
|
components->push_back(s.substr(startPos));
|
|
}
|
|
}
|
|
|
|
std::string StringHelper::JoinStrings(
|
|
const std::vector<std::string> &components,
|
|
const std::string &separator) {
|
|
std::string out;
|
|
bool first = true;
|
|
for (const auto &component : components) {
|
|
if (!first) {
|
|
out += separator;
|
|
}
|
|
out += component;
|
|
|
|
first = false;
|
|
}
|
|
|
|
return out;
|
|
}
|
|
|
|
} // namespace android
|
|
|