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