/* * 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 #include #include #include #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 *vec) { std::smatch match; if (in.empty()) { vec->clear(); return; } std::string copy(in); vec->clear(); std::vector 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 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 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 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 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 *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 &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