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