515 | | return METRIC_STRING; |
---|
| 520 | copy = cp = strdup(s); |
---|
| 521 | |
---|
| 522 | /* TRIM the string */ |
---|
| 523 | while(*cp && isspace(*cp)) cp++; /* ltrim */ |
---|
| 524 | s = cp; /* found a good starting point */ |
---|
| 525 | while(*cp) cp++; /* advance to \0 */ |
---|
| 526 | cp--; /* back up one */ |
---|
| 527 | while(cp > s && isspace(*cp)) *cp-- = '\0'; /* rtrim */ |
---|
| 528 | |
---|
| 529 | /* Find the first space */ |
---|
| 530 | cp = (char *)s; |
---|
| 531 | while(*cp && !isspace(*cp)) cp++; |
---|
| 532 | trailer = cp; |
---|
| 533 | cp--; /* backup one */ |
---|
| 534 | if(cp > s && *cp == '%') *cp-- = '\0'; /* chop a last % is there is one */ |
---|
| 535 | |
---|
| 536 | while(*trailer && isspace(*trailer)) *trailer++; /* rtrim */ |
---|
| 537 | |
---|
| 538 | /* string was ' -1.23e-01% inodes used ' */ |
---|
| 539 | /* copy is (~ = \0) ' -1.23e-01~ inodes used~~' */ |
---|
| 540 | /* ^ ^ */ |
---|
| 541 | /* s trailer */ |
---|
| 542 | |
---|
| 543 | /* So, the trailer must not contain numbers */ |
---|
| 544 | while(*trailer) { if(isdigit(*trailer)) goto notanumber; trailer++; } |
---|
| 545 | |
---|
| 546 | /* And the 's' must be of the form: |
---|
| 547 | * 0) may start with a sign [-+]? |
---|
| 548 | * 1) [1-9][0-9]* |
---|
| 549 | * 2) [0]?.[0-9]+ |
---|
| 550 | * 3) 0 |
---|
| 551 | * 4) [1-9][0-9]*.[0-9]+ |
---|
| 552 | * 5) all of the above ending with e[+-][0-9]+ |
---|
| 553 | */ |
---|
| 554 | rpl = (char *)s; |
---|
| 555 | /* CASE 0 */ |
---|
| 556 | if(s[0] == '-' || s[0] == '+') { |
---|
| 557 | if(s[0] == '-') negative = 1; |
---|
| 558 | s++; |
---|
| 559 | } |
---|
| 560 | |
---|
| 561 | if(s[0] == '.') goto decimal; /* CASE 2 */ |
---|
| 562 | if(s[0] == '0') { /* CASE 2 & 3 */ |
---|
| 563 | s++; |
---|
| 564 | if(!s[0]) goto scanint; /* CASE 3 */ |
---|
| 565 | if(s[0] == '.') goto decimal; /* CASE 2 */ |
---|
| 566 | goto notanumber; |
---|
| 567 | } |
---|
| 568 | if(s[0] >= '1' && s[0] <= '9') { /* CASE 1 & 4 */ |
---|
| 569 | s++; |
---|
| 570 | while(isdigit(s[0])) s++; /* CASE 1 & 4 */ |
---|
| 571 | if(!s[0]) goto scanint; /* CASE 1 */ |
---|
| 572 | if(s[0] == '.') goto decimal; /* CASE 4 */ |
---|
| 573 | goto notanumber; |
---|
| 574 | } |
---|
| 575 | /* Not case 1,2,3,4 */ |
---|
| 576 | goto notanumber; |
---|
| 577 | |
---|
| 578 | decimal: |
---|
| 579 | s++; |
---|
| 580 | if(!isdigit(s[0])) goto notanumber; |
---|
| 581 | s++; |
---|
| 582 | while(isdigit(s[0])) s++; |
---|
| 583 | if(!s[0]) goto scandouble; |
---|
| 584 | if(s[0] == 'e' || s[0] == 'E') goto exponent; /* CASE 5 */ |
---|
| 585 | goto notanumber; |
---|
| 586 | |
---|
| 587 | exponent: |
---|
| 588 | if(s[0] == 'E') bigF = 1; /* We want the caps variant */ |
---|
| 589 | s++; |
---|
| 590 | if(s[0] != '-' && s[0] != '+') goto notanumber; |
---|
| 591 | s++; |
---|
| 592 | if(!isdigit(s[0])) goto notanumber; |
---|
| 593 | s++; |
---|
| 594 | while(isdigit(s[0])) s++; |
---|
| 595 | if(!s[0]) goto scandouble; |
---|
| 596 | goto notanumber; |
---|
| 597 | |
---|
| 598 | scanint: |
---|
| 599 | if(negative) { |
---|
| 600 | int64_t *v; |
---|
| 601 | v = calloc(1, sizeof(*v)); |
---|
| 602 | *v = strtoll(rpl, NULL, 10); |
---|
| 603 | *replacement = v; |
---|
| 604 | type = METRIC_INT64; |
---|
| 605 | goto alldone; |
---|
| 606 | } |
---|
| 607 | else { |
---|
| 608 | u_int64_t *v; |
---|
| 609 | v = calloc(1, sizeof(*v)); |
---|
| 610 | *v = strtoull(rpl, NULL, 10); |
---|
| 611 | *replacement = v; |
---|
| 612 | type = METRIC_UINT64; |
---|
| 613 | goto alldone; |
---|
| 614 | } |
---|
| 615 | scandouble: |
---|
| 616 | { |
---|
| 617 | double *v; |
---|
| 618 | v = calloc(1, sizeof(*v)); |
---|
| 619 | *v = strtod(rpl, NULL); |
---|
| 620 | *replacement = v; |
---|
| 621 | type = METRIC_DOUBLE; |
---|
| 622 | goto alldone; |
---|
| 623 | } |
---|
| 624 | |
---|
| 625 | alldone: |
---|
| 626 | notanumber: |
---|
| 627 | free(copy); |
---|
| 628 | return type; |
---|