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
This commit is contained in:
		@@ -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 <stdio.h>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include <ctype.h>
 | 
			
		||||
 | 
			
		||||
int buffer2array(char *origBuffer, char ***array)
 | 
			
		||||
 | 
			
		||||
inline static
 | 
			
		||||
int
 | 
			
		||||
isWhiteSpace(char c)
 | 
			
		||||
{
 | 
			
		||||
	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;
 | 
			
		||||
	return (c == ' ' || c == '\t');
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
	beginArray = xmalloc(sizeof(int) * count);
 | 
			
		||||
	(*array) = xmalloc(sizeof(char *) * count);
 | 
			
		||||
 | 
			
		||||
	count = 0;
 | 
			
		||||
 | 
			
		||||
	for (curr = 0; curr < bufferLength; curr++) {
 | 
			
		||||
		if (markArray[curr] == '1') {
 | 
			
		||||
			if (curr > 0) {
 | 
			
		||||
				if (markArray[curr - 1] == '0') {
 | 
			
		||||
					beginArray[count++] = curr;
 | 
			
		||||
				}
 | 
			
		||||
			} else {
 | 
			
		||||
				beginArray[count++] = curr;
 | 
			
		||||
			}
 | 
			
		||||
		} else {
 | 
			
		||||
			buffer[curr] = '\0';
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	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 buffer2array(char *buffer, char *array[], const int max)
 | 
			
		||||
{
 | 
			
		||||
	int i;
 | 
			
		||||
	int i = 0;
 | 
			
		||||
	char *c = buffer;
 | 
			
		||||
 | 
			
		||||
	if (argArrayLength == 0)
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < argArrayLength; i++) {
 | 
			
		||||
		free(array[i]);
 | 
			
		||||
	while (*c != '\0' && i < max) {
 | 
			
		||||
		if (*c == '\"') {
 | 
			
		||||
			array[i++] = ++c;
 | 
			
		||||
			while (*c != '\0') {
 | 
			
		||||
				if (*c == '\"') {
 | 
			
		||||
					*(c++) = '\0';
 | 
			
		||||
					break;
 | 
			
		||||
				} 
 | 
			
		||||
	free(array);
 | 
			
		||||
				else if (*(c++) == '\\' && *c != '\0') {
 | 
			
		||||
					memmove(c - 1, c, strlen(c) + 1);
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		} else {
 | 
			
		||||
			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;
 | 
			
		||||
	}
 | 
			
		||||
	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] );
 | 
			
		||||
 
 | 
			
		||||
@@ -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
 | 
			
		||||
 
 | 
			
		||||
@@ -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;
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										17
									
								
								src/conf.c
									
									
									
									
									
								
							
							
						
						
									
										17
									
								
								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);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user