From 82e79efaf2885778d89d69a8a545b00e600365d0 Mon Sep 17 00:00:00 2001 From: Neil Date: Tue, 1 Nov 2022 21:06:43 -0700 Subject: [PATCH] Updated array, tree. --- Makefile | 2 +- src/array.h | 214 +++++++----------- src/interpret.c | 37 ++-- src/lex.re_c.c | 14 +- src/to_string.h | 87 +++++--- src/tree.h | 559 ++++++++++++++++++++---------------------------- 6 files changed, 398 insertions(+), 515 deletions(-) diff --git a/Makefile b/Makefile index 6d899b9..dfaf3a7 100644 --- a/Makefile +++ b/Makefile @@ -74,7 +74,7 @@ gperf := gperf target := # -mwindows optimize := -ffast-math -warnbasic := -Wall -pedantic -ansi # -std=c99 +warnbasic := -Wall -pedantic -std=c11 # Some stuff is really new. warnclang := -Wextra \ -Weverything \ diff --git a/src/array.h b/src/array.h index 616d680..2b0b23d 100644 --- a/src/array.h +++ b/src/array.h @@ -17,48 +17,35 @@ type>, associated therewith; required. `` is private, whose names are prefixed in a manner to avoid collisions. - @param[ARRAY_EXPECT_TRAIT] - Do not un-define certain variables for subsequent inclusion in a parameterized - trait. + @param[ARRAY_COMPARE, ARRAY_IS_EQUAL] + Compare `` trait contained in . Requires + `[]compare` to be declared as compare_fn> or + `[]is_equal` to be declared as bipredicate_fn>, + respectfully, (but not both.) - @param[ARRAY_COMPARE_NAME, ARRAY_COMPARE, ARRAY_IS_EQUAL] - Compare trait contained in . An optional mangled name for - uniqueness and a function implementing either compare_fn> or - bipredicate_fn>. + @param[ARRAY_TO_STRING] + To string `` trait contained in . Requires + `[]to_string` be declared as to_string_fn>. - @param[ARRAY_TO_STRING_NAME, ARRAY_TO_STRING] - To string trait contained in . An optional mangled name for - uniqueness and function implementing to_string_fn>. + @param[ARRAY_EXPECT_TRAIT, ARRAY_TRAIT] + Named traits are obtained by including `array.h` multiple times with + `ARRAY_EXPECT_TRAIT` and then subsequently including the name in + `ARRAY_TRAIT`. @std C89 */ #if !defined(ARRAY_NAME) || !defined(ARRAY_TYPE) -#error Name ARRAY_NAME or tag type ARRAY_TYPE undefined. +#error Name or tag type undefined. #endif -#if defined(ARRAY_TO_STRING_NAME) || defined(ARRAY_TO_STRING) -#define ARRAY_TO_STRING_TRAIT 1 -#else -#define ARRAY_TO_STRING_TRAIT 0 +#if defined(ARRAY_TRAIT) ^ defined(BOX_TYPE) +#error ARRAY_TRAIT name must come after ARRAY_EXPECT_TRAIT. #endif -#if defined(ARRAY_COMPARE_NAME) || defined(ARRAY_COMPARE) \ - || defined(ARRAY_IS_EQUAL) -#define ARRAY_COMPARE_TRAIT 1 -#else -#define ARRAY_COMPARE_TRAIT 0 +#if defined(ARRAY_COMPARE) && defined(ARRAY_IS_EQUAL) +#error Only one can be defined at a time. #endif -#define ARRAY_TRAITS ARRAY_TO_STRING_TRAIT + ARRAY_COMPARE_TRAIT -#if ARRAY_TRAITS > 1 -#error Only one trait per include is allowed; use ARRAY_EXPECT_TRAIT. -#endif -#if ARRAY_TRAITS && !defined(BOX) -#error Trying to define a trait without defining the base datatype. -#endif -#if defined(ARRAY_TO_STRING_NAME) && !defined(ARRAY_TO_STRING) -#error ARRAY_TO_STRING_NAME requires ARRAY_TO_STRING. -#endif -#if defined(ARRAY_COMPARE_NAME) \ - && (!(!defined(ARRAY_COMPARE) ^ !defined(ARRAY_IS_EQUAL))) -#error ARRAY_COMPARE_NAME requires ARRAY_COMPARE or ARRAY_IS_EQUAL not both. +#if defined(ARRAY_TEST) && (!defined(ARRAY_TRAIT) && !defined(ARRAY_TO_STRING) \ + || defined(ARRAY_TRAIT) && !defined(ARRAY_HAS_TO_STRING)) +#error Test requires to string. #endif #ifndef ARRAY_H /* */ +/* Box override information. */ +#define BOX_TYPE struct A_(array) +#define BOX_CONTENT PA_(type) * +#define BOX_ PA_ +#define BOX_MAJOR_NAME array +#define BOX_MINOR_NAME ARRAY_NAME +#define BOX_ACCESS +#define BOX_CONTIGUOUS -#ifdef ARRAY_TEST /* */ +#ifdef HAVE_ITERATE_H /* */ static void PA_(unused_base_coda)(void); static void PA_(unused_base)(void) { - PA_(is_element_c)(0); PA_(forward)(0); PA_(next_c)(0); - PA_(is_element)(0); PA_(remove)(0); PA_(size)(0); PA_(at)(0, 0); - PA_(tell_size)(0, 0); + PA_(null)(); PA_(is_element)(0); PA_(remove)(0); PA_(size)(0); + PA_(at)(0, 0); PA_(tell_size)(0, 0); A_(array)(); A_(array_)(0); - A_(array_iterator)(0); A_(array_iterator_before)(0, 0); + A_(array_iterator)(0); A_(array_iterator_at)(0, 0); A_(array_previous)(0); A_(array_next)(0); A_(array_previous)(0); A_(array_insert)(0, 0, 0); A_(array_new)(0); A_(array_shrink)(0); A_(array_remove)(0, 0); A_(array_lazy_remove)(0, 0); @@ -398,38 +358,29 @@ static void PA_(unused_base)(void) { } static void PA_(unused_base_coda)(void) { PA_(unused_base)(); } - -#elif defined(ARRAY_TO_STRING) /* base code --> */ -#ifdef ARRAY_TO_STRING_NAME -#define STR_(n) ARRAY_CAT(A_(array), ARRAY_CAT(ARRAY_TO_STRING_NAME, n)) -#else -#define STR_(n) ARRAY_CAT(A_(array), n) -#endif -#define TO_STRING ARRAY_TO_STRING +#ifdef ARRAY_TRAIT /* <-- trait: Will be different on different includes. */ +#define BOX_TRAIT_NAME ARRAY_TRAIT +#endif /* trait --> */ + + +#ifdef ARRAY_TO_STRING /* */ -#undef STR_ #undef ARRAY_TO_STRING -#ifdef ARRAY_TO_STRING_NAME -#undef ARRAY_TO_STRING_NAME +#ifndef ARRAY_TRAIT +#define ARRAY_HAS_TO_STRING #endif +#endif /* to string trait --> */ -#else /* to string trait --> */ -#ifdef ARRAY_COMPARE_NAME -#define CMP_(n) ARRAY_CAT(A_(array), ARRAY_CAT(ARRAY_COMPARE_NAME, n)) -#else -#define CMP_(n) ARRAY_CAT(A_(array), n) -#endif +#if defined(ARRAY_COMPARE) || defined(ARRAY_IS_EQUAL) /* */ #include "compare.h" /** \include */ #ifdef ARRAY_TEST /* */ -#undef CMP_ -#ifdef ARRAY_COMPARE_NAME -#undef ARRAY_COMPARE_NAME -#endif +#undef CMP_ /* From . */ +#undef CMPEXTERN_ #ifdef ARRAY_COMPARE #undef ARRAY_COMPARE -#endif -#ifdef ARRAY_IS_EQUAL +#else #undef ARRAY_IS_EQUAL #endif +#endif /* compare trait --> */ -#endif /* traits --> */ - - -#ifdef ARRAY_EXPECT_TRAIT /* */ -#undef ARRAY_TO_STRING_TRAIT -#undef ARRAY_COMPARE_TRAIT -#undef ARRAY_TRAITS +#undef ARRAY_NAME +#undef ARRAY_TYPE +#undef ARRAY_MIN_CAPACITY +#ifdef ARRAY_HAS_TO_STRING +#undef ARRAY_HAS_TO_STRING +#endif +#ifdef ARRAY_TEST +#undef ARRAY_TEST +#endif +#endif /* done --> */ +#ifdef ARRAY_TRAIT +#undef ARRAY_TRAIT +#undef BOX_TRAIT_NAME +#endif #ifdef ARRAY_RESTRICT #undef ARRAY_RESTRICT #undef restrict diff --git a/src/interpret.c b/src/interpret.c index 9c1785d..d872198 100644 --- a/src/interpret.c +++ b/src/interpret.c @@ -17,9 +17,7 @@ static void int_to_string(const int *const n, char (*const a)[12]) { sprintf(*a, "%d", *n); } #define ARRAY_NAME int #define ARRAY_TYPE int -#define ARRAY_EXPECT_TRAIT -#include "array.h" -#define ARRAY_TO_STRING &int_to_string +#define ARRAY_TO_STRING #include "array.h" static int int_cmp(const int *const a, const int *const b) { return (*b < *a) - (*a < *b); } @@ -73,7 +71,8 @@ union date32 { uint32_t u32; struct { unsigned day : 5, month : 4, year : 23; }; }; -static int date_mixup(union date32 a, union date32 b) { return a.u32 > b.u32; } +static int page_compare(const union date32 a, const union date32 b) + { return a.u32 > b.u32; } static void date32_to_string(const union date32 d, char (*const z)[12]) { assert(d.year < 10000 && d.month && d.month <= 31 && d.day && d.day <= 31); sprintf(*z, "%u-%2.2u-%2.2u", d.year % 10000, d.month, d.day); @@ -97,19 +96,19 @@ no: } /** Tomohiko Sakamoto comp.lang.c 1993-04-10. */ -static unsigned weekday(union date32 d) { +/*static unsigned weekday(union date32 d) { d.year -= d.month < 3; return (d.year + d.year / 4 - d.year / 100 + d.year / 400 + "-bed=pen+mad."[d.month] + d.day) % 7; -} +}*/ /* Contained in to share with . */ #define ARRAY_NAME lex #define ARRAY_TYPE struct lex #include "array.h" -struct page_tree_entry_c; -static void entry_to_string(struct page_tree_entry_c, char (*)[12]); +struct page_tree_entry; +static void page_to_string(struct page_tree_entry, char (*)[12]); struct page { struct char_array entry; struct lex_array meaning; @@ -117,12 +116,10 @@ struct page { #define TREE_NAME page #define TREE_KEY union date32 #define TREE_VALUE struct page -#define TREE_COMPARE &date_mixup -#define TREE_EXPECT_TRAIT +#define TREE_COMPARE &page_compare +#define TREE_TO_STRING #include "tree.h" -#define TREE_TO_STRING &entry_to_string -#include "tree.h" -static void entry_to_string(const struct page_tree_entry_c entry, +static void page_to_string(const struct page_tree_entry entry, char (*const z)[12]) { date32_to_string(*entry.key, z); } struct source { char *key, *desc; }; @@ -165,7 +162,7 @@ static int bible_graph(/*const*/ struct page_tree *const journal) { struct page_tree_entry entry = { 0, 0 }; struct lex *lex = 0; size_t count = 0; - for(struct page_tree_iterator p_it = page_tree_iterator(journal); + for(struct page_tree_iterator p_it = page_tree_begin(journal); (entry = page_tree_next(&p_it)).key; ) { struct page *const page = entry.value; for(struct lex_array_iterator l_it = lex_array_iterator(&page->meaning); @@ -218,11 +215,11 @@ catch: return 0; } -#define C_BLACK "\033[0;30m" +/*#define C_BLACK "\033[0;30m" #define C_RED "\033[0;31m" -#define C_GREEN "\033[0;32m" +#define C_GREEN "\033[0;32m"*/ #define C_YELLOW "\033[0;33m" -#define C_BLUE "\033[0;34m" +/*#define C_BLUE "\033[0;34m" #define C_PURPLE "\033[0;35m" #define C_CYAN "\033[0;36m" #define C_WHITE "\033[0;37m" @@ -234,7 +231,7 @@ catch: #define CB_BLUE "\033[1;34m" #define CB_PURPLE "\033[1;35m" #define CB_CYAN "\033[1;36m" -#define CB_WHITE "\033[1;37m" +#define CB_WHITE "\033[1;37m"*/ #define C_RESET "\033[0m" @@ -346,7 +343,7 @@ int main(int argc, char **argv) { (int)(lex->s1 - lex->s0), lex->s0); break; case KJV_CHAPTER_VERSE: printf(" ch. %.*s", (int)(lex->s1 - lex->s0), lex->s0); break; - case KJV_TEXT: printf("%s%.*s", + case KJV_TEXT: printf("%.*s", (int)(lex->s1 - lex->s0), lex->s0); break; case KJV_NEXT: printf("(next)\n"); break; default: @@ -411,7 +408,7 @@ finally: if(dir && closedir(dir)) success = EXIT_FAILURE, perror("dir"); int_array_(&years), int_array_(&months), int_array_(&days); struct page_tree_entry entry; - for(struct page_tree_iterator it = page_tree_iterator(&journal); + for(struct page_tree_iterator it = page_tree_begin(&journal); (entry = page_tree_next(&it)).key; ) { struct page *const page = entry.value; char z[12]; diff --git a/src/lex.re_c.c b/src/lex.re_c.c index 005d27e..39528d1 100644 --- a/src/lex.re_c.c +++ b/src/lex.re_c.c @@ -21,7 +21,7 @@ re2c:define:YYCTYPE = char; int lex_looks_like_year(const char *const a, int *const year) { const char *YYCURSOR = a, *YYMARKER = a, *s0; /*!stags:re2c format = 'const char *@@;\n'; */ - (void)yyt2; + (void)yyt2, (void)yyt3; assert(a && year); /*!re2c @s0 ("-"? [1-9][0-9]* | "0") "\x00" { @@ -43,7 +43,7 @@ int lex_looks_like_year(const char *const a, int *const year) { int lex_looks_like_month(const char *const a) { const char *YYCURSOR = a, *YYMARKER = a, *s0; /*!stags:re2c format = 'const char *@@;\n'; */ - (void)yyt1, (void)yyt2; + (void)yyt1, (void)yyt2, (void)yyt3; assert(a); /*!re2c @s0 [0-1][0-9] "\x00" { @@ -58,7 +58,7 @@ int lex_looks_like_month(const char *const a) { int lex_looks_like_day(const char *const a) { const char *YYCURSOR = a, *YYMARKER = a, *s0; /*!stags:re2c format = 'const char *@@;\n'; */ - (void)yyt1, (void)yyt2; + (void)yyt1, (void)yyt2, (void)yyt3; assert(a); /*!re2c @s0 [0-3][0-9] ".txt\x00" { @@ -85,7 +85,7 @@ int lex_looks_like_day(const char *const a) { concurrent: convenient and bad. */ static struct scan { /* `re2c` variables; these point directly into `buffer`. */ - const char *marker, *ctx_marker, *from, *cursor; + const char *marker, /**ctx_marker,*/ *from, *cursor; /* Weird `c2re` stuff: these fields have to come after when >5? */ const char *label, *buffer; enum condition condition; @@ -100,7 +100,7 @@ static struct scan { /** Resets the buffer to some `buffer`. */ void lex_reset(const char *const buffer) { - scan.marker = scan.ctx_marker = scan.from = scan.cursor = scan.label + scan.marker = /*scan.ctx_marker =*/ scan.from = scan.cursor = scan.label = scan.buffer = buffer; scan.condition = yycline; scan.line = 1; @@ -124,7 +124,7 @@ int lex_next(struct lex *const x) { re2c:flags:tags = 1; re2c:define:YYCURSOR = scan.cursor; re2c:define:YYMARKER = scan.marker; - re2c:define:YYCTXMARKER = scan.ctx_marker; + /*re2c:define:YYCTXMARKER = scan.ctx_marker;*/ re2c:define:YYCONDTYPE = 'condition'; re2c:define:YYGETCONDITION = 'scan.condition'; re2c:define:YYGETCONDITION:naked = 1; @@ -170,7 +170,7 @@ scan: "^" => text { return x->symbol = CANCELLED, 1; } "#" => text { return x->symbol = HEADING, 1; } /* Just plain text. */ - ws* / glyph :=> text /* match-empty-string: text takes care of it. */ + ws* / glyph :=> text /* Match-empty-string: text takes care of it. */ newline => line { x->line = ++scan.line; goto scan; } ws+ { goto scan; } diff --git a/src/to_string.h b/src/to_string.h index c1c74d9..affdc62 100644 --- a/src/to_string.h +++ b/src/to_string.h @@ -3,16 +3,8 @@ @subtitle To string trait - Interface defined by `BOX_`, `BOX`, and `BOX_CONTENT`. - - @param[STR_(n)] - A one-argument macro producing a name that is responsible for the name of the - to string function. Should be something like - `STR_(to_string) -> widget_foo_to_string`. The caller is responsible for - undefining `STR_`. - - @param[TO_STRING] - Function implementing to_string_fn>. + Interface defined by box. Requires `[_]_to_string` be declared as + a to_string_fn>. @param[TO_STRING_LEFT, TO_STRING_RIGHT] 7-bit characters, defaults to '(' and ')'. @@ -27,8 +19,9 @@ @std C89 */ -#if !defined(BOX_) || !defined(BOX) || !defined(BOX_CONTENT) \ - || !defined(STR_) || !defined(TO_STRING) +#if !defined(BOX_TYPE) || !defined(BOX_CONTENT) || !defined(BOX_) \ + || !defined(BOX_MAJOR_NAME) || !defined(BOX_MINOR_NAME) \ + || defined(STR_) || defined(STREXTERN_) #error Unexpected preprocessor symbols. #endif @@ -45,7 +38,7 @@ #define TO_STRING_H #include #if defined(TO_STRING_CAT_) || defined(TO_STRING_CAT) || defined(PSTR_) -#error Unexpected defines. +#error Unexpected preprocessor symbols. #endif /* . */ #define TO_STRING_CAT_(n, m) n ## _ ## m @@ -78,19 +71,39 @@ static unsigned to_string_buffer_i; #define TO_STRING_RIGHT ')' #endif -typedef BOX PSTR_(box); -typedef BOX_CONTENT PSTR_(element_c); +#ifndef BOX_TRAIT_NAME /* */ -/** : responsible for turning the argument into a 12-`char` - null-terminated output string. */ -typedef void (*PSTR_(to_string_fn))(PSTR_(element_c), char (*)[12]); -/* Check that `TO_STRING` is a function implementing - to_string>. */ -static const PSTR_(to_string_fn) PSTR_(to_string) = (TO_STRING); +/* Provides an extra level of indirection for boxes if they need it. */ +#ifndef TO_STRING_THUNK_ +#define TO_STRING_THUNK_(n) n +#endif + +/* Hopefully gets rid of any nestled-qualifiers, but only when appropriate. */ +#ifndef TO_STRING_CAST +#define TO_STRING_CAST (void *) +#endif + +typedef BOX_TYPE PSTR_(box); +typedef BOX_CONTENT PSTR_(element); +typedef const BOX_CONTENT PSTR_(element_c); /* Assumes a lot. */ + +/** : responsible for turning the read-only argument into a + 12-`char` null-terminated output string. The first argument should be a + read-only reference to an element and the second a pointer to the bytes. */ +typedef void (*PSTR_(to_string_fn))(const PSTR_(element), char (*)[12]); +/* _Nb_: this is for documentation only; there is no way to get a general + read-only type which what we are supplied. Think of nested pointers. */ /** : print the contents of `box` in a static string buffer of - 256 bytes, with limitations of only printing 4 things at a time. `` is - loosely contracted to be a name `box[]`. + 256 bytes, with limitations of only printing 4 things at a time. @return Address of the static buffer. @order \Theta(1) @allow */ static const char *STR_(to_string)(const PSTR_(box) *const box) { const char comma = ',', space = ' ', ellipsis[] = "…", @@ -98,25 +111,31 @@ static const char *STR_(to_string)(const PSTR_(box) *const box) { const size_t ellipsis_len = sizeof ellipsis - 1; char *const buffer = to_string_buffers[to_string_buffer_i++], *b = buffer; size_t advance; - PSTR_(element_c) x; - struct BOX_(forward) it; + PSTR_(element) x; + struct BOX_(iterator) it; int is_sep = 0; /* Minimum size: "(" "XXXXXXXXXXX" "," "…" ")" "\0". */ assert(box && !(to_string_buffers_no & (to_string_buffers_no - 1)) && to_string_buffer_size >= 1 + 11 + 1 + ellipsis_len + 1 + 1); /* Advance the buffer for next time. */ to_string_buffer_i &= to_string_buffers_no - 1; - it = BOX_(forward)(box); + { /* We do not modify `box`, but the compiler doesn't know that. */ + PSTR_(box) *promise_box; + memcpy(&promise_box, &box, sizeof box); + it = BOX_(iterator)(promise_box); + } *b++ = left; - while(BOX_(is_element_c)(x = BOX_(next_c)(&it))) { - PSTR_(to_string)(x, (char (*)[12])b); - /* Paranoid about '\0'. */ + while(BOX_(is_element)(x = BOX_(next)(&it))) { + /* One must have this function declared! */ + TO_STRING_THUNK_(STREXTERN_(to_string))(TO_STRING_CAST + x, (char (*)[12])b); + /* Paranoid about '\0'; wastes 1 byte of 12, but otherwise confusing. */ for(advance = 0; *b != '\0' && advance < 11; b++, advance++); is_sep = 1, *b++ = comma, *b++ = space; /* Greedy typesetting: enough for "XXXXXXXXXXX" "," "…" ")" "\0". */ if((size_t)(b - buffer) > to_string_buffer_size - 11 - 1 - ellipsis_len - 1 - 1) { - if(BOX_(is_element_c)(BOX_(next_c)(&it))) goto ellipsis; + if(BOX_(is_element)(BOX_(next)(&it))) goto ellipsis; else break; } } @@ -138,10 +157,10 @@ static void PSTR_(unused_to_string)(void) { STR_(to_string)(0); PSTR_(unused_to_string_coda)(); } static void PSTR_(unused_to_string_coda)(void) { PSTR_(unused_to_string)(); } -#undef TO_STRING -#ifdef TO_STRING_NAME -#undef TO_STRING_NAME -#endif +#undef STR_ +#undef STREXTERN_ +#undef TO_STRING_CAST +#undef TO_STRING_THUNK_ #ifdef TO_STRING_EXTERN #undef TO_STRING_EXTERN #endif diff --git a/src/tree.h b/src/tree.h index 9c9f213..79179ce 100644 --- a/src/tree.h +++ b/src/tree.h @@ -32,46 +32,31 @@ should be okay for most variations. 4 is isomorphic to left-leaning red-black tree, . The above illustration is 5. - @param[TREE_EXPECT_TRAIT] - Do not un-define certain variables for subsequent inclusion in a parameterized - trait. - - @param[TREE_DEFAULT_NAME, TREE_DEFAULT] + @param[TREE_DEFAULT] Default trait; a name that satisfies `C` naming conventions when mangled and a - value> used in treeget>. There can be multiple - defaults, but only one can omit `TREE_DEFAULT_NAME`. + value> used in treeget>. - @param[TREE_TO_STRING_NAME, TREE_TO_STRING] - To string trait contained in ; an optional unique `` - that satisfies `C` naming conventions when mangled and function implementing - to_string_fn>. + @param[TREE_TO_STRING] + To string trait `` contained in . Require + `[]to_string` be declared as to_string_fn>. + + @param[TREE_EXPECT_TRAIT, TREE_TRAIT] + Named traits are obtained by including `tree.h` multiple times with + `TREE_EXPECT_TRAIT` and then subsequently including the name in `TREE_TRAIT`. @fixme merge, difference @std C89 */ #if !defined(TREE_NAME) -#error Name TREE_NAME undefined. +#error Name undefined. #endif -#if defined(TREE_DEFAULT_NAME) || defined(TREE_DEFAULT) -#define TREE_DEFAULT_TRAIT 1 -#else -#define TREE_DEFAULT_TRAIT 0 +#if defined(TREE_TRAIT) ^ defined(BOX_TYPE) +#error TREE_TRAIT name must come after TREE_EXPECT_TRAIT. #endif -#if defined(TREE_TO_STRING_NAME) || defined(TREE_TO_STRING) -#define TREE_TO_STRING_TRAIT 1 -#else -#define TREE_TO_STRING_TRAIT 0 -#endif -#define TREE_TRAITS TREE_DEFAULT_TRAIT + TREE_TO_STRING_TRAIT -#if TREE_TRAITS > 1 -#error Only one trait per include is allowed; use TREE_EXPECT_TRAIT. -#endif -#if defined(TREE_DEFAULT_NAME) && !defined(TREE_DEFAULT) -#error TREE_DEFAULT_NAME requires TREE_DEFAULT. -#endif -#if defined(TREE_TO_STRING_NAME) && !defined(TREE_TO_STRING) -#error TREE_TO_STRING_NAME requires TREE_TO_STRING. +#if defined(TREE_TEST) && (!defined(TREE_TRAIT) && !defined(TREE_TO_STRING) \ + || defined(TREE_TRAIT) && !defined(TREE_HAS_TO_STRING)) +#error Test requires to string. #endif #ifndef TREE_H /* */ -#if TREE_TRAITS == 0 /* */ - /* Check that `TREE_COMPARE` is a function implementing compare_fn>, if defined. */ static const PB_(compare_fn) PB_(compare) = (TREE_COMPARE); @@ -198,7 +180,6 @@ static const struct PB_(branch) *PB_(as_branch_c)(const struct PB_(node) * /* Address of a specific key by node. There is a need for node plus index without height, but we'll just let height be unused. */ struct PB_(ref) { struct PB_(node) *node; unsigned height, idx; }; -struct PB_(ref_c) { const struct PB_(node) *node; unsigned height, idx; }; /* Node plus height is a sub-tree. A tree> is a sub-tree of the tree. */ struct PB_(tree) { struct PB_(node) *node; unsigned height; }; /** To initialize it to an idle state, see tree>, `{0}` (`C99`), or @@ -214,26 +195,15 @@ struct B_(tree) { struct PB_(tree) root; }; pointer-to-value>. The reason these are pointers is because it is not contiguous in memory. */ struct B_(tree_entry) { PB_(key) *key; PB_(value) *value; }; -/* FIXME: are you sure that this doesn't allow you to movify keys? we do not - want modification of keys (right?? otoh, it is the *placement* not the actual - value that is fixed.) */ -struct B_(tree_entry_c) { PB_(key_c) *key; const PB_(value) *value; }; /** On `TREE_VALUE`, otherwise it's just an alias for pointer-to-key>. */ typedef struct B_(tree_entry) PB_(entry); -typedef struct B_(tree_entry_c) PB_(entry_c); static PB_(entry) PB_(null_entry)(void) { const PB_(entry) e = { 0, 0 }; return e; } -static PB_(entry_c) PB_(null_entry_c)(void) - { const PB_(entry_c) e = { 0, 0 }; return e; } /** Constructs entry from `node` and `i`. */ static PB_(entry) PB_(cons_entry)(struct PB_(node) *const node, const unsigned i) { PB_(entry) e; e.key = node->key + i, e.value = node->value + i; return e; } -/** Constructs entry from `node` and `i`. */ -static PB_(entry_c) PB_(cons_entry_c)(const struct PB_(node) *const node, - const unsigned i) { PB_(entry_c) e; - e.key = node->key + i, e.value = node->value + i; return e; } /** Gets the value of `ref`. */ static PB_(value) *PB_(ref_to_valuep)(const struct PB_(ref) ref) { return ref.node ? ref.node->value + ref.idx : 0; } @@ -242,15 +212,10 @@ static PB_(value) *PB_(ref_to_valuep)(const struct PB_(ref) ref) typedef PB_(key) PB_(value); typedef PB_(key) *PB_(entry); -typedef PB_(key_c) *PB_(entry_c); -static PB_(entry_c) PB_(null_entry_c)(void) { return 0; } static PB_(entry) PB_(null_entry)(void) { return 0; } /** Constructs entry from `node` and `i`. */ static PB_(entry) PB_(cons_entry)(struct PB_(node) *const node, const unsigned i) { return node->key + i; } -/** Constructs entry from `node` and `i`. */ -static PB_(entry_c) PB_(cons_entry_c)(const struct PB_(node) *const node, - const unsigned i) { return node->key + i; } /** Gets the value of `ref`. */ static PB_(value) *PB_(ref_to_valuep)(const struct PB_(ref) ref) { return ref.node ? ref.node->key + ref.idx : 0; } @@ -296,69 +261,39 @@ static int PB_(to_predecessor)(struct PB_(tree) tree, *ref = prev; } return 1; /* Jumped nodes. */ } -/* @return If `ref_c` in `tree` has a successor, then it increments. */ -#define TREE_TO_SUCCESSOR(to_successor_c, ref_c) \ -static int PB_(to_successor_c)(struct PB_(tree) tree, \ - struct PB_(ref_c) *const ref) { \ - assert(ref); \ - if(!tree.node || tree.height == UINT_MAX) return 0; /* Empty. */ \ - if(!ref->node) \ - ref->node = tree.node, ref->height = tree.height, ref->idx = 0; \ - else \ - ref->idx++; \ - while(ref->height) ref->height--, \ - ref->node = PB_(as_branch_c)(ref->node)->child[ref->idx], ref->idx = 0; \ - if(ref->idx < ref->node->size) return 1; /* Likely. */ \ - if(!ref->node->size) return 0; /* When bulk-loading. */ \ -{ /* Re-descend; pick the minimum height node that has a next key. */ \ - struct PB_(ref_c) next; \ - unsigned a0; \ - PB_(key) x; \ - for(next.node = 0, x = ref->node->key[ref->node->size - 1]; tree.height; \ - tree.node = PB_(as_branch_c)(tree.node)->child[a0], tree.height--) { \ - unsigned a1 = tree.node->size; \ - a0 = 0; \ - while(a0 < a1) { \ - const unsigned m = (a0 + a1) / 2; \ - if(PB_(compare)(x, tree.node->key[m]) > 0) a0 = m + 1; else a1 = m;\ - } \ - if(a0 < tree.node->size) \ - next.node = tree.node, next.height = tree.height, next.idx = a0; \ - } \ - if(!next.node) return 0; /* Off right. */ \ - *ref = next; \ -} return 1; /* Jumped nodes. */ \ -} -TREE_TO_SUCCESSOR(to_successor, ref) /* For cursor. */ -TREE_TO_SUCCESSOR(to_successor_c, ref_c) /* For forward iteration. */ -#undef TREE_TO_SUCCESSOR - -#define BOX_CONTENT PB_(entry_c) -/** Is `e` not null? @implements `is_element_c` */ -static int PB_(is_element_c)(PB_(entry_c) e) { -#ifdef TREE_VALUE - return !!e.key; -#else - return !!e; -#endif +/** @return If `ref` in `tree` has a successor, then it increments. */ +static int PB_(to_successor)(struct PB_(tree) tree, + struct PB_(ref) *const ref) { + assert(ref); + if(!tree.node || tree.height == UINT_MAX) return 0; /* Empty. */ + if(!ref->node) + ref->node = tree.node, ref->height = tree.height, ref->idx = 0; + else + ref->idx++; + while(ref->height) ref->height--, + ref->node = PB_(as_branch_c)(ref->node)->child[ref->idx], ref->idx = 0; + if(ref->idx < ref->node->size) return 1; /* Likely. */ + if(!ref->node->size) return 0; /* When bulk-loading. */ +{ /* Re-descend; pick the minimum height node that has a next key. */ + struct PB_(ref) next; + unsigned a0; + PB_(key) x; + for(next.node = 0, x = ref->node->key[ref->node->size - 1]; tree.height; + tree.node = PB_(as_branch_c)(tree.node)->child[a0], tree.height--) { + unsigned a1 = tree.node->size; + a0 = 0; + while(a0 < a1) { + const unsigned m = (a0 + a1) / 2; + if(PB_(compare)(x, tree.node->key[m]) > 0) a0 = m + 1; else a1 = m; + } + if(a0 < tree.node->size) + next.node = tree.node, next.height = tree.height, next.idx = a0; + } + if(!next.node) return 0; /* Off right. */ + *ref = next; +} return 1; /* Jumped nodes. */ } -/* @implements `forward` */ -struct PB_(forward) { const struct PB_(tree) *root; struct PB_(ref_c) next; }; - -/** @return Before `tree`, (can be null.) @implements `forward` */ -static struct PB_(forward) PB_(forward)(const struct B_(tree) *const tree) { - struct PB_(forward) it; - it.root = tree ? &tree->root : 0, it.next.node = 0; - return it; -} -/** Move to next `it`. @return Element or null. @implements `next_c` */ -static PB_(entry_c) PB_(next_c)(struct PB_(forward) *const it) { - return assert(it), PB_(to_successor_c)(*it->root, &it->next) ? - PB_(cons_entry_c)(it->next.node, it->next.idx) : PB_(null_entry_c)(); -} - -#define BOX_ITERATOR PB_(entry) /** Is `e` not null? @implements `is_element` */ static int PB_(is_element)(const PB_(entry) e) { #ifdef TREE_VALUE @@ -367,14 +302,11 @@ static int PB_(is_element)(const PB_(entry) e) { return !!e; #endif } - -/* @implements `cursor` */ -struct PB_(cursor) { struct PB_(tree) *root; struct PB_(ref) ref; int seen; }; - -/** Eliminates code-re-use from begin> and end>. +struct PB_(iterator) { struct PB_(tree) *root; struct PB_(ref) ref; int seen; }; +/** Eliminates code-re-use from iterator> and end>. @return Fills `it` and returns if `tree` has contents, in which case, `idx` is uninitialized. */ -static int PB_(cursor_fill_part)(struct PB_(cursor) *const it, +static int PB_(iterator_fill_part)(struct PB_(iterator) *const it, struct B_(tree) *const tree) { assert(it); it->seen = 0; @@ -389,20 +321,21 @@ static int PB_(cursor_fill_part)(struct PB_(cursor) *const it, return 1; } /** @return Before the start of `tree`, (can be null.) @implements `begin` */ -static struct PB_(cursor) PB_(begin)(struct B_(tree) *const tree) { - struct PB_(cursor) it; - if(PB_(cursor_fill_part)(&it, tree)) { +static struct PB_(iterator) PB_(iterator)(struct B_(tree) *const tree) { + struct PB_(iterator) it; + if(PB_(iterator_fill_part)(&it, tree)) { for(it.ref.node = tree->root.node; it.ref.height; - it.ref.node = PB_(as_branch)(it.ref.node)->child[0], it.ref.height--); + it.ref.node = PB_(as_branch)(it.ref.node)->child[0], + it.ref.height--); it.ref.idx = 0; } return it; } /** @return Iterator after the end of `tree`, (can be null.) @implements `end` */ -static struct PB_(cursor) PB_(end)(struct B_(tree) *const tree) { - struct PB_(cursor) it; - if(PB_(cursor_fill_part)(&it, tree)) { +static struct PB_(iterator) PB_(end)(struct B_(tree) *const tree) { + struct PB_(iterator) it; + if(PB_(iterator_fill_part)(&it, tree)) { for(it.ref.node = tree->root.node; it.ref.height; it.ref.node = PB_(as_branch)(it.ref.node)->child[it.ref.node->size], it.ref.height--); @@ -410,9 +343,8 @@ static struct PB_(cursor) PB_(end)(struct B_(tree) *const tree) { } return it; } - /** Advances `it`. @return Element or null. @implements `next` */ -static PB_(entry) PB_(next)(struct PB_(cursor) *const it) { +static PB_(entry) PB_(next)(struct PB_(iterator) *const it) { assert(it); if(!it->root || (it->seen || !it->ref.node) && !PB_(to_successor)(*it->root, &it->ref)) @@ -423,7 +355,7 @@ static PB_(entry) PB_(next)(struct PB_(cursor) *const it) { : (it->seen = 0, PB_(null_entry)()); } /** Move to previous `it`. @return Element or null. @implements `previous` */ -static PB_(entry) PB_(previous)(struct PB_(cursor) *const it) { +static PB_(entry) PB_(previous)(struct PB_(iterator) *const it) { assert(it); if(!it->root || !PB_(to_predecessor)(*it->root, &it->ref)) return it->ref.node = 0, it->seen = 0, PB_(null_entry)(); @@ -534,7 +466,6 @@ static struct PB_(ref) PB_(lookup_remove)(struct PB_(tree) *const tree, #undef TREE_FORNODE #undef TREE_FLIPPED - /** Zeroed data (not all-bits-zero) is initialized. @return An idle tree. @order \Theta(1) @allow */ static struct B_(tree) B_(tree)(void) { @@ -853,7 +784,7 @@ static enum tree_result PB_(update)(struct PB_(tree) *const root, PB_(key) key, PB_(key) *const eject) { #endif /* set --> */ struct PB_(node) *new_head = 0; - struct PB_(ref) add, hole, cursor; + struct PB_(ref) add, hole, iterator; assert(root); if(!(add.node = root->node)) goto idle; else if(root->height == UINT_MAX) goto empty; @@ -937,93 +868,93 @@ grow: /* Leaf is full. */ { new_root->child[0] = root->node, root->node = hole.node; hole.node->size = 1; } - cursor = hole; /* Go down; (as opposed to doing it on paper.) */ + iterator = hole; /* Go down; (as opposed to doing it on paper.) */ goto split; } split: { /* Split between the new and existing nodes. */ struct PB_(node) *sibling; - assert(cursor.node && cursor.node->size && cursor.height); + assert(iterator.node && iterator.node->size && iterator.height); sibling = new_head; /*PB_(graph_usual)(tree, "graph/work.gv");*/ /* Descend now while split hasn't happened -- easier. */ - new_head = --cursor.height ? PB_(as_branch)(new_head)->child[0] : 0; - cursor.node = PB_(as_branch)(cursor.node)->child[cursor.idx]; - PB_(find_idx)(&cursor, key); - assert(!sibling->size && cursor.node->size == TREE_MAX); /* Atomic. */ - /* Expand `cursor`, which is full, to multiple nodes. */ - if(cursor.idx < TREE_SPLIT) { /* Descend hole to `cursor`. */ - memcpy(sibling->key, cursor.node->key + TREE_SPLIT, + new_head = --iterator.height ? PB_(as_branch)(new_head)->child[0] : 0; + iterator.node = PB_(as_branch)(iterator.node)->child[iterator.idx]; + PB_(find_idx)(&iterator, key); + assert(!sibling->size && iterator.node->size == TREE_MAX); /* Atomic. */ + /* Expand `iterator`, which is full, to multiple nodes. */ + if(iterator.idx < TREE_SPLIT) { /* Descend hole to `iterator`. */ + memcpy(sibling->key, iterator.node->key + TREE_SPLIT, sizeof *sibling->key * (TREE_MAX - TREE_SPLIT)); #ifdef TREE_VALUE - memcpy(sibling->value, cursor.node->value + TREE_SPLIT, + memcpy(sibling->value, iterator.node->value + TREE_SPLIT, sizeof *sibling->value * (TREE_MAX - TREE_SPLIT)); #endif - hole.node->key[hole.idx] = cursor.node->key[TREE_SPLIT - 1]; + hole.node->key[hole.idx] = iterator.node->key[TREE_SPLIT - 1]; #ifdef TREE_VALUE - hole.node->value[hole.idx] = cursor.node->value[TREE_SPLIT - 1]; + hole.node->value[hole.idx] = iterator.node->value[TREE_SPLIT - 1]; #endif - memmove(cursor.node->key + cursor.idx + 1, - cursor.node->key + cursor.idx, - sizeof *cursor.node->key * (TREE_SPLIT - 1 - cursor.idx)); + memmove(iterator.node->key + iterator.idx + 1, + iterator.node->key + iterator.idx, + sizeof *iterator.node->key * (TREE_SPLIT - 1 - iterator.idx)); #ifdef TREE_VALUE - memmove(cursor.node->value + cursor.idx + 1, - cursor.node->value + cursor.idx, - sizeof *cursor.node->value * (TREE_SPLIT - 1 - cursor.idx)); + memmove(iterator.node->value + iterator.idx + 1, + iterator.node->value + iterator.idx, + sizeof *iterator.node->value * (TREE_SPLIT - 1 - iterator.idx)); #endif - if(cursor.height) { - struct PB_(branch) *const cb = PB_(as_branch)(cursor.node), + if(iterator.height) { + struct PB_(branch) *const cb = PB_(as_branch)(iterator.node), *const sb = PB_(as_branch)(sibling); struct PB_(node) *temp = sb->child[0]; memcpy(sb->child, cb->child + TREE_SPLIT, sizeof *cb->child * (TREE_MAX - TREE_SPLIT + 1)); - memmove(cb->child + cursor.idx + 2, cb->child + cursor.idx + 1, - sizeof *cb->child * (TREE_SPLIT - 1 - cursor.idx)); - cb->child[cursor.idx + 1] = temp; + memmove(cb->child + iterator.idx + 2, cb->child + iterator.idx + 1, + sizeof *cb->child * (TREE_SPLIT - 1 - iterator.idx)); + cb->child[iterator.idx + 1] = temp; } - hole = cursor; - } else if(cursor.idx > TREE_SPLIT) { /* Descend hole to `sibling`. */ - hole.node->key[hole.idx] = cursor.node->key[TREE_SPLIT]; + hole = iterator; + } else if(iterator.idx > TREE_SPLIT) { /* Descend hole to `sibling`. */ + hole.node->key[hole.idx] = iterator.node->key[TREE_SPLIT]; #ifdef TREE_VALUE - hole.node->value[hole.idx] = cursor.node->value[TREE_SPLIT]; + hole.node->value[hole.idx] = iterator.node->value[TREE_SPLIT]; #endif - hole.node = sibling, hole.height = cursor.height, - hole.idx = cursor.idx - TREE_SPLIT - 1; - memcpy(sibling->key, cursor.node->key + TREE_SPLIT + 1, + hole.node = sibling, hole.height = iterator.height, + hole.idx = iterator.idx - TREE_SPLIT - 1; + memcpy(sibling->key, iterator.node->key + TREE_SPLIT + 1, sizeof *sibling->key * hole.idx); - memcpy(sibling->key + hole.idx + 1, cursor.node->key + cursor.idx, - sizeof *sibling->key * (TREE_MAX - cursor.idx)); + memcpy(sibling->key + hole.idx + 1, iterator.node->key + iterator.idx, + sizeof *sibling->key * (TREE_MAX - iterator.idx)); #ifdef TREE_VALUE - memcpy(sibling->value, cursor.node->value + TREE_SPLIT + 1, + memcpy(sibling->value, iterator.node->value + TREE_SPLIT + 1, sizeof *sibling->value * hole.idx); - memcpy(sibling->value + hole.idx + 1, cursor.node->value + cursor.idx, - sizeof *sibling->value * (TREE_MAX - cursor.idx)); + memcpy(sibling->value + hole.idx + 1, iterator.node->value + iterator.idx, + sizeof *sibling->value * (TREE_MAX - iterator.idx)); #endif - if(cursor.height) { - struct PB_(branch) *const cb = PB_(as_branch)(cursor.node), + if(iterator.height) { + struct PB_(branch) *const cb = PB_(as_branch)(iterator.node), *const sb = PB_(as_branch)(sibling); struct PB_(node) *temp = sb->child[0]; memcpy(sb->child, cb->child + TREE_SPLIT + 1, sizeof *cb->child * (hole.idx + 1)); - memcpy(sb->child + hole.idx + 2, cb->child + cursor.idx + 1, - sizeof *cb->child * (TREE_MAX - cursor.idx)); + memcpy(sb->child + hole.idx + 2, cb->child + iterator.idx + 1, + sizeof *cb->child * (TREE_MAX - iterator.idx)); sb->child[hole.idx + 1] = temp; } } else { /* Equal split: leave the hole where it is. */ - memcpy(sibling->key, cursor.node->key + TREE_SPLIT, + memcpy(sibling->key, iterator.node->key + TREE_SPLIT, sizeof *sibling->key * (TREE_MAX - TREE_SPLIT)); #ifdef TREE_VALUE - memcpy(sibling->value, cursor.node->value + TREE_SPLIT, + memcpy(sibling->value, iterator.node->value + TREE_SPLIT, sizeof *sibling->value * (TREE_MAX - TREE_SPLIT)); #endif - if(cursor.height) { - struct PB_(branch) *const cb = PB_(as_branch)(cursor.node), + if(iterator.height) { + struct PB_(branch) *const cb = PB_(as_branch)(iterator.node), *const sb = PB_(as_branch)(sibling); memcpy(sb->child + 1, cb->child + TREE_SPLIT + 1, sizeof *cb->child * (TREE_MAX - TREE_SPLIT)); } } /* Divide `TREE_MAX + 1` into two trees. */ - cursor.node->size = TREE_SPLIT, sibling->size = TREE_MAX - TREE_SPLIT; - if(cursor.height) goto split; /* Loop max `\log_{TREE_MIN} size`. */ + iterator.node->size = TREE_SPLIT, sibling->size = TREE_MAX - TREE_SPLIT; + if(iterator.height) goto split; /* Loop max `\log_{TREE_MIN} size`. */ hole.node->key[hole.idx] = key; #ifdef TREE_VALUE if(value) *value = PB_(ref_to_valuep)(hole); @@ -1391,7 +1322,7 @@ struct PB_(scaffold) { struct tree_node_count victim, source; size_t no; struct PB_(node) **data; - struct { struct PB_(node) **head, **fresh, **cursor; } branch, leaf; + struct { struct PB_(node) **head, **fresh, **iterator; } branch, leaf; }; /** Counts the nodes `no` in `tree` for nodes>. */ static int PB_(nodes_r)(struct PB_(tree) tree, @@ -1431,15 +1362,15 @@ static int PB_(nodes)(const struct B_(tree) *const tree, static void PB_(cannibalize_r)(struct PB_(ref) ref, struct PB_(scaffold) *const sc) { struct PB_(branch) *branch = PB_(as_branch)(ref.node); - const int keep_branch = sc->branch.cursor < sc->branch.fresh; + const int keep_branch = sc->branch.iterator < sc->branch.fresh; assert(ref.node && ref.height && sc); - if(keep_branch) *sc->branch.cursor = ref.node, sc->branch.cursor++; + if(keep_branch) *sc->branch.iterator = ref.node, sc->branch.iterator++; if(ref.height == 1) { /* Children are leaves. */ unsigned n; for(n = 0; n <= ref.node->size; n++) { - const int keep_leaf = sc->leaf.cursor < sc->leaf.fresh; + const int keep_leaf = sc->leaf.iterator < sc->leaf.fresh; struct PB_(node) *child = branch->child[n]; - if(keep_leaf) *sc->leaf.cursor = child, sc->leaf.cursor++; + if(keep_leaf) *sc->leaf.iterator = child, sc->leaf.iterator++; else free(child); } } else while(ref.idx <= ref.node->size) { @@ -1461,12 +1392,12 @@ static void PB_(cannibalize)(const struct B_(tree) *const tree, if(!sc->victim.branches && !sc->victim.leaves) return; assert(tree->root.node); ref.node = tree->root.node, ref.height = tree->root.height, ref.idx = 0; - sc->branch.cursor = sc->branch.head; - sc->leaf.cursor = sc->leaf.head; + sc->branch.iterator = sc->branch.head; + sc->leaf.iterator = sc->leaf.head; if(ref.height) { PB_(cannibalize_r)(ref, sc); } else { /* Just one leaf. */ - *sc->leaf.cursor = ref.node; + *sc->leaf.iterator = ref.node; } } /** Do the work of `src` cloned with `sc`. Called from clone>. */ @@ -1475,7 +1406,7 @@ static struct PB_(node) *PB_(clone_r)(struct PB_(tree) src, struct PB_(node) *node; if(src.height) { struct PB_(branch) *const srcb = PB_(as_branch)(src.node), - *const branch = PB_(as_branch)(node = *sc->branch.cursor++); + *const branch = PB_(as_branch)(node = *sc->branch.iterator++); unsigned i; struct PB_(tree) child; *node = *src.node; /* Copy node. */ @@ -1485,7 +1416,7 @@ static struct PB_(node) *PB_(clone_r)(struct PB_(tree) src, branch->child[i] = PB_(clone_r)(child, sc); } } else { /* Leaves. */ - node = *sc->leaf.cursor++; + node = *sc->leaf.iterator++; *node = *src.node; } return node; @@ -1496,13 +1427,13 @@ static struct PB_(tree) PB_(clone)(const struct PB_(tree) *const src, struct PB_(tree) sub; assert(src && src->node && sc); /* Go back to the beginning of the scaffold and pick off one by one. */ - sc->branch.cursor = sc->branch.head; - sc->leaf.cursor = sc->leaf.head; + sc->branch.iterator = sc->branch.head; + sc->leaf.iterator = sc->leaf.head; sub.node = PB_(clone_r)(*src, sc); sub.height = src->height; /* Used up all of them. No concurrent modifications, please. */ - assert(sc->branch.cursor == sc->leaf.head - && sc->leaf.cursor == sc->data + sc->no); + assert(sc->branch.iterator == sc->leaf.head + && sc->leaf.iterator == sc->data + sc->no); return sub; } /** `source` is copied to, and overwrites, `tree`. @@ -1536,26 +1467,26 @@ static int B_(tree_clone)(struct B_(tree) *const tree, need.branches = sc.source.branches > sc.victim.branches ? sc.source.branches - sc.victim.branches : 0; sc.branch.head = sc.data; - sc.branch.fresh = sc.branch.cursor + sc.branch.fresh = sc.branch.iterator = sc.branch.head + sc.source.branches - need.branches; sc.leaf.head = sc.branch.fresh + need.branches; - sc.leaf.fresh = sc.leaf.cursor + sc.leaf.fresh = sc.leaf.iterator = sc.leaf.head + sc.source.leaves - need.leaves; assert(sc.leaf.fresh + need.leaves == sc.data + sc.no); } /* Add new nodes. */ - while(sc.branch.cursor != sc.leaf.head) { + while(sc.branch.iterator != sc.leaf.head) { struct PB_(branch) *branch; if(!(branch = malloc(sizeof *branch))) goto catch; branch->base.size = 0; branch->child[0] = 0; - *sc.branch.cursor++ = &branch->base; + *sc.branch.iterator++ = &branch->base; } - while(sc.leaf.cursor != sc.data + sc.no) { + while(sc.leaf.iterator != sc.data + sc.no) { struct PB_(node) *leaf; if(!(leaf = malloc(sizeof *leaf))) goto catch; leaf->size = 0; - *sc.leaf.cursor++ = leaf; + *sc.leaf.iterator++ = leaf; } /* Resources acquired; now we don't care about tree. */ PB_(cannibalize)(tree, &sc); @@ -1565,13 +1496,13 @@ static int B_(tree_clone)(struct B_(tree) *const tree, catch: success = 0; if(!sc.data) goto finally; - while(sc.leaf.cursor != sc.leaf.fresh) { - struct PB_(node) *leaf = *(--sc.leaf.cursor); + while(sc.leaf.iterator != sc.leaf.fresh) { + struct PB_(node) *leaf = *(--sc.leaf.iterator); assert(leaf); free(leaf); } - while(sc.branch.cursor != sc.branch.fresh) { - struct PB_(branch) *branch = PB_(as_branch)(*(--sc.branch.cursor)); + while(sc.branch.iterator != sc.branch.fresh) { + struct PB_(branch) *branch = PB_(as_branch)(*(--sc.branch.iterator)); assert(branch); free(branch); } @@ -1581,27 +1512,22 @@ finally: } -/* Box override information. */ -#define BOX_ PB_ -#define BOX struct B_(tree) - - /** Adding, deleting, or changes in the topology of the tree invalidate it. */ -struct B_(tree_cursor); -struct B_(tree_cursor) { struct PB_(cursor) _; }; +struct B_(tree_iterator); +struct B_(tree_iterator) { struct PB_(iterator) _; }; /** @return Cursor before the first element of `tree`. Can be null. @order \Theta(\log |`tree`|) @allow */ -static struct B_(tree_cursor) B_(tree_begin)(struct B_(tree) *const tree) - { struct B_(tree_cursor) cur; cur._ = PB_(begin)(tree); return cur; } +static struct B_(tree_iterator) B_(tree_begin)(struct B_(tree) *const tree) + { struct B_(tree_iterator) it; it._ = PB_(iterator)(tree); return it; } /** @param[tree] Can be null. @return Cursor in `tree` between elements, such that if tree_next> is called, it will be smallest key that is not smaller than `x`, or, tree_end> if `x` is greater than all in `tree`. @order \Theta(\log |`tree`|) @allow */ -static struct B_(tree_cursor) B_(tree_begin_at)(struct B_(tree) *const tree, +static struct B_(tree_iterator) B_(tree_begin_at)(struct B_(tree) *const tree, const PB_(key) x) { - struct B_(tree_cursor) cur; + struct B_(tree_iterator) cur; if(!tree) return cur._.root = 0, cur; cur._.ref = PB_(lower)(tree->root, x); cur._.root = &tree->root; @@ -1610,65 +1536,67 @@ static struct B_(tree_cursor) B_(tree_begin_at)(struct B_(tree) *const tree, } /** @return Cursor after the last element of `tree`. Can be null. @order \Theta(\log |`tree`|) @allow */ -static struct B_(tree_cursor) B_(tree_end)(struct B_(tree) *const tree) - { struct B_(tree_cursor) cur; cur._ = PB_(end)(tree); return cur; } +static struct B_(tree_iterator) B_(tree_end)(struct B_(tree) *const tree) + { struct B_(tree_iterator) cur; cur._ = PB_(end)(tree); return cur; } /** Advances `cur` to the next element. @return A pointer to the current element, or null if it ran out of elements. The type is either a set pointer-to-key or a map tree_entry> (with `TREE_VALUE`, both fields are null if null). @order \O(\log |`tree`|) @allow */ -static PB_(entry) B_(tree_next)(struct B_(tree_cursor) *const cur) +static PB_(entry) B_(tree_next)(struct B_(tree_iterator) *const cur) { return PB_(next)(&cur->_); } /** Reverses `cur` to the previous element. @return A pointer to the previous element, or null if it ran out of elements. The type is either a set pointer-to-key or a map tree_entry> (with `TREE_VALUE`, both fields are null if null). @order \O(\log |`tree`|) @allow */ -static PB_(entry) B_(tree_previous)(struct B_(tree_cursor) *const cur) +static PB_(entry) B_(tree_previous)(struct B_(tree_iterator) *const cur) { return PB_(previous)(&cur->_); } #ifdef TREE_VALUE /* */ - enum { NONODE, ITERATING, END } where; + enum { TREE_NONODE, TREE_ITERATING, TREE_END } where; PB_(key) anchor; enum tree_result ret; memset(&anchor, 0, sizeof anchor); /* Silence warnings. */ - if(!cur || !cur->_.root) return TREE_ERROR; /* No tree. */ - if(cur->_.ref.node && cur->_.root->height != UINT_MAX) { - where = (cur->_.ref.idx < cur->_.ref.node->size) ? ITERATING : END; + if(!it || !it->_.root) return TREE_ERROR; /* No tree. */ + if(it->_.ref.node && it->_.root->height != UINT_MAX) { + where = (it->_.ref.idx < it->_.ref.node->size) + ? TREE_ITERATING : TREE_END; } else { - where = NONODE; + where = TREE_NONODE; } - if(where == ITERATING) anchor = cur->_.ref.node->key[cur->_.ref.idx]; - if(where == NONODE || where == END) cur->_.seen = 0; /* Should be already. */ + if(where == TREE_ITERATING) anchor = it->_.ref.node->key[it->_.ref.idx]; + /* Should be already. */ + if(where == TREE_NONODE || where == TREE_END) it->_.seen = 0; #ifdef TREE_VALUE - ret = PB_(update)(cur->_.root, key, 0, value); + ret = PB_(update)(it->_.root, key, 0, value); #else - ret = PB_(update)(cur->_.root, key, 0); + ret = PB_(update)(it->_.root, key, 0); #endif if(ret == TREE_ERROR) return TREE_ERROR; - assert(cur->_.root->height != UINT_MAX); /* Can't be empty. */ + assert(it->_.root->height != UINT_MAX); /* Can't be empty. */ switch(where) { - case NONODE: cur->_.ref.node = 0; cur->_.seen = 0; break; - case ITERATING: cur->_.ref = PB_(lower)(*cur->_.root, anchor); break; - case END: - assert(cur->_.root->node); - cur->_.ref.node = cur->_.root->node; - cur->_.ref.height = cur->_.root->height; - cur->_.ref.idx = cur->_.root->node->size; - while(cur->_.ref.height) { - cur->_.ref.node - = PB_(as_branch_c)(cur->_.ref.node)->child[cur->_.ref.idx]; - cur->_.ref.idx = cur->_.ref.node->size; - cur->_.ref.height--; + case TREE_NONODE: it->_.ref.node = 0; it->_.seen = 0; break; + case TREE_ITERATING: it->_.ref = PB_(lower)(*it->_.root, anchor); break; + case TREE_END: + assert(it->_.root->node); + it->_.ref.node = it->_.root->node; + it->_.ref.height = it->_.root->height; + it->_.ref.idx = it->_.root->node->size; + while(it->_.ref.height) { + it->_.ref.node + = PB_(as_branch_c)(it->_.ref.node)->child[it->_.ref.idx]; + it->_.ref.idx = it->_.ref.node->size; + it->_.ref.height--; } - cur->_.seen = 0; + it->_.seen = 0; break; } return ret; @@ -1678,68 +1606,86 @@ static enum tree_result B_(tree_cursor_try)(struct B_(tree_cursor) *const } #endif -/** Removes the last entry returned by a valid `cur`. All other cursors on the +/** Removes the last entry returned by a valid `it`. All other iterators on the same object are invalidated, but `cur` is now between on the removed node. - @return Success, otherwise `cur` is not at a valid element. + @return Success, otherwise `it` is not at a valid element. @order \Theta(\log |`tree`|) */ -static int B_(tree_cursor_remove)(struct B_(tree_cursor) *const cur) { +static int B_(tree_iterator_remove)(struct B_(tree_iterator) *const it) { PB_(key) remove; - if(!cur || !cur->_.seen || !cur->_.root || !cur->_.ref.node - || cur->_.root->height == UINT_MAX - || cur->_.ref.idx >= cur->_.ref.node->size - || (remove = cur->_.ref.node->key[cur->_.ref.idx], - !PB_(remove)(cur->_.root, remove))) return 0; + if(!it || !it->_.seen || !it->_.root || !it->_.ref.node + || it->_.root->height == UINT_MAX + || it->_.ref.idx >= it->_.ref.node->size + || (remove = it->_.ref.node->key[it->_.ref.idx], + !PB_(remove)(it->_.root, remove))) return 0; /* tree_begin_at>. */ - cur->_.ref = PB_(lower)(*cur->_.root, remove); - cur->_.seen = 0; + it->_.ref = PB_(lower)(*it->_.root, remove); + it->_.seen = 0; return 1; } -#ifdef TREE_TEST /* */ - - static void PB_(unused_base_coda)(void); static void PB_(unused_base)(void) { PB_(key) k; PB_(value) v; memset(&k, 0, sizeof k); memset(&v, 0, sizeof v); - PB_(is_element_c); PB_(forward); PB_(next_c); PB_(is_element); + PB_(is_element); B_(tree)(); B_(tree_)(0); B_(tree_clear)(0); B_(tree_count)(0); B_(tree_contains)(0, k); B_(tree_get_or)(0, k, v); B_(tree_at_or)(0, k, v); #ifdef TREE_VALUE B_(tree_bulk_add)(0, k, 0); B_(tree_try)(0, k, 0); - B_(tree_assign)(0, k, 0, 0); B_(tree_cursor_try)(0, k, 0); + B_(tree_assign)(0, k, 0, 0); B_(tree_iterator_try)(0, k, 0); #else B_(tree_bulk_add)(0, k); B_(tree_try)(0, k); - B_(tree_assign)(0, k, 0); B_(tree_cursor_try)(0, k); + B_(tree_assign)(0, k, 0); B_(tree_iterator_try)(0, k); #endif B_(tree_bulk_finish)(0); B_(tree_remove)(0, k); B_(tree_clone)(0, 0); B_(tree_begin)(0); B_(tree_begin_at)(0, k); B_(tree_end)(0); B_(tree_previous)(0); B_(tree_next)(0); - B_(tree_cursor_remove)(0); + B_(tree_iterator_remove)(0); PB_(unused_base_coda)(); } static void PB_(unused_base_coda)(void) { PB_(unused_base)(); } +/* Box override information. */ +#define BOX_TYPE struct B_(tree) +#define BOX_CONTENT PB_(entry) +#define BOX_ PB_ +#define BOX_MAJOR_NAME tree +#define BOX_MINOR_NAME TREE_NAME -#elif defined(TREE_DEFAULT) /* base code --> */ -#ifdef TREE_DEFAULT_NAME -#define B_D_(n, m) TREE_CAT(B_(n), TREE_CAT(TREE_DEFAULT_NAME, m)) +#ifdef TREE_TRAIT /* <-- trait: Will be different on different includes. */ +#define BOX_TRAIT_NAME TREE_TRAIT +#endif /* trait --> */ + + +#ifdef TREE_TO_STRING /* */ + + +#if defined(TREE_TEST) && !defined(TREE_TRAIT) /* */ + + +#ifdef TREE_DEFAULT /* */ -#elif defined(TREE_TO_STRING) /* default --> */ -#undef STR_ -#undef TREE_TO_STRING -#ifdef TREE_TO_STRING_NAME -#undef TREE_TO_STRING_NAME -#endif - - -#endif /* traits --> */ - - -#ifdef TREE_EXPECT_TRAIT /* */ -#undef TREE_DEFAULT_TRAIT -#undef TREE_TO_STRING_TRAIT -#undef TREE_TRAITS +#endif /* done --> */ +#ifdef TREE_TRAIT +#undef TREE_TRAIT +#undef BOX_TRAIT_NAME +#endif