Merge branch 'collectd-4.6'
[collectd.git] / src / common.c
index 1af2f14..d42453e 100644 (file)
@@ -253,7 +253,7 @@ int strsplit (char *string, char **fields, size_t size)
                        break;
        }
 
-       return (i);
+       return ((int) i);
 }
 
 int strjoin (char *dst, size_t dst_len,
@@ -317,6 +317,40 @@ int strsubstitute (char *str, char c_from, char c_to)
        return (ret);
 } /* int strsubstitute */
 
+int strunescape (char *buf, size_t buf_len)
+{
+       size_t i;
+
+       for (i = 0; (i < buf_len) && (buf[i] != '\0'); ++i)
+       {
+               if (buf[i] != '\\')
+                       continue;
+
+               if ((i >= buf_len) || (buf[i + 1] == '\0')) {
+                       ERROR ("string unescape: backslash found at end of string.");
+                       return (-1);
+               }
+
+               switch (buf[i + 1]) {
+                       case 't':
+                               buf[i] = '\t';
+                               break;
+                       case 'n':
+                               buf[i] = '\n';
+                               break;
+                       case 'r':
+                               buf[i] = '\r';
+                               break;
+                       default:
+                               buf[i] = buf[i + 1];
+                               break;
+               }
+
+               memmove (buf + i + 1, buf + i + 2, buf_len - i - 2);
+       }
+       return (0);
+} /* int strunescape */
+
 int escape_slashes (char *buf, int buf_len)
 {
        int i;
@@ -349,6 +383,19 @@ int escape_slashes (char *buf, int buf_len)
        return (0);
 } /* int escape_slashes */
 
+void replace_special (char *buffer, size_t buffer_size)
+{
+       size_t i;
+
+       for (i = 0; i < buffer_size; i++)
+       {
+               if (buffer[i] == 0)
+                       return;
+               if ((!isalnum ((int) buffer[i])) && (buffer[i] != '-'))
+                       buffer[i] = '_';
+       }
+} /* void replace_special */
+
 int timeval_cmp (struct timeval tv0, struct timeval tv1, struct timeval *delta)
 {
        struct timeval *larger;
@@ -790,6 +837,30 @@ int parse_identifier (char *str, char **ret_host,
        return (0);
 } /* int parse_identifier */
 
+int parse_value (const char *value, value_t *ret_value, const data_source_t ds)
+{
+       char *endptr = NULL;
+
+       if (DS_TYPE_COUNTER == ds.type)
+               ret_value->counter = (counter_t)strtoll (value, &endptr, 0);
+       else if (DS_TYPE_GAUGE == ds.type)
+               ret_value->gauge = (gauge_t)strtod (value, &endptr);
+       else {
+               ERROR ("parse_value: Invalid data source \"%s\" "
+                               "(type = %i).", ds.name, ds.type);
+               return -1;
+       }
+
+       if (value == endptr) {
+               ERROR ("parse_value: Failed to parse string as number: %s.", value);
+               return -1;
+       }
+       else if ((NULL != endptr) && ('\0' != *endptr))
+               WARNING ("parse_value: Ignoring trailing garbage after number: %s.",
+                               endptr);
+       return 0;
+} /* int parse_value */
+
 int parse_values (char *buffer, value_list_t *vl, const data_set_t *ds)
 {
        int i;
@@ -816,12 +887,10 @@ int parse_values (char *buffer, value_list_t *vl, const data_set_t *ds)
                }
                else
                {
-                       if (strcmp ("U", ptr) == 0)
+                       if ((strcmp ("U", ptr) == 0) && (ds->ds[i].type == DS_TYPE_GAUGE))
                                vl->values[i].gauge = NAN;
-                       else if (ds->ds[i].type == DS_TYPE_COUNTER)
-                               vl->values[i].counter = atoll (ptr);
-                       else if (ds->ds[i].type == DS_TYPE_GAUGE)
-                               vl->values[i].gauge = atof (ptr);
+                       else if (0 != parse_value (ptr, &vl->values[i], ds->ds[i]))
+                               return -1;
                }
 
                i++;