]>
git.saurik.com Git - redis.git/blob - src/util.c
11 /* Glob-style pattern matching. */
12 int stringmatchlen(const char *pattern
, int patternLen
,
13 const char *string
, int stringLen
, int nocase
)
18 while (pattern
[1] == '*') {
25 if (stringmatchlen(pattern
+1, patternLen
-1,
26 string
, stringLen
, nocase
))
31 return 0; /* no match */
35 return 0; /* no match */
45 not = pattern
[0] == '^';
52 if (pattern
[0] == '\\') {
55 if (pattern
[0] == string
[0])
57 } else if (pattern
[0] == ']') {
59 } else if (patternLen
== 0) {
63 } else if (pattern
[1] == '-' && patternLen
>= 3) {
64 int start
= pattern
[0];
73 start
= tolower(start
);
79 if (c
>= start
&& c
<= end
)
83 if (pattern
[0] == string
[0])
86 if (tolower((int)pattern
[0]) == tolower((int)string
[0]))
96 return 0; /* no match */
102 if (patternLen
>= 2) {
109 if (pattern
[0] != string
[0])
110 return 0; /* no match */
112 if (tolower((int)pattern
[0]) != tolower((int)string
[0]))
113 return 0; /* no match */
121 if (stringLen
== 0) {
122 while(*pattern
== '*') {
129 if (patternLen
== 0 && stringLen
== 0)
134 int stringmatch(const char *pattern
, const char *string
, int nocase
) {
135 return stringmatchlen(pattern
,strlen(pattern
),string
,strlen(string
),nocase
);
138 /* Convert a string representing an amount of memory into the number of
139 * bytes, so for instance memtoll("1Gi") will return 1073741824 that is
142 * On parsing error, if *err is not NULL, it's set to 1, otherwise it's
144 long long memtoll(const char *p
, int *err
) {
147 long mul
; /* unit multiplier */
152 /* Search the first non digit character. */
155 while(*u
&& isdigit(*u
)) u
++;
156 if (*u
== '\0' || !strcasecmp(u
,"b")) {
158 } else if (!strcasecmp(u
,"k")) {
160 } else if (!strcasecmp(u
,"kb")) {
162 } else if (!strcasecmp(u
,"m")) {
164 } else if (!strcasecmp(u
,"mb")) {
166 } else if (!strcasecmp(u
,"g")) {
167 mul
= 1000L*1000*1000;
168 } else if (!strcasecmp(u
,"gb")) {
169 mul
= 1024L*1024*1024;
175 if (digits
>= sizeof(buf
)) {
179 memcpy(buf
,p
,digits
);
181 val
= strtoll(buf
,NULL
,10);
185 /* Convert a long long into a string. Returns the number of
186 * characters needed to represent the number, that can be shorter if passed
187 * buffer length is not enough to store the whole number. */
188 int ll2string(char *s
, size_t len
, long long value
) {
190 unsigned long long v
;
193 if (len
== 0) return 0;
194 v
= (value
< 0) ? -value
: value
;
195 p
= buf
+31; /* point to the last character */
200 if (value
< 0) *p
-- = '-';
203 if (l
+1 > len
) l
= len
-1; /* Make sure it fits, including the nul term */
209 /* Convert a string into a long long. Returns 1 if the string could be parsed
210 * into a (non-overflowing) long long, 0 otherwise. The value will be set to
211 * the parsed value when appropriate. */
212 int string2ll(char *s
, size_t slen
, long long *value
) {
216 unsigned long long v
;
221 /* Special case: first and only digit is 0. */
222 if (slen
== 1 && p
[0] == '0') {
223 if (value
!= NULL
) *value
= 0;
231 /* Abort on only a negative sign. */
236 /* First digit should be 1-9, otherwise the string should just be 0. */
237 if (p
[0] >= '1' && p
[0] <= '9') {
240 } else if (p
[0] == '0' && slen
== 1) {
247 while (plen
< slen
&& p
[0] >= '0' && p
[0] <= '9') {
248 if (v
> (ULLONG_MAX
/ 10)) /* Overflow. */
252 if (v
> (ULLONG_MAX
- (p
[0]-'0'))) /* Overflow. */
259 /* Return if not all bytes were used. */
264 if (v
> ((unsigned long long)(-(LLONG_MIN
+1))+1)) /* Overflow. */
266 if (value
!= NULL
) *value
= -v
;
268 if (v
> LLONG_MAX
) /* Overflow. */
270 if (value
!= NULL
) *value
= v
;
275 /* Convert a string into a long. Returns 1 if the string could be parsed into a
276 * (non-overflowing) long, 0 otherwise. The value will be set to the parsed
277 * value when appropriate. */
278 int string2l(char *s
, size_t slen
, long *lval
) {
281 if (!string2ll(s
,slen
,&llval
))
284 if (llval
< LONG_MIN
|| llval
> LONG_MAX
)
291 /* Convert a double to a string representation. Returns the number of bytes
292 * required. The representation should always be parsable by stdtod(3). */
293 int d2string(char *buf
, size_t len
, double value
) {
295 len
= snprintf(buf
,len
,"nan");
296 } else if (isinf(value
)) {
298 len
= snprintf(buf
,len
,"-inf");
300 len
= snprintf(buf
,len
,"inf");
301 } else if (value
== 0) {
302 /* See: http://en.wikipedia.org/wiki/Signed_zero, "Comparisons". */
304 len
= snprintf(buf
,len
,"-0");
306 len
= snprintf(buf
,len
,"0");
308 #if (DBL_MANT_DIG >= 52) && (LLONG_MAX == 0x7fffffffffffffffLL)
309 /* Check if the float is in a safe range to be casted into a
310 * long long. We are assuming that long long is 64 bit here.
311 * Also we are assuming that there are no implementations around where
312 * double has precision < 52 bit.
314 * Under this assumptions we test if a double is inside an interval
315 * where casting to long long is safe. Then using two castings we
316 * make sure the decimal part is zero. If all this is true we use
317 * integer printing function that is much faster. */
318 double min
= -4503599627370495; /* (2^52)-1 */
319 double max
= 4503599627370496; /* -(2^52) */
320 if (val
> min
&& val
< max
&& value
== ((double)((long long)value
)))
321 len
= ll2string(buf
,len
,(long long)value
);
324 len
= snprintf(buf
,len
,"%.17g",value
);
330 #ifdef UTIL_TEST_MAIN
333 void test_string2ll(void) {
337 /* May not start with +. */
339 assert(string2ll(buf
,strlen(buf
),&v
) == 0);
343 assert(string2ll(buf
,strlen(buf
),&v
) == 0);
345 /* Trailing space. */
347 assert(string2ll(buf
,strlen(buf
),&v
) == 0);
349 /* May not start with 0. */
351 assert(string2ll(buf
,strlen(buf
),&v
) == 0);
354 assert(string2ll(buf
,strlen(buf
),&v
) == 1);
358 assert(string2ll(buf
,strlen(buf
),&v
) == 1);
362 assert(string2ll(buf
,strlen(buf
),&v
) == 1);
366 assert(string2ll(buf
,strlen(buf
),&v
) == 1);
370 assert(string2ll(buf
,strlen(buf
),&v
) == 1);
373 strcpy(buf
,"-9223372036854775808");
374 assert(string2ll(buf
,strlen(buf
),&v
) == 1);
375 assert(v
== LLONG_MIN
);
377 strcpy(buf
,"-9223372036854775809"); /* overflow */
378 assert(string2ll(buf
,strlen(buf
),&v
) == 0);
380 strcpy(buf
,"9223372036854775807");
381 assert(string2ll(buf
,strlen(buf
),&v
) == 1);
382 assert(v
== LLONG_MAX
);
384 strcpy(buf
,"9223372036854775808"); /* overflow */
385 assert(string2ll(buf
,strlen(buf
),&v
) == 0);
388 void test_string2l(void) {
392 /* May not start with +. */
394 assert(string2l(buf
,strlen(buf
),&v
) == 0);
396 /* May not start with 0. */
398 assert(string2l(buf
,strlen(buf
),&v
) == 0);
401 assert(string2l(buf
,strlen(buf
),&v
) == 1);
405 assert(string2l(buf
,strlen(buf
),&v
) == 1);
409 assert(string2l(buf
,strlen(buf
),&v
) == 1);
413 assert(string2l(buf
,strlen(buf
),&v
) == 1);
417 assert(string2l(buf
,strlen(buf
),&v
) == 1);
420 #if LONG_MAX != LLONG_MAX
421 strcpy(buf
,"-2147483648");
422 assert(string2l(buf
,strlen(buf
),&v
) == 1);
423 assert(v
== LONG_MIN
);
425 strcpy(buf
,"-2147483649"); /* overflow */
426 assert(string2l(buf
,strlen(buf
),&v
) == 0);
428 strcpy(buf
,"2147483647");
429 assert(string2l(buf
,strlen(buf
),&v
) == 1);
430 assert(v
== LONG_MAX
);
432 strcpy(buf
,"2147483648"); /* overflow */
433 assert(string2l(buf
,strlen(buf
),&v
) == 0);
437 int main(int argc
, char **argv
) {