Changeset 3118b56d7f3a3ab28ff8dcb187e25e2014f235ec

Show
Ignore:
Timestamp:
02/20/08 05:17:26 (6 years ago)
Author:
Theo Schlossnagle <jesus@omniti.com>
git-committer:
Theo Schlossnagle <jesus@omniti.com> 1203484646 +0000
git-parent:

[7b927621aa1d1fb7e9e915e74ab2a86ce90f73ac]

git-author:
Theo Schlossnagle <jesus@omniti.com> 1203484646 +0000
Message:

crazy guessing of string types and autoconversion to signed/unsigned int64s and doubles

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • src/noit_check.c

    r7b92762 r3118b56  
    99#include <stdlib.h> 
    1010#include <unistd.h> 
     11#include <ctype.h> 
    1112#include <assert.h> 
    1213#include <netinet/in.h> 
     
    511512} 
    512513static metric_type_t 
    513 noit_metric_guess_type(const char *s) { 
     514noit_metric_guess_type(const char *s, void **replacement) { 
     515  char *copy, *cp, *trailer, *rpl; 
     516  int negative = 0, bigF = 0; 
     517  metric_type_t type = METRIC_STRING; 
     518 
    514519  if(!s) return METRIC_GUESS; 
    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; 
    516629} 
    517630void 
     
    519632                      void *value) { 
    520633  metric_t *m; 
    521   if(type == METRIC_GUESS) type = noit_metric_guess_type((char *)value); 
     634  void *replacement = NULL; 
     635  if(type == METRIC_GUESS) 
     636    type = noit_metric_guess_type((char *)value, &replacement); 
    522637  if(type == METRIC_GUESS) return; 
    523638 
     
    525640  m->metric_name = strdup(name); 
    526641  m->metric_type = type; 
    527   if(value) { 
     642  if(replacement) 
     643    m->metric_value.vp = replacement; 
     644  else if(value) { 
    528645    size_t len; 
    529646    len = noit_metric_sizes(type, value);