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