aboutsummaryrefslogtreecommitdiff
path: root/libbb/parse_config.c
diff options
context:
space:
mode:
authorDenis Vlasenko <vda.linux@googlemail.com>2008-08-09 17:16:40 +0000
committerDenis Vlasenko <vda.linux@googlemail.com>2008-08-09 17:16:40 +0000
commit69f4f9a6f40e2825c93fad4d3adf453c9b33d9bb (patch)
tree5e35a08d3b3db69b6dc212cbdf681d78bf4425ff /libbb/parse_config.c
parent3fd15e197e21aa313ce56126ee814f0ebc884dee (diff)
downloadbusybox-w32-69f4f9a6f40e2825c93fad4d3adf453c9b33d9bb.tar.gz
busybox-w32-69f4f9a6f40e2825c93fad4d3adf453c9b33d9bb.tar.bz2
busybox-w32-69f4f9a6f40e2825c93fad4d3adf453c9b33d9bb.zip
optimize config_read() (by Timo Teras <timo.teras AT iki.fi>)
function old new delta bb_get_chunk_with_continuation - 176 +176 find_pair 169 187 +18 ... process_stdin 443 433 -10 config_read 549 456 -93 bb_get_chunk_from_file 139 7 -132 ------------------------------------------------------------------------------ (add/remove: 1/0 grow/shrink: 7/7 up/down: 215/-254) Total: -39 bytes
Diffstat (limited to 'libbb/parse_config.c')
-rw-r--r--libbb/parse_config.c175
1 files changed, 67 insertions, 108 deletions
diff --git a/libbb/parse_config.c b/libbb/parse_config.c
index ace6f3ad3..a0599d4b4 100644
--- a/libbb/parse_config.c
+++ b/libbb/parse_config.c
@@ -123,137 +123,96 @@ mintokens > 0 make config_read() print error message if less than mintokens
123#undef config_read 123#undef config_read
124int FAST_FUNC config_read(parser_t *parser, char **tokens, unsigned flags, const char *delims) 124int FAST_FUNC config_read(parser_t *parser, char **tokens, unsigned flags, const char *delims)
125{ 125{
126 char *line, *q; 126 char *line;
127 char comment; 127 int ntokens, mintokens;
128 int ii; 128 int t, len;
129 int ntokens;
130 int mintokens;
131 129
132 comment = *delims++;
133 ntokens = flags & 0xFF; 130 ntokens = flags & 0xFF;
134 mintokens = (flags & 0xFF00) >> 8; 131 mintokens = (flags & 0xFF00) >> 8;
135 132
136 again: 133 if (parser == NULL)
137 memset(tokens, 0, sizeof(tokens[0]) * ntokens);
138 if (!parser)
139 return 0; 134 return 0;
135
136again:
137 memset(tokens, 0, sizeof(tokens[0]) * ntokens);
140 config_free_data(parser); 138 config_free_data(parser);
141 139
142 while (1) { 140 /* Read one line (handling continuations with backslash) */
143//TODO: speed up xmalloc_fgetline by internally using fgets, not fgetc 141 line = bb_get_chunk_with_continuation(parser->fp, &len, &parser->lineno);
144 line = xmalloc_fgetline(parser->fp); 142 if (line == NULL)
145 if (!line) 143 return 0;
146 return 0; 144 parser->line = line;
147 145
148 parser->lineno++; 146 /* Strip trailing line-feed if any */
149 // handle continuations. Tito's code stolen :) 147 if (len && line[len-1] == '\n')
150 while (1) { 148 line[len-1] = '\0';
151 ii = strlen(line);
152 if (!ii)
153 goto next_line;
154 if (line[ii - 1] != '\\')
155 break;
156 // multi-line object
157 line[--ii] = '\0';
158//TODO: add xmalloc_fgetline-like iface but with appending to existing str
159 q = xmalloc_fgetline(parser->fp);
160 if (!q)
161 break;
162 parser->lineno++;
163 line = xasprintf("%s%s", line, q);
164 free(q);
165 }
166 // discard comments
167 if (comment) {
168 q = strchrnul(line, comment);
169 *q = '\0';
170 ii = q - line;
171 }
172 // skip leading and trailing delimiters
173 if (flags & PARSE_TRIM) {
174 // skip leading
175 int n = strspn(line, delims);
176 if (n) {
177 ii -= n;
178 overlapping_strcpy(line, line + n);
179 }
180 // cut trailing
181 if (ii) {
182 while (strchr(delims, line[--ii]))
183 continue;
184 line[++ii] = '\0';
185 }
186 }
187 // if something still remains -> return it
188 if (ii)
189 break;
190 149
191 next_line: 150 /* Skip token in the start of line? */
192 // skip empty line 151 if (flags & PARSE_TRIM)
193 free(line); 152 line += strspn(line, delims + 1);
194 }
195 // non-empty line found, parse and return the number of tokens
196 153
197 // store line 154 if (line[0] == '\0' || line[0] == delims[0])
198 parser->line = line = xrealloc(line, ii + 1); 155 goto again;
199 if (flags & PARSE_KEEP_COPY) { 156
157 if (flags & PARSE_KEEP_COPY)
200 parser->data = xstrdup(line); 158 parser->data = xstrdup(line);
201 }
202 159
203 // split line to tokens 160 /* Tokenize the line */
204 ntokens--; // now it's max allowed token no 161 for (t = 0; *line && *line != delims[0] && t < ntokens; t++) {
205 // N.B. non-empty remainder is also a token, 162 /* Pin token */
206 // so if ntokens <= 1, we just return the whole line 163 tokens[t] = line;
207 // N.B. if PARSE_GREEDY is set the remainder of the line is stuck to the last token 164
208 ii = 0; 165 /* Combine remaining arguments? */
209 while (*line && ii <= ntokens) { 166 if ((t != (ntokens-1)) || !(flags & PARSE_GREEDY)) {
210 //bb_info_msg("L[%s]", line); 167 /* Vanilla token, find next delimiter */
211 // get next token 168 line += strcspn(line, delims[0] ? delims : delims + 1);
212 // at last token and need greedy token ->
213 if ((flags & PARSE_GREEDY) && (ii == ntokens)) {
214 // skip possible delimiters
215 if (flags & PARSE_COLLAPSE)
216 line += strspn(line, delims);
217 // don't cut the line
218 q = line + strlen(line);
219 } else { 169 } else {
220 // vanilla token. cut the line at the first delim 170 /* Combining, find comment char if any */
221 q = line + strcspn(line, delims); 171 line = strchrnul(line, delims[0]);
222 if (*q) // watch out: do not step past the line end! 172
223 *q++ = '\0'; 173 /* Trim any extra delimiters from the end */
174 if (flags & PARSE_TRIM) {
175 while (strchr(delims + 1, line[-1]) != NULL)
176 line--;
177 }
224 } 178 }
225 // pin token 179
226 if (!(flags & (PARSE_COLLAPSE | PARSE_TRIM)) || *line) { 180 /* Token not terminated? */
227 //bb_info_msg("N[%d] T[%s]", ii, line); 181 if (line[0] == delims[0])
228 tokens[ii++] = line; 182 *line = '\0';
229 // process escapes in token 183 else if (line[0] != '\0')
230#if 0 // unused so far 184 *(line++) = '\0';
231 if (flags & PARSE_ESCAPE) { 185
232 char *s = line; 186#if 0 /* unused so far */
233 while (*s) { 187 if (flags & PARSE_ESCAPE) {
234 if (*s == '\\') { 188 const char *from;
235 s++; 189 char *to;
236 *line++ = bb_process_escape_sequence((const char **)&s); 190
237 } else { 191 from = to = tokens[t];
238 *line++ = *s++; 192 while (*from) {
239 } 193 if (*from == '\\') {
194 from++;
195 *to++ = bb_process_escape_sequence(&from);
196 } else {
197 *to++ = *from++;
240 } 198 }
241 *line = '\0';
242 } 199 }
243#endif 200 *to = '\0';
244 } 201 }
245 line = q; 202#endif
246 //bb_info_msg("A[%s]", line); 203
204 /* Skip possible delimiters */
205 if (flags & PARSE_COLLAPSE)
206 line += strspn(line, delims + 1);
247 } 207 }
248 208
249 if (ii < mintokens) { 209 if (t < mintokens) {
250 bb_error_msg("bad line %u: %d tokens found, %d needed", 210 bb_error_msg("bad line %u: %d tokens found, %d needed",
251 parser->lineno, ii, mintokens); 211 parser->lineno, t, mintokens);
252 if (flags & PARSE_MIN_DIE) 212 if (flags & PARSE_MIN_DIE)
253 xfunc_die(); 213 xfunc_die();
254 ntokens++;
255 goto again; 214 goto again;
256 } 215 }
257 216
258 return ii; 217 return t;
259} 218}