]> git.tuebingen.mpg.de Git - paraslash.git/blobdiff - string.c
string: Replace the for_each_line_modes enum by a bitmap.
[paraslash.git] / string.c
index aa3bcbddabe425cc823e3ad5e567f707f70dbccb..d7e74d9dda16915d4bbe865d1f268dfa7d311963 100644 (file)
--- a/string.c
+++ b/string.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2004-2012 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2004-2013 Andre Noll <maan@systemlinux.org>
  *
  * 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;
 }
 
 /**