1 /*
2 *
3 * Copyright 2015 gRPC authors.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 */
18
19 #include <grpc/support/port_platform.h>
20
21 #include "src/core/lib/gpr/string.h"
22
23 #include <ctype.h>
24 #include <limits.h>
25 #include <stddef.h>
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <time.h>
30
31 #include "absl/strings/str_cat.h"
32
33 #include <grpc/support/alloc.h>
34 #include <grpc/support/log.h>
35 #include <grpc/support/string_util.h>
36
37 #include "src/core/lib/gpr/useful.h"
38
gpr_strdup(const char * src)39 char* gpr_strdup(const char* src) {
40 char* dst;
41 size_t len;
42
43 if (!src) {
44 return nullptr;
45 }
46
47 len = strlen(src) + 1;
48 dst = static_cast<char*>(gpr_malloc(len));
49
50 memcpy(dst, src, len);
51
52 return dst;
53 }
54
gpr_format_timespec(gpr_timespec tm)55 std::string gpr_format_timespec(gpr_timespec tm) {
56 char time_buffer[35];
57 char ns_buffer[11]; // '.' + 9 digits of precision
58 struct tm* tm_info = localtime(reinterpret_cast<time_t*>(&tm.tv_sec));
59 strftime(time_buffer, sizeof(time_buffer), "%Y-%m-%dT%H:%M:%S", tm_info);
60 snprintf(ns_buffer, 11, ".%09d", tm.tv_nsec);
61 // This loop trims off trailing zeros by inserting a null character that the
62 // right point. We iterate in chunks of three because we want 0, 3, 6, or 9
63 // fractional digits.
64 for (int i = 7; i >= 1; i -= 3) {
65 if (ns_buffer[i] == '0' && ns_buffer[i + 1] == '0' &&
66 ns_buffer[i + 2] == '0') {
67 ns_buffer[i] = '\0';
68 // Edge case in which all fractional digits were 0.
69 if (i == 1) {
70 ns_buffer[0] = '\0';
71 }
72 } else {
73 break;
74 }
75 }
76 return absl::StrCat(time_buffer, ns_buffer, "Z");
77 }
78
79 struct dump_out {
80 size_t capacity;
81 size_t length;
82 char* data;
83 };
84
dump_out_create(void)85 static dump_out dump_out_create(void) {
86 dump_out r = {0, 0, nullptr};
87 return r;
88 }
89
dump_out_append(dump_out * out,char c)90 static void dump_out_append(dump_out* out, char c) {
91 if (out->length == out->capacity) {
92 out->capacity = GPR_MAX(8, 2 * out->capacity);
93 out->data = static_cast<char*>(gpr_realloc(out->data, out->capacity));
94 }
95 out->data[out->length++] = c;
96 }
97
hexdump(dump_out * out,const char * buf,size_t len)98 static void hexdump(dump_out* out, const char* buf, size_t len) {
99 static const char* hex = "0123456789abcdef";
100
101 const uint8_t* const beg = reinterpret_cast<const uint8_t*>(buf);
102 const uint8_t* const end = beg + len;
103 const uint8_t* cur;
104
105 for (cur = beg; cur != end; ++cur) {
106 if (cur != beg) dump_out_append(out, ' ');
107 dump_out_append(out, hex[*cur >> 4]);
108 dump_out_append(out, hex[*cur & 0xf]);
109 }
110 }
111
asciidump(dump_out * out,const char * buf,size_t len)112 static void asciidump(dump_out* out, const char* buf, size_t len) {
113 const uint8_t* const beg = reinterpret_cast<const uint8_t*>(buf);
114 const uint8_t* const end = beg + len;
115 const uint8_t* cur;
116 int out_was_empty = (out->length == 0);
117 if (!out_was_empty) {
118 dump_out_append(out, ' ');
119 dump_out_append(out, '\'');
120 }
121 for (cur = beg; cur != end; ++cur) {
122 dump_out_append(
123 out, (isprint(*cur) ? *reinterpret_cast<const char*>(cur) : '.'));
124 }
125 if (!out_was_empty) {
126 dump_out_append(out, '\'');
127 }
128 }
129
gpr_dump_return_len(const char * buf,size_t len,uint32_t flags,size_t * out_len)130 char* gpr_dump_return_len(const char* buf, size_t len, uint32_t flags,
131 size_t* out_len) {
132 dump_out out = dump_out_create();
133 if (flags & GPR_DUMP_HEX) {
134 hexdump(&out, buf, len);
135 }
136 if (flags & GPR_DUMP_ASCII) {
137 asciidump(&out, buf, len);
138 }
139 dump_out_append(&out, 0);
140 *out_len = out.length;
141 return out.data;
142 }
143
gpr_dump(const char * buf,size_t len,uint32_t flags)144 char* gpr_dump(const char* buf, size_t len, uint32_t flags) {
145 size_t unused;
146 return gpr_dump_return_len(buf, len, flags, &unused);
147 }
148
gpr_parse_bytes_to_uint32(const char * buf,size_t len,uint32_t * result)149 int gpr_parse_bytes_to_uint32(const char* buf, size_t len, uint32_t* result) {
150 uint32_t out = 0;
151 uint32_t new_val;
152 size_t i;
153
154 if (len == 0) return 0; /* must have some bytes */
155
156 for (i = 0; i < len; i++) {
157 if (buf[i] < '0' || buf[i] > '9') return 0; /* bad char */
158 new_val = 10 * out + static_cast<uint32_t>(buf[i] - '0');
159 if (new_val < out) return 0; /* overflow */
160 out = new_val;
161 }
162
163 *result = out;
164 return 1;
165 }
166
gpr_reverse_bytes(char * str,int len)167 void gpr_reverse_bytes(char* str, int len) {
168 char *p1, *p2;
169 for (p1 = str, p2 = str + len - 1; p2 > p1; ++p1, --p2) {
170 char temp = *p1;
171 *p1 = *p2;
172 *p2 = temp;
173 }
174 }
175
gpr_ltoa(long value,char * output)176 int gpr_ltoa(long value, char* output) {
177 long sign;
178 int i = 0;
179
180 if (value == 0) {
181 output[0] = '0';
182 output[1] = 0;
183 return 1;
184 }
185
186 sign = value < 0 ? -1 : 1;
187 while (value) {
188 output[i++] = static_cast<char>('0' + sign * (value % 10));
189 value /= 10;
190 }
191 if (sign < 0) output[i++] = '-';
192 gpr_reverse_bytes(output, i);
193 output[i] = 0;
194 return i;
195 }
196
int64_ttoa(int64_t value,char * output)197 int int64_ttoa(int64_t value, char* output) {
198 int64_t sign;
199 int i = 0;
200
201 if (value == 0) {
202 output[0] = '0';
203 output[1] = 0;
204 return 1;
205 }
206
207 sign = value < 0 ? -1 : 1;
208 while (value) {
209 output[i++] = static_cast<char>('0' + sign * (value % 10));
210 value /= 10;
211 }
212 if (sign < 0) output[i++] = '-';
213 gpr_reverse_bytes(output, i);
214 output[i] = 0;
215 return i;
216 }
217
gpr_parse_nonnegative_int(const char * value)218 int gpr_parse_nonnegative_int(const char* value) {
219 char* end;
220 long result = strtol(value, &end, 10);
221 if (*end != '\0' || result < 0 || result > INT_MAX) return -1;
222 return static_cast<int>(result);
223 }
224
gpr_leftpad(const char * str,char flag,size_t length)225 char* gpr_leftpad(const char* str, char flag, size_t length) {
226 const size_t str_length = strlen(str);
227 const size_t out_length = str_length > length ? str_length : length;
228 char* out = static_cast<char*>(gpr_malloc(out_length + 1));
229 memset(out, flag, out_length - str_length);
230 memcpy(out + out_length - str_length, str, str_length);
231 out[out_length] = 0;
232 return out;
233 }
234
gpr_strjoin(const char ** strs,size_t nstrs,size_t * final_length)235 char* gpr_strjoin(const char** strs, size_t nstrs, size_t* final_length) {
236 return gpr_strjoin_sep(strs, nstrs, "", final_length);
237 }
238
gpr_strjoin_sep(const char ** strs,size_t nstrs,const char * sep,size_t * final_length)239 char* gpr_strjoin_sep(const char** strs, size_t nstrs, const char* sep,
240 size_t* final_length) {
241 const size_t sep_len = strlen(sep);
242 size_t out_length = 0;
243 size_t i;
244 char* out;
245 for (i = 0; i < nstrs; i++) {
246 out_length += strlen(strs[i]);
247 }
248 out_length += 1; /* null terminator */
249 if (nstrs > 0) {
250 out_length += sep_len * (nstrs - 1); /* separators */
251 }
252 out = static_cast<char*>(gpr_malloc(out_length));
253 out_length = 0;
254 for (i = 0; i < nstrs; i++) {
255 const size_t slen = strlen(strs[i]);
256 if (i != 0) {
257 memcpy(out + out_length, sep, sep_len);
258 out_length += sep_len;
259 }
260 memcpy(out + out_length, strs[i], slen);
261 out_length += slen;
262 }
263 out[out_length] = 0;
264 if (final_length != nullptr) {
265 *final_length = out_length;
266 }
267 return out;
268 }
269
gpr_strincmp(const char * a,const char * b,size_t n)270 int gpr_strincmp(const char* a, const char* b, size_t n) {
271 int ca, cb;
272 do {
273 ca = tolower(*a);
274 cb = tolower(*b);
275 ++a;
276 ++b;
277 --n;
278 } while (ca == cb && ca != 0 && cb != 0 && n != 0);
279 return ca - cb;
280 }
281
gpr_stricmp(const char * a,const char * b)282 int gpr_stricmp(const char* a, const char* b) {
283 return gpr_strincmp(a, b, SIZE_MAX);
284 }
285
add_string_to_split(const char * beg,const char * end,char *** strs,size_t * nstrs,size_t * capstrs)286 static void add_string_to_split(const char* beg, const char* end, char*** strs,
287 size_t* nstrs, size_t* capstrs) {
288 char* out =
289 static_cast<char*>(gpr_malloc(static_cast<size_t>(end - beg) + 1));
290 memcpy(out, beg, static_cast<size_t>(end - beg));
291 out[end - beg] = 0;
292 if (*nstrs == *capstrs) {
293 *capstrs = GPR_MAX(8, 2 * *capstrs);
294 *strs = static_cast<char**>(gpr_realloc(*strs, sizeof(*strs) * *capstrs));
295 }
296 (*strs)[*nstrs] = out;
297 ++*nstrs;
298 }
299
gpr_string_split(const char * input,const char * sep,char *** strs,size_t * nstrs)300 void gpr_string_split(const char* input, const char* sep, char*** strs,
301 size_t* nstrs) {
302 const char* next;
303 *strs = nullptr;
304 *nstrs = 0;
305 size_t capstrs = 0;
306 while ((next = strstr(input, sep))) {
307 add_string_to_split(input, next, strs, nstrs, &capstrs);
308 input = next + strlen(sep);
309 }
310 add_string_to_split(input, input + strlen(input), strs, nstrs, &capstrs);
311 }
312
gpr_memrchr(const void * s,int c,size_t n)313 void* gpr_memrchr(const void* s, int c, size_t n) {
314 if (s == nullptr) return nullptr;
315 char* b = const_cast<char*>(reinterpret_cast<const char*>(s));
316 size_t i;
317 for (i = 0; i < n; i++) {
318 if (b[n - i - 1] == c) {
319 return &b[n - i - 1];
320 }
321 }
322 return nullptr;
323 }
324
gpr_parse_bool_value(const char * value,bool * dst)325 bool gpr_parse_bool_value(const char* value, bool* dst) {
326 const char* kTrue[] = {"1", "t", "true", "y", "yes"};
327 const char* kFalse[] = {"0", "f", "false", "n", "no"};
328 static_assert(sizeof(kTrue) == sizeof(kFalse), "true_false_equal");
329
330 if (value == nullptr) {
331 return false;
332 }
333 for (size_t i = 0; i < GPR_ARRAY_SIZE(kTrue); ++i) {
334 if (gpr_stricmp(value, kTrue[i]) == 0) {
335 *dst = true;
336 return true;
337 } else if (gpr_stricmp(value, kFalse[i]) == 0) {
338 *dst = false;
339 return true;
340 }
341 }
342 return false; // didn't match a legal input
343 }
344