1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155
|
/*
* Copyright (C) 2015 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.
*/
#pragma once
#include <ctype.h>
#include <sstream>
#include <string>
#include <string_view>
#include <type_traits>
#include <utility>
#include <vector>
namespace android {
namespace base {
// Splits a string into a vector of strings.
//
// The string is split at each occurrence of a character in delimiters.
//
// The empty string is not a valid delimiter list.
std::vector<std::string> Split(const std::string& s,
const std::string& delimiters);
// Splits a string into a vector of string tokens.
//
// The string is split at each occurrence of a character in delimiters.
// Coalesce runs of delimiter bytes and ignore delimiter bytes at the start or
// end of string. In other words, return only nonempty string tokens.
// Use when you don't care about recovering the original string with Join().
//
// Example:
// Tokenize(" foo bar ", " ") => {"foo", "bar"}
// Join(Tokenize(" foo bar", " "), " ") => "foo bar"
//
// The empty string is not a valid delimiter list.
std::vector<std::string> Tokenize(const std::string& s, const std::string& delimiters);
namespace internal {
template <typename>
constexpr bool always_false_v = false;
}
template <typename T>
std::string Trim(T&& t) {
std::string_view sv;
std::string s;
if constexpr (std::is_convertible_v<T, std::string_view>) {
sv = std::forward<T>(t);
} else if constexpr (std::is_convertible_v<T, std::string>) {
// The previous version of this function allowed for types which are implicitly convertible
// to std::string but not to std::string_view. For these types we go through std::string first
// here in order to retain source compatibility.
s = t;
sv = s;
} else {
static_assert(internal::always_false_v<T>,
"Implicit conversion to std::string or std::string_view not possible");
}
// Skip initial whitespace.
while (!sv.empty() && isspace(sv.front())) {
sv.remove_prefix(1);
}
// Skip terminating whitespace.
while (!sv.empty() && isspace(sv.back())) {
sv.remove_suffix(1);
}
return std::string(sv);
}
// We instantiate the common cases in strings.cpp.
extern template std::string Trim(const char*&);
extern template std::string Trim(const char*&&);
extern template std::string Trim(const std::string&);
extern template std::string Trim(const std::string&&);
extern template std::string Trim(std::string_view&);
extern template std::string Trim(std::string_view&&);
// Joins a container of things into a single string, using the given separator.
template <typename ContainerT, typename SeparatorT>
std::string Join(const ContainerT& things, SeparatorT separator) {
if (things.empty()) {
return "";
}
std::ostringstream result;
result << *things.begin();
for (auto it = std::next(things.begin()); it != things.end(); ++it) {
result << separator << *it;
}
return result.str();
}
// We instantiate the common cases in strings.cpp.
extern template std::string Join(const std::vector<std::string>&, char);
extern template std::string Join(const std::vector<const char*>&, char);
extern template std::string Join(const std::vector<std::string>&, const std::string&);
extern template std::string Join(const std::vector<const char*>&, const std::string&);
// Tests whether 's' starts with 'prefix'.
bool StartsWith(std::string_view s, std::string_view prefix);
bool StartsWith(std::string_view s, char prefix);
bool StartsWithIgnoreCase(std::string_view s, std::string_view prefix);
// Tests whether 's' ends with 'suffix'.
bool EndsWith(std::string_view s, std::string_view suffix);
bool EndsWith(std::string_view s, char suffix);
bool EndsWithIgnoreCase(std::string_view s, std::string_view suffix);
// Tests whether 'lhs' equals 'rhs', ignoring case.
bool EqualsIgnoreCase(std::string_view lhs, std::string_view rhs);
// Removes `prefix` from the start of the given string and returns true (if
// it was present), false otherwise.
inline bool ConsumePrefix(std::string_view* s, std::string_view prefix) {
if (!StartsWith(*s, prefix)) return false;
s->remove_prefix(prefix.size());
return true;
}
// Removes `suffix` from the end of the given string and returns true (if
// it was present), false otherwise.
inline bool ConsumeSuffix(std::string_view* s, std::string_view suffix) {
if (!EndsWith(*s, suffix)) return false;
s->remove_suffix(suffix.size());
return true;
}
// Replaces `from` with `to` in `s`, once if `all == false`, or as many times as
// there are matches if `all == true`.
[[nodiscard]] std::string StringReplace(std::string_view s, std::string_view from,
std::string_view to, bool all);
// Converts an errno number to its error message string.
std::string ErrnoNumberAsString(int errnum);
} // namespace base
} // namespace android
|