Add iter index functions

This commit is contained in:
jun 2025-01-30 16:10:10 +01:00
parent 67b5759e03
commit df9d1c9c10
2 changed files with 87 additions and 19 deletions

View File

@ -3,7 +3,7 @@
#include "guf_common.h" #include "guf_common.h"
#include "guf_assert.h" #include "guf_assert.h"
#include "guf_alloc.h" #include "guf_alloc.h"
#define GUF_DBUF_FOREACH(DBUF, ELEM_TYPE, ELEM_PTR_NAME) for (ELEM_TYPE *ELEM_PTR_NAME = (DBUF).data, *end = (DBUF).data ? (DBUF).data + (DBUF).size : NULL; ELEM_PTR_NAME != end; ++ELEM_PTR_NAME) #define GUF_DBUF_FOREACH(DBUF, ELEM_TYPE, ELEM_PTR_NAME) for (ELEM_TYPE *ELEM_PTR_NAME = (DBUF).data, *guf_foreach_end = (DBUF).data ? (DBUF).data + (DBUF).size : NULL; ELEM_PTR_NAME != guf_foreach_end; ++ELEM_PTR_NAME)
#endif #endif
/* /*
@ -124,11 +124,14 @@ GUF_FN_KEYWORDS GUF_CAT(GUF_CNT_NAME, _iter) GUF_CAT(GUF_CNT_NAME, _end)(const G
GUF_FN_KEYWORDS GUF_CAT(GUF_CNT_NAME, _iter) GUF_CAT(GUF_CNT_NAME, _rbegin)(const GUF_CNT_NAME* dbuf); GUF_FN_KEYWORDS GUF_CAT(GUF_CNT_NAME, _iter) GUF_CAT(GUF_CNT_NAME, _rbegin)(const GUF_CNT_NAME* dbuf);
GUF_FN_KEYWORDS GUF_CAT(GUF_CNT_NAME, _iter) GUF_CAT(GUF_CNT_NAME, _rend)(const GUF_CNT_NAME* dbuf); GUF_FN_KEYWORDS GUF_CAT(GUF_CNT_NAME, _iter) GUF_CAT(GUF_CNT_NAME, _rend)(const GUF_CNT_NAME* dbuf);
GUF_FN_KEYWORDS GUF_CAT(GUF_CNT_NAME, _iter) GUF_CAT(GUF_CNT_NAME, _iter_next)(const GUF_CNT_NAME *dbuf, GUF_CAT(GUF_CNT_NAME, _iter) it, ptrdiff_t step); GUF_FN_KEYWORDS GUF_CAT(GUF_CNT_NAME, _iter) GUF_CAT(GUF_CNT_NAME, _iter_next)(const GUF_CNT_NAME *dbuf, GUF_CAT(GUF_CNT_NAME, _iter) it, ptrdiff_t step);
GUF_FN_KEYWORDS GUF_CAT(GUF_CNT_NAME, _iter) GUF_CAT(GUF_CNT_NAME, _iter_at_idx)(const GUF_CNT_NAME* dbuf, ptrdiff_t idx);
GUF_FN_KEYWORDS GUF_CAT(GUF_CNT_NAME, _iter) GUF_CAT(GUF_CNT_NAME, _reverse_iter_at_idx)(const GUF_CNT_NAME* dbuf, ptrdiff_t idx);
GUF_FN_KEYWORDS ptrdiff_t GUF_CAT(GUF_CNT_NAME, _iter_to_idx)(const GUF_CNT_NAME* dbuf, GUF_CAT(GUF_CNT_NAME, _iter) it);
#if defined(GUF_T_IS_INTEGRAL_TYPE) || defined(GUF_T_EQ) #if defined(GUF_T_IS_INTEGRAL_TYPE) || defined(GUF_T_EQ)
GUF_FN_KEYWORDS GUF_CAT(GUF_CNT_NAME, _iter) GUF_CAT(GUF_CNT_NAME, _find)(GUF_CNT_NAME *dbuf, GUF_CAT(GUF_CNT_NAME, _iter) begin, GUF_CAT(GUF_CNT_NAME, _iter) end, const GUF_T *needle); GUF_FN_KEYWORDS GUF_CAT(GUF_CNT_NAME, _iter) GUF_CAT(GUF_CNT_NAME, _find)(GUF_CNT_NAME *dbuf, GUF_CAT(GUF_CNT_NAME, _iter) begin, GUF_CAT(GUF_CNT_NAME, _iter) end, const GUF_T *needle);
GUF_FN_KEYWORDS GUF_CAT(GUF_CNT_NAME, _iter) GUF_CAT(GUF_CNT_NAME, _find_val)(GUF_CNT_NAME *dbuf, GUF_CAT(GUF_CNT_NAME, _iter) begin, GUF_CAT(GUF_CNT_NAME, _iter) end, GUF_T needle_val); GUF_FN_KEYWORDS GUF_CAT(GUF_CNT_NAME, _iter) GUF_CAT(GUF_CNT_NAME, _find_val)(GUF_CNT_NAME *dbuf, GUF_CAT(GUF_CNT_NAME, _iter) begin, GUF_CAT(GUF_CNT_NAME, _iter) end, GUF_T needle_val);
GUF_FN_KEYWORDS GUF_CAT(GUF_CNT_NAME, _iter) GUF_CAT(GUF_CNT_NAME, _find_if)(GUF_CNT_NAME *dbuf, GUF_CAT(GUF_CNT_NAME, _iter) *begin, GUF_CAT(GUF_CNT_NAME, _iter) *end, bool (*predicate)(const GUF_T *)); GUF_FN_KEYWORDS GUF_CAT(GUF_CNT_NAME, _iter) GUF_CAT(GUF_CNT_NAME, _find_if)(GUF_CNT_NAME *dbuf, GUF_CAT(GUF_CNT_NAME, _iter) begin, GUF_CAT(GUF_CNT_NAME, _iter) end, bool (*predicate)(const GUF_T *));
#endif #endif
#if defined(GUF_IMPL) || defined(GUF_IMPL_STATIC) #if defined(GUF_IMPL) || defined(GUF_IMPL_STATIC)
@ -756,6 +759,8 @@ GUF_FN_KEYWORDS void GUF_CAT(GUF_CNT_NAME, _try_shrink_to_fit)(GUF_CNT_NAME *dbu
} }
/* Iterator functions */
GUF_FN_KEYWORDS GUF_CAT(GUF_CNT_NAME, _iter) GUF_CAT(GUF_CNT_NAME, _begin)(const GUF_CNT_NAME* dbuf) GUF_FN_KEYWORDS GUF_CAT(GUF_CNT_NAME, _iter) GUF_CAT(GUF_CNT_NAME, _begin)(const GUF_CNT_NAME* dbuf)
{ {
GUF_ASSERT_RELEASE(GUF_CAT(GUF_CNT_NAME, _valid)(dbuf)); GUF_ASSERT_RELEASE(GUF_CAT(GUF_CNT_NAME, _valid)(dbuf));
@ -792,6 +797,47 @@ GUF_FN_KEYWORDS GUF_CAT(GUF_CNT_NAME, _iter) GUF_CAT(GUF_CNT_NAME, _rend)(const
}; };
} }
GUF_FN_KEYWORDS GUF_CAT(GUF_CNT_NAME, _iter) GUF_CAT(GUF_CNT_NAME, _iter_at_idx)(const GUF_CNT_NAME* dbuf, ptrdiff_t idx)
{
GUF_ASSERT(GUF_CAT(GUF_CNT_NAME, _valid)(dbuf));
GUF_CAT(GUF_CNT_NAME, _iter) it;
it.reverse = false;
if (idx < 0 || idx >= dbuf->size || !dbuf->data) {
it.ptr = GUF_CAT(GUF_CNT_NAME, _end)(dbuf).ptr;
} else {
it.ptr = dbuf->data + idx;
}
return it;
}
GUF_FN_KEYWORDS GUF_CAT(GUF_CNT_NAME, _iter) GUF_CAT(GUF_CNT_NAME, _reverse_iter_at_idx)(const GUF_CNT_NAME* dbuf, ptrdiff_t idx)
{
GUF_CAT(GUF_CNT_NAME, _iter) it = GUF_CAT(GUF_CNT_NAME, _iter_at_idx)(dbuf, idx);
it.reverse = true;
return it;
}
static const ptrdiff_t GUF_CAT(GUF_CNT_NAME, _npos) = -1;
GUF_FN_KEYWORDS ptrdiff_t GUF_CAT(GUF_CNT_NAME, _iter_to_idx)(const GUF_CNT_NAME* dbuf, GUF_CAT(GUF_CNT_NAME, _iter) it)
{
GUF_ASSERT(GUF_CAT(GUF_CNT_NAME, _valid)(dbuf));
GUF_CAT(GUF_CNT_NAME, _iter) begin = GUF_CAT(GUF_CNT_NAME, _begin)(dbuf);
GUF_CAT(GUF_CNT_NAME, _iter) end = GUF_CAT(GUF_CNT_NAME, _end)(dbuf);
if (it.ptr == NULL || begin.ptr == NULL || end.ptr == NULL || it.ptr < begin.ptr || it.ptr > end.ptr || !dbuf->data) {
return GUF_CAT(GUF_CNT_NAME, _npos);
} else if (it.ptr == end.ptr) {
return it.reverse ? -1 : dbuf->size;
} else {
ptrdiff_t idx = it.ptr - begin.ptr;
GUF_ASSERT(idx >= 0 && idx <= dbuf->size);
return idx;
}
}
GUF_FN_KEYWORDS GUF_CAT(GUF_CNT_NAME, _iter) GUF_CAT(GUF_CNT_NAME, _iter_next)(const GUF_CNT_NAME *dbuf, GUF_CAT(GUF_CNT_NAME, _iter) it, ptrdiff_t step) GUF_FN_KEYWORDS GUF_CAT(GUF_CNT_NAME, _iter) GUF_CAT(GUF_CNT_NAME, _iter_next)(const GUF_CNT_NAME *dbuf, GUF_CAT(GUF_CNT_NAME, _iter) it, ptrdiff_t step)
{ {
GUF_ASSERT(GUF_CAT(GUF_CNT_NAME, _valid)(dbuf)); GUF_ASSERT(GUF_CAT(GUF_CNT_NAME, _valid)(dbuf));
@ -816,18 +862,14 @@ GUF_FN_KEYWORDS GUF_CAT(GUF_CNT_NAME, _iter) GUF_CAT(GUF_CNT_NAME, _iter_next)(c
} else if (it.ptr == end_ptr && !it.reverse) { // Handle end() } else if (it.ptr == end_ptr && !it.reverse) { // Handle end()
it_idx = dbuf->size + step; it_idx = dbuf->size + step;
} else { } else {
GUF_ASSERT_RELEASE(it.ptr >= dbuf->data && it.ptr < end_ptr && (ptrdiff_t)it.ptr - (ptrdiff_t)dbuf->data >= 0) GUF_ASSERT_RELEASE(it.ptr >= dbuf->data && it.ptr < end_ptr)
it_idx = (ptrdiff_t)(it.ptr - dbuf->data) + step; // TODO: is this legal? it_idx = (ptrdiff_t)(it.ptr - dbuf->data) + step;
} }
const ptrdiff_t len = end_ptr && dbuf->data ? end_ptr - dbuf->data : 0; const ptrdiff_t len = (end_ptr && dbuf->data) ? end_ptr - dbuf->data : 0;
GUF_ASSERT_RELEASE(len >= 0); GUF_ASSERT_RELEASE(len >= 0);
if (len == 0) { if (len == 0 || it_idx >= len || it_idx < 0) {
it.ptr = end_ptr;
} else if (it_idx >= len) {
it.ptr = end_ptr;
} else if (it_idx < 0) {
it.ptr = end_ptr; it.ptr = end_ptr;
} else { } else {
GUF_ASSERT(dbuf->data && it.ptr); GUF_ASSERT(dbuf->data && it.ptr);
@ -842,8 +884,20 @@ GUF_FN_KEYWORDS GUF_CAT(GUF_CNT_NAME, _iter) GUF_CAT(GUF_CNT_NAME, _find)(GUF_CN
{ {
GUF_ASSERT_RELEASE(GUF_CAT(GUF_CNT_NAME, _valid)(dbuf)); GUF_ASSERT_RELEASE(GUF_CAT(GUF_CNT_NAME, _valid)(dbuf));
GUF_ASSERT_RELEASE(needle); GUF_ASSERT_RELEASE(needle);
GUF_CAT(GUF_CNT_NAME, _iter) dbuf_end = GUF_CAT(GUF_CNT_NAME, _end)(dbuf);
dbuf_end.reverse = begin.reverse;
for (GUF_CAT(GUF_CNT_NAME, _iter) it = begin; it.ptr != end.ptr; it = GUF_CAT(GUF_CNT_NAME, _iter_next)(dbuf, it, 1)) { ptrdiff_t begin_idx = GUF_CAT(GUF_CNT_NAME, _iter_to_idx)(dbuf, begin);
ptrdiff_t end_idx = GUF_CAT(GUF_CNT_NAME, _iter_to_idx)(dbuf, end);
if (!begin.ptr || !end.ptr || !dbuf->data || begin.ptr == dbuf_end.ptr) {
return dbuf_end;
} else if (!begin.reverse && begin_idx >= end_idx) {
return dbuf_end;
} else if (begin.reverse && begin_idx <= end_idx) {
return dbuf_end;
}
for (GUF_CAT(GUF_CNT_NAME, _iter) it = begin; it.ptr != end.ptr && it.ptr != dbuf_end.ptr; it = GUF_CAT(GUF_CNT_NAME, _iter_next)(dbuf, it, 1)) {
#ifdef GUF_T_EQ #ifdef GUF_T_EQ
if (GUF_T_EQ(it.ptr, needle)) { if (GUF_T_EQ(it.ptr, needle)) {
return it; return it;
@ -862,12 +916,22 @@ GUF_FN_KEYWORDS GUF_CAT(GUF_CNT_NAME, _iter) GUF_CAT(GUF_CNT_NAME, _find_val)(GU
return GUF_CAT(GUF_CNT_NAME, _find)(dbuf, begin, end, &needle_val); return GUF_CAT(GUF_CNT_NAME, _find)(dbuf, begin, end, &needle_val);
} }
GUF_FN_KEYWORDS GUF_CAT(GUF_CNT_NAME, _iter) GUF_CAT(GUF_CNT_NAME, _find_if)(GUF_CNT_NAME *dbuf, GUF_CAT(GUF_CNT_NAME, _iter) *begin, GUF_CAT(GUF_CNT_NAME, _iter) *end, bool (*predicate)(const GUF_T *)) GUF_FN_KEYWORDS GUF_CAT(GUF_CNT_NAME, _iter) GUF_CAT(GUF_CNT_NAME, _find_if)(GUF_CNT_NAME *dbuf, GUF_CAT(GUF_CNT_NAME, _iter) begin, GUF_CAT(GUF_CNT_NAME, _iter) end, bool (*predicate)(const GUF_T *))
{ {
GUF_ASSERT_RELEASE(GUF_CAT(GUF_CNT_NAME, _valid)(dbuf)); GUF_ASSERT_RELEASE(GUF_CAT(GUF_CNT_NAME, _valid)(dbuf));
GUF_ASSERT_RELEASE(begin && end && predicate); GUF_ASSERT_RELEASE(predicate);
for (GUF_CAT(GUF_CNT_NAME, _iter) it = *begin; it.ptr != end->ptr; GUF_CAT(GUF_CNT_NAME, _iter_next)(dbuf, it, 1)) { GUF_CAT(GUF_CNT_NAME, _iter) dbuf_end = GUF_CAT(GUF_CNT_NAME, _end)(dbuf);
dbuf_end.reverse = begin.reverse;
if (!begin.ptr || !end.ptr || !dbuf->data) {
return dbuf_end;
} else if (!begin.reverse && begin.ptr >= end.ptr) {
return dbuf_end;
} else if (begin.reverse && begin.ptr <= end.ptr) {
return dbuf_end;
}
for (GUF_CAT(GUF_CNT_NAME, _iter) it = begin; it.ptr != end.ptr; GUF_CAT(GUF_CNT_NAME, _iter_next)(dbuf, it, 1)) {
if (predicate(it.ptr)) { if (predicate(it.ptr)) {
return it; return it;
} }

View File

@ -72,12 +72,16 @@ int main(void)
dbuf_heap_cstr_push(&strings, &move_me, GUF_CPY_MOVE); dbuf_heap_cstr_push(&strings, &move_me, GUF_CPY_MOVE);
GUF_ASSERT_RELEASE(move_me == NULL); GUF_ASSERT_RELEASE(move_me == NULL);
char *findme = "Baz 3"; dbuf_heap_cstr_push_val_cpy(&strings, "Boz 4");
dbuf_heap_cstr_iter fnd_it = dbuf_heap_cstr_find(&strings, dbuf_heap_cstr_begin(&strings), dbuf_heap_cstr_end(&strings), &findme); char *findme = "Baz 3";
dbuf_heap_cstr_iter beg = dbuf_heap_cstr_rbegin(&strings);
dbuf_heap_cstr_iter end = dbuf_heap_cstr_rend(&strings);
dbuf_heap_cstr_iter fnd_it = dbuf_heap_cstr_find(&strings, beg, end, &findme);
if (fnd_it.ptr != dbuf_heap_cstr_end(&strings).ptr) { if (fnd_it.ptr != dbuf_heap_cstr_end(&strings).ptr) {
guf_cstr_heap_free(fnd_it.ptr, NULL); printf("%s found in range [%td, %td) at idx %td\n", findme, dbuf_heap_cstr_iter_to_idx(&strings, beg), dbuf_heap_cstr_iter_to_idx(&strings, end), dbuf_heap_cstr_iter_to_idx(&strings, fnd_it));
*fnd_it.ptr = strdup("Found!"); } else {
printf("%s not found in range [%td, %td) at idx %td\n", findme, dbuf_heap_cstr_iter_to_idx(&strings, beg), dbuf_heap_cstr_iter_to_idx(&strings, end), dbuf_heap_cstr_iter_to_idx(&strings, fnd_it));
} }
GUF_CNT_FOREACH(&strings, dbuf_heap_cstr, it) { GUF_CNT_FOREACH(&strings, dbuf_heap_cstr, it) {
@ -140,7 +144,7 @@ int main(void)
} }
for (dbuf_int_iter it = dbuf_int_rbegin(&integers); it.ptr != dbuf_int_rend(&integers).ptr; it = dbuf_int_iter_next(&integers, it, 2)) { for (dbuf_int_iter it = dbuf_int_rbegin(&integers); it.ptr != dbuf_int_rend(&integers).ptr; it = dbuf_int_iter_next(&integers, it, 2)) {
printf("every other reverse: %d\n", *it.ptr); printf("every other reverse: %d (idx %td)\n", *it.ptr, dbuf_int_iter_to_idx(&integers, it));
} }
dbuf_int_free(&integers, NULL); dbuf_int_free(&integers, NULL);