1 /*
2 * Copyright (C) 2018 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
17 #ifndef INCLUDE_PERFETTO_EXT_BASE_STRING_UTILS_H_
18 #define INCLUDE_PERFETTO_EXT_BASE_STRING_UTILS_H_
19
20 #include <stdarg.h>
21 #include <stdlib.h>
22 #include <string.h>
23
24 #include <cinttypes>
25 #include <optional>
26 #include <string>
27 #include <vector>
28
29 #include "perfetto/ext/base/string_view.h"
30
31 namespace perfetto {
32 namespace base {
33
Lowercase(char c)34 inline char Lowercase(char c) {
35 return ('A' <= c && c <= 'Z') ? static_cast<char>(c - ('A' - 'a')) : c;
36 }
37
Uppercase(char c)38 inline char Uppercase(char c) {
39 return ('a' <= c && c <= 'z') ? static_cast<char>(c + ('A' - 'a')) : c;
40 }
41
42 inline std::optional<uint32_t> CStringToUInt32(const char* s, int base = 10) {
43 char* endptr = nullptr;
44 auto value = static_cast<uint32_t>(strtoul(s, &endptr, base));
45 return (*s && !*endptr) ? std::make_optional(value) : std::nullopt;
46 }
47
48 inline std::optional<int32_t> CStringToInt32(const char* s, int base = 10) {
49 char* endptr = nullptr;
50 auto value = static_cast<int32_t>(strtol(s, &endptr, base));
51 return (*s && !*endptr) ? std::make_optional(value) : std::nullopt;
52 }
53
54 // Note: it saturates to 7fffffffffffffff if parsing a hex number >= 0x8000...
55 inline std::optional<int64_t> CStringToInt64(const char* s, int base = 10) {
56 char* endptr = nullptr;
57 auto value = static_cast<int64_t>(strtoll(s, &endptr, base));
58 return (*s && !*endptr) ? std::make_optional(value) : std::nullopt;
59 }
60
61 inline std::optional<uint64_t> CStringToUInt64(const char* s, int base = 10) {
62 char* endptr = nullptr;
63 auto value = static_cast<uint64_t>(strtoull(s, &endptr, base));
64 return (*s && !*endptr) ? std::make_optional(value) : std::nullopt;
65 }
66
67 double StrToD(const char* nptr, char** endptr);
68
CStringToDouble(const char * s)69 inline std::optional<double> CStringToDouble(const char* s) {
70 char* endptr = nullptr;
71 double value = StrToD(s, &endptr);
72 std::optional<double> result(std::nullopt);
73 if (*s != '\0' && *endptr == '\0')
74 result = value;
75 return result;
76 }
77
78 inline std::optional<uint32_t> StringToUInt32(const std::string& s,
79 int base = 10) {
80 return CStringToUInt32(s.c_str(), base);
81 }
82
83 inline std::optional<int32_t> StringToInt32(const std::string& s,
84 int base = 10) {
85 return CStringToInt32(s.c_str(), base);
86 }
87
88 inline std::optional<uint64_t> StringToUInt64(const std::string& s,
89 int base = 10) {
90 return CStringToUInt64(s.c_str(), base);
91 }
92
93 inline std::optional<int64_t> StringToInt64(const std::string& s,
94 int base = 10) {
95 return CStringToInt64(s.c_str(), base);
96 }
97
StringToDouble(const std::string & s)98 inline std::optional<double> StringToDouble(const std::string& s) {
99 return CStringToDouble(s.c_str());
100 }
101
102 bool StartsWith(const std::string& str, const std::string& prefix);
103 bool EndsWith(const std::string& str, const std::string& suffix);
104 bool StartsWithAny(const std::string& str,
105 const std::vector<std::string>& prefixes);
106 bool Contains(const std::string& haystack, const std::string& needle);
107 bool Contains(const std::string& haystack, char needle);
108 size_t Find(const StringView& needle, const StringView& haystack);
109 bool CaseInsensitiveEqual(const std::string& first, const std::string& second);
110 std::string Join(const std::vector<std::string>& parts,
111 const std::string& delim);
112 std::vector<std::string> SplitString(const std::string& text,
113 const std::string& delimiter);
114 std::string StripPrefix(const std::string& str, const std::string& prefix);
115 std::string StripSuffix(const std::string& str, const std::string& suffix);
116 std::string TrimWhitespace(const std::string& str);
117 std::string ToLower(const std::string& str);
118 std::string ToUpper(const std::string& str);
119 std::string StripChars(const std::string& str,
120 const std::string& chars,
121 char replacement);
122 std::string ToHex(const char* data, size_t size);
ToHex(const std::string & s)123 inline std::string ToHex(const std::string& s) {
124 return ToHex(s.c_str(), s.size());
125 }
126 std::string IntToHexString(uint32_t number);
127 std::string Uint64ToHexString(uint64_t number);
128 std::string Uint64ToHexStringNoPrefix(uint64_t number);
129 std::string ReplaceAll(std::string str,
130 const std::string& to_replace,
131 const std::string& replacement);
132
133 #if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
134 bool WideToUTF8(const std::wstring& source, std::string& output);
135 bool UTF8ToWide(const std::string& source, std::wstring& output);
136 #endif // PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
137
138 // A BSD-style strlcpy without the return value.
139 // Copies at most |dst_size|-1 characters. Unlike strncpy, it always \0
140 // terminates |dst|, as long as |dst_size| is not 0.
141 // Unlike strncpy and like strlcpy it does not zero-pad the rest of |dst|.
142 // Returns nothing. The BSD strlcpy returns the size of |src|, which might
143 // be > |dst_size|. Anecdotal experience suggests people assume the return value
144 // is the number of bytes written in |dst|. That assumption can lead to
145 // dangerous bugs.
146 // In order to avoid being subtly uncompliant with strlcpy AND avoid misuse,
147 // the choice here is to return nothing.
StringCopy(char * dst,const char * src,size_t dst_size)148 inline void StringCopy(char* dst, const char* src, size_t dst_size) {
149 for (size_t i = 0; i < dst_size; ++i) {
150 if ((dst[i] = src[i]) == '\0') {
151 return; // We hit and copied the null terminator.
152 }
153 }
154
155 // We were left off at dst_size. We over copied 1 byte. Null terminate.
156 if (PERFETTO_LIKELY(dst_size > 0))
157 dst[dst_size - 1] = 0;
158 }
159
160 // Like snprintf() but returns the number of chars *actually* written (without
161 // counting the null terminator) NOT "the number of chars which would have been
162 // written to the final string if enough space had been available".
163 // This should be used in almost all cases when the caller uses the return value
164 // of snprintf(). If the return value is not used, there is no benefit in using
165 // this wrapper, as this just calls snprintf() and mangles the return value.
166 // It always null-terminates |dst| (even in case of errors), unless
167 // |dst_size| == 0.
168 // Examples:
169 // SprintfTrunc(x, 4, "123whatever"): returns 3 and writes "123\0".
170 // SprintfTrunc(x, 4, "123"): returns 3 and writes "123\0".
171 // SprintfTrunc(x, 3, "123"): returns 2 and writes "12\0".
172 // SprintfTrunc(x, 2, "123"): returns 1 and writes "1\0".
173 // SprintfTrunc(x, 1, "123"): returns 0 and writes "\0".
174 // SprintfTrunc(x, 0, "123"): returns 0 and writes nothing.
175 // NOTE: This means that the caller has no way to tell when truncation happens
176 // vs the edge case of *just* fitting in the buffer.
177 size_t SprintfTrunc(char* dst, size_t dst_size, const char* fmt, ...)
178 PERFETTO_PRINTF_FORMAT(3, 4);
179
180 // Line number starts from 1
181 struct LineWithOffset {
182 base::StringView line;
183 uint32_t line_offset;
184 uint32_t line_num;
185 };
186
187 // For given string and offset Pfinds a line with character for
188 // which offset points, what number is this line (starts from 1), and the offset
189 // inside this line. returns std::nullopt if the offset points to
190 // line break character or exceeds string length.
191 std::optional<LineWithOffset> FindLineWithOffset(base::StringView str,
192 uint32_t offset);
193
194 // A helper class to facilitate construction and usage of write-once stack
195 // strings.
196 // Example usage:
197 // StackString<32> x("format %d %s", 42, string_arg);
198 // TakeString(x.c_str() | x.string_view() | x.ToStdString());
199 // Rather than char x[32] + sprintf.
200 // Advantages:
201 // - Avoids useless zero-fills caused by people doing `char buf[32] {}` (mainly
202 // by fearing unknown snprintf failure modes).
203 // - Makes the code more robust in case of snprintf truncations (len() and
204 // string_view() will return the truncated length, unlike snprintf).
205 template <size_t N>
206 class StackString {
207 public:
208 explicit PERFETTO_PRINTF_FORMAT(/* 1=this */ 2, 3)
StackString(const char * fmt,...)209 StackString(const char* fmt, ...) {
210 buf_[0] = '\0';
211 va_list args;
212 va_start(args, fmt);
213 int res = vsnprintf(buf_, sizeof(buf_), fmt, args);
214 va_end(args);
215 buf_[sizeof(buf_) - 1] = '\0';
216 len_ = res < 0 ? 0 : std::min(static_cast<size_t>(res), sizeof(buf_) - 1);
217 }
218
string_view()219 StringView string_view() const { return StringView(buf_, len_); }
ToStdString()220 std::string ToStdString() const { return std::string(buf_, len_); }
c_str()221 const char* c_str() const { return buf_; }
len()222 size_t len() const { return len_; }
mutable_data()223 char* mutable_data() { return buf_; }
224
225 private:
226 char buf_[N];
227 size_t len_ = 0; // Does not include the \0.
228 };
229
230 } // namespace base
231 } // namespace perfetto
232
233 #endif // INCLUDE_PERFETTO_EXT_BASE_STRING_UTILS_H_
234