|
@@ -1,5 +1,5 @@
|
|
|
/** @file vec.c
|
|
|
- *
|
|
|
+ * Implementation of variable length vector of arbitrary structures.
|
|
|
*/
|
|
|
|
|
|
|
|
@@ -10,195 +10,171 @@
|
|
|
#include <stdio.h>
|
|
|
|
|
|
#include "private.h"
|
|
|
-#include "faux/str.h"
|
|
|
|
|
|
-#if 0
|
|
|
-/*--------------------------------------------------------- */
|
|
|
-static void lub_argv_init(lub_argv_t * this, const char *line, size_t off)
|
|
|
-{
|
|
|
- size_t len = 0;
|
|
|
- const char *word = NULL;
|
|
|
- lub_arg_t *arg = NULL;
|
|
|
- bool_t quoted = BOOL_FALSE;
|
|
|
- bool_t alt_quoted = BOOL_FALSE;
|
|
|
- const char *str = line + off; // Start on specified offset
|
|
|
- const char *offset = NULL;
|
|
|
-
|
|
|
- this->argv = NULL;
|
|
|
- this->argc = 0;
|
|
|
- if (!line)
|
|
|
- return;
|
|
|
- /* first of all count the words in the line */
|
|
|
- this->argc = lub_string_wordcount(line);
|
|
|
- if (0 == this->argc)
|
|
|
- return;
|
|
|
- /* allocate space to hold the vector */
|
|
|
- arg = this->argv = malloc(sizeof(lub_arg_t) * this->argc);
|
|
|
- assert(arg);
|
|
|
-
|
|
|
- /* then fill out the array with the words */
|
|
|
- for (word = lub_string_nextword(str, &len, &offset, "ed, NULL, &alt_quoted);
|
|
|
- word && (*word != '\0');
|
|
|
- word = lub_string_nextword(str, &len, &offset, "ed, NULL, &alt_quoted)) {
|
|
|
- if (alt_quoted)
|
|
|
- (*arg).arg = lub_string_dupn(word, len);
|
|
|
- else
|
|
|
- (*arg).arg = lub_string_ndecode(word, len);
|
|
|
- (*arg).offset = offset - line;
|
|
|
- (*arg).quoted = quoted;
|
|
|
- str = offset;
|
|
|
- arg++;
|
|
|
- }
|
|
|
-}
|
|
|
|
|
|
-/*--------------------------------------------------------- */
|
|
|
-lub_argv_t *lub_argv_new(const char *line, size_t offset)
|
|
|
+faux_vec_t *faux_vec_new(size_t item_size, faux_vec_kcmp_fn matchFn)
|
|
|
{
|
|
|
- lub_argv_t *this;
|
|
|
+ faux_vec_t *faux_vec = NULL;
|
|
|
|
|
|
- this = malloc(sizeof(lub_argv_t));
|
|
|
- if (this)
|
|
|
- lub_argv_init(this, line, offset);
|
|
|
+ faux_vec = faux_zmalloc(sizeof(*faux_vec));
|
|
|
+ assert(faux_vec);
|
|
|
+ if (!faux_vec)
|
|
|
+ return NULL;
|
|
|
+
|
|
|
+ // Init
|
|
|
+ faux_vec->data = NULL;
|
|
|
+ faux_vec->item_size = item_size;
|
|
|
+ faux_vec->len = 0;
|
|
|
+ faux_vec->kcmpFn = matchFn;
|
|
|
|
|
|
- return this;
|
|
|
+ return faux_vec;
|
|
|
}
|
|
|
|
|
|
-/*--------------------------------------------------------- */
|
|
|
-void lub_argv_add(lub_argv_t * this, const char *text)
|
|
|
-{
|
|
|
- lub_arg_t * arg;
|
|
|
|
|
|
- if (!text)
|
|
|
+void faux_vec_free(faux_vec_t *faux_vec)
|
|
|
+{
|
|
|
+ if (!faux_vec)
|
|
|
return;
|
|
|
-
|
|
|
- /* allocate space to hold the vector */
|
|
|
- arg = realloc(this->argv, sizeof(lub_arg_t) * (this->argc + 1));
|
|
|
- assert(arg);
|
|
|
- this->argv = arg;
|
|
|
- (this->argv[this->argc++]).arg = strdup(text);
|
|
|
+ faux_free(faux_vec->data);
|
|
|
+ faux_free(faux_vec);
|
|
|
}
|
|
|
|
|
|
-/*--------------------------------------------------------- */
|
|
|
-static void lub_argv_fini(lub_argv_t * this)
|
|
|
+
|
|
|
+size_t faux_vec_len(const faux_vec_t *faux_vec)
|
|
|
{
|
|
|
- unsigned i;
|
|
|
+ assert(faux_vec);
|
|
|
+ if (!faux_vec)
|
|
|
+ return 0;
|
|
|
|
|
|
- for (i = 0; i < this->argc; i++)
|
|
|
- free(this->argv[i].arg);
|
|
|
- free(this->argv);
|
|
|
- this->argv = NULL;
|
|
|
+ return faux_vec->len;
|
|
|
}
|
|
|
|
|
|
-/*--------------------------------------------------------- */
|
|
|
-void lub_argv_delete(lub_argv_t * this)
|
|
|
-{
|
|
|
- lub_argv_fini(this);
|
|
|
- free(this);
|
|
|
-}
|
|
|
|
|
|
-/*--------------------------------------------------------- */
|
|
|
-char *lub_argv__get_line(const lub_argv_t * this)
|
|
|
+size_t faux_vec_item_size(const faux_vec_t *faux_vec)
|
|
|
{
|
|
|
- int space = 0;
|
|
|
- const char *p;
|
|
|
- unsigned i;
|
|
|
- char *line = NULL;
|
|
|
-
|
|
|
- for (i = 0; i < this->argc; i++) {
|
|
|
- if (i != 0)
|
|
|
- lub_string_cat(&line, " ");
|
|
|
- space = 0;
|
|
|
- /* Search for spaces */
|
|
|
- for (p = this->argv[i].arg; *p; p++) {
|
|
|
- if (isspace(*p)) {
|
|
|
- space = 1;
|
|
|
- break;
|
|
|
- }
|
|
|
- }
|
|
|
- if (space)
|
|
|
- lub_string_cat(&line, "\"");
|
|
|
- lub_string_cat(&line, this->argv[i].arg);
|
|
|
- if (space)
|
|
|
- lub_string_cat(&line, "\"");
|
|
|
- }
|
|
|
+ assert(faux_vec);
|
|
|
+ if (!faux_vec)
|
|
|
+ return 0;
|
|
|
|
|
|
- return line;
|
|
|
+ return faux_vec->item_size;
|
|
|
}
|
|
|
|
|
|
-/*--------------------------------------------------------- */
|
|
|
-char **lub_argv__get_argv(const lub_argv_t * this, const char *argv0)
|
|
|
-{
|
|
|
- char **result = NULL;
|
|
|
- unsigned i;
|
|
|
- unsigned a = 0;
|
|
|
-
|
|
|
- if (argv0)
|
|
|
- a = 1;
|
|
|
|
|
|
- result = malloc(sizeof(char *) * (this->argc + 1 + a));
|
|
|
+void *faux_vec_item(const faux_vec_t *faux_vec, unsigned int index)
|
|
|
+{
|
|
|
+ assert(faux_vec);
|
|
|
+ if (!faux_vec)
|
|
|
+ return NULL;
|
|
|
|
|
|
- if (argv0)
|
|
|
- result[0] = strdup(argv0);
|
|
|
- for (i = 0; i < this->argc; i++)
|
|
|
- result[i + a] = strdup(this->argv[i].arg);
|
|
|
- result[i + a] = NULL;
|
|
|
+ if ((index + 1) > faux_vec_len(faux_vec))
|
|
|
+ return NULL;
|
|
|
|
|
|
- return result;
|
|
|
+ return (char *)faux_vec->data + index * faux_vec_item_size(faux_vec);
|
|
|
}
|
|
|
|
|
|
-/*--------------------------------------------------------- */
|
|
|
-void lub_argv__free_argv(char **argv)
|
|
|
-{
|
|
|
- unsigned i;
|
|
|
|
|
|
- if (!argv)
|
|
|
- return;
|
|
|
+void *faux_vec_data(const faux_vec_t *faux_vec)
|
|
|
+{
|
|
|
+ assert(faux_vec);
|
|
|
+ if (!faux_vec)
|
|
|
+ return NULL;
|
|
|
|
|
|
- for (i = 0; argv[i]; i++)
|
|
|
- free(argv[i]);
|
|
|
- free(argv);
|
|
|
+ return faux_vec->data;
|
|
|
}
|
|
|
|
|
|
-/*--------------------------------------------------------- */
|
|
|
-const char *lub_argv__get_arg(const lub_argv_t *this, unsigned int index)
|
|
|
+
|
|
|
+void *faux_vec_add(faux_vec_t *faux_vec)
|
|
|
{
|
|
|
- const char *result = NULL;
|
|
|
+ void *new_vector = NULL;
|
|
|
+ size_t new_data_len = 0;
|
|
|
|
|
|
- if (!this)
|
|
|
+ assert(faux_vec);
|
|
|
+ if (!faux_vec)
|
|
|
return NULL;
|
|
|
- if (this->argc > index)
|
|
|
- result = this->argv[index].arg;
|
|
|
|
|
|
- return result;
|
|
|
-}
|
|
|
+ // Allocate space to hold new vector
|
|
|
+ new_data_len = (faux_vec_len(faux_vec) + 1) * faux_vec_item_size(faux_vec);
|
|
|
+ new_vector = realloc(faux_vec->data, new_data_len);
|
|
|
+ assert(new_vector);
|
|
|
+ if (!new_vector)
|
|
|
+ return NULL;
|
|
|
+ faux_vec->len++;
|
|
|
+ faux_vec->data = new_vector;
|
|
|
|
|
|
-/*--------------------------------------------------------- */
|
|
|
-unsigned lub_argv__get_count(const lub_argv_t * this)
|
|
|
-{
|
|
|
- return this->argc;
|
|
|
+ // Return newly created item (it's last one)
|
|
|
+ return faux_vec_item(faux_vec, faux_vec_len(faux_vec) - 1);
|
|
|
}
|
|
|
|
|
|
-/*--------------------------------------------------------- */
|
|
|
-size_t lub_argv__get_offset(const lub_argv_t * this, unsigned index)
|
|
|
+
|
|
|
+ssize_t faux_vec_del(faux_vec_t *faux_vec, unsigned int index)
|
|
|
{
|
|
|
- size_t result = 0;
|
|
|
+ void *new_vector = NULL;
|
|
|
+ size_t new_data_len = 0;
|
|
|
+
|
|
|
+ assert(faux_vec);
|
|
|
+ if (!faux_vec)
|
|
|
+ return -1;
|
|
|
+
|
|
|
+ if ((index + 1) > faux_vec_len(faux_vec))
|
|
|
+ return -1;
|
|
|
+
|
|
|
+ // Move following items to fill the space of deleted item
|
|
|
+ if (index != (faux_vec_len(faux_vec) - 1)) { // Is it last item?
|
|
|
+ void *item_to_del = faux_vec_item(faux_vec, index);
|
|
|
+ void *next_item = faux_vec_item(faux_vec, index + 1);
|
|
|
+ unsigned int items_to_move =
|
|
|
+ faux_vec_len(faux_vec) - (index + 1);
|
|
|
+ memmove(item_to_del, next_item,
|
|
|
+ items_to_move * faux_vec_item_size(faux_vec));
|
|
|
+ }
|
|
|
|
|
|
- if (this->argc > index)
|
|
|
- result = this->argv[index].offset;
|
|
|
+ // Re-allocate space to hold new vector
|
|
|
+ faux_vec->len--;
|
|
|
+ new_data_len = faux_vec_len(faux_vec) * faux_vec_item_size(faux_vec);
|
|
|
+ new_vector = realloc(faux_vec->data, new_data_len);
|
|
|
+ assert(new_vector);
|
|
|
+ if (!new_vector)
|
|
|
+ return -1;
|
|
|
+ faux_vec->data = new_vector;
|
|
|
|
|
|
- return result;
|
|
|
+ return faux_vec_len(faux_vec);
|
|
|
}
|
|
|
|
|
|
-/*--------------------------------------------------------- */
|
|
|
-bool_t lub_argv__get_quoted(const lub_argv_t * this, unsigned index)
|
|
|
-{
|
|
|
- bool_t result = BOOL_FALSE;
|
|
|
|
|
|
- if (this->argc > index)
|
|
|
- result = this->argv[index].quoted;
|
|
|
+int faux_vec_find_fn(const faux_vec_t *faux_vec, faux_vec_kcmp_fn matchFn,
|
|
|
+ const void *userkey, unsigned int start_index)
|
|
|
+{
|
|
|
+ unsigned int i = 0;
|
|
|
+
|
|
|
+ assert(faux_vec);
|
|
|
+ if (!faux_vec)
|
|
|
+ return -1;
|
|
|
+ assert(userkey);
|
|
|
+ if (!userkey)
|
|
|
+ return -1;
|
|
|
+ assert(matchFn);
|
|
|
+ if (!matchFn)
|
|
|
+ return -1;
|
|
|
+
|
|
|
+ for (i = start_index; i < faux_vec_len(faux_vec); i++) {
|
|
|
+ if (matchFn(userkey, faux_vec_item(faux_vec, i)) == 0)
|
|
|
+ return i;
|
|
|
+ }
|
|
|
|
|
|
- return result;
|
|
|
+ return -1;
|
|
|
}
|
|
|
|
|
|
-/*--------------------------------------------------------- */
|
|
|
-#endif
|
|
|
+
|
|
|
+int faux_vec_find(const faux_vec_t *faux_vec, const void *userkey,
|
|
|
+ unsigned int start_index)
|
|
|
+{
|
|
|
+ assert(faux_vec);
|
|
|
+ if (!faux_vec)
|
|
|
+ return -1;
|
|
|
+ assert(faux_vec->kcmpFn);
|
|
|
+ if (!faux_vec->kcmpFn)
|
|
|
+ return -1;
|
|
|
+
|
|
|
+ return faux_vec_find_fn(faux_vec, faux_vec->kcmpFn,
|
|
|
+ userkey, start_index);
|
|
|
+}
|