Code

b4d50a580cdbbb4e5db910c455f5fc8bf0344372
[collectd.git] / src / utils_match.c
1 /**
2  * collectd - src/utils_match.c
3  * Copyright (C) 2008  Florian octo Forster
4  *
5  * This program is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License as published by the
7  * Free Software Foundation; either version 2 of the License, or (at your
8  * option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License along
16  * with this program; if not, write to the Free Software Foundation, Inc.,
17  * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
18  *
19  * Authors:
20  *   Florian octo Forster <octo at verplant.org>
21  **/
23 #include "collectd.h"
24 #include "common.h"
25 #include "plugin.h"
27 #include "utils_match.h"
29 #include <regex.h>
31 #define UTILS_MATCH_FLAGS_FREE_USER_DATA 0x01
33 struct cu_match_s
34 {
35   regex_t regex;
36   int flags;
38   int (*callback) (const char *str, void *user_data);
39   void *user_data;
40 };
42 /*
43  * Private functions
44  */
45 static int default_callback (const char *str, void *user_data)
46 {
47   cu_match_value_t *data = (cu_match_value_t *) user_data;
49   if (data->ds_type == UTILS_MATCH_DS_TYPE_GAUGE)
50   {
51     gauge_t value;
52     char *endptr = NULL;
54     value = strtod (str, &endptr);
55     if (str == endptr)
56       return (-1);
58     data->value.gauge = value;
59   }
60   else if ((data->ds_type == UTILS_MATCH_DS_TYPE_COUNTER_SET)
61       || (data->ds_type == UTILS_MATCH_DS_TYPE_COUNTER_ADD))
62   {
63     counter_t value;
64     char *endptr = NULL;
66     value = strtoll (str, &endptr, 0);
67     if (str == endptr)
68       return (-1);
70     if (data->ds_type == UTILS_MATCH_DS_TYPE_COUNTER_SET)
71       data->value.counter = value;
72     else
73       data->value.counter += value;
74   }
75   else if (data->ds_type == UTILS_MATCH_DS_TYPE_COUNTER_INC)
76   {
77     data->value.counter++;
78   }
79   else
80   {
81     return (-1);
82   }
84   return (0);
85 } /* int default_callback */
87 /*
88  * Public functions
89  */
90 cu_match_t *match_create_callback (const char *regex,
91                 int (*callback) (const char *str, void *user_data),
92                 void *user_data)
93 {
94   cu_match_t *obj;
95   int status;
97   obj = (cu_match_t *) malloc (sizeof (cu_match_t));
98   if (obj == NULL)
99     return (NULL);
100   memset (obj, '\0', sizeof (cu_match_t));
102   status = regcomp (&obj->regex, regex, REG_EXTENDED);
103   if (status != 0)
104   {
105     ERROR ("Compiling the regular expression \"%s\" failed.", regex);
106     sfree (obj);
107     return (NULL);
108   }
110   obj->callback = callback;
111   obj->user_data = user_data;
113   return (obj);
114 } /* cu_match_t *match_create_callback */
116 cu_match_t *match_create_simple (const char *regex, int match_ds_type)
118   cu_match_value_t *user_data;
119   cu_match_t *obj;
121   user_data = (cu_match_value_t *) malloc (sizeof (cu_match_value_t));
122   if (user_data == NULL)
123     return (NULL);
124   memset (user_data, '\0', sizeof (cu_match_value_t));
126   obj = match_create_callback (regex, default_callback, user_data);
127   if (obj == NULL)
128   {
129     sfree (user_data);
130     return (NULL);
131   }
133   obj->flags |= UTILS_MATCH_FLAGS_FREE_USER_DATA;
135   return (obj);
136 } /* cu_match_t *match_create_simple */
138 void match_destroy (cu_match_t *obj)
140   if (obj == NULL)
141     return;
143   if (obj->flags & UTILS_MATCH_FLAGS_FREE_USER_DATA)
144   {
145     sfree (obj->user_data);
146   }
148   sfree (obj);
149 } /* void match_destroy */
151 int match_apply (cu_match_t *obj, const char *str)
153   int status;
154   regmatch_t re_match;
155   char *sub_match;
156   size_t sub_match_len;
158   if ((obj == NULL) || (str == NULL))
159     return (-1);
161   re_match.rm_so = -1;
162   re_match.rm_eo = -1;
164   status = regexec (&obj->regex, str, /* nmatch = */ 1, &re_match,
165       /* eflags = */ 0);
167   /* Regex did not match */
168   if (status != 0)
169     return (0);
171   if (re_match.rm_so < 0)
172   {
173     status = obj->callback (str, obj->user_data);
174     return (status);
175   }
177   assert (re_match.rm_so < re_match.rm_eo);
178   sub_match_len = (size_t) (re_match.rm_eo - re_match.rm_so);
179   sub_match = (char *) malloc (sizeof (char) * (sub_match_len + 1));
180   if (sub_match == NULL)
181   {
182     ERROR ("malloc failed.");
183     return (-1);
184   }
185   sstrncpy (sub_match, str + re_match.rm_so, sub_match_len + 1);
187   status = obj->callback (sub_match, obj->user_data);
189   sfree (sub_match);
191   return (status);
192 } /* int match_apply */
194 void *match_get_user_data (cu_match_t *obj)
196   if (obj == NULL)
197     return (NULL);
198   return (obj->user_data);
199 } /* void *match_get_user_data */
201 /* vim: set sw=2 sts=2 ts=8 : */