1*8f0ba417SAndroid Build Coastguard Worker /*
2*8f0ba417SAndroid Build Coastguard Worker * Copyright (C) 2015 The Android Open Source Project
3*8f0ba417SAndroid Build Coastguard Worker *
4*8f0ba417SAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*8f0ba417SAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*8f0ba417SAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*8f0ba417SAndroid Build Coastguard Worker *
8*8f0ba417SAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*8f0ba417SAndroid Build Coastguard Worker *
10*8f0ba417SAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*8f0ba417SAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*8f0ba417SAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*8f0ba417SAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*8f0ba417SAndroid Build Coastguard Worker * limitations under the License.
15*8f0ba417SAndroid Build Coastguard Worker */
16*8f0ba417SAndroid Build Coastguard Worker
17*8f0ba417SAndroid Build Coastguard Worker #include "android-base/strings.h"
18*8f0ba417SAndroid Build Coastguard Worker
19*8f0ba417SAndroid Build Coastguard Worker #include "android-base/stringprintf.h"
20*8f0ba417SAndroid Build Coastguard Worker
21*8f0ba417SAndroid Build Coastguard Worker #include <stdlib.h>
22*8f0ba417SAndroid Build Coastguard Worker #include <string.h>
23*8f0ba417SAndroid Build Coastguard Worker
24*8f0ba417SAndroid Build Coastguard Worker #include <string>
25*8f0ba417SAndroid Build Coastguard Worker #include <vector>
26*8f0ba417SAndroid Build Coastguard Worker
27*8f0ba417SAndroid Build Coastguard Worker // Wraps the posix version of strerror_r to make it available in translation units
28*8f0ba417SAndroid Build Coastguard Worker // that define _GNU_SOURCE.
29*8f0ba417SAndroid Build Coastguard Worker extern "C" int posix_strerror_r(int errnum, char* buf, size_t buflen);
30*8f0ba417SAndroid Build Coastguard Worker
31*8f0ba417SAndroid Build Coastguard Worker namespace android {
32*8f0ba417SAndroid Build Coastguard Worker namespace base {
33*8f0ba417SAndroid Build Coastguard Worker
34*8f0ba417SAndroid Build Coastguard Worker #define CHECK_NE(a, b) \
35*8f0ba417SAndroid Build Coastguard Worker if ((a) == (b)) abort();
36*8f0ba417SAndroid Build Coastguard Worker
Split(const std::string & s,const std::string & delimiters)37*8f0ba417SAndroid Build Coastguard Worker std::vector<std::string> Split(const std::string& s,
38*8f0ba417SAndroid Build Coastguard Worker const std::string& delimiters) {
39*8f0ba417SAndroid Build Coastguard Worker CHECK_NE(delimiters.size(), 0U);
40*8f0ba417SAndroid Build Coastguard Worker
41*8f0ba417SAndroid Build Coastguard Worker std::vector<std::string> result;
42*8f0ba417SAndroid Build Coastguard Worker
43*8f0ba417SAndroid Build Coastguard Worker size_t base = 0;
44*8f0ba417SAndroid Build Coastguard Worker size_t found;
45*8f0ba417SAndroid Build Coastguard Worker while (true) {
46*8f0ba417SAndroid Build Coastguard Worker found = s.find_first_of(delimiters, base);
47*8f0ba417SAndroid Build Coastguard Worker result.push_back(s.substr(base, found - base));
48*8f0ba417SAndroid Build Coastguard Worker if (found == s.npos) break;
49*8f0ba417SAndroid Build Coastguard Worker base = found + 1;
50*8f0ba417SAndroid Build Coastguard Worker }
51*8f0ba417SAndroid Build Coastguard Worker
52*8f0ba417SAndroid Build Coastguard Worker return result;
53*8f0ba417SAndroid Build Coastguard Worker }
54*8f0ba417SAndroid Build Coastguard Worker
Tokenize(const std::string & s,const std::string & delimiters)55*8f0ba417SAndroid Build Coastguard Worker std::vector<std::string> Tokenize(const std::string& s, const std::string& delimiters) {
56*8f0ba417SAndroid Build Coastguard Worker CHECK_NE(delimiters.size(), 0U);
57*8f0ba417SAndroid Build Coastguard Worker
58*8f0ba417SAndroid Build Coastguard Worker std::vector<std::string> result;
59*8f0ba417SAndroid Build Coastguard Worker size_t end = 0;
60*8f0ba417SAndroid Build Coastguard Worker
61*8f0ba417SAndroid Build Coastguard Worker while (true) {
62*8f0ba417SAndroid Build Coastguard Worker size_t base = s.find_first_not_of(delimiters, end);
63*8f0ba417SAndroid Build Coastguard Worker if (base == s.npos) {
64*8f0ba417SAndroid Build Coastguard Worker break;
65*8f0ba417SAndroid Build Coastguard Worker }
66*8f0ba417SAndroid Build Coastguard Worker end = s.find_first_of(delimiters, base);
67*8f0ba417SAndroid Build Coastguard Worker result.push_back(s.substr(base, end - base));
68*8f0ba417SAndroid Build Coastguard Worker }
69*8f0ba417SAndroid Build Coastguard Worker return result;
70*8f0ba417SAndroid Build Coastguard Worker }
71*8f0ba417SAndroid Build Coastguard Worker
72*8f0ba417SAndroid Build Coastguard Worker template std::string Trim(const char*&);
73*8f0ba417SAndroid Build Coastguard Worker template std::string Trim(const char*&&);
74*8f0ba417SAndroid Build Coastguard Worker template std::string Trim(const std::string&);
75*8f0ba417SAndroid Build Coastguard Worker template std::string Trim(const std::string&&);
76*8f0ba417SAndroid Build Coastguard Worker template std::string Trim(std::string_view&);
77*8f0ba417SAndroid Build Coastguard Worker template std::string Trim(std::string_view&&);
78*8f0ba417SAndroid Build Coastguard Worker
79*8f0ba417SAndroid Build Coastguard Worker // These cases were measured either to be used during build by more than one binary, or during
80*8f0ba417SAndroid Build Coastguard Worker // runtime as a significant portion of total calls.
81*8f0ba417SAndroid Build Coastguard Worker // Instantiate them to aid compile time and binary size.
82*8f0ba417SAndroid Build Coastguard Worker template std::string Join(std::vector<std::string>&, char);
83*8f0ba417SAndroid Build Coastguard Worker template std::string Join(std::vector<std::string>&, const char*);
84*8f0ba417SAndroid Build Coastguard Worker template std::string Join(std::vector<std::string>&&, const char*);
85*8f0ba417SAndroid Build Coastguard Worker template std::string Join(const std::vector<std::string>&, char);
86*8f0ba417SAndroid Build Coastguard Worker template std::string Join(const std::vector<std::string>&, const char*);
87*8f0ba417SAndroid Build Coastguard Worker template std::string Join(const std::vector<std::string>&&, const char*);
88*8f0ba417SAndroid Build Coastguard Worker template std::string Join(std::set<std::string>&, const char*);
89*8f0ba417SAndroid Build Coastguard Worker template std::string Join(const std::set<std::string>&, char);
90*8f0ba417SAndroid Build Coastguard Worker template std::string Join(const std::set<std::string>&, const char*);
91*8f0ba417SAndroid Build Coastguard Worker template std::string Join(const std::unordered_set<std::string>&, const char*);
92*8f0ba417SAndroid Build Coastguard Worker
93*8f0ba417SAndroid Build Coastguard Worker
StartsWith(std::string_view s,std::string_view prefix)94*8f0ba417SAndroid Build Coastguard Worker bool StartsWith(std::string_view s, std::string_view prefix) {
95*8f0ba417SAndroid Build Coastguard Worker return s.starts_with(prefix);
96*8f0ba417SAndroid Build Coastguard Worker }
97*8f0ba417SAndroid Build Coastguard Worker
StartsWith(std::string_view s,char prefix)98*8f0ba417SAndroid Build Coastguard Worker bool StartsWith(std::string_view s, char prefix) {
99*8f0ba417SAndroid Build Coastguard Worker return s.starts_with(prefix);
100*8f0ba417SAndroid Build Coastguard Worker }
101*8f0ba417SAndroid Build Coastguard Worker
StartsWithIgnoreCase(std::string_view s,std::string_view prefix)102*8f0ba417SAndroid Build Coastguard Worker bool StartsWithIgnoreCase(std::string_view s, std::string_view prefix) {
103*8f0ba417SAndroid Build Coastguard Worker return s.size() >= prefix.size() && strncasecmp(s.data(), prefix.data(), prefix.size()) == 0;
104*8f0ba417SAndroid Build Coastguard Worker }
105*8f0ba417SAndroid Build Coastguard Worker
EndsWith(std::string_view s,std::string_view suffix)106*8f0ba417SAndroid Build Coastguard Worker bool EndsWith(std::string_view s, std::string_view suffix) {
107*8f0ba417SAndroid Build Coastguard Worker return s.ends_with(suffix);
108*8f0ba417SAndroid Build Coastguard Worker }
109*8f0ba417SAndroid Build Coastguard Worker
EndsWith(std::string_view s,char suffix)110*8f0ba417SAndroid Build Coastguard Worker bool EndsWith(std::string_view s, char suffix) {
111*8f0ba417SAndroid Build Coastguard Worker return s.ends_with(suffix);
112*8f0ba417SAndroid Build Coastguard Worker }
113*8f0ba417SAndroid Build Coastguard Worker
EndsWithIgnoreCase(std::string_view s,std::string_view suffix)114*8f0ba417SAndroid Build Coastguard Worker bool EndsWithIgnoreCase(std::string_view s, std::string_view suffix) {
115*8f0ba417SAndroid Build Coastguard Worker return s.size() >= suffix.size() &&
116*8f0ba417SAndroid Build Coastguard Worker strncasecmp(s.data() + (s.size() - suffix.size()), suffix.data(), suffix.size()) == 0;
117*8f0ba417SAndroid Build Coastguard Worker }
118*8f0ba417SAndroid Build Coastguard Worker
EqualsIgnoreCase(std::string_view lhs,std::string_view rhs)119*8f0ba417SAndroid Build Coastguard Worker bool EqualsIgnoreCase(std::string_view lhs, std::string_view rhs) {
120*8f0ba417SAndroid Build Coastguard Worker return lhs.size() == rhs.size() && strncasecmp(lhs.data(), rhs.data(), lhs.size()) == 0;
121*8f0ba417SAndroid Build Coastguard Worker }
122*8f0ba417SAndroid Build Coastguard Worker
StringReplace(std::string_view s,std::string_view from,std::string_view to,bool all)123*8f0ba417SAndroid Build Coastguard Worker std::string StringReplace(std::string_view s, std::string_view from, std::string_view to,
124*8f0ba417SAndroid Build Coastguard Worker bool all) {
125*8f0ba417SAndroid Build Coastguard Worker if (from.empty()) return std::string(s);
126*8f0ba417SAndroid Build Coastguard Worker
127*8f0ba417SAndroid Build Coastguard Worker std::string result;
128*8f0ba417SAndroid Build Coastguard Worker std::string_view::size_type start_pos = 0;
129*8f0ba417SAndroid Build Coastguard Worker do {
130*8f0ba417SAndroid Build Coastguard Worker std::string_view::size_type pos = s.find(from, start_pos);
131*8f0ba417SAndroid Build Coastguard Worker if (pos == std::string_view::npos) break;
132*8f0ba417SAndroid Build Coastguard Worker
133*8f0ba417SAndroid Build Coastguard Worker result.append(s.data() + start_pos, pos - start_pos);
134*8f0ba417SAndroid Build Coastguard Worker result.append(to.data(), to.size());
135*8f0ba417SAndroid Build Coastguard Worker
136*8f0ba417SAndroid Build Coastguard Worker start_pos = pos + from.size();
137*8f0ba417SAndroid Build Coastguard Worker } while (all);
138*8f0ba417SAndroid Build Coastguard Worker result.append(s.data() + start_pos, s.size() - start_pos);
139*8f0ba417SAndroid Build Coastguard Worker return result;
140*8f0ba417SAndroid Build Coastguard Worker }
141*8f0ba417SAndroid Build Coastguard Worker
ErrnoNumberAsString(int errnum)142*8f0ba417SAndroid Build Coastguard Worker std::string ErrnoNumberAsString(int errnum) {
143*8f0ba417SAndroid Build Coastguard Worker char buf[100];
144*8f0ba417SAndroid Build Coastguard Worker buf[0] = '\0';
145*8f0ba417SAndroid Build Coastguard Worker int strerror_err = posix_strerror_r(errnum, buf, sizeof(buf));
146*8f0ba417SAndroid Build Coastguard Worker if (strerror_err < 0) {
147*8f0ba417SAndroid Build Coastguard Worker return StringPrintf("Failed to convert errno %d to string: %d", errnum, strerror_err);
148*8f0ba417SAndroid Build Coastguard Worker }
149*8f0ba417SAndroid Build Coastguard Worker return buf;
150*8f0ba417SAndroid Build Coastguard Worker }
151*8f0ba417SAndroid Build Coastguard Worker
152*8f0ba417SAndroid Build Coastguard Worker } // namespace base
153*8f0ba417SAndroid Build Coastguard Worker } // namespace android
154