src/utils_search.c: Add folding markers.
[collection4.git] / src / utils_search.c
1 /**
2  * collection4 - utils_search.c
3  * Copyright (C) 2010  Florian octo Forster
4  * 
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2.1 of the License, or (at your option) any later version.
9  * 
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  * 
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor,
18  * Boston, MA  02110-1301  USA
19  *
20  * Authors:
21  *   Florian octo Forster <ff at octo.it>
22  **/
23
24 #include <stdlib.h>
25 #include <stdio.h>
26 #include <string.h>
27 #include <ctype.h>
28 #include <errno.h>
29
30 #include "utils_search.h"
31 #include "utils_array.h"
32
33 #include <fcgiapp.h>
34 #include <fcgi_stdio.h>
35
36 struct search_info_s
37 {
38   char *host;
39   char *plugin;
40   char *plugin_instance;
41   char *type;
42   char *type_instance;
43
44   str_array_t *terms;
45 };
46
47 /*
48  * Private functions
49  */
50 static char *read_quoted_string (const char **buffer) /* {{{ */
51 {
52   const char *ptr = *buffer;
53   char *ret;
54   size_t ret_len;
55
56   if (ptr[0] != '"')
57     return (NULL);
58   ptr++;
59
60   ret_len = 0;
61   while ((*ptr != '"') && (*ptr != 0))
62   {
63     ret_len++;
64
65     if (*ptr == '\\')
66       ptr += 2;
67     else
68       ptr++;
69   }
70
71   if ((ret_len < 1) || (*ptr != '"'))
72     return (NULL);
73
74   ret = malloc (ret_len + 1);
75   if (ret == NULL)
76     return (NULL);
77
78   ptr = *buffer + 1;
79   ret_len = 0;
80   while ((*ptr != '"') && (*ptr != 0))
81   {
82     if (*ptr == '"')
83       break;
84
85     if (*ptr == '\\')
86       ptr++;
87
88     ret[ret_len] = *ptr;
89
90     ptr++;
91     ret_len++;
92   }
93
94   /* terminate string */
95   ret[ret_len] = 0;
96
97   /* "ptr" points to the '"' sign, so advance one more */
98   ptr++;
99   *buffer = ptr;
100
101   return (ret);
102 } /* }}} char *read_quoted_string */
103
104 static char *read_unquoted_word (const char **buffer) /* {{{ */
105 {
106   const char *ptr = *buffer;
107   char *ret;
108   size_t ret_len;
109
110   ret_len = 0;
111   while (!isspace ((int) ptr[ret_len]) && (ptr[ret_len] != 0))
112     ret_len++;
113
114   if (ret_len < 1)
115     return (NULL);
116
117   ret = malloc (ret_len + 1);
118   if (ret == NULL)
119     return (NULL);
120
121   memcpy (ret, ptr, ret_len);
122   ret[ret_len] = 0;
123
124   ptr += ret_len;
125   *buffer = ptr;
126
127   return (ret);
128 } /* }}} char *read_unquoted_word */
129
130 static char *next_token (const char **buffer) /* {{{ */
131 {
132   const char *ptr = *buffer;
133   char *ret;
134
135   while (isspace ((int) (*ptr)))
136     ptr++;
137
138   if (ptr[0] == 0)
139     return (NULL);
140   else if (ptr[0] == '"')
141   {
142     ret = read_quoted_string (&ptr);
143     if (ret != NULL)
144     {
145       *buffer = ptr;
146       return (ret);
147     }
148   }
149
150   ret = read_unquoted_word (&ptr);
151   if (ret != NULL)
152     *buffer = ptr;
153
154   return (ret);
155 } /* }}} char *next_token */
156
157 static int store_token_field (char **field, const char *token) /* {{{ */
158 {
159   char *copy;
160
161   if ((field == NULL) || (token == NULL))
162     return (EINVAL);
163
164   copy = strdup (token);
165   if (copy == NULL)
166     return (ENOMEM);
167
168   free (*field);
169   *field = copy;
170
171   return (0);
172 } /* }}} int store_token_field */
173
174 static int store_token (search_info_t *si, const char *token) /* {{{ */
175 {
176   if (strncmp ("host:", token, strlen ("host:")) == 0)
177     return (store_token_field (&si->host, token + strlen ("host:")));
178   else if (strncmp ("plugin:", token, strlen ("plugin:")) == 0)
179     return (store_token_field (&si->plugin, token + strlen ("plugin:")));
180   else if (strncmp ("plugin_instance:", token, strlen ("plugin_instance:")) == 0)
181     return (store_token_field (&si->plugin_instance, token + strlen ("plugin_instance:")));
182   else if (strncmp ("type:", token, strlen ("type:")) == 0)
183     return (store_token_field (&si->type, token + strlen ("type:")));
184   else if (strncmp ("type_instance:", token, strlen ("type_instance:")) == 0)
185     return (store_token_field (&si->type_instance, token + strlen ("type_instance:")));
186
187   return (array_append (si->terms, token));
188 } /* }}} int store_token */
189
190 /*
191  * Public functions
192  */
193 search_info_t *search_parse (const char *search) /* {{{ */
194 {
195   const char *ptr;
196   char *token;
197   search_info_t *si;
198
199   si = malloc (sizeof (*si));
200   if (si == NULL)
201     return (NULL);
202   memset (si, 0, sizeof (*si));
203
204   si->terms = array_create ();
205   if (si->terms == NULL)
206   {
207     free (si);
208     return (NULL);
209   }
210
211   ptr = search;
212
213   while ((token = next_token (&ptr)) != NULL)
214   {
215     store_token (si, token);
216     free (token);
217   }
218
219   return (si);
220 } /* }}} search_info_t *search_parse */
221
222 void search_destroy (search_info_t *si) /* {{{ */
223 {
224   if (si == NULL)
225     return;
226
227   free (si->host);
228   free (si->plugin);
229   free (si->plugin_instance);
230   free (si->type);
231   free (si->type_instance);
232
233   array_destroy (si->terms);
234 } /* }}} void search_destroy */
235
236 /* vim: set sw=2 sts=2 et fdm=marker : */