StringHelper.cpp revision db364989ebda11138911ef1c2a6e69e6299f05f8
1af44014f7b42697be072a7bde111c432b313d684Steven Moreland/* 2af44014f7b42697be072a7bde111c432b313d684Steven Moreland * Copyright (C) 2016 The Android Open Source Project 3af44014f7b42697be072a7bde111c432b313d684Steven Moreland * 4af44014f7b42697be072a7bde111c432b313d684Steven Moreland * Licensed under the Apache License, Version 2.0 (the "License"); 5af44014f7b42697be072a7bde111c432b313d684Steven Moreland * you may not use this file except in compliance with the License. 6af44014f7b42697be072a7bde111c432b313d684Steven Moreland * You may obtain a copy of the License at 7af44014f7b42697be072a7bde111c432b313d684Steven Moreland * 8af44014f7b42697be072a7bde111c432b313d684Steven Moreland * http://www.apache.org/licenses/LICENSE-2.0 9af44014f7b42697be072a7bde111c432b313d684Steven Moreland * 10af44014f7b42697be072a7bde111c432b313d684Steven Moreland * Unless required by applicable law or agreed to in writing, software 11af44014f7b42697be072a7bde111c432b313d684Steven Moreland * distributed under the License is distributed on an "AS IS" BASIS, 12af44014f7b42697be072a7bde111c432b313d684Steven Moreland * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13af44014f7b42697be072a7bde111c432b313d684Steven Moreland * See the License for the specific language governing permissions and 14af44014f7b42697be072a7bde111c432b313d684Steven Moreland * limitations under the License. 15af44014f7b42697be072a7bde111c432b313d684Steven Moreland */ 16af44014f7b42697be072a7bde111c432b313d684Steven Moreland 17af44014f7b42697be072a7bde111c432b313d684Steven Moreland#include "StringHelper.h" 18af44014f7b42697be072a7bde111c432b313d684Steven Moreland 19868aff8458f94a81cf932537c4b7354074df181eSteven Moreland#include <sstream> 204200903983e12253942381e2f9331479848c0b94Yifan Hong#include <regex> 214200903983e12253942381e2f9331479848c0b94Yifan Hong 224200903983e12253942381e2f9331479848c0b94Yifan Hong#include <android-base/macros.h> 234200903983e12253942381e2f9331479848c0b94Yifan Hong#include <android-base/logging.h> 244200903983e12253942381e2f9331479848c0b94Yifan Hong 254200903983e12253942381e2f9331479848c0b94Yifan Hong#define UPPERCASE "[A-Z0-9]+" 264200903983e12253942381e2f9331479848c0b94Yifan Hong#define LOWERCASE "[a-z0-9]+" 274200903983e12253942381e2f9331479848c0b94Yifan Hong#define CAPCASE "[A-Z0-9][a-z0-9]*" 284200903983e12253942381e2f9331479848c0b94Yifan Hongstatic const std::regex kStartUppercase("^" UPPERCASE); 294200903983e12253942381e2f9331479848c0b94Yifan Hongstatic const std::regex kStartLowercase("^" LOWERCASE); 304200903983e12253942381e2f9331479848c0b94Yifan Hongstatic const std::regex kStartCapcase("^" CAPCASE); 31868aff8458f94a81cf932537c4b7354074df181eSteven Moreland 32af44014f7b42697be072a7bde111c432b313d684Steven Morelandnamespace android { 33af44014f7b42697be072a7bde111c432b313d684Steven Moreland 34af44014f7b42697be072a7bde111c432b313d684Steven Moreland// static 354200903983e12253942381e2f9331479848c0b94Yifan Hongstd::string StringHelper::Uppercase(const std::string &in) { 36af44014f7b42697be072a7bde111c432b313d684Steven Moreland std::string out{in}; 37af44014f7b42697be072a7bde111c432b313d684Steven Moreland 38af44014f7b42697be072a7bde111c432b313d684Steven Moreland for (auto &ch : out) { 39af44014f7b42697be072a7bde111c432b313d684Steven Moreland ch = toupper(ch); 40af44014f7b42697be072a7bde111c432b313d684Steven Moreland } 41af44014f7b42697be072a7bde111c432b313d684Steven Moreland 42af44014f7b42697be072a7bde111c432b313d684Steven Moreland return out; 43af44014f7b42697be072a7bde111c432b313d684Steven Moreland} 44af44014f7b42697be072a7bde111c432b313d684Steven Moreland 45af44014f7b42697be072a7bde111c432b313d684Steven Moreland// static 464200903983e12253942381e2f9331479848c0b94Yifan Hongstd::string StringHelper::Lowercase(const std::string &in) { 474200903983e12253942381e2f9331479848c0b94Yifan Hong std::string out{in}; 484200903983e12253942381e2f9331479848c0b94Yifan Hong 494200903983e12253942381e2f9331479848c0b94Yifan Hong for (auto &ch : out) { 504200903983e12253942381e2f9331479848c0b94Yifan Hong ch = tolower(ch); 514200903983e12253942381e2f9331479848c0b94Yifan Hong } 524200903983e12253942381e2f9331479848c0b94Yifan Hong 534200903983e12253942381e2f9331479848c0b94Yifan Hong return out; 544200903983e12253942381e2f9331479848c0b94Yifan Hong} 554200903983e12253942381e2f9331479848c0b94Yifan Hong 564200903983e12253942381e2f9331479848c0b94Yifan Hong// static 57868aff8458f94a81cf932537c4b7354074df181eSteven Morelandstd::string StringHelper::Capitalize(const std::string &in) { 58868aff8458f94a81cf932537c4b7354074df181eSteven Moreland std::string out{in}; 59868aff8458f94a81cf932537c4b7354074df181eSteven Moreland 60868aff8458f94a81cf932537c4b7354074df181eSteven Moreland if(!out.empty()) { 61868aff8458f94a81cf932537c4b7354074df181eSteven Moreland out[0] = toupper(out[0]); 62868aff8458f94a81cf932537c4b7354074df181eSteven Moreland } 63868aff8458f94a81cf932537c4b7354074df181eSteven Moreland 64868aff8458f94a81cf932537c4b7354074df181eSteven Moreland return out; 65868aff8458f94a81cf932537c4b7354074df181eSteven Moreland} 66868aff8458f94a81cf932537c4b7354074df181eSteven Moreland 67868aff8458f94a81cf932537c4b7354074df181eSteven Moreland// static 684200903983e12253942381e2f9331479848c0b94Yifan Hongvoid StringHelper::Tokenize(const std::string &in, 694200903983e12253942381e2f9331479848c0b94Yifan Hong std::vector<std::string> *vec) { 7095b46238e9f0420e2e79ce2bda2cabc24aff4769Steven Moreland 714200903983e12253942381e2f9331479848c0b94Yifan Hong std::smatch match; 724200903983e12253942381e2f9331479848c0b94Yifan Hong if (in.empty()) { 734200903983e12253942381e2f9331479848c0b94Yifan Hong vec->clear(); 744200903983e12253942381e2f9331479848c0b94Yifan Hong return; 754200903983e12253942381e2f9331479848c0b94Yifan Hong } 764200903983e12253942381e2f9331479848c0b94Yifan Hong std::string copy(in); 774200903983e12253942381e2f9331479848c0b94Yifan Hong vec->clear(); 784200903983e12253942381e2f9331479848c0b94Yifan Hong std::vector<std::string> matches; 794200903983e12253942381e2f9331479848c0b94Yifan Hong 804200903983e12253942381e2f9331479848c0b94Yifan Hong copy = RTrimAll(copy, "_"); 814200903983e12253942381e2f9331479848c0b94Yifan Hong while(!copy.empty()) { 824200903983e12253942381e2f9331479848c0b94Yifan Hong copy = LTrimAll(copy, "_"); 834200903983e12253942381e2f9331479848c0b94Yifan Hong if (std::regex_search(copy, match, kStartLowercase)) 844200903983e12253942381e2f9331479848c0b94Yifan Hong matches.push_back(match.str(0)); 854200903983e12253942381e2f9331479848c0b94Yifan Hong if (std::regex_search(copy, match, kStartCapcase)) 864200903983e12253942381e2f9331479848c0b94Yifan Hong matches.push_back(match.str(0)); 874200903983e12253942381e2f9331479848c0b94Yifan Hong if (std::regex_search(copy, match, kStartUppercase)) 884200903983e12253942381e2f9331479848c0b94Yifan Hong matches.push_back(match.str(0)); 894200903983e12253942381e2f9331479848c0b94Yifan Hong if (!matches.empty()) { 904200903983e12253942381e2f9331479848c0b94Yifan Hong std::string &maxmatch = matches[0]; 914200903983e12253942381e2f9331479848c0b94Yifan Hong for (std::string &match : matches) 924200903983e12253942381e2f9331479848c0b94Yifan Hong if(match.length() > maxmatch.length()) 934200903983e12253942381e2f9331479848c0b94Yifan Hong maxmatch = match; 944200903983e12253942381e2f9331479848c0b94Yifan Hong vec->push_back(maxmatch); 954200903983e12253942381e2f9331479848c0b94Yifan Hong copy = copy.substr(maxmatch.length()); 964200903983e12253942381e2f9331479848c0b94Yifan Hong matches.clear(); 974200903983e12253942381e2f9331479848c0b94Yifan Hong continue; 9895b46238e9f0420e2e79ce2bda2cabc24aff4769Steven Moreland } 994200903983e12253942381e2f9331479848c0b94Yifan Hong LOG(WARNING) << "Could not stylize \"" << in << "\""; 1004200903983e12253942381e2f9331479848c0b94Yifan Hong // don't know what to do, so push back the rest of the string. 1014200903983e12253942381e2f9331479848c0b94Yifan Hong vec->push_back(copy); 10295b46238e9f0420e2e79ce2bda2cabc24aff4769Steven Moreland } 1034200903983e12253942381e2f9331479848c0b94Yifan Hong} 10495b46238e9f0420e2e79ce2bda2cabc24aff4769Steven Moreland 1054200903983e12253942381e2f9331479848c0b94Yifan Hong// static 1064200903983e12253942381e2f9331479848c0b94Yifan Hongstd::string StringHelper::ToCamelCase(const std::string &in) { 1074200903983e12253942381e2f9331479848c0b94Yifan Hong std::vector<std::string> components; 1084200903983e12253942381e2f9331479848c0b94Yifan Hong Tokenize(in, &components); 1094200903983e12253942381e2f9331479848c0b94Yifan Hong if (components.empty()) { 1104200903983e12253942381e2f9331479848c0b94Yifan Hong if (!in.empty()) 1114200903983e12253942381e2f9331479848c0b94Yifan Hong LOG(WARNING) << "Could not stylize \"" << in << "\""; 1124200903983e12253942381e2f9331479848c0b94Yifan Hong return in; 1134200903983e12253942381e2f9331479848c0b94Yifan Hong } 1144200903983e12253942381e2f9331479848c0b94Yifan Hong components[0] = Lowercase(components[0]); 1154200903983e12253942381e2f9331479848c0b94Yifan Hong for (size_t i = 1; i < components.size(); i++) { 1164200903983e12253942381e2f9331479848c0b94Yifan Hong components[i] = Capitalize(components[i]); 1174200903983e12253942381e2f9331479848c0b94Yifan Hong } 1184200903983e12253942381e2f9331479848c0b94Yifan Hong return JoinStrings(components, ""); 11995b46238e9f0420e2e79ce2bda2cabc24aff4769Steven Moreland} 12095b46238e9f0420e2e79ce2bda2cabc24aff4769Steven Moreland 12195b46238e9f0420e2e79ce2bda2cabc24aff4769Steven Moreland// static 1224200903983e12253942381e2f9331479848c0b94Yifan Hongstd::string StringHelper::ToPascalCase(const std::string &in) { 1234200903983e12253942381e2f9331479848c0b94Yifan Hong std::vector<std::string> components; 1244200903983e12253942381e2f9331479848c0b94Yifan Hong Tokenize(in, &components); 1254200903983e12253942381e2f9331479848c0b94Yifan Hong for (size_t i = 0; i < components.size(); i++) { 1264200903983e12253942381e2f9331479848c0b94Yifan Hong components[i] = Capitalize(components[i]); 1274200903983e12253942381e2f9331479848c0b94Yifan Hong } 1284200903983e12253942381e2f9331479848c0b94Yifan Hong return JoinStrings(components, ""); 1294200903983e12253942381e2f9331479848c0b94Yifan Hong} 13095b46238e9f0420e2e79ce2bda2cabc24aff4769Steven Moreland 1314200903983e12253942381e2f9331479848c0b94Yifan Hong// static 1324200903983e12253942381e2f9331479848c0b94Yifan Hongstd::string StringHelper::ToUpperSnakeCase(const std::string &in) { 1334200903983e12253942381e2f9331479848c0b94Yifan Hong std::vector<std::string> components; 1344200903983e12253942381e2f9331479848c0b94Yifan Hong Tokenize(in, &components); 1354200903983e12253942381e2f9331479848c0b94Yifan Hong for (size_t i = 0; i < components.size(); i++) { 1364200903983e12253942381e2f9331479848c0b94Yifan Hong components[i] = Uppercase(components[i]); 137868aff8458f94a81cf932537c4b7354074df181eSteven Moreland } 1384200903983e12253942381e2f9331479848c0b94Yifan Hong return JoinStrings(components, "_"); 1394200903983e12253942381e2f9331479848c0b94Yifan Hong} 140868aff8458f94a81cf932537c4b7354074df181eSteven Moreland 1414200903983e12253942381e2f9331479848c0b94Yifan Hong// static 1424200903983e12253942381e2f9331479848c0b94Yifan Hongstd::string StringHelper::ToLowerSnakeCase(const std::string &in) { 1434200903983e12253942381e2f9331479848c0b94Yifan Hong std::vector<std::string> components; 1444200903983e12253942381e2f9331479848c0b94Yifan Hong Tokenize(in, &components); 1454200903983e12253942381e2f9331479848c0b94Yifan Hong for (size_t i = 0; i < components.size(); i++) { 1464200903983e12253942381e2f9331479848c0b94Yifan Hong components[i] = Lowercase(components[i]); 1474200903983e12253942381e2f9331479848c0b94Yifan Hong } 1484200903983e12253942381e2f9331479848c0b94Yifan Hong return JoinStrings(components, "_"); 1494200903983e12253942381e2f9331479848c0b94Yifan Hong} 1504200903983e12253942381e2f9331479848c0b94Yifan Hong 1514200903983e12253942381e2f9331479848c0b94Yifan Hong// static 1524200903983e12253942381e2f9331479848c0b94Yifan Hongstd::string StringHelper::ToCase(StringHelper::Case c, const std::string &in) { 1534200903983e12253942381e2f9331479848c0b94Yifan Hong switch(c) { 1544200903983e12253942381e2f9331479848c0b94Yifan Hong case kCamelCase: 1554200903983e12253942381e2f9331479848c0b94Yifan Hong return ToCamelCase(in); 1564200903983e12253942381e2f9331479848c0b94Yifan Hong case kPascalCase: 1574200903983e12253942381e2f9331479848c0b94Yifan Hong return ToPascalCase(in); 1584200903983e12253942381e2f9331479848c0b94Yifan Hong case kUpperSnakeCase: 1594200903983e12253942381e2f9331479848c0b94Yifan Hong return ToUpperSnakeCase(in); 1604200903983e12253942381e2f9331479848c0b94Yifan Hong case kLowerSnakeCase: 1614200903983e12253942381e2f9331479848c0b94Yifan Hong return ToLowerSnakeCase(in); 1624200903983e12253942381e2f9331479848c0b94Yifan Hong case kNoCase: 1634200903983e12253942381e2f9331479848c0b94Yifan Hong return in; 1644200903983e12253942381e2f9331479848c0b94Yifan Hong } 1654200903983e12253942381e2f9331479848c0b94Yifan Hong LOG(FATAL) << "Should not reach here."; 1664200903983e12253942381e2f9331479848c0b94Yifan Hong return in; 167868aff8458f94a81cf932537c4b7354074df181eSteven Moreland} 168868aff8458f94a81cf932537c4b7354074df181eSteven Moreland 169868aff8458f94a81cf932537c4b7354074df181eSteven Moreland// static 170f9a6ef3343d757b878a780dc3839ab8d21861ae5Steven Morelandbool StringHelper::EndsWith(const std::string &in, const std::string &suffix) { 171f9a6ef3343d757b878a780dc3839ab8d21861ae5Steven Moreland return in.size() >= suffix.size() && 172f9a6ef3343d757b878a780dc3839ab8d21861ae5Steven Moreland in.substr(in.size() - suffix.size()) == suffix; 173f9a6ef3343d757b878a780dc3839ab8d21861ae5Steven Moreland} 174f9a6ef3343d757b878a780dc3839ab8d21861ae5Steven Moreland 175f9a6ef3343d757b878a780dc3839ab8d21861ae5Steven Moreland// static 17695b46238e9f0420e2e79ce2bda2cabc24aff4769Steven Morelandbool StringHelper::StartsWith(const std::string &in, const std::string &prefix) { 17795b46238e9f0420e2e79ce2bda2cabc24aff4769Steven Moreland return in.size() >= prefix.size() && 17895b46238e9f0420e2e79ce2bda2cabc24aff4769Steven Moreland in.substr(0, prefix.size()) == prefix; 17995b46238e9f0420e2e79ce2bda2cabc24aff4769Steven Moreland} 18095b46238e9f0420e2e79ce2bda2cabc24aff4769Steven Moreland 18195b46238e9f0420e2e79ce2bda2cabc24aff4769Steven Moreland// static 182f9a6ef3343d757b878a780dc3839ab8d21861ae5Steven Morelandstd::string StringHelper::RTrim(const std::string &in, const std::string &suffix) { 183f9a6ef3343d757b878a780dc3839ab8d21861ae5Steven Moreland if (EndsWith(in, suffix)) { 184f9a6ef3343d757b878a780dc3839ab8d21861ae5Steven Moreland return in.substr(0, in.size() - suffix.size()); 185f9a6ef3343d757b878a780dc3839ab8d21861ae5Steven Moreland } 18695b46238e9f0420e2e79ce2bda2cabc24aff4769Steven Moreland 187f9a6ef3343d757b878a780dc3839ab8d21861ae5Steven Moreland return in; 188f9a6ef3343d757b878a780dc3839ab8d21861ae5Steven Moreland} 189f9a6ef3343d757b878a780dc3839ab8d21861ae5Steven Moreland 190f9a6ef3343d757b878a780dc3839ab8d21861ae5Steven Moreland// static 191f9a6ef3343d757b878a780dc3839ab8d21861ae5Steven Morelandstd::string StringHelper::LTrim(const std::string &in, const std::string &prefix) { 192f9a6ef3343d757b878a780dc3839ab8d21861ae5Steven Moreland if (StartsWith(in, prefix)) { 193f9a6ef3343d757b878a780dc3839ab8d21861ae5Steven Moreland return in.substr(prefix.size()); 19495b46238e9f0420e2e79ce2bda2cabc24aff4769Steven Moreland } 19595b46238e9f0420e2e79ce2bda2cabc24aff4769Steven Moreland 19695b46238e9f0420e2e79ce2bda2cabc24aff4769Steven Moreland return in; 19795b46238e9f0420e2e79ce2bda2cabc24aff4769Steven Moreland} 19895b46238e9f0420e2e79ce2bda2cabc24aff4769Steven Moreland 1994200903983e12253942381e2f9331479848c0b94Yifan Hong// static 2004200903983e12253942381e2f9331479848c0b94Yifan Hongstd::string StringHelper::RTrimAll(const std::string &in, const std::string &suffix) { 2014200903983e12253942381e2f9331479848c0b94Yifan Hong std::string copy(in); 2024200903983e12253942381e2f9331479848c0b94Yifan Hong while (EndsWith(copy, suffix)) { 2034200903983e12253942381e2f9331479848c0b94Yifan Hong copy = copy.substr(0, copy.size() - suffix.size()); 2044200903983e12253942381e2f9331479848c0b94Yifan Hong } 2054200903983e12253942381e2f9331479848c0b94Yifan Hong 2064200903983e12253942381e2f9331479848c0b94Yifan Hong return copy; 2074200903983e12253942381e2f9331479848c0b94Yifan Hong} 2084200903983e12253942381e2f9331479848c0b94Yifan Hong 2094200903983e12253942381e2f9331479848c0b94Yifan Hong// static 2104200903983e12253942381e2f9331479848c0b94Yifan Hongstd::string StringHelper::LTrimAll(const std::string &in, const std::string &prefix) { 2114200903983e12253942381e2f9331479848c0b94Yifan Hong std::string copy(in); 2124200903983e12253942381e2f9331479848c0b94Yifan Hong while (StartsWith(copy, prefix)) { 2134200903983e12253942381e2f9331479848c0b94Yifan Hong copy = copy.substr(prefix.size()); 2144200903983e12253942381e2f9331479848c0b94Yifan Hong } 2154200903983e12253942381e2f9331479848c0b94Yifan Hong 2164200903983e12253942381e2f9331479848c0b94Yifan Hong return copy; 2174200903983e12253942381e2f9331479848c0b94Yifan Hong} 218f9a6ef3343d757b878a780dc3839ab8d21861ae5Steven Moreland 21995b46238e9f0420e2e79ce2bda2cabc24aff4769Steven Moreland// static 220af44014f7b42697be072a7bde111c432b313d684Steven Morelandvoid StringHelper::SplitString( 221af44014f7b42697be072a7bde111c432b313d684Steven Moreland const std::string &s, char c, std::vector<std::string> *components) { 222af44014f7b42697be072a7bde111c432b313d684Steven Moreland components->clear(); 223af44014f7b42697be072a7bde111c432b313d684Steven Moreland 224af44014f7b42697be072a7bde111c432b313d684Steven Moreland size_t startPos = 0; 225af44014f7b42697be072a7bde111c432b313d684Steven Moreland size_t matchPos; 226af44014f7b42697be072a7bde111c432b313d684Steven Moreland while ((matchPos = s.find(c, startPos)) != std::string::npos) { 227af44014f7b42697be072a7bde111c432b313d684Steven Moreland components->push_back(s.substr(startPos, matchPos - startPos)); 228af44014f7b42697be072a7bde111c432b313d684Steven Moreland startPos = matchPos + 1; 229af44014f7b42697be072a7bde111c432b313d684Steven Moreland } 230af44014f7b42697be072a7bde111c432b313d684Steven Moreland 231db364989ebda11138911ef1c2a6e69e6299f05f8Yifan Hong if (startPos <= s.length()) { 232af44014f7b42697be072a7bde111c432b313d684Steven Moreland components->push_back(s.substr(startPos)); 233af44014f7b42697be072a7bde111c432b313d684Steven Moreland } 234af44014f7b42697be072a7bde111c432b313d684Steven Moreland} 235af44014f7b42697be072a7bde111c432b313d684Steven Moreland 236af44014f7b42697be072a7bde111c432b313d684Steven Moreland// static 237af44014f7b42697be072a7bde111c432b313d684Steven Morelandstd::string StringHelper::JoinStrings( 238af44014f7b42697be072a7bde111c432b313d684Steven Moreland const std::vector<std::string> &components, 239af44014f7b42697be072a7bde111c432b313d684Steven Moreland const std::string &separator) { 240af44014f7b42697be072a7bde111c432b313d684Steven Moreland std::string out; 241af44014f7b42697be072a7bde111c432b313d684Steven Moreland bool first = true; 242af44014f7b42697be072a7bde111c432b313d684Steven Moreland for (const auto &component : components) { 243af44014f7b42697be072a7bde111c432b313d684Steven Moreland if (!first) { 244af44014f7b42697be072a7bde111c432b313d684Steven Moreland out += separator; 245af44014f7b42697be072a7bde111c432b313d684Steven Moreland } 246af44014f7b42697be072a7bde111c432b313d684Steven Moreland out += component; 247af44014f7b42697be072a7bde111c432b313d684Steven Moreland 248af44014f7b42697be072a7bde111c432b313d684Steven Moreland first = false; 249af44014f7b42697be072a7bde111c432b313d684Steven Moreland } 250af44014f7b42697be072a7bde111c432b313d684Steven Moreland 251af44014f7b42697be072a7bde111c432b313d684Steven Moreland return out; 252af44014f7b42697be072a7bde111c432b313d684Steven Moreland} 253af44014f7b42697be072a7bde111c432b313d684Steven Moreland 254af44014f7b42697be072a7bde111c432b313d684Steven Moreland} // namespace android 255af44014f7b42697be072a7bde111c432b313d684Steven Moreland 256