char *endptr;
int status;
size_t i;
+ double tmp;
if ((str_array = (char**)malloc(array_len * sizeof (char*))) == NULL)
return (-1);
* will expect a comma as the decimal separator, i.e. "42,77". */
for (i = 0; i < array_len; i++)
{
- endptr = NULL;
- array[i] = (rrd_value_t) rrd_strtod (str_array[i], &endptr);
- if ((endptr == str_array[i]) || (errno != 0))
- {
- free(str_array);
- return (-1);
+ if( rrd_strtoding(str_array[i], 0, &tmp) == 2) {
+ array[i] = (rrd_value_t)tmp;
+ } else {
+ free(str_array);
+ return (-1);
}
}
|| (strcmp ("TreeNodesNumber", key) == 0))
{
s->type = RRDC_STATS_TYPE_GAUGE;
- s->value.gauge = rrd_strtod (value, &endptr);
+ rrd_strtoding(value, &endptr, &(s->value.gauge));
}
else if ((strcmp ("DataSetsWritten", key) == 0)
|| (strcmp ("FlushesReceived", key) == 0)
}
/* Conversion failed */
- if (endptr == value)
+ if ( (endptr == value) || (endptr[0] != '\0') )
{
free (s);
continue;
if (minstr[0] == 'U' && minstr[1] == 0)
ds_def->par[DS_min_val].u_val = DNAN;
else
- ds_def->par[DS_min_val].u_val = rrd_strtod(minstr, 0);
+ rrd_strtoding(minstr, 0, &(ds_def->par[DS_min_val].u_val) );
if (maxstr[0] == 'U' && maxstr[1] == 0)
ds_def->par[DS_max_val].u_val = DNAN;
else
- ds_def->par[DS_max_val].u_val = rrd_strtod(maxstr, 0);
+ rrd_strtoding(maxstr, 0, &(ds_def->par[DS_max_val].u_val) );
if (!isnan(ds_def->par[DS_min_val].u_val) &&
!isnan(ds_def->par[DS_max_val].u_val) &&
/* make sure update time is always moving forward. We use double here since
update does support subsecond precision for timestamps ... */
- stamp = rrd_strtod(value, &eostamp);
- if (eostamp == value || eostamp == NULL || *eostamp != ':')
+ if ( ( rrd_strtoding( value, &eostamp, &stamp ) != 2 ) || *eostamp != ':')
{
pthread_mutex_unlock(&cache_lock);
return send_response(sock, RESP_ERR,
switch (type) {
case DBI_TYPE_STRING:
ptmp=(char*)dbi_result_get_string_idx(result,idx);
- value=rrd_strtod(ptmp,NULL);
+ rrd_strtoding(ptmp,NULL, &value);
break;
case DBI_TYPE_INTEGER:
if (attr & DBI_INTEGER_SIZE1) { value=dbi_result_get_char_idx(result,idx);
}
}
/* convert to number */
- value=rrd_strtod(ptmp,NULL);
+ rrd_strtoding(ptmp,NULL, &value);
/* free pointer */
free(ptmp);
break;
im->forceleftspace = 1;
break;
case 'T':
- im->tabwidth = rrd_strtod(optarg, 0);
+ rrd_strtoding(optarg, 0, &(im->tabwidth) );
break;
case 'S':
im->step = atoi(optarg);
break;
};
if (sscanf(optarg, "%[-0-9.e+]:%d", double_str , &im->ylabfact) == 2) {
- im->ygridstep = rrd_strtod( double_str, 0 );
+ rrd_strtoding( double_str, 0, &(im->ygridstep) );
if (im->ygridstep <= 0) {
rrd_set_error("grid step must be > 0");
return;
"%[-0-9.e+]:%[-0-9.e+]",
double_str,
double_str2 ) != 2) {
- im->grid_dash_on = rrd_strtod( double_str, 0 );
- im->grid_dash_off = rrd_strtod( double_str2, 0 );
+ rrd_strtoding( double_str, 0, &(im->grid_dash_on) );
+ rrd_strtoding( double_str2, 0, &(im->grid_dash_off) );
rrd_set_error("expected grid-dash format float:float");
return;
}
"%[-0-9.e+]:%[-0-9.e+]",
double_str,
double_str2 ) == 2) {
- im->second_axis_scale = rrd_strtod( double_str, 0 );
- im->second_axis_shift = rrd_strtod( double_str2, 0 );
+ rrd_strtoding( double_str, 0, &(im->second_axis_scale) );
+ rrd_strtoding( double_str2, 0, &(im->second_axis_shift) );
if(im->second_axis_scale==0){
rrd_set_error("the second_axis_scale must not be 0");
return;
}
break;
case 'u':
- im->maxval = rrd_strtod(optarg, 0);
+ rrd_strtoding(optarg, 0, &(im->maxval));
break;
case 'l':
- im->minval = rrd_strtod(optarg, 0);
+ rrd_strtoding(optarg, 0, &(im->minval));
break;
case 'b':
im->base = atol(optarg);
int end;
if (sscanf(optarg, "%10[A-Z]:%[-0-9.e+]%n", prop, double_str, &end) >= 2) {
- size = rrd_strtod( double_str, 0 );
+ rrd_strtoding( double_str, 0, &size );
int sindex, propidx;
if ((sindex = text_prop_conv(prop)) != -1) {
break;
}
case 'm':
- im->zoom = rrd_strtod(optarg, 0);
+ rrd_strtoding(optarg, 0, &(im->zoom));
if (im->zoom <= 0.0) {
rrd_set_error("zoom factor must be > 0");
return;
}
break;
case 't':
- im->title=strdup(optarg);
- if (!im->title) {
+ im->title=strdup(optarg);
+ if (!im->title) {
rrd_set_error("cannot allocate memory for title");
return;
- }
+ }
break;
case 'R':
if (strcmp(optarg, "normal") == 0) {
n = 0;
sscanf(str, "%[-0-9.e+],%29[A-Z]%n", double_str, func, &n);
- param = rrd_strtod( double_str, 0 );
+ rrd_strtoding( double_str, 0, ¶m );
if (n == (int) strlen(str)) { /* matched */
;
} else {
int getDouble(const char* v, double *val,char**extra) {
/* try to execute the parser */
/* NOTE that this may be a bit different from the original parser */
+ unsigned int strtod_ret;
*extra=NULL;
- errno = 0;
- *val = rrd_strtod(v,extra);
- if (errno > 0) {
- rrd_set_error("converting '%s' to float: %s", v, rrd_strerror(errno));
- return -1;
- };
-
- *val=rrd_strtod(v,extra);
- /* and error handling */
- if (extra==NULL) {
- return 0;
- } else {
- if (*extra==v) {
- return -1; /* failed miserably */
- } else {
- if ((*extra)[0]==0) { return 0; }
- return 1; /* got extra bytes */
- }
+
+ if( rrd_strtoding( v, extra, val ) != 2 ) {
+ return -1;
}
- /* not found, so return error */
- return -2;
+
+ strtod_ret = rrd_strtoding( v, extra, val );
+
+ /* see rrd_strtoding's return values for more infromation */
+ if( strtod_ret == 0 )
+ return -1;
+ else if( strtod_ret == 1 )
+ return 1;
+ else if( strtod_ret == 2 )
+ return 0;
+ else
+ return -2;
}
int addToArguments(parsedargs_t* pa, char*key, char*value, int cnt) {
xmlFree(text);
return 0;
}
- errno = 0;
- temp = rrd_strtod((char *)text,NULL);
- if (errno>0){
+ if ( rrd_strtoding((char *)text,NULL, &temp) != 2 ){
rrd_set_error("ling %d: get_xml_double from '%s' %s",
xmlTextReaderGetParserLineNumber(reader),
text,rrd_strerror(errno));
- xmlFree(text);
+ xmlFree(text);
return -1;
}
xmlFree(text);
else if ((sscanf(expr, "%[-0-9.e+]%n", double_str, &pos) == 1)
&& (expr[pos] == ',')) {
- rpnp[steps].val = rrd_strtod( double_str, 0 );
+ rrd_strtoding( double_str, 0, &(rpnp[steps].val) );
rpnp[steps].op = OP_NUMBER;
expr += pos;
}
break;
case OP_GT:
stackunderflow(1);
+ printf("in OP_GT\n");
if (isnan(rpnstack->s[stptr - 1]));
else if (isnan(rpnstack->s[stptr]))
rpnstack->s[stptr - 1] = rpnstack->s[stptr];
else
rpnstack->s[stptr - 1] = rpnstack->s[stptr - 1] >
rpnstack->s[stptr] ? 1.0 : 0.0;
+ printf("rpnstack->s[stptr - 1] = %f\n", rpnstack->s[stptr - 1]);
+ printf("rpnstack->s[stptr]) = %f\n", rpnstack->s[stptr] );
+ printf("rpnstack->s[stptr - 1] = %f\n", rpnstack->s[stptr - 1]);
stptr--;
break;
case OP_GE:
|| rpnstack->s[stptr - 2] ==
0.0) ? rpnstack->s[stptr] : rpnstack->
s[stptr - 1];
+ printf("In OP_IF\n");
+ printf("rpnstack->s[stptr - 2] = %f\n", rpnstack->s[stptr - 2]);
+ printf("rpnstack->s[stptr] = %f\n", rpnstack->s[stptr] );
+ printf("rpnstack->s[stptr - 1] = %f\n", rpnstack->s[stptr - 1]);
stptr--;
stptr--;
break;
// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
// SUCH DAMAGE.
//
-
+
#include <errno.h>
#include <ctype.h>
#include <math.h>
#include <float.h>
#include <stdlib.h>
-
+
+#include "rrd.h"
#include "rrd_strtod.h"
-
+
+/* returns 2 on success */
+/* i.e. if the whole string has been converted to a double successfully */
+unsigned int rrd_strtoding(const char * str, char ** endptr, double * dbl) {
+ *dbl = rrd_strtod( str, endptr );
+
+ if( endptr != NULL && *endptr == str ) {
+ /* no conversion has been done */
+ /* for inputs like "abcdj", i.e. no number at all */
+ rrd_set_error("Cannot convert %s to float", str);
+ return 0;
+ } else if( endptr != NULL && endptr[0] != '\0' ) {
+ /* conversion has been done, but whole string is not a number */
+ /* for inputs like "33.343djdjk" */
+ rrd_set_error("Cannot convert %s to float", str);
+ return 1;
+ } else if( endptr != NULL && endptr[0] == '\0' ) {
+ /* conversion successfully done */
+ /* for inputs that are totally numbers "23.343" */
+ return 2;
+ } else {
+ /* just to be safe */
+ rrd_set_error("..");
+ return 3;
+ }
+}
+
double rrd_strtod(const char *str, char **endptr) {
double number;
int exponent;
int n;
int num_digits;
int num_decimals;
-
+
// Skip leading whitespace
while (isspace(*p)) p++;
-
+
// Handle optional sign
negative = 0;
switch (*p) {
case '-': negative = 1; // Fall through to increment position
case '+': p++;
}
-
+
number = 0.;
exponent = 0;
num_digits = 0;
num_decimals = 0;
-
+
// Process string of digits
while (isdigit(*p)) {
number = number * 10. + (*p - '0');
p++;
num_digits++;
}
-
+
// Process decimal part
if (*p == '.') {
p++;
-
+
while (isdigit(*p)) {
number = number * 10. + (*p - '0');
p++;
num_digits++;
num_decimals++;
}
-
+
exponent -= num_decimals;
}
-
+
if (num_digits == 0) {
errno = ERANGE;
return 0.0;
}
-
+
// Correct for sign
if (negative) number = -number;
-
+
// Process an exponent string
if (*p == 'e' || *p == 'E') {
// Handle optional sign
case '-': negative = 1; // Fall through to increment pos
case '+': p++;
}
-
+
// Process string of digits
n = 0;
while (isdigit(*p)) {
n = n * 10 + (*p - '0');
p++;
}
-
+
if (negative) {
exponent -= n;
} else {
exponent += n;
}
}
-
+
if (exponent < DBL_MIN_EXP || exponent > DBL_MAX_EXP) {
errno = ERANGE;
return HUGE_VAL;
}
-
+
// Scale the result
p10 = 10.;
n = exponent;
n >>= 1;
p10 *= p10;
}
-
+
if (number == HUGE_VAL) errno = ERANGE;
if (endptr) *endptr = p;
-
+
return number;
}
+unsigned int rrd_strtoding(const char * str, char ** endptr, double * dbl);
double rrd_strtod(const char *str, char **endptr);
rrd_set_error("invalid arguments for minimum ds value");
goto done;
}
- min = rrd_strtod( double_str, 0 );
+ rrd_strtoding( double_str, 0, &min );
if ((ds = ds_match(&rrd, ds_nam)) == -1) {
goto done;
}
rrd_set_error("invalid arguments for maximum ds value");
goto done;
}
- max = rrd_strtod( double_str, 0 );
+ rrd_strtoding( double_str, 0, &max );
if ((ds = ds_match(&rrd, ds_nam)) == -1) {
goto done;
}
signed short rra_idx = -1;
/* read the value */
- param = rrd_strtod(arg, 0);
+ rrd_strtoding(arg, 0, ¶m);
if (param <= 0.0 || param >= 1.0) {
rrd_set_error("Holt-Winters parameter must be between 0 and 1");
return -1;
signed short rra_idx = -1;
/* read the value */
- param = rrd_strtod(arg, 0);
+ rrd_strtoding(arg, 0, ¶m);
/* in order to avoid smoothing of SEASONAL or DEVSEASONAL, we need to
* the 0.0 value*/
if (param < 0.0 || param > 1.0) {
unsigned long i;
signed short rra_idx = -1;
- param = rrd_strtod(arg, 0);
+ rrd_strtoding(arg, 0, ¶m);
if (param < 0.1) {
rrd_set_error("Parameter specified is too small");
return -1;
*current_time = tmp_time.tv_sec;
*current_time_usec = tmp_time.tv_usec;
} else {
- errno = 0;
- tmp = rrd_strtod(updvals[0], 0);
- if (errno > 0) {
- rrd_set_error("converting '%s' to float: %s",
- updvals[0], rrd_strerror(errno));
+ if ( rrd_strtoding( updvals[0], 0, &tmp) != 2) {
return -1;
};
if (tmp < 0.0){
{
unsigned long ds_idx;
int ii;
- char *endptr; /* used in the conversion */
double rate;
+ double tmp;
enum dst_en dst_idx;
for (ds_idx = 0; ds_idx < rrd->stat_head->ds_cnt; ds_idx++) {
}
break;
case DST_ABSOLUTE:
- errno = 0;
- pdp_new[ds_idx] = rrd_strtod(updvals[ds_idx + 1], &endptr);
- if (errno > 0) {
- rrd_set_error("converting '%s' to float: %s",
- updvals[ds_idx + 1], rrd_strerror(errno));
- return -1;
- };
- if (endptr[0] != '\0') {
- rrd_set_error
- ("conversion of '%s' to float not complete: tail '%s'",
- updvals[ds_idx + 1], endptr);
+ if( rrd_strtoding(updvals[ds_idx + 1], 0, &pdp_new[ds_idx] ) != 2 ) {
return -1;
}
rate = pdp_new[ds_idx] / interval;
break;
case DST_GAUGE:
- errno = 0;
- pdp_new[ds_idx] =
- rrd_strtod(updvals[ds_idx + 1], &endptr) * interval;
- if (errno) {
- rrd_set_error("converting '%s' to float: %s",
- updvals[ds_idx + 1], rrd_strerror(errno));
- return -1;
- };
- if (endptr[0] != '\0') {
- rrd_set_error
- ("conversion of '%s' to float not complete: tail '%s'",
- updvals[ds_idx + 1], endptr);
+ if( rrd_strtoding( updvals[ds_idx + 1], 0, &tmp ) == 2 ) {
+ pdp_new[ds_idx] = tmp * interval;
+ } else {
return -1;
}
rate = pdp_new[ds_idx] / interval;