ucx/iterator.c

branch
newapi
changeset 324
ce13a778654a
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ucx/iterator.c	Sun Oct 06 12:00:31 2024 +0200
@@ -0,0 +1,112 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2024 Mike Becker, Olaf Wintermann All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *   1. Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *
+ *   2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 THE COPYRIGHT HOLDER 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 "cx/iterator.h"
+
+#include <string.h>
+
+static bool cx_iter_valid(const void *it) {
+    const struct cx_iterator_s *iter = it;
+    return iter->index < iter->elem_count;
+}
+
+static void *cx_iter_current(const void *it) {
+    const struct cx_iterator_s *iter = it;
+    return iter->elem_handle;
+}
+
+static void cx_iter_next_fast(void *it) {
+    struct cx_iterator_s *iter = it;
+    if (iter->base.remove) {
+        iter->base.remove = false;
+        iter->elem_count--;
+        // only move the last element when we are not currently aiming
+        // at the last element already
+        if (iter->index < iter->elem_count) {
+            void *last = ((char *) iter->src_handle.m)
+                         + iter->elem_count * iter->elem_size;
+            memcpy(iter->elem_handle, last, iter->elem_size);
+        }
+    } else {
+        iter->index++;
+        iter->elem_handle = ((char *) iter->elem_handle) + iter->elem_size;
+    }
+}
+
+static void cx_iter_next_slow(void *it) {
+    struct cx_iterator_s *iter = it;
+    if (iter->base.remove) {
+        iter->base.remove = false;
+        iter->elem_count--;
+
+        // number of elements to move
+        size_t remaining = iter->elem_count - iter->index;
+        if (remaining > 0) {
+            memmove(
+                    iter->elem_handle,
+                    ((char *) iter->elem_handle) + iter->elem_size,
+                    remaining * iter->elem_size
+            );
+        }
+    } else {
+        iter->index++;
+        iter->elem_handle = ((char *) iter->elem_handle) + iter->elem_size;
+    }
+}
+
+CxIterator cxMutIterator(
+        void *array,
+        size_t elem_size,
+        size_t elem_count,
+        bool remove_keeps_order
+) {
+    CxIterator iter;
+
+    iter.index = 0;
+    iter.src_handle.m = array;
+    iter.elem_handle = array;
+    iter.elem_size = elem_size;
+    iter.elem_count = array == NULL ? 0 : elem_count;
+    iter.base.valid = cx_iter_valid;
+    iter.base.current = cx_iter_current;
+    iter.base.next = remove_keeps_order ? cx_iter_next_slow : cx_iter_next_fast;
+    iter.base.remove = false;
+    iter.base.mutating = true;
+
+    return iter;
+}
+
+CxIterator cxIterator(
+        const void *array,
+        size_t elem_size,
+        size_t elem_count
+) {
+    CxIterator iter = cxMutIterator((void*)array, elem_size, elem_count, false);
+    iter.base.mutating = false;
+    return iter;
+}

mercurial