34eb340a564577691f121bac613921e71812c3c2
[strongswan.git] / src / libstrongswan / utils / lexparser.c
1 /*
2 * Copyright (C) 2001-2006 Andreas Steffen
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the
6 * Free Software Foundation; either version 2 of the License, or (at your
7 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
11 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * for more details.
13 *
14 * $Id$
15 */
16
17 /* memrchr is a GNU extension */
18 #define _GNU_SOURCE
19 #include <string.h>
20
21 #include "lexparser.h"
22
23
24 /**
25 * eat whitespace
26 */
27 bool eat_whitespace(chunk_t *src)
28 {
29 while (src->len > 0 && (*src->ptr == ' ' || *src->ptr == '\t'))
30 {
31 src->ptr++; src->len--;
32 }
33 return src->len > 0 && *src->ptr != '#';
34 }
35
36 /**
37 * compare string with chunk
38 */
39 bool match(const char *pattern, const chunk_t *ch)
40 {
41 return ch->len == strlen(pattern) && strncmp(pattern, ch->ptr, ch->len) == 0;
42 }
43
44 /**
45 * extracts a token ending with the first occurrence of a given termination symbol
46 */
47 bool extract_token(chunk_t *token, const char termination, chunk_t *src)
48 {
49 u_char *eot = memchr(src->ptr, termination, src->len);
50
51 if (termination == ' ')
52 {
53 u_char *eot_tab = memchr(src->ptr, '\t', src->len);
54
55 /* check if a tab instead of a space terminates the token */
56 eot = ( eot_tab == NULL || (eot && eot < eot_tab) ) ? eot : eot_tab;
57 }
58
59 /* initialize empty token */
60 *token = chunk_empty;
61
62 if (eot == NULL) /* termination symbol not found */
63 {
64 return FALSE;
65 }
66
67 /* extract token */
68 token->ptr = src->ptr;
69 token->len = (u_int)(eot - src->ptr);
70
71 /* advance src pointer after termination symbol */
72 src->ptr = eot + 1;
73 src->len -= (token->len + 1);
74
75 return TRUE;
76 }
77
78 /**
79 * extracts a token ending with the first occurrence of a given null-terminated string
80 */
81 bool extract_token_str(chunk_t *token, const char *termination, chunk_t *src)
82 {
83 u_char *eot = memstr(src->ptr, termination, src->len);
84 size_t l = strlen(termination);
85
86 /* initialize empty token */
87 *token = chunk_empty;
88
89 if (eot == NULL) /* termination string not found */
90 {
91 return FALSE;
92 }
93
94 /* extract token */
95 token->ptr = src->ptr;
96 token->len = (u_int)(eot - src->ptr);
97
98 /* advance src pointer after termination string */
99 src->ptr = eot + l;
100 src->len -= (token->len + l);
101
102 return TRUE;
103 }
104
105 /**
106 * extracts a token ending with the last occurrence of a given termination symbol
107 */
108 bool extract_last_token(chunk_t *token, const char termination, chunk_t *src)
109 {
110 u_char *eot = memrchr(src->ptr, termination, src->len);
111
112 /* initialize empty token */
113 *token = chunk_empty;
114
115 if (eot == NULL) /* termination symbol not found */
116 {
117 return FALSE;
118 }
119
120 /* extract token */
121 token->ptr = src->ptr;
122 token->len = (u_int)(eot - src->ptr);
123
124 /* advance src pointer after termination symbol */
125 src->ptr = eot + 1;
126 src->len -= (token->len + 1);
127
128 return TRUE;
129 }
130
131 /**
132 * fetches a new line terminated by \n or \r\n
133 */
134 bool fetchline(chunk_t *src, chunk_t *line)
135 {
136 if (src->len == 0) /* end of src reached */
137 return FALSE;
138
139 if (extract_token(line, '\n', src))
140 {
141 if (line->len > 0 && *(line->ptr + line->len -1) == '\r')
142 line->len--; /* remove optional \r */
143 }
144 else /*last line ends without newline */
145 {
146 *line = *src;
147 src->ptr += src->len;
148 src->len = 0;
149 }
150 return TRUE;
151 }
152
153 err_t extract_value(chunk_t *value, chunk_t *line)
154 {
155 char delimiter = ' ';
156
157 if (!eat_whitespace(line))
158 {
159 *value = chunk_empty;
160 return NULL;
161 }
162 if (*line->ptr == '\'' || *line->ptr == '"')
163 {
164 delimiter = *line->ptr;
165 line->ptr++; line->len--;
166 }
167 if (!extract_token(value, delimiter, line))
168 {
169 if (delimiter == ' ')
170 {
171 *value = *line;
172 line->len = 0;
173 }
174 else
175 {
176 return "missing second delimiter";
177 }
178 }
179 return NULL;
180 }
181
182 /**
183 * extracts a parameter: value pair
184 */
185 err_t extract_parameter_value(chunk_t *name, chunk_t *value, chunk_t *line)
186 {
187 /* extract name */
188 if (!extract_token(name,':', line))
189 {
190 return "missing ':'";
191 }
192
193 /* extract value */
194 return extract_value(value, line);
195 }