diff --git a/src/utils_match.c b/src/utils_match.c
index 23bedb1b9fd442fab4b0021ea5ae7e90cfe6468e..bdbad3f213155a544b8d06009aa90c7322e7522c 100644 (file)
--- a/src/utils_match.c
+++ b/src/utils_match.c
regex_t regex;
int flags;
- int (*callback) (const char *str, void *user_data);
+ int (*callback) (const char *str, char * const *matches, size_t matches_num,
+ void *user_data);
void *user_data;
};
/*
* Private functions
*/
-static int default_callback (const char *str, void *user_data)
+static char *match_substr (const char *str, int begin, int end)
+{
+ char *ret;
+ size_t ret_len;
+
+ if ((begin < 0) || (end < 0) || (begin >= end))
+ return (NULL);
+ if ((size_t) end > (strlen (str) + 1))
+ {
+ ERROR ("utils_match: match_substr: `end' points after end of string.");
+ return (NULL);
+ }
+
+ ret_len = end - begin;
+ ret = (char *) malloc (sizeof (char) * (ret_len + 1));
+ if (ret == NULL)
+ {
+ ERROR ("utils_match: match_substr: malloc failed.");
+ return (NULL);
+ }
+
+ sstrncpy (ret, str + begin, ret_len + 1);
+ return (ret);
+} /* char *match_substr */
+
+static int default_callback (const char __attribute__((unused)) *str,
+ char * const *matches, size_t matches_num, void *user_data)
{
cu_match_value_t *data = (cu_match_value_t *) user_data;
- if (data->ds_type == UTILS_MATCH_DS_TYPE_GAUGE)
+ if (data->ds_type & UTILS_MATCH_DS_TYPE_GAUGE)
{
gauge_t value;
char *endptr = NULL;
- value = strtod (str, &endptr);
- if (str == endptr)
+ if (matches_num < 2)
+ return (-1);
+
+ value = strtod (matches[1], &endptr);
+ if (matches[1] == endptr)
return (-1);
- data->value.gauge = value;
+ if ((data->values_num == 0)
+ || (data->ds_type & UTILS_MATCH_CF_GAUGE_LAST))
+ {
+ data->value.gauge = value;
+ }
+ else if (data->ds_type & UTILS_MATCH_CF_GAUGE_AVERAGE)
+ {
+ double f = ((double) data->values_num)
+ / ((double) (data->values_num + 1));
+ data->value.gauge = (data->value.gauge * f) + (value * (1.0 - f));
+ }
+ else if (data->ds_type & UTILS_MATCH_CF_GAUGE_MIN)
+ {
+ if (data->value.gauge > value)
+ data->value.gauge = value;
+ }
+ else if (data->ds_type & UTILS_MATCH_CF_GAUGE_MAX)
+ {
+ if (data->value.gauge < value)
+ data->value.gauge = value;
+ }
+ else
+ {
+ ERROR ("utils_match: default_callback: obj->ds_type is invalid!");
+ return (-1);
+ }
+
+ data->values_num++;
}
- else if ((data->ds_type == UTILS_MATCH_DS_TYPE_COUNTER_SET)
- || (data->ds_type == UTILS_MATCH_DS_TYPE_COUNTER_ADD))
+ else if (data->ds_type & UTILS_MATCH_DS_TYPE_COUNTER)
{
counter_t value;
char *endptr = NULL;
- value = strtoll (str, &endptr, 0);
- if (str == endptr)
+ if (data->ds_type & UTILS_MATCH_CF_COUNTER_INC)
+ {
+ data->value.counter++;
+ data->values_num++;
+ return (0);
+ }
+
+ if (matches_num < 2)
return (-1);
- if (data->ds_type == UTILS_MATCH_DS_TYPE_COUNTER_SET)
+ value = strtoll (matches[1], &endptr, 0);
+ if (matches[1] == endptr)
+ return (-1);
+
+ if (data->ds_type & UTILS_MATCH_CF_COUNTER_SET)
data->value.counter = value;
- else
+ else if (data->ds_type & UTILS_MATCH_CF_COUNTER_ADD)
data->value.counter += value;
+ else
+ {
+ ERROR ("utils_match: default_callback: obj->ds_type is invalid!");
+ return (-1);
+ }
+
+ data->values_num++;
}
- else if (data->ds_type == UTILS_MATCH_DS_TYPE_COUNTER_INC)
+ else if (data->ds_type & UTILS_MATCH_DS_TYPE_DERIVE)
{
- data->value.counter++;
+ derive_t value;
+ char *endptr = NULL;
+
+ if (data->ds_type & UTILS_MATCH_CF_DERIVE_INC)
+ {
+ data->value.counter++;
+ data->values_num++;
+ return (0);
+ }
+
+ if (matches_num < 2)
+ return (-1);
+
+ value = strtoll (matches[1], &endptr, 0);
+ if (matches[1] == endptr)
+ return (-1);
+
+ if (data->ds_type & UTILS_MATCH_CF_DERIVE_SET)
+ data->value.derive = value;
+ else if (data->ds_type & UTILS_MATCH_CF_DERIVE_ADD)
+ data->value.derive += value;
+ else
+ {
+ ERROR ("utils_match: default_callback: obj->ds_type is invalid!");
+ return (-1);
+ }
+
+ data->values_num++;
+ }
+ else if (data->ds_type & UTILS_MATCH_DS_TYPE_ABSOLUTE)
+ {
+ absolute_t value;
+ char *endptr = NULL;
+
+ if (matches_num < 2)
+ return (-1);
+
+ value = strtoll (matches[1], &endptr, 0);
+ if (matches[1] == endptr)
+ return (-1);
+
+ if (data->ds_type & UTILS_MATCH_CF_ABSOLUTE_SET)
+ data->value.absolute = value;
+ else
+ {
+ ERROR ("utils_match: default_callback: obj->ds_type is invalid!");
+ return (-1);
+ }
+
+ data->values_num++;
}
else
{
+ ERROR ("utils_match: default_callback: obj->ds_type is invalid!");
return (-1);
}
* Public functions
*/
cu_match_t *match_create_callback (const char *regex,
- int (*callback) (const char *str, void *user_data),
+ int (*callback) (const char *str,
+ char * const *matches, size_t matches_num, void *user_data),
void *user_data)
{
cu_match_t *obj;
int status;
+ DEBUG ("utils_match: match_create_callback: regex = %s", regex);
+
obj = (cu_match_t *) malloc (sizeof (cu_match_t));
if (obj == NULL)
return (NULL);
return (obj);
} /* cu_match_t *match_create_callback */
-cu_match_t *match_create_default (const char *regex, int match_ds_type)
+cu_match_t *match_create_simple (const char *regex, int match_ds_type)
{
cu_match_value_t *user_data;
cu_match_t *obj;
if (user_data == NULL)
return (NULL);
memset (user_data, '\0', sizeof (cu_match_value_t));
+ user_data->ds_type = match_ds_type;
obj = match_create_callback (regex, default_callback, user_data);
if (obj == NULL)
obj->flags |= UTILS_MATCH_FLAGS_FREE_USER_DATA;
return (obj);
-} /* cu_match_t *match_create_default */
+} /* cu_match_t *match_create_simple */
void match_destroy (cu_match_t *obj)
{
int match_apply (cu_match_t *obj, const char *str)
{
int status;
- regmatch_t re_match;
- char *sub_match;
- size_t sub_match_len;
+ regmatch_t re_match[32];
+ char *matches[32];
+ size_t matches_num;
+ size_t i;
if ((obj == NULL) || (str == NULL))
return (-1);
- re_match.rm_so = -1;
- re_match.rm_eo = -1;
-
- status = regexec (&obj->regex, str, /* nmatch = */ 1, &re_match,
+ status = regexec (&obj->regex, str,
+ STATIC_ARRAY_SIZE (re_match), re_match,
/* eflags = */ 0);
/* Regex did not match */
if (status != 0)
return (0);
- if (re_match.rm_so < 0)
+ memset (matches, '\0', sizeof (matches));
+ for (matches_num = 0; matches_num < STATIC_ARRAY_SIZE (matches); matches_num++)
{
- status = obj->callback (str, obj->user_data);
- return (status);
+ if ((re_match[matches_num].rm_so < 0)
+ || (re_match[matches_num].rm_eo < 0))
+ break;
+
+ matches[matches_num] = match_substr (str,
+ re_match[matches_num].rm_so, re_match[matches_num].rm_eo);
+ if (matches[matches_num] == NULL)
+ {
+ status = -1;
+ break;
+ }
}
- assert (re_match.rm_so < re_match.rm_eo);
- sub_match_len = (size_t) (re_match.rm_eo - re_match.rm_so);
- sub_match = (char *) malloc (sizeof (char) * (sub_match_len + 1));
- if (sub_match == NULL)
+ if (status != 0)
{
- ERROR ("malloc failed.");
- return (-1);
+ ERROR ("utils_match: match_apply: match_substr failed.");
+ }
+ else
+ {
+ status = obj->callback (str, matches, matches_num, obj->user_data);
+ if (status != 0)
+ {
+ ERROR ("utils_match: match_apply: callback failed.");
+ }
}
- sstrncpy (sub_match, str + re_match.rm_so, sub_match_len + 1);
-
- status = obj->callback (sub_match, obj->user_data);
- sfree (sub_match);
+ for (i = 0; i < matches_num; i++)
+ {
+ sfree (matches[i]);
+ }
return (status);
} /* int match_apply */