aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPetr Machata <pmachata@redhat.com>2012-09-25 14:52:23 +0200
committerPetr Machata <pmachata@redhat.com>2012-09-25 14:52:23 +0200
commit49d3d52e19692f92cf2114b053053c549a723b79 (patch)
treee9360bd50c2d36695efea2cbeb2000422428e00a
parenta24021c5abfa8c2482e3224f14ac191cd0826a8f (diff)
downloadltrace-49d3d52e19692f92cf2114b053053c549a723b79.tar.gz
Add vect_each, VECT_EACH for iteration over vectors
-rw-r--r--ChangeLog5
-rw-r--r--vect.c22
-rw-r--r--vect.h21
3 files changed, 48 insertions, 0 deletions
diff --git a/ChangeLog b/ChangeLog
index c08f83d..93f613f 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,10 @@
2012-09-25 Petr Machata <pmachata@redhat.com>
+ * vect.h, vect.c (vect_each): New function.
+ * vect.h (VECT_EACH): New wrapper macro.
+
+2012-09-25 Petr Machata <pmachata@redhat.com>
+
* callback.h: New file.
* proc.h (enum callback_status): Move to callback.h.
diff --git a/vect.c b/vect.c
index f2e58b2..7dae847 100644
--- a/vect.c
+++ b/vect.c
@@ -134,3 +134,25 @@ vect_destroy(struct vect *vec, void (*dtor)(void *emt, void *data), void *data)
}
free(vec->data);
}
+
+void *
+vect_each(struct vect *vec, void *start_after,
+ enum callback_status (*cb)(void *, void *), void *data)
+{
+ size_t i = start_after == NULL ? 0
+ : ((start_after - vec->data) / vec->elt_size) + 1;
+
+ for (; i < vec->size; ++i) {
+ void *slt = slot(vec, i);
+ switch ((*cb)(slt, data)) {
+ case CBS_FAIL:
+ /* XXX handle me */
+ case CBS_STOP:
+ return slt;
+ case CBS_CONT:
+ break;
+ }
+ }
+
+ return NULL;
+}
diff --git a/vect.h b/vect.h
index 50401bb..c07235f 100644
--- a/vect.h
+++ b/vect.h
@@ -22,6 +22,9 @@
#define VECT_H
#include <stddef.h>
+#include <assert.h>
+
+#include "callback.h"
/* Vector is an array that can grow as needed to accommodate the data
* that it needs to hold. ELT_SIZE is also used as an elementary
@@ -122,4 +125,22 @@ void vect_destroy(struct vect *vec,
DATA); \
} while (0)
+/* Iterate through vector VEC. See callback.h for notes on iteration
+ * interfaces. */
+void *vect_each(struct vect *vec, void *start_after,
+ enum callback_status (*cb)(void *, void *), void *data);
+
+#define VECT_EACH(VECP, ELT_TYPE, START_AFTER, CB, DATA) \
+ /* xxx GCC-ism necessary to get in the safety latches. */ \
+ ({ \
+ assert((VECP)->elt_size == sizeof(ELT_TYPE)); \
+ /* Check that CB is typed properly. */ \
+ enum callback_status (*_cb)(ELT_TYPE *, void *) = CB; \
+ ELT_TYPE *start_after = (START_AFTER); \
+ (ELT_TYPE *)vect_each((VECP), start_after, \
+ (enum callback_status \
+ (*)(void *, void *))_cb, \
+ DATA); \
+ })
+
#endif /* VECT_H */