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