X-Git-Url: http://git.tuebingen.mpg.de/?a=blobdiff_plain;f=string.c;h=d7e74d9dda16915d4bbe865d1f268dfa7d311963;hb=6256ed835dc5ced1fb4c75ed91fb4e68fbf436fd;hp=aa3bcbddabe425cc823e3ad5e567f707f70dbccb;hpb=6101e63b98b5517b65bd967e6efbb0af47738084;p=paraslash.git diff --git a/string.c b/string.c index aa3bcbdd..d7e74d9d 100644 --- a/string.c +++ b/string.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2012 Andre Noll + * Copyright (C) 2004-2013 Andre Noll * * Licensed under the GPL v2. For licencing details see COPYING. */ @@ -350,18 +350,16 @@ __malloc char *para_hostname(void) } /** - * Used to distinguish between read-only and read-write mode. + * Controls behavior of for_each_complete_line(). * * \sa for_each_line(), for_each_line_ro(). */ -enum for_each_line_modes{ +enum for_each_line_flags { /** Activate read-only mode. */ - LINE_MODE_RO, - /** Activate read-write mode. */ - LINE_MODE_RW + FELF_READ_ONLY = 1 << 0, }; -static int for_each_complete_line(enum for_each_line_modes mode, char *buf, +static int for_each_complete_line(unsigned flags, char *buf, size_t size, line_handler_t *line_handler, void *private_data) { char *start = buf, *end; @@ -387,7 +385,7 @@ static int for_each_complete_line(enum for_each_line_modes mode, char *buf, start = ++end; continue; } - if (mode == LINE_MODE_RO) { + if (flags & FELF_READ_ONLY) { size_t s = end - start; char *b = para_malloc(s + 1); memcpy(b, start, s); @@ -403,7 +401,7 @@ static int for_each_complete_line(enum for_each_line_modes mode, char *buf, return ret; start = ++end; } - if (!line_handler || mode == LINE_MODE_RO) + if (!line_handler || (flags & FELF_READ_ONLY)) return num_lines; i = buf + size - start; if (i && i != size) @@ -436,8 +434,7 @@ static int for_each_complete_line(enum for_each_line_modes mode, char *buf, int for_each_line(char *buf, size_t size, line_handler_t *line_handler, void *private_data) { - return for_each_complete_line(LINE_MODE_RW, buf, size, line_handler, - private_data); + return for_each_complete_line(0, buf, size, line_handler, private_data); } /** @@ -458,7 +455,7 @@ int for_each_line(char *buf, size_t size, line_handler_t *line_handler, int for_each_line_ro(char *buf, size_t size, line_handler_t *line_handler, void *private_data) { - return for_each_complete_line(LINE_MODE_RO, buf, size, line_handler, + return for_each_complete_line(FELF_READ_ONLY, buf, size, line_handler, private_data); } @@ -800,7 +797,7 @@ int compute_word_num(const char *buf, const char *delim, int point) } /** - * Free an array of words created by create_argv(). + * Free an array of words created by create_argv() or create_shifted_argv(). * * \param argv A pointer previously obtained by \ref create_argv(). */ @@ -815,6 +812,35 @@ void free_argv(char **argv) free(argv); } +static int create_argv_offset(int offset, const char *buf, const char *delim, + char ***result) +{ + char *word, **argv = para_malloc((offset + 1) * sizeof(char *)); + const char *p; + int i, ret; + + for (i = 0; i < offset; i++) + argv[i] = NULL; + for (p = buf; p && *p; p += ret, i++) { + ret = get_next_word(p, delim, &word); + if (ret < 0) + goto err; + if (!ret) + break; + argv = para_realloc(argv, (i + 2) * sizeof(char*)); + argv[i] = word; + } + argv[i] = NULL; + *result = argv; + return i; +err: + while (i > 0) + free(argv[--i]); + free(argv); + *result = NULL; + return ret; +} + /** * Split a buffer into words. * @@ -831,28 +857,47 @@ void free_argv(char **argv) */ int create_argv(const char *buf, const char *delim, char ***result) { - char *word, **argv = para_malloc(2 * sizeof(char *)); - const char *p; - int ret, num_words; + return create_argv_offset(0, buf, delim, result); +} - for (p = buf, num_words = 0; ; p += ret, num_words++) { - ret = get_next_word(p, delim, &word); - if (ret < 0) - goto err; - if (!ret) - break; - argv = para_realloc(argv, (num_words + 2) * sizeof(char*)); - argv[num_words] = word; - } - argv[num_words] = NULL; - *result = argv; - return num_words; -err: - while (num_words > 0) - free(argv[--num_words]); - free(argv); - *result = NULL; - return ret; +/** + * Split a buffer into words, offset one. + * + * This is similar to \ref create_argv() but the returned array is one element + * larger, words start at index one and element zero is initialized to \p NULL. + * Callers must set element zero to a non-NULL value before calling free_argv() + * on the returned array to avoid a memory leak. + * + * \param buf See \ref create_argv(). + * \param delim See \ref create_argv(). + * \param result See \ref create_argv(). + * + * \return Number of words plus one on success, negative on errors. + */ +int create_shifted_argv(const char *buf, const char *delim, char ***result) +{ + return create_argv_offset(1, buf, delim, result); +} + +/** + * Find out if the given string is contained in the arg vector. + * + * \param arg The string to look for. + * \param argv The array to search. + * + * \return The first index whose value equals \a arg, or \p -E_ARG_NOT_FOUND if + * arg was not found in \a argv. + */ +int find_arg(const char *arg, char **argv) +{ + int i; + + if (!argv) + return -E_ARG_NOT_FOUND; + for (i = 0; argv[i]; i++) + if (strcmp(arg, argv[i]) == 0) + return i; + return -E_ARG_NOT_FOUND; } /**