]>
git.saurik.com Git - redis.git/blob - src/util.c
6 /* Glob-style pattern matching. */
7 int stringmatchlen(const char *pattern
, int patternLen
,
8 const char *string
, int stringLen
, int nocase
)
13 while (pattern
[1] == '*') {
20 if (stringmatchlen(pattern
+1, patternLen
-1,
21 string
, stringLen
, nocase
))
26 return 0; /* no match */
30 return 0; /* no match */
40 not = pattern
[0] == '^';
47 if (pattern
[0] == '\\') {
50 if (pattern
[0] == string
[0])
52 } else if (pattern
[0] == ']') {
54 } else if (patternLen
== 0) {
58 } else if (pattern
[1] == '-' && patternLen
>= 3) {
59 int start
= pattern
[0];
68 start
= tolower(start
);
74 if (c
>= start
&& c
<= end
)
78 if (pattern
[0] == string
[0])
81 if (tolower((int)pattern
[0]) == tolower((int)string
[0]))
91 return 0; /* no match */
97 if (patternLen
>= 2) {
104 if (pattern
[0] != string
[0])
105 return 0; /* no match */
107 if (tolower((int)pattern
[0]) != tolower((int)string
[0]))
108 return 0; /* no match */
116 if (stringLen
== 0) {
117 while(*pattern
== '*') {
124 if (patternLen
== 0 && stringLen
== 0)
129 int stringmatch(const char *pattern
, const char *string
, int nocase
) {
130 return stringmatchlen(pattern
,strlen(pattern
),string
,strlen(string
),nocase
);
133 /* Convert a string representing an amount of memory into the number of
134 * bytes, so for instance memtoll("1Gi") will return 1073741824 that is
137 * On parsing error, if *err is not NULL, it's set to 1, otherwise it's
139 long long memtoll(const char *p
, int *err
) {
142 long mul
; /* unit multiplier */
147 /* Search the first non digit character. */
150 while(*u
&& isdigit(*u
)) u
++;
151 if (*u
== '\0' || !strcasecmp(u
,"b")) {
153 } else if (!strcasecmp(u
,"k")) {
155 } else if (!strcasecmp(u
,"kb")) {
157 } else if (!strcasecmp(u
,"m")) {
159 } else if (!strcasecmp(u
,"mb")) {
161 } else if (!strcasecmp(u
,"g")) {
162 mul
= 1000L*1000*1000;
163 } else if (!strcasecmp(u
,"gb")) {
164 mul
= 1024L*1024*1024;
170 if (digits
>= sizeof(buf
)) {
174 memcpy(buf
,p
,digits
);
176 val
= strtoll(buf
,NULL
,10);
180 /* Convert a long long into a string. Returns the number of
181 * characters needed to represent the number, that can be shorter if passed
182 * buffer length is not enough to store the whole number. */
183 int ll2string(char *s
, size_t len
, long long value
) {
185 unsigned long long v
;
188 if (len
== 0) return 0;
189 v
= (value
< 0) ? -value
: value
;
190 p
= buf
+31; /* point to the last character */
195 if (value
< 0) *p
-- = '-';
198 if (l
+1 > len
) l
= len
-1; /* Make sure it fits, including the nul term */
204 /* Convert a string into a long long. Returns 1 if the string could be parsed
205 * into a (non-overflowing) long long, 0 otherwise. The value will be set to
206 * the parsed value when appropriate. */
207 int string2ll(char *s
, size_t slen
, long long *value
) {
211 unsigned long long v
;
220 /* Abort on only a negative sign. */
225 /* First digit should be 1-9. */
226 if (p
[0] >= '1' && p
[0] <= '9') {
233 while (plen
< slen
&& p
[0] >= '0' && p
[0] <= '9') {
234 if (v
> (ULLONG_MAX
/ 10)) /* Overflow. */
238 if (v
> (ULLONG_MAX
- (p
[0]-'0'))) /* Overflow. */
245 /* Return if not all bytes were used. */
250 if (v
> (-(unsigned long long)LLONG_MIN
)) /* Overflow. */
252 if (value
!= NULL
) *value
= -v
;
254 if (v
> LLONG_MAX
) /* Overflow. */
256 if (value
!= NULL
) *value
= v
;
261 /* Convert a double to a string representation. Returns the number of bytes
262 * required. The representation should always be parsable by stdtod(3). */
263 int d2string(char *buf
, size_t len
, double value
) {
265 len
= snprintf(buf
,len
,"nan");
266 } else if (isinf(value
)) {
268 len
= snprintf(buf
,len
,"-inf");
270 len
= snprintf(buf
,len
,"inf");
271 } else if (value
== 0) {
272 /* See: http://en.wikipedia.org/wiki/Signed_zero, "Comparisons". */
274 len
= snprintf(buf
,len
,"-0");
276 len
= snprintf(buf
,len
,"0");
278 #if (DBL_MANT_DIG >= 52) && (LLONG_MAX == 0x7fffffffffffffffLL)
279 /* Check if the float is in a safe range to be casted into a
280 * long long. We are assuming that long long is 64 bit here.
281 * Also we are assuming that there are no implementations around where
282 * double has precision < 52 bit.
284 * Under this assumptions we test if a double is inside an interval
285 * where casting to long long is safe. Then using two castings we
286 * make sure the decimal part is zero. If all this is true we use
287 * integer printing function that is much faster. */
288 double min
= -4503599627370495; /* (2^52)-1 */
289 double max
= 4503599627370496; /* -(2^52) */
290 if (val
> min
&& val
< max
&& value
== ((double)((long long)value
)))
291 len
= ll2string(buf
,len
,(long long)value
);
294 len
= snprintf(buf
,len
,"%.17g",value
);
300 /* Check if the sds string 's' can be represented by a long long
301 * (that is, is a number that fits into long without any other space or
302 * character before or after the digits, so that converting this number
303 * back to a string will result in the same bytes as the original string).
305 * If so, the function returns REDIS_OK and *llongval is set to the value
306 * of the number. Otherwise REDIS_ERR is returned */
307 int isStringRepresentableAsLongLong(sds s
, long long *llongval
) {
308 char buf
[32], *endptr
;
312 value
= strtoll(s
, &endptr
, 10);
313 if (endptr
[0] != '\0') return REDIS_ERR
;
314 slen
= ll2string(buf
,32,value
);
316 /* If the number converted back into a string is not identical
317 * then it's not possible to encode the string as integer */
318 if (sdslen(s
) != (unsigned)slen
|| memcmp(buf
,s
,slen
)) return REDIS_ERR
;
319 if (llongval
) *llongval
= value
;
323 int isStringRepresentableAsLong(sds s
, long *longval
) {
326 if (isStringRepresentableAsLongLong(s
,&ll
) == REDIS_ERR
) return REDIS_ERR
;
327 if (ll
< LONG_MIN
|| ll
> LONG_MAX
) return REDIS_ERR
;
332 int isObjectRepresentableAsLongLong(robj
*o
, long long *llongval
) {
333 redisAssert(o
->type
== REDIS_STRING
);
334 if (o
->encoding
== REDIS_ENCODING_INT
) {
335 if (llongval
) *llongval
= (long) o
->ptr
;
338 return isStringRepresentableAsLongLong(o
->ptr
,llongval
);