From e19882660677baf8ba01c3006cf1a8ae5bee83ef Mon Sep 17 00:00:00 2001 From: Warren Dukes Date: Fri, 6 Oct 2006 10:33:27 +0000 Subject: put back np's supperrior buffer2array, and fix my bug fix from change 4872 git-svn-id: https://svn.musicpd.org/mpd/trunk@4875 09075e82-0dd4-0310-85a5-a0d7c8717e4f --- src/buffer2array.c | 142 ++++++++++++++++------------------------------------- src/buffer2array.h | 10 ++-- src/command.c | 22 ++++++--- src/conf.c | 17 +++---- 4 files changed, 69 insertions(+), 122 deletions(-) diff --git a/src/buffer2array.c b/src/buffer2array.c index ef08bc32a..fdcef790f 100644 --- a/src/buffer2array.c +++ b/src/buffer2array.c @@ -17,111 +17,53 @@ */ #include "buffer2array.h" -#ifdef UNIT_TEST -# define xstrdup(x) strdup(x) -# define xmalloc(x) malloc(x) -#else -# include "utils.h" -#endif #include #include #include +#include -int buffer2array(char *origBuffer, char ***array) -{ - int quotes = 0; - int count = 0; - int i; - int curr; - int *beginArray; - char *buffer = xstrdup(origBuffer); - int bufferLength = strlen(buffer); - char *markArray = xmalloc(sizeof(char) * (bufferLength + 1)); - - for (curr = 0; curr < bufferLength; curr++) { - if (!quotes && (buffer[curr] == ' ' || buffer[curr] == '\t')) { - markArray[curr] = '0'; - } else if (buffer[curr] == '\"') { - if (curr > 0 && buffer[curr - 1] != '\\') { - quotes = quotes ? 0 : 1; - markArray[curr] = '0'; - } else { - markArray[curr] = '1'; - } - } else { - markArray[curr] = '1'; - } - if (markArray[curr] == '1') { - if (curr > 0) { - if (markArray[curr - 1] == '0') { - count++; - } - } else { - count++; - } - } - } - markArray[bufferLength] = '\0'; - - if (!count) { - free(buffer); - free(markArray); - return count; - } - beginArray = xmalloc(sizeof(int) * count); - (*array) = xmalloc(sizeof(char *) * count); - - count = 0; +inline static +int +isWhiteSpace(char c) +{ + return (c == ' ' || c == '\t'); +} - for (curr = 0; curr < bufferLength; curr++) { - if (markArray[curr] == '1') { - if (curr > 0) { - if (markArray[curr - 1] == '0') { - beginArray[count++] = curr; +int buffer2array(char *buffer, char *array[], const int max) +{ + int i = 0; + char *c = buffer; + + while (*c != '\0' && i < max) { + if (*c == '\"') { + array[i++] = ++c; + while (*c != '\0') { + if (*c == '\"') { + *(c++) = '\0'; + break; + } + else if (*(c++) == '\\' && *c != '\0') { + memmove(c - 1, c, strlen(c) + 1); } - } else { - beginArray[count++] = curr; } } else { - buffer[curr] = '\0'; + while (isWhiteSpace(*c)) + ++c; + array[i++] = c++; + if (*c == '\0') + return i; + while (!isWhiteSpace(*c) && *c != '\0') + ++c; } + if (*c == '\0') + return i; + *(c++) = '\0'; + while (isWhiteSpace(*c)) + ++c; } - - for (i = 0; i < count; i++) { - int len = strlen(buffer + beginArray[i]) + 1; - int arrayCurr = 0; - (*array)[i] = xmalloc(sizeof(char) * len); - for (curr = beginArray[i]; buffer[curr] != '\0'; curr++) { - if (buffer[curr] == '\\') { - if (buffer[curr + 1] != '\0') { - curr++; - } - } - (*array)[i][arrayCurr++] = buffer[curr]; - } - (*array)[i][arrayCurr] = '\0'; - } - - free(markArray); - free(beginArray); - free(buffer); - - return count; -} - -void freeArgArray(char **array, int argArrayLength) -{ - int i; - - if (argArrayLength == 0) - return; - - for (i = 0; i < argArrayLength; i++) { - free(array[i]); - } - free(array); + return i; } #ifdef UNIT_TEST @@ -132,42 +74,42 @@ void freeArgArray(char **array, int argArrayLength) int main() { - char **a; + char *a[4] = { NULL }; char *b; int i, max; b = xstrdup("lsinfo \"/some/dir/name \\\"test\\\"\""); - max = buffer2array(b, &a); + max = buffer2array(b, a, 4); assert( !strcmp("lsinfo", a[0]) ); assert( !strcmp("/some/dir/name \"test\"", a[1]) ); assert( !a[2] ); b = xstrdup("lsinfo \"/some/dir/name \\\"test\\\" something else\""); - max = buffer2array(b, &a); + max = buffer2array(b, a, 4); assert( !strcmp("lsinfo", a[0]) ); assert( !strcmp("/some/dir/name \"test\" something else", a[1]) ); assert( !a[2] ); b = xstrdup("lsinfo \"/some/dir\\\\name\""); - max = buffer2array(b, &a); + max = buffer2array(b, a, 4); assert( !strcmp("lsinfo", a[0]) ); assert( !strcmp("/some/dir\\name", a[1]) ); assert( !a[2] ); b = xstrdup("lsinfo \"/some/dir name\""); - max = buffer2array(b, &a); + max = buffer2array(b, a, 4); assert( !strcmp("lsinfo", a[0]) ); assert( !strcmp("/some/dir name", a[1]) ); assert( !a[2] ); b = xstrdup("lsinfo \"\\\"/some/dir\\\"\""); - max = buffer2array(b, &a); + max = buffer2array(b, a, 4); assert( !strcmp("lsinfo", a[0]) ); assert( !strcmp("\"/some/dir\"", a[1]) ); assert( !a[2] ); b = xstrdup("lsinfo \"\\\"/some/dir\\\" x\""); - max = buffer2array(b, &a); + max = buffer2array(b, a, 4); assert( !strcmp("lsinfo", a[0]) ); assert( !strcmp("\"/some/dir\" x", a[1]) ); assert( !a[2] ); diff --git a/src/buffer2array.h b/src/buffer2array.h index fa6882fd9..e12f0ceed 100644 --- a/src/buffer2array.h +++ b/src/buffer2array.h @@ -21,8 +21,12 @@ #include "../config.h" -int buffer2array(char *buffer, char ***array); - -void freeArgArray(char **array, int argArrayLength); +/* tokenizes up to max elements in buffer (a null-terminated string) and + * stores the result in array (which must be capable of holding up to + * max elements). Tokenization is based on C string quoting rules. + * The arguments buffer and array are modified. + * Returns the number of elements tokenized. + */ +int buffer2array(char *buffer, char *array[], const int max); #endif diff --git a/src/command.c b/src/command.c index 41fdbd716..f1b98a9f3 100644 --- a/src/command.c +++ b/src/command.c @@ -108,6 +108,13 @@ #define COMMAND_STATUS_AUDIO "audio" #define COMMAND_STATUS_UPDATING_DB "updating_db" +/* + * The most we ever use is for search/find, and that limits it to the + * number of tags we can have. Add one for the command, and one extra + * to catch errors clients may send us + */ +#define COMMAND_ARGV_MAX (2+(TAG_NUM_OF_ITEM_TYPES*2)) + typedef struct _CommandEntry CommandEntry; typedef int (*CommandHandlerFunction) (int, int *, int, char **); @@ -1052,27 +1059,28 @@ static CommandEntry *getCommandEntryAndCheckArgcAndPermission(int fd, static CommandEntry *getCommandEntryFromString(char *string, int *permission) { CommandEntry *cmd = NULL; - char **argv; - int argc = buffer2array(string, &argv); + char *argv[COMMAND_ARGV_MAX] = { NULL }; + int argc = buffer2array(string, argv, COMMAND_ARGV_MAX); if (0 == argc) return NULL; cmd = getCommandEntryAndCheckArgcAndPermission(0, permission, argc, argv); - freeArgArray(argv, argc); return cmd; } static int processCommandInternal(int fd, int *permission, - char *string, struct strnode *cmdnode) + char *commandString, struct strnode *cmdnode) { - char **argv; - int argc = buffer2array(string, &argv); + int argc; + char *argv[COMMAND_ARGV_MAX] = { NULL }; CommandEntry *cmd; int ret = -1; + argc = buffer2array(commandString, argv, COMMAND_ARGV_MAX); + if (argc == 0) return 0; @@ -1086,8 +1094,6 @@ static int processCommandInternal(int fd, int *permission, } } - freeArgArray(argv, argc); - current_command = NULL; return ret; diff --git a/src/conf.c b/src/conf.c index dc45ed2b9..0b3e0df5f 100644 --- a/src/conf.c +++ b/src/conf.c @@ -41,6 +41,7 @@ #define CONF_REPEATABLE_MASK 0x01 #define CONF_BLOCK_MASK 0x02 +#define CONF_LINE_TOKEN_MAX 3 typedef struct _configEntry { unsigned char mask; @@ -193,15 +194,16 @@ static ConfigParam *readConfigBlock(FILE * fp, int *count, char *string) { ConfigParam *ret = newConfigParam(NULL, *count); - char **array; int i; int numberOfArgs; int argsMinusComment; while (myFgets(string, MAX_STRING_SIZE, fp)) { + char *array[CONF_LINE_TOKEN_MAX] = { NULL }; + (*count)++; - numberOfArgs = buffer2array(string, &array); + numberOfArgs = buffer2array(string, array, CONF_LINE_TOKEN_MAX); for (i = 0; i < numberOfArgs; i++) { if (array[i][0] == CONF_COMMENT) @@ -211,13 +213,11 @@ static ConfigParam *readConfigBlock(FILE * fp, int *count, char *string) argsMinusComment = i; if (0 == argsMinusComment) { - freeArgArray(array, numberOfArgs); continue; } if (1 == argsMinusComment && 0 == strcmp(array[0], CONF_BLOCK_END)) { - freeArgArray(array, numberOfArgs); break; } @@ -238,8 +238,6 @@ static ConfigParam *readConfigBlock(FILE * fp, int *count, char *string) } addBlockParam(ret, array[0], array[1], *count); - - freeArgArray(array, numberOfArgs); } return ret; @@ -256,7 +254,6 @@ void readConf(char *file) ConfigEntry *entry; void *voidPtr; ConfigParam *param; - char **array; if (!(fp = fopen(file, "r"))) { ERROR("problems opening file %s for reading: %s\n", file, @@ -265,9 +262,10 @@ void readConf(char *file) } while (myFgets(string, MAX_STRING_SIZE, fp)) { + char *array[CONF_LINE_TOKEN_MAX] = { NULL }; count++; - numberOfArgs = buffer2array(string, &array); + numberOfArgs = buffer2array(string, array, CONF_LINE_TOKEN_MAX); for (i = 0; i < numberOfArgs; i++) { if (array[i][0] == CONF_COMMENT) @@ -277,7 +275,6 @@ void readConf(char *file) argsMinusComment = i; if (0 == argsMinusComment) { - freeArgArray(array, numberOfArgs); continue; } @@ -316,8 +313,6 @@ void readConf(char *file) param = newConfigParam(array[1], count); insertInListWithoutKey(entry->configParamList, param); - - freeArgArray(array, numberOfArgs); } fclose(fp); } -- cgit v1.2.3