1 : #include "fmacros.h"
2 : #include <stdlib.h>
3 : #include <stdio.h>
4 : #include <string.h>
5 : #include <ctype.h>
6 : #include <limits.h>
7 : #include <math.h>
8 : #include <unistd.h>
9 : #include <sys/time.h>
10 :
11 : #include "util.h"
12 :
13 : /* Glob-style pattern matching. */
14 21 : int stringmatchlen(const char *pattern, int patternLen,
15 : const char *string, int stringLen, int nocase)
16 : {
17 83 : while(patternLen) {
18 62 : switch(pattern[0]) {
19 : case '*':
20 9 : while (pattern[1] == '*') {
21 0 : pattern++;
22 0 : patternLen--;
23 : }
24 9 : if (patternLen == 1)
25 9 : return 1; /* match */
26 0 : while(stringLen) {
27 0 : if (stringmatchlen(pattern+1, patternLen-1,
28 : string, stringLen, nocase))
29 0 : return 1; /* match */
30 0 : string++;
31 0 : stringLen--;
32 : }
33 0 : return 0; /* no match */
34 : break;
35 : case '?':
36 0 : if (stringLen == 0)
37 0 : return 0; /* no match */
38 0 : string++;
39 0 : stringLen--;
40 0 : break;
41 : case '[':
42 : {
43 : int not, match;
44 :
45 0 : pattern++;
46 0 : patternLen--;
47 0 : not = pattern[0] == '^';
48 0 : if (not) {
49 0 : pattern++;
50 0 : patternLen--;
51 : }
52 0 : match = 0;
53 : while(1) {
54 0 : if (pattern[0] == '\\') {
55 0 : pattern++;
56 0 : patternLen--;
57 0 : if (pattern[0] == string[0])
58 0 : match = 1;
59 0 : } else if (pattern[0] == ']') {
60 : break;
61 0 : } else if (patternLen == 0) {
62 0 : pattern--;
63 0 : patternLen++;
64 0 : break;
65 0 : } else if (pattern[1] == '-' && patternLen >= 3) {
66 0 : int start = pattern[0];
67 0 : int end = pattern[2];
68 0 : int c = string[0];
69 0 : if (start > end) {
70 0 : int t = start;
71 0 : start = end;
72 0 : end = t;
73 : }
74 0 : if (nocase) {
75 0 : start = tolower(start);
76 0 : end = tolower(end);
77 0 : c = tolower(c);
78 : }
79 0 : pattern += 2;
80 0 : patternLen -= 2;
81 0 : if (c >= start && c <= end)
82 0 : match = 1;
83 : } else {
84 0 : if (!nocase) {
85 0 : if (pattern[0] == string[0])
86 0 : match = 1;
87 : } else {
88 0 : if (tolower((int)pattern[0]) == tolower((int)string[0]))
89 0 : match = 1;
90 : }
91 : }
92 0 : pattern++;
93 0 : patternLen--;
94 0 : }
95 0 : if (not)
96 0 : match = !match;
97 0 : if (!match)
98 0 : return 0; /* no match */
99 0 : string++;
100 0 : stringLen--;
101 0 : break;
102 : }
103 : case '\\':
104 0 : if (patternLen >= 2) {
105 0 : pattern++;
106 0 : patternLen--;
107 : }
108 : /* fall through */
109 : default:
110 53 : if (!nocase) {
111 53 : if (pattern[0] != string[0])
112 12 : return 0; /* no match */
113 : } else {
114 0 : if (tolower((int)pattern[0]) != tolower((int)string[0]))
115 0 : return 0; /* no match */
116 : }
117 41 : string++;
118 41 : stringLen--;
119 : break;
120 : }
121 41 : pattern++;
122 41 : patternLen--;
123 41 : if (stringLen == 0) {
124 0 : while(*pattern == '*') {
125 0 : pattern++;
126 0 : patternLen--;
127 : }
128 : break;
129 : }
130 : }
131 0 : if (patternLen == 0 && stringLen == 0)
132 0 : return 1;
133 0 : return 0;
134 : }
135 :
136 0 : int stringmatch(const char *pattern, const char *string, int nocase) {
137 0 : return stringmatchlen(pattern,strlen(pattern),string,strlen(string),nocase);
138 : }
139 :
140 : /* Convert a string representing an amount of memory into the number of
141 : * bytes, so for instance memtoll("1Gi") will return 1073741824 that is
142 : * (1024*1024*1024).
143 : *
144 : * On parsing error, if *err is not NULL, it's set to 1, otherwise it's
145 : * set to 0 */
146 265 : long long memtoll(const char *p, int *err) {
147 : const char *u;
148 : char buf[128];
149 : long mul; /* unit multiplier */
150 : long long val;
151 : unsigned int digits;
152 :
153 265 : if (err) *err = 0;
154 : /* Search the first non digit character. */
155 265 : u = p;
156 265 : if (*u == '-') u++;
157 688 : while(*u && isdigit(*u)) u++;
158 530 : if (*u == '\0' || !strcasecmp(u,"b")) {
159 265 : mul = 1;
160 0 : } else if (!strcasecmp(u,"k")) {
161 0 : mul = 1000;
162 0 : } else if (!strcasecmp(u,"kb")) {
163 0 : mul = 1024;
164 0 : } else if (!strcasecmp(u,"m")) {
165 0 : mul = 1000*1000;
166 0 : } else if (!strcasecmp(u,"mb")) {
167 0 : mul = 1024*1024;
168 0 : } else if (!strcasecmp(u,"g")) {
169 0 : mul = 1000L*1000*1000;
170 0 : } else if (!strcasecmp(u,"gb")) {
171 0 : mul = 1024L*1024*1024;
172 : } else {
173 0 : if (err) *err = 1;
174 0 : mul = 1;
175 : }
176 265 : digits = u-p;
177 265 : if (digits >= sizeof(buf)) {
178 0 : if (err) *err = 1;
179 0 : return LLONG_MAX;
180 : }
181 265 : memcpy(buf,p,digits);
182 265 : buf[digits] = '\0';
183 265 : val = strtoll(buf,NULL,10);
184 265 : return val*mul;
185 : }
186 :
187 : /* Convert a long long into a string. Returns the number of
188 : * characters needed to represent the number, that can be shorter if passed
189 : * buffer length is not enough to store the whole number. */
190 956054 : int ll2string(char *s, size_t len, long long value) {
191 : char buf[32], *p;
192 : unsigned long long v;
193 : size_t l;
194 :
195 956054 : if (len == 0) return 0;
196 956054 : v = (value < 0) ? -value : value;
197 956054 : p = buf+31; /* point to the last character */
198 : do {
199 5566455 : *p-- = '0'+(v%10);
200 5566455 : v /= 10;
201 5566455 : } while(v);
202 956054 : if (value < 0) *p-- = '-';
203 956054 : p++;
204 956054 : l = 32-(p-buf);
205 956054 : if (l+1 > len) l = len-1; /* Make sure it fits, including the nul term */
206 : memcpy(s,p,l);
207 956054 : s[l] = '\0';
208 956054 : return l;
209 : }
210 :
211 : /* Convert a string into a long long. Returns 1 if the string could be parsed
212 : * into a (non-overflowing) long long, 0 otherwise. The value will be set to
213 : * the parsed value when appropriate. */
214 10149190 : int string2ll(const char *s, size_t slen, long long *value) {
215 10149190 : const char *p = s;
216 10149190 : size_t plen = 0;
217 10149190 : int negative = 0;
218 : unsigned long long v;
219 :
220 10149190 : if (plen == slen)
221 699 : return 0;
222 :
223 : /* Special case: first and only digit is 0. */
224 10148491 : if (slen == 1 && p[0] == '0') {
225 3781 : if (value != NULL) *value = 0;
226 3781 : return 1;
227 : }
228 :
229 10144710 : if (p[0] == '-') {
230 3594 : negative = 1;
231 3594 : p++; plen++;
232 :
233 : /* Abort on only a negative sign. */
234 3594 : if (plen == slen)
235 2 : return 0;
236 : }
237 :
238 : /* First digit should be 1-9, otherwise the string should just be 0. */
239 10144708 : if (p[0] >= '1' && p[0] <= '9') {
240 8215826 : v = p[0]-'0';
241 8215826 : p++; plen++;
242 1928882 : } else if (p[0] == '0' && slen == 1) {
243 0 : *value = 0;
244 0 : return 1;
245 : } else {
246 1928882 : return 0;
247 : }
248 :
249 23824252 : while (plen < slen && p[0] >= '0' && p[0] <= '9') {
250 7402618 : if (v > (ULLONG_MAX / 10)) /* Overflow. */
251 10018 : return 0;
252 7392600 : v *= 10;
253 :
254 7392600 : if (v > (ULLONG_MAX - (p[0]-'0'))) /* Overflow. */
255 0 : return 0;
256 7392600 : v += p[0]-'0';
257 :
258 7392600 : p++; plen++;
259 : }
260 :
261 : /* Return if not all bytes were used. */
262 8205808 : if (plen < slen)
263 4156 : return 0;
264 :
265 8201652 : if (negative) {
266 2169 : if (v > ((unsigned long long)(-(LLONG_MIN+1))+1)) /* Overflow. */
267 0 : return 0;
268 2169 : if (value != NULL) *value = -v;
269 : } else {
270 8199483 : if (v > LLONG_MAX) /* Overflow. */
271 27 : return 0;
272 8199456 : if (value != NULL) *value = v;
273 : }
274 8201625 : return 1;
275 : }
276 :
277 : /* Convert a string into a long. Returns 1 if the string could be parsed into a
278 : * (non-overflowing) long, 0 otherwise. The value will be set to the parsed
279 : * value when appropriate. */
280 2067775 : int string2l(const char *s, size_t slen, long *lval) {
281 : long long llval;
282 :
283 2067775 : if (!string2ll(s,slen,&llval))
284 1857780 : return 0;
285 :
286 : if (llval < LONG_MIN || llval > LONG_MAX)
287 : return 0;
288 :
289 209995 : *lval = (long)llval;
290 209995 : return 1;
291 : }
292 :
293 : /* Convert a double to a string representation. Returns the number of bytes
294 : * required. The representation should always be parsable by stdtod(3). */
295 20169 : int d2string(char *buf, size_t len, double value) {
296 20169 : if (isnan(value)) {
297 0 : len = snprintf(buf,len,"nan");
298 20169 : } else if (isinf(value)) {
299 2863 : if (value < 0)
300 2716 : len = snprintf(buf,len,"-inf");
301 : else
302 3010 : len = snprintf(buf,len,"inf");
303 17306 : } else if (value == 0) {
304 : /* See: http://en.wikipedia.org/wiki/Signed_zero, "Comparisons". */
305 15 : if (1.0/value < 0)
306 0 : len = snprintf(buf,len,"-0");
307 : else
308 30 : len = snprintf(buf,len,"0");
309 : } else {
310 : #if (DBL_MANT_DIG >= 52) && (LLONG_MAX == 0x7fffffffffffffffLL)
311 : /* Check if the float is in a safe range to be casted into a
312 : * long long. We are assuming that long long is 64 bit here.
313 : * Also we are assuming that there are no implementations around where
314 : * double has precision < 52 bit.
315 : *
316 : * Under this assumptions we test if a double is inside an interval
317 : * where casting to long long is safe. Then using two castings we
318 : * make sure the decimal part is zero. If all this is true we use
319 : * integer printing function that is much faster. */
320 : double min = -4503599627370495; /* (2^52)-1 */
321 : double max = 4503599627370496; /* -(2^52) */
322 : if (val > min && val < max && value == ((double)((long long)value)))
323 : len = ll2string(buf,len,(long long)value);
324 : else
325 : #endif
326 34582 : len = snprintf(buf,len,"%.17g",value);
327 : }
328 :
329 20169 : return len;
330 : }
331 :
332 : /* Generate the Redis "Run ID", a SHA1-sized random number that identifies a
333 : * given execution of Redis, so that if you are talking with an instance
334 : * having run_id == A, and you reconnect and it has run_id == B, you can be
335 : * sure that it is either a different instance or it was restarted. */
336 53 : void getRandomHexChars(char *p, unsigned int len) {
337 53 : FILE *fp = fopen("/dev/urandom","r");
338 53 : char *charset = "0123456789abcdef";
339 : unsigned int j;
340 :
341 106 : if (fp == NULL || fread(p,len,1,fp) == 0) {
342 : /* If we can't read from /dev/urandom, do some reasonable effort
343 : * in order to create some entropy, since this function is used to
344 : * generate run_id and cluster instance IDs */
345 0 : char *x = p;
346 0 : unsigned int l = len;
347 : struct timeval tv;
348 0 : pid_t pid = getpid();
349 :
350 : /* Use time and PID to fill the initial array. */
351 0 : gettimeofday(&tv,NULL);
352 0 : if (l >= sizeof(tv.tv_usec)) {
353 : memcpy(x,&tv.tv_usec,sizeof(tv.tv_usec));
354 0 : l -= sizeof(tv.tv_usec);
355 0 : x += sizeof(tv.tv_usec);
356 : }
357 0 : if (l >= sizeof(tv.tv_sec)) {
358 : memcpy(x,&tv.tv_sec,sizeof(tv.tv_sec));
359 0 : l -= sizeof(tv.tv_sec);
360 0 : x += sizeof(tv.tv_sec);
361 : }
362 0 : if (l >= sizeof(pid)) {
363 : memcpy(x,&pid,sizeof(pid));
364 0 : l -= sizeof(pid);
365 0 : x += sizeof(pid);
366 : }
367 : /* Finally xor it with rand() output, that was already seeded with
368 : * time() at startup. */
369 0 : for (j = 0; j < len; j++)
370 0 : p[j] ^= rand();
371 : }
372 : /* Turn it into hex digits taking just 4 bits out of 8 for every byte. */
373 2173 : for (j = 0; j < len; j++)
374 2120 : p[j] = charset[p[j] & 0x0F];
375 53 : fclose(fp);
376 53 : }
377 :
378 : #ifdef UTIL_TEST_MAIN
379 : #include <assert.h>
380 :
381 : void test_string2ll(void) {
382 : char buf[32];
383 : long long v;
384 :
385 : /* May not start with +. */
386 : strcpy(buf,"+1");
387 : assert(string2ll(buf,strlen(buf),&v) == 0);
388 :
389 : /* Leading space. */
390 : strcpy(buf," 1");
391 : assert(string2ll(buf,strlen(buf),&v) == 0);
392 :
393 : /* Trailing space. */
394 : strcpy(buf,"1 ");
395 : assert(string2ll(buf,strlen(buf),&v) == 0);
396 :
397 : /* May not start with 0. */
398 : strcpy(buf,"01");
399 : assert(string2ll(buf,strlen(buf),&v) == 0);
400 :
401 : strcpy(buf,"-1");
402 : assert(string2ll(buf,strlen(buf),&v) == 1);
403 : assert(v == -1);
404 :
405 : strcpy(buf,"0");
406 : assert(string2ll(buf,strlen(buf),&v) == 1);
407 : assert(v == 0);
408 :
409 : strcpy(buf,"1");
410 : assert(string2ll(buf,strlen(buf),&v) == 1);
411 : assert(v == 1);
412 :
413 : strcpy(buf,"99");
414 : assert(string2ll(buf,strlen(buf),&v) == 1);
415 : assert(v == 99);
416 :
417 : strcpy(buf,"-99");
418 : assert(string2ll(buf,strlen(buf),&v) == 1);
419 : assert(v == -99);
420 :
421 : strcpy(buf,"-9223372036854775808");
422 : assert(string2ll(buf,strlen(buf),&v) == 1);
423 : assert(v == LLONG_MIN);
424 :
425 : strcpy(buf,"-9223372036854775809"); /* overflow */
426 : assert(string2ll(buf,strlen(buf),&v) == 0);
427 :
428 : strcpy(buf,"9223372036854775807");
429 : assert(string2ll(buf,strlen(buf),&v) == 1);
430 : assert(v == LLONG_MAX);
431 :
432 : strcpy(buf,"9223372036854775808"); /* overflow */
433 : assert(string2ll(buf,strlen(buf),&v) == 0);
434 : }
435 :
436 : void test_string2l(void) {
437 : char buf[32];
438 : long v;
439 :
440 : /* May not start with +. */
441 : strcpy(buf,"+1");
442 : assert(string2l(buf,strlen(buf),&v) == 0);
443 :
444 : /* May not start with 0. */
445 : strcpy(buf,"01");
446 : assert(string2l(buf,strlen(buf),&v) == 0);
447 :
448 : strcpy(buf,"-1");
449 : assert(string2l(buf,strlen(buf),&v) == 1);
450 : assert(v == -1);
451 :
452 : strcpy(buf,"0");
453 : assert(string2l(buf,strlen(buf),&v) == 1);
454 : assert(v == 0);
455 :
456 : strcpy(buf,"1");
457 : assert(string2l(buf,strlen(buf),&v) == 1);
458 : assert(v == 1);
459 :
460 : strcpy(buf,"99");
461 : assert(string2l(buf,strlen(buf),&v) == 1);
462 : assert(v == 99);
463 :
464 : strcpy(buf,"-99");
465 : assert(string2l(buf,strlen(buf),&v) == 1);
466 : assert(v == -99);
467 :
468 : #if LONG_MAX != LLONG_MAX
469 : strcpy(buf,"-2147483648");
470 : assert(string2l(buf,strlen(buf),&v) == 1);
471 : assert(v == LONG_MIN);
472 :
473 : strcpy(buf,"-2147483649"); /* overflow */
474 : assert(string2l(buf,strlen(buf),&v) == 0);
475 :
476 : strcpy(buf,"2147483647");
477 : assert(string2l(buf,strlen(buf),&v) == 1);
478 : assert(v == LONG_MAX);
479 :
480 : strcpy(buf,"2147483648"); /* overflow */
481 : assert(string2l(buf,strlen(buf),&v) == 0);
482 : #endif
483 : }
484 :
485 : int main(int argc, char **argv) {
486 : test_string2ll();
487 : test_string2l();
488 : return 0;
489 : }
490 : #endif
|