blob: 8f3c7d998a3e79daf670d69c9d43f754e8ec3ddc [file] [log] [blame]
Dan Albert00716d72015-03-13 22:57:40 -07001/*
2 * Copyright (C) 2015 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Elliott Hughesb6351622015-12-04 22:00:26 -080017#include "android-base/strings.h"
Dan Albert00716d72015-03-13 22:57:40 -070018
Dan Albert0d716d02015-03-19 13:24:26 -070019#include <stdlib.h>
Dan Albert852d2e72015-03-26 23:23:32 -070020#include <string.h>
Dan Albert0d716d02015-03-19 13:24:26 -070021
Dan Albert00716d72015-03-13 22:57:40 -070022#include <string>
23#include <vector>
24
25namespace android {
26namespace base {
27
Dan Albert0d716d02015-03-19 13:24:26 -070028#define CHECK_NE(a, b) \
29 if ((a) == (b)) abort();
30
31std::vector<std::string> Split(const std::string& s,
32 const std::string& delimiters) {
33 CHECK_NE(delimiters.size(), 0U);
34
Elliott Hughes9964efc2015-04-24 23:02:00 -070035 std::vector<std::string> result;
Dan Albert0d716d02015-03-19 13:24:26 -070036
37 size_t base = 0;
38 size_t found;
Elliott Hughesb2264792017-02-07 15:30:24 -080039 while (true) {
Dan Albert0d716d02015-03-19 13:24:26 -070040 found = s.find_first_of(delimiters, base);
Elliott Hughes9964efc2015-04-24 23:02:00 -070041 result.push_back(s.substr(base, found - base));
Elliott Hughesb2264792017-02-07 15:30:24 -080042 if (found == s.npos) break;
Dan Albert0d716d02015-03-19 13:24:26 -070043 base = found + 1;
Elliott Hughesb2264792017-02-07 15:30:24 -080044 }
Dan Albert0d716d02015-03-19 13:24:26 -070045
Elliott Hughes9964efc2015-04-24 23:02:00 -070046 return result;
Dan Albert00716d72015-03-13 22:57:40 -070047}
48
Yi-Yo Chiang5ad131f2021-11-09 19:48:09 +080049std::vector<std::string> Tokenize(const std::string& s, const std::string& delimiters) {
50 CHECK_NE(delimiters.size(), 0U);
51
52 std::vector<std::string> result;
53 size_t end = 0;
54
55 while (true) {
56 size_t base = s.find_first_not_of(delimiters, end);
57 if (base == s.npos) {
58 break;
59 }
60 end = s.find_first_of(delimiters, base);
61 result.push_back(s.substr(base, end - base));
62 }
63 return result;
64}
65
Dan Albert00716d72015-03-13 22:57:40 -070066std::string Trim(const std::string& s) {
67 std::string result;
68
69 if (s.size() == 0) {
70 return result;
71 }
72
73 size_t start_index = 0;
74 size_t end_index = s.size() - 1;
75
76 // Skip initial whitespace.
77 while (start_index < s.size()) {
78 if (!isspace(s[start_index])) {
79 break;
80 }
81 start_index++;
82 }
83
84 // Skip terminating whitespace.
85 while (end_index >= start_index) {
86 if (!isspace(s[end_index])) {
87 break;
88 }
89 end_index--;
90 }
91
92 // All spaces, no beef.
93 if (end_index < start_index) {
94 return "";
95 }
96 // Start_index is the first non-space, end_index is the last one.
97 return s.substr(start_index, end_index - start_index + 1);
98}
99
Dan Albert0d20cc92015-05-21 18:37:36 -0700100// These cases are probably the norm, so we mark them extern in the header to
101// aid compile time and binary size.
102template std::string Join(const std::vector<std::string>&, char);
103template std::string Join(const std::vector<const char*>&, char);
Casey Dahlinf8557e72015-10-30 18:54:38 -0700104template std::string Join(const std::vector<std::string>&, const std::string&);
105template std::string Join(const std::vector<const char*>&, const std::string&);
Dan Albert00716d72015-03-13 22:57:40 -0700106
Yurii Zubrytskyief973ce2019-03-19 17:03:42 -0700107bool StartsWith(std::string_view s, std::string_view prefix) {
108 return s.substr(0, prefix.size()) == prefix;
Dan Albert00716d72015-03-13 22:57:40 -0700109}
110
Yurii Zubrytskyief973ce2019-03-19 17:03:42 -0700111bool StartsWith(std::string_view s, char prefix) {
112 return !s.empty() && s.front() == prefix;
Elliott Hughes9955af22017-12-20 09:41:00 -0800113}
114
Yurii Zubrytskyief973ce2019-03-19 17:03:42 -0700115bool StartsWithIgnoreCase(std::string_view s, std::string_view prefix) {
116 return s.size() >= prefix.size() && strncasecmp(s.data(), prefix.data(), prefix.size()) == 0;
Yabin Cuia87b3882018-10-30 15:49:53 -0700117}
118
Yurii Zubrytskyief973ce2019-03-19 17:03:42 -0700119bool EndsWith(std::string_view s, std::string_view suffix) {
120 return s.size() >= suffix.size() && s.substr(s.size() - suffix.size(), suffix.size()) == suffix;
Elliott Hughes85484272016-10-25 14:56:04 -0700121}
122
Yurii Zubrytskyief973ce2019-03-19 17:03:42 -0700123bool EndsWith(std::string_view s, char suffix) {
124 return !s.empty() && s.back() == suffix;
Elliott Hughes9955af22017-12-20 09:41:00 -0800125}
126
Yurii Zubrytskyief973ce2019-03-19 17:03:42 -0700127bool EndsWithIgnoreCase(std::string_view s, std::string_view suffix) {
128 return s.size() >= suffix.size() &&
129 strncasecmp(s.data() + (s.size() - suffix.size()), suffix.data(), suffix.size()) == 0;
Elliott Hughes85484272016-10-25 14:56:04 -0700130}
131
Yurii Zubrytskyief973ce2019-03-19 17:03:42 -0700132bool EqualsIgnoreCase(std::string_view lhs, std::string_view rhs) {
133 return lhs.size() == rhs.size() && strncasecmp(lhs.data(), rhs.data(), lhs.size()) == 0;
Elliott Hughes7872ff32017-01-13 18:51:32 -0800134}
135
Elliott Hughes80ac17b2019-11-18 16:01:21 -0800136std::string StringReplace(std::string_view s, std::string_view from, std::string_view to,
137 bool all) {
138 if (from.empty()) return std::string(s);
139
140 std::string result;
141 std::string_view::size_type start_pos = 0;
142 do {
143 std::string_view::size_type pos = s.find(from, start_pos);
144 if (pos == std::string_view::npos) break;
145
146 result.append(s.data() + start_pos, pos - start_pos);
147 result.append(to.data(), to.size());
148
149 start_pos = pos + from.size();
150 } while (all);
151 result.append(s.data() + start_pos, s.size() - start_pos);
152 return result;
153}
154
Dan Albert00716d72015-03-13 22:57:40 -0700155} // namespace base
156} // namespace android