LCOV - code coverage report
Current view: top level - source/tree_map.c (source / functions) Coverage Total Hit
Test: CCC Test Suite Coverage Report Lines: 98.6 % 649 640
Test Date: 2026-04-02 00:15:37 Functions: 100.0 % 70 70

            Line data    Source code
       1              : /** Copyright 2025 Alexander G. Lopez
       2              : 
       3              : Licensed under the Apache License, Version 2.0 (the "License");
       4              : you may not use this file except in compliance with the License.
       5              : You may obtain a copy of the License at
       6              : 
       7              :    http://www.apache.org/licenses/LICENSE-2.0
       8              : 
       9              : Unless required by applicable law or agreed to in writing, software
      10              : distributed under the License is distributed on an "AS IS" BASIS,
      11              : WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      12              : See the License for the specific language governing permissions and
      13              : limitations under the License.
      14              : 
      15              : This file contains my implementation of a realtime ordered map. The added
      16              : realtime prefix is to indicate that this map meets specific run time bounds
      17              : that can be relied upon consistently. This is may not be the case if a map
      18              : is implemented with some self-optimizing data structure like a Splay Tree.
      19              : 
      20              : This map, however, pmapises O(lg N) search, insert, and remove as a true
      21              : upper bound, inclusive. This is achieved through a Weak AVL (WAVL) tree
      22              : that is derived from the following two sources.
      23              : 
      24              : [1] Bernhard Haeupler, Siddhartha Sen, and Robert E. Tarjan, 2014.
      25              : Rank-Balanced Trees, J.ACM Transactions on Algorithms 11, 4, Article 0
      26              : (June 2015), 24 pages.
      27              : https://sidsen.azurewebsites.net//papers/rb-trees-talg.pdf
      28              : 
      29              : [2] Phil Vachon (pvachon) https://github.com/pvachon/wavl_tree
      30              : This implementation is heavily influential throughout. However there have
      31              : been some major adjustments and simplifications. Namely, the allocation has
      32              : been adjusted to accommodate this library's ability to be an allocating or
      33              : non-allocating container. All left-right symmetric cases have been united
      34              : into one and I chose to tackle rotations and deletions slightly differently,
      35              : shortening the code significantly. A few other changes and improvements
      36              : suggested by the authors of the original paper are implemented. See the required
      37              : license at the bottom of the file for BSD-2-Clause compliance.
      38              : 
      39              : Overall a WAVL tree is quite impressive for it's simplicity and purported
      40              : improvements over AVL and Red-Black trees. The rank framework is intuitive
      41              : and flexible in how it can be implemented.
      42              : 
      43              : Excuse the mathematical variable naming in the WAVL implementation. It is
      44              : easiest to check work against the research paper if we use the exact same names
      45              : that appear in the paper. We could choose to describe the nodes in terms of
      46              : their tree lineage but that changes with rotations so a symbolic representation
      47              : is fine. */
      48              : /** C23 provided headers. */
      49              : #include <stddef.h>
      50              : 
      51              : /** CCC provided headers. */
      52              : #include "ccc/configuration.h"
      53              : #include "ccc/private/private_tree_map.h"
      54              : #include "ccc/tree_map.h"
      55              : #include "ccc/types.h"
      56              : 
      57              : /** @internal */
      58              : enum Link {
      59              :     L = 0,
      60              :     R,
      61              : };
      62              : 
      63              : #define INORDER R
      64              : #define INORDER_REVERSE L
      65              : 
      66              : /** @internal This will utilize safe type punning in C. Both union fields have
      67              : the same type and when obtaining an entry we either have the desired element
      68              : or its parent. Preserving the known parent is what makes the Entry Interface
      69              : No further look ups are required for insertions, modification, or removal. */
      70              : struct Query {
      71              :     CCC_Order last_order;
      72              :     union {
      73              :         struct CCC_Tree_map_node *found;
      74              :         struct CCC_Tree_map_node *parent;
      75              :     };
      76              : };
      77              : 
      78              : /*==============================  Prototypes   ==============================*/
      79              : 
      80              : static void init_node(struct CCC_Tree_map *, struct CCC_Tree_map_node *);
      81              : static CCC_Order order(
      82              :     struct CCC_Tree_map const *, void const *, struct CCC_Tree_map_node const *
      83              : );
      84              : static void *
      85              : struct_base(struct CCC_Tree_map const *, struct CCC_Tree_map_node const *);
      86              : static struct Query find(struct CCC_Tree_map const *, void const *);
      87              : static void swap(void *, void *, void *, size_t);
      88              : static void *maybe_allocate_insert(
      89              :     struct CCC_Tree_map *,
      90              :     struct CCC_Tree_map_node *,
      91              :     CCC_Order,
      92              :     struct CCC_Tree_map_node *,
      93              :     CCC_Allocator const *
      94              : );
      95              : static void *remove_fixup(struct CCC_Tree_map *, struct CCC_Tree_map_node *);
      96              : static void insert_fixup(
      97              :     struct CCC_Tree_map *,
      98              :     struct CCC_Tree_map_node *,
      99              :     struct CCC_Tree_map_node *
     100              : );
     101              : static void transplant(
     102              :     struct CCC_Tree_map *,
     103              :     struct CCC_Tree_map_node *,
     104              :     struct CCC_Tree_map_node *
     105              : );
     106              : static CCC_Tribool parity(struct CCC_Tree_map_node const *);
     107              : static void rebalance_3_child(
     108              :     struct CCC_Tree_map *,
     109              :     struct CCC_Tree_map_node *,
     110              :     struct CCC_Tree_map_node *
     111              : );
     112              : static CCC_Tribool
     113              : is_0_child(struct CCC_Tree_map_node const *, struct CCC_Tree_map_node const *);
     114              : static CCC_Tribool
     115              : is_1_child(struct CCC_Tree_map_node const *, struct CCC_Tree_map_node const *);
     116              : static CCC_Tribool
     117              : is_2_child(struct CCC_Tree_map_node const *, struct CCC_Tree_map_node const *);
     118              : static CCC_Tribool
     119              : is_3_child(struct CCC_Tree_map_node const *, struct CCC_Tree_map_node const *);
     120              : static CCC_Tribool is_01_parent(
     121              :     struct CCC_Tree_map_node const *,
     122              :     struct CCC_Tree_map_node const *,
     123              :     struct CCC_Tree_map_node const *
     124              : );
     125              : static CCC_Tribool is_11_parent(
     126              :     struct CCC_Tree_map_node const *,
     127              :     struct CCC_Tree_map_node const *,
     128              :     struct CCC_Tree_map_node const *
     129              : );
     130              : static CCC_Tribool is_02_parent(
     131              :     struct CCC_Tree_map_node const *,
     132              :     struct CCC_Tree_map_node const *,
     133              :     struct CCC_Tree_map_node const *
     134              : );
     135              : static CCC_Tribool is_22_parent(
     136              :     struct CCC_Tree_map_node const *,
     137              :     struct CCC_Tree_map_node const *,
     138              :     struct CCC_Tree_map_node const *
     139              : );
     140              : static CCC_Tribool is_leaf(struct CCC_Tree_map_node const *);
     141              : static struct CCC_Tree_map_node *sibling_of(struct CCC_Tree_map_node const *);
     142              : static void promote(struct CCC_Tree_map_node *);
     143              : static void demote(struct CCC_Tree_map_node *);
     144              : static void double_promote(struct CCC_Tree_map_node *);
     145              : static void double_demote(struct CCC_Tree_map_node *);
     146              : 
     147              : static void rotate(
     148              :     struct CCC_Tree_map *,
     149              :     struct CCC_Tree_map_node *,
     150              :     struct CCC_Tree_map_node *,
     151              :     struct CCC_Tree_map_node *,
     152              :     enum Link
     153              : );
     154              : static void double_rotate(
     155              :     struct CCC_Tree_map *,
     156              :     struct CCC_Tree_map_node *,
     157              :     struct CCC_Tree_map_node *,
     158              :     struct CCC_Tree_map_node *,
     159              :     enum Link
     160              : );
     161              : static CCC_Tribool validate(struct CCC_Tree_map const *);
     162              : static struct CCC_Tree_map_node *
     163              : next(struct CCC_Tree_map const *, struct CCC_Tree_map_node const *, enum Link);
     164              : static struct CCC_Tree_map_node *
     165              : min_max_from(struct CCC_Tree_map_node *, enum Link);
     166              : static CCC_Range
     167              : equal_range(struct CCC_Tree_map const *, void const *, void const *, enum Link);
     168              : static struct CCC_Tree_map_entry
     169              : entry(struct CCC_Tree_map const *, void const *);
     170              : static void *insert(
     171              :     struct CCC_Tree_map *,
     172              :     struct CCC_Tree_map_node *,
     173              :     CCC_Order,
     174              :     struct CCC_Tree_map_node *
     175              : );
     176              : static void *
     177              : key_from_node(struct CCC_Tree_map const *, struct CCC_Tree_map_node const *);
     178              : static void *key_in_slot(struct CCC_Tree_map const *, void const *);
     179              : static struct CCC_Tree_map_node *
     180              : elem_in_slot(struct CCC_Tree_map const *, void const *);
     181              : 
     182              : /*==============================  Interface    ==============================*/
     183              : 
     184              : CCC_Tribool
     185          102 : CCC_tree_map_contains(CCC_Tree_map const *const map, void const *const key) {
     186          102 :     if (!map || !key) {
     187            2 :         return CCC_TRIBOOL_ERROR;
     188              :     }
     189          100 :     return CCC_ORDER_EQUAL == find(map, key).last_order;
     190          102 : }
     191              : 
     192              : void *
     193           17 : CCC_tree_map_get_key_value(
     194              :     CCC_Tree_map const *const map, void const *const key
     195              : ) {
     196           17 :     if (!map || !key) {
     197            2 :         return NULL;
     198              :     }
     199           15 :     struct Query const q = find(map, key);
     200           15 :     return (CCC_ORDER_EQUAL == q.last_order) ? struct_base(map, q.found) : NULL;
     201           17 : }
     202              : 
     203              : CCC_Entry
     204         1012 : CCC_tree_map_swap_entry(
     205              :     CCC_Tree_map *const map,
     206              :     CCC_Tree_map_node *const type_intruder,
     207              :     CCC_Tree_map_node *const temp_intruder,
     208              :     CCC_Allocator const *const allocator
     209              : ) {
     210         1012 :     if (!map || !type_intruder || !allocator || !temp_intruder) {
     211            4 :         return (CCC_Entry){.status = CCC_ENTRY_ARGUMENT_ERROR};
     212              :     }
     213         1008 :     struct Query const q = find(map, key_from_node(map, type_intruder));
     214         1008 :     if (CCC_ORDER_EQUAL == q.last_order) {
     215           94 :         *type_intruder = *q.found;
     216           94 :         void *const found = struct_base(map, q.found);
     217           94 :         void *const any_struct = struct_base(map, type_intruder);
     218           94 :         void *const old_val = struct_base(map, temp_intruder);
     219           94 :         swap(old_val, found, any_struct, map->sizeof_type);
     220          188 :         type_intruder->branch[L] = type_intruder->branch[R]
     221          188 :             = type_intruder->parent = NULL;
     222          188 :         temp_intruder->branch[L] = temp_intruder->branch[R]
     223          188 :             = temp_intruder->parent = NULL;
     224          188 :         return (CCC_Entry){
     225           94 :             .type = old_val,
     226              :             .status = CCC_ENTRY_OCCUPIED,
     227              :         };
     228           94 :     }
     229          914 :     if (!maybe_allocate_insert(
     230          914 :             map, q.parent, q.last_order, type_intruder, allocator
     231              :         )) {
     232            1 :         return (CCC_Entry){
     233              :             .type = NULL,
     234              :             .status = CCC_ENTRY_INSERT_ERROR,
     235              :         };
     236              :     }
     237          913 :     return (CCC_Entry){
     238              :         .type = NULL,
     239              :         .status = CCC_ENTRY_VACANT,
     240              :     };
     241         1012 : }
     242              : 
     243              : CCC_Entry
     244          110 : CCC_tree_map_try_insert(
     245              :     CCC_Tree_map *const map,
     246              :     CCC_Tree_map_node *const type_intruder,
     247              :     CCC_Allocator const *const allocator
     248              : ) {
     249          110 :     if (!map || !type_intruder || !allocator) {
     250            3 :         return (CCC_Entry){.status = CCC_ENTRY_ARGUMENT_ERROR};
     251              :     }
     252          107 :     struct Query const q = find(map, key_from_node(map, type_intruder));
     253          107 :     if (CCC_ORDER_EQUAL == q.last_order) {
     254          106 :         return (CCC_Entry){
     255           53 :             .type = struct_base(map, q.found),
     256              :             .status = CCC_ENTRY_OCCUPIED,
     257              :         };
     258              :     }
     259          108 :     void *const inserted = maybe_allocate_insert(
     260           54 :         map, q.parent, q.last_order, type_intruder, allocator
     261              :     );
     262           54 :     if (!inserted) {
     263            1 :         return (CCC_Entry){
     264              :             .type = NULL,
     265              :             .status = CCC_ENTRY_INSERT_ERROR,
     266              :         };
     267              :     }
     268          106 :     return (CCC_Entry){
     269           53 :         .type = inserted,
     270              :         .status = CCC_ENTRY_VACANT,
     271              :     };
     272          110 : }
     273              : 
     274              : CCC_Entry
     275          251 : CCC_tree_map_insert_or_assign(
     276              :     CCC_Tree_map *const map,
     277              :     CCC_Tree_map_node *const type_intruder,
     278              :     CCC_Allocator const *const allocator
     279              : ) {
     280          251 :     if (!map || !type_intruder || !allocator) {
     281            3 :         return (CCC_Entry){.status = CCC_ENTRY_ARGUMENT_ERROR};
     282              :     }
     283          248 :     struct Query const q = find(map, key_from_node(map, type_intruder));
     284          248 :     if (CCC_ORDER_EQUAL == q.last_order) {
     285            3 :         void *const found = struct_base(map, q.found);
     286            3 :         *type_intruder = *elem_in_slot(map, found);
     287            3 :         memcpy(found, struct_base(map, type_intruder), map->sizeof_type);
     288            6 :         return (CCC_Entry){
     289            3 :             .type = found,
     290              :             .status = CCC_ENTRY_OCCUPIED,
     291              :         };
     292            3 :     }
     293          490 :     void *const inserted = maybe_allocate_insert(
     294          245 :         map, q.parent, q.last_order, type_intruder, allocator
     295              :     );
     296          245 :     if (!inserted) {
     297            1 :         return (CCC_Entry){
     298              :             .type = NULL,
     299              :             .status = CCC_ENTRY_INSERT_ERROR,
     300              :         };
     301              :     }
     302          488 :     return (CCC_Entry){
     303          244 :         .type = inserted,
     304              :         .status = CCC_ENTRY_VACANT,
     305              :     };
     306          251 : }
     307              : 
     308              : CCC_Tree_map_entry
     309         1202 : CCC_tree_map_entry(CCC_Tree_map const *const map, void const *const key) {
     310         1202 :     if (!map || !key) {
     311            4 :         return (CCC_Tree_map_entry){
     312            2 :             .entry = {.status = CCC_ENTRY_ARGUMENT_ERROR},
     313              :         };
     314              :     }
     315         1200 :     return entry(map, key);
     316         1202 : }
     317              : 
     318              : void *
     319          263 : CCC_tree_map_or_insert(
     320              :     CCC_Tree_map_entry const *const entry,
     321              :     CCC_Tree_map_node *const type_intruder,
     322              :     CCC_Allocator const *const allocator
     323              : ) {
     324          263 :     if (!entry || !type_intruder || !allocator) {
     325            3 :         return NULL;
     326              :     }
     327          260 :     if (entry->entry.status == CCC_ENTRY_OCCUPIED) {
     328          153 :         return entry->entry.type;
     329              :     }
     330          107 :     return maybe_allocate_insert(
     331          107 :         entry->map,
     332          107 :         elem_in_slot(entry->map, entry->entry.type),
     333          107 :         entry->last_order,
     334          107 :         type_intruder,
     335          107 :         allocator
     336              :     );
     337          263 : }
     338              : 
     339              : void *
     340          336 : CCC_tree_map_insert_entry(
     341              :     CCC_Tree_map_entry const *const entry,
     342              :     CCC_Tree_map_node *const type_intruder,
     343              :     CCC_Allocator const *const allocator
     344              : ) {
     345          336 :     if (!entry || !type_intruder || !allocator) {
     346            3 :         return NULL;
     347              :     }
     348          333 :     if (entry->entry.status == CCC_ENTRY_OCCUPIED) {
     349          103 :         *type_intruder = *elem_in_slot(entry->map, entry->entry.type);
     350          103 :         memcpy(
     351          103 :             entry->entry.type,
     352          103 :             struct_base(entry->map, type_intruder),
     353          103 :             entry->map->sizeof_type
     354              :         );
     355          103 :         return entry->entry.type;
     356              :     }
     357          230 :     return maybe_allocate_insert(
     358          230 :         entry->map,
     359          230 :         elem_in_slot(entry->map, entry->entry.type),
     360          230 :         entry->last_order,
     361          230 :         type_intruder,
     362          230 :         allocator
     363              :     );
     364          336 : }
     365              : 
     366              : CCC_Entry
     367          222 : CCC_tree_map_remove_entry(
     368              :     CCC_Tree_map_entry const *const entry, CCC_Allocator const *const allocator
     369              : ) {
     370          222 :     if (!entry || !allocator) {
     371            2 :         return (CCC_Entry){.status = CCC_ENTRY_ARGUMENT_ERROR};
     372              :     }
     373          220 :     if (entry->entry.status == CCC_ENTRY_OCCUPIED) {
     374          420 :         void *const erased = remove_fixup(
     375          210 :             entry->map, elem_in_slot(entry->map, entry->entry.type)
     376              :         );
     377          210 :         assert(erased);
     378          210 :         if (allocator->allocate) {
     379          462 :             allocator->allocate((CCC_Allocator_arguments){
     380          154 :                 .input = erased,
     381              :                 .bytes = 0,
     382          154 :                 .context = allocator->context,
     383              :             });
     384          154 :             return (CCC_Entry){
     385              :                 .type = NULL,
     386              :                 .status = CCC_ENTRY_OCCUPIED,
     387              :             };
     388              :         }
     389          112 :         return (CCC_Entry){
     390           56 :             .type = erased,
     391              :             .status = CCC_ENTRY_OCCUPIED,
     392              :         };
     393          210 :     }
     394           10 :     return (CCC_Entry){
     395              :         .type = NULL,
     396              :         .status = CCC_ENTRY_VACANT,
     397              :     };
     398          222 : }
     399              : 
     400              : CCC_Entry
     401          197 : CCC_tree_map_remove_key_value(
     402              :     CCC_Tree_map *const map,
     403              :     CCC_Tree_map_node *const type_output_intruder,
     404              :     CCC_Allocator const *const allocator
     405              : ) {
     406          197 :     if (!map || !type_output_intruder || !allocator) {
     407            3 :         return (CCC_Entry){.status = CCC_ENTRY_ARGUMENT_ERROR};
     408              :     }
     409          194 :     struct Query const q = find(map, key_from_node(map, type_output_intruder));
     410          194 :     if (q.last_order != CCC_ORDER_EQUAL) {
     411            3 :         return (CCC_Entry){
     412              :             .type = NULL,
     413              :             .status = CCC_ENTRY_VACANT,
     414              :         };
     415              :     }
     416          191 :     void *const removed = remove_fixup(map, q.found);
     417          191 :     if (allocator->allocate) {
     418           75 :         void *const any_struct = struct_base(map, type_output_intruder);
     419           75 :         memcpy(any_struct, removed, map->sizeof_type);
     420          225 :         allocator->allocate((CCC_Allocator_arguments){
     421           75 :             .input = removed,
     422              :             .bytes = 0,
     423           75 :             .context = allocator->context,
     424              :         });
     425          150 :         return (CCC_Entry){
     426           75 :             .type = any_struct,
     427              :             .status = CCC_ENTRY_OCCUPIED,
     428              :         };
     429           75 :     }
     430          232 :     return (CCC_Entry){
     431          116 :         .type = removed,
     432              :         .status = CCC_ENTRY_OCCUPIED,
     433              :     };
     434          197 : }
     435              : 
     436              : CCC_Tree_map_entry *
     437          112 : CCC_tree_map_and_modify(
     438              :     CCC_Tree_map_entry *e, CCC_Modifier const *const modifier
     439              : ) {
     440          112 :     if (!e || !modifier) {
     441            2 :         return NULL;
     442              :     }
     443          110 :     if (modifier->modify && e->entry.status & CCC_ENTRY_OCCUPIED
     444          110 :         && e->entry.type) {
     445          168 :         modifier->modify((CCC_Arguments){
     446           56 :             .type = e->entry.type,
     447           56 :             .context = modifier->context,
     448              :         });
     449           56 :     }
     450          110 :     return e;
     451          112 : }
     452              : 
     453              : void *
     454           26 : CCC_tree_map_unwrap(CCC_Tree_map_entry const *const e) {
     455           26 :     if (e && e->entry.status & CCC_ENTRY_OCCUPIED) {
     456           15 :         return e->entry.type;
     457              :     }
     458           11 :     return NULL;
     459           26 : }
     460              : 
     461              : CCC_Tribool
     462          119 : CCC_tree_map_occupied(CCC_Tree_map_entry const *const e) {
     463          119 :     if (!e) {
     464            1 :         return CCC_TRIBOOL_ERROR;
     465              :     }
     466          118 :     return (e->entry.status & CCC_ENTRY_OCCUPIED) != 0;
     467          119 : }
     468              : 
     469              : CCC_Tribool
     470            2 : CCC_tree_map_insert_error(CCC_Tree_map_entry const *const e) {
     471            2 :     if (!e) {
     472            1 :         return CCC_TRIBOOL_ERROR;
     473              :     }
     474            1 :     return (e->entry.status & CCC_ENTRY_INSERT_ERROR) != 0;
     475            2 : }
     476              : 
     477              : CCC_Entry_status
     478            2 : CCC_tree_map_entry_status(CCC_Tree_map_entry const *const e) {
     479            2 :     return e ? e->entry.status : CCC_ENTRY_ARGUMENT_ERROR;
     480              : }
     481              : 
     482              : void *
     483           10 : CCC_tree_map_begin(CCC_Tree_map const *map) {
     484           10 :     if (!map) {
     485            1 :         return NULL;
     486              :     }
     487            9 :     struct CCC_Tree_map_node *const m = min_max_from(map->root, L);
     488            9 :     return m == NULL ? NULL : struct_base(map, m);
     489           10 : }
     490              : 
     491              : void *
     492          454 : CCC_tree_map_next(
     493              :     CCC_Tree_map const *const map,
     494              :     CCC_Tree_map_node const *const iterator_intruder
     495              : ) {
     496          454 :     if (!map || !iterator_intruder) {
     497            2 :         return NULL;
     498              :     }
     499          904 :     struct CCC_Tree_map_node const *const n
     500          452 :         = next(map, iterator_intruder, INORDER);
     501          452 :     if (n == NULL) {
     502            9 :         return NULL;
     503              :     }
     504          443 :     return struct_base(map, n);
     505          454 : }
     506              : 
     507              : void *
     508            4 : CCC_tree_map_reverse_begin(CCC_Tree_map const *const map) {
     509            4 :     if (!map) {
     510            1 :         return NULL;
     511              :     }
     512            3 :     struct CCC_Tree_map_node *const m = min_max_from(map->root, R);
     513            3 :     return m == NULL ? NULL : struct_base(map, m);
     514            4 : }
     515              : 
     516              : void *
     517          261 : CCC_tree_map_end(CCC_Tree_map const *const) {
     518          261 :     return NULL;
     519              : }
     520              : 
     521              : void *
     522          124 : CCC_tree_map_reverse_end(CCC_Tree_map const *const) {
     523          124 :     return NULL;
     524              : }
     525              : 
     526              : void *
     527          146 : CCC_tree_map_reverse_next(
     528              :     CCC_Tree_map const *const map,
     529              :     CCC_Tree_map_node const *const iterator_intruder
     530              : ) {
     531          146 :     if (!map || !iterator_intruder) {
     532            2 :         return NULL;
     533              :     }
     534          288 :     struct CCC_Tree_map_node const *const n
     535          144 :         = next(map, iterator_intruder, INORDER_REVERSE);
     536          144 :     return (n == NULL) ? NULL : struct_base(map, n);
     537          146 : }
     538              : 
     539              : CCC_Range
     540            8 : CCC_tree_map_equal_range(
     541              :     CCC_Tree_map const *const map,
     542              :     void const *const begin_key,
     543              :     void const *const end_key
     544              : ) {
     545            8 :     if (!map || !begin_key || !end_key) {
     546            3 :         return (CCC_Range){};
     547              :     }
     548            5 :     return equal_range(map, begin_key, end_key, INORDER);
     549            8 : }
     550              : 
     551              : CCC_Range_reverse
     552            8 : CCC_tree_map_equal_range_reverse(
     553              :     CCC_Tree_map const *const map,
     554              :     void const *const reverse_begin_key,
     555              :     void const *const reverse_end_key
     556              : ) {
     557            8 :     if (!map || !reverse_begin_key || !reverse_end_key) {
     558            3 :         return (CCC_Range_reverse){};
     559              :     }
     560            5 :     CCC_Range const range
     561            5 :         = equal_range(map, reverse_begin_key, reverse_end_key, INORDER_REVERSE);
     562           15 :     return (CCC_Range_reverse){
     563            5 :         .reverse_begin = range.begin,
     564            5 :         .reverse_end = range.end,
     565              :     };
     566            8 : }
     567              : 
     568              : CCC_Count
     569          123 : CCC_tree_map_count(CCC_Tree_map const *const map) {
     570          123 :     if (!map) {
     571            1 :         return (CCC_Count){.error = CCC_RESULT_ARGUMENT_ERROR};
     572              :     }
     573          122 :     return (CCC_Count){.count = map->count};
     574          123 : }
     575              : 
     576              : CCC_Tribool
     577            7 : CCC_tree_map_is_empty(CCC_Tree_map const *const map) {
     578            7 :     if (!map) {
     579            1 :         return CCC_TRIBOOL_ERROR;
     580              :     }
     581            6 :     return !map->count;
     582            7 : }
     583              : 
     584              : CCC_Tribool
     585         1928 : CCC_tree_map_validate(CCC_Tree_map const *map) {
     586         1928 :     if (!map) {
     587            1 :         return CCC_TRIBOOL_ERROR;
     588              :     }
     589         1927 :     return validate(map);
     590         1928 : }
     591              : 
     592              : /** This is a linear time constant space deletion of tree nodes via left
     593              : rotations so element fields are modified during progression of deletes. */
     594              : CCC_Result
     595           16 : CCC_tree_map_clear(
     596              :     CCC_Tree_map *const map,
     597              :     CCC_Destructor const *const destructor,
     598              :     CCC_Allocator const *const allocator
     599              : ) {
     600           16 :     if (!map || !destructor || !allocator) {
     601            3 :         return CCC_RESULT_ARGUMENT_ERROR;
     602              :     }
     603           13 :     struct CCC_Tree_map_node *node = map->root;
     604         1129 :     while (node != NULL) {
     605         1116 :         if (node->branch[L] != NULL) {
     606          530 :             struct CCC_Tree_map_node *const left = node->branch[L];
     607          530 :             node->branch[L] = left->branch[R];
     608          530 :             left->branch[R] = node;
     609          530 :             node = left;
     610              :             continue;
     611          530 :         }
     612          586 :         struct CCC_Tree_map_node *const next = node->branch[R];
     613          586 :         node->branch[L] = node->branch[R] = NULL;
     614          586 :         node->parent = NULL;
     615          586 :         void *const type = struct_base(map, node);
     616          586 :         if (destructor->destroy) {
     617           48 :             destructor->destroy((CCC_Arguments){
     618           16 :                 .type = type,
     619           16 :                 .context = destructor->context,
     620              :             });
     621           16 :         }
     622          586 :         if (allocator->allocate) {
     623         1758 :             (void)allocator->allocate((CCC_Allocator_arguments){
     624          586 :                 .input = type,
     625              :                 .bytes = 0,
     626          586 :                 .context = allocator->context,
     627              :             });
     628          586 :         }
     629          586 :         node = next;
     630          586 :     }
     631           13 :     return CCC_RESULT_OK;
     632           16 : }
     633              : 
     634              : /*=========================   Private Interface  ============================*/
     635              : 
     636              : struct CCC_Tree_map_entry
     637           98 : CCC_private_tree_map_entry(
     638              :     struct CCC_Tree_map const *const map, void const *const key
     639              : ) {
     640           98 :     return entry(map, key);
     641           98 : }
     642              : 
     643              : void *
     644          196 : CCC_private_tree_map_insert(
     645              :     struct CCC_Tree_map *const map,
     646              :     struct CCC_Tree_map_node *const parent,
     647              :     CCC_Order const last_order,
     648              :     struct CCC_Tree_map_node *const type_output_intruder
     649              : ) {
     650          196 :     return insert(map, parent, last_order, type_output_intruder);
     651              : }
     652              : 
     653              : void *
     654           87 : CCC_private_tree_map_key_in_slot(
     655              :     struct CCC_Tree_map const *const map, void const *const slot
     656              : ) {
     657           87 :     return key_in_slot(map, slot);
     658              : }
     659              : 
     660              : struct CCC_Tree_map_node *
     661          410 : CCC_private_tree_map_node_in_slot(
     662              :     struct CCC_Tree_map const *const map, void const *const slot
     663              : ) {
     664          410 :     return elem_in_slot(map, slot);
     665              : }
     666              : 
     667              : /*=========================    Static Helpers    ============================*/
     668              : 
     669              : static struct CCC_Tree_map_node *
     670          159 : min_max_from(struct CCC_Tree_map_node *start, enum Link const dir) {
     671          159 :     if (start == NULL) {
     672            1 :         return start;
     673              :     }
     674          362 :     for (; start->branch[dir] != NULL; start = start->branch[dir]) {}
     675          158 :     return start;
     676          159 : }
     677              : 
     678              : static struct CCC_Tree_map_entry
     679         1298 : entry(struct CCC_Tree_map const *const map, void const *const key) {
     680         1298 :     struct Query const q = find(map, key);
     681         1298 :     if (CCC_ORDER_EQUAL == q.last_order) {
     682         2776 :         return (struct CCC_Tree_map_entry){
     683          694 :             .map = (struct CCC_Tree_map *)map,
     684          694 :             .last_order = q.last_order,
     685         1388 :             .entry = {
     686          694 :                 .type = struct_base(map, q.found),
     687              :                 .status = CCC_ENTRY_OCCUPIED,
     688              :             },
     689              :         };
     690              :     }
     691         2416 :     return (struct CCC_Tree_map_entry){
     692          604 :         .map = (struct CCC_Tree_map *)map,
     693          604 :         .last_order = q.last_order,
     694         1208 :         .entry = {
     695          604 :             .type = struct_base(map, q.parent),
     696              :             .status = CCC_ENTRY_VACANT | CCC_ENTRY_NO_UNWRAP,
     697              :         },
     698              :     };
     699         1298 : }
     700              : 
     701              : static void *
     702         1550 : maybe_allocate_insert(
     703              :     struct CCC_Tree_map *const map,
     704              :     struct CCC_Tree_map_node *const parent,
     705              :     CCC_Order const last_order,
     706              :     struct CCC_Tree_map_node *type_output_intruder,
     707              :     CCC_Allocator const *const allocator
     708              : ) {
     709         1550 :     if (allocator->allocate) {
     710         4122 :         void *const new = allocator->allocate((CCC_Allocator_arguments){
     711              :             .input = NULL,
     712         1374 :             .bytes = map->sizeof_type,
     713         1374 :             .context = allocator->context,
     714              :         });
     715         1374 :         if (!new) {
     716            5 :             return NULL;
     717              :         }
     718         1369 :         memcpy(new, struct_base(map, type_output_intruder), map->sizeof_type);
     719         1369 :         type_output_intruder = elem_in_slot(map, new);
     720         1374 :     }
     721         1545 :     return insert(map, parent, last_order, type_output_intruder);
     722         1550 : }
     723              : 
     724              : static void *
     725         1741 : insert(
     726              :     struct CCC_Tree_map *const map,
     727              :     struct CCC_Tree_map_node *const parent,
     728              :     CCC_Order const last_order,
     729              :     struct CCC_Tree_map_node *const type_output_intruder
     730              : ) {
     731         1741 :     init_node(map, type_output_intruder);
     732         1741 :     if (!map->count) {
     733           46 :         map->root = type_output_intruder;
     734           46 :         ++map->count;
     735           46 :         return struct_base(map, type_output_intruder);
     736              :     }
     737         1695 :     assert(last_order == CCC_ORDER_GREATER || last_order == CCC_ORDER_LESSER);
     738         1695 :     CCC_Tribool rank_rule_break = CCC_FALSE;
     739         1695 :     if (parent) {
     740              :         rank_rule_break
     741         1695 :             = parent->branch[L] == NULL && parent->branch[R] == NULL;
     742         1695 :         parent->branch[CCC_ORDER_GREATER == last_order] = type_output_intruder;
     743         1695 :     }
     744         1695 :     type_output_intruder->parent = parent;
     745         1695 :     if (rank_rule_break) {
     746         1498 :         insert_fixup(map, parent, type_output_intruder);
     747         1498 :     }
     748         1695 :     ++map->count;
     749         1695 :     return struct_base(map, type_output_intruder);
     750         1741 : }
     751              : 
     752              : static struct Query
     753         2986 : find(struct CCC_Tree_map const *const map, void const *const key) {
     754         2986 :     struct CCC_Tree_map_node const *parent = NULL;
     755         2986 :     struct Query q = {
     756              :         .last_order = CCC_ORDER_ERROR,
     757         2986 :         .found = map->root,
     758              :     };
     759        15751 :     while (q.found != NULL) {
     760        13860 :         q.last_order = order(map, key, q.found);
     761        13860 :         if (CCC_ORDER_EQUAL == q.last_order) {
     762         1095 :             return q;
     763              :         }
     764        12765 :         parent = q.found;
     765        12765 :         q.found = q.found->branch[CCC_ORDER_GREATER == q.last_order];
     766              :     }
     767              :     /* Type punning here OK as both union members have same type and size. */
     768         1891 :     q.parent = (struct CCC_Tree_map_node *)parent;
     769         1891 :     return q;
     770         2986 : }
     771              : 
     772              : static struct CCC_Tree_map_node *
     773          603 : next(
     774              :     struct CCC_Tree_map const *const map [[maybe_unused]],
     775              :     struct CCC_Tree_map_node const *n,
     776              :     enum Link const traversal
     777              : ) {
     778          603 :     if (!n) {
     779            0 :         return NULL;
     780              :     }
     781          603 :     assert(map->root->parent == NULL);
     782          603 :     if (n->branch[traversal]) {
     783              :         /* The goal is to get far left/right ASAP in any traversal. */
     784          522 :         for (n = n->branch[traversal]; n->branch[!traversal];
     785          213 :              n = n->branch[!traversal]) {}
     786          309 :         return (struct CCC_Tree_map_node *)n;
     787              :     }
     788          600 :     for (; n->parent && n->parent->branch[!traversal] != n; n = n->parent) {}
     789          294 :     return n->parent;
     790          603 : }
     791              : 
     792              : static CCC_Range
     793           10 : equal_range(
     794              :     struct CCC_Tree_map const *const map,
     795              :     void const *const begin_key,
     796              :     void const *const end_key,
     797              :     enum Link const traversal
     798              : ) {
     799           10 :     if (!map->count) {
     800            2 :         return (CCC_Range){};
     801              :     }
     802            8 :     CCC_Order const les_or_grt[2] = {CCC_ORDER_LESSER, CCC_ORDER_GREATER};
     803            8 :     struct Query b = find(map, begin_key);
     804            8 :     if (b.last_order == les_or_grt[traversal]) {
     805            2 :         b.found = next(map, b.found, traversal);
     806            2 :     }
     807            8 :     struct Query e = find(map, end_key);
     808            8 :     if (e.last_order != les_or_grt[!traversal]) {
     809            5 :         e.found = next(map, e.found, traversal);
     810            5 :     }
     811           24 :     return (CCC_Range){
     812            8 :         .begin = b.found == NULL ? NULL : struct_base(map, b.found),
     813            8 :         .end = e.found == NULL ? NULL : struct_base(map, e.found),
     814              :     };
     815           10 : }
     816              : 
     817              : static inline void
     818         1741 : init_node(
     819              :     struct CCC_Tree_map *const map [[maybe_unused]],
     820              :     struct CCC_Tree_map_node *const e
     821              : ) {
     822         1741 :     assert(e != NULL);
     823         1741 :     assert(map != NULL);
     824         1741 :     e->branch[L] = e->branch[R] = e->parent = NULL;
     825         1741 :     e->parity = 0;
     826         1741 : }
     827              : 
     828              : static inline void
     829           94 : swap(void *const temp, void *const a, void *const b, size_t const sizeof_type) {
     830           94 :     if (a == b || !a || !b) {
     831            0 :         return;
     832              :     }
     833           94 :     (void)memcpy(temp, a, sizeof_type);
     834           94 :     (void)memcpy(a, b, sizeof_type);
     835           94 :     (void)memcpy(b, temp, sizeof_type);
     836          188 : }
     837              : 
     838              : static inline CCC_Order
     839       125237 : order(
     840              :     struct CCC_Tree_map const *const map,
     841              :     void const *const key,
     842              :     struct CCC_Tree_map_node const *const node
     843              : ) {
     844       500948 :     return map->comparator.compare((CCC_Key_comparator_arguments){
     845       125237 :         .key_left = key,
     846       125237 :         .type_right = struct_base(map, node),
     847       125237 :         .context = map->comparator.context,
     848              :     });
     849              : }
     850              : 
     851              : static inline void *
     852       244699 : struct_base(
     853              :     struct CCC_Tree_map const *const map,
     854              :     struct CCC_Tree_map_node const *const e
     855              : ) {
     856       244699 :     return e ? ((char *)e->branch) - map->type_intruder_offset : NULL;
     857              : }
     858              : 
     859              : static inline void *
     860       112934 : key_from_node(
     861              :     struct CCC_Tree_map const *const map,
     862              :     struct CCC_Tree_map_node const *const node
     863              : ) {
     864       112934 :     return node ? (char *)struct_base(map, node) + map->key_offset : NULL;
     865              : }
     866              : 
     867              : static inline void *
     868           87 : key_in_slot(struct CCC_Tree_map const *const map, void const *const slot) {
     869           87 :     return slot ? (char *)slot + map->key_offset : NULL;
     870              : }
     871              : 
     872              : static inline struct CCC_Tree_map_node *
     873         2432 : elem_in_slot(struct CCC_Tree_map const *const map, void const *const slot) {
     874         2432 :     return slot ? (struct CCC_Tree_map_node *)((char *)slot
     875         2413 :                                                + map->type_intruder_offset)
     876              :                 : NULL;
     877              : }
     878              : 
     879              : /*=======================   WAVL Tree Maintenance   =========================*/
     880              : 
     881              : /** Follows the specification in the "Rank-Balanced Trees" paper by Haeupler,
     882              : Sen, and Tarjan (Fig. 2. pg 7). Assumes x's parent z is not null. */
     883              : static void
     884         1498 : insert_fixup(
     885              :     struct CCC_Tree_map *const map,
     886              :     struct CCC_Tree_map_node *z,
     887              :     struct CCC_Tree_map_node *x
     888              : ) {
     889         1498 :     assert(z);
     890         1498 :     do {
     891         2780 :         promote(z);
     892         2780 :         x = z;
     893         2780 :         z = z->parent;
     894         2780 :         if (z == NULL) {
     895          186 :             return;
     896              :         }
     897         2594 :     } while (is_01_parent(x, z, sibling_of(x)));
     898              : 
     899         1312 :     if (!is_02_parent(x, z, sibling_of(x))) {
     900          336 :         return;
     901              :     }
     902          976 :     assert(x != NULL);
     903          976 :     assert(is_0_child(z, x));
     904          976 :     enum Link const p_to_x_dir = z->branch[R] == x;
     905          976 :     struct CCC_Tree_map_node *const y = x->branch[!p_to_x_dir];
     906          976 :     if (y == NULL || is_2_child(z, y)) {
     907          877 :         rotate(map, z, x, y, !p_to_x_dir);
     908          877 :         demote(z);
     909          877 :     } else {
     910           99 :         assert(is_1_child(z, y));
     911           99 :         double_rotate(map, z, x, y, p_to_x_dir);
     912           99 :         promote(y);
     913           99 :         demote(x);
     914           99 :         demote(z);
     915              :     }
     916         2474 : }
     917              : 
     918              : static void *
     919          401 : remove_fixup(
     920              :     struct CCC_Tree_map *const map, struct CCC_Tree_map_node *const remove
     921              : ) {
     922          401 :     struct CCC_Tree_map_node *y = NULL;
     923          401 :     struct CCC_Tree_map_node *x = NULL;
     924          401 :     struct CCC_Tree_map_node *p_of_xy = NULL;
     925          401 :     CCC_Tribool two_child = CCC_FALSE;
     926          401 :     if (remove->branch[L] == NULL || remove->branch[R] == NULL) {
     927          254 :         y = remove;
     928          254 :         p_of_xy = y->parent;
     929          254 :         x = y->branch[y->branch[L] == NULL];
     930          254 :         if (x) {
     931           92 :             x->parent = y->parent;
     932           92 :         }
     933          254 :         if (p_of_xy == NULL) {
     934           10 :             map->root = x;
     935           10 :         } else {
     936          244 :             p_of_xy->branch[p_of_xy->branch[R] == y] = x;
     937              :         }
     938          254 :         two_child = is_2_child(p_of_xy, y);
     939          254 :     } else {
     940          147 :         y = min_max_from(remove->branch[R], L);
     941          147 :         p_of_xy = y->parent;
     942          147 :         x = y->branch[y->branch[L] == NULL];
     943          147 :         if (x) {
     944           38 :             x->parent = y->parent;
     945           38 :         }
     946              : 
     947              :         /* Save if check and improve readability by assuming this is true. */
     948          147 :         assert(p_of_xy != NULL);
     949              : 
     950          147 :         two_child = is_2_child(p_of_xy, y);
     951          147 :         p_of_xy->branch[p_of_xy->branch[R] == y] = x;
     952          147 :         transplant(map, remove, y);
     953          147 :         if (remove == p_of_xy) {
     954           62 :             p_of_xy = y;
     955           62 :         }
     956              :     }
     957              : 
     958          401 :     if (p_of_xy != NULL) {
     959          391 :         if (two_child) {
     960          210 :             assert(p_of_xy != NULL);
     961          210 :             rebalance_3_child(map, p_of_xy, x);
     962          391 :         } else if (x == NULL && p_of_xy->branch[L] == p_of_xy->branch[R]) {
     963           64 :             assert(p_of_xy != NULL);
     964          128 :             CCC_Tribool const demote_makes_3_child
     965           64 :                 = is_2_child(p_of_xy->parent, p_of_xy);
     966           64 :             demote(p_of_xy);
     967           64 :             if (demote_makes_3_child) {
     968           36 :                 rebalance_3_child(map, p_of_xy->parent, p_of_xy);
     969           36 :             }
     970           64 :         }
     971          391 :         assert(!is_leaf(p_of_xy) || !parity(p_of_xy));
     972          391 :     }
     973          401 :     remove->branch[L] = remove->branch[R] = remove->parent = NULL;
     974          401 :     remove->parity = 0;
     975          401 :     --map->count;
     976          802 :     return struct_base(map, remove);
     977          401 : }
     978              : 
     979              : /** Follows the specification in the "Rank-Balanced Trees" paper by Haeupler,
     980              : Sen, and Tarjan (Fig. 3. pg 8). */
     981              : static void
     982          246 : rebalance_3_child(
     983              :     struct CCC_Tree_map *const map,
     984              :     struct CCC_Tree_map_node *z,
     985              :     struct CCC_Tree_map_node *x
     986              : ) {
     987          246 :     CCC_Tribool made_3_child = CCC_TRUE;
     988          454 :     while (z && made_3_child) {
     989          311 :         assert(z->branch[L] == x || z->branch[R] == x);
     990          311 :         struct CCC_Tree_map_node *const g = z->parent;
     991          311 :         struct CCC_Tree_map_node *const y = z->branch[z->branch[L] == x];
     992          311 :         made_3_child = g != NULL && is_2_child(g, z);
     993          311 :         if (is_2_child(z, y)) {
     994          183 :             demote(z);
     995          311 :         } else if (y && is_22_parent(y->branch[L], y, y->branch[R])) {
     996           25 :             demote(z);
     997           25 :             demote(y);
     998          128 :         } else if (y) {
     999          103 :             assert(is_1_child(z, y));
    1000          103 :             assert(is_3_child(z, x));
    1001          103 :             assert(!is_2_child(z, y));
    1002          103 :             assert(!is_22_parent(y->branch[L], y, y->branch[R]));
    1003          103 :             enum Link const z_to_x_dir = z->branch[R] == x;
    1004          103 :             struct CCC_Tree_map_node *const w = y->branch[!z_to_x_dir];
    1005          103 :             if (is_1_child(y, w)) {
    1006           81 :                 rotate(map, z, y, y->branch[z_to_x_dir], z_to_x_dir);
    1007           81 :                 promote(y);
    1008           81 :                 demote(z);
    1009           81 :                 if (is_leaf(z)) {
    1010           24 :                     demote(z);
    1011           24 :                 }
    1012           81 :             } else {
    1013              :                 /* w is a 2-child and v will be a 1-child. */
    1014           22 :                 struct CCC_Tree_map_node *const v = y->branch[z_to_x_dir];
    1015           22 :                 assert(is_2_child(y, w));
    1016           22 :                 assert(is_1_child(y, v));
    1017           22 :                 double_rotate(map, z, y, v, !z_to_x_dir);
    1018           22 :                 double_promote(v);
    1019           22 :                 demote(y);
    1020           22 :                 double_demote(z);
    1021              :                 /* Optional "Rebalancing with Promotion," defined as follows:
    1022              :                        if node z is a non-leaf 1,1 node, we promote it;
    1023              :                        otherwise, if y is a non-leaf 1,1 node, we promote it.
    1024              :                        (See Figure 4.) (Haeupler et. al. 2014, 17).
    1025              :                    This reduces constants in some of theorems mentioned in the
    1026              :                    paper but may not be worth doing. Rotations stay at 2 worst
    1027              :                    case. Should revisit after more performance testing. */
    1028           22 :                 if (!is_leaf(z)
    1029           22 :                     && is_11_parent(z->branch[L], z, z->branch[R])) {
    1030            2 :                     promote(z);
    1031           22 :                 } else if (!is_leaf(y)
    1032           20 :                            && is_11_parent(y->branch[L], y, y->branch[R])) {
    1033            5 :                     promote(y);
    1034            5 :                 }
    1035           22 :             }
    1036              :             /* Returning here confirms O(1) rotations for re-balance. */
    1037              :             return;
    1038          103 :         }
    1039          208 :         x = z;
    1040          208 :         z = g;
    1041          311 :     }
    1042          246 : }
    1043              : 
    1044              : static void
    1045          147 : transplant(
    1046              :     struct CCC_Tree_map *const map,
    1047              :     struct CCC_Tree_map_node *const remove,
    1048              :     struct CCC_Tree_map_node *const replacement
    1049              : ) {
    1050          147 :     assert(remove != NULL);
    1051          147 :     assert(replacement != NULL);
    1052          147 :     replacement->parent = remove->parent;
    1053          147 :     if (remove->parent == NULL) {
    1054           18 :         map->root = replacement;
    1055           18 :     } else {
    1056          129 :         remove->parent->branch[remove->parent->branch[R] == remove]
    1057          258 :             = replacement;
    1058              :     }
    1059          147 :     if (remove->branch[R]) {
    1060          104 :         remove->branch[R]->parent = replacement;
    1061          104 :     }
    1062          147 :     if (remove->branch[L]) {
    1063          147 :         remove->branch[L]->parent = replacement;
    1064          147 :     }
    1065          147 :     replacement->branch[R] = remove->branch[R];
    1066          147 :     replacement->branch[L] = remove->branch[L];
    1067          147 :     replacement->parity
    1068          294 :         = (typeof((struct CCC_Tree_map_node){}.parity))parity(remove);
    1069          147 : }
    1070              : 
    1071              : /** A single rotation is symmetric. Here is the right case. Lowercase are nodes
    1072              : and uppercase are arbitrary subtrees.
    1073              :         z            x
    1074              :      ╭──┴──╮      ╭──┴──╮
    1075              :      x     C      A     z
    1076              :    ╭─┴─╮      ->      ╭─┴─╮
    1077              :    A   y              y   C
    1078              :        │              │
    1079              :        B              B
    1080              : 
    1081              : Taking a link as input allows us to code both symmetrical cases at once. */
    1082              : static void
    1083          958 : rotate(
    1084              :     struct CCC_Tree_map *const map,
    1085              :     struct CCC_Tree_map_node *const z,
    1086              :     struct CCC_Tree_map_node *const x,
    1087              :     struct CCC_Tree_map_node *const y,
    1088              :     enum Link const dir
    1089              : ) {
    1090          958 :     assert(z != NULL);
    1091          958 :     struct CCC_Tree_map_node *const g = z->parent;
    1092          958 :     x->parent = g;
    1093          958 :     if (g == NULL) {
    1094          127 :         map->root = x;
    1095          127 :     } else {
    1096          831 :         g->branch[g->branch[R] == z] = x;
    1097              :     }
    1098          958 :     x->branch[dir] = z;
    1099          958 :     z->parent = x;
    1100          958 :     z->branch[!dir] = y;
    1101          958 :     if (y) {
    1102          417 :         y->parent = z;
    1103          417 :     }
    1104          958 : }
    1105              : 
    1106              : /** A double rotation shouldn't actually be two calls to rotate because that
    1107              : would invoke pointless memory writes. Here is an example of double right.
    1108              : Lowercase are nodes and uppercase are arbitrary subtrees.
    1109              : 
    1110              :         z            y
    1111              :      ╭──┴──╮      ╭──┴──╮
    1112              :      x     D      x     z
    1113              :    ╭─┴─╮     -> ╭─┴─╮ ╭─┴─╮
    1114              :    A   y        A   B C   D
    1115              :      ╭─┴─╮
    1116              :      B   C
    1117              : 
    1118              : Taking a link as input allows us to code both symmetrical cases at once. */
    1119              : static void
    1120          121 : double_rotate(
    1121              :     struct CCC_Tree_map *const map,
    1122              :     struct CCC_Tree_map_node *const z,
    1123              :     struct CCC_Tree_map_node *const x,
    1124              :     struct CCC_Tree_map_node *const y,
    1125              :     enum Link const dir
    1126              : ) {
    1127          121 :     assert(z != NULL);
    1128          121 :     assert(x != NULL);
    1129          121 :     assert(y != NULL);
    1130          121 :     struct CCC_Tree_map_node *const g = z->parent;
    1131          121 :     y->parent = g;
    1132          121 :     if (g == NULL) {
    1133            7 :         map->root = y;
    1134            7 :     } else {
    1135          114 :         g->branch[g->branch[R] == z] = y;
    1136              :     }
    1137          121 :     x->branch[!dir] = y->branch[dir];
    1138          121 :     if (y->branch[dir]) {
    1139           33 :         y->branch[dir]->parent = x;
    1140           33 :     }
    1141          121 :     y->branch[dir] = x;
    1142          121 :     x->parent = y;
    1143              : 
    1144          121 :     z->branch[dir] = y->branch[!dir];
    1145          121 :     if (y->branch[!dir]) {
    1146           34 :         y->branch[!dir]->parent = z;
    1147           34 :     }
    1148          121 :     y->branch[!dir] = z;
    1149          121 :     z->parent = y;
    1150          121 : }
    1151              : 
    1152              : /* Returns the parity of a node either 0 or 1. A NULL node has a parity of 1 aka
    1153              :    CCC_TRUE. */
    1154              : static inline CCC_Tribool
    1155        21243 : parity(struct CCC_Tree_map_node const *const x) {
    1156        21243 :     return x ? (CCC_Tribool)x->parity : CCC_TRUE;
    1157              : }
    1158              : 
    1159              : /* Returns true for rank difference 0 (rule break) between the parent and node.
    1160              :          p
    1161              :       1╭─╯
    1162              :        x */
    1163              : [[maybe_unused]] static inline CCC_Tribool
    1164          976 : is_0_child(
    1165              :     struct CCC_Tree_map_node const *const p,
    1166              :     struct CCC_Tree_map_node const *const x
    1167              : ) {
    1168          976 :     return parity(p) == parity(x);
    1169              : }
    1170              : 
    1171              : /* Returns true for rank difference 1 between the parent and node.
    1172              :          p
    1173              :        1/
    1174              :        x*/
    1175              : static inline CCC_Tribool
    1176          327 : is_1_child(
    1177              :     struct CCC_Tree_map_node const *const p,
    1178              :     struct CCC_Tree_map_node const *const x
    1179              : ) {
    1180          327 :     return parity(p) != parity(x);
    1181              : }
    1182              : 
    1183              : /* Returns true for rank difference 2 between the parent and node.
    1184              :          p
    1185              :       2╭─╯
    1186              :        x */
    1187              : static inline CCC_Tribool
    1188         1638 : is_2_child(
    1189              :     struct CCC_Tree_map_node const *const p,
    1190              :     struct CCC_Tree_map_node const *const x
    1191              : ) {
    1192         1638 :     return parity(p) == parity(x);
    1193              : }
    1194              : 
    1195              : /* Returns true for rank difference 3 between the parent and node.
    1196              :          p
    1197              :       3╭─╯
    1198              :        x */
    1199              : [[maybe_unused]] static inline CCC_Tribool
    1200          103 : is_3_child(
    1201              :     struct CCC_Tree_map_node const *const p,
    1202              :     struct CCC_Tree_map_node const *const x
    1203              : ) {
    1204          103 :     return parity(p) != parity(x);
    1205              : }
    1206              : 
    1207              : /* Returns true if a parent is a 0,1 or 1,0 node, which is not allowed. Either
    1208              :    child may be the sentinel node which has a parity of 1 and rank -1.
    1209              :          p
    1210              :       0╭─┴─╮1
    1211              :        x   y */
    1212              : static inline CCC_Tribool
    1213         2594 : is_01_parent(
    1214              :     struct CCC_Tree_map_node const *const x,
    1215              :     struct CCC_Tree_map_node const *const p,
    1216              :     struct CCC_Tree_map_node const *const y
    1217              : ) {
    1218         4785 :     return (!parity(x) && !parity(p) && parity(y))
    1219         2594 :         || (parity(x) && parity(p) && !parity(y));
    1220              : }
    1221              : 
    1222              : /* Returns true if a parent is a 1,1 node. Either child may be the sentinel
    1223              :    node which has a parity of 1 and rank -1.
    1224              :          p
    1225              :       1╭─┴─╮1
    1226              :        x   y */
    1227              : static inline CCC_Tribool
    1228           12 : is_11_parent(
    1229              :     struct CCC_Tree_map_node const *const x,
    1230              :     struct CCC_Tree_map_node const *const p,
    1231              :     struct CCC_Tree_map_node const *const y
    1232              : ) {
    1233           18 :     return (!parity(x) && parity(p) && !parity(y))
    1234           12 :         || (parity(x) && !parity(p) && parity(y));
    1235              : }
    1236              : 
    1237              : /* Returns true if a parent is a 0,2 or 2,0 node, which is not allowed. Either
    1238              :    child may be the sentinel node which has a parity of 1 and rank -1.
    1239              :          p
    1240              :       0╭─┴─╮2
    1241              :        x   y */
    1242              : static inline CCC_Tribool
    1243         1312 : is_02_parent(
    1244              :     struct CCC_Tree_map_node const *const x,
    1245              :     struct CCC_Tree_map_node const *const p,
    1246              :     struct CCC_Tree_map_node const *const y
    1247              : ) {
    1248         1312 :     return (parity(x) == parity(p)) && (parity(p) == parity(y));
    1249              : }
    1250              : 
    1251              : /* Returns true if a parent is a 2,2 or 2,2 node, which is allowed. 2,2 nodes
    1252              :    are allowed in a WAVL tree but the absence of any 2,2 nodes is the exact
    1253              :    equivalent of a normal AVL tree which can occur if only insertions occur
    1254              :    for a WAVL tree. Either child may be the sentinel node which has a parity of
    1255              :    1 and rank -1.
    1256              :          p
    1257              :       2╭─┴─╮2
    1258              :        x   y */
    1259              : static inline CCC_Tribool
    1260          231 : is_22_parent(
    1261              :     struct CCC_Tree_map_node const *const x,
    1262              :     struct CCC_Tree_map_node const *const p,
    1263              :     struct CCC_Tree_map_node const *const y
    1264              : ) {
    1265          231 :     return (parity(x) == parity(p)) && (parity(p) == parity(y));
    1266              : }
    1267              : 
    1268              : static inline void
    1269         4466 : promote(struct CCC_Tree_map_node *const x) {
    1270         4466 :     if (x) {
    1271         4466 :         x->parity = !x->parity;
    1272         4466 :     }
    1273         4466 : }
    1274              : 
    1275              : static inline void
    1276         1499 : demote(struct CCC_Tree_map_node *const x) {
    1277         1499 :     promote(x);
    1278         1499 : }
    1279              : 
    1280              : /* One could imagine non-parity based rank tracking making this function
    1281              :    meaningful, but two parity changes are the same as a no-op. Leave for
    1282              :    clarity of what the code is meant to do through certain sections. */
    1283              : static inline void
    1284           22 : double_promote(struct CCC_Tree_map_node *const) {
    1285           22 : }
    1286              : 
    1287              : /* One could imagine non-parity based rank tracking making this function
    1288              :    meaningful, but two parity changes are the same as a no-op. Leave for
    1289              :    clarity of what the code is meant to do through certain sections. */
    1290              : static inline void
    1291           22 : double_demote(struct CCC_Tree_map_node *const) {
    1292           22 : }
    1293              : 
    1294              : static inline CCC_Tribool
    1295          514 : is_leaf(struct CCC_Tree_map_node const *const x) {
    1296          514 :     return x->branch[L] == NULL && x->branch[R] == NULL;
    1297              : }
    1298              : 
    1299              : static inline struct CCC_Tree_map_node *
    1300         3906 : sibling_of(struct CCC_Tree_map_node const *const x) {
    1301         3906 :     if (x->parent == NULL) {
    1302            0 :         return NULL;
    1303              :     }
    1304              :     /* We want the sibling so we need the truthy value to be opposite of x. */
    1305         3906 :     return x->parent->branch[x->parent->branch[L] == x];
    1306         3906 : }
    1307              : 
    1308              : /*===========================   Validation   ===============================*/
    1309              : 
    1310              : /* NOLINTBEGIN(*misc-no-recursion) */
    1311              : 
    1312              : /** @internal */
    1313              : struct Tree_range {
    1314              :     struct CCC_Tree_map_node const *low;
    1315              :     struct CCC_Tree_map_node const *root;
    1316              :     struct CCC_Tree_map_node const *high;
    1317              : };
    1318              : 
    1319              : static size_t
    1320       131079 : recursive_count(
    1321              :     struct CCC_Tree_map const *const map,
    1322              :     struct CCC_Tree_map_node const *const r
    1323              : ) {
    1324       131079 :     if (r == NULL) {
    1325        66503 :         return 0;
    1326              :     }
    1327       129152 :     return 1 + recursive_count(map, r->branch[R])
    1328        64576 :          + recursive_count(map, r->branch[L]);
    1329       131079 : }
    1330              : 
    1331              : static CCC_Tribool
    1332       131079 : are_subtrees_valid(struct CCC_Tree_map const *t, struct Tree_range const r) {
    1333       131079 :     if (!r.root) {
    1334        66503 :         return CCC_TRUE;
    1335              :     }
    1336        64576 :     if (r.low
    1337        64576 :         && order(t, key_from_node(t, r.low), r.root) != CCC_ORDER_LESSER) {
    1338            0 :         return CCC_FALSE;
    1339              :     }
    1340        64576 :     if (r.high
    1341        64576 :         && order(t, key_from_node(t, r.high), r.root) != CCC_ORDER_GREATER) {
    1342            0 :         return CCC_FALSE;
    1343              :     }
    1344       129152 :     return are_subtrees_valid(
    1345        64576 :                t,
    1346       258304 :                (struct Tree_range){
    1347        64576 :                    .low = r.low,
    1348        64576 :                    .root = r.root->branch[L],
    1349        64576 :                    .high = r.root,
    1350              :                }
    1351              :            )
    1352        64576 :         && are_subtrees_valid(
    1353        64576 :                t,
    1354       258304 :                (struct Tree_range){
    1355        64576 :                    .low = r.root,
    1356        64576 :                    .root = r.root->branch[R],
    1357        64576 :                    .high = r.high,
    1358              :                }
    1359              :         );
    1360       131079 : }
    1361              : 
    1362              : static CCC_Tribool
    1363       131079 : is_storing_parent(
    1364              :     struct CCC_Tree_map const *const t,
    1365              :     struct CCC_Tree_map_node const *const parent,
    1366              :     struct CCC_Tree_map_node const *const root
    1367              : ) {
    1368       131079 :     if (root == NULL) {
    1369        66503 :         return CCC_TRUE;
    1370              :     }
    1371        64576 :     if (root->parent != parent) {
    1372            0 :         return CCC_FALSE;
    1373              :     }
    1374       129152 :     return is_storing_parent(t, root, root->branch[L])
    1375        64576 :         && is_storing_parent(t, root, root->branch[R]);
    1376       131079 : }
    1377              : 
    1378              : static CCC_Tribool
    1379         1927 : validate(struct CCC_Tree_map const *const map) {
    1380         1927 :     if (!are_subtrees_valid(
    1381         1927 :             map,
    1382         3854 :             (struct Tree_range){
    1383              :                 .low = NULL,
    1384         1927 :                 .root = map->root,
    1385              :                 .high = NULL,
    1386              :             }
    1387              :         )) {
    1388            0 :         return CCC_FALSE;
    1389              :     }
    1390         1927 :     if (recursive_count(map, map->root) != map->count) {
    1391            0 :         return CCC_FALSE;
    1392              :     }
    1393         1927 :     if (!is_storing_parent(map, NULL, map->root)) {
    1394            0 :         return CCC_FALSE;
    1395              :     }
    1396         1927 :     return CCC_TRUE;
    1397         1927 : }
    1398              : 
    1399              : /* NOLINTEND(*misc-no-recursion) */
    1400              : 
    1401              : /* Below you will find the required license for code that inspired the
    1402              : implementation of a WAVL tree in this repository for some map containers.
    1403              : 
    1404              : The original repository can be found here:
    1405              : 
    1406              : https://github.com/pvachon/wavl_tree
    1407              : 
    1408              : The original implementation has be changed to eliminate left and right cases
    1409              : and work within the C Container Collection memory framework.
    1410              : 
    1411              : Redistribution and use in source and binary forms, with or without
    1412              : modification, are permitted provided that the following conditions are met:
    1413              : 
    1414              : 1. Redistributions of source code must retain the above copyright notice, this
    1415              :    list of conditions and the following disclaimer.
    1416              : 
    1417              : 2. Redistributions in binary form must reproduce the above copyright notice,
    1418              :    this list of conditions and the following disclaimer in the documentation
    1419              :    and/or other materials provided with the distribution.
    1420              : 
    1421              : THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
    1422              : AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
    1423              : IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
    1424              : DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
    1425              : FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
    1426              : DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
    1427              : SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
    1428              : CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
    1429              : OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
    1430              : OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
        

Generated by: LCOV version 2.4.1-beta