diff options
author | Timo Teras <timo.teras@iki.fi> | 2011-06-20 09:49:56 +0200 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2011-06-20 09:49:56 +0200 |
commit | adcabf3235a13e77a32ff2a7b7cf80be8ee3dfe3 (patch) | |
tree | 5bb62bad050d86c1b711a19a1ea9e7ae525b9311 | |
parent | e12e0acb92329f95a77121f489b491d84b6a2c33 (diff) | |
download | busybox-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.h | 3 | ||||
-rw-r--r-- | libbb/parse_config.c | 92 |
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 | }; |
1185 | typedef struct parser_t { | 1185 | typedef 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; |
1191 | parser_t* config_open(const char *filename) FAST_FUNC; | 1192 | parser_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 | ||
86 | static 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 | |||
96 | void FAST_FUNC config_close(parser_t *parser) | 86 | void 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 | */ |
111 | static char* get_line_with_continuation(FILE *file, int *lineno) | 103 | static 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 | ||
179 | again: | 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 | ||