Updated table to simplify iteration. Iterated.

This commit is contained in:
Neil 2022-12-14 20:44:36 -08:00
parent 659ea490e2
commit 60671ccb47
3 changed files with 38 additions and 35 deletions

View File

@ -74,7 +74,7 @@ gperf := gperf
target := # -mwindows
optimize := -ffast-math
warnbasic := -Wall -pedantic -ansi # -std=c99
warnbasic := -Wall -pedantic #-ansi # -std=c99
# Some stuff is really new.
warnclang := -Wextra \
-Weverything \

View File

@ -269,6 +269,7 @@ static void words_to_string(const union kjvcite x, char (*const a)[12])
#define TABLE_KEY union kjvcite
#define TABLE_UINT uint32_t
#define TABLE_VALUE unsigned
#define TABLE_DEFUALT 0
#define TABLE_INVERSE
#define TABLE_TO_STRING
#include "../src/table.h"
@ -338,6 +339,17 @@ int main(void) {
printf("words: %s\n", words_table_to_string(&words));
printf("kjv: %zu words\n", cum_words);
{
union kjvcite c;
struct words_table_iterator it = words_table_begin(&words);
unsigned *w;
while(words_table_next(&it, &c, &w))
printf("%s %u:%u -> %u\n",
kjv_book_string[c.book], c.chapter, c.verse, *w);
c.u32 = 0; /* Unnecessary? */
c.book = Genesis, c.chapter = 1, c.verse = 1;
printf("%u\n", words_table_get_or(&words, c, 0)); /* Why not get? */
}
goto finally;
catch:
success = EXIT_FAILURE;

View File

@ -13,6 +13,8 @@
It must be supplied <typedef:<PN>hash_fn> `<N>hash` and,
<typedef:<PN>is_equal_fn> `<N>is_equal` or <typedef:<PN>unhash_fn> `<N>unhash`.
(Fixme: remove entry as public struct, this should be entirely private.)
@param[TABLE_NAME, TABLE_KEY]
`<N>` that satisfies `C` naming conventions when mangled and a valid
<typedef:<PN>key> associated therewith; required. `<PN>` is private, whose
@ -607,40 +609,28 @@ static void N_(table_)(struct N_(table) *const table)
static struct N_(table_iterator) N_(table_begin)(struct N_(table) *const
table) { struct N_(table_iterator) it; it._ = PN_(iterator)(table);
return it; }
/** Advances `it`. The awkwardness of this function because <typedef:<PN>entry>
is not necessarily nullifyable, so we are not guaranteed to have an
out-of-band entry to indicate completion. (May be changed in the future.)
@param[entry] If non-null, the entry is filled with the next element only if
it has a next. @return Whether it had a next element. @allow */
#ifdef TABLE_VALUE /* <!-- map */
/** Advances `it`. @param[key, value] If non-null, the key or value is filled
with the next element on return true. `value` is a pointer to the actual value
in the map, only there if it is a map.
@return Whether it had a next element. @allow */
static int N_(table_next)(struct N_(table_iterator) *const it,
PN_(entry) *entry) {
struct PN_(bucket) *b = PN_(next)(&it->_);
if(!b) return 0;
if(entry) *entry = PN_(to_entry)(b);
PN_(key) *key, PN_(value) **value) {
struct PN_(bucket) *bucket = PN_(next)(&it->_);
if(!bucket) return 0;
if(key) *key = PN_(bucket_key)(bucket);
if(value) *value = &bucket->value;
return 1;
}
/** Especially for tables that can have zero as a valid value, this is used to
differentiate between zero and null.
@return Whether the table specified to `it` in <fn:<N>table_begin> has a
next element. @order Amortized on the capacity, \O(1). @allow */
static int N_(table_has_next)(struct N_(table_iterator) *const it) {
assert(it);
return it->_.table && it->_.table->buckets && PN_(skip)(&it->_);
#else /* map --><!-- set */
/** Advances `it`, sets `key` on true. */
static int N_(table_next)(struct N_(table_iterator) *const it, PN_(key) *key) {
struct PN_(bucket) *bucket = PN_(next)(&it->_);
if(!bucket) return 0;
if(key) *key = PN_(bucket_key)(bucket);
return 1;
}
#ifdef TABLE_VALUE /* <!-- value */
/** Defined if `TABLE_VALUE`. Advances `it` only when <fn:<N>table_has_next>.
@return The next key. @allow */
static PN_(key) N_(table_next_key)(struct N_(table_iterator) *const it) {
struct PN_(bucket) *b = PN_(next)(&it->_);
return PN_(bucket_key)(b);
}
/** Defined if `TABLE_VALUE`. Advances `it` only when <fn:<N>table_has_next>.
@return The next value. @allow */
static PN_(value) N_(table_next_value)(struct N_(table_iterator) *const it) {
struct PN_(bucket) *b = PN_(next)(&it->_);
return b->value;
}
#endif /* value --> */
#endif /* set --> */
/** Removes the entry at `it`. Whereas <fn:<N>table_remove> invalidates the
iterator, this corrects for a signal `it`.
@return Success, or there was no entry at the iterator's position, (anymore.)
@ -825,14 +815,15 @@ static void PN_(unused_base)(void) {
PN_(entry) e; PN_(key) k; PN_(value) v;
memset(&e, 0, sizeof e); memset(&k, 0, sizeof k); memset(&v, 0, sizeof v);
PN_(is_element)(0);
N_(table)(); N_(table_)(0); N_(table_begin)(0); N_(table_next)(0, 0);
N_(table)(); N_(table_)(0); N_(table_begin)(0);
N_(table_buffer)(0, 0); N_(table_clear)(0); N_(table_is)(0, k);
N_(table_query)(0, k, 0); N_(table_get_or)(0, k, v); N_(table_try)(0, e);
N_(table_update)(0, e, 0); N_(table_policy)(0,e,0,0);
N_(table_remove)(0, k); N_(table_begin)(0); N_(table_next)(0, 0);
N_(table_has_next)(0); N_(table_iterator_remove)(0);
N_(table_remove)(0, k); N_(table_iterator_remove)(0);
#ifdef TABLE_VALUE
N_(table_assign)(0, k, 0); N_(table_next_key)(0); N_(table_next_value)(0);
N_(table_next)(0, 0, 0); N_(table_assign)(0, k, 0);
#else
N_(table_next)(0, 0);
#endif
PN_(unused_base_coda)();
}