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>
This commit is contained in:
parent
e12e0acb92
commit
adcabf3235
@ -1184,8 +1184,9 @@ enum {
|
|||||||
};
|
};
|
||||||
typedef struct parser_t {
|
typedef struct parser_t {
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
char *line;
|
|
||||||
char *data;
|
char *data;
|
||||||
|
char *line, *nline;
|
||||||
|
size_t line_alloc, nline_alloc;
|
||||||
int lineno;
|
int lineno;
|
||||||
} parser_t;
|
} parser_t;
|
||||||
parser_t* config_open(const char *filename) FAST_FUNC;
|
parser_t* config_open(const char *filename) FAST_FUNC;
|
||||||
|
@ -83,60 +83,55 @@ parser_t* FAST_FUNC config_open(const char *filename)
|
|||||||
return config_open2(filename, fopen_or_warn_stdin);
|
return config_open2(filename, fopen_or_warn_stdin);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void config_free_data(parser_t *parser)
|
|
||||||
{
|
|
||||||
free(parser->line);
|
|
||||||
parser->line = NULL;
|
|
||||||
if (PARSE_KEEP_COPY) { /* compile-time constant */
|
|
||||||
free(parser->data);
|
|
||||||
parser->data = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void FAST_FUNC config_close(parser_t *parser)
|
void FAST_FUNC config_close(parser_t *parser)
|
||||||
{
|
{
|
||||||
if (parser) {
|
if (parser) {
|
||||||
config_free_data(parser);
|
if (PARSE_KEEP_COPY) /* compile-time constant */
|
||||||
|
free(parser->data);
|
||||||
fclose(parser->fp);
|
fclose(parser->fp);
|
||||||
|
free(parser->line);
|
||||||
|
free(parser->nline);
|
||||||
free(parser);
|
free(parser);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This function reads an entire line from a text file, up to a newline
|
/* This function reads an entire line from a text file,
|
||||||
* or NUL byte, exclusive. It returns a malloc'ed char*.
|
* up to a newline, exclusive.
|
||||||
* *lineno is incremented for each line.
|
|
||||||
* Trailing '\' is recognized as line continuation.
|
* Trailing '\' is recognized as line continuation.
|
||||||
* Returns NULL if EOF/error.
|
* Returns -1 if EOF/error.
|
||||||
*/
|
*/
|
||||||
static char* get_line_with_continuation(FILE *file, int *lineno)
|
static int get_line_with_continuation(parser_t *parser)
|
||||||
{
|
{
|
||||||
int ch;
|
ssize_t len, nlen;
|
||||||
unsigned idx = 0;
|
char *line;
|
||||||
char *linebuf = NULL;
|
|
||||||
|
|
||||||
while ((ch = getc(file)) != EOF) {
|
len = getline(&parser->line, &parser->line_alloc, parser->fp);
|
||||||
/* grow the line buffer as necessary */
|
if (len <= 0)
|
||||||
if (!(idx & 0xff))
|
return len;
|
||||||
linebuf = xrealloc(linebuf, idx + 0x101);
|
|
||||||
if (ch == '\n')
|
line = parser->line;
|
||||||
ch = '\0';
|
for (;;) {
|
||||||
linebuf[idx] = (char) ch;
|
parser->lineno++;
|
||||||
if (ch == '\0') {
|
if (line[len - 1] == '\n')
|
||||||
(*lineno)++;
|
len--;
|
||||||
if (idx == 0 || linebuf[idx-1] != '\\')
|
if (len == 0 || line[len - 1] != '\\')
|
||||||
break;
|
break;
|
||||||
idx--; /* go back to '/' */
|
len--;
|
||||||
continue;
|
|
||||||
|
nlen = getline(&parser->nline, &parser->nline_alloc, parser->fp);
|
||||||
|
if (nlen <= 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (parser->line_alloc < len + nlen + 1) {
|
||||||
|
parser->line_alloc = len + nlen + 1;
|
||||||
|
line = parser->line = xrealloc(line, parser->line_alloc);
|
||||||
}
|
}
|
||||||
idx++;
|
memcpy(&line[len], parser->nline, nlen);
|
||||||
|
len += nlen;
|
||||||
}
|
}
|
||||||
if (ch == EOF) {
|
|
||||||
/* handle corner case when the file is not ended with '\n' */
|
line[len] = '\0';
|
||||||
(*lineno)++;
|
return len;
|
||||||
if (linebuf)
|
|
||||||
linebuf[idx] = '\0';
|
|
||||||
}
|
|
||||||
return linebuf;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -176,15 +171,14 @@ int FAST_FUNC config_read(parser_t *parser, char **tokens, unsigned flags, const
|
|||||||
ntokens = (uint8_t)flags;
|
ntokens = (uint8_t)flags;
|
||||||
mintokens = (uint8_t)(flags >> 8);
|
mintokens = (uint8_t)(flags >> 8);
|
||||||
|
|
||||||
again:
|
again:
|
||||||
memset(tokens, 0, sizeof(tokens[0]) * ntokens);
|
memset(tokens, 0, sizeof(tokens[0]) * ntokens);
|
||||||
config_free_data(parser);
|
|
||||||
|
|
||||||
/* Read one line (handling continuations with backslash) */
|
/* Read one line (handling continuations with backslash) */
|
||||||
line = get_line_with_continuation(parser->fp, &parser->lineno);
|
if (get_line_with_continuation(parser) < 0)
|
||||||
if (line == NULL)
|
|
||||||
return 0;
|
return 0;
|
||||||
parser->line = line;
|
|
||||||
|
line = parser->line;
|
||||||
|
|
||||||
/* Skip token in the start of line? */
|
/* Skip token in the start of line? */
|
||||||
if (flags & PARSE_TRIM)
|
if (flags & PARSE_TRIM)
|
||||||
@ -193,8 +187,10 @@ again:
|
|||||||
if (line[0] == '\0' || line[0] == delims[0])
|
if (line[0] == '\0' || line[0] == delims[0])
|
||||||
goto again;
|
goto again;
|
||||||
|
|
||||||
if (flags & PARSE_KEEP_COPY)
|
if (flags & PARSE_KEEP_COPY) {
|
||||||
|
free(parser->data);
|
||||||
parser->data = xstrdup(line);
|
parser->data = xstrdup(line);
|
||||||
|
}
|
||||||
|
|
||||||
/* Tokenize the line */
|
/* Tokenize the line */
|
||||||
t = 0;
|
t = 0;
|
||||||
@ -240,8 +236,6 @@ again:
|
|||||||
parser->lineno, t, mintokens);
|
parser->lineno, t, mintokens);
|
||||||
if (flags & PARSE_MIN_DIE)
|
if (flags & PARSE_MIN_DIE)
|
||||||
xfunc_die();
|
xfunc_die();
|
||||||
if (flags & PARSE_KEEP_COPY)
|
|
||||||
free(parser->data);
|
|
||||||
goto again;
|
goto again;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user