GCC Code Coverage Report


Directory: ./
File: iterator.c
Date: 2025-04-06 13:22:55
Exec Total Coverage
Lines: 58 58 100.0%
Functions: 9 9 100.0%
Branches: 12 12 100.0%

Line Branch Exec Source
1 /*
2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3 *
4 * Copyright 2024 Mike Becker, Olaf Wintermann All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are met:
8 *
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 *
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE.
27 */
28
29 #include "cx/iterator.h"
30
31 #include <string.h>
32
33 254 static bool cx_iter_valid(const void *it) {
34 254 const struct cx_iterator_s *iter = it;
35 254 return iter->index < iter->elem_count;
36 }
37
38 117 static void *cx_iter_current(const void *it) {
39 117 const struct cx_iterator_s *iter = it;
40 117 return iter->elem_handle;
41 }
42
43 94 static void *cx_iter_current_ptr(const void *it) {
44 94 const struct cx_iterator_s *iter = it;
45 94 return *(void**)iter->elem_handle;
46 }
47
48 188 static void cx_iter_next_fast(void *it) {
49 188 struct cx_iterator_s *iter = it;
50
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 178 times.
188 if (iter->base.remove) {
51 10 iter->base.remove = false;
52 10 iter->elem_count--;
53 // only move the last element when we are not currently aiming
54 // at the last element already
55
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 1 times.
10 if (iter->index < iter->elem_count) {
56 9 void *last = ((char *) iter->src_handle.m)
57 9 + iter->elem_count * iter->elem_size;
58 9 memcpy(iter->elem_handle, last, iter->elem_size);
59 }
60 } else {
61 178 iter->index++;
62 178 iter->elem_handle = ((char *) iter->elem_handle) + iter->elem_size;
63 }
64 188 }
65
66 20 static void cx_iter_next_slow(void *it) {
67 20 struct cx_iterator_s *iter = it;
68
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 10 times.
20 if (iter->base.remove) {
69 10 iter->base.remove = false;
70 10 iter->elem_count--;
71
72 // number of elements to move
73 10 size_t remaining = iter->elem_count - iter->index;
74
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 1 times.
10 if (remaining > 0) {
75 9 memmove(
76 iter->elem_handle,
77 9 ((char *) iter->elem_handle) + iter->elem_size,
78 9 remaining * iter->elem_size
79 );
80 }
81 } else {
82 10 iter->index++;
83 10 iter->elem_handle = ((char *) iter->elem_handle) + iter->elem_size;
84 }
85 20 }
86
87 40 CxIterator cxMutIterator(
88 void *array,
89 size_t elem_size,
90 size_t elem_count,
91 bool remove_keeps_order
92 ) {
93 CxIterator iter;
94
95 40 iter.index = 0;
96 40 iter.src_handle.m = array;
97 40 iter.elem_handle = array;
98 40 iter.elem_size = elem_size;
99
2/2
✓ Branch 0 taken 39 times.
✓ Branch 1 taken 1 times.
40 iter.elem_count = array == NULL ? 0 : elem_count;
100 40 iter.base.valid = cx_iter_valid;
101 40 iter.base.current = cx_iter_current;
102
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 39 times.
40 iter.base.next = remove_keeps_order ? cx_iter_next_slow : cx_iter_next_fast;
103 40 iter.base.remove = false;
104 40 iter.base.mutating = true;
105
106 40 return iter;
107 }
108
109 12 CxIterator cxIterator(
110 const void *array,
111 size_t elem_size,
112 size_t elem_count
113 ) {
114 12 CxIterator iter = cxMutIterator((void*)array, elem_size, elem_count, false);
115 12 iter.base.mutating = false;
116 12 return iter;
117 }
118
119 26 CxIterator cxMutIteratorPtr(
120 void *array,
121 size_t elem_count,
122 bool remove_keeps_order
123 ) {
124 26 CxIterator iter = cxMutIterator(array, sizeof(void*), elem_count, remove_keeps_order);
125 26 iter.base.current = cx_iter_current_ptr;
126 26 return iter;
127 }
128
129 26 CxIterator cxIteratorPtr(
130 const void *array,
131 size_t elem_count
132 ) {
133 26 CxIterator iter = cxMutIteratorPtr((void*) array, elem_count, false);
134 26 iter.base.mutating = false;
135 26 return iter;
136 }
137