src/utils_search.c: Implement parsing of the tokens.
[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 static char *read_quoted_string (const char **buffer) /* {{{ */
48 {
49   const char *ptr = *buffer;
50   char *ret;
51   size_t ret_len;
52
53   if (ptr[0] != '"')
54     return (NULL);
55   ptr++;
56
57   ret_len = 0;
58   while ((*ptr != '"') && (*ptr != 0))
59   {
60     ret_len++;
61
62     if (*ptr == '\\')
63       ptr += 2;
64     else
65       ptr++;
66   }
67
68   if ((ret_len < 1) || (*ptr != '"'))
69     return (NULL);
70
71   ret = malloc (ret_len + 1);
72   if (ret == NULL)
73     return (NULL);
74
75   ptr = *buffer + 1;
76   ret_len = 0;
77   while ((*ptr != '"') && (*ptr != 0))
78   {
79     if (*ptr == '"')
80       break;
81
82     if (*ptr == '\\')
83       ptr++;
84
85     ret[ret_len] = *ptr;
86
87     ptr++;
88     ret_len++;
89   }
90
91   /* terminate string */
92   ret[ret_len] = 0;
93
94   /* "ptr" points to the '"' sign, so advance one more */
95   ptr++;
96   *buffer = ptr;
97
98   return (ret);
99 } /* }}} char *read_quoted_string */
100
101 static char *read_unquoted_word (const char **buffer) /* {{{ */
102 {
103   const char *ptr = *buffer;
104   char *ret;
105   size_t ret_len;
106
107   ret_len = 0;
108   while (!isspace ((int) ptr[ret_len]) && (ptr[ret_len] != 0))
109     ret_len++;
110
111   if (ret_len < 1)
112     return (NULL);
113
114   ret = malloc (ret_len + 1);
115   if (ret == NULL)
116     return (NULL);
117
118   memcpy (ret, ptr, ret_len);
119   ret[ret_len] = 0;
120
121   ptr += ret_len;
122   *buffer = ptr;
123
124   return (ret);
125 } /* }}} char *read_unquoted_word */
126
127 static char *next_token (const char **buffer) /* {{{ */
128 {
129   const char *ptr = *buffer;
130   char *ret;
131
132   while (isspace ((int) (*ptr)))
133     ptr++;
134
135   if (ptr[0] == 0)
136     return (NULL);
137   else if (ptr[0] == '"')
138   {
139     ret = read_quoted_string (&ptr);
140     if (ret != NULL)
141     {
142       *buffer = ptr;
143       return (ret);
144     }
145   }
146
147   ret = read_unquoted_word (&ptr);
148   if (ret != NULL)
149     *buffer = ptr;
150
151   return (ret);
152 } /* }}} char *next_token */
153
154 static int store_token_field (char **field, const char *token)
155 {
156   char *copy;
157
158   if ((field == NULL) || (token == NULL))
159     return (EINVAL);
160
161   copy = strdup (token);
162   if (copy == NULL)
163     return (ENOMEM);
164
165   free (*field);
166   *field = copy;
167
168   return (0);
169 } /* }}} int store_token_field */
170
171 static int store_token (search_info_t *si, const char *token)
172 {
173   if (strncmp ("host:", token, strlen ("host:")) == 0)
174     return (store_token_field (&si->host, token + strlen ("host:")));
175   else if (strncmp ("plugin:", token, strlen ("plugin:")) == 0)
176     return (store_token_field (&si->plugin, token + strlen ("plugin:")));
177   else if (strncmp ("plugin_instance:", token, strlen ("plugin_instance:")) == 0)
178     return (store_token_field (&si->plugin_instance, token + strlen ("plugin_instance:")));
179   else if (strncmp ("type:", token, strlen ("type:")) == 0)
180     return (store_token_field (&si->type, token + strlen ("type:")));
181   else if (strncmp ("type_instance:", token, strlen ("type_instance:")) == 0)
182     return (store_token_field (&si->type_instance, token + strlen ("type_instance:")));
183
184   return (array_append (si->terms, token));
185 } /* }}} int store_token */
186
187 search_info_t *search_parse (const char *search) /* {{{ */
188 {
189   const char *ptr;
190   char *token;
191   search_info_t *si;
192
193   si = malloc (sizeof (*si));
194   if (si == NULL)
195     return (NULL);
196   memset (si, 0, sizeof (*si));
197
198   si->terms = array_create ();
199   if (si->terms == NULL)
200   {
201     free (si);
202     return (NULL);
203   }
204
205   ptr = search;
206
207   while ((token = next_token (&ptr)) != NULL)
208   {
209     store_token (si, token);
210     free (token);
211   }
212
213   return (si);
214 } /* }}} search_info_t *search_parse */
215
216 void search_destroy (search_info_t *si) /* {{{ */
217 {
218   if (si == NULL)
219     return;
220
221   free (si->host);
222   free (si->plugin);
223   free (si->plugin_instance);
224   free (si->type);
225   free (si->type_instance);
226
227   array_destroy (si->terms);
228 } /* }}} void search_destroy */
229
230 /* vim: set sw=2 sts=2 et fdm=marker : */