Clean up string parser

Clean up string parser routines.
This commit is contained in:
Takashi Iwai 2005-08-18 14:53:39 +00:00
parent f1acd7726c
commit e120114bde

View file

@ -671,29 +671,75 @@ static int get_quotedchar(input_t *input)
} }
} }
#define LOCAL_STR_BUFSIZE 64
struct local_string {
char *buf;
size_t alloc;
size_t idx;
char tmpbuf[LOCAL_STR_BUFSIZE];
};
static void init_local_string(struct local_string *s)
{
memset(s, 0, sizeof(*s));
s->buf = s->tmpbuf;
s->alloc = LOCAL_STR_BUFSIZE;
}
static void free_local_string(struct local_string *s)
{
if (s->buf != s->tmpbuf)
free(s->buf);
}
static int add_char_local_string(struct local_string *s, int c)
{
if (s->idx >= s->alloc) {
size_t nalloc = s->alloc * 2;
if (s->buf == s->tmpbuf) {
s->buf = malloc(nalloc);
if (s->buf == NULL)
return -ENOMEM;
memcpy(s->buf, s->tmpbuf, s->alloc);
} else {
char *ptr = realloc(s->buf, nalloc);
if (ptr == NULL)
return -ENOMEM;
s->buf = ptr;
}
s->alloc = nalloc;
}
s->buf[s->idx++] = c;
return 0;
}
static char *copy_local_string(struct local_string *s)
{
char *dst = malloc(s->idx + 1);
if (dst) {
memcpy(dst, s->buf, s->idx);
dst[s->idx] = '\0';
}
return dst;
}
static int get_freestring(char **string, int id, input_t *input) static int get_freestring(char **string, int id, input_t *input)
{ {
const size_t bufsize = 64; struct local_string str;
char _buf[bufsize];
char *buf = _buf;
size_t alloc = bufsize;
size_t idx = 0;
int c; int c;
init_local_string(&str);
while (1) { while (1) {
c = get_char(input); c = get_char(input);
if (c < 0) { if (c < 0) {
if (c == LOCAL_UNEXPECTED_EOF) { if (c == LOCAL_UNEXPECTED_EOF) {
char *s = malloc(idx + 1); *string = copy_local_string(&str);
if (!s) if (! *string)
return -ENOMEM; c = -ENOMEM;
memcpy(s, buf, idx); else
s[idx] = '\0'; c = 0;
*string = s;
c = 0;
} }
if (alloc > bufsize) break;
free(buf);
return c;
} }
switch (c) { switch (c) {
case '.': case '.':
@ -715,95 +761,58 @@ static int get_freestring(char **string, int id, input_t *input)
case '"': case '"':
case '\\': case '\\':
case '#': case '#':
{ *string = copy_local_string(&str);
char *s = malloc(idx + 1); if (! *string)
if (!s) c = -ENOMEM;
return -ENOMEM; else {
unget_char(c, input); unget_char(c, input);
memcpy(s, buf, idx); c = 0;
s[idx] = '\0'; }
*string = s; goto _out;
if (alloc > bufsize)
free(buf);
return 0;
}
default: default:
break; break;
} }
if (idx >= alloc) { if (add_char_local_string(&str, c) < 0) {
size_t old_alloc = alloc; c = -ENOMEM;
alloc *= 2; break;
if (old_alloc == bufsize) {
buf = malloc(alloc);
if (buf == NULL)
return -ENOMEM;
memcpy(buf, _buf, old_alloc);
} else {
char *ptr = realloc(buf, alloc);
if (ptr == NULL) {
free(buf);
return -ENOMEM;
}
buf = ptr;
}
} }
buf[idx++] = c;
} }
return 0; _out:
free_local_string(&str);
return c;
} }
static int get_delimstring(char **string, int delim, input_t *input) static int get_delimstring(char **string, int delim, input_t *input)
{ {
const size_t bufsize = 64; struct local_string str;
char _buf[bufsize];
char *buf = _buf;
size_t alloc = bufsize;
size_t idx = 0;
int c; int c;
init_local_string(&str);
while (1) { while (1) {
c = get_char(input); c = get_char(input);
if (c < 0) if (c < 0)
return c; break;
switch (c) { if (c == '\\') {
case '\\':
c = get_quotedchar(input); c = get_quotedchar(input);
if (c < 0) if (c < 0)
return c; break;
if (c == '\n') if (c == '\n')
continue; continue;
} else if (c == delim) {
*string = copy_local_string(&str);
if (! *string)
c = -ENOMEM;
else
c = 0;
break; break;
default:
if (c == delim) {
char *s = malloc(idx + 1);
if (!s)
return -ENOMEM;
memcpy(s, buf, idx);
s[idx] = '\0';
*string = s;
if (alloc > bufsize)
free(buf);
return 0;
}
} }
if (idx >= alloc) { if (add_char_local_string(&str, c) < 0) {
size_t old_alloc = alloc; c = -ENOMEM;
alloc *= 2; break;
if (old_alloc == bufsize) {
buf = malloc(alloc);
if (buf == NULL)
return -ENOMEM;
memcpy(buf, _buf, old_alloc);
} else {
char *ptr = realloc(buf, alloc);
if (ptr == NULL) {
free(buf);
return -ENOMEM;
}
buf = ptr;
}
} }
buf[idx++] = c;
} }
free_local_string(&str);
return c;
} }
/* Return 0 for free string, 1 for delimited string */ /* Return 0 for free string, 1 for delimited string */
@ -978,14 +987,14 @@ static int parse_array_defs(snd_config_t *farther, input_t *input, int skip, int
static int parse_array_def(snd_config_t *father, input_t *input, int idx, int skip, int override) static int parse_array_def(snd_config_t *father, input_t *input, int idx, int skip, int override)
{ {
char static_id[12], *id = NULL; char *id = NULL;
int c; int c;
int err; int err;
snd_config_t *n = NULL; snd_config_t *n = NULL;
if (!skip) { if (!skip) {
char static_id[12];
snprintf(static_id, sizeof(static_id), "%i", idx); snprintf(static_id, sizeof(static_id), "%i", idx);
static_id[sizeof(static_id)-1] = '\0';
id = strdup(static_id); id = strdup(static_id);
if (id == NULL) if (id == NULL)
return -ENOMEM; return -ENOMEM;