Can be used for building up lists of things, especially
lists of strings.
---
common/include/Makefile.am | 6 +++
common/include/test-vector.c | 90 +++++++++++++++++++++++++++++++++
common/include/vector.h | 96 ++++++++++++++++++++++++++++++++++++
.gitignore | 1 +
4 files changed, 193 insertions(+)
diff --git a/common/include/Makefile.am b/common/include/Makefile.am
index 4482de37..3089a0a1 100644
--- a/common/include/Makefile.am
+++ b/common/include/Makefile.am
@@ -45,6 +45,7 @@ EXTRA_DIST = \
random.h \
rounding.h \
tvdiff.h \
+ vector.h \
$(NULL)
# Unit tests.
@@ -59,6 +60,7 @@ TESTS = \
test-nextnonzero \
test-random \
test-tvdiff \
+ test-vector \
$(NULL)
check_PROGRAMS = $(TESTS)
@@ -97,3 +99,7 @@ test_random_CFLAGS = $(WARNINGS_CFLAGS)
test_tvdiff_SOURCES = test-tvdiff.c tvdiff.h
test_tvdiff_CPPFLAGS = -I$(srcdir)
test_tvdiff_CFLAGS = $(WARNINGS_CFLAGS)
+
+test_vector_SOURCES = test-vector.c vector.h
+test_vector_CPPFLAGS = -I$(srcdir)
+test_vector_CFLAGS = $(WARNINGS_CFLAGS)
diff --git a/common/include/test-vector.c b/common/include/test-vector.c
new file mode 100644
index 00000000..8bf6e349
--- /dev/null
+++ b/common/include/test-vector.c
@@ -0,0 +1,90 @@
+/* nbdkit
+ * Copyright (C) 2020 Red Hat Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * * Neither the name of Red Hat nor the names of its contributors may be
+ * used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY RED HAT AND CONTRIBUTORS ''AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL RED HAT OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <assert.h>
+
+#include "vector.h"
+
+DEFINE_VECTOR_TYPE(int64_vector, int64_t);
+DEFINE_VECTOR_TYPE(string_vector, char *);
+
+static void
+test_int64_vector (void)
+{
+ int64_vector v = empty_vector;
+ size_t i;
+
+ for (i = 0; i < 10; ++i)
+ assert (int64_vector_append (&v, i) == 0);
+ for (i = 0; i < 10; ++i)
+ assert (v.ptr[i] == i);
+ free (v.ptr);
+}
+
+static void
+test_string_vector (void)
+{
+ string_vector v = empty_vector;
+ size_t i;
+
+ for (i = 0; i < 10; ++i) {
+ char *s;
+
+ assert (asprintf (&s, "number %zu", i) >= 0);
+ assert (string_vector_append (&v, s) == 0);
+ }
+ /* NULL-terminate the strings. */
+ assert (string_vector_append (&v, NULL) == 0);
+
+ /* Now print them. */
+ for (i = 0; v.ptr[i] != NULL; ++i)
+ printf ("%s\n", v.ptr[i]);
+ assert (i == 10);
+
+ /* And free them. We can use the generated iter function here
+ * even though it calls free on the final NULL pointer.
+ */
+ string_vector_iter (&v, (void*)free);
+ free (v.ptr);
+}
+
+int
+main (int argc, char *argv[])
+{
+ test_int64_vector ();
+ test_string_vector ();
+}
diff --git a/common/include/vector.h b/common/include/vector.h
new file mode 100644
index 00000000..69a350be
--- /dev/null
+++ b/common/include/vector.h
@@ -0,0 +1,96 @@
+/* nbdkit
+ * Copyright (C) 2020 Red Hat Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * * Neither the name of Red Hat nor the names of its contributors may be
+ * used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY RED HAT AND CONTRIBUTORS ''AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL RED HAT OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* Simple implementation of appendable vector. There are two main
+ * use-cases we consider: lists of strings (either with a defined
+ * length, or NULL-terminated), and lists of numbers. It is generic
+ * so could be used for lists of anything (eg. structs) where being
+ * able to append easily is important.
+ */
+
+#ifndef NBDKIT_VECTOR_H
+#define NBDKIT_VECTOR_H
+
+#include <assert.h>
+
+#define DEFINE_VECTOR_TYPE(name, type) \
+ struct name { \
+ type *ptr; /* Pointer to array of items. */ \
+ size_t size; /* Number of valid items in the array. */ \
+ size_t alloc; /* Number of items allocated. */ \
+ }; \
+ typedef struct name name; \
+ static inline int \
+ name##_extend (name *v, size_t n) \
+ { \
+ return generic_vector_extend ((struct generic_vector *)v, n, \
+ sizeof (type)); \
+ } \
+ static inline int \
+ name##_append (name *v, type elem) \
+ { \
+ if (v->size >= v->alloc) { \
+ if (name##_extend (v, 1) == -1) return -1; \
+ } \
+ v->ptr[v->size++] = elem; \
+ return 0; \
+ } \
+ static inline void \
+ name##_iter (name *v, void (*f) (type elem)) \
+ { \
+ size_t i; \
+ for (i = 0; i < v->size; ++i) \
+ f (v->ptr[i]); \
+ }
+
+#define empty_vector { .ptr = NULL, .size = 0, .alloc = 0 }
+
+struct generic_vector {
+ void *ptr;
+ size_t size;
+ size_t alloc;
+};
+
+static int
+generic_vector_extend (struct generic_vector *v, size_t n, size_t itemsize)
+{
+ void *newptr;
+
+ newptr = realloc (v->ptr, (n + v->alloc) * itemsize);
+ if (newptr == NULL)
+ return -1;
+ v->ptr = newptr;
+ v->alloc += n;
+ return 0;
+}
+
+#endif /* NBDKIT_VECTOR_H */
diff --git a/.gitignore b/.gitignore
index c44fb40d..8974b64f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -42,6 +42,7 @@ plugins/*/*.3
/common/include/test-nextnonzero
/common/include/test-random
/common/include/test-tvdiff
+/common/include/test-vector
/common/protocol/generate-protostrings.sh
/common/protocol/protostrings.c
/common/utils/test-quotes
--
2.25.0