aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTimo Teras <timo.teras@iki.fi>2011-06-20 09:49:56 +0200
committerDenys Vlasenko <vda.linux@googlemail.com>2011-06-20 09:49:56 +0200
commitadcabf3235a13e77a32ff2a7b7cf80be8ee3dfe3 (patch)
tree5bb62bad050d86c1b711a19a1ea9e7ae525b9311
parente12e0acb92329f95a77121f489b491d84b6a2c33 (diff)
downloadbusybox-w32-adcabf3235a13e77a32ff2a7b7cf80be8ee3dfe3.tar.gz
busybox-w32-adcabf3235a13e77a32ff2a7b7cf80be8ee3dfe3.tar.bz2
busybox-w32-adcabf3235a13e77a32ff2a7b7cf80be8ee3dfe3.zip
parse_config: use getline. BIG speedup with glibc (~40%).
function old new delta config_read 559 604 +45 getline - 23 +23 config_close 29 49 +20 find_pair 169 187 +18 showmode 330 338 +8 hash_find 233 234 +1 builtin_umask 133 132 -1 lzo1x_optimize 1434 1429 -5 test_main 253 247 -6 buffer_fill_and_print 196 179 -17 create_J 1849 1826 -23 config_free_data 37 - -37 ------------------------------------------------------------------------------ (add/remove: 3/1 grow/shrink: 5/5 up/down: 138/-89) Total: 26 bytes Signed-off-by: Timo Teras <timo.teras@iki.fi> Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r--include/libbb.h3
-rw-r--r--libbb/parse_config.c92
2 files changed, 45 insertions, 50 deletions
diff --git a/include/libbb.h b/include/libbb.h
index 2cac7e60c..953bec334 100644
--- a/include/libbb.h
+++ b/include/libbb.h
@@ -1184,8 +1184,9 @@ enum {
1184}; 1184};
1185typedef struct parser_t { 1185typedef struct parser_t {
1186 FILE *fp; 1186 FILE *fp;
1187 char *line;
1188 char *data; 1187 char *data;
1188 char *line, *nline;
1189 size_t line_alloc, nline_alloc;
1189 int lineno; 1190 int lineno;
1190} parser_t; 1191} parser_t;
1191parser_t* config_open(const char *filename) FAST_FUNC; 1192parser_t* config_open(const char *filename) FAST_FUNC;
diff --git a/libbb/parse_config.c b/libbb/parse_config.c
index c0c34f312..cf5ba4deb 100644
--- a/libbb/parse_config.c
+++ b/libbb/parse_config.c
@@ -83,60 +83,55 @@ parser_t* FAST_FUNC config_open(const char *filename)
83 return config_open2(filename, fopen_or_warn_stdin); 83 return config_open2(filename, fopen_or_warn_stdin);
84} 84}
85 85
86static void config_free_data(parser_t *parser)
87{
88 free(parser->line);
89 parser->line = NULL;
90 if (PARSE_KEEP_COPY) { /* compile-time constant */
91 free(parser->data);
92 parser->data = NULL;
93 }
94}
95
96void FAST_FUNC config_close(parser_t *parser) 86void FAST_FUNC config_close(parser_t *parser)
97{ 87{
98 if (parser) { 88 if (parser) {
99 config_free_data(parser); 89 if (PARSE_KEEP_COPY) /* compile-time constant */
90 free(parser->data);
100 fclose(parser->fp); 91 fclose(parser->fp);
92 free(parser->line);
93 free(parser->nline);
101 free(parser); 94 free(parser);
102 } 95 }
103} 96}
104 97
105/* This function reads an entire line from a text file, up to a newline 98/* This function reads an entire line from a text file,
106 * or NUL byte, exclusive. It returns a malloc'ed char*. 99 * up to a newline, exclusive.
107 * *lineno is incremented for each line.
108 * Trailing '\' is recognized as line continuation. 100 * Trailing '\' is recognized as line continuation.
109 * Returns NULL if EOF/error. 101 * Returns -1 if EOF/error.
110 */ 102 */
111static char* get_line_with_continuation(FILE *file, int *lineno) 103static int get_line_with_continuation(parser_t *parser)
112{ 104{
113 int ch; 105 ssize_t len, nlen;
114 unsigned idx = 0; 106 char *line;
115 char *linebuf = NULL; 107
116 108 len = getline(&parser->line, &parser->line_alloc, parser->fp);
117 while ((ch = getc(file)) != EOF) { 109 if (len <= 0)
118 /* grow the line buffer as necessary */ 110 return len;
119 if (!(idx & 0xff)) 111
120 linebuf = xrealloc(linebuf, idx + 0x101); 112 line = parser->line;
121 if (ch == '\n') 113 for (;;) {
122 ch = '\0'; 114 parser->lineno++;
123 linebuf[idx] = (char) ch; 115 if (line[len - 1] == '\n')
124 if (ch == '\0') { 116 len--;
125 (*lineno)++; 117 if (len == 0 || line[len - 1] != '\\')
126 if (idx == 0 || linebuf[idx-1] != '\\') 118 break;
127 break; 119 len--;
128 idx--; /* go back to '/' */ 120
129 continue; 121 nlen = getline(&parser->nline, &parser->nline_alloc, parser->fp);
122 if (nlen <= 0)
123 break;
124
125 if (parser->line_alloc < len + nlen + 1) {
126 parser->line_alloc = len + nlen + 1;
127 line = parser->line = xrealloc(line, parser->line_alloc);
130 } 128 }
131 idx++; 129 memcpy(&line[len], parser->nline, nlen);
132 } 130 len += nlen;
133 if (ch == EOF) {
134 /* handle corner case when the file is not ended with '\n' */
135 (*lineno)++;
136 if (linebuf)
137 linebuf[idx] = '\0';
138 } 131 }
139 return linebuf; 132
133 line[len] = '\0';
134 return len;
140} 135}
141 136
142 137
@@ -176,15 +171,14 @@ int FAST_FUNC config_read(parser_t *parser, char **tokens, unsigned flags, const
176 ntokens = (uint8_t)flags; 171 ntokens = (uint8_t)flags;
177 mintokens = (uint8_t)(flags >> 8); 172 mintokens = (uint8_t)(flags >> 8);
178 173
179again: 174 again:
180 memset(tokens, 0, sizeof(tokens[0]) * ntokens); 175 memset(tokens, 0, sizeof(tokens[0]) * ntokens);
181 config_free_data(parser);
182 176
183 /* Read one line (handling continuations with backslash) */ 177 /* Read one line (handling continuations with backslash) */
184 line = get_line_with_continuation(parser->fp, &parser->lineno); 178 if (get_line_with_continuation(parser) < 0)
185 if (line == NULL)
186 return 0; 179 return 0;
187 parser->line = line; 180
181 line = parser->line;
188 182
189 /* Skip token in the start of line? */ 183 /* Skip token in the start of line? */
190 if (flags & PARSE_TRIM) 184 if (flags & PARSE_TRIM)
@@ -193,8 +187,10 @@ again:
193 if (line[0] == '\0' || line[0] == delims[0]) 187 if (line[0] == '\0' || line[0] == delims[0])
194 goto again; 188 goto again;
195 189
196 if (flags & PARSE_KEEP_COPY) 190 if (flags & PARSE_KEEP_COPY) {
191 free(parser->data);
197 parser->data = xstrdup(line); 192 parser->data = xstrdup(line);
193 }
198 194
199 /* Tokenize the line */ 195 /* Tokenize the line */
200 t = 0; 196 t = 0;
@@ -240,8 +236,6 @@ again:
240 parser->lineno, t, mintokens); 236 parser->lineno, t, mintokens);
241 if (flags & PARSE_MIN_DIE) 237 if (flags & PARSE_MIN_DIE)
242 xfunc_die(); 238 xfunc_die();
243 if (flags & PARSE_KEEP_COPY)
244 free(parser->data);
245 goto again; 239 goto again;
246 } 240 }
247 241