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 9 #include "util.h" 10 11 /* Glob-style pattern matching. */ 12 int stringmatchlen(const char *pattern, int patternLen, 13 const char *string, int stringLen, int nocase) 14 { 15 while(patternLen) { 16 switch(pattern[0]) { 17 case '*': 18 while (pattern[1] == '*') { 19 pattern++; 20 patternLen--; 21 } 22 if (patternLen == 1) 23 return 1; /* match */ 24 while(stringLen) { 25 if (stringmatchlen(pattern+1, patternLen-1, 26 string, stringLen, nocase)) 27 return 1; /* match */ 28 string++; 29 stringLen--; 30 } 31 return 0; /* no match */ 32 break; 33 case '?': 34 if (stringLen == 0) 35 return 0; /* no match */ 36 string++; 37 stringLen--; 38 break; 39 case '[': 40 { 41 int not, match; 42 43 pattern++; 44 patternLen--; 45 not = pattern[0] == '^'; 46 if (not) { 47 pattern++; 48 patternLen--; 49 } 50 match = 0; 51 while(1) { 52 if (pattern[0] == '\\') { 53 pattern++; 54 patternLen--; 55 if (pattern[0] == string[0]) 56 match = 1; 57 } else if (pattern[0] == ']') { 58 break; 59 } else if (patternLen == 0) { 60 pattern--; 61 patternLen++; 62 break; 63 } else if (pattern[1] == '-' && patternLen >= 3) { 64 int start = pattern[0]; 65 int end = pattern[2]; 66 int c = string[0]; 67 if (start > end) { 68 int t = start; 69 start = end; 70 end = t; 71 } 72 if (nocase) { 73 start = tolower(start); 74 end = tolower(end); 75 c = tolower(c); 76 } 77 pattern += 2; 78 patternLen -= 2; 79 if (c >= start && c <= end) 80 match = 1; 81 } else { 82 if (!nocase) { 83 if (pattern[0] == string[0]) 84 match = 1; 85 } else { 86 if (tolower((int)pattern[0]) == tolower((int)string[0])) 87 match = 1; 88 } 89 } 90 pattern++; 91 patternLen--; 92 } 93 if (not) 94 match = !match; 95 if (!match) 96 return 0; /* no match */ 97 string++; 98 stringLen--; 99 break; 100 } 101 case '\\': 102 if (patternLen >= 2) { 103 pattern++; 104 patternLen--; 105 } 106 /* fall through */ 107 default: 108 if (!nocase) { 109 if (pattern[0] != string[0]) 110 return 0; /* no match */ 111 } else { 112 if (tolower((int)pattern[0]) != tolower((int)string[0])) 113 return 0; /* no match */ 114 } 115 string++; 116 stringLen--; 117 break; 118 } 119 pattern++; 120 patternLen--; 121 if (stringLen == 0) { 122 while(*pattern == '*') { 123 pattern++; 124 patternLen--; 125 } 126 break; 127 } 128 } 129 if (patternLen == 0 && stringLen == 0) 130 return 1; 131 return 0; 132 } 133 134 int stringmatch(const char *pattern, const char *string, int nocase) { 135 return stringmatchlen(pattern,strlen(pattern),string,strlen(string),nocase); 136 } 137 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 140 * (1024*1024*1024). 141 * 142 * On parsing error, if *err is not NULL, it's set to 1, otherwise it's 143 * set to 0 */ 144 long long memtoll(const char *p, int *err) { 145 const char *u; 146 char buf[128]; 147 long mul; /* unit multiplier */ 148 long long val; 149 unsigned int digits; 150 151 if (err) *err = 0; 152 /* Search the first non digit character. */ 153 u = p; 154 if (*u == '-') u++; 155 while(*u && isdigit(*u)) u++; 156 if (*u == '\0' || !strcasecmp(u,"b")) { 157 mul = 1; 158 } else if (!strcasecmp(u,"k")) { 159 mul = 1000; 160 } else if (!strcasecmp(u,"kb")) { 161 mul = 1024; 162 } else if (!strcasecmp(u,"m")) { 163 mul = 1000*1000; 164 } else if (!strcasecmp(u,"mb")) { 165 mul = 1024*1024; 166 } else if (!strcasecmp(u,"g")) { 167 mul = 1000L*1000*1000; 168 } else if (!strcasecmp(u,"gb")) { 169 mul = 1024L*1024*1024; 170 } else { 171 if (err) *err = 1; 172 mul = 1; 173 } 174 digits = u-p; 175 if (digits >= sizeof(buf)) { 176 if (err) *err = 1; 177 return LLONG_MAX; 178 } 179 memcpy(buf,p,digits); 180 buf[digits] = '\0'; 181 val = strtoll(buf,NULL,10); 182 return val*mul; 183 } 184 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) { 189 char buf[32], *p; 190 unsigned long long v; 191 size_t l; 192 193 if (len == 0) return 0; 194 v = (value < 0) ? -value : value; 195 p = buf+31; /* point to the last character */ 196 do { 197 *p-- = '0'+(v%10); 198 v /= 10; 199 } while(v); 200 if (value < 0) *p-- = '-'; 201 p++; 202 l = 32-(p-buf); 203 if (l+1 > len) l = len-1; /* Make sure it fits, including the nul term */ 204 memcpy(s,p,l); 205 s[l] = '\0'; 206 return l; 207 } 208 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) { 213 char *p = s; 214 size_t plen = 0; 215 int negative = 0; 216 unsigned long long v; 217 218 if (plen == slen) 219 return 0; 220 221 /* Special case: first and only digit is 0. */ 222 if (slen == 1 && p[0] == '0') { 223 if (value != NULL) *value = 0; 224 return 1; 225 } 226 227 if (p[0] == '-') { 228 negative = 1; 229 p++; plen++; 230 231 /* Abort on only a negative sign. */ 232 if (plen == slen) 233 return 0; 234 } 235 236 /* First digit should be 1-9, otherwise the string should just be 0. */ 237 if (p[0] >= '1' && p[0] <= '9') { 238 v = p[0]-'0'; 239 p++; plen++; 240 } else if (p[0] == '0' && slen == 1) { 241 *value = 0; 242 return 1; 243 } else { 244 return 0; 245 } 246 247 while (plen < slen && p[0] >= '0' && p[0] <= '9') { 248 if (v > (ULLONG_MAX / 10)) /* Overflow. */ 249 return 0; 250 v *= 10; 251 252 if (v > (ULLONG_MAX - (p[0]-'0'))) /* Overflow. */ 253 return 0; 254 v += p[0]-'0'; 255 256 p++; plen++; 257 } 258 259 /* Return if not all bytes were used. */ 260 if (plen < slen) 261 return 0; 262 263 if (negative) { 264 if (v > ((unsigned long long)(-(LLONG_MIN+1))+1)) /* Overflow. */ 265 return 0; 266 if (value != NULL) *value = -v; 267 } else { 268 if (v > LLONG_MAX) /* Overflow. */ 269 return 0; 270 if (value != NULL) *value = v; 271 } 272 return 1; 273 } 274 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) { 279 long long llval; 280 281 if (!string2ll(s,slen,&llval)) 282 return 0; 283 284 if (llval < LONG_MIN || llval > LONG_MAX) 285 return 0; 286 287 *lval = (long)llval; 288 return 1; 289 } 290 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) { 294 if (isnan(value)) { 295 len = snprintf(buf,len,"nan"); 296 } else if (isinf(value)) { 297 if (value < 0) 298 len = snprintf(buf,len,"-inf"); 299 else 300 len = snprintf(buf,len,"inf"); 301 } else if (value == 0) { 302 /* See: http://en.wikipedia.org/wiki/Signed_zero, "Comparisons". */ 303 if (1.0/value < 0) 304 len = snprintf(buf,len,"-0"); 305 else 306 len = snprintf(buf,len,"0"); 307 } else { 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. 313 * 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); 322 else 323 #endif 324 len = snprintf(buf,len,"%.17g",value); 325 } 326 327 return len; 328 } 329 330 #ifdef UTIL_TEST_MAIN 331 #include <assert.h> 332 333 void test_string2ll(void) { 334 char buf[32]; 335 long long v; 336 337 /* May not start with +. */ 338 strcpy(buf,"+1"); 339 assert(string2ll(buf,strlen(buf),&v) == 0); 340 341 /* Leading space. */ 342 strcpy(buf," 1"); 343 assert(string2ll(buf,strlen(buf),&v) == 0); 344 345 /* Trailing space. */ 346 strcpy(buf,"1 "); 347 assert(string2ll(buf,strlen(buf),&v) == 0); 348 349 /* May not start with 0. */ 350 strcpy(buf,"01"); 351 assert(string2ll(buf,strlen(buf),&v) == 0); 352 353 strcpy(buf,"-1"); 354 assert(string2ll(buf,strlen(buf),&v) == 1); 355 assert(v == -1); 356 357 strcpy(buf,"0"); 358 assert(string2ll(buf,strlen(buf),&v) == 1); 359 assert(v == 0); 360 361 strcpy(buf,"1"); 362 assert(string2ll(buf,strlen(buf),&v) == 1); 363 assert(v == 1); 364 365 strcpy(buf,"99"); 366 assert(string2ll(buf,strlen(buf),&v) == 1); 367 assert(v == 99); 368 369 strcpy(buf,"-99"); 370 assert(string2ll(buf,strlen(buf),&v) == 1); 371 assert(v == -99); 372 373 strcpy(buf,"-9223372036854775808"); 374 assert(string2ll(buf,strlen(buf),&v) == 1); 375 assert(v == LLONG_MIN); 376 377 strcpy(buf,"-9223372036854775809"); /* overflow */ 378 assert(string2ll(buf,strlen(buf),&v) == 0); 379 380 strcpy(buf,"9223372036854775807"); 381 assert(string2ll(buf,strlen(buf),&v) == 1); 382 assert(v == LLONG_MAX); 383 384 strcpy(buf,"9223372036854775808"); /* overflow */ 385 assert(string2ll(buf,strlen(buf),&v) == 0); 386 } 387 388 void test_string2l(void) { 389 char buf[32]; 390 long v; 391 392 /* May not start with +. */ 393 strcpy(buf,"+1"); 394 assert(string2l(buf,strlen(buf),&v) == 0); 395 396 /* May not start with 0. */ 397 strcpy(buf,"01"); 398 assert(string2l(buf,strlen(buf),&v) == 0); 399 400 strcpy(buf,"-1"); 401 assert(string2l(buf,strlen(buf),&v) == 1); 402 assert(v == -1); 403 404 strcpy(buf,"0"); 405 assert(string2l(buf,strlen(buf),&v) == 1); 406 assert(v == 0); 407 408 strcpy(buf,"1"); 409 assert(string2l(buf,strlen(buf),&v) == 1); 410 assert(v == 1); 411 412 strcpy(buf,"99"); 413 assert(string2l(buf,strlen(buf),&v) == 1); 414 assert(v == 99); 415 416 strcpy(buf,"-99"); 417 assert(string2l(buf,strlen(buf),&v) == 1); 418 assert(v == -99); 419 420 #if LONG_MAX != LLONG_MAX 421 strcpy(buf,"-2147483648"); 422 assert(string2l(buf,strlen(buf),&v) == 1); 423 assert(v == LONG_MIN); 424 425 strcpy(buf,"-2147483649"); /* overflow */ 426 assert(string2l(buf,strlen(buf),&v) == 0); 427 428 strcpy(buf,"2147483647"); 429 assert(string2l(buf,strlen(buf),&v) == 1); 430 assert(v == LONG_MAX); 431 432 strcpy(buf,"2147483648"); /* overflow */ 433 assert(string2l(buf,strlen(buf),&v) == 0); 434 #endif 435 } 436 437 int main(int argc, char **argv) { 438 test_string2ll(); 439 test_string2l(); 440 return 0; 441 } 442 #endif 443