mirror of
https://git.haproxy.org/git/haproxy.git/
synced 2025-09-20 13:21:29 +02:00
IMPORT: cebtree: import version 0.5.0 to support duplicates
The support for duplicates is necessary for various use cases related to config names, so let's upgrade to the latest version which brings this support. This updates the cebtree code to commit 808ed67 (tag 0.5.0). A few tiny adaptations were needed: - replace a few ceb_node** with ceb_root** since pointers are now tagged ; - replace cebu*.h with ceb*.h since both are now merged in the same include file. This way we can drop the unused cebu*.h files from cebtree that are provided only for compatibility. - rename immediate storage functions to cebXX_imm_XXX() as per the API change in 0.5 that makes immediate explicit rather than implicit. This only affects vars and tools.c:copy_file_name(). The tests continue to work.
This commit is contained in:
parent
90b70b61b1
commit
ddf900a0ce
12
Makefile
12
Makefile
@ -962,15 +962,15 @@ OBJS += src/mux_h2.o src/mux_h1.o src/mux_fcgi.o src/log.o \
|
||||
src/cache.o src/stconn.o src/http_htx.o src/debug.o \
|
||||
src/check.o src/stats-html.o src/haproxy.o src/listener.o \
|
||||
src/applet.o src/pattern.o src/cfgparse-listen.o \
|
||||
src/flt_spoe.o src/cebuis_tree.o src/http_ext.o \
|
||||
src/http_act.o src/http_fetch.o src/cebus_tree.o \
|
||||
src/cebuib_tree.o src/http_client.o src/dns.o \
|
||||
src/cebub_tree.o src/vars.o src/event_hdl.o src/tcp_rules.o \
|
||||
src/flt_spoe.o src/cebis_tree.o src/http_ext.o \
|
||||
src/http_act.o src/http_fetch.o src/cebs_tree.o \
|
||||
src/cebib_tree.o src/http_client.o src/dns.o \
|
||||
src/cebb_tree.o src/vars.o src/event_hdl.o src/tcp_rules.o \
|
||||
src/trace.o src/stats-proxy.o src/pool.o src/stats.o \
|
||||
src/cfgparse-global.o src/filters.o src/mux_pt.o \
|
||||
src/flt_http_comp.o src/sock.o src/h1.o src/sink.o \
|
||||
src/cebua_tree.o src/session.o src/payload.o src/htx.o \
|
||||
src/cebul_tree.o src/cebu32_tree.o src/cebu64_tree.o \
|
||||
src/ceba_tree.o src/session.o src/payload.o src/htx.o \
|
||||
src/cebl_tree.o src/ceb32_tree.o src/ceb64_tree.o \
|
||||
src/server_state.o src/proto_rhttp.o src/flt_trace.o src/fd.o \
|
||||
src/task.o src/map.o src/fcgi-app.o src/h2.o src/mworker.o \
|
||||
src/tcp_sample.o src/mjson.o src/h1_htx.o src/tcp_act.o \
|
||||
|
@ -50,7 +50,7 @@ enum vars_scope {
|
||||
|
||||
#define VAR_NAME_ROOTS 4
|
||||
struct vars {
|
||||
struct ceb_node *name_root[VAR_NAME_ROOTS];
|
||||
struct ceb_root *name_root[VAR_NAME_ROOTS];
|
||||
enum vars_scope scope;
|
||||
unsigned int size;
|
||||
__decl_thread(HA_RWLOCK_T rwlock);
|
||||
|
@ -22,7 +22,7 @@
|
||||
#ifndef _HAPROXY_VARS_H
|
||||
#define _HAPROXY_VARS_H
|
||||
|
||||
#include <import/cebu64_tree.h>
|
||||
#include <import/ceb64_tree.h>
|
||||
|
||||
#include <haproxy/api-t.h>
|
||||
#include <haproxy/session-t.h>
|
||||
@ -86,7 +86,7 @@ static inline void vars_prune(struct vars *vars, struct session *sess, struct st
|
||||
int i;
|
||||
|
||||
for (i = 0; i < VAR_NAME_ROOTS; i++) {
|
||||
while ((node = cebu64_first(&vars->name_root[i]))) {
|
||||
while ((node = cebu64_imm_first(&vars->name_root[i]))) {
|
||||
var = container_of(node, struct var, node);
|
||||
size += var_clear(vars, var, 1);
|
||||
}
|
||||
|
426
include/import/ceb32_tree.h
Normal file
426
include/import/ceb32_tree.h
Normal file
@ -0,0 +1,426 @@
|
||||
/*
|
||||
* Compact Elastic Binary Trees - exported functions operating on u32 keys
|
||||
*
|
||||
* Copyright (C) 2014-2025 Willy Tarreau - w@1wt.eu
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef _CEB32_TREE_H
|
||||
#define _CEB32_TREE_H
|
||||
|
||||
#include "cebtree.h"
|
||||
#include <inttypes.h>
|
||||
|
||||
/* simpler version */
|
||||
struct ceb_node *ceb32_imm_insert(struct ceb_root **root, struct ceb_node *node);
|
||||
struct ceb_node *ceb32_imm_first(struct ceb_root *const *root);
|
||||
struct ceb_node *ceb32_imm_last(struct ceb_root *const *root);
|
||||
struct ceb_node *ceb32_imm_lookup(struct ceb_root *const *root, uint32_t key);
|
||||
struct ceb_node *ceb32_imm_lookup_le(struct ceb_root *const *root, uint32_t key);
|
||||
struct ceb_node *ceb32_imm_lookup_lt(struct ceb_root *const *root, uint32_t key);
|
||||
struct ceb_node *ceb32_imm_lookup_ge(struct ceb_root *const *root, uint32_t key);
|
||||
struct ceb_node *ceb32_imm_lookup_gt(struct ceb_root *const *root, uint32_t key);
|
||||
struct ceb_node *ceb32_imm_next_unique(struct ceb_root *const *root, struct ceb_node *node);
|
||||
struct ceb_node *ceb32_imm_prev_unique(struct ceb_root *const *root, struct ceb_node *node);
|
||||
struct ceb_node *ceb32_imm_next_dup(struct ceb_root *const *root, struct ceb_node *node);
|
||||
struct ceb_node *ceb32_imm_prev_dup(struct ceb_root *const *root, struct ceb_node *node);
|
||||
struct ceb_node *ceb32_imm_next(struct ceb_root *const *root, struct ceb_node *node);
|
||||
struct ceb_node *ceb32_imm_prev(struct ceb_root *const *root, struct ceb_node *node);
|
||||
struct ceb_node *ceb32_imm_delete(struct ceb_root **root, struct ceb_node *node);
|
||||
struct ceb_node *ceb32_imm_pick(struct ceb_root **root, uint32_t key);
|
||||
|
||||
struct ceb_node *cebu32_imm_insert(struct ceb_root **root, struct ceb_node *node);
|
||||
struct ceb_node *cebu32_imm_first(struct ceb_root *const *root);
|
||||
struct ceb_node *cebu32_imm_last(struct ceb_root *const *root);
|
||||
struct ceb_node *cebu32_imm_lookup(struct ceb_root *const *root, uint32_t key);
|
||||
struct ceb_node *cebu32_imm_lookup_le(struct ceb_root *const *root, uint32_t key);
|
||||
struct ceb_node *cebu32_imm_lookup_lt(struct ceb_root *const *root, uint32_t key);
|
||||
struct ceb_node *cebu32_imm_lookup_ge(struct ceb_root *const *root, uint32_t key);
|
||||
struct ceb_node *cebu32_imm_lookup_gt(struct ceb_root *const *root, uint32_t key);
|
||||
struct ceb_node *cebu32_imm_next(struct ceb_root *const *root, struct ceb_node *node);
|
||||
struct ceb_node *cebu32_imm_prev(struct ceb_root *const *root, struct ceb_node *node);
|
||||
struct ceb_node *cebu32_imm_delete(struct ceb_root **root, struct ceb_node *node);
|
||||
struct ceb_node *cebu32_imm_pick(struct ceb_root **root, uint32_t key);
|
||||
|
||||
/* generic dump function */
|
||||
void ceb32_imm_default_dump(struct ceb_root **ceb_root, const char *label, const void *ctx, int sub);
|
||||
|
||||
/* returns the pointer to the uint32_t key */
|
||||
static inline uint32_t *ceb32_imm_key(const struct ceb_node *node)
|
||||
{
|
||||
return (uint32_t *)ceb_key_ptr(node, sizeof(struct ceb_node));
|
||||
}
|
||||
|
||||
/* version taking a key offset */
|
||||
struct ceb_node *ceb32_ofs_insert(struct ceb_root **root, ptrdiff_t kofs, struct ceb_node *node);
|
||||
struct ceb_node *ceb32_ofs_first(struct ceb_root *const *root, ptrdiff_t kofs);
|
||||
struct ceb_node *ceb32_ofs_last(struct ceb_root *const *root, ptrdiff_t kofs);
|
||||
struct ceb_node *ceb32_ofs_lookup(struct ceb_root *const *root, ptrdiff_t kofs, uint32_t key);
|
||||
struct ceb_node *ceb32_ofs_lookup_le(struct ceb_root *const *root, ptrdiff_t kofs, uint32_t key);
|
||||
struct ceb_node *ceb32_ofs_lookup_lt(struct ceb_root *const *root, ptrdiff_t kofs, uint32_t key);
|
||||
struct ceb_node *ceb32_ofs_lookup_ge(struct ceb_root *const *root, ptrdiff_t kofs, uint32_t key);
|
||||
struct ceb_node *ceb32_ofs_lookup_gt(struct ceb_root *const *root, ptrdiff_t kofs, uint32_t key);
|
||||
struct ceb_node *ceb32_ofs_next_unique(struct ceb_root *const *root, ptrdiff_t kofs, struct ceb_node *node);
|
||||
struct ceb_node *ceb32_ofs_prev_unique(struct ceb_root *const *root, ptrdiff_t kofs, struct ceb_node *node);
|
||||
struct ceb_node *ceb32_ofs_next_dup(struct ceb_root *const *root, ptrdiff_t kofs, struct ceb_node *node);
|
||||
struct ceb_node *ceb32_ofs_prev_dup(struct ceb_root *const *root, ptrdiff_t kofs, struct ceb_node *node);
|
||||
struct ceb_node *ceb32_ofs_next(struct ceb_root *const *root, ptrdiff_t kofs, struct ceb_node *node);
|
||||
struct ceb_node *ceb32_ofs_prev(struct ceb_root *const *root, ptrdiff_t kofs, struct ceb_node *node);
|
||||
struct ceb_node *ceb32_ofs_delete(struct ceb_root **root, ptrdiff_t kofs, struct ceb_node *node);
|
||||
struct ceb_node *ceb32_ofs_pick(struct ceb_root **root, ptrdiff_t kofs, uint32_t key);
|
||||
|
||||
struct ceb_node *cebu32_ofs_insert(struct ceb_root **root, ptrdiff_t kofs, struct ceb_node *node);
|
||||
struct ceb_node *cebu32_ofs_first(struct ceb_root *const *root, ptrdiff_t kofs);
|
||||
struct ceb_node *cebu32_ofs_last(struct ceb_root *const *root, ptrdiff_t kofs);
|
||||
struct ceb_node *cebu32_ofs_lookup(struct ceb_root *const *root, ptrdiff_t kofs, uint32_t key);
|
||||
struct ceb_node *cebu32_ofs_lookup_le(struct ceb_root *const *root, ptrdiff_t kofs, uint32_t key);
|
||||
struct ceb_node *cebu32_ofs_lookup_lt(struct ceb_root *const *root, ptrdiff_t kofs, uint32_t key);
|
||||
struct ceb_node *cebu32_ofs_lookup_ge(struct ceb_root *const *root, ptrdiff_t kofs, uint32_t key);
|
||||
struct ceb_node *cebu32_ofs_lookup_gt(struct ceb_root *const *root, ptrdiff_t kofs, uint32_t key);
|
||||
struct ceb_node *cebu32_ofs_next(struct ceb_root *const *root, ptrdiff_t kofs, struct ceb_node *node);
|
||||
struct ceb_node *cebu32_ofs_prev(struct ceb_root *const *root, ptrdiff_t kofs, struct ceb_node *node);
|
||||
struct ceb_node *cebu32_ofs_delete(struct ceb_root **root, ptrdiff_t kofs, struct ceb_node *node);
|
||||
struct ceb_node *cebu32_ofs_pick(struct ceb_root **root, ptrdiff_t kofs, uint32_t key);
|
||||
|
||||
/* generic dump function taking a key offset */
|
||||
void ceb32_ofs_default_dump(struct ceb_root *const *root, ptrdiff_t kofs, const char *label, const void *ctx, int sub);
|
||||
|
||||
/* returns the pointer to the uint32_t key */
|
||||
static inline uint32_t *ceb32_ofs_key(const struct ceb_node *node, ptrdiff_t kofs)
|
||||
{
|
||||
return (uint32_t *)ceb_key_ptr(node, kofs);
|
||||
}
|
||||
|
||||
/* insert at root <root>, the item <item_ptr> using node member <nname> and
|
||||
* key member <kname>, and returns either the inserted item, or the one that
|
||||
* was found there.
|
||||
*/
|
||||
#define ceb32_item_insert(root, nname, kname, item_ptr) ({ \
|
||||
ptrdiff_t _nofs = offsetof(typeof(*(item_ptr)), nname); \
|
||||
ptrdiff_t _kofs = offsetof(typeof(*(item_ptr)), kname) - _nofs; \
|
||||
struct ceb_node *_node = ceb32_ofs_insert(root, _kofs, &(item_ptr)->nname); \
|
||||
(typeof(item_ptr))((char *)(_node) - _nofs); \
|
||||
})
|
||||
|
||||
/* descend root <root>, and return the first item of type <type>, using node
|
||||
* member <nname> and key member <kname>, or NULL if the tree is empty.
|
||||
*/
|
||||
#define ceb32_item_first(root, nname, kname, type) ({ \
|
||||
ptrdiff_t _nofs = offsetof(type, nname); \
|
||||
ptrdiff_t _kofs = offsetof(type, kname) - _nofs; \
|
||||
struct ceb_node *_node = ceb32_ofs_first(root, _kofs); \
|
||||
_node ? (type *)((char *)(_node) - _nofs) : NULL; \
|
||||
})
|
||||
|
||||
/* descend root <root>, and return the last item of type <type>, using node
|
||||
* member <nname> and key member <kname>, or NULL if the tree is empty.
|
||||
*/
|
||||
#define ceb32_item_last(root, nname, kname, type) ({ \
|
||||
ptrdiff_t _nofs = offsetof(type, nname); \
|
||||
ptrdiff_t _kofs = offsetof(type, kname) - _nofs; \
|
||||
struct ceb_node *_node = ceb32_ofs_last(root, _kofs); \
|
||||
_node ? (type *)((char *)(_node) - _nofs) : NULL; \
|
||||
})
|
||||
|
||||
/* lookup from root <root>, the first item of type <type> which contains the
|
||||
* key <key>, using node member <nname> and key member <kname>. Returns the
|
||||
* pointer to the item, or NULL if not found.
|
||||
*/
|
||||
#define ceb32_item_lookup(root, nname, kname, key, type) ({ \
|
||||
ptrdiff_t _nofs = offsetof(type, nname); \
|
||||
ptrdiff_t _kofs = offsetof(type, kname) - _nofs; \
|
||||
struct ceb_node *_node = ceb32_ofs_lookup(root, _kofs, key); \
|
||||
_node ? (type *)((char *)(_node) - _nofs) : NULL; \
|
||||
})
|
||||
|
||||
/* lookup from root <root>, the item of type <type> which contains the last of
|
||||
* the greatest keys that are lower than or equal to <key>, using node member
|
||||
* <nname> and key member <kname>. Returns the pointer to the item, or NULL if
|
||||
* not found.
|
||||
*/
|
||||
#define ceb32_item_lookup_le(root, nname, kname, key, type) ({ \
|
||||
ptrdiff_t _nofs = offsetof(type, nname); \
|
||||
ptrdiff_t _kofs = offsetof(type, kname) - _nofs; \
|
||||
struct ceb_node *_node = ceb32_ofs_lookup_le(root, _kofs, key); \
|
||||
_node ? (type *)((char *)(_node) - _nofs) : NULL; \
|
||||
})
|
||||
|
||||
/* lookup from root <root>, the item of type <type> which contains the last of
|
||||
* the greatest keys that are strictly lower than <key>, using node member
|
||||
* <nname> and key member <kname>. Returns the pointer to the item, or NULL if
|
||||
* not found.
|
||||
*/
|
||||
#define ceb32_item_lookup_lt(root, nname, kname, key, type) ({ \
|
||||
ptrdiff_t _nofs = offsetof(type, nname); \
|
||||
ptrdiff_t _kofs = offsetof(type, kname) - _nofs; \
|
||||
struct ceb_node *_node = ceb32_ofs_lookup_lt(root, _kofs, key); \
|
||||
_node ? (type *)((char *)(_node) - _nofs) : NULL; \
|
||||
})
|
||||
|
||||
/* lookup from root <root>, the item of type <type> which contains the first of
|
||||
* the lowest keys key that are greater than or equal to <key>, using node
|
||||
* member <nname> and key member <kname>. Returns the pointer to the item, or
|
||||
* NULL if not found.
|
||||
*/
|
||||
#define ceb32_item_lookup_ge(root, nname, kname, key, type) ({ \
|
||||
ptrdiff_t _nofs = offsetof(type, nname); \
|
||||
ptrdiff_t _kofs = offsetof(type, kname) - _nofs; \
|
||||
struct ceb_node *_node = ceb32_ofs_lookup_ge(root, _kofs, key); \
|
||||
_node ? (type *)((char *)(_node) - _nofs) : NULL; \
|
||||
})
|
||||
|
||||
/* lookup from root <root>, the item of type <type> which contains the first of
|
||||
* the lowest keys that are strictly greater than <key>, using node member
|
||||
* <nname> and key member <kname>. Returns the pointer to the item, or NULL if
|
||||
* not found.
|
||||
*/
|
||||
#define ceb32_item_lookup_gt(root, nname, kname, key, type) ({ \
|
||||
ptrdiff_t _nofs = offsetof(type, nname); \
|
||||
ptrdiff_t _kofs = offsetof(type, kname) - _nofs; \
|
||||
struct ceb_node *_node = ceb32_ofs_lookup_gt(root, _kofs, key); \
|
||||
_node ? (type *)((char *)(_node) - _nofs) : NULL; \
|
||||
})
|
||||
|
||||
/* lookup from root <root>, the first item after item <item_ptr> that has a
|
||||
* strictly greater key, using node member <nname> and key member <kname>, and
|
||||
* returns either the found item, or NULL if none exists.
|
||||
*/
|
||||
#define ceb32_item_next_unique(root, nname, kname, item_ptr) ({ \
|
||||
ptrdiff_t _nofs = offsetof(typeof(*(item_ptr)), nname); \
|
||||
ptrdiff_t _kofs = offsetof(typeof(*(item_ptr)), kname) - _nofs; \
|
||||
struct ceb_node *_node = ceb32_ofs_next_unique(root, _kofs, &(item_ptr)->nname);\
|
||||
_node ? (typeof(item_ptr))((char *)(_node) - _nofs) : NULL; \
|
||||
})
|
||||
|
||||
/* lookup from root <root>, the last item before item <item_ptr> that has a
|
||||
* strictly lower key, using node member <nname> and key member <kname>, and
|
||||
* returns either the found item, or NULL if none exists.
|
||||
*/
|
||||
#define ceb32_item_prev_unique(root, nname, kname, item_ptr) ({ \
|
||||
ptrdiff_t _nofs = offsetof(typeof(*(item_ptr)), nname); \
|
||||
ptrdiff_t _kofs = offsetof(typeof(*(item_ptr)), kname) - _nofs; \
|
||||
struct ceb_node *_node = ceb32_ofs_prev_unique(root, _kofs, &(item_ptr)->nname);\
|
||||
_node ? (typeof(item_ptr))((char *)(_node) - _nofs) : NULL; \
|
||||
})
|
||||
|
||||
/* lookup from root <root>, the first item after item <item_ptr> that has
|
||||
* exactly the same key, using node member <nname> and key member <kname>, and
|
||||
* returns either the found item, or NULL if none exists.
|
||||
*/
|
||||
#define ceb32_item_next_dup(root, nname, kname, item_ptr) ({ \
|
||||
ptrdiff_t _nofs = offsetof(typeof(*(item_ptr)), nname); \
|
||||
ptrdiff_t _kofs = offsetof(typeof(*(item_ptr)), kname) - _nofs; \
|
||||
struct ceb_node *_node = ceb32_ofs_next_dup(root, _kofs, &(item_ptr)->nname); \
|
||||
_node ? (typeof(item_ptr))((char *)(_node) - _nofs) : NULL; \
|
||||
})
|
||||
|
||||
/* lookup from root <root>, the last item before item <item_ptr> that has
|
||||
* exactly the same key, using node member <nname> and key member <kname>, and
|
||||
* returns either the found item, or NULL if none exists.
|
||||
*/
|
||||
#define ceb32_item_prev_dup(root, nname, kname, item_ptr) ({ \
|
||||
ptrdiff_t _nofs = offsetof(typeof(*(item_ptr)), nname); \
|
||||
ptrdiff_t _kofs = offsetof(typeof(*(item_ptr)), kname) - _nofs; \
|
||||
struct ceb_node *_node = ceb32_ofs_prev_dup(root, _kofs, &(item_ptr)->nname); \
|
||||
_node ? (typeof(item_ptr))((char *)(_node) - _nofs) : NULL; \
|
||||
})
|
||||
|
||||
/* lookup from root <root>, the first item immediately after item <item_ptr>,
|
||||
* using node member <nname> and key member <kname>, and returns either the
|
||||
* found item, or NULL if none exists.
|
||||
*/
|
||||
#define ceb32_item_next(root, nname, kname, item_ptr) ({ \
|
||||
ptrdiff_t _nofs = offsetof(typeof(*(item_ptr)), nname); \
|
||||
ptrdiff_t _kofs = offsetof(typeof(*(item_ptr)), kname) - _nofs; \
|
||||
struct ceb_node *_node = ceb32_ofs_next(root, _kofs, &(item_ptr)->nname); \
|
||||
_node ? (typeof(item_ptr))((char *)(_node) - _nofs) : NULL; \
|
||||
})
|
||||
|
||||
/* lookup from root <root>, the last item immediately before item <item_ptr>,
|
||||
* using node member <nname> and key member <kname>, and returns either the
|
||||
* found item, or NULL if none exists.
|
||||
*/
|
||||
#define ceb32_item_prev(root, nname, kname, item_ptr) ({ \
|
||||
ptrdiff_t _nofs = offsetof(typeof(*(item_ptr)), nname); \
|
||||
ptrdiff_t _kofs = offsetof(typeof(*(item_ptr)), kname) - _nofs; \
|
||||
struct ceb_node *_node = ceb32_ofs_prev(root, _kofs, &(item_ptr)->nname); \
|
||||
_node ? (typeof(item_ptr))((char *)(_node) - _nofs) : NULL; \
|
||||
})
|
||||
|
||||
/* lookup from root <root>, the item <item_ptr> using node member <nname> and
|
||||
* key member <kname>, deletes it and returns it. If the item is NULL or absent
|
||||
* from the tree, NULL is returned.
|
||||
*/
|
||||
#define ceb32_item_delete(root, nname, kname, item_ptr) ({ \
|
||||
ptrdiff_t _nofs = offsetof(typeof(*(item_ptr)), nname); \
|
||||
ptrdiff_t _kofs = offsetof(typeof(*(item_ptr)), kname) - _nofs; \
|
||||
typeof(item_ptr) _item = (item_ptr); \
|
||||
struct ceb_node *_node = ceb32_ofs_delete(root, _kofs, _item ? &_item->nname : NULL); \
|
||||
_node ? (typeof(item_ptr))((char *)(_node) - _nofs) : NULL; \
|
||||
})
|
||||
|
||||
/* lookup from root <root>, the first item of type <type> which contains the
|
||||
* key <key>, using node member <nname> and key member <kname>, deletes it and
|
||||
* returns it. If the key is not found in the tree, NULL is returned.
|
||||
*/
|
||||
#define ceb32_item_pick(root, nname, kname, key, type) ({ \
|
||||
ptrdiff_t _nofs = offsetof(type, nname); \
|
||||
ptrdiff_t _kofs = offsetof(type, kname) - _nofs; \
|
||||
struct ceb_node *_node = ceb32_ofs_pick(root, _kofs, key); \
|
||||
_node ? (type *)((char *)(_node) - _nofs) : NULL; \
|
||||
})
|
||||
|
||||
/*** versions using unique keys below ***/
|
||||
|
||||
/* insert at root <root>, the item <item_ptr> using node member <nname> and key
|
||||
* member <kname>, and returns either the inserted item, or the one that was
|
||||
* found there.
|
||||
*/
|
||||
#define cebu32_item_insert(root, nname, kname, item_ptr) ({ \
|
||||
ptrdiff_t _nofs = offsetof(typeof(*(item_ptr)), nname); \
|
||||
ptrdiff_t _kofs = offsetof(typeof(*(item_ptr)), kname) - _nofs; \
|
||||
struct ceb_node *_node = cebu32_ofs_insert(root, _kofs, &(item_ptr)->nname); \
|
||||
(typeof(item_ptr))((char *)(_node) - _nofs); \
|
||||
})
|
||||
|
||||
/* descend root <root>, and return the first item of type <type>, using node
|
||||
* member <nname> and key member <kname>, or NULL if the tree is empty.
|
||||
*/
|
||||
#define cebu32_item_first(root, nname, kname, type) ({ \
|
||||
ptrdiff_t _nofs = offsetof(type, nname); \
|
||||
ptrdiff_t _kofs = offsetof(type, kname) - _nofs; \
|
||||
struct ceb_node *_node = cebu32_ofs_first(root, _kofs); \
|
||||
_node ? (type *)((char *)(_node) - _nofs) : NULL; \
|
||||
})
|
||||
|
||||
/* descend root <root>, and return the last item of type <type>, using node
|
||||
* member <nname> and key member <kname>, or NULL if the tree is empty.
|
||||
*/
|
||||
#define cebu32_item_last(root, nname, kname, type) ({ \
|
||||
ptrdiff_t _nofs = offsetof(type, nname); \
|
||||
ptrdiff_t _kofs = offsetof(type, kname) - _nofs; \
|
||||
struct ceb_node *_node = cebu32_ofs_last(root, _kofs); \
|
||||
_node ? (type *)((char *)(_node) - _nofs) : NULL; \
|
||||
})
|
||||
|
||||
/* lookup from root <root>, the item of type <type> which contains the key
|
||||
* <key>, using node member <nname> and key member <kname>. Returns the pointer
|
||||
* to the item, or NULL if not found.
|
||||
*/
|
||||
#define cebu32_item_lookup(root, nname, kname, key, type) ({ \
|
||||
ptrdiff_t _nofs = offsetof(type, nname); \
|
||||
ptrdiff_t _kofs = offsetof(type, kname) - _nofs; \
|
||||
struct ceb_node *_node = cebu32_ofs_lookup(root, _kofs, key); \
|
||||
_node ? (type *)((char *)(_node) - _nofs) : NULL; \
|
||||
})
|
||||
|
||||
/* lookup from root <root>, the item of type <type> which contains the greatest
|
||||
* key that is lower than or equal to <key>, using node member <nname> and key
|
||||
* member <kname>. Returns the pointer to the item, or NULL if not found.
|
||||
*/
|
||||
#define cebu32_item_lookup_le(root, nname, kname, key, type) ({ \
|
||||
ptrdiff_t _nofs = offsetof(type, nname); \
|
||||
ptrdiff_t _kofs = offsetof(type, kname) - _nofs; \
|
||||
struct ceb_node *_node = cebu32_ofs_lookup_le(root, _kofs, key); \
|
||||
_node ? (type *)((char *)(_node) - _nofs) : NULL; \
|
||||
})
|
||||
|
||||
/* lookup from root <root>, the item of type <type> which contains the greatest
|
||||
* key that is strictly lower than <key>, using node member <nname> and key
|
||||
* member <kname>. Returns the pointer to the item, or NULL if not found.
|
||||
*/
|
||||
#define cebu32_item_lookup_lt(root, nname, kname, key, type) ({ \
|
||||
ptrdiff_t _nofs = offsetof(type, nname); \
|
||||
ptrdiff_t _kofs = offsetof(type, kname) - _nofs; \
|
||||
struct ceb_node *_node = cebu32_ofs_lookup_lt(root, _kofs, key); \
|
||||
_node ? (type *)((char *)(_node) - _nofs) : NULL; \
|
||||
})
|
||||
|
||||
/* lookup from root <root>, the item of type <type> which contains the lowest
|
||||
* key key that is greater than or equal to <key>, using node member <nname>
|
||||
* and key member <kname>. Returns the pointer to the item, or NULL if not
|
||||
* found.
|
||||
*/
|
||||
#define cebu32_item_lookup_ge(root, nname, kname, key, type) ({ \
|
||||
ptrdiff_t _nofs = offsetof(type, nname); \
|
||||
ptrdiff_t _kofs = offsetof(type, kname) - _nofs; \
|
||||
struct ceb_node *_node = cebu32_ofs_lookup_ge(root, _kofs, key); \
|
||||
_node ? (type *)((char *)(_node) - _nofs) : NULL; \
|
||||
})
|
||||
|
||||
/* lookup from root <root>, the item of type <type> which contains the lowest
|
||||
* key that is strictly greater than <key>, using node member <nname> and key
|
||||
* member <kname>. Returns the pointer to the item, or NULL if not found.
|
||||
*/
|
||||
#define cebu32_item_lookup_gt(root, nname, kname, key, type) ({ \
|
||||
ptrdiff_t _nofs = offsetof(type, nname); \
|
||||
ptrdiff_t _kofs = offsetof(type, kname) - _nofs; \
|
||||
struct ceb_node *_node = cebu32_ofs_lookup_gt(root, _kofs, key); \
|
||||
_node ? (type *)((char *)(_node) - _nofs) : NULL; \
|
||||
})
|
||||
|
||||
/* lookup from root <root>, the first item immediately after item <item_ptr>,
|
||||
* using node member <nname> and key member <kname>, and returns either the
|
||||
* found item, or NULL if none exists.
|
||||
*/
|
||||
#define cebu32_item_next(root, nname, kname, item_ptr) ({ \
|
||||
ptrdiff_t _nofs = offsetof(typeof(*(item_ptr)), nname); \
|
||||
ptrdiff_t _kofs = offsetof(typeof(*(item_ptr)), kname) - _nofs; \
|
||||
struct ceb_node *_node = cebu32_ofs_next(root, _kofs, &(item_ptr)->nname); \
|
||||
_node ? (typeof(item_ptr))((char *)(_node) - _nofs) : NULL; \
|
||||
})
|
||||
|
||||
/* lookup from root <root>, the last item immediately before item <item_ptr>,
|
||||
* using node member <nname> and key member <kname>, and returns either the
|
||||
* found item, or NULL if none exists.
|
||||
*/
|
||||
#define cebu32_item_prev(root, nname, kname, item_ptr) ({ \
|
||||
ptrdiff_t _nofs = offsetof(typeof(*(item_ptr)), nname); \
|
||||
ptrdiff_t _kofs = offsetof(typeof(*(item_ptr)), kname) - _nofs; \
|
||||
struct ceb_node *_node = cebu32_ofs_prev(root, _kofs, &(item_ptr)->nname); \
|
||||
_node ? (typeof(item_ptr))((char *)(_node) - _nofs) : NULL; \
|
||||
})
|
||||
|
||||
/* lookup from root <root>, the item <item_ptr> using node member <nname> and
|
||||
* key member <kname>, deletes it and returns it. If the item is NULL or absent
|
||||
* from the tree, NULL is returned.
|
||||
*/
|
||||
#define cebu32_item_delete(root, nname, kname, item_ptr) ({ \
|
||||
ptrdiff_t _nofs = offsetof(typeof(*(item_ptr)), nname); \
|
||||
ptrdiff_t _kofs = offsetof(typeof(*(item_ptr)), kname) - _nofs; \
|
||||
typeof(item_ptr) _item = (item_ptr); \
|
||||
struct ceb_node *_node = cebu32_ofs_delete(root, _kofs, _item ? &_item->nname : NULL); \
|
||||
_node ? (typeof(item_ptr))((char *)(_node) - _nofs) : NULL; \
|
||||
})
|
||||
|
||||
/* lookup from root <root>, the first item of type <type> which contains the
|
||||
* key <key>, using node member <nname> and key member <kname>, deletes it and
|
||||
* returns it. If the key is not found in the tree, NULL is returned.
|
||||
*/
|
||||
#define cebu32_item_pick(root, nname, kname, key, type) ({ \
|
||||
ptrdiff_t _nofs = offsetof(type, nname); \
|
||||
ptrdiff_t _kofs = offsetof(type, kname) - _nofs; \
|
||||
struct ceb_node *_node = cebu32_ofs_pick(root, _kofs, key); \
|
||||
_node ? (type *)((char *)(_node) - _nofs) : NULL; \
|
||||
})
|
||||
|
||||
#endif /* _CEB32_TREE_H */
|
426
include/import/ceb64_tree.h
Normal file
426
include/import/ceb64_tree.h
Normal file
@ -0,0 +1,426 @@
|
||||
/*
|
||||
* Compact Elastic Binary Trees - exported functions for operations on u64 keys
|
||||
*
|
||||
* Copyright (C) 2014-2025 Willy Tarreau - w@1wt.eu
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef _CEB64_TREE_H
|
||||
#define _CEB64_TREE_H
|
||||
|
||||
#include "cebtree.h"
|
||||
#include <inttypes.h>
|
||||
|
||||
/* simpler version */
|
||||
struct ceb_node *ceb64_imm_insert(struct ceb_root **root, struct ceb_node *node);
|
||||
struct ceb_node *ceb64_imm_first(struct ceb_root *const *root);
|
||||
struct ceb_node *ceb64_imm_last(struct ceb_root *const *root);
|
||||
struct ceb_node *ceb64_imm_lookup(struct ceb_root *const *root, uint64_t key);
|
||||
struct ceb_node *ceb64_imm_lookup_le(struct ceb_root *const *root, uint64_t key);
|
||||
struct ceb_node *ceb64_imm_lookup_lt(struct ceb_root *const *root, uint64_t key);
|
||||
struct ceb_node *ceb64_imm_lookup_ge(struct ceb_root *const *root, uint64_t key);
|
||||
struct ceb_node *ceb64_imm_lookup_gt(struct ceb_root *const *root, uint64_t key);
|
||||
struct ceb_node *ceb64_imm_next_unique(struct ceb_root *const *root, struct ceb_node *node);
|
||||
struct ceb_node *ceb64_imm_prev_unique(struct ceb_root *const *root, struct ceb_node *node);
|
||||
struct ceb_node *ceb64_imm_next_dup(struct ceb_root *const *root, struct ceb_node *node);
|
||||
struct ceb_node *ceb64_imm_prev_dup(struct ceb_root *const *root, struct ceb_node *node);
|
||||
struct ceb_node *ceb64_imm_next(struct ceb_root *const *root, struct ceb_node *node);
|
||||
struct ceb_node *ceb64_imm_prev(struct ceb_root *const *root, struct ceb_node *node);
|
||||
struct ceb_node *ceb64_imm_delete(struct ceb_root **root, struct ceb_node *node);
|
||||
struct ceb_node *ceb64_imm_pick(struct ceb_root **root, uint64_t key);
|
||||
|
||||
struct ceb_node *cebu64_imm_insert(struct ceb_root **root, struct ceb_node *node);
|
||||
struct ceb_node *cebu64_imm_first(struct ceb_root *const *root);
|
||||
struct ceb_node *cebu64_imm_last(struct ceb_root *const *root);
|
||||
struct ceb_node *cebu64_imm_lookup(struct ceb_root *const *root, uint64_t key);
|
||||
struct ceb_node *cebu64_imm_lookup_le(struct ceb_root *const *root, uint64_t key);
|
||||
struct ceb_node *cebu64_imm_lookup_lt(struct ceb_root *const *root, uint64_t key);
|
||||
struct ceb_node *cebu64_imm_lookup_ge(struct ceb_root *const *root, uint64_t key);
|
||||
struct ceb_node *cebu64_imm_lookup_gt(struct ceb_root *const *root, uint64_t key);
|
||||
struct ceb_node *cebu64_imm_next(struct ceb_root *const *root, struct ceb_node *node);
|
||||
struct ceb_node *cebu64_imm_prev(struct ceb_root *const *root, struct ceb_node *node);
|
||||
struct ceb_node *cebu64_imm_delete(struct ceb_root **root, struct ceb_node *node);
|
||||
struct ceb_node *cebu64_imm_pick(struct ceb_root **root, uint64_t key);
|
||||
|
||||
/* generic dump function */
|
||||
void ceb64_imm_default_dump(struct ceb_root **ceb_root, const char *label, const void *ctx, int sub);
|
||||
|
||||
/* returns the pointer to the uint64_t key */
|
||||
static inline uint64_t *ceb64_imm_key(const struct ceb_node *node)
|
||||
{
|
||||
return (uint64_t *)ceb_key_ptr(node, sizeof(struct ceb_node));
|
||||
}
|
||||
|
||||
/* version taking a key offset */
|
||||
struct ceb_node *ceb64_ofs_insert(struct ceb_root **root, ptrdiff_t kofs, struct ceb_node *node);
|
||||
struct ceb_node *ceb64_ofs_first(struct ceb_root *const *root, ptrdiff_t kofs);
|
||||
struct ceb_node *ceb64_ofs_last(struct ceb_root *const *root, ptrdiff_t kofs);
|
||||
struct ceb_node *ceb64_ofs_lookup(struct ceb_root *const *root, ptrdiff_t kofs, uint64_t key);
|
||||
struct ceb_node *ceb64_ofs_lookup_le(struct ceb_root *const *root, ptrdiff_t kofs, uint64_t key);
|
||||
struct ceb_node *ceb64_ofs_lookup_lt(struct ceb_root *const *root, ptrdiff_t kofs, uint64_t key);
|
||||
struct ceb_node *ceb64_ofs_lookup_ge(struct ceb_root *const *root, ptrdiff_t kofs, uint64_t key);
|
||||
struct ceb_node *ceb64_ofs_lookup_gt(struct ceb_root *const *root, ptrdiff_t kofs, uint64_t key);
|
||||
struct ceb_node *ceb64_ofs_next_unique(struct ceb_root *const *root, ptrdiff_t kofs, struct ceb_node *node);
|
||||
struct ceb_node *ceb64_ofs_prev_unique(struct ceb_root *const *root, ptrdiff_t kofs, struct ceb_node *node);
|
||||
struct ceb_node *ceb64_ofs_next_dup(struct ceb_root *const *root, ptrdiff_t kofs, struct ceb_node *node);
|
||||
struct ceb_node *ceb64_ofs_prev_dup(struct ceb_root *const *root, ptrdiff_t kofs, struct ceb_node *node);
|
||||
struct ceb_node *ceb64_ofs_next(struct ceb_root *const *root, ptrdiff_t kofs, struct ceb_node *node);
|
||||
struct ceb_node *ceb64_ofs_prev(struct ceb_root *const *root, ptrdiff_t kofs, struct ceb_node *node);
|
||||
struct ceb_node *ceb64_ofs_delete(struct ceb_root **root, ptrdiff_t kofs, struct ceb_node *node);
|
||||
struct ceb_node *ceb64_ofs_pick(struct ceb_root **root, ptrdiff_t kofs, uint64_t key);
|
||||
|
||||
struct ceb_node *cebu64_ofs_insert(struct ceb_root **root, ptrdiff_t kofs, struct ceb_node *node);
|
||||
struct ceb_node *cebu64_ofs_first(struct ceb_root *const *root, ptrdiff_t kofs);
|
||||
struct ceb_node *cebu64_ofs_last(struct ceb_root *const *root, ptrdiff_t kofs);
|
||||
struct ceb_node *cebu64_ofs_lookup(struct ceb_root *const *root, ptrdiff_t kofs, uint64_t key);
|
||||
struct ceb_node *cebu64_ofs_lookup_le(struct ceb_root *const *root, ptrdiff_t kofs, uint64_t key);
|
||||
struct ceb_node *cebu64_ofs_lookup_lt(struct ceb_root *const *root, ptrdiff_t kofs, uint64_t key);
|
||||
struct ceb_node *cebu64_ofs_lookup_ge(struct ceb_root *const *root, ptrdiff_t kofs, uint64_t key);
|
||||
struct ceb_node *cebu64_ofs_lookup_gt(struct ceb_root *const *root, ptrdiff_t kofs, uint64_t key);
|
||||
struct ceb_node *cebu64_ofs_next(struct ceb_root *const *root, ptrdiff_t kofs, struct ceb_node *node);
|
||||
struct ceb_node *cebu64_ofs_prev(struct ceb_root *const *root, ptrdiff_t kofs, struct ceb_node *node);
|
||||
struct ceb_node *cebu64_ofs_delete(struct ceb_root **root, ptrdiff_t kofs, struct ceb_node *node);
|
||||
struct ceb_node *cebu64_ofs_pick(struct ceb_root **root, ptrdiff_t kofs, uint64_t key);
|
||||
|
||||
/* generic dump function taking a key offset */
|
||||
void ceb64_ofs_default_dump(struct ceb_root *const *root, ptrdiff_t kofs, const char *label, const void *ctx, int sub);
|
||||
|
||||
/* returns the pointer to the uint64_t key */
|
||||
static inline uint64_t *ceb64_ofs_key(const struct ceb_node *node, ptrdiff_t kofs)
|
||||
{
|
||||
return (uint64_t *)ceb_key_ptr(node, kofs);
|
||||
}
|
||||
|
||||
/* insert at root <root>, the item <item_ptr> using node member <nname> and
|
||||
* key member <kname>, and returns either the inserted item, or the one that
|
||||
* was found there.
|
||||
*/
|
||||
#define ceb64_item_insert(root, nname, kname, item_ptr) ({ \
|
||||
ptrdiff_t _nofs = offsetof(typeof(*(item_ptr)), nname); \
|
||||
ptrdiff_t _kofs = offsetof(typeof(*(item_ptr)), kname) - _nofs; \
|
||||
struct ceb_node *_node = ceb64_ofs_insert(root, _kofs, &(item_ptr)->nname); \
|
||||
(typeof(item_ptr))((char *)(_node) - _nofs); \
|
||||
})
|
||||
|
||||
/* descend root <root>, and return the first item of type <type>, using node
|
||||
* member <nname> and key member <kname>, or NULL if the tree is empty.
|
||||
*/
|
||||
#define ceb64_item_first(root, nname, kname, type) ({ \
|
||||
ptrdiff_t _nofs = offsetof(type, nname); \
|
||||
ptrdiff_t _kofs = offsetof(type, kname) - _nofs; \
|
||||
struct ceb_node *_node = ceb64_ofs_first(root, _kofs); \
|
||||
_node ? (type *)((char *)(_node) - _nofs) : NULL; \
|
||||
})
|
||||
|
||||
/* descend root <root>, and return the last item of type <type>, using node
|
||||
* member <nname> and key member <kname>, or NULL if the tree is empty.
|
||||
*/
|
||||
#define ceb64_item_last(root, nname, kname, type) ({ \
|
||||
ptrdiff_t _nofs = offsetof(type, nname); \
|
||||
ptrdiff_t _kofs = offsetof(type, kname) - _nofs; \
|
||||
struct ceb_node *_node = ceb64_ofs_last(root, _kofs); \
|
||||
_node ? (type *)((char *)(_node) - _nofs) : NULL; \
|
||||
})
|
||||
|
||||
/* lookup from root <root>, the first item of type <type> which contains the
|
||||
* key <key>, using node member <nname> and key member <kname>. Returns the
|
||||
* pointer to the item, or NULL if not found.
|
||||
*/
|
||||
#define ceb64_item_lookup(root, nname, kname, key, type) ({ \
|
||||
ptrdiff_t _nofs = offsetof(type, nname); \
|
||||
ptrdiff_t _kofs = offsetof(type, kname) - _nofs; \
|
||||
struct ceb_node *_node = ceb64_ofs_lookup(root, _kofs, key); \
|
||||
_node ? (type *)((char *)(_node) - _nofs) : NULL; \
|
||||
})
|
||||
|
||||
/* lookup from root <root>, the item of type <type> which contains the last of
|
||||
* the greatest keys that are lower than or equal to <key>, using node member
|
||||
* <nname> and key member <kname>. Returns the pointer to the item, or NULL if
|
||||
* not found.
|
||||
*/
|
||||
#define ceb64_item_lookup_le(root, nname, kname, key, type) ({ \
|
||||
ptrdiff_t _nofs = offsetof(type, nname); \
|
||||
ptrdiff_t _kofs = offsetof(type, kname) - _nofs; \
|
||||
struct ceb_node *_node = ceb64_ofs_lookup_le(root, _kofs, key); \
|
||||
_node ? (type *)((char *)(_node) - _nofs) : NULL; \
|
||||
})
|
||||
|
||||
/* lookup from root <root>, the item of type <type> which contains the last of
|
||||
* the greatest keys that are strictly lower than <key>, using node member
|
||||
* <nname> and key member <kname>. Returns the pointer to the item, or NULL if
|
||||
* not found.
|
||||
*/
|
||||
#define ceb64_item_lookup_lt(root, nname, kname, key, type) ({ \
|
||||
ptrdiff_t _nofs = offsetof(type, nname); \
|
||||
ptrdiff_t _kofs = offsetof(type, kname) - _nofs; \
|
||||
struct ceb_node *_node = ceb64_ofs_lookup_lt(root, _kofs, key); \
|
||||
_node ? (type *)((char *)(_node) - _nofs) : NULL; \
|
||||
})
|
||||
|
||||
/* lookup from root <root>, the item of type <type> which contains the first of
|
||||
* the lowest keys key that are greater than or equal to <key>, using node
|
||||
* member <nname> and key member <kname>. Returns the pointer to the item, or
|
||||
* NULL if not found.
|
||||
*/
|
||||
#define ceb64_item_lookup_ge(root, nname, kname, key, type) ({ \
|
||||
ptrdiff_t _nofs = offsetof(type, nname); \
|
||||
ptrdiff_t _kofs = offsetof(type, kname) - _nofs; \
|
||||
struct ceb_node *_node = ceb64_ofs_lookup_ge(root, _kofs, key); \
|
||||
_node ? (type *)((char *)(_node) - _nofs) : NULL; \
|
||||
})
|
||||
|
||||
/* lookup from root <root>, the item of type <type> which contains the first of
|
||||
* the lowest keys that are strictly greater than <key>, using node member
|
||||
* <nname> and key member <kname>. Returns the pointer to the item, or NULL if
|
||||
* not found.
|
||||
*/
|
||||
#define ceb64_item_lookup_gt(root, nname, kname, key, type) ({ \
|
||||
ptrdiff_t _nofs = offsetof(type, nname); \
|
||||
ptrdiff_t _kofs = offsetof(type, kname) - _nofs; \
|
||||
struct ceb_node *_node = ceb64_ofs_lookup_gt(root, _kofs, key); \
|
||||
_node ? (type *)((char *)(_node) - _nofs) : NULL; \
|
||||
})
|
||||
|
||||
/* lookup from root <root>, the first item after item <item_ptr> that has a
|
||||
* strictly greater key, using node member <nname> and key member <kname>, and
|
||||
* returns either the found item, or NULL if none exists.
|
||||
*/
|
||||
#define ceb64_item_next_unique(root, nname, kname, item_ptr) ({ \
|
||||
ptrdiff_t _nofs = offsetof(typeof(*(item_ptr)), nname); \
|
||||
ptrdiff_t _kofs = offsetof(typeof(*(item_ptr)), kname) - _nofs; \
|
||||
struct ceb_node *_node = ceb64_ofs_next_unique(root, _kofs, &(item_ptr)->nname);\
|
||||
_node ? (typeof(item_ptr))((char *)(_node) - _nofs) : NULL; \
|
||||
})
|
||||
|
||||
/* lookup from root <root>, the last item before item <item_ptr> that has a
|
||||
* strictly lower key, using node member <nname> and key member <kname>, and
|
||||
* returns either the found item, or NULL if none exists.
|
||||
*/
|
||||
#define ceb64_item_prev_unique(root, nname, kname, item_ptr) ({ \
|
||||
ptrdiff_t _nofs = offsetof(typeof(*(item_ptr)), nname); \
|
||||
ptrdiff_t _kofs = offsetof(typeof(*(item_ptr)), kname) - _nofs; \
|
||||
struct ceb_node *_node = ceb64_ofs_prev_unique(root, _kofs, &(item_ptr)->nname);\
|
||||
_node ? (typeof(item_ptr))((char *)(_node) - _nofs) : NULL; \
|
||||
})
|
||||
|
||||
/* lookup from root <root>, the first item after item <item_ptr> that has
|
||||
* exactly the same key, using node member <nname> and key member <kname>, and
|
||||
* returns either the found item, or NULL if none exists.
|
||||
*/
|
||||
#define ceb64_item_next_dup(root, nname, kname, item_ptr) ({ \
|
||||
ptrdiff_t _nofs = offsetof(typeof(*(item_ptr)), nname); \
|
||||
ptrdiff_t _kofs = offsetof(typeof(*(item_ptr)), kname) - _nofs; \
|
||||
struct ceb_node *_node = ceb64_ofs_next_dup(root, _kofs, &(item_ptr)->nname); \
|
||||
_node ? (typeof(item_ptr))((char *)(_node) - _nofs) : NULL; \
|
||||
})
|
||||
|
||||
/* lookup from root <root>, the last item before item <item_ptr> that has
|
||||
* exactly the same key, using node member <nname> and key member <kname>, and
|
||||
* returns either the found item, or NULL if none exists.
|
||||
*/
|
||||
#define ceb64_item_prev_dup(root, nname, kname, item_ptr) ({ \
|
||||
ptrdiff_t _nofs = offsetof(typeof(*(item_ptr)), nname); \
|
||||
ptrdiff_t _kofs = offsetof(typeof(*(item_ptr)), kname) - _nofs; \
|
||||
struct ceb_node *_node = ceb64_ofs_prev_dup(root, _kofs, &(item_ptr)->nname); \
|
||||
_node ? (typeof(item_ptr))((char *)(_node) - _nofs) : NULL; \
|
||||
})
|
||||
|
||||
/* lookup from root <root>, the first item immediately after item <item_ptr>,
|
||||
* using node member <nname> and key member <kname>, and returns either the
|
||||
* found item, or NULL if none exists.
|
||||
*/
|
||||
#define ceb64_item_next(root, nname, kname, item_ptr) ({ \
|
||||
ptrdiff_t _nofs = offsetof(typeof(*(item_ptr)), nname); \
|
||||
ptrdiff_t _kofs = offsetof(typeof(*(item_ptr)), kname) - _nofs; \
|
||||
struct ceb_node *_node = ceb64_ofs_next(root, _kofs, &(item_ptr)->nname); \
|
||||
_node ? (typeof(item_ptr))((char *)(_node) - _nofs) : NULL; \
|
||||
})
|
||||
|
||||
/* lookup from root <root>, the last item immediately before item <item_ptr>,
|
||||
* using node member <nname> and key member <kname>, and returns either the
|
||||
* found item, or NULL if none exists.
|
||||
*/
|
||||
#define ceb64_item_prev(root, nname, kname, item_ptr) ({ \
|
||||
ptrdiff_t _nofs = offsetof(typeof(*(item_ptr)), nname); \
|
||||
ptrdiff_t _kofs = offsetof(typeof(*(item_ptr)), kname) - _nofs; \
|
||||
struct ceb_node *_node = ceb64_ofs_prev(root, _kofs, &(item_ptr)->nname); \
|
||||
_node ? (typeof(item_ptr))((char *)(_node) - _nofs) : NULL; \
|
||||
})
|
||||
|
||||
/* lookup from root <root>, the item <item_ptr> using node member <nname> and
|
||||
* key member <kname>, deletes it and returns it. If the item is NULL or absent
|
||||
* from the tree, NULL is returned.
|
||||
*/
|
||||
#define ceb64_item_delete(root, nname, kname, item_ptr) ({ \
|
||||
ptrdiff_t _nofs = offsetof(typeof(*(item_ptr)), nname); \
|
||||
ptrdiff_t _kofs = offsetof(typeof(*(item_ptr)), kname) - _nofs; \
|
||||
typeof(item_ptr) _item = (item_ptr); \
|
||||
struct ceb_node *_node = ceb64_ofs_delete(root, _kofs, _item ? &_item->nname : NULL); \
|
||||
_node ? (typeof(item_ptr))((char *)(_node) - _nofs) : NULL; \
|
||||
})
|
||||
|
||||
/* lookup from root <root>, the first item of type <type> which contains the
|
||||
* key <key>, using node member <nname> and key member <kname>, deletes it and
|
||||
* returns it. If the key is not found in the tree, NULL is returned.
|
||||
*/
|
||||
#define ceb64_item_pick(root, nname, kname, key, type) ({ \
|
||||
ptrdiff_t _nofs = offsetof(type, nname); \
|
||||
ptrdiff_t _kofs = offsetof(type, kname) - _nofs; \
|
||||
struct ceb_node *_node = ceb64_ofs_pick(root, _kofs, key); \
|
||||
_node ? (type *)((char *)(_node) - _nofs) : NULL; \
|
||||
})
|
||||
|
||||
/*** versions using unique keys below ***/
|
||||
|
||||
/* insert at root <root>, the item <item_ptr> using node member <nname> and key
|
||||
* member <kname>, and returns either the inserted item, or the one that was
|
||||
* found there.
|
||||
*/
|
||||
#define cebu64_item_insert(root, nname, kname, item_ptr) ({ \
|
||||
ptrdiff_t _nofs = offsetof(typeof(*(item_ptr)), nname); \
|
||||
ptrdiff_t _kofs = offsetof(typeof(*(item_ptr)), kname) - _nofs; \
|
||||
struct ceb_node *_node = cebu64_ofs_insert(root, _kofs, &(item_ptr)->nname); \
|
||||
(typeof(item_ptr))((char *)(_node) - _nofs); \
|
||||
})
|
||||
|
||||
/* descend root <root>, and return the first item of type <type>, using node
|
||||
* member <nname> and key member <kname>, or NULL if the tree is empty.
|
||||
*/
|
||||
#define cebu64_item_first(root, nname, kname, type) ({ \
|
||||
ptrdiff_t _nofs = offsetof(type, nname); \
|
||||
ptrdiff_t _kofs = offsetof(type, kname) - _nofs; \
|
||||
struct ceb_node *_node = cebu64_ofs_first(root, _kofs); \
|
||||
_node ? (type *)((char *)(_node) - _nofs) : NULL; \
|
||||
})
|
||||
|
||||
/* descend root <root>, and return the last item of type <type>, using node
|
||||
* member <nname> and key member <kname>, or NULL if the tree is empty.
|
||||
*/
|
||||
#define cebu64_item_last(root, nname, kname, type) ({ \
|
||||
ptrdiff_t _nofs = offsetof(type, nname); \
|
||||
ptrdiff_t _kofs = offsetof(type, kname) - _nofs; \
|
||||
struct ceb_node *_node = cebu64_ofs_last(root, _kofs); \
|
||||
_node ? (type *)((char *)(_node) - _nofs) : NULL; \
|
||||
})
|
||||
|
||||
/* lookup from root <root>, the item of type <type> which contains the key
|
||||
* <key>, using node member <nname> and key member <kname>. Returns the pointer
|
||||
* to the item, or NULL if not found.
|
||||
*/
|
||||
#define cebu64_item_lookup(root, nname, kname, key, type) ({ \
|
||||
ptrdiff_t _nofs = offsetof(type, nname); \
|
||||
ptrdiff_t _kofs = offsetof(type, kname) - _nofs; \
|
||||
struct ceb_node *_node = cebu64_ofs_lookup(root, _kofs, key); \
|
||||
_node ? (type *)((char *)(_node) - _nofs) : NULL; \
|
||||
})
|
||||
|
||||
/* lookup from root <root>, the item of type <type> which contains the greatest
|
||||
* key that is lower than or equal to <key>, using node member <nname> and key
|
||||
* member <kname>. Returns the pointer to the item, or NULL if not found.
|
||||
*/
|
||||
#define cebu64_item_lookup_le(root, nname, kname, key, type) ({ \
|
||||
ptrdiff_t _nofs = offsetof(type, nname); \
|
||||
ptrdiff_t _kofs = offsetof(type, kname) - _nofs; \
|
||||
struct ceb_node *_node = cebu64_ofs_lookup_le(root, _kofs, key); \
|
||||
_node ? (type *)((char *)(_node) - _nofs) : NULL; \
|
||||
})
|
||||
|
||||
/* lookup from root <root>, the item of type <type> which contains the greatest
|
||||
* key that is strictly lower than <key>, using node member <nname> and key
|
||||
* member <kname>. Returns the pointer to the item, or NULL if not found.
|
||||
*/
|
||||
#define cebu64_item_lookup_lt(root, nname, kname, key, type) ({ \
|
||||
ptrdiff_t _nofs = offsetof(type, nname); \
|
||||
ptrdiff_t _kofs = offsetof(type, kname) - _nofs; \
|
||||
struct ceb_node *_node = cebu64_ofs_lookup_lt(root, _kofs, key); \
|
||||
_node ? (type *)((char *)(_node) - _nofs) : NULL; \
|
||||
})
|
||||
|
||||
/* lookup from root <root>, the item of type <type> which contains the lowest
|
||||
* key key that is greater than or equal to <key>, using node member <nname>
|
||||
* and key member <kname>. Returns the pointer to the item, or NULL if not
|
||||
* found.
|
||||
*/
|
||||
#define cebu64_item_lookup_ge(root, nname, kname, key, type) ({ \
|
||||
ptrdiff_t _nofs = offsetof(type, nname); \
|
||||
ptrdiff_t _kofs = offsetof(type, kname) - _nofs; \
|
||||
struct ceb_node *_node = cebu64_ofs_lookup_ge(root, _kofs, key); \
|
||||
_node ? (type *)((char *)(_node) - _nofs) : NULL; \
|
||||
})
|
||||
|
||||
/* lookup from root <root>, the item of type <type> which contains the lowest
|
||||
* key that is strictly greater than <key>, using node member <nname> and key
|
||||
* member <kname>. Returns the pointer to the item, or NULL if not found.
|
||||
*/
|
||||
#define cebu64_item_lookup_gt(root, nname, kname, key, type) ({ \
|
||||
ptrdiff_t _nofs = offsetof(type, nname); \
|
||||
ptrdiff_t _kofs = offsetof(type, kname) - _nofs; \
|
||||
struct ceb_node *_node = cebu64_ofs_lookup_gt(root, _kofs, key); \
|
||||
_node ? (type *)((char *)(_node) - _nofs) : NULL; \
|
||||
})
|
||||
|
||||
/* lookup from root <root>, the first item immediately after item <item_ptr>,
|
||||
* using node member <nname> and key member <kname>, and returns either the
|
||||
* found item, or NULL if none exists.
|
||||
*/
|
||||
#define cebu64_item_next(root, nname, kname, item_ptr) ({ \
|
||||
ptrdiff_t _nofs = offsetof(typeof(*(item_ptr)), nname); \
|
||||
ptrdiff_t _kofs = offsetof(typeof(*(item_ptr)), kname) - _nofs; \
|
||||
struct ceb_node *_node = cebu64_ofs_next(root, _kofs, &(item_ptr)->nname); \
|
||||
_node ? (typeof(item_ptr))((char *)(_node) - _nofs) : NULL; \
|
||||
})
|
||||
|
||||
/* lookup from root <root>, the last item immediately before item <item_ptr>,
|
||||
* using node member <nname> and key member <kname>, and returns either the
|
||||
* found item, or NULL if none exists.
|
||||
*/
|
||||
#define cebu64_item_prev(root, nname, kname, item_ptr) ({ \
|
||||
ptrdiff_t _nofs = offsetof(typeof(*(item_ptr)), nname); \
|
||||
ptrdiff_t _kofs = offsetof(typeof(*(item_ptr)), kname) - _nofs; \
|
||||
struct ceb_node *_node = cebu64_ofs_prev(root, _kofs, &(item_ptr)->nname); \
|
||||
_node ? (typeof(item_ptr))((char *)(_node) - _nofs) : NULL; \
|
||||
})
|
||||
|
||||
/* lookup from root <root>, the item <item_ptr> using node member <nname> and
|
||||
* key member <kname>, deletes it and returns it. If the item is NULL or absent
|
||||
* from the tree, NULL is returned.
|
||||
*/
|
||||
#define cebu64_item_delete(root, nname, kname, item_ptr) ({ \
|
||||
ptrdiff_t _nofs = offsetof(typeof(*(item_ptr)), nname); \
|
||||
ptrdiff_t _kofs = offsetof(typeof(*(item_ptr)), kname) - _nofs; \
|
||||
typeof(item_ptr) _item = (item_ptr); \
|
||||
struct ceb_node *_node = cebu64_ofs_delete(root, _kofs, _item ? &_item->nname : NULL); \
|
||||
_node ? (typeof(item_ptr))((char *)(_node) - _nofs) : NULL; \
|
||||
})
|
||||
|
||||
/* lookup from root <root>, the first item of type <type> which contains the
|
||||
* key <key>, using node member <nname> and key member <kname>, deletes it and
|
||||
* returns it. If the key is not found in the tree, NULL is returned.
|
||||
*/
|
||||
#define cebu64_item_pick(root, nname, kname, key, type) ({ \
|
||||
ptrdiff_t _nofs = offsetof(type, nname); \
|
||||
ptrdiff_t _kofs = offsetof(type, kname) - _nofs; \
|
||||
struct ceb_node *_node = cebu64_ofs_pick(root, _kofs, key); \
|
||||
_node ? (type *)((char *)(_node) - _nofs) : NULL; \
|
||||
})
|
||||
|
||||
#endif /* _CEB64_TREE_H */
|
55
include/import/ceba_tree.h
Normal file
55
include/import/ceba_tree.h
Normal file
@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Compact Elastic Binary Trees - exported functions operating on addr keys
|
||||
*
|
||||
* Copyright (C) 2014-2025 Willy Tarreau - w@1wt.eu
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef _CEBA_TREE_H
|
||||
#define _CEBA_TREE_H
|
||||
|
||||
#include "cebtree.h"
|
||||
|
||||
/* simpler version */
|
||||
struct ceb_node *cebua_imm_insert(struct ceb_root **root, struct ceb_node *node);
|
||||
struct ceb_node *cebua_imm_first(struct ceb_root *const *root);
|
||||
struct ceb_node *cebua_imm_last(struct ceb_root *const *root);
|
||||
struct ceb_node *cebua_imm_lookup(struct ceb_root *const *root, const void *key);
|
||||
struct ceb_node *cebua_imm_lookup_le(struct ceb_root *const *root, const void *key);
|
||||
struct ceb_node *cebua_imm_lookup_lt(struct ceb_root *const *root, const void *key);
|
||||
struct ceb_node *cebua_imm_lookup_ge(struct ceb_root *const *root, const void *key);
|
||||
struct ceb_node *cebua_imm_lookup_gt(struct ceb_root *const *root, const void *key);
|
||||
struct ceb_node *cebua_imm_next(struct ceb_root *const *root, struct ceb_node *node);
|
||||
struct ceb_node *cebua_imm_prev(struct ceb_root *const *root, struct ceb_node *node);
|
||||
struct ceb_node *cebua_imm_delete(struct ceb_root **root, struct ceb_node *node);
|
||||
struct ceb_node *cebua_imm_pick(struct ceb_root **root, const void *key);
|
||||
|
||||
/* generic dump function */
|
||||
void ceba_imm_default_dump(struct ceb_root *const *root, const char *label, const void *ctx, int sub);
|
||||
|
||||
/* returns the pointer to the area that immediately follows the node */
|
||||
static inline void *ceba_imm_key(const struct ceb_node *node)
|
||||
{
|
||||
return (void *)ceb_key_ptr(node, sizeof(struct ceb_node));
|
||||
}
|
||||
|
||||
#endif /* _CEBA_TREE_H */
|
419
include/import/cebb_tree.h
Normal file
419
include/import/cebb_tree.h
Normal file
@ -0,0 +1,419 @@
|
||||
/*
|
||||
* Compact Elastic Binary Trees - exported functions operating on mb keys
|
||||
*
|
||||
* Copyright (C) 2014-2025 Willy Tarreau - w@1wt.eu
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef _CEBB_TREE_H
|
||||
#define _CEBB_TREE_H
|
||||
|
||||
#include "cebtree.h"
|
||||
|
||||
/* simpler version */
|
||||
struct ceb_node *cebb_imm_insert(struct ceb_root **root, struct ceb_node *node, size_t len);
|
||||
struct ceb_node *cebb_imm_first(struct ceb_root *const *root, size_t len);
|
||||
struct ceb_node *cebb_imm_last(struct ceb_root *const *root, size_t len);
|
||||
struct ceb_node *cebb_imm_lookup(struct ceb_root *const *root, const void *key, size_t len);
|
||||
struct ceb_node *cebb_imm_lookup_le(struct ceb_root *const *root, const void *key, size_t len);
|
||||
struct ceb_node *cebb_imm_lookup_lt(struct ceb_root *const *root, const void *key, size_t len);
|
||||
struct ceb_node *cebb_imm_lookup_ge(struct ceb_root *const *root, const void *key, size_t len);
|
||||
struct ceb_node *cebb_imm_lookup_gt(struct ceb_root *const *root, const void *key, size_t len);
|
||||
struct ceb_node *cebb_imm_next_unique(struct ceb_root *const *root, struct ceb_node *node, size_t len);
|
||||
struct ceb_node *cebb_imm_prev_unique(struct ceb_root *const *root, struct ceb_node *node, size_t len);
|
||||
struct ceb_node *cebb_imm_next_dup(struct ceb_root *const *root, struct ceb_node *node, size_t len);
|
||||
struct ceb_node *cebb_imm_prev_dup(struct ceb_root *const *root, struct ceb_node *node, size_t len);
|
||||
struct ceb_node *cebb_imm_next(struct ceb_root *const *root, struct ceb_node *node, size_t len);
|
||||
struct ceb_node *cebb_imm_prev(struct ceb_root *const *root, struct ceb_node *node, size_t len);
|
||||
struct ceb_node *cebb_imm_delete(struct ceb_root **root, struct ceb_node *node, size_t len);
|
||||
struct ceb_node *cebb_imm_pick(struct ceb_root **root, const void *key, size_t len);
|
||||
|
||||
struct ceb_node *cebub_imm_insert(struct ceb_root **root, struct ceb_node *node, size_t len);
|
||||
struct ceb_node *cebub_imm_first(struct ceb_root *const *root, size_t len);
|
||||
struct ceb_node *cebub_imm_last(struct ceb_root *const *root, size_t len);
|
||||
struct ceb_node *cebub_imm_lookup(struct ceb_root *const *root, const void *key, size_t len);
|
||||
struct ceb_node *cebub_imm_lookup_le(struct ceb_root *const *root, const void *key, size_t len);
|
||||
struct ceb_node *cebub_imm_lookup_lt(struct ceb_root *const *root, const void *key, size_t len);
|
||||
struct ceb_node *cebub_imm_lookup_ge(struct ceb_root *const *root, const void *key, size_t len);
|
||||
struct ceb_node *cebub_imm_lookup_gt(struct ceb_root *const *root, const void *key, size_t len);
|
||||
struct ceb_node *cebub_imm_next(struct ceb_root *const *root, struct ceb_node *node, size_t len);
|
||||
struct ceb_node *cebub_imm_prev(struct ceb_root *const *root, struct ceb_node *node, size_t len);
|
||||
struct ceb_node *cebub_imm_delete(struct ceb_root **root, struct ceb_node *node, size_t len);
|
||||
struct ceb_node *cebub_imm_pick(struct ceb_root **root, const void *key, size_t len);
|
||||
|
||||
/* returns the pointer to the void* key that follows the node */
|
||||
static inline void *cebb_imm_key(const struct ceb_node *node)
|
||||
{
|
||||
return (void *)ceb_key_ptr(node, sizeof(struct ceb_node));
|
||||
}
|
||||
|
||||
/* version taking a key offset */
|
||||
struct ceb_node *cebb_ofs_insert(struct ceb_root **root, ptrdiff_t kofs, struct ceb_node *node, size_t len);
|
||||
struct ceb_node *cebb_ofs_first(struct ceb_root *const *root, ptrdiff_t kofs, size_t len);
|
||||
struct ceb_node *cebb_ofs_last(struct ceb_root *const *root, ptrdiff_t kofs, size_t len);
|
||||
struct ceb_node *cebb_ofs_lookup(struct ceb_root *const *root, ptrdiff_t kofs, const void *key, size_t len);
|
||||
struct ceb_node *cebb_ofs_lookup_le(struct ceb_root *const *root, ptrdiff_t kofs, const void *key, size_t len);
|
||||
struct ceb_node *cebb_ofs_lookup_lt(struct ceb_root *const *root, ptrdiff_t kofs, const void *key, size_t len);
|
||||
struct ceb_node *cebb_ofs_lookup_ge(struct ceb_root *const *root, ptrdiff_t kofs, const void *key, size_t len);
|
||||
struct ceb_node *cebb_ofs_lookup_gt(struct ceb_root *const *root, ptrdiff_t kofs, const void *key, size_t len);
|
||||
struct ceb_node *cebb_ofs_next_unique(struct ceb_root *const *root, ptrdiff_t kofs, struct ceb_node *node, size_t len);
|
||||
struct ceb_node *cebb_ofs_prev_unique(struct ceb_root *const *root, ptrdiff_t kofs, struct ceb_node *node, size_t len);
|
||||
struct ceb_node *cebb_ofs_next_dup(struct ceb_root *const *root, ptrdiff_t kofs, struct ceb_node *node, size_t len);
|
||||
struct ceb_node *cebb_ofs_prev_dup(struct ceb_root *const *root, ptrdiff_t kofs, struct ceb_node *node, size_t len);
|
||||
struct ceb_node *cebb_ofs_next(struct ceb_root *const *root, ptrdiff_t kofs, struct ceb_node *node, size_t len);
|
||||
struct ceb_node *cebb_ofs_prev(struct ceb_root *const *root, ptrdiff_t kofs, struct ceb_node *node, size_t len);
|
||||
struct ceb_node *cebb_ofs_delete(struct ceb_root **root, ptrdiff_t kofs, struct ceb_node *node, size_t len);
|
||||
struct ceb_node *cebb_ofs_pick(struct ceb_root **root, ptrdiff_t kofs, const void *key, size_t len);
|
||||
|
||||
struct ceb_node *cebub_ofs_insert(struct ceb_root **root, ptrdiff_t kofs, struct ceb_node *node, size_t len);
|
||||
struct ceb_node *cebub_ofs_first(struct ceb_root *const *root, ptrdiff_t kofs, size_t len);
|
||||
struct ceb_node *cebub_ofs_last(struct ceb_root *const *root, ptrdiff_t kofs, size_t len);
|
||||
struct ceb_node *cebub_ofs_lookup(struct ceb_root *const *root, ptrdiff_t kofs, const void *key, size_t len);
|
||||
struct ceb_node *cebub_ofs_lookup_le(struct ceb_root *const *root, ptrdiff_t kofs, const void *key, size_t len);
|
||||
struct ceb_node *cebub_ofs_lookup_lt(struct ceb_root *const *root, ptrdiff_t kofs, const void *key, size_t len);
|
||||
struct ceb_node *cebub_ofs_lookup_ge(struct ceb_root *const *root, ptrdiff_t kofs, const void *key, size_t len);
|
||||
struct ceb_node *cebub_ofs_lookup_gt(struct ceb_root *const *root, ptrdiff_t kofs, const void *key, size_t len);
|
||||
struct ceb_node *cebub_ofs_next(struct ceb_root *const *root, ptrdiff_t kofs, struct ceb_node *node, size_t len);
|
||||
struct ceb_node *cebub_ofs_prev(struct ceb_root *const *root, ptrdiff_t kofs, struct ceb_node *node, size_t len);
|
||||
struct ceb_node *cebub_ofs_delete(struct ceb_root **root, ptrdiff_t kofs, struct ceb_node *node, size_t len);
|
||||
struct ceb_node *cebub_ofs_pick(struct ceb_root **root, ptrdiff_t kofs, const void *key, size_t len);
|
||||
|
||||
/* returns the pointer to the void* key*/
|
||||
static inline void *cebb_ofs_key(const struct ceb_node *node, ptrdiff_t kofs)
|
||||
{
|
||||
return (void*)ceb_key_ptr(node, kofs);
|
||||
}
|
||||
|
||||
/* insert at root <root>, the item <item_ptr> using node member <nname> and key
|
||||
* member <kname>, and length <len> and returns either the inserted item, or
|
||||
* the one that was found there.
|
||||
*/
|
||||
#define cebb_item_insert(root, nname, kname, len, item_ptr) ({ \
|
||||
ptrdiff_t _nofs = offsetof(typeof(*(item_ptr)), nname); \
|
||||
ptrdiff_t _kofs = offsetof(typeof(*(item_ptr)), kname) - _nofs; \
|
||||
struct ceb_node *_node = cebb_ofs_insert(root, _kofs, &(item_ptr)->nname, len); \
|
||||
(typeof(item_ptr))((char *)(_node) - _nofs); \
|
||||
})
|
||||
|
||||
/* descend root <root>, and return the first item of type <type>, using node
|
||||
* member <nname> and key member <kname>, or NULL if the tree is empty.
|
||||
*/
|
||||
#define cebb_item_first(root, nname, kname, len, type) ({ \
|
||||
ptrdiff_t _nofs = offsetof(type, nname); \
|
||||
ptrdiff_t _kofs = offsetof(type, kname) - _nofs; \
|
||||
struct ceb_node *_node = cebb_ofs_first(root, _kofs, len); \
|
||||
_node ? (type *)((char *)(_node) - _nofs) : NULL; \
|
||||
})
|
||||
|
||||
/* descend root <root>, and return the last item of type <type>, using node
|
||||
* member <nname> and key member <kname>, or NULL if the tree is empty.
|
||||
*/
|
||||
#define cebb_item_last(root, nname, kname, len, type) ({ \
|
||||
ptrdiff_t _nofs = offsetof(type, nname); \
|
||||
ptrdiff_t _kofs = offsetof(type, kname) - _nofs; \
|
||||
struct ceb_node *_node = cebb_ofs_last(root, _kofs, len); \
|
||||
_node ? (type *)((char *)(_node) - _nofs) : NULL; \
|
||||
})
|
||||
|
||||
/* lookup from root <root>, the first item of type <type> which contains the
|
||||
* key <key>, using node member <nname> and key member <kname>. Returns the
|
||||
* pointer to the item, or NULL if not found.
|
||||
*/
|
||||
#define cebb_item_lookup(root, nname, kname, key, len, type) ({ \
|
||||
ptrdiff_t _nofs = offsetof(type, nname); \
|
||||
ptrdiff_t _kofs = offsetof(type, kname) - _nofs; \
|
||||
struct ceb_node *_node = cebb_ofs_lookup(root, _kofs, key, len); \
|
||||
_node ? (type *)((char *)(_node) - _nofs) : NULL; \
|
||||
})
|
||||
|
||||
/* lookup from root <root>, the item of type <type> which contains the last of
|
||||
* the greatest keys that are lower than or equal to <key>, using node member
|
||||
* <nname> and key member <kname>. Returns the pointer to the item, or NULL if
|
||||
* not found.
|
||||
*/
|
||||
#define cebb_item_lookup_le(root, nname, kname, key, len, type) ({ \
|
||||
ptrdiff_t _nofs = offsetof(type, nname); \
|
||||
ptrdiff_t _kofs = offsetof(type, kname) - _nofs; \
|
||||
struct ceb_node *_node = cebb_ofs_lookup_le(root, _kofs, key, len); \
|
||||
_node ? (type *)((char *)(_node) - _nofs) : NULL; \
|
||||
})
|
||||
|
||||
/* lookup from root <root>, the item of type <type> which contains the last of
|
||||
* the greatest keys that are strictly lower than <key>, using node member
|
||||
* <nname> and key member <kname>. Returns the pointer to the item, or NULL if
|
||||
* not found.
|
||||
*/
|
||||
#define cebb_item_lookup_lt(root, nname, kname, key, len, type) ({ \
|
||||
ptrdiff_t _nofs = offsetof(type, nname); \
|
||||
ptrdiff_t _kofs = offsetof(type, kname) - _nofs; \
|
||||
struct ceb_node *_node = cebb_ofs_lookup_lt(root, _kofs, key, len); \
|
||||
_node ? (type *)((char *)(_node) - _nofs) : NULL; \
|
||||
})
|
||||
|
||||
/* lookup from root <root>, the item of type <type> which contains the first of
|
||||
* the lowest keys key that are greater than or equal to <key>, using node
|
||||
* member <nname> and key member <kname>. Returns the pointer to the item, or
|
||||
* NULL if not found.
|
||||
*/
|
||||
#define cebb_item_lookup_ge(root, nname, kname, key, len, type) ({ \
|
||||
ptrdiff_t _nofs = offsetof(type, nname); \
|
||||
ptrdiff_t _kofs = offsetof(type, kname) - _nofs; \
|
||||
struct ceb_node *_node = cebb_ofs_lookup_ge(root, _kofs, key, len); \
|
||||
_node ? (type *)((char *)(_node) - _nofs) : NULL; \
|
||||
})
|
||||
|
||||
/* lookup from root <root>, the item of type <type> which contains the first of
|
||||
* the lowest keys that are strictly greater than <key>, using node member
|
||||
* <nname> and key member <kname>. Returns the pointer to the item, or NULL if
|
||||
* not found.
|
||||
*/
|
||||
#define cebb_item_lookup_gt(root, nname, kname, key, len, type) ({ \
|
||||
ptrdiff_t _nofs = offsetof(type, nname); \
|
||||
ptrdiff_t _kofs = offsetof(type, kname) - _nofs; \
|
||||
struct ceb_node *_node = cebb_ofs_lookup_gt(root, _kofs, key, len); \
|
||||
_node ? (type *)((char *)(_node) - _nofs) : NULL; \
|
||||
})
|
||||
|
||||
/* lookup from root <root>, the first item after item <item_ptr> that has a
|
||||
* strictly greater key, using node member <nname> and key member <kname>, and
|
||||
* returns either the found item, or NULL if none exists.
|
||||
*/
|
||||
#define cebb_item_next_unique(root, nname, kname, len, item_ptr) ({ \
|
||||
ptrdiff_t _nofs = offsetof(typeof(*(item_ptr)), nname); \
|
||||
ptrdiff_t _kofs = offsetof(typeof(*(item_ptr)), kname) - _nofs; \
|
||||
struct ceb_node *_node = cebb_ofs_next_unique(root, _kofs, &(item_ptr)->nname, len); \
|
||||
_node ? (typeof(item_ptr))((char *)(_node) - _nofs) : NULL; \
|
||||
})
|
||||
|
||||
/* lookup from root <root>, the last item before item <item_ptr> that has a
|
||||
* strictly lower key, using node member <nname> and key member <kname>, and
|
||||
* returns either the found item, or NULL if none exists.
|
||||
*/
|
||||
#define cebb_item_prev_unique(root, nname, kname, len, item_ptr) ({ \
|
||||
ptrdiff_t _nofs = offsetof(typeof(*(item_ptr)), nname); \
|
||||
ptrdiff_t _kofs = offsetof(typeof(*(item_ptr)), kname) - _nofs; \
|
||||
struct ceb_node *_node = cebb_ofs_prev_unique(root, _kofs, &(item_ptr)->nname, len); \
|
||||
_node ? (typeof(item_ptr))((char *)(_node) - _nofs) : NULL; \
|
||||
})
|
||||
|
||||
/* lookup from root <root>, the first item after item <item_ptr> that has
|
||||
* exactly the same key, using node member <nname> and key member <kname>, and
|
||||
* returns either the found item, or NULL if none exists.
|
||||
*/
|
||||
#define cebb_item_next_dup(root, nname, kname, len, item_ptr) ({ \
|
||||
ptrdiff_t _nofs = offsetof(typeof(*(item_ptr)), nname); \
|
||||
ptrdiff_t _kofs = offsetof(typeof(*(item_ptr)), kname) - _nofs; \
|
||||
struct ceb_node *_node = cebb_ofs_next_dup(root, _kofs, &(item_ptr)->nname, len); \
|
||||
_node ? (typeof(item_ptr))((char *)(_node) - _nofs) : NULL; \
|
||||
})
|
||||
|
||||
/* lookup from root <root>, the last item before item <item_ptr> that has
|
||||
* exactly the same key, using node member <nname> and key member <kname>, and
|
||||
* returns either the found item, or NULL if none exists.
|
||||
*/
|
||||
#define cebb_item_prev_dup(root, nname, kname, len, item_ptr) ({ \
|
||||
ptrdiff_t _nofs = offsetof(typeof(*(item_ptr)), nname); \
|
||||
ptrdiff_t _kofs = offsetof(typeof(*(item_ptr)), kname) - _nofs; \
|
||||
struct ceb_node *_node = cebb_ofs_prev_dup(root, _kofs, &(item_ptr)->nname, len); \
|
||||
_node ? (typeof(item_ptr))((char *)(_node) - _nofs) : NULL; \
|
||||
})
|
||||
|
||||
/* lookup from root <root>, the first item immediately after item <item_ptr>,
|
||||
* using node member <nname> and key member <kname>, and returns either the
|
||||
* found item, or NULL if none exists.
|
||||
*/
|
||||
#define cebb_item_next(root, nname, kname, len, item_ptr) ({ \
|
||||
ptrdiff_t _nofs = offsetof(typeof(*(item_ptr)), nname); \
|
||||
ptrdiff_t _kofs = offsetof(typeof(*(item_ptr)), kname) - _nofs; \
|
||||
struct ceb_node *_node = cebb_ofs_next(root, _kofs, &(item_ptr)->nname, len); \
|
||||
_node ? (typeof(item_ptr))((char *)(_node) - _nofs) : NULL; \
|
||||
})
|
||||
|
||||
/* lookup from root <root>, the last item immediately before item <item_ptr>,
|
||||
* using node member <nname> and key member <kname>, and returns either the
|
||||
* found item, or NULL if none exists.
|
||||
*/
|
||||
#define cebb_item_prev(root, nname, kname, len, item_ptr) ({ \
|
||||
ptrdiff_t _nofs = offsetof(typeof(*(item_ptr)), nname); \
|
||||
ptrdiff_t _kofs = offsetof(typeof(*(item_ptr)), kname) - _nofs; \
|
||||
struct ceb_node *_node = cebb_ofs_prev(root, _kofs, &(item_ptr)->nname, len); \
|
||||
_node ? (typeof(item_ptr))((char *)(_node) - _nofs) : NULL; \
|
||||
})
|
||||
|
||||
/* lookup from root <root>, the item <item_ptr> using node member <nname> and
|
||||
* key member <kname>, deletes it and returns it. If the item is NULL or absent
|
||||
* from the tree, NULL is returned.
|
||||
*/
|
||||
#define cebb_item_delete(root, nname, kname, len, item_ptr) ({ \
|
||||
ptrdiff_t _nofs = offsetof(typeof(*(item_ptr)), nname); \
|
||||
ptrdiff_t _kofs = offsetof(typeof(*(item_ptr)), kname) - _nofs; \
|
||||
typeof(item_ptr) _item = (item_ptr); \
|
||||
struct ceb_node *_node = cebb_ofs_delete(root, _kofs, _item ? &_item->nname : NULL, len); \
|
||||
_node ? (typeof(item_ptr))((char *)(_node) - _nofs) : NULL; \
|
||||
})
|
||||
|
||||
/* lookup from root <root>, the first item of type <type> which contains the
|
||||
* key <key>, using node member <nname> and key member <kname>, deletes it and
|
||||
* returns it. If the key is not found in the tree, NULL is returned.
|
||||
*/
|
||||
#define cebb_item_pick(root, nname, kname, key, len, type) ({ \
|
||||
ptrdiff_t _nofs = offsetof(type, nname); \
|
||||
ptrdiff_t _kofs = offsetof(type, kname) - _nofs; \
|
||||
struct ceb_node *_node = cebb_ofs_pick(root, _kofs, key, len); \
|
||||
_node ? (type *)((char *)(_node) - _nofs) : NULL; \
|
||||
})
|
||||
|
||||
/*** versions using unique keys below ***/
|
||||
|
||||
/* insert at root <root>, the item <item_ptr> using node member <nname> and key
|
||||
* member <kname>, and returns either the inserted item, or the one that was
|
||||
* found there.
|
||||
*/
|
||||
#define cebub_item_insert(root, nname, kname, len, item_ptr) ({ \
|
||||
ptrdiff_t _nofs = offsetof(typeof(*(item_ptr)), nname); \
|
||||
ptrdiff_t _kofs = offsetof(typeof(*(item_ptr)), kname) - _nofs; \
|
||||
struct ceb_node *_node = cebub_ofs_insert(root, _kofs, &(item_ptr)->nname, len); \
|
||||
(typeof(item_ptr))((char *)(_node) - _nofs); \
|
||||
})
|
||||
|
||||
/* descend root <root>, and return the first item of type <type>, using node
|
||||
* member <nname> and key member <kname>, or NULL if the tree is empty.
|
||||
*/
|
||||
#define cebub_item_first(root, nname, kname, len, type) ({ \
|
||||
ptrdiff_t _nofs = offsetof(type, nname); \
|
||||
ptrdiff_t _kofs = offsetof(type, kname) - _nofs; \
|
||||
struct ceb_node *_node = cebub_ofs_first(root, _kofs, len); \
|
||||
_node ? (type *)((char *)(_node) - _nofs) : NULL; \
|
||||
})
|
||||
|
||||
/* descend root <root>, and return the last item of type <type>, using node
|
||||
* member <nname> and key member <kname>, or NULL if the tree is empty.
|
||||
*/
|
||||
#define cebub_item_last(root, nname, kname, len, type) ({ \
|
||||
ptrdiff_t _nofs = offsetof(type, nname); \
|
||||
ptrdiff_t _kofs = offsetof(type, kname) - _nofs; \
|
||||
struct ceb_node *_node = cebub_ofs_last(root, _kofs, len); \
|
||||
_node ? (type *)((char *)(_node) - _nofs) : NULL; \
|
||||
})
|
||||
|
||||
/* lookup from root <root>, the item of type <type> which contains the key
|
||||
* <key>, using node member <nname> and key member <kname>. Returns the pointer
|
||||
* to the item, or NULL if not found.
|
||||
*/
|
||||
#define cebub_item_lookup(root, nname, kname, key, len, type) ({ \
|
||||
ptrdiff_t _nofs = offsetof(type, nname); \
|
||||
ptrdiff_t _kofs = offsetof(type, kname) - _nofs; \
|
||||
struct ceb_node *_node = cebub_ofs_lookup(root, _kofs, key, len); \
|
||||
_node ? (type *)((char *)(_node) - _nofs) : NULL; \
|
||||
})
|
||||
|
||||
/* lookup from root <root>, the item of type <type> which contains the greatest
|
||||
* key that is lower than or equal to <key>, using node member <nname> and key
|
||||
* member <kname>. Returns the pointer to the item, or NULL if not found.
|
||||
*/
|
||||
#define cebub_item_lookup_le(root, nname, kname, key, len, type) ({ \
|
||||
ptrdiff_t _nofs = offsetof(type, nname); \
|
||||
ptrdiff_t _kofs = offsetof(type, kname) - _nofs; \
|
||||
struct ceb_node *_node = cebub_ofs_lookup_le(root, _kofs, key, len); \
|
||||
_node ? (type *)((char *)(_node) - _nofs) : NULL; \
|
||||
})
|
||||
|
||||
/* lookup from root <root>, the item of type <type> which contains the greatest
|
||||
* key that is strictly lower than <key>, using node member <nname> and key
|
||||
* member <kname>. Returns the pointer to the item, or NULL if not found.
|
||||
*/
|
||||
#define cebub_item_lookup_lt(root, nname, kname, key, len, type) ({ \
|
||||
ptrdiff_t _nofs = offsetof(type, nname); \
|
||||
ptrdiff_t _kofs = offsetof(type, kname) - _nofs; \
|
||||
struct ceb_node *_node = cebub_ofs_lookup_lt(root, _kofs, key, len); \
|
||||
_node ? (type *)((char *)(_node) - _nofs) : NULL; \
|
||||
})
|
||||
|
||||
/* lookup from root <root>, the item of type <type> which contains the lowest
|
||||
* key key that is greater than or equal to <key>, using node member <nname>
|
||||
* and key member <kname>. Returns the pointer to the item, or NULL if not
|
||||
* found.
|
||||
*/
|
||||
#define cebub_item_lookup_ge(root, nname, kname, key, len, type) ({ \
|
||||
ptrdiff_t _nofs = offsetof(type, nname); \
|
||||
ptrdiff_t _kofs = offsetof(type, kname) - _nofs; \
|
||||
struct ceb_node *_node = cebub_ofs_lookup_ge(root, _kofs, key, len); \
|
||||
_node ? (type *)((char *)(_node) - _nofs) : NULL; \
|
||||
})
|
||||
|
||||
/* lookup from root <root>, the item of type <type> which contains the lowest
|
||||
* key that is strictly greater than <key>, using node member <nname> and key
|
||||
* member <kname>. Returns the pointer to the item, or NULL if not found.
|
||||
*/
|
||||
#define cebub_item_lookup_gt(root, nname, kname, key, len, type) ({ \
|
||||
ptrdiff_t _nofs = offsetof(type, nname); \
|
||||
ptrdiff_t _kofs = offsetof(type, kname) - _nofs; \
|
||||
struct ceb_node *_node = cebub_ofs_lookup_gt(root, _kofs, key, len); \
|
||||
_node ? (type *)((char *)(_node) - _nofs) : NULL; \
|
||||
})
|
||||
|
||||
/* lookup from root <root>, the first item immediately after item <item_ptr>,
|
||||
* using node member <nname> and key member <kname>, and returns either the
|
||||
* found item, or NULL if none exists.
|
||||
*/
|
||||
#define cebub_item_next(root, nname, kname, len, item_ptr) ({ \
|
||||
ptrdiff_t _nofs = offsetof(typeof(*(item_ptr)), nname); \
|
||||
ptrdiff_t _kofs = offsetof(typeof(*(item_ptr)), kname) - _nofs; \
|
||||
struct ceb_node *_node = cebub_ofs_next(root, _kofs, &(item_ptr)->nname, len); \
|
||||
_node ? (typeof(item_ptr))((char *)(_node) - _nofs) : NULL; \
|
||||
})
|
||||
|
||||
/* lookup from root <root>, the last item immediately before item <item_ptr>,
|
||||
* using node member <nname> and key member <kname>, and returns either the
|
||||
* found item, or NULL if none exists.
|
||||
*/
|
||||
#define cebub_item_prev(root, nname, kname, len, item_ptr) ({ \
|
||||
ptrdiff_t _nofs = offsetof(typeof(*(item_ptr)), nname); \
|
||||
ptrdiff_t _kofs = offsetof(typeof(*(item_ptr)), kname) - _nofs; \
|
||||
struct ceb_node *_node = cebub_ofs_prev(root, _kofs, &(item_ptr)->nname, len); \
|
||||
_node ? (typeof(item_ptr))((char *)(_node) - _nofs) : NULL; \
|
||||
})
|
||||
|
||||
/* lookup from root <root>, the item <item_ptr> using node member <nname> and
|
||||
* key member <kname>, deletes it and returns it. If the item is NULL or absent
|
||||
* from the tree, NULL is returned.
|
||||
*/
|
||||
#define cebub_item_delete(root, nname, kname, len, item_ptr) ({ \
|
||||
ptrdiff_t _nofs = offsetof(typeof(*(item_ptr)), nname); \
|
||||
ptrdiff_t _kofs = offsetof(typeof(*(item_ptr)), kname) - _nofs; \
|
||||
typeof(item_ptr) _item = (item_ptr); \
|
||||
struct ceb_node *_node = cebub_ofs_delete(root, _kofs, _item ? &_item->nname : NULL, len); \
|
||||
_node ? (typeof(item_ptr))((char *)(_node) - _nofs) : NULL; \
|
||||
})
|
||||
|
||||
/* lookup from root <root>, the first item of type <type> which contains the
|
||||
* key <key>, using node member <nname> and key member <kname>, deletes it and
|
||||
* returns it. If the key is not found in the tree, NULL is returned.
|
||||
*/
|
||||
#define cebub_item_pick(root, nname, kname, key, len, type) ({ \
|
||||
ptrdiff_t _nofs = offsetof(type, nname); \
|
||||
ptrdiff_t _kofs = offsetof(type, kname) - _nofs; \
|
||||
struct ceb_node *_node = cebub_ofs_pick(root, _kofs, key, len); \
|
||||
_node ? (type *)((char *)(_node) - _nofs) : NULL; \
|
||||
})
|
||||
|
||||
#endif /* _CEBB_TREE_H */
|
425
include/import/cebib_tree.h
Normal file
425
include/import/cebib_tree.h
Normal file
@ -0,0 +1,425 @@
|
||||
/*
|
||||
* Compact Elastic Binary Trees - exported functions operating on indirect blocks
|
||||
*
|
||||
* Copyright (C) 2014-2025 Willy Tarreau - w@1wt.eu
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef _CEBIB_TREE_H
|
||||
#define _CEBIB_TREE_H
|
||||
|
||||
#include "cebtree.h"
|
||||
|
||||
/* simpler version */
|
||||
struct ceb_node *cebib_imm_insert(struct ceb_root **root, struct ceb_node *node, size_t len);
|
||||
struct ceb_node *cebib_imm_first(struct ceb_root *const *root, size_t len);
|
||||
struct ceb_node *cebib_imm_last(struct ceb_root *const *root, size_t len);
|
||||
struct ceb_node *cebib_imm_lookup(struct ceb_root *const *root, const void *key, size_t len);
|
||||
struct ceb_node *cebib_imm_lookup_le(struct ceb_root *const *root, const void *key, size_t len);
|
||||
struct ceb_node *cebib_imm_lookup_lt(struct ceb_root *const *root, const void *key, size_t len);
|
||||
struct ceb_node *cebib_imm_lookup_ge(struct ceb_root *const *root, const void *key, size_t len);
|
||||
struct ceb_node *cebib_imm_lookup_gt(struct ceb_root *const *root, const void *key, size_t len);
|
||||
struct ceb_node *cebib_imm_next_unique(struct ceb_root *const *root, struct ceb_node *node, size_t len);
|
||||
struct ceb_node *cebib_imm_prev_unique(struct ceb_root *const *root, struct ceb_node *node, size_t len);
|
||||
struct ceb_node *cebib_imm_next_dup(struct ceb_root *const *root, struct ceb_node *node, size_t len);
|
||||
struct ceb_node *cebib_imm_prev_dup(struct ceb_root *const *root, struct ceb_node *node, size_t len);
|
||||
struct ceb_node *cebib_imm_next(struct ceb_root *const *root, struct ceb_node *node, size_t len);
|
||||
struct ceb_node *cebib_imm_prev(struct ceb_root *const *root, struct ceb_node *node, size_t len);
|
||||
struct ceb_node *cebib_imm_delete(struct ceb_root **root, struct ceb_node *node, size_t len);
|
||||
struct ceb_node *cebib_imm_pick(struct ceb_root **root, const void *key, size_t len);
|
||||
|
||||
struct ceb_node *cebuib_imm_insert(struct ceb_root **root, struct ceb_node *node, size_t len);
|
||||
struct ceb_node *cebuib_imm_first(struct ceb_root *const *root, size_t len);
|
||||
struct ceb_node *cebuib_imm_last(struct ceb_root *const *root, size_t len);
|
||||
struct ceb_node *cebuib_imm_lookup(struct ceb_root *const *root, const void *key, size_t len);
|
||||
struct ceb_node *cebuib_imm_lookup_le(struct ceb_root *const *root, const void *key, size_t len);
|
||||
struct ceb_node *cebuib_imm_lookup_lt(struct ceb_root *const *root, const void *key, size_t len);
|
||||
struct ceb_node *cebuib_imm_lookup_ge(struct ceb_root *const *root, const void *key, size_t len);
|
||||
struct ceb_node *cebuib_imm_lookup_gt(struct ceb_root *const *root, const void *key, size_t len);
|
||||
struct ceb_node *cebuib_imm_next(struct ceb_root *const *root, struct ceb_node *node, size_t len);
|
||||
struct ceb_node *cebuib_imm_prev(struct ceb_root *const *root, struct ceb_node *node, size_t len);
|
||||
struct ceb_node *cebuib_imm_delete(struct ceb_root **root, struct ceb_node *node, size_t len);
|
||||
struct ceb_node *cebuib_imm_pick(struct ceb_root **root, const void *key, size_t len);
|
||||
|
||||
/* returns the pointer to the indirect void* key, not the pointer itself,
|
||||
* or NULL if node is NULL (note that the indirect pointer cannot be NULL
|
||||
* if node is non-NULL).
|
||||
*/
|
||||
static inline void *cebib_imm_key(const struct ceb_node *node)
|
||||
{
|
||||
return node ? *(void **)_ceb_key_ptr(node, sizeof(struct ceb_node)) : NULL;
|
||||
}
|
||||
|
||||
/* version taking a key offset */
|
||||
struct ceb_node *cebib_ofs_insert(struct ceb_root **root, ptrdiff_t kofs, struct ceb_node *node, size_t len);
|
||||
struct ceb_node *cebib_ofs_first(struct ceb_root *const *root, ptrdiff_t kofs, size_t len);
|
||||
struct ceb_node *cebib_ofs_last(struct ceb_root *const *root, ptrdiff_t kofs, size_t len);
|
||||
struct ceb_node *cebib_ofs_lookup(struct ceb_root *const *root, ptrdiff_t kofs, const void *key, size_t len);
|
||||
struct ceb_node *cebib_ofs_lookup_le(struct ceb_root *const *root, ptrdiff_t kofs, const void *key, size_t len);
|
||||
struct ceb_node *cebib_ofs_lookup_lt(struct ceb_root *const *root, ptrdiff_t kofs, const void *key, size_t len);
|
||||
struct ceb_node *cebib_ofs_lookup_ge(struct ceb_root *const *root, ptrdiff_t kofs, const void *key, size_t len);
|
||||
struct ceb_node *cebib_ofs_lookup_gt(struct ceb_root *const *root, ptrdiff_t kofs, const void *key, size_t len);
|
||||
struct ceb_node *cebib_ofs_next_unique(struct ceb_root *const *root, ptrdiff_t kofs, struct ceb_node *node, size_t len);
|
||||
struct ceb_node *cebib_ofs_prev_unique(struct ceb_root *const *root, ptrdiff_t kofs, struct ceb_node *node, size_t len);
|
||||
struct ceb_node *cebib_ofs_next_dup(struct ceb_root *const *root, ptrdiff_t kofs, struct ceb_node *node, size_t len);
|
||||
struct ceb_node *cebib_ofs_prev_dup(struct ceb_root *const *root, ptrdiff_t kofs, struct ceb_node *node, size_t len);
|
||||
struct ceb_node *cebib_ofs_next(struct ceb_root *const *root, ptrdiff_t kofs, struct ceb_node *node, size_t len);
|
||||
struct ceb_node *cebib_ofs_prev(struct ceb_root *const *root, ptrdiff_t kofs, struct ceb_node *node, size_t len);
|
||||
struct ceb_node *cebib_ofs_delete(struct ceb_root **root, ptrdiff_t kofs, struct ceb_node *node, size_t len);
|
||||
struct ceb_node *cebib_ofs_pick(struct ceb_root **root, ptrdiff_t kofs, const void *key, size_t len);
|
||||
|
||||
struct ceb_node *cebuib_ofs_insert(struct ceb_root **root, ptrdiff_t kofs, struct ceb_node *node, size_t len);
|
||||
struct ceb_node *cebuib_ofs_first(struct ceb_root *const *root, ptrdiff_t kofs, size_t len);
|
||||
struct ceb_node *cebuib_ofs_last(struct ceb_root *const *root, ptrdiff_t kofs, size_t len);
|
||||
struct ceb_node *cebuib_ofs_lookup(struct ceb_root *const *root, ptrdiff_t kofs, const void *key, size_t len);
|
||||
struct ceb_node *cebuib_ofs_lookup_le(struct ceb_root *const *root, ptrdiff_t kofs, const void *key, size_t len);
|
||||
struct ceb_node *cebuib_ofs_lookup_lt(struct ceb_root *const *root, ptrdiff_t kofs, const void *key, size_t len);
|
||||
struct ceb_node *cebuib_ofs_lookup_ge(struct ceb_root *const *root, ptrdiff_t kofs, const void *key, size_t len);
|
||||
struct ceb_node *cebuib_ofs_lookup_gt(struct ceb_root *const *root, ptrdiff_t kofs, const void *key, size_t len);
|
||||
struct ceb_node *cebuib_ofs_next(struct ceb_root *const *root, ptrdiff_t kofs, struct ceb_node *node, size_t len);
|
||||
struct ceb_node *cebuib_ofs_prev(struct ceb_root *const *root, ptrdiff_t kofs, struct ceb_node *node, size_t len);
|
||||
struct ceb_node *cebuib_ofs_delete(struct ceb_root **root, ptrdiff_t kofs, struct ceb_node *node, size_t len);
|
||||
struct ceb_node *cebuib_ofs_pick(struct ceb_root **root, ptrdiff_t kofs, const void *key, size_t len);
|
||||
|
||||
/* returns the pointer to the indirect void* key, not the pointer itself,
|
||||
* or NULL if node is NULL (note that the indirect pointer cannot be NULL
|
||||
* if node is non-NULL).
|
||||
*/
|
||||
static inline void *cebib_ofs_key(const struct ceb_node *node, ptrdiff_t kofs)
|
||||
{
|
||||
return node ? *(void **)_ceb_key_ptr(node, kofs) : NULL;
|
||||
}
|
||||
|
||||
/* insert at root <root>, the item <item_ptr> using node member <nname> and key
|
||||
* member <kname>, and length <len> and returns either the inserted item, or
|
||||
* the one that was found there.
|
||||
*/
|
||||
#define cebib_item_insert(root, nname, kname, len, item_ptr) ({ \
|
||||
ptrdiff_t _nofs = offsetof(typeof(*(item_ptr)), nname); \
|
||||
ptrdiff_t _kofs = offsetof(typeof(*(item_ptr)), kname) - _nofs; \
|
||||
struct ceb_node *_node = cebib_ofs_insert(root, _kofs, &(item_ptr)->nname, len);\
|
||||
(typeof(item_ptr))((char *)(_node) - _nofs); \
|
||||
})
|
||||
|
||||
/* descend root <root>, and return the first item of type <type>, using node
|
||||
* member <nname> and key member <kname>, or NULL if the tree is empty.
|
||||
*/
|
||||
#define cebib_item_first(root, nname, kname, len, type) ({ \
|
||||
ptrdiff_t _nofs = offsetof(type, nname); \
|
||||
ptrdiff_t _kofs = offsetof(type, kname) - _nofs; \
|
||||
struct ceb_node *_node = cebib_ofs_first(root, _kofs, len); \
|
||||
_node ? (type *)((char *)(_node) - _nofs) : NULL; \
|
||||
})
|
||||
|
||||
/* descend root <root>, and return the last item of type <type>, using node
|
||||
* member <nname> and key member <kname>, or NULL if the tree is empty.
|
||||
*/
|
||||
#define cebib_item_last(root, nname, kname, len, type) ({ \
|
||||
ptrdiff_t _nofs = offsetof(type, nname); \
|
||||
ptrdiff_t _kofs = offsetof(type, kname) - _nofs; \
|
||||
struct ceb_node *_node = cebib_ofs_last(root, _kofs, len); \
|
||||
_node ? (type *)((char *)(_node) - _nofs) : NULL; \
|
||||
})
|
||||
|
||||
/* lookup from root <root>, the first item of type <type> which contains the
|
||||
* key <key>, using node member <nname> and key member <kname>. Returns the
|
||||
* pointer to the item, or NULL if not found.
|
||||
*/
|
||||
#define cebib_item_lookup(root, nname, kname, key, len, type) ({ \
|
||||
ptrdiff_t _nofs = offsetof(type, nname); \
|
||||
ptrdiff_t _kofs = offsetof(type, kname) - _nofs; \
|
||||
struct ceb_node *_node = cebib_ofs_lookup(root, _kofs, key, len); \
|
||||
_node ? (type *)((char *)(_node) - _nofs) : NULL; \
|
||||
})
|
||||
|
||||
/* lookup from root <root>, the item of type <type> which contains the last of
|
||||
* the greatest keys that are lower than or equal to <key>, using node member
|
||||
* <nname> and key member <kname>. Returns the pointer to the item, or NULL if
|
||||
* not found.
|
||||
*/
|
||||
#define cebib_item_lookup_le(root, nname, kname, key, len, type) ({ \
|
||||
ptrdiff_t _nofs = offsetof(type, nname); \
|
||||
ptrdiff_t _kofs = offsetof(type, kname) - _nofs; \
|
||||
struct ceb_node *_node = cebib_ofs_lookup_le(root, _kofs, key, len); \
|
||||
_node ? (type *)((char *)(_node) - _nofs) : NULL; \
|
||||
})
|
||||
|
||||
/* lookup from root <root>, the item of type <type> which contains the last of
|
||||
* the greatest keys that are strictly lower than <key>, using node member
|
||||
* <nname> and key member <kname>. Returns the pointer to the item, or NULL if
|
||||
* not found.
|
||||
*/
|
||||
#define cebib_item_lookup_lt(root, nname, kname, key, len, type) ({ \
|
||||
ptrdiff_t _nofs = offsetof(type, nname); \
|
||||
ptrdiff_t _kofs = offsetof(type, kname) - _nofs; \
|
||||
struct ceb_node *_node = cebib_ofs_lookup_lt(root, _kofs, key, len); \
|
||||
_node ? (type *)((char *)(_node) - _nofs) : NULL; \
|
||||
})
|
||||
|
||||
/* lookup from root <root>, the item of type <type> which contains the first of
|
||||
* the lowest keys key that are greater than or equal to <key>, using node
|
||||
* member <nname> and key member <kname>. Returns the pointer to the item, or
|
||||
* NULL if not found.
|
||||
*/
|
||||
#define cebib_item_lookup_ge(root, nname, kname, key, len, type) ({ \
|
||||
ptrdiff_t _nofs = offsetof(type, nname); \
|
||||
ptrdiff_t _kofs = offsetof(type, kname) - _nofs; \
|
||||
struct ceb_node *_node = cebib_ofs_lookup_ge(root, _kofs, key, len); \
|
||||
_node ? (type *)((char *)(_node) - _nofs) : NULL; \
|
||||
})
|
||||
|
||||
/* lookup from root <root>, the item of type <type> which contains the first of
|
||||
* the lowest keys that are strictly greater than <key>, using node member
|
||||
* <nname> and key member <kname>. Returns the pointer to the item, or NULL if
|
||||
* not found.
|
||||
*/
|
||||
#define cebib_item_lookup_gt(root, nname, kname, key, len, type) ({ \
|
||||
ptrdiff_t _nofs = offsetof(type, nname); \
|
||||
ptrdiff_t _kofs = offsetof(type, kname) - _nofs; \
|
||||
struct ceb_node *_node = cebib_ofs_lookup_gt(root, _kofs, key, len); \
|
||||
_node ? (type *)((char *)(_node) - _nofs) : NULL; \
|
||||
})
|
||||
|
||||
/* lookup from root <root>, the first item of type <type> after item <item_ptr>
|
||||
* that has a strictly greater key, using node member <nname> and key member
|
||||
* <kname>, and returns either the found item, or NULL if none exists.
|
||||
*/
|
||||
#define cebib_item_next_unique(root, nname, kname, len, item_ptr) ({ \
|
||||
ptrdiff_t _nofs = offsetof(typeof(*(item_ptr)), nname); \
|
||||
ptrdiff_t _kofs = offsetof(typeof(*(item_ptr)), kname) - _nofs; \
|
||||
struct ceb_node *_node = cebib_ofs_next_unique(root, _kofs, &(item_ptr)->nname, len); \
|
||||
_node ? (typeof(item_ptr))((char *)(_node) - _nofs) : NULL; \
|
||||
})
|
||||
|
||||
/* lookup from root <root>, the last item of type <type> before item <item_ptr>
|
||||
* that has a strictly lower key, using node member <nname> and key member
|
||||
* <kname>, and returns either the found item, or NULL if none exists.
|
||||
*/
|
||||
#define cebib_item_prev_unique(root, nname, kname, len, item_ptr) ({ \
|
||||
ptrdiff_t _nofs = offsetof(typeof(*(item_ptr)), nname); \
|
||||
ptrdiff_t _kofs = offsetof(typeof(*(item_ptr)), kname) - _nofs; \
|
||||
struct ceb_node *_node = cebib_ofs_prev_unique(root, _kofs, &(item_ptr)->nname, len); \
|
||||
_node ? (typeof(item_ptr))((char *)(_node) - _nofs) : NULL; \
|
||||
})
|
||||
|
||||
/* lookup from root <root>, the first item of type <type> after item <item_ptr>
|
||||
* that has exactly the same key, using node member <nname> and key member
|
||||
* <kname>, and returns either the found item, or NULL if none exists.
|
||||
*/
|
||||
#define cebib_item_next_dup(root, nname, kname, len, item_ptr) ({ \
|
||||
ptrdiff_t _nofs = offsetof(typeof(*(item_ptr)), nname); \
|
||||
ptrdiff_t _kofs = offsetof(typeof(*(item_ptr)), kname) - _nofs; \
|
||||
struct ceb_node *_node = cebib_ofs_next_dup(root, _kofs, &(item_ptr)->nname, len); \
|
||||
_node ? (typeof(item_ptr))((char *)(_node) - _nofs) : NULL; \
|
||||
})
|
||||
|
||||
/* lookup from root <root>, the last item of type <type> before item <item_ptr>
|
||||
* that has exactly the same key, using node member <nname> and key member
|
||||
* <kname>, and returns either the found item, or NULL if none exists.
|
||||
*/
|
||||
#define cebib_item_prev_dup(root, nname, kname, len, item_ptr) ({ \
|
||||
ptrdiff_t _nofs = offsetof(typeof(*(item_ptr)), nname); \
|
||||
ptrdiff_t _kofs = offsetof(typeof(*(item_ptr)), kname) - _nofs; \
|
||||
struct ceb_node *_node = cebib_ofs_prev_dup(root, _kofs, &(item_ptr)->nname, len); \
|
||||
_node ? (typeof(item_ptr))((char *)(_node) - _nofs) : NULL; \
|
||||
})
|
||||
|
||||
/* lookup from root <root>, the first item of type <type> immediately after
|
||||
* item <item_ptr>, using node member <nname> and key member <kname>, and
|
||||
* returns either the found item, or NULL if none exists.
|
||||
*/
|
||||
#define cebib_item_next(root, nname, kname, len, item_ptr) ({ \
|
||||
ptrdiff_t _nofs = offsetof(typeof(*(item_ptr)), nname); \
|
||||
ptrdiff_t _kofs = offsetof(typeof(*(item_ptr)), kname) - _nofs; \
|
||||
struct ceb_node *_node = cebib_ofs_next(root, _kofs, &(item_ptr)->nname, len); \
|
||||
_node ? (typeof(item_ptr))((char *)(_node) - _nofs) : NULL; \
|
||||
})
|
||||
|
||||
/* lookup from root <root>, the last item of type <type> immediately before
|
||||
* item <item_ptr>, using node member <nname> and key member <kname>, and
|
||||
* returns either the found item, or NULL if none exists.
|
||||
*/
|
||||
#define cebib_item_prev(root, nname, kname, len, item_ptr) ({ \
|
||||
ptrdiff_t _nofs = offsetof(typeof(*(item_ptr)), nname); \
|
||||
ptrdiff_t _kofs = offsetof(typeof(*(item_ptr)), kname) - _nofs; \
|
||||
struct ceb_node *_node = cebib_ofs_prev(root, _kofs, &(item_ptr)->nname, len); \
|
||||
_node ? (typeof(item_ptr))((char *)(_node) - _nofs) : NULL; \
|
||||
})
|
||||
|
||||
/* lookup from root <root>, the item <item_ptr> using node member <nname> and
|
||||
* key member <kname>, deletes it and returns it. If the item is NULL or absent
|
||||
* from the tree, NULL is returned.
|
||||
*/
|
||||
#define cebib_item_delete(root, nname, kname, len, item_ptr) ({ \
|
||||
ptrdiff_t _nofs = offsetof(typeof(*(item_ptr)), nname); \
|
||||
ptrdiff_t _kofs = offsetof(typeof(*(item_ptr)), kname) - _nofs; \
|
||||
typeof(item_ptr) _item = (item_ptr); \
|
||||
struct ceb_node *_node = cebib_ofs_delete(root, _kofs, _item ? &_item->nname : NULL, len); \
|
||||
_node ? (typeof(item_ptr))((char *)(_node) - _nofs) : NULL; \
|
||||
})
|
||||
|
||||
/* lookup from root <root>, the first item of type <type> which contains the
|
||||
* key <key>, using node member <nname> and key member <kname>, deletes it and
|
||||
* returns it. If the key is not found in the tree, NULL is returned.
|
||||
*/
|
||||
#define cebib_item_pick(root, nname, kname, key, len, type) ({ \
|
||||
ptrdiff_t _nofs = offsetof(type, nname); \
|
||||
ptrdiff_t _kofs = offsetof(type, kname) - _nofs; \
|
||||
struct ceb_node *_node = cebib_ofs_pick(root, _kofs, key, len); \
|
||||
_node ? (type *)((char *)(_node) - _nofs) : NULL; \
|
||||
})
|
||||
|
||||
/*** versions using unique keys below ***/
|
||||
|
||||
/* insert at root <root>, the item <item_ptr> using node member <nname> and key
|
||||
* member <kname>, and returns either the inserted item, or the one that was
|
||||
* found there.
|
||||
*/
|
||||
#define cebuib_item_insert(root, nname, kname, len, item_ptr) ({ \
|
||||
ptrdiff_t _nofs = offsetof(typeof(*(item_ptr)), nname); \
|
||||
ptrdiff_t _kofs = offsetof(typeof(*(item_ptr)), kname) - _nofs; \
|
||||
struct ceb_node *_node = cebuib_ofs_insert(root, _kofs, &(item_ptr)->nname, len); \
|
||||
(typeof(item_ptr))((char *)(_node) - _nofs); \
|
||||
})
|
||||
|
||||
/* descend root <root>, and return the first item of type <type>, using node
|
||||
* member <nname> and key member <kname>, or NULL if the tree is empty.
|
||||
*/
|
||||
#define cebuib_item_first(root, nname, kname, len, type) ({ \
|
||||
ptrdiff_t _nofs = offsetof(type, nname); \
|
||||
ptrdiff_t _kofs = offsetof(type, kname) - _nofs; \
|
||||
struct ceb_node *_node = cebuib_ofs_first(root, _kofs, len); \
|
||||
_node ? (type *)((char *)(_node) - _nofs) : NULL; \
|
||||
})
|
||||
|
||||
/* descend root <root>, and return the last item of type <type>, using node
|
||||
* member <nname> and key member <kname>, or NULL if the tree is empty.
|
||||
*/
|
||||
#define cebuib_item_last(root, nname, kname, len, type) ({ \
|
||||
ptrdiff_t _nofs = offsetof(type, nname); \
|
||||
ptrdiff_t _kofs = offsetof(type, kname) - _nofs; \
|
||||
struct ceb_node *_node = cebuib_ofs_last(root, _kofs, len); \
|
||||
_node ? (type *)((char *)(_node) - _nofs) : NULL; \
|
||||
})
|
||||
|
||||
/* lookup from root <root>, the item of type <type> which contains the key
|
||||
* <key>, using node member <nname> and key member <kname>. Returns the pointer
|
||||
* to the item, or NULL if not found.
|
||||
*/
|
||||
#define cebuib_item_lookup(root, nname, kname, key, len, type) ({ \
|
||||
ptrdiff_t _nofs = offsetof(type, nname); \
|
||||
ptrdiff_t _kofs = offsetof(type, kname) - _nofs; \
|
||||
struct ceb_node *_node = cebuib_ofs_lookup(root, _kofs, key, len); \
|
||||
_node ? (type *)((char *)(_node) - _nofs) : NULL; \
|
||||
})
|
||||
|
||||
/* lookup from root <root>, the item of type <type> which contains the greatest
|
||||
* key that is lower than or equal to <key>, using node member <nname> and key
|
||||
* member <kname>. Returns the pointer to the item, or NULL if not found.
|
||||
*/
|
||||
#define cebuib_item_lookup_le(root, nname, kname, key, len, type) ({ \
|
||||
ptrdiff_t _nofs = offsetof(type, nname); \
|
||||
ptrdiff_t _kofs = offsetof(type, kname) - _nofs; \
|
||||
struct ceb_node *_node = cebuib_ofs_lookup_le(root, _kofs, key, len); \
|
||||
_node ? (type *)((char *)(_node) - _nofs) : NULL; \
|
||||
})
|
||||
|
||||
/* lookup from root <root>, the item of type <type> which contains the greatest
|
||||
* key that is strictly lower than <key>, using node member <nname> and key
|
||||
* member <kname>. Returns the pointer to the item, or NULL if not found.
|
||||
*/
|
||||
#define cebuib_item_lookup_lt(root, nname, kname, key, len, type) ({ \
|
||||
ptrdiff_t _nofs = offsetof(type, nname); \
|
||||
ptrdiff_t _kofs = offsetof(type, kname) - _nofs; \
|
||||
struct ceb_node *_node = cebuib_ofs_lookup_lt(root, _kofs, key, len); \
|
||||
_node ? (type *)((char *)(_node) - _nofs) : NULL; \
|
||||
})
|
||||
|
||||
/* lookup from root <root>, the item of type <type> which contains the lowest
|
||||
* key key that is greater than or equal to <key>, using node member <nname>
|
||||
* and key member <kname>. Returns the pointer to the item, or NULL if not
|
||||
* found.
|
||||
*/
|
||||
#define cebuib_item_lookup_ge(root, nname, kname, key, len, type) ({ \
|
||||
ptrdiff_t _nofs = offsetof(type, nname); \
|
||||
ptrdiff_t _kofs = offsetof(type, kname) - _nofs; \
|
||||
struct ceb_node *_node = cebuib_ofs_lookup_ge(root, _kofs, key, len); \
|
||||
_node ? (type *)((char *)(_node) - _nofs) : NULL; \
|
||||
})
|
||||
|
||||
/* lookup from root <root>, the item of type <type> which contains the lowest
|
||||
* key that is strictly greater than <key>, using node member <nname> and key
|
||||
* member <kname>. Returns the pointer to the item, or NULL if not found.
|
||||
*/
|
||||
#define cebuib_item_lookup_gt(root, nname, kname, key, len, type) ({ \
|
||||
ptrdiff_t _nofs = offsetof(type, nname); \
|
||||
ptrdiff_t _kofs = offsetof(type, kname) - _nofs; \
|
||||
struct ceb_node *_node = cebuib_ofs_lookup_gt(root, _kofs, key, len); \
|
||||
_node ? (type *)((char *)(_node) - _nofs) : NULL; \
|
||||
})
|
||||
|
||||
/* lookup from root <root>, the first item of type <type> immediately after
|
||||
* item <item_ptr>, using node member <nname> and key member <kname>, and
|
||||
* returns either the found item, or NULL if none exists.
|
||||
*/
|
||||
#define cebuib_item_next(root, nname, kname, len, item_ptr) ({ \
|
||||
ptrdiff_t _nofs = offsetof(typeof(*(item_ptr)), nname); \
|
||||
ptrdiff_t _kofs = offsetof(typeof(*(item_ptr)), kname) - _nofs; \
|
||||
struct ceb_node *_node = cebuib_ofs_next(root, _kofs, &(item_ptr)->nname, len); \
|
||||
_node ? (typeof(item_ptr))((char *)(_node) - _nofs) : NULL; \
|
||||
})
|
||||
|
||||
/* lookup from root <root>, the last item of type <type> immediately before
|
||||
* item <item_ptr>, using node member <nname> and key member <kname>, and
|
||||
* returns either the found item, or NULL if none exists.
|
||||
*/
|
||||
#define cebuib_item_prev(root, nname, kname, len, item_ptr) ({ \
|
||||
ptrdiff_t _nofs = offsetof(typeof(*(item_ptr)), nname); \
|
||||
ptrdiff_t _kofs = offsetof(typeof(*(item_ptr)), kname) - _nofs; \
|
||||
struct ceb_node *_node = cebuib_ofs_prev(root, _kofs, &(item_ptr)->nname, len); \
|
||||
_node ? (typeof(item_ptr))((char *)(_node) - _nofs) : NULL; \
|
||||
})
|
||||
|
||||
/* lookup from root <root>, the item <item_ptr> using node member <nname> and
|
||||
* key member <kname>, deletes it and returns it. If the item is NULL or absent
|
||||
* from the tree, NULL is returned.
|
||||
*/
|
||||
#define cebuib_item_delete(root, nname, kname, len, item_ptr) ({ \
|
||||
ptrdiff_t _nofs = offsetof(typeof(*(item_ptr)), nname); \
|
||||
ptrdiff_t _kofs = offsetof(typeof(*(item_ptr)), kname) - _nofs; \
|
||||
typeof(item_ptr) _item = (item_ptr); \
|
||||
struct ceb_node *_node = cebuib_ofs_delete(root, _kofs, _item ? &_item->nname : NULL, len); \
|
||||
_node ? (typeof(item_ptr))((char *)(_node) - _nofs) : NULL; \
|
||||
})
|
||||
|
||||
/* lookup from root <root>, the first item of type <type> which contains the
|
||||
* key <key>, using node member <nname> and key member <kname>, deletes it and
|
||||
* returns it. If the key is not found in the tree, NULL is returned.
|
||||
*/
|
||||
#define cebuib_item_pick(root, nname, kname, key, len, type) ({ \
|
||||
ptrdiff_t _nofs = offsetof(type, nname); \
|
||||
ptrdiff_t _kofs = offsetof(type, kname) - _nofs; \
|
||||
struct ceb_node *_node = cebuib_ofs_pick(root, _kofs, key, len); \
|
||||
_node ? (type *)((char *)(_node) - _nofs) : NULL; \
|
||||
})
|
||||
|
||||
#endif /* _CEBIB_TREE_H */
|
431
include/import/cebis_tree.h
Normal file
431
include/import/cebis_tree.h
Normal file
@ -0,0 +1,431 @@
|
||||
/*
|
||||
* Compact Elastic Binary Trees - exported functions operating on indirect strings
|
||||
*
|
||||
* Copyright (C) 2014-2025 Willy Tarreau - w@1wt.eu
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef _CEBIS_TREE_H
|
||||
#define _CEBIS_TREE_H
|
||||
|
||||
#include "cebtree.h"
|
||||
|
||||
/* simpler version */
|
||||
struct ceb_node *cebis_imm_insert(struct ceb_root **root, struct ceb_node *node);
|
||||
struct ceb_node *cebis_imm_first(struct ceb_root *const *root);
|
||||
struct ceb_node *cebis_imm_last(struct ceb_root *const *root);
|
||||
struct ceb_node *cebis_imm_lookup(struct ceb_root *const *root, const void *key);
|
||||
struct ceb_node *cebis_imm_lookup_le(struct ceb_root *const *root, const void *key);
|
||||
struct ceb_node *cebis_imm_lookup_lt(struct ceb_root *const *root, const void *key);
|
||||
struct ceb_node *cebis_imm_lookup_ge(struct ceb_root *const *root, const void *key);
|
||||
struct ceb_node *cebis_imm_lookup_gt(struct ceb_root *const *root, const void *key);
|
||||
struct ceb_node *cebis_imm_next_unique(struct ceb_root *const *root, struct ceb_node *node);
|
||||
struct ceb_node *cebis_imm_prev_unique(struct ceb_root *const *root, struct ceb_node *node);
|
||||
struct ceb_node *cebis_imm_next_dup(struct ceb_root *const *root, struct ceb_node *node);
|
||||
struct ceb_node *cebis_imm_prev_dup(struct ceb_root *const *root, struct ceb_node *node);
|
||||
struct ceb_node *cebis_imm_next(struct ceb_root *const *root, struct ceb_node *node);
|
||||
struct ceb_node *cebis_imm_prev(struct ceb_root *const *root, struct ceb_node *node);
|
||||
struct ceb_node *cebis_imm_delete(struct ceb_root **root, struct ceb_node *node);
|
||||
struct ceb_node *cebis_imm_pick(struct ceb_root **root, const void *key);
|
||||
|
||||
struct ceb_node *cebuis_imm_insert(struct ceb_root **root, struct ceb_node *node);
|
||||
struct ceb_node *cebuis_imm_first(struct ceb_root *const *root);
|
||||
struct ceb_node *cebuis_imm_last(struct ceb_root *const *root);
|
||||
struct ceb_node *cebuis_imm_lookup(struct ceb_root *const *root, const void *key);
|
||||
struct ceb_node *cebuis_imm_lookup_le(struct ceb_root *const *root, const void *key);
|
||||
struct ceb_node *cebuis_imm_lookup_lt(struct ceb_root *const *root, const void *key);
|
||||
struct ceb_node *cebuis_imm_lookup_ge(struct ceb_root *const *root, const void *key);
|
||||
struct ceb_node *cebuis_imm_lookup_gt(struct ceb_root *const *root, const void *key);
|
||||
struct ceb_node *cebuis_imm_next(struct ceb_root *const *root, struct ceb_node *node);
|
||||
struct ceb_node *cebuis_imm_prev(struct ceb_root *const *root, struct ceb_node *node);
|
||||
struct ceb_node *cebuis_imm_delete(struct ceb_root **root, struct ceb_node *node);
|
||||
struct ceb_node *cebuis_imm_pick(struct ceb_root **root, const void *key);
|
||||
|
||||
/* generic dump function */
|
||||
void cebis_imm_default_dump(struct ceb_root *const *root, const char *label, const void *ctx, int sub);
|
||||
|
||||
/* returns the pointer to the indirect char* key, not the pointer itself,
|
||||
* or NULL if node is NULL (note that the indirect pointer cannot be NULL
|
||||
* if node is non-NULL).
|
||||
*/
|
||||
static inline char *cebis_imm_key(const struct ceb_node *node)
|
||||
{
|
||||
return node ? *(char **)_ceb_key_ptr(node, sizeof(struct ceb_node)) : NULL;
|
||||
}
|
||||
|
||||
/* version taking a key offset */
|
||||
struct ceb_node *cebis_ofs_insert(struct ceb_root **root, ptrdiff_t kofs, struct ceb_node *node);
|
||||
struct ceb_node *cebis_ofs_first(struct ceb_root *const *root, ptrdiff_t kofs);
|
||||
struct ceb_node *cebis_ofs_last(struct ceb_root *const *root, ptrdiff_t kofs);
|
||||
struct ceb_node *cebis_ofs_lookup(struct ceb_root *const *root, ptrdiff_t kofs, const void *key);
|
||||
struct ceb_node *cebis_ofs_lookup_le(struct ceb_root *const *root, ptrdiff_t kofs, const void *key);
|
||||
struct ceb_node *cebis_ofs_lookup_lt(struct ceb_root *const *root, ptrdiff_t kofs, const void *key);
|
||||
struct ceb_node *cebis_ofs_lookup_ge(struct ceb_root *const *root, ptrdiff_t kofs, const void *key);
|
||||
struct ceb_node *cebis_ofs_lookup_gt(struct ceb_root *const *root, ptrdiff_t kofs, const void *key);
|
||||
struct ceb_node *cebis_ofs_next_unique(struct ceb_root *const *root, ptrdiff_t kofs, struct ceb_node *node);
|
||||
struct ceb_node *cebis_ofs_prev_unique(struct ceb_root *const *root, ptrdiff_t kofs, struct ceb_node *node);
|
||||
struct ceb_node *cebis_ofs_next_dup(struct ceb_root *const *root, ptrdiff_t kofs, struct ceb_node *node);
|
||||
struct ceb_node *cebis_ofs_prev_dup(struct ceb_root *const *root, ptrdiff_t kofs, struct ceb_node *node);
|
||||
struct ceb_node *cebis_ofs_next(struct ceb_root *const *root, ptrdiff_t kofs, struct ceb_node *node);
|
||||
struct ceb_node *cebis_ofs_prev(struct ceb_root *const *root, ptrdiff_t kofs, struct ceb_node *node);
|
||||
struct ceb_node *cebis_ofs_delete(struct ceb_root **root, ptrdiff_t kofs, struct ceb_node *node);
|
||||
struct ceb_node *cebis_ofs_pick(struct ceb_root **root, ptrdiff_t kofs, const void *key);
|
||||
|
||||
struct ceb_node *cebuis_ofs_insert(struct ceb_root **root, ptrdiff_t kofs, struct ceb_node *node);
|
||||
struct ceb_node *cebuis_ofs_first(struct ceb_root *const *root, ptrdiff_t kofs);
|
||||
struct ceb_node *cebuis_ofs_last(struct ceb_root *const *root, ptrdiff_t kofs);
|
||||
struct ceb_node *cebuis_ofs_lookup(struct ceb_root *const *root, ptrdiff_t kofs, const void *key);
|
||||
struct ceb_node *cebuis_ofs_lookup_le(struct ceb_root *const *root, ptrdiff_t kofs, const void *key);
|
||||
struct ceb_node *cebuis_ofs_lookup_lt(struct ceb_root *const *root, ptrdiff_t kofs, const void *key);
|
||||
struct ceb_node *cebuis_ofs_lookup_ge(struct ceb_root *const *root, ptrdiff_t kofs, const void *key);
|
||||
struct ceb_node *cebuis_ofs_lookup_gt(struct ceb_root *const *root, ptrdiff_t kofs, const void *key);
|
||||
struct ceb_node *cebuis_ofs_next(struct ceb_root *const *root, ptrdiff_t kofs, struct ceb_node *node);
|
||||
struct ceb_node *cebuis_ofs_prev(struct ceb_root *const *root, ptrdiff_t kofs, struct ceb_node *node);
|
||||
struct ceb_node *cebuis_ofs_delete(struct ceb_root **root, ptrdiff_t kofs, struct ceb_node *node);
|
||||
struct ceb_node *cebuis_ofs_pick(struct ceb_root **root, ptrdiff_t kofs, const void *key);
|
||||
|
||||
/* generic dump function taking a key offset */
|
||||
void cebis_ofs_default_dump(struct ceb_root *const *root, ptrdiff_t kofs, const char *label, const void *ctx, int sub);
|
||||
|
||||
/* returns the pointer to the indirect char* key, not the pointer itself,
|
||||
* or NULL if node is NULL (note that the indirect pointer cannot be NULL
|
||||
* if node is non-NULL).
|
||||
*/
|
||||
static inline char *cebis_ofs_key(const struct ceb_node *node, ptrdiff_t kofs)
|
||||
{
|
||||
return node ? *(char **)_ceb_key_ptr(node, kofs) : NULL;
|
||||
}
|
||||
|
||||
/* insert at root <root>, the item <item_ptr> using node member <nname> and key
|
||||
* member <kname>, and returns either the inserted item, or the one that was
|
||||
* found there.
|
||||
*/
|
||||
#define cebis_item_insert(root, nname, kname, item_ptr) ({ \
|
||||
ptrdiff_t _nofs = offsetof(typeof(*(item_ptr)), nname); \
|
||||
ptrdiff_t _kofs = offsetof(typeof(*(item_ptr)), kname) - _nofs; \
|
||||
struct ceb_node *_node = cebis_ofs_insert(root, _kofs, &(item_ptr)->nname); \
|
||||
(typeof(item_ptr))((char *)(_node) - _nofs); \
|
||||
})
|
||||
|
||||
/* descend root <root>, and return the first item of type <type>, using node
|
||||
* member <nname> and key member <kname>, or NULL if the tree is empty.
|
||||
*/
|
||||
#define cebis_item_first(root, nname, kname, type) ({ \
|
||||
ptrdiff_t _nofs = offsetof(type, nname); \
|
||||
ptrdiff_t _kofs = offsetof(type, kname) - _nofs; \
|
||||
struct ceb_node *_node = cebis_ofs_first(root, _kofs); \
|
||||
_node ? (type *)((char *)(_node) - _nofs) : NULL; \
|
||||
})
|
||||
|
||||
/* descend root <root>, and return the last item of type <type>, using node
|
||||
* member <nname> and key member <kname>, or NULL if the tree is empty.
|
||||
*/
|
||||
#define cebis_item_last(root, nname, kname, type) ({ \
|
||||
ptrdiff_t _nofs = offsetof(type, nname); \
|
||||
ptrdiff_t _kofs = offsetof(type, kname) - _nofs; \
|
||||
struct ceb_node *_node = cebis_ofs_last(root, _kofs); \
|
||||
_node ? (type *)((char *)(_node) - _nofs) : NULL; \
|
||||
})
|
||||
|
||||
/* lookup from root <root>, the first item of type <type> which contains the
|
||||
* key <key>, using node member <nname> and key member <kname>. Returns the
|
||||
* pointer to the item, or NULL if not found.
|
||||
*/
|
||||
#define cebis_item_lookup(root, nname, kname, key, type) ({ \
|
||||
ptrdiff_t _nofs = offsetof(type, nname); \
|
||||
ptrdiff_t _kofs = offsetof(type, kname) - _nofs; \
|
||||
struct ceb_node *_node = cebis_ofs_lookup(root, _kofs, key); \
|
||||
_node ? (type *)((char *)(_node) - _nofs) : NULL; \
|
||||
})
|
||||
|
||||
/* lookup from root <root>, the item of type <type> which contains the last of
|
||||
* the greatest keys that are lower than or equal to <key>, using node member
|
||||
* <nname> and key member <kname>. Returns the pointer to the item, or NULL if
|
||||
* not found.
|
||||
*/
|
||||
#define cebis_item_lookup_le(root, nname, kname, key, type) ({ \
|
||||
ptrdiff_t _nofs = offsetof(type, nname); \
|
||||
ptrdiff_t _kofs = offsetof(type, kname) - _nofs; \
|
||||
struct ceb_node *_node = cebis_ofs_lookup_le(root, _kofs, key); \
|
||||
_node ? (type *)((char *)(_node) - _nofs) : NULL; \
|
||||
})
|
||||
|
||||
/* lookup from root <root>, the item of type <type> which contains the last of
|
||||
* the greatest keys that are strictly lower than <key>, using node member
|
||||
* <nname> and key member <kname>. Returns the pointer to the item, or NULL if
|
||||
* not found.
|
||||
*/
|
||||
#define cebis_item_lookup_lt(root, nname, kname, key, type) ({ \
|
||||
ptrdiff_t _nofs = offsetof(type, nname); \
|
||||
ptrdiff_t _kofs = offsetof(type, kname) - _nofs; \
|
||||
struct ceb_node *_node = cebis_ofs_lookup_lt(root, _kofs, key); \
|
||||
_node ? (type *)((char *)(_node) - _nofs) : NULL; \
|
||||
})
|
||||
|
||||
/* lookup from root <root>, the item of type <type> which contains the first of
|
||||
* the lowest keys key that are greater than or equal to <key>, using node
|
||||
* member <nname> and key member <kname>. Returns the pointer to the item, or
|
||||
* NULL if not found.
|
||||
*/
|
||||
#define cebis_item_lookup_ge(root, nname, kname, key, type) ({ \
|
||||
ptrdiff_t _nofs = offsetof(type, nname); \
|
||||
ptrdiff_t _kofs = offsetof(type, kname) - _nofs; \
|
||||
struct ceb_node *_node = cebis_ofs_lookup_ge(root, _kofs, key); \
|
||||
_node ? (type *)((char *)(_node) - _nofs) : NULL; \
|
||||
})
|
||||
|
||||
/* lookup from root <root>, the item of type <type> which contains the first of
|
||||
* the lowest keys that are strictly greater than <key>, using node member
|
||||
* <nname> and key member <kname>. Returns the pointer to the item, or NULL if
|
||||
* not found.
|
||||
*/
|
||||
#define cebis_item_lookup_gt(root, nname, kname, key, type) ({ \
|
||||
ptrdiff_t _nofs = offsetof(type, nname); \
|
||||
ptrdiff_t _kofs = offsetof(type, kname) - _nofs; \
|
||||
struct ceb_node *_node = cebis_ofs_lookup_gt(root, _kofs, key); \
|
||||
_node ? (type *)((char *)(_node) - _nofs) : NULL; \
|
||||
})
|
||||
|
||||
/* lookup from root <root>, the first item after item <item_ptr> that has a
|
||||
* strictly greater key, using node member <nname> and key member <kname>, and
|
||||
* returns either the found item, or NULL if none exists.
|
||||
*/
|
||||
#define cebis_item_next_unique(root, nname, kname, item_ptr) ({ \
|
||||
ptrdiff_t _nofs = offsetof(typeof(*(item_ptr)), nname); \
|
||||
ptrdiff_t _kofs = offsetof(typeof(*(item_ptr)), kname) - _nofs; \
|
||||
struct ceb_node *_node = cebis_ofs_next_unique(root, _kofs, &(item_ptr)->nname);\
|
||||
_node ? (typeof(item_ptr))((char *)(_node) - _nofs) : NULL; \
|
||||
})
|
||||
|
||||
/* lookup from root <root>, the last item before item <item_ptr> that has a
|
||||
* strictly lower key, using node member <nname> and key member <kname>, and
|
||||
* returns either the found item, or NULL if none exists.
|
||||
*/
|
||||
#define cebis_item_prev_unique(root, nname, kname, item_ptr) ({ \
|
||||
ptrdiff_t _nofs = offsetof(typeof(*(item_ptr)), nname); \
|
||||
ptrdiff_t _kofs = offsetof(typeof(*(item_ptr)), kname) - _nofs; \
|
||||
struct ceb_node *_node = cebis_ofs_prev_unique(root, _kofs, &(item_ptr)->nname);\
|
||||
_node ? (typeof(item_ptr))((char *)(_node) - _nofs) : NULL; \
|
||||
})
|
||||
|
||||
/* lookup from root <root>, the first item after item <item_ptr> that has
|
||||
* exactly the same key, using node member <nname> and key member <kname>, and
|
||||
* returns either the found item, or NULL if none exists.
|
||||
*/
|
||||
#define cebis_item_next_dup(root, nname, kname, item_ptr) ({ \
|
||||
ptrdiff_t _nofs = offsetof(typeof(*(item_ptr)), nname); \
|
||||
ptrdiff_t _kofs = offsetof(typeof(*(item_ptr)), kname) - _nofs; \
|
||||
struct ceb_node *_node = cebis_ofs_next_dup(root, _kofs, &(item_ptr)->nname); \
|
||||
_node ? (typeof(item_ptr))((char *)(_node) - _nofs) : NULL; \
|
||||
})
|
||||
|
||||
/* lookup from root <root>, the last item before item <item_ptr> that has
|
||||
* exactly the same key, using node member <nname> and key member <kname>, and
|
||||
* returns either the found item, or NULL if none exists.
|
||||
*/
|
||||
#define cebis_item_prev_dup(root, nname, kname, item_ptr) ({ \
|
||||
ptrdiff_t _nofs = offsetof(typeof(*(item_ptr)), nname); \
|
||||
ptrdiff_t _kofs = offsetof(typeof(*(item_ptr)), kname) - _nofs; \
|
||||
struct ceb_node *_node = cebis_ofs_prev_dup(root, _kofs, &(item_ptr)->nname); \
|
||||
_node ? (typeof(item_ptr))((char *)(_node) - _nofs) : NULL; \
|
||||
})
|
||||
|
||||
/* lookup from root <root>, the first item immediately after item <item_ptr>,
|
||||
* using node member <nname> and key member <kname>, and returns either the
|
||||
* found item, or NULL if none exists.
|
||||
*/
|
||||
#define cebis_item_next(root, nname, kname, item_ptr) ({ \
|
||||
ptrdiff_t _nofs = offsetof(typeof(*(item_ptr)), nname); \
|
||||
ptrdiff_t _kofs = offsetof(typeof(*(item_ptr)), kname) - _nofs; \
|
||||
struct ceb_node *_node = cebis_ofs_next(root, _kofs, &(item_ptr)->nname); \
|
||||
_node ? (typeof(item_ptr))((char *)(_node) - _nofs) : NULL; \
|
||||
})
|
||||
|
||||
/* lookup from root <root>, the last item immediately before item <item_ptr>,
|
||||
* using node member <nname> and key member <kname>, and returns either the
|
||||
* found item, or NULL if none exists.
|
||||
*/
|
||||
#define cebis_item_prev(root, nname, kname, item_ptr) ({ \
|
||||
ptrdiff_t _nofs = offsetof(typeof(*(item_ptr)), nname); \
|
||||
ptrdiff_t _kofs = offsetof(typeof(*(item_ptr)), kname) - _nofs; \
|
||||
struct ceb_node *_node = cebis_ofs_prev(root, _kofs, &(item_ptr)->nname); \
|
||||
_node ? (typeof(item_ptr))((char *)(_node) - _nofs) : NULL; \
|
||||
})
|
||||
|
||||
/* lookup from root <root>, the item <item_ptr> using node member <nname> and
|
||||
* key member <kname>, deletes it and returns it. If the item is NULL or absent
|
||||
* from the tree, NULL is returned.
|
||||
*/
|
||||
#define cebis_item_delete(root, nname, kname, item_ptr) ({ \
|
||||
ptrdiff_t _nofs = offsetof(typeof(*(item_ptr)), nname); \
|
||||
ptrdiff_t _kofs = offsetof(typeof(*(item_ptr)), kname) - _nofs; \
|
||||
typeof(item_ptr) _item = (item_ptr); \
|
||||
struct ceb_node *_node = cebis_ofs_delete(root, _kofs, _item ? &_item->nname : NULL); \
|
||||
_node ? (typeof(item_ptr))((char *)(_node) - _nofs) : NULL; \
|
||||
})
|
||||
|
||||
/* lookup from root <root>, the first item of type <type> which contains the
|
||||
* key <key>, using node member <nname> and key member <kname>, deletes it and
|
||||
* returns it. If the key is not found in the tree, NULL is returned.
|
||||
*/
|
||||
#define cebis_item_pick(root, nname, kname, key, type) ({ \
|
||||
ptrdiff_t _nofs = offsetof(type, nname); \
|
||||
ptrdiff_t _kofs = offsetof(type, kname) - _nofs; \
|
||||
struct ceb_node *_node = cebis_ofs_pick(root, _kofs, key); \
|
||||
_node ? (type *)((char *)(_node) - _nofs) : NULL; \
|
||||
})
|
||||
|
||||
/*** versions using unique keys below ***/
|
||||
|
||||
/* insert at root <root>, the item <item_ptr> using node member <nname> and key
|
||||
* member <kname>, and returns either the inserted item, or the one that was
|
||||
* found there.
|
||||
*/
|
||||
#define cebuis_item_insert(root, nname, kname, item_ptr) ({ \
|
||||
ptrdiff_t _nofs = offsetof(typeof(*(item_ptr)), nname); \
|
||||
ptrdiff_t _kofs = offsetof(typeof(*(item_ptr)), kname) - _nofs; \
|
||||
struct ceb_node *_node = cebuis_ofs_insert(root, _kofs, &(item_ptr)->nname); \
|
||||
(typeof(item_ptr))((char *)(_node) - _nofs); \
|
||||
})
|
||||
|
||||
/* descend root <root>, and return the first item of type <type>, using node
|
||||
* member <nname> and key member <kname>, or NULL if the tree is empty.
|
||||
*/
|
||||
#define cebuis_item_first(root, nname, kname, type) ({ \
|
||||
ptrdiff_t _nofs = offsetof(type, nname); \
|
||||
ptrdiff_t _kofs = offsetof(type, kname) - _nofs; \
|
||||
struct ceb_node *_node = cebuis_ofs_first(root, _kofs); \
|
||||
_node ? (type *)((char *)(_node) - _nofs) : NULL; \
|
||||
})
|
||||
|
||||
/* descend root <root>, and return the last item of type <type>, using node
|
||||
* member <nname> and key member <kname>, or NULL if the tree is empty.
|
||||
*/
|
||||
#define cebuis_item_last(root, nname, kname, type) ({ \
|
||||
ptrdiff_t _nofs = offsetof(type, nname); \
|
||||
ptrdiff_t _kofs = offsetof(type, kname) - _nofs; \
|
||||
struct ceb_node *_node = cebuis_ofs_last(root, _kofs); \
|
||||
_node ? (type *)((char *)(_node) - _nofs) : NULL; \
|
||||
})
|
||||
|
||||
/* lookup from root <root>, the item of type <type> which contains the key
|
||||
* <key>, using node member <nname> and key member <kname>. Returns the pointer
|
||||
* to the item, or NULL if not found.
|
||||
*/
|
||||
#define cebuis_item_lookup(root, nname, kname, key, type) ({ \
|
||||
ptrdiff_t _nofs = offsetof(type, nname); \
|
||||
ptrdiff_t _kofs = offsetof(type, kname) - _nofs; \
|
||||
struct ceb_node *_node = cebuis_ofs_lookup(root, _kofs, key); \
|
||||
_node ? (type *)((char *)(_node) - _nofs) : NULL; \
|
||||
})
|
||||
|
||||
/* lookup from root <root>, the item of type <type> which contains the greatest
|
||||
* key that is lower than or equal to <key>, using node member <nname> and key
|
||||
* member <kname>. Returns the pointer to the item, or NULL if not found.
|
||||
*/
|
||||
#define cebuis_item_lookup_le(root, nname, kname, key, type) ({ \
|
||||
ptrdiff_t _nofs = offsetof(type, nname); \
|
||||
ptrdiff_t _kofs = offsetof(type, kname) - _nofs; \
|
||||
struct ceb_node *_node = cebuis_ofs_lookup_le(root, _kofs, key); \
|
||||
_node ? (type *)((char *)(_node) - _nofs) : NULL; \
|
||||
})
|
||||
|
||||
/* lookup from root <root>, the item of type <type> which contains the greatest
|
||||
* key that is strictly lower than <key>, using node member <nname> and key
|
||||
* member <kname>. Returns the pointer to the item, or NULL if not found.
|
||||
*/
|
||||
#define cebuis_item_lookup_lt(root, nname, kname, key, type) ({ \
|
||||
ptrdiff_t _nofs = offsetof(type, nname); \
|
||||
ptrdiff_t _kofs = offsetof(type, kname) - _nofs; \
|
||||
struct ceb_node *_node = cebuis_ofs_lookup_lt(root, _kofs, key); \
|
||||
_node ? (type *)((char *)(_node) - _nofs) : NULL; \
|
||||
})
|
||||
|
||||
/* lookup from root <root>, the item of type <type> which contains the lowest
|
||||
* key key that is greater than or equal to <key>, using node member <nname>
|
||||
* and key member <kname>. Returns the pointer to the item, or NULL if not
|
||||
* found.
|
||||
*/
|
||||
#define cebuis_item_lookup_ge(root, nname, kname, key, type) ({ \
|
||||
ptrdiff_t _nofs = offsetof(type, nname); \
|
||||
ptrdiff_t _kofs = offsetof(type, kname) - _nofs; \
|
||||
struct ceb_node *_node = cebuis_ofs_lookup_ge(root, _kofs, key); \
|
||||
_node ? (type *)((char *)(_node) - _nofs) : NULL; \
|
||||
})
|
||||
|
||||
/* lookup from root <root>, the item of type <type> which contains the lowest
|
||||
* key that is strictly greater than <key>, using node member <nname> and key
|
||||
* member <kname>. Returns the pointer to the item, or NULL if not found.
|
||||
*/
|
||||
#define cebuis_item_lookup_gt(root, nname, kname, key, type) ({ \
|
||||
ptrdiff_t _nofs = offsetof(type, nname); \
|
||||
ptrdiff_t _kofs = offsetof(type, kname) - _nofs; \
|
||||
struct ceb_node *_node = cebuis_ofs_lookup_gt(root, _kofs, key); \
|
||||
_node ? (type *)((char *)(_node) - _nofs) : NULL; \
|
||||
})
|
||||
|
||||
/* lookup from root <root>, the first item immediately after item <item_ptr>,
|
||||
* using node member <nname> and key member <kname>, and returns either the
|
||||
* found item, or NULL if none exists.
|
||||
*/
|
||||
#define cebuis_item_next(root, nname, kname, item_ptr) ({ \
|
||||
ptrdiff_t _nofs = offsetof(typeof(*(item_ptr)), nname); \
|
||||
ptrdiff_t _kofs = offsetof(typeof(*(item_ptr)), kname) - _nofs; \
|
||||
struct ceb_node *_node = cebuis_ofs_next(root, _kofs, &(item_ptr)->nname); \
|
||||
_node ? (typeof(item_ptr))((char *)(_node) - _nofs) : NULL; \
|
||||
})
|
||||
|
||||
/* lookup from root <root>, the last item immediately before item <item_ptr>,
|
||||
* using node member <nname> and key member <kname>, and returns either the
|
||||
* found item, or NULL if none exists.
|
||||
*/
|
||||
#define cebuis_item_prev(root, nname, kname, item_ptr) ({ \
|
||||
ptrdiff_t _nofs = offsetof(typeof(*(item_ptr)), nname); \
|
||||
ptrdiff_t _kofs = offsetof(typeof(*(item_ptr)), kname) - _nofs; \
|
||||
struct ceb_node *_node = cebuis_ofs_prev(root, _kofs, &(item_ptr)->nname); \
|
||||
_node ? (typeof(item_ptr))((char *)(_node) - _nofs) : NULL; \
|
||||
})
|
||||
|
||||
/* lookup from root <root>, the item <item_ptr> using node member <nname> and
|
||||
* key member <kname>, deletes it and returns it. If the item is NULL or absent
|
||||
* from the tree, NULL is returned.
|
||||
*/
|
||||
#define cebuis_item_delete(root, nname, kname, item_ptr) ({ \
|
||||
ptrdiff_t _nofs = offsetof(typeof(*(item_ptr)), nname); \
|
||||
ptrdiff_t _kofs = offsetof(typeof(*(item_ptr)), kname) - _nofs; \
|
||||
typeof(item_ptr) _item = (item_ptr); \
|
||||
struct ceb_node *_node = cebuis_ofs_delete(root, _kofs, _item ? &_item->nname : NULL); \
|
||||
_node ? (typeof(item_ptr))((char *)(_node) - _nofs) : NULL; \
|
||||
})
|
||||
|
||||
/* lookup from root <root>, the first item of type <type> which contains the
|
||||
* key <key>, using node member <nname> and key member <kname>, deletes it and
|
||||
* returns it. If the key is not found in the tree, NULL is returned.
|
||||
*/
|
||||
#define cebuis_item_pick(root, nname, kname, key, type) ({ \
|
||||
ptrdiff_t _nofs = offsetof(type, nname); \
|
||||
ptrdiff_t _kofs = offsetof(type, kname) - _nofs; \
|
||||
struct ceb_node *_node = cebuis_ofs_pick(root, _kofs, key); \
|
||||
_node ? (type *)((char *)(_node) - _nofs) : NULL; \
|
||||
})
|
||||
|
||||
#endif /* _CEBIS_TREE_H */
|
425
include/import/cebl_tree.h
Normal file
425
include/import/cebl_tree.h
Normal file
@ -0,0 +1,425 @@
|
||||
/*
|
||||
* Compact Elastic Binary Trees - exported functions operating on ulong keys
|
||||
*
|
||||
* Copyright (C) 2014-2025 Willy Tarreau - w@1wt.eu
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef _CEBL_TREE_H
|
||||
#define _CEBL_TREE_H
|
||||
|
||||
#include "cebtree.h"
|
||||
|
||||
/* simpler version */
|
||||
struct ceb_node *cebl_imm_insert(struct ceb_root **root, struct ceb_node *node);
|
||||
struct ceb_node *cebl_imm_first(struct ceb_root *const *root);
|
||||
struct ceb_node *cebl_imm_last(struct ceb_root *const *root);
|
||||
struct ceb_node *cebl_imm_lookup(struct ceb_root *const *root, unsigned long key);
|
||||
struct ceb_node *cebl_imm_lookup_le(struct ceb_root *const *root, unsigned long key);
|
||||
struct ceb_node *cebl_imm_lookup_lt(struct ceb_root *const *root, unsigned long key);
|
||||
struct ceb_node *cebl_imm_lookup_ge(struct ceb_root *const *root, unsigned long key);
|
||||
struct ceb_node *cebl_imm_lookup_gt(struct ceb_root *const *root, unsigned long key);
|
||||
struct ceb_node *cebl_imm_next_unique(struct ceb_root *const *root, struct ceb_node *node);
|
||||
struct ceb_node *cebl_imm_prev_unique(struct ceb_root *const *root, struct ceb_node *node);
|
||||
struct ceb_node *cebl_imm_next_dup(struct ceb_root *const *root, struct ceb_node *node);
|
||||
struct ceb_node *cebl_imm_prev_dup(struct ceb_root *const *root, struct ceb_node *node);
|
||||
struct ceb_node *cebl_imm_next(struct ceb_root *const *root, struct ceb_node *node);
|
||||
struct ceb_node *cebl_imm_prev(struct ceb_root *const *root, struct ceb_node *node);
|
||||
struct ceb_node *cebl_imm_delete(struct ceb_root **root, struct ceb_node *node);
|
||||
struct ceb_node *cebl_imm_pick(struct ceb_root **root, unsigned long key);
|
||||
|
||||
struct ceb_node *cebul_imm_insert(struct ceb_root *const *root, struct ceb_node *node);
|
||||
struct ceb_node *cebul_imm_first(struct ceb_root *const *root);
|
||||
struct ceb_node *cebul_imm_last(struct ceb_root *const *root);
|
||||
struct ceb_node *cebul_imm_lookup(struct ceb_root *const *root, unsigned long key);
|
||||
struct ceb_node *cebul_imm_lookup_le(struct ceb_root *const *root, unsigned long key);
|
||||
struct ceb_node *cebul_imm_lookup_lt(struct ceb_root *const *root, unsigned long key);
|
||||
struct ceb_node *cebul_imm_lookup_ge(struct ceb_root *const *root, unsigned long key);
|
||||
struct ceb_node *cebul_imm_lookup_gt(struct ceb_root *const *root, unsigned long key);
|
||||
struct ceb_node *cebul_imm_next(struct ceb_root *const *root, struct ceb_node *node);
|
||||
struct ceb_node *cebul_imm_prev(struct ceb_root *const *root, struct ceb_node *node);
|
||||
struct ceb_node *cebul_imm_delete(struct ceb_root **root, struct ceb_node *node);
|
||||
struct ceb_node *cebul_imm_pick(struct ceb_root **root, unsigned long key);
|
||||
|
||||
/* generic dump function */
|
||||
void cebl_imm_default_dump(struct ceb_root **ceb_root, const char *label, const void *ctx, int sub);
|
||||
|
||||
/* returns the pointer to the unsigned long key */
|
||||
static inline unsigned long *cebl_imm_key(const struct ceb_node *node)
|
||||
{
|
||||
return (unsigned long *)ceb_key_ptr(node, sizeof(struct ceb_node));
|
||||
}
|
||||
|
||||
/* version taking a key offset */
|
||||
struct ceb_node *cebl_ofs_insert(struct ceb_root **root, ptrdiff_t kofs, struct ceb_node *node);
|
||||
struct ceb_node *cebl_ofs_first(struct ceb_root *const *root, ptrdiff_t kofs);
|
||||
struct ceb_node *cebl_ofs_last(struct ceb_root *const *root, ptrdiff_t kofs);
|
||||
struct ceb_node *cebl_ofs_lookup(struct ceb_root *const *root, ptrdiff_t kofs, unsigned long key);
|
||||
struct ceb_node *cebl_ofs_lookup_le(struct ceb_root *const *root, ptrdiff_t kofs, unsigned long key);
|
||||
struct ceb_node *cebl_ofs_lookup_lt(struct ceb_root *const *root, ptrdiff_t kofs, unsigned long key);
|
||||
struct ceb_node *cebl_ofs_lookup_ge(struct ceb_root *const *root, ptrdiff_t kofs, unsigned long key);
|
||||
struct ceb_node *cebl_ofs_lookup_gt(struct ceb_root *const *root, ptrdiff_t kofs, unsigned long key);
|
||||
struct ceb_node *cebl_ofs_next_unique(struct ceb_root *const *root, ptrdiff_t kofs, struct ceb_node *node);
|
||||
struct ceb_node *cebl_ofs_prev_unique(struct ceb_root *const *root, ptrdiff_t kofs, struct ceb_node *node);
|
||||
struct ceb_node *cebl_ofs_next_dup(struct ceb_root *const *root, ptrdiff_t kofs, struct ceb_node *node);
|
||||
struct ceb_node *cebl_ofs_prev_dup(struct ceb_root *const *root, ptrdiff_t kofs, struct ceb_node *node);
|
||||
struct ceb_node *cebl_ofs_next(struct ceb_root *const *root, ptrdiff_t kofs, struct ceb_node *node);
|
||||
struct ceb_node *cebl_ofs_prev(struct ceb_root *const *root, ptrdiff_t kofs, struct ceb_node *node);
|
||||
struct ceb_node *cebl_ofs_delete(struct ceb_root *const *root, ptrdiff_t kofs, struct ceb_node *node);
|
||||
struct ceb_node *cebl_ofs_pick(struct ceb_root *const *root, ptrdiff_t kofs, unsigned long key);
|
||||
|
||||
struct ceb_node *cebul_ofs_insert(struct ceb_root **root, ptrdiff_t kofs, struct ceb_node *node);
|
||||
struct ceb_node *cebul_ofs_first(struct ceb_root *const *root, ptrdiff_t kofs);
|
||||
struct ceb_node *cebul_ofs_last(struct ceb_root *const *root, ptrdiff_t kofs);
|
||||
struct ceb_node *cebul_ofs_lookup(struct ceb_root *const *root, ptrdiff_t kofs, unsigned long key);
|
||||
struct ceb_node *cebul_ofs_lookup_le(struct ceb_root *const *root, ptrdiff_t kofs, unsigned long key);
|
||||
struct ceb_node *cebul_ofs_lookup_lt(struct ceb_root *const *root, ptrdiff_t kofs, unsigned long key);
|
||||
struct ceb_node *cebul_ofs_lookup_ge(struct ceb_root *const *root, ptrdiff_t kofs, unsigned long key);
|
||||
struct ceb_node *cebul_ofs_lookup_gt(struct ceb_root *const *root, ptrdiff_t kofs, unsigned long key);
|
||||
struct ceb_node *cebul_ofs_next(struct ceb_root *const *root, ptrdiff_t kofs, struct ceb_node *node);
|
||||
struct ceb_node *cebul_ofs_prev(struct ceb_root *const *root, ptrdiff_t kofs, struct ceb_node *node);
|
||||
struct ceb_node *cebul_ofs_delete(struct ceb_root **root, ptrdiff_t kofs, struct ceb_node *node);
|
||||
struct ceb_node *cebul_ofs_pick(struct ceb_root **root, ptrdiff_t kofs, unsigned long key);
|
||||
|
||||
/* generic dump function taking a key offset */
|
||||
void cebl_ofs_default_dump(struct ceb_root *const *root, ptrdiff_t kofs, const char *label, const void *ctx, int sub);
|
||||
|
||||
/* returns the pointer to the unsigned long key */
|
||||
static inline unsigned long *cebl_ofs_key(const struct ceb_node *node, ptrdiff_t kofs)
|
||||
{
|
||||
return (unsigned long *)ceb_key_ptr(node, kofs);
|
||||
}
|
||||
|
||||
/* insert at root <root>, the item <item_ptr> using node member <nname> and key
|
||||
* member <kname>, and returns either the inserted item, or the one that was
|
||||
* found there.
|
||||
*/
|
||||
#define cebl_item_insert(root, nname, kname, item_ptr) ({ \
|
||||
ptrdiff_t _nofs = offsetof(typeof(*(item_ptr)), nname); \
|
||||
ptrdiff_t _kofs = offsetof(typeof(*(item_ptr)), kname) - _nofs; \
|
||||
struct ceb_node *_node = cebl_ofs_insert(root, _kofs, &(item_ptr)->nname); \
|
||||
(typeof(item_ptr))((char *)(_node) - _nofs); \
|
||||
})
|
||||
|
||||
/* descend root <root>, and return the first item of type <type>, using node
|
||||
* member <nname> and key member <kname>, or NULL if the tree is empty.
|
||||
*/
|
||||
#define cebl_item_first(root, nname, kname, type) ({ \
|
||||
ptrdiff_t _nofs = offsetof(type, nname); \
|
||||
ptrdiff_t _kofs = offsetof(type, kname) - _nofs; \
|
||||
struct ceb_node *_node = cebl_ofs_first(root, _kofs); \
|
||||
_node ? (type *)((char *)(_node) - _nofs) : NULL; \
|
||||
})
|
||||
|
||||
/* descend root <root>, and return the last item of type <type>, using node
|
||||
* member <nname> and key member <kname>, or NULL if the tree is empty.
|
||||
*/
|
||||
#define cebl_item_last(root, nname, kname, type) ({ \
|
||||
ptrdiff_t _nofs = offsetof(type, nname); \
|
||||
ptrdiff_t _kofs = offsetof(type, kname) - _nofs; \
|
||||
struct ceb_node *_node = cebl_ofs_last(root, _kofs); \
|
||||
_node ? (type *)((char *)(_node) - _nofs) : NULL; \
|
||||
})
|
||||
|
||||
/* lookup from root <root>, the first item of type <type> which contains the
|
||||
* key <key>, using node member <nname> and key member <kname>. Returns the
|
||||
* pointer to the item, or NULL if not found.
|
||||
*/
|
||||
#define cebl_item_lookup(root, nname, kname, key, type) ({ \
|
||||
ptrdiff_t _nofs = offsetof(type, nname); \
|
||||
ptrdiff_t _kofs = offsetof(type, kname) - _nofs; \
|
||||
struct ceb_node *_node = cebl_ofs_lookup(root, _kofs, key); \
|
||||
_node ? (type *)((char *)(_node) - _nofs) : NULL; \
|
||||
})
|
||||
|
||||
/* lookup from root <root>, the item of type <type> which contains the last of
|
||||
* the greatest keys that are lower than or equal to <key>, using node member
|
||||
* <nname> and key member <kname>. Returns the pointer to the item, or NULL if
|
||||
* not found.
|
||||
*/
|
||||
#define cebl_item_lookup_le(root, nname, kname, key, type) ({ \
|
||||
ptrdiff_t _nofs = offsetof(type, nname); \
|
||||
ptrdiff_t _kofs = offsetof(type, kname) - _nofs; \
|
||||
struct ceb_node *_node = cebl_ofs_lookup_le(root, _kofs, key); \
|
||||
_node ? (type *)((char *)(_node) - _nofs) : NULL; \
|
||||
})
|
||||
|
||||
/* lookup from root <root>, the item of type <type> which contains the last of
|
||||
* the greatest keys that are strictly lower than <key>, using node member
|
||||
* <nname> and key member <kname>. Returns the pointer to the item, or NULL if
|
||||
* not found.
|
||||
*/
|
||||
#define cebl_item_lookup_lt(root, nname, kname, key, type) ({ \
|
||||
ptrdiff_t _nofs = offsetof(type, nname); \
|
||||
ptrdiff_t _kofs = offsetof(type, kname) - _nofs; \
|
||||
struct ceb_node *_node = cebl_ofs_lookup_lt(root, _kofs, key); \
|
||||
_node ? (type *)((char *)(_node) - _nofs) : NULL; \
|
||||
})
|
||||
|
||||
/* lookup from root <root>, the item of type <type> which contains the first of
|
||||
* the lowest keys key that are greater than or equal to <key>, using node
|
||||
* member <nname> and key member <kname>. Returns the pointer to the item, or
|
||||
* NULL if not found.
|
||||
*/
|
||||
#define cebl_item_lookup_ge(root, nname, kname, key, type) ({ \
|
||||
ptrdiff_t _nofs = offsetof(type, nname); \
|
||||
ptrdiff_t _kofs = offsetof(type, kname) - _nofs; \
|
||||
struct ceb_node *_node = cebl_ofs_lookup_ge(root, _kofs, key); \
|
||||
_node ? (type *)((char *)(_node) - _nofs) : NULL; \
|
||||
})
|
||||
|
||||
/* lookup from root <root>, the item of type <type> which contains the first of
|
||||
* the lowest keys that are strictly greater than <key>, using node member
|
||||
* <nname> and key member <kname>. Returns the pointer to the item, or NULL if
|
||||
* not found.
|
||||
*/
|
||||
#define cebl_item_lookup_gt(root, nname, kname, key, type) ({ \
|
||||
ptrdiff_t _nofs = offsetof(type, nname); \
|
||||
ptrdiff_t _kofs = offsetof(type, kname) - _nofs; \
|
||||
struct ceb_node *_node = cebl_ofs_lookup_gt(root, _kofs, key); \
|
||||
_node ? (type *)((char *)(_node) - _nofs) : NULL; \
|
||||
})
|
||||
|
||||
/* lookup from root <root>, the first item after item <item_ptr> that has a
|
||||
* strictly greater key, using node member <nname> and key member <kname>, and
|
||||
* returns either the found item, or NULL if none exists.
|
||||
*/
|
||||
#define cebl_item_next_unique(root, nname, kname, item_ptr) ({ \
|
||||
ptrdiff_t _nofs = offsetof(typeof(*(item_ptr)), nname); \
|
||||
ptrdiff_t _kofs = offsetof(typeof(*(item_ptr)), kname) - _nofs; \
|
||||
struct ceb_node *_node = cebl_ofs_next_unique(root, _kofs, &(item_ptr)->nname); \
|
||||
_node ? (typeof(item_ptr))((char *)(_node) - _nofs) : NULL; \
|
||||
})
|
||||
|
||||
/* lookup from root <root>, the last item before item <item_ptr> that has a
|
||||
* strictly lower key, using node member <nname> and key member <kname>, and
|
||||
* returns either the found item, or NULL if none exists.
|
||||
*/
|
||||
#define cebl_item_prev_unique(root, nname, kname, item_ptr) ({ \
|
||||
ptrdiff_t _nofs = offsetof(typeof(*(item_ptr)), nname); \
|
||||
ptrdiff_t _kofs = offsetof(typeof(*(item_ptr)), kname) - _nofs; \
|
||||
struct ceb_node *_node = cebl_ofs_prev_unique(root, _kofs, &(item_ptr)->nname); \
|
||||
_node ? (typeof(item_ptr))((char *)(_node) - _nofs) : NULL; \
|
||||
})
|
||||
|
||||
/* lookup from root <root>, the first item after item <item_ptr> that has
|
||||
* exactly the same key, using node member <nname> and key member <kname>, and
|
||||
* returns either the found item, or NULL if none exists.
|
||||
*/
|
||||
#define cebl_item_next_dup(root, nname, kname, item_ptr) ({ \
|
||||
ptrdiff_t _nofs = offsetof(typeof(*(item_ptr)), nname); \
|
||||
ptrdiff_t _kofs = offsetof(typeof(*(item_ptr)), kname) - _nofs; \
|
||||
struct ceb_node *_node = cebl_ofs_next_dup(root, _kofs, &(item_ptr)->nname); \
|
||||
_node ? (typeof(item_ptr))((char *)(_node) - _nofs) : NULL; \
|
||||
})
|
||||
|
||||
/* lookup from root <root>, the last item before item <item_ptr> that has
|
||||
* exactly the same key, using node member <nname> and key member <kname>, and
|
||||
* returns either the found item, or NULL if none exists.
|
||||
*/
|
||||
#define cebl_item_prev_dup(root, nname, kname, item_ptr) ({ \
|
||||
ptrdiff_t _nofs = offsetof(typeof(*(item_ptr)), nname); \
|
||||
ptrdiff_t _kofs = offsetof(typeof(*(item_ptr)), kname) - _nofs; \
|
||||
struct ceb_node *_node = cebl_ofs_prev_dup(root, _kofs, &(item_ptr)->nname); \
|
||||
_node ? (typeof(item_ptr))((char *)(_node) - _nofs) : NULL; \
|
||||
})
|
||||
|
||||
/* lookup from root <root>, the first item immediately after item <item_ptr>,
|
||||
* using node member <nname> and key member <kname>, and returns either the
|
||||
* found item, or NULL if none exists.
|
||||
*/
|
||||
#define cebl_item_next(root, nname, kname, item_ptr) ({ \
|
||||
ptrdiff_t _nofs = offsetof(typeof(*(item_ptr)), nname); \
|
||||
ptrdiff_t _kofs = offsetof(typeof(*(item_ptr)), kname) - _nofs; \
|
||||
struct ceb_node *_node = cebl_ofs_next(root, _kofs, &(item_ptr)->nname); \
|
||||
_node ? (typeof(item_ptr))((char *)(_node) - _nofs) : NULL; \
|
||||
})
|
||||
|
||||
/* lookup from root <root>, the last item immediately before item <item_ptr>,
|
||||
* using node member <nname> and key member <kname>, and returns either the
|
||||
* found item, or NULL if none exists.
|
||||
*/
|
||||
#define cebl_item_prev(root, nname, kname, item_ptr) ({ \
|
||||
ptrdiff_t _nofs = offsetof(typeof(*(item_ptr)), nname); \
|
||||
ptrdiff_t _kofs = offsetof(typeof(*(item_ptr)), kname) - _nofs; \
|
||||
struct ceb_node *_node = cebl_ofs_prev(root, _kofs, &(item_ptr)->nname); \
|
||||
_node ? (typeof(item_ptr))((char *)(_node) - _nofs) : NULL; \
|
||||
})
|
||||
|
||||
/* lookup from root <root>, the item <item_ptr> using node member <nname> and
|
||||
* key member <kname>, deletes it and returns it. If the item is NULL or absent
|
||||
* from the tree, NULL is returned.
|
||||
*/
|
||||
#define cebl_item_delete(root, nname, kname, item_ptr) ({ \
|
||||
ptrdiff_t _nofs = offsetof(typeof(*(item_ptr)), nname); \
|
||||
ptrdiff_t _kofs = offsetof(typeof(*(item_ptr)), kname) - _nofs; \
|
||||
typeof(item_ptr) _item = (item_ptr); \
|
||||
struct ceb_node *_node = cebl_ofs_delete(root, _kofs, _item ? &_item->nname : NULL); \
|
||||
_node ? (typeof(item_ptr))((char *)(_node) - _nofs) : NULL; \
|
||||
})
|
||||
|
||||
/* lookup from root <root>, the first item of type <type> which contains the
|
||||
* key <key>, using node member <nname> and key member <kname>, deletes it and
|
||||
* returns it. If the key is not found in the tree, NULL is returned.
|
||||
*/
|
||||
#define cebl_item_pick(root, nname, kname, key, type) ({ \
|
||||
ptrdiff_t _nofs = offsetof(type, nname); \
|
||||
ptrdiff_t _kofs = offsetof(type, kname) - _nofs; \
|
||||
struct ceb_node *_node = cebl_ofs_pick(root, _kofs, key); \
|
||||
_node ? (type *)((char *)(_node) - _nofs) : NULL; \
|
||||
})
|
||||
|
||||
/*** versions using unique keys below ***/
|
||||
|
||||
/* insert at root <root>, the item <item_ptr> using node member <nname> and key
|
||||
* member <kname>, and returns either the inserted item, or the one that was
|
||||
* found there.
|
||||
*/
|
||||
#define cebul_item_insert(root, nname, kname, item_ptr) ({ \
|
||||
ptrdiff_t _nofs = offsetof(typeof(*(item_ptr)), nname); \
|
||||
ptrdiff_t _kofs = offsetof(typeof(*(item_ptr)), kname) - _nofs; \
|
||||
struct ceb_node *_node = cebul_ofs_insert(root, _kofs, &(item_ptr)->nname); \
|
||||
(typeof(item_ptr))((char *)(_node) - _nofs); \
|
||||
})
|
||||
|
||||
/* descend root <root>, and return the first item of type <type>, using node
|
||||
* member <nname> and key member <kname>, or NULL if the tree is empty.
|
||||
*/
|
||||
#define cebul_item_first(root, nname, kname, type) ({ \
|
||||
ptrdiff_t _nofs = offsetof(type, nname); \
|
||||
ptrdiff_t _kofs = offsetof(type, kname) - _nofs; \
|
||||
struct ceb_node *_node = cebul_ofs_first(root, _kofs); \
|
||||
_node ? (type *)((char *)(_node) - _nofs) : NULL; \
|
||||
})
|
||||
|
||||
/* descend root <root>, and return the last item of type <type>, using node
|
||||
* member <nname> and key member <kname>, or NULL if the tree is empty.
|
||||
*/
|
||||
#define cebul_item_last(root, nname, kname, type) ({ \
|
||||
ptrdiff_t _nofs = offsetof(type, nname); \
|
||||
ptrdiff_t _kofs = offsetof(type, kname) - _nofs; \
|
||||
struct ceb_node *_node = cebul_ofs_last(root, _kofs); \
|
||||
_node ? (type *)((char *)(_node) - _nofs) : NULL; \
|
||||
})
|
||||
|
||||
/* lookup from root <root>, the item of type <type> which contains the key
|
||||
* <key>, using node member <nname> and key member <kname>. Returns the pointer
|
||||
* to the item, or NULL if not found.
|
||||
*/
|
||||
#define cebul_item_lookup(root, nname, kname, key, type) ({ \
|
||||
ptrdiff_t _nofs = offsetof(type, nname); \
|
||||
ptrdiff_t _kofs = offsetof(type, kname) - _nofs; \
|
||||
struct ceb_node *_node = cebul_ofs_lookup(root, _kofs, key); \
|
||||
_node ? (type *)((char *)(_node) - _nofs) : NULL; \
|
||||
})
|
||||
|
||||
/* lookup from root <root>, the item of type <type> which contains the greatest
|
||||
* key that is lower than or equal to <key>, using node member <nname> and key
|
||||
* member <kname>. Returns the pointer to the item, or NULL if not found.
|
||||
*/
|
||||
#define cebul_item_lookup_le(root, nname, kname, key, type) ({ \
|
||||
ptrdiff_t _nofs = offsetof(type, nname); \
|
||||
ptrdiff_t _kofs = offsetof(type, kname) - _nofs; \
|
||||
struct ceb_node *_node = cebul_ofs_lookup_le(root, _kofs, key); \
|
||||
_node ? (type *)((char *)(_node) - _nofs) : NULL; \
|
||||
})
|
||||
|
||||
/* lookup from root <root>, the item of type <type> which contains the greatest
|
||||
* key that is strictly lower than <key>, using node member <nname> and key
|
||||
* member <kname>. Returns the pointer to the item, or NULL if not found.
|
||||
*/
|
||||
#define cebul_item_lookup_lt(root, nname, kname, key, type) ({ \
|
||||
ptrdiff_t _nofs = offsetof(type, nname); \
|
||||
ptrdiff_t _kofs = offsetof(type, kname) - _nofs; \
|
||||
struct ceb_node *_node = cebul_ofs_lookup_lt(root, _kofs, key); \
|
||||
_node ? (type *)((char *)(_node) - _nofs) : NULL; \
|
||||
})
|
||||
|
||||
/* lookup from root <root>, the item of type <type> which contains the lowest
|
||||
* key key that is greater than or equal to <key>, using node member <nname>
|
||||
* and key member <kname>. Returns the pointer to the item, or NULL if not
|
||||
* found.
|
||||
*/
|
||||
#define cebul_item_lookup_ge(root, nname, kname, key, type) ({ \
|
||||
ptrdiff_t _nofs = offsetof(type, nname); \
|
||||
ptrdiff_t _kofs = offsetof(type, kname) - _nofs; \
|
||||
struct ceb_node *_node = cebul_ofs_lookup_ge(root, _kofs, key); \
|
||||
_node ? (type *)((char *)(_node) - _nofs) : NULL; \
|
||||
})
|
||||
|
||||
/* lookup from root <root>, the item of type <type> which contains the lowest
|
||||
* key that is strictly greater than <key>, using node member <nname> and key
|
||||
* member <kname>. Returns the pointer to the item, or NULL if not found.
|
||||
*/
|
||||
#define cebul_item_lookup_gt(root, nname, kname, key, type) ({ \
|
||||
ptrdiff_t _nofs = offsetof(type, nname); \
|
||||
ptrdiff_t _kofs = offsetof(type, kname) - _nofs; \
|
||||
struct ceb_node *_node = cebul_ofs_lookup_gt(root, _kofs, key); \
|
||||
_node ? (type *)((char *)(_node) - _nofs) : NULL; \
|
||||
})
|
||||
|
||||
/* lookup from root <root>, the first item immediately after item <item_ptr>,
|
||||
* using node member <nname> and key member <kname>, and returns either the
|
||||
* found item, or NULL if none exists.
|
||||
*/
|
||||
#define cebul_item_next(root, nname, kname, item_ptr) ({ \
|
||||
ptrdiff_t _nofs = offsetof(typeof(*(item_ptr)), nname); \
|
||||
ptrdiff_t _kofs = offsetof(typeof(*(item_ptr)), kname) - _nofs; \
|
||||
struct ceb_node *_node = cebul_ofs_next(root, _kofs, &(item_ptr)->nname); \
|
||||
_node ? (typeof(item_ptr))((char *)(_node) - _nofs) : NULL; \
|
||||
})
|
||||
|
||||
/* lookup from root <root>, the last item immediately before item <item_ptr>,
|
||||
* using node member <nname> and key member <kname>, and returns either the
|
||||
* found item, or NULL if none exists.
|
||||
*/
|
||||
#define cebul_item_prev(root, nname, kname, item_ptr) ({ \
|
||||
ptrdiff_t _nofs = offsetof(typeof(*(item_ptr)), nname); \
|
||||
ptrdiff_t _kofs = offsetof(typeof(*(item_ptr)), kname) - _nofs; \
|
||||
struct ceb_node *_node = cebul_ofs_prev(root, _kofs, &(item_ptr)->nname); \
|
||||
_node ? (typeof(item_ptr))((char *)(_node) - _nofs) : NULL; \
|
||||
})
|
||||
|
||||
/* lookup from root <root>, the item <item_ptr> using node member <nname> and
|
||||
* key member <kname>, deletes it and returns it. If the item is NULL or absent
|
||||
* from the tree, NULL is returned.
|
||||
*/
|
||||
#define cebul_item_delete(root, nname, kname, item_ptr) ({ \
|
||||
ptrdiff_t _nofs = offsetof(typeof(*(item_ptr)), nname); \
|
||||
ptrdiff_t _kofs = offsetof(typeof(*(item_ptr)), kname) - _nofs; \
|
||||
typeof(item_ptr) _item = (item_ptr); \
|
||||
struct ceb_node *_node = cebul_ofs_delete(root, _kofs, _item ? &_item->nname : NULL); \
|
||||
_node ? (typeof(item_ptr))((char *)(_node) - _nofs) : NULL; \
|
||||
})
|
||||
|
||||
/* lookup from root <root>, the first item of type <type> which contains the
|
||||
* key <key>, using node member <nname> and key member <kname>, deletes it and
|
||||
* returns it. If the key is not found in the tree, NULL is returned.
|
||||
*/
|
||||
#define cebul_item_pick(root, nname, kname, key, type) ({ \
|
||||
ptrdiff_t _nofs = offsetof(type, nname); \
|
||||
ptrdiff_t _kofs = offsetof(type, kname) - _nofs; \
|
||||
struct ceb_node *_node = cebul_ofs_pick(root, _kofs, key); \
|
||||
_node ? (type *)((char *)(_node) - _nofs) : NULL; \
|
||||
})
|
||||
|
||||
#endif /* _CEBL_TREE_H */
|
425
include/import/cebs_tree.h
Normal file
425
include/import/cebs_tree.h
Normal file
@ -0,0 +1,425 @@
|
||||
/*
|
||||
* Compact Elastic Binary Trees - exported functions operating on string keys
|
||||
*
|
||||
* Copyright (C) 2014-2025 Willy Tarreau - w@1wt.eu
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef _CEBS_TREE_H
|
||||
#define _CEBS_TREE_H
|
||||
|
||||
#include "cebtree.h"
|
||||
|
||||
/* simpler version */
|
||||
struct ceb_node *cebs_imm_insert(struct ceb_root **root, struct ceb_node *node);
|
||||
struct ceb_node *cebs_imm_first(struct ceb_root *const *root);
|
||||
struct ceb_node *cebs_imm_last(struct ceb_root *const *root);
|
||||
struct ceb_node *cebs_imm_lookup(struct ceb_root *const *root, const void *key);
|
||||
struct ceb_node *cebs_imm_lookup_le(struct ceb_root *const *root, const void *key);
|
||||
struct ceb_node *cebs_imm_lookup_lt(struct ceb_root *const *root, const void *key);
|
||||
struct ceb_node *cebs_imm_lookup_ge(struct ceb_root *const *root, const void *key);
|
||||
struct ceb_node *cebs_imm_lookup_gt(struct ceb_root *const *root, const void *key);
|
||||
struct ceb_node *cebs_imm_next_unique(struct ceb_root *const *root, struct ceb_node *node);
|
||||
struct ceb_node *cebs_imm_prev_unique(struct ceb_root *const *root, struct ceb_node *node);
|
||||
struct ceb_node *cebs_imm_next_dup(struct ceb_root *const *root, struct ceb_node *node);
|
||||
struct ceb_node *cebs_imm_prev_dup(struct ceb_root *const *root, struct ceb_node *node);
|
||||
struct ceb_node *cebs_imm_next(struct ceb_root *const *root, struct ceb_node *node);
|
||||
struct ceb_node *cebs_imm_prev(struct ceb_root *const *root, struct ceb_node *node);
|
||||
struct ceb_node *cebs_imm_delete(struct ceb_root **root, struct ceb_node *node);
|
||||
struct ceb_node *cebs_imm_pick(struct ceb_root **root, const void *key);
|
||||
|
||||
struct ceb_node *cebus_imm_insert(struct ceb_root **root, struct ceb_node *node);
|
||||
struct ceb_node *cebus_imm_first(struct ceb_root *const *root);
|
||||
struct ceb_node *cebus_imm_last(struct ceb_root *const *root);
|
||||
struct ceb_node *cebus_imm_lookup(struct ceb_root *const *root, const void *key);
|
||||
struct ceb_node *cebus_imm_lookup_le(struct ceb_root *const *root, const void *key);
|
||||
struct ceb_node *cebus_imm_lookup_lt(struct ceb_root *const *root, const void *key);
|
||||
struct ceb_node *cebus_imm_lookup_ge(struct ceb_root *const *root, const void *key);
|
||||
struct ceb_node *cebus_imm_lookup_gt(struct ceb_root *const *root, const void *key);
|
||||
struct ceb_node *cebus_imm_next(struct ceb_root *const *root, struct ceb_node *node);
|
||||
struct ceb_node *cebus_imm_prev(struct ceb_root *const *root, struct ceb_node *node);
|
||||
struct ceb_node *cebus_imm_delete(struct ceb_root **root, struct ceb_node *node);
|
||||
struct ceb_node *cebus_imm_pick(struct ceb_root **root, const void *key);
|
||||
|
||||
/* generic dump function */
|
||||
void cebs_imm_default_dump(struct ceb_root *const *root, const char *label, const void *ctx, int sub);
|
||||
|
||||
/* returns the pointer to the char* key that follows the node */
|
||||
static inline char *cebs_imm_key(const struct ceb_node *node)
|
||||
{
|
||||
return (char *)ceb_key_ptr(node, sizeof(struct ceb_node));
|
||||
}
|
||||
|
||||
/* version taking a key offset */
|
||||
struct ceb_node *cebs_ofs_insert(struct ceb_root **root, ptrdiff_t kofs, struct ceb_node *node);
|
||||
struct ceb_node *cebs_ofs_first(struct ceb_root *const *root, ptrdiff_t kofs);
|
||||
struct ceb_node *cebs_ofs_last(struct ceb_root *const *root, ptrdiff_t kofs);
|
||||
struct ceb_node *cebs_ofs_lookup(struct ceb_root *const *root, ptrdiff_t kofs, const void *key);
|
||||
struct ceb_node *cebs_ofs_lookup_le(struct ceb_root *const *root, ptrdiff_t kofs, const void *key);
|
||||
struct ceb_node *cebs_ofs_lookup_lt(struct ceb_root *const *root, ptrdiff_t kofs, const void *key);
|
||||
struct ceb_node *cebs_ofs_lookup_ge(struct ceb_root *const *root, ptrdiff_t kofs, const void *key);
|
||||
struct ceb_node *cebs_ofs_lookup_gt(struct ceb_root *const *root, ptrdiff_t kofs, const void *key);
|
||||
struct ceb_node *cebs_ofs_next_unique(struct ceb_root *const *root, ptrdiff_t kofs, struct ceb_node *node);
|
||||
struct ceb_node *cebs_ofs_prev_unique(struct ceb_root *const *root, ptrdiff_t kofs, struct ceb_node *node);
|
||||
struct ceb_node *cebs_ofs_next_dup(struct ceb_root *const *root, ptrdiff_t kofs, struct ceb_node *node);
|
||||
struct ceb_node *cebs_ofs_prev_dup(struct ceb_root *const *root, ptrdiff_t kofs, struct ceb_node *node);
|
||||
struct ceb_node *cebs_ofs_next(struct ceb_root *const *root, ptrdiff_t kofs, struct ceb_node *node);
|
||||
struct ceb_node *cebs_ofs_prev(struct ceb_root *const *root, ptrdiff_t kofs, struct ceb_node *node);
|
||||
struct ceb_node *cebs_ofs_delete(struct ceb_root **root, ptrdiff_t kofs, struct ceb_node *node);
|
||||
struct ceb_node *cebs_ofs_pick(struct ceb_root **root, ptrdiff_t kofs, const void *key);
|
||||
|
||||
struct ceb_node *cebus_ofs_insert(struct ceb_root *const *root, ptrdiff_t kofs, struct ceb_node *node);
|
||||
struct ceb_node *cebus_ofs_first(struct ceb_root *const *root, ptrdiff_t kofs);
|
||||
struct ceb_node *cebus_ofs_last(struct ceb_root *const *root, ptrdiff_t kofs);
|
||||
struct ceb_node *cebus_ofs_lookup(struct ceb_root *const *root, ptrdiff_t kofs, const void *key);
|
||||
struct ceb_node *cebus_ofs_lookup_le(struct ceb_root *const *root, ptrdiff_t kofs, const void *key);
|
||||
struct ceb_node *cebus_ofs_lookup_lt(struct ceb_root *const *root, ptrdiff_t kofs, const void *key);
|
||||
struct ceb_node *cebus_ofs_lookup_ge(struct ceb_root *const *root, ptrdiff_t kofs, const void *key);
|
||||
struct ceb_node *cebus_ofs_lookup_gt(struct ceb_root *const *root, ptrdiff_t kofs, const void *key);
|
||||
struct ceb_node *cebus_ofs_next(struct ceb_root *const *root, ptrdiff_t kofs, struct ceb_node *node);
|
||||
struct ceb_node *cebus_ofs_prev(struct ceb_root *const *root, ptrdiff_t kofs, struct ceb_node *node);
|
||||
struct ceb_node *cebus_ofs_delete(struct ceb_root **root, ptrdiff_t kofs, struct ceb_node *node);
|
||||
struct ceb_node *cebus_ofs_pick(struct ceb_root **root, ptrdiff_t kofs, const void *key);
|
||||
|
||||
/* generic dump function taking a key offset */
|
||||
void cebs_ofs_default_dump(struct ceb_root *const *root, ptrdiff_t kofs, const char *label, const void *ctx, int sub);
|
||||
|
||||
/* returns the pointer to the char* key*/
|
||||
static inline char *cebs_ofs_key(const struct ceb_node *node, ptrdiff_t kofs)
|
||||
{
|
||||
return (char *)ceb_key_ptr(node, kofs);
|
||||
}
|
||||
|
||||
/* insert at root <root>, the item <item_ptr> using node member <nname> and key
|
||||
* member <kname>, and returns either the inserted item, or the one that was
|
||||
* found there.
|
||||
*/
|
||||
#define cebs_item_insert(root, nname, kname, item_ptr) ({ \
|
||||
ptrdiff_t _nofs = offsetof(typeof(*(item_ptr)), nname); \
|
||||
ptrdiff_t _kofs = offsetof(typeof(*(item_ptr)), kname) - _nofs; \
|
||||
struct ceb_node *_node = cebs_ofs_insert(root, _kofs, &(item_ptr)->nname); \
|
||||
(typeof(item_ptr))((char *)(_node) - _nofs); \
|
||||
})
|
||||
|
||||
/* descend root <root>, and return the first item of type <type>, using node
|
||||
* member <nname> and key member <kname>, or NULL if the tree is empty.
|
||||
*/
|
||||
#define cebs_item_first(root, nname, kname, type) ({ \
|
||||
ptrdiff_t _nofs = offsetof(type, nname); \
|
||||
ptrdiff_t _kofs = offsetof(type, kname) - _nofs; \
|
||||
struct ceb_node *_node = cebs_ofs_first(root, _kofs); \
|
||||
_node ? (type *)((char *)(_node) - _nofs) : NULL; \
|
||||
})
|
||||
|
||||
/* descend root <root>, and return the last item of type <type>, using node
|
||||
* member <nname> and key member <kname>, or NULL if the tree is empty.
|
||||
*/
|
||||
#define cebs_item_last(root, nname, kname, type) ({ \
|
||||
ptrdiff_t _nofs = offsetof(type, nname); \
|
||||
ptrdiff_t _kofs = offsetof(type, kname) - _nofs; \
|
||||
struct ceb_node *_node = cebs_ofs_last(root, _kofs); \
|
||||
_node ? (type *)((char *)(_node) - _nofs) : NULL; \
|
||||
})
|
||||
|
||||
/* lookup from root <root>, the first item of type <type> which contains the
|
||||
* key <key>, using node member <nname> and key member <kname>. Returns the
|
||||
* pointer to the item, or NULL if not found.
|
||||
*/
|
||||
#define cebs_item_lookup(root, nname, kname, key, type) ({ \
|
||||
ptrdiff_t _nofs = offsetof(type, nname); \
|
||||
ptrdiff_t _kofs = offsetof(type, kname) - _nofs; \
|
||||
struct ceb_node *_node = cebs_ofs_lookup(root, _kofs, key); \
|
||||
_node ? (type *)((char *)(_node) - _nofs) : NULL; \
|
||||
})
|
||||
|
||||
/* lookup from root <root>, the item of type <type> which contains the last of
|
||||
* the greatest keys that are lower than or equal to <key>, using node member
|
||||
* <nname> and key member <kname>. Returns the pointer to the item, or NULL if
|
||||
* not found.
|
||||
*/
|
||||
#define cebs_item_lookup_le(root, nname, kname, key, type) ({ \
|
||||
ptrdiff_t _nofs = offsetof(type, nname); \
|
||||
ptrdiff_t _kofs = offsetof(type, kname) - _nofs; \
|
||||
struct ceb_node *_node = cebs_ofs_lookup_le(root, _kofs, key); \
|
||||
_node ? (type *)((char *)(_node) - _nofs) : NULL; \
|
||||
})
|
||||
|
||||
/* lookup from root <root>, the item of type <type> which contains the last of
|
||||
* the greatest keys that are strictly lower than <key>, using node member
|
||||
* <nname> and key member <kname>. Returns the pointer to the item, or NULL if
|
||||
* not found.
|
||||
*/
|
||||
#define cebs_item_lookup_lt(root, nname, kname, key, type) ({ \
|
||||
ptrdiff_t _nofs = offsetof(type, nname); \
|
||||
ptrdiff_t _kofs = offsetof(type, kname) - _nofs; \
|
||||
struct ceb_node *_node = cebs_ofs_lookup_lt(root, _kofs, key); \
|
||||
_node ? (type *)((char *)(_node) - _nofs) : NULL; \
|
||||
})
|
||||
|
||||
/* lookup from root <root>, the item of type <type> which contains the first of
|
||||
* the lowest keys key that are greater than or equal to <key>, using node
|
||||
* member <nname> and key member <kname>. Returns the pointer to the item, or
|
||||
* NULL if not found.
|
||||
*/
|
||||
#define cebs_item_lookup_ge(root, nname, kname, key, type) ({ \
|
||||
ptrdiff_t _nofs = offsetof(type, nname); \
|
||||
ptrdiff_t _kofs = offsetof(type, kname) - _nofs; \
|
||||
struct ceb_node *_node = cebs_ofs_lookup_ge(root, _kofs, key); \
|
||||
_node ? (type *)((char *)(_node) - _nofs) : NULL; \
|
||||
})
|
||||
|
||||
/* lookup from root <root>, the item of type <type> which contains the first of
|
||||
* the lowest keys that are strictly greater than <key>, using node member
|
||||
* <nname> and key member <kname>. Returns the pointer to the item, or NULL if
|
||||
* not found.
|
||||
*/
|
||||
#define cebs_item_lookup_gt(root, nname, kname, key, type) ({ \
|
||||
ptrdiff_t _nofs = offsetof(type, nname); \
|
||||
ptrdiff_t _kofs = offsetof(type, kname) - _nofs; \
|
||||
struct ceb_node *_node = cebs_ofs_lookup_gt(root, _kofs, key); \
|
||||
_node ? (type *)((char *)(_node) - _nofs) : NULL; \
|
||||
})
|
||||
|
||||
/* lookup from root <root>, the first item after item <item_ptr> that has a
|
||||
* strictly greater key, using node member <nname> and key member <kname>, and
|
||||
* returns either the found item, or NULL if none exists.
|
||||
*/
|
||||
#define cebs_item_next_unique(root, nname, kname, item_ptr) ({ \
|
||||
ptrdiff_t _nofs = offsetof(typeof(*(item_ptr)), nname); \
|
||||
ptrdiff_t _kofs = offsetof(typeof(*(item_ptr)), kname) - _nofs; \
|
||||
struct ceb_node *_node = cebs_ofs_next_unique(root, _kofs, &(item_ptr)->nname); \
|
||||
_node ? (typeof(item_ptr))((char *)(_node) - _nofs) : NULL; \
|
||||
})
|
||||
|
||||
/* lookup from root <root>, the last item before item <item_ptr> that has a
|
||||
* strictly lower key, using node member <nname> and key member <kname>, and
|
||||
* returns either the found item, or NULL if none exists.
|
||||
*/
|
||||
#define cebs_item_prev_unique(root, nname, kname, item_ptr) ({ \
|
||||
ptrdiff_t _nofs = offsetof(typeof(*(item_ptr)), nname); \
|
||||
ptrdiff_t _kofs = offsetof(typeof(*(item_ptr)), kname) - _nofs; \
|
||||
struct ceb_node *_node = cebs_ofs_prev_unique(root, _kofs, &(item_ptr)->nname); \
|
||||
_node ? (typeof(item_ptr))((char *)(_node) - _nofs) : NULL; \
|
||||
})
|
||||
|
||||
/* lookup from root <root>, the first item after item <item_ptr> that has
|
||||
* exactly the same key, using node member <nname> and key member <kname>, and
|
||||
* returns either the found item, or NULL if none exists.
|
||||
*/
|
||||
#define cebs_item_next_dup(root, nname, kname, item_ptr) ({ \
|
||||
ptrdiff_t _nofs = offsetof(typeof(*(item_ptr)), nname); \
|
||||
ptrdiff_t _kofs = offsetof(typeof(*(item_ptr)), kname) - _nofs; \
|
||||
struct ceb_node *_node = cebs_ofs_next_dup(root, _kofs, &(item_ptr)->nname); \
|
||||
_node ? (typeof(item_ptr))((char *)(_node) - _nofs) : NULL; \
|
||||
})
|
||||
|
||||
/* lookup from root <root>, the last item before item <item_ptr> that has
|
||||
* exactly the same key, using node member <nname> and key member <kname>, and
|
||||
* returns either the found item, or NULL if none exists.
|
||||
*/
|
||||
#define cebs_item_prev_dup(root, nname, kname, item_ptr) ({ \
|
||||
ptrdiff_t _nofs = offsetof(typeof(*(item_ptr)), nname); \
|
||||
ptrdiff_t _kofs = offsetof(typeof(*(item_ptr)), kname) - _nofs; \
|
||||
struct ceb_node *_node = cebs_ofs_prev_dup(root, _kofs, &(item_ptr)->nname); \
|
||||
_node ? (typeof(item_ptr))((char *)(_node) - _nofs) : NULL; \
|
||||
})
|
||||
|
||||
/* lookup from root <root>, the first item immediately after item <item_ptr>,
|
||||
* using node member <nname> and key member <kname>, and returns either the
|
||||
* found item, or NULL if none exists.
|
||||
*/
|
||||
#define cebs_item_next(root, nname, kname, item_ptr) ({ \
|
||||
ptrdiff_t _nofs = offsetof(typeof(*(item_ptr)), nname); \
|
||||
ptrdiff_t _kofs = offsetof(typeof(*(item_ptr)), kname) - _nofs; \
|
||||
struct ceb_node *_node = cebs_ofs_next(root, _kofs, &(item_ptr)->nname); \
|
||||
_node ? (typeof(item_ptr))((char *)(_node) - _nofs) : NULL; \
|
||||
})
|
||||
|
||||
/* lookup from root <root>, the last item immediately before item <item_ptr>,
|
||||
* using node member <nname> and key member <kname>, and returns either the
|
||||
* found item, or NULL if none exists.
|
||||
*/
|
||||
#define cebs_item_prev(root, nname, kname, item_ptr) ({ \
|
||||
ptrdiff_t _nofs = offsetof(typeof(*(item_ptr)), nname); \
|
||||
ptrdiff_t _kofs = offsetof(typeof(*(item_ptr)), kname) - _nofs; \
|
||||
struct ceb_node *_node = cebs_ofs_prev(root, _kofs, &(item_ptr)->nname); \
|
||||
_node ? (typeof(item_ptr))((char *)(_node) - _nofs) : NULL; \
|
||||
})
|
||||
|
||||
/* lookup from root <root>, the item <item_ptr> using node member <nname> and
|
||||
* key member <kname>, deletes it and returns it. If the item is NULL or absent
|
||||
* from the tree, NULL is returned.
|
||||
*/
|
||||
#define cebs_item_delete(root, nname, kname, item_ptr) ({ \
|
||||
ptrdiff_t _nofs = offsetof(typeof(*(item_ptr)), nname); \
|
||||
ptrdiff_t _kofs = offsetof(typeof(*(item_ptr)), kname) - _nofs; \
|
||||
typeof(item_ptr) _item = (item_ptr); \
|
||||
struct ceb_node *_node = cebs_ofs_delete(root, _kofs, _item ? &_item->nname : NULL); \
|
||||
_node ? (typeof(item_ptr))((char *)(_node) - _nofs) : NULL; \
|
||||
})
|
||||
|
||||
/* lookup from root <root>, the first item of type <type> which contains the
|
||||
* key <key>, using node member <nname> and key member <kname>, deletes it and
|
||||
* returns it. If the key is not found in the tree, NULL is returned.
|
||||
*/
|
||||
#define cebs_item_pick(root, nname, kname, key, type) ({ \
|
||||
ptrdiff_t _nofs = offsetof(type, nname); \
|
||||
ptrdiff_t _kofs = offsetof(type, kname) - _nofs; \
|
||||
struct ceb_node *_node = cebs_ofs_pick(root, _kofs, key); \
|
||||
_node ? (type *)((char *)(_node) - _nofs) : NULL; \
|
||||
})
|
||||
|
||||
/*** versions using unique keys below ***/
|
||||
|
||||
/* insert at root <root>, the item <item_ptr> using node member <nname> and key
|
||||
* member <kname>, and returns either the inserted item, or the one that was
|
||||
* found there.
|
||||
*/
|
||||
#define cebus_item_insert(root, nname, kname, item_ptr) ({ \
|
||||
ptrdiff_t _nofs = offsetof(typeof(*(item_ptr)), nname); \
|
||||
ptrdiff_t _kofs = offsetof(typeof(*(item_ptr)), kname) - _nofs; \
|
||||
struct ceb_node *_node = cebus_ofs_insert(root, _kofs, &(item_ptr)->nname); \
|
||||
(typeof(item_ptr))((char *)(_node) - _nofs); \
|
||||
})
|
||||
|
||||
/* descend root <root>, and return the first item of type <type>, using node
|
||||
* member <nname> and key member <kname>, or NULL if the tree is empty.
|
||||
*/
|
||||
#define cebus_item_first(root, nname, kname, type) ({ \
|
||||
ptrdiff_t _nofs = offsetof(type, nname); \
|
||||
ptrdiff_t _kofs = offsetof(type, kname) - _nofs; \
|
||||
struct ceb_node *_node = cebus_ofs_first(root, _kofs); \
|
||||
_node ? (type *)((char *)(_node) - _nofs) : NULL; \
|
||||
})
|
||||
|
||||
/* descend root <root>, and return the last item of type <type>, using node
|
||||
* member <nname> and key member <kname>, or NULL if the tree is empty.
|
||||
*/
|
||||
#define cebus_item_last(root, nname, kname, type) ({ \
|
||||
ptrdiff_t _nofs = offsetof(type, nname); \
|
||||
ptrdiff_t _kofs = offsetof(type, kname) - _nofs; \
|
||||
struct ceb_node *_node = cebus_ofs_last(root, _kofs); \
|
||||
_node ? (type *)((char *)(_node) - _nofs) : NULL; \
|
||||
})
|
||||
|
||||
/* lookup from root <root>, the item of type <type> which contains the key
|
||||
* <key>, using node member <nname> and key member <kname>. Returns the pointer
|
||||
* to the item, or NULL if not found.
|
||||
*/
|
||||
#define cebus_item_lookup(root, nname, kname, key, type) ({ \
|
||||
ptrdiff_t _nofs = offsetof(type, nname); \
|
||||
ptrdiff_t _kofs = offsetof(type, kname) - _nofs; \
|
||||
struct ceb_node *_node = cebus_ofs_lookup(root, _kofs, key); \
|
||||
_node ? (type *)((char *)(_node) - _nofs) : NULL; \
|
||||
})
|
||||
|
||||
/* lookup from root <root>, the item of type <type> which contains the greatest
|
||||
* key that is lower than or equal to <key>, using node member <nname> and key
|
||||
* member <kname>. Returns the pointer to the item, or NULL if not found.
|
||||
*/
|
||||
#define cebus_item_lookup_le(root, nname, kname, key, type) ({ \
|
||||
ptrdiff_t _nofs = offsetof(type, nname); \
|
||||
ptrdiff_t _kofs = offsetof(type, kname) - _nofs; \
|
||||
struct ceb_node *_node = cebus_ofs_lookup_le(root, _kofs, key); \
|
||||
_node ? (type *)((char *)(_node) - _nofs) : NULL; \
|
||||
})
|
||||
|
||||
/* lookup from root <root>, the item of type <type> which contains the greatest
|
||||
* key that is strictly lower than <key>, using node member <nname> and key
|
||||
* member <kname>. Returns the pointer to the item, or NULL if not found.
|
||||
*/
|
||||
#define cebus_item_lookup_lt(root, nname, kname, key, type) ({ \
|
||||
ptrdiff_t _nofs = offsetof(type, nname); \
|
||||
ptrdiff_t _kofs = offsetof(type, kname) - _nofs; \
|
||||
struct ceb_node *_node = cebus_ofs_lookup_lt(root, _kofs, key); \
|
||||
_node ? (type *)((char *)(_node) - _nofs) : NULL; \
|
||||
})
|
||||
|
||||
/* lookup from root <root>, the item of type <type> which contains the lowest
|
||||
* key key that is greater than or equal to <key>, using node member <nname>
|
||||
* and key member <kname>. Returns the pointer to the item, or NULL if not
|
||||
* found.
|
||||
*/
|
||||
#define cebus_item_lookup_ge(root, nname, kname, key, type) ({ \
|
||||
ptrdiff_t _nofs = offsetof(type, nname); \
|
||||
ptrdiff_t _kofs = offsetof(type, kname) - _nofs; \
|
||||
struct ceb_node *_node = cebus_ofs_lookup_ge(root, _kofs, key); \
|
||||
_node ? (type *)((char *)(_node) - _nofs) : NULL; \
|
||||
})
|
||||
|
||||
/* lookup from root <root>, the item of type <type> which contains the lowest
|
||||
* key that is strictly greater than <key>, using node member <nname> and key
|
||||
* member <kname>. Returns the pointer to the item, or NULL if not found.
|
||||
*/
|
||||
#define cebus_item_lookup_gt(root, nname, kname, key, type) ({ \
|
||||
ptrdiff_t _nofs = offsetof(type, nname); \
|
||||
ptrdiff_t _kofs = offsetof(type, kname) - _nofs; \
|
||||
struct ceb_node *_node = cebus_ofs_lookup_gt(root, _kofs, key); \
|
||||
_node ? (type *)((char *)(_node) - _nofs) : NULL; \
|
||||
})
|
||||
|
||||
/* lookup from root <root>, the first item immediately after item <item_ptr>,
|
||||
* using node member <nname> and key member <kname>, and returns either the
|
||||
* found item, or NULL if none exists.
|
||||
*/
|
||||
#define cebus_item_next(root, nname, kname, item_ptr) ({ \
|
||||
ptrdiff_t _nofs = offsetof(typeof(*(item_ptr)), nname); \
|
||||
ptrdiff_t _kofs = offsetof(typeof(*(item_ptr)), kname) - _nofs; \
|
||||
struct ceb_node *_node = cebus_ofs_next(root, _kofs, &(item_ptr)->nname); \
|
||||
_node ? (typeof(item_ptr))((char *)(_node) - _nofs) : NULL; \
|
||||
})
|
||||
|
||||
/* lookup from root <root>, the last item immediately before item <item_ptr>,
|
||||
* using node member <nname> and key member <kname>, and returns either the
|
||||
* found item, or NULL if none exists.
|
||||
*/
|
||||
#define cebus_item_prev(root, nname, kname, item_ptr) ({ \
|
||||
ptrdiff_t _nofs = offsetof(typeof(*(item_ptr)), nname); \
|
||||
ptrdiff_t _kofs = offsetof(typeof(*(item_ptr)), kname) - _nofs; \
|
||||
struct ceb_node *_node = cebus_ofs_prev(root, _kofs, &(item_ptr)->nname); \
|
||||
_node ? (typeof(item_ptr))((char *)(_node) - _nofs) : NULL; \
|
||||
})
|
||||
|
||||
/* lookup from root <root>, the item <item_ptr> using node member <nname> and
|
||||
* key member <kname>, deletes it and returns it. If the item is NULL or absent
|
||||
* from the tree, NULL is returned.
|
||||
*/
|
||||
#define cebus_item_delete(root, nname, kname, item_ptr) ({ \
|
||||
ptrdiff_t _nofs = offsetof(typeof(*(item_ptr)), nname); \
|
||||
ptrdiff_t _kofs = offsetof(typeof(*(item_ptr)), kname) - _nofs; \
|
||||
typeof(item_ptr) _item = (item_ptr); \
|
||||
struct ceb_node *_node = cebus_ofs_delete(root, _kofs, _item ? &_item->nname : NULL); \
|
||||
_node ? (typeof(item_ptr))((char *)(_node) - _nofs) : NULL; \
|
||||
})
|
||||
|
||||
/* lookup from root <root>, the first item of type <type> which contains the
|
||||
* key <key>, using node member <nname> and key member <kname>, deletes it and
|
||||
* returns it. If the key is not found in the tree, NULL is returned.
|
||||
*/
|
||||
#define cebus_item_pick(root, nname, kname, key, type) ({ \
|
||||
ptrdiff_t _nofs = offsetof(type, nname); \
|
||||
ptrdiff_t _kofs = offsetof(type, kname) - _nofs; \
|
||||
struct ceb_node *_node = cebus_ofs_pick(root, _kofs, key); \
|
||||
_node ? (type *)((char *)(_node) - _nofs) : NULL; \
|
||||
})
|
||||
|
||||
#endif /* _CEBS_TREE_H */
|
File diff suppressed because it is too large
Load Diff
@ -28,56 +28,83 @@
|
||||
#define _CEBTREE_H
|
||||
|
||||
#include <stddef.h>
|
||||
#include "ebtree.h"
|
||||
|
||||
/* offsetof() is provided as a builtin starting with gcc-4.1 */
|
||||
#ifndef offsetof
|
||||
# if (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 1))
|
||||
# define offsetof(type, field) __builtin_offsetof(type, field)
|
||||
# else
|
||||
# define offsetof(type, field) ((__size_t)(__uintptr_t)((const volatile void *)&((type *)0)->field))
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* Linux-like "container_of". It returns a pointer to the structure of type
|
||||
* <type> which has its member <name> stored at address <ptr>.
|
||||
*/
|
||||
#ifndef container_of
|
||||
#define container_of(ptr, type, name) ((type *)(((char *)(ptr)) - offsetof(type, name)))
|
||||
#endif
|
||||
|
||||
/* returns a pointer to the structure of type <type> which has its member <name>
|
||||
* stored at address <ptr>, unless <ptr> is 0, in which case 0 is returned.
|
||||
*/
|
||||
#ifndef container_of_safe
|
||||
#define container_of_safe(ptr, type, name) \
|
||||
({ void *__p = (ptr); \
|
||||
__p ? container_of(__p, type, name) : (type *)0; \
|
||||
})
|
||||
#endif
|
||||
|
||||
/* This is what a tagged pointer points to, as found on the root or any branch.
|
||||
* It's only a forward declaration so that it is never directly dereferenced.
|
||||
*/
|
||||
struct ceb_root;
|
||||
|
||||
/* Standard node when using absolute pointers */
|
||||
struct ceb_node {
|
||||
struct ceb_node *b[2]; /* branches: 0=left, 1=right */
|
||||
struct ceb_root *b[2]; /* branches: 0=left, 1=right */
|
||||
};
|
||||
|
||||
/* initializes a root as an empty tree */
|
||||
static inline void ceb_init_root(struct ceb_root **root)
|
||||
{
|
||||
*root = NULL;
|
||||
}
|
||||
|
||||
/* initializes a node as not belonging to a tree */
|
||||
static inline void ceb_init_node(struct ceb_node *node)
|
||||
{
|
||||
node->b[0] = NULL;
|
||||
}
|
||||
|
||||
/* indicates whether a valid node is in a tree or not */
|
||||
static inline int ceb_intree(const struct ceb_node *node)
|
||||
{
|
||||
return !!node->b[0];
|
||||
}
|
||||
|
||||
/* tag an untagged pointer */
|
||||
static inline struct ceb_node *__ceb_dotag(const struct ceb_node *node)
|
||||
/* indicates whether a root is empty or not */
|
||||
static inline int ceb_isempty(struct ceb_root * const*root)
|
||||
{
|
||||
return (struct ceb_node *)((size_t)node + 1);
|
||||
return !*root;
|
||||
}
|
||||
|
||||
/* untag a tagged pointer */
|
||||
static inline struct ceb_node *__ceb_untag(const struct ceb_node *node)
|
||||
/* returns a pointer to the key from the node and offset, where node is
|
||||
* assumed to be non-null.
|
||||
*/
|
||||
static inline void *_ceb_key_ptr(const struct ceb_node *node, ptrdiff_t kofs)
|
||||
{
|
||||
return (struct ceb_node *)((size_t)node - 1);
|
||||
return (void*)((char *)node + kofs);
|
||||
}
|
||||
|
||||
/* clear a pointer's tag */
|
||||
static inline struct ceb_node *__ceb_clrtag(const struct ceb_node *node)
|
||||
/* returns a pointer to the key from the node and offset if node is non-null,
|
||||
* otherwise null. I.e. this is made to safely return a pointer to the key
|
||||
* location from the return of a lookup operation.
|
||||
*/
|
||||
static inline void *ceb_key_ptr(const struct ceb_node *node, ptrdiff_t kofs)
|
||||
{
|
||||
return (struct ceb_node *)((size_t)node & ~((size_t)1));
|
||||
return node ? _ceb_key_ptr(node, kofs) : NULL;
|
||||
}
|
||||
|
||||
/* returns whether a pointer is tagged */
|
||||
static inline int __ceb_tagged(const struct ceb_node *node)
|
||||
{
|
||||
return !!((size_t)node & 1);
|
||||
}
|
||||
|
||||
/* returns an integer equivalent of the pointer */
|
||||
static inline size_t __ceb_intptr(struct ceb_node *tree)
|
||||
{
|
||||
return (size_t)tree;
|
||||
}
|
||||
|
||||
///* returns true if at least one of the branches is a subtree node, indicating
|
||||
// * that the current node is at the top of a duplicate sub-tree and that all
|
||||
// * values below it are the same.
|
||||
// */
|
||||
//static inline int __ceb_is_dup(const struct ceb_node *node)
|
||||
//{
|
||||
// return __ceb_tagged((struct ceb_node *)(__ceb_intptr(node->l) | __ceb_intptr(node->r)));
|
||||
//}
|
||||
|
||||
#endif /* _CEBTREE_H */
|
||||
|
@ -1,58 +0,0 @@
|
||||
/*
|
||||
* Compact Elastic Binary Trees - exported functions operating on u32 keys
|
||||
*
|
||||
* Copyright (C) 2014-2024 Willy Tarreau - w@1wt.eu
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "cebtree.h"
|
||||
#include <inttypes.h>
|
||||
|
||||
/* simpler version */
|
||||
struct ceb_node *cebu32_insert(struct ceb_node **root, struct ceb_node *node);
|
||||
struct ceb_node *cebu32_first(struct ceb_node **root);
|
||||
struct ceb_node *cebu32_last(struct ceb_node **root);
|
||||
struct ceb_node *cebu32_lookup(struct ceb_node **root, uint32_t key);
|
||||
struct ceb_node *cebu32_lookup_le(struct ceb_node **root, uint32_t key);
|
||||
struct ceb_node *cebu32_lookup_lt(struct ceb_node **root, uint32_t key);
|
||||
struct ceb_node *cebu32_lookup_ge(struct ceb_node **root, uint32_t key);
|
||||
struct ceb_node *cebu32_lookup_gt(struct ceb_node **root, uint32_t key);
|
||||
struct ceb_node *cebu32_next(struct ceb_node **root, struct ceb_node *node);
|
||||
struct ceb_node *cebu32_prev(struct ceb_node **root, struct ceb_node *node);
|
||||
struct ceb_node *cebu32_delete(struct ceb_node **root, struct ceb_node *node);
|
||||
struct ceb_node *cebu32_pick(struct ceb_node **root, uint32_t key);
|
||||
void cebu32_default_dump(struct ceb_node **ceb_root, const char *label, const void *ctx);
|
||||
|
||||
/* version taking a key offset */
|
||||
struct ceb_node *cebu32_ofs_insert(struct ceb_node **root, ptrdiff_t kofs, struct ceb_node *node);
|
||||
struct ceb_node *cebu32_ofs_first(struct ceb_node **root, ptrdiff_t kofs);
|
||||
struct ceb_node *cebu32_ofs_last(struct ceb_node **root, ptrdiff_t kofs);
|
||||
struct ceb_node *cebu32_ofs_lookup(struct ceb_node **root, ptrdiff_t kofs, uint32_t key);
|
||||
struct ceb_node *cebu32_ofs_lookup_le(struct ceb_node **root, ptrdiff_t kofs, uint32_t key);
|
||||
struct ceb_node *cebu32_ofs_lookup_lt(struct ceb_node **root, ptrdiff_t kofs, uint32_t key);
|
||||
struct ceb_node *cebu32_ofs_lookup_ge(struct ceb_node **root, ptrdiff_t kofs, uint32_t key);
|
||||
struct ceb_node *cebu32_ofs_lookup_gt(struct ceb_node **root, ptrdiff_t kofs, uint32_t key);
|
||||
struct ceb_node *cebu32_ofs_next(struct ceb_node **root, ptrdiff_t kofs, struct ceb_node *node);
|
||||
struct ceb_node *cebu32_ofs_prev(struct ceb_node **root, ptrdiff_t kofs, struct ceb_node *node);
|
||||
struct ceb_node *cebu32_ofs_delete(struct ceb_node **root, ptrdiff_t kofs, struct ceb_node *node);
|
||||
struct ceb_node *cebu32_ofs_pick(struct ceb_node **root, ptrdiff_t kofs, uint32_t key);
|
||||
void cebu32_ofs_default_dump(struct ceb_node **root, ptrdiff_t kofs, const char *label, const void *ctx);
|
@ -1,58 +0,0 @@
|
||||
/*
|
||||
* Compact Elastic Binary Trees - exported functions for operations on u64 keys
|
||||
*
|
||||
* Copyright (C) 2014-2024 Willy Tarreau - w@1wt.eu
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "cebtree.h"
|
||||
#include <inttypes.h>
|
||||
|
||||
/* simpler version */
|
||||
struct ceb_node *cebu64_insert(struct ceb_node **root, struct ceb_node *node);
|
||||
struct ceb_node *cebu64_first(struct ceb_node **root);
|
||||
struct ceb_node *cebu64_last(struct ceb_node **root);
|
||||
struct ceb_node *cebu64_lookup(struct ceb_node **root, uint64_t key);
|
||||
struct ceb_node *cebu64_lookup_le(struct ceb_node **root, uint64_t key);
|
||||
struct ceb_node *cebu64_lookup_lt(struct ceb_node **root, uint64_t key);
|
||||
struct ceb_node *cebu64_lookup_ge(struct ceb_node **root, uint64_t key);
|
||||
struct ceb_node *cebu64_lookup_gt(struct ceb_node **root, uint64_t key);
|
||||
struct ceb_node *cebu64_next(struct ceb_node **root, struct ceb_node *node);
|
||||
struct ceb_node *cebu64_prev(struct ceb_node **root, struct ceb_node *node);
|
||||
struct ceb_node *cebu64_delete(struct ceb_node **root, struct ceb_node *node);
|
||||
struct ceb_node *cebu64_pick(struct ceb_node **root, uint64_t key);
|
||||
void cebu64_default_dump(struct ceb_node **ceb_root, const char *label, const void *ctx);
|
||||
|
||||
/* version taking a key offset */
|
||||
struct ceb_node *cebu64_ofs_insert(struct ceb_node **root, ptrdiff_t kofs, struct ceb_node *node);
|
||||
struct ceb_node *cebu64_ofs_first(struct ceb_node **root, ptrdiff_t kofs);
|
||||
struct ceb_node *cebu64_ofs_last(struct ceb_node **root, ptrdiff_t kofs);
|
||||
struct ceb_node *cebu64_ofs_lookup(struct ceb_node **root, ptrdiff_t kofs, uint64_t key);
|
||||
struct ceb_node *cebu64_ofs_lookup_le(struct ceb_node **root, ptrdiff_t kofs, uint64_t key);
|
||||
struct ceb_node *cebu64_ofs_lookup_lt(struct ceb_node **root, ptrdiff_t kofs, uint64_t key);
|
||||
struct ceb_node *cebu64_ofs_lookup_ge(struct ceb_node **root, ptrdiff_t kofs, uint64_t key);
|
||||
struct ceb_node *cebu64_ofs_lookup_gt(struct ceb_node **root, ptrdiff_t kofs, uint64_t key);
|
||||
struct ceb_node *cebu64_ofs_next(struct ceb_node **root, ptrdiff_t kofs, struct ceb_node *node);
|
||||
struct ceb_node *cebu64_ofs_prev(struct ceb_node **root, ptrdiff_t kofs, struct ceb_node *node);
|
||||
struct ceb_node *cebu64_ofs_delete(struct ceb_node **root, ptrdiff_t kofs, struct ceb_node *node);
|
||||
struct ceb_node *cebu64_ofs_pick(struct ceb_node **root, ptrdiff_t kofs, uint64_t key);
|
||||
void cebu64_ofs_default_dump(struct ceb_node **root, ptrdiff_t kofs, const char *label, const void *ctx);
|
@ -1,57 +0,0 @@
|
||||
/*
|
||||
* Compact Elastic Binary Trees - exported functions operating on addr keys
|
||||
*
|
||||
* Copyright (C) 2014-2024 Willy Tarreau - w@1wt.eu
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "cebtree.h"
|
||||
|
||||
/* simpler version */
|
||||
struct ceb_node *cebua_insert(struct ceb_node **root, struct ceb_node *node);
|
||||
struct ceb_node *cebua_first(struct ceb_node **root);
|
||||
struct ceb_node *cebua_last(struct ceb_node **root);
|
||||
struct ceb_node *cebua_lookup(struct ceb_node **root, const void *key);
|
||||
struct ceb_node *cebua_lookup_le(struct ceb_node **root, const void *key);
|
||||
struct ceb_node *cebua_lookup_lt(struct ceb_node **root, const void *key);
|
||||
struct ceb_node *cebua_lookup_ge(struct ceb_node **root, const void *key);
|
||||
struct ceb_node *cebua_lookup_gt(struct ceb_node **root, const void *key);
|
||||
struct ceb_node *cebua_next(struct ceb_node **root, struct ceb_node *node);
|
||||
struct ceb_node *cebua_prev(struct ceb_node **root, struct ceb_node *node);
|
||||
struct ceb_node *cebua_delete(struct ceb_node **root, struct ceb_node *node);
|
||||
struct ceb_node *cebua_pick(struct ceb_node **root, const void *key);
|
||||
void cebua_default_dump(struct ceb_node **root, const char *label, const void *ctx);
|
||||
|
||||
/* version taking a key offset */
|
||||
struct ceb_node *cebua_ofs_insert(struct ceb_node **root, ptrdiff_t kofs, struct ceb_node *node);
|
||||
struct ceb_node *cebua_ofs_first(struct ceb_node **root, ptrdiff_t kofs);
|
||||
struct ceb_node *cebua_ofs_last(struct ceb_node **root, ptrdiff_t kofs);
|
||||
struct ceb_node *cebua_ofs_lookup(struct ceb_node **root, ptrdiff_t kofs, const void *key);
|
||||
struct ceb_node *cebua_ofs_lookup_le(struct ceb_node **root, ptrdiff_t kofs, const void *key);
|
||||
struct ceb_node *cebua_ofs_lookup_lt(struct ceb_node **root, ptrdiff_t kofs, const void *key);
|
||||
struct ceb_node *cebua_ofs_lookup_ge(struct ceb_node **root, ptrdiff_t kofs, const void *key);
|
||||
struct ceb_node *cebua_ofs_lookup_gt(struct ceb_node **root, ptrdiff_t kofs, const void *key);
|
||||
struct ceb_node *cebua_ofs_next(struct ceb_node **root, ptrdiff_t kofs, struct ceb_node *node);
|
||||
struct ceb_node *cebua_ofs_prev(struct ceb_node **root, ptrdiff_t kofs, struct ceb_node *node);
|
||||
struct ceb_node *cebua_ofs_delete(struct ceb_node **root, ptrdiff_t kofs, struct ceb_node *node);
|
||||
struct ceb_node *cebua_ofs_pick(struct ceb_node **root, ptrdiff_t kofs, const void *key);
|
||||
void cebua_ofs_default_dump(struct ceb_node **root, ptrdiff_t kofs, const char *label, const void *ctx);
|
@ -1,55 +0,0 @@
|
||||
/*
|
||||
* Compact Elastic Binary Trees - exported functions operating on mb keys
|
||||
*
|
||||
* Copyright (C) 2014-2024 Willy Tarreau - w@1wt.eu
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "cebtree.h"
|
||||
|
||||
/* simpler version */
|
||||
struct ceb_node *cebub_insert(struct ceb_node **root, struct ceb_node *node, size_t len);
|
||||
struct ceb_node *cebub_first(struct ceb_node **root);
|
||||
struct ceb_node *cebub_last(struct ceb_node **root);
|
||||
struct ceb_node *cebub_lookup(struct ceb_node **root, const void *key, size_t len);
|
||||
struct ceb_node *cebub_lookup_le(struct ceb_node **root, const void *key, size_t len);
|
||||
struct ceb_node *cebub_lookup_lt(struct ceb_node **root, const void *key, size_t len);
|
||||
struct ceb_node *cebub_lookup_ge(struct ceb_node **root, const void *key, size_t len);
|
||||
struct ceb_node *cebub_lookup_gt(struct ceb_node **root, const void *key, size_t len);
|
||||
struct ceb_node *cebub_next(struct ceb_node **root, struct ceb_node *node, size_t len);
|
||||
struct ceb_node *cebub_prev(struct ceb_node **root, struct ceb_node *node, size_t len);
|
||||
struct ceb_node *cebub_delete(struct ceb_node **root, struct ceb_node *node, size_t len);
|
||||
struct ceb_node *cebub_pick(struct ceb_node **root, const void *key, size_t len);
|
||||
|
||||
/* version taking a key offset */
|
||||
struct ceb_node *cebub_ofs_insert(struct ceb_node **root, ptrdiff_t kofs, struct ceb_node *node, size_t len);
|
||||
struct ceb_node *cebub_ofs_first(struct ceb_node **root, ptrdiff_t kofs, size_t len);
|
||||
struct ceb_node *cebub_ofs_last(struct ceb_node **root, ptrdiff_t kofs, size_t len);
|
||||
struct ceb_node *cebub_ofs_lookup(struct ceb_node **root, ptrdiff_t kofs, const void *key, size_t len);
|
||||
struct ceb_node *cebub_ofs_lookup_le(struct ceb_node **root, ptrdiff_t kofs, const void *key, size_t len);
|
||||
struct ceb_node *cebub_ofs_lookup_lt(struct ceb_node **root, ptrdiff_t kofs, const void *key, size_t len);
|
||||
struct ceb_node *cebub_ofs_lookup_ge(struct ceb_node **root, ptrdiff_t kofs, const void *key, size_t len);
|
||||
struct ceb_node *cebub_ofs_lookup_gt(struct ceb_node **root, ptrdiff_t kofs, const void *key, size_t len);
|
||||
struct ceb_node *cebub_ofs_next(struct ceb_node **root, ptrdiff_t kofs, struct ceb_node *node, size_t len);
|
||||
struct ceb_node *cebub_ofs_prev(struct ceb_node **root, ptrdiff_t kofs, struct ceb_node *node, size_t len);
|
||||
struct ceb_node *cebub_ofs_delete(struct ceb_node **root, ptrdiff_t kofs, struct ceb_node *node, size_t len);
|
||||
struct ceb_node *cebub_ofs_pick(struct ceb_node **root, ptrdiff_t kofs, const void *key, size_t len);
|
@ -1,55 +0,0 @@
|
||||
/*
|
||||
* Compact Elastic Binary Trees - exported functions operating on indirect blocks
|
||||
*
|
||||
* Copyright (C) 2014-2024 Willy Tarreau - w@1wt.eu
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "cebtree.h"
|
||||
|
||||
/* simpler version */
|
||||
struct ceb_node *cebuib_insert(struct ceb_node **root, struct ceb_node *node, size_t len);
|
||||
struct ceb_node *cebuib_first(struct ceb_node **root);
|
||||
struct ceb_node *cebuib_last(struct ceb_node **root);
|
||||
struct ceb_node *cebuib_lookup(struct ceb_node **root, const void *key, size_t len);
|
||||
struct ceb_node *cebuib_lookup_le(struct ceb_node **root, const void *key, size_t len);
|
||||
struct ceb_node *cebuib_lookup_lt(struct ceb_node **root, const void *key, size_t len);
|
||||
struct ceb_node *cebuib_lookup_ge(struct ceb_node **root, const void *key, size_t len);
|
||||
struct ceb_node *cebuib_lookup_gt(struct ceb_node **root, const void *key, size_t len);
|
||||
struct ceb_node *cebuib_next(struct ceb_node **root, struct ceb_node *node, size_t len);
|
||||
struct ceb_node *cebuib_prev(struct ceb_node **root, struct ceb_node *node, size_t len);
|
||||
struct ceb_node *cebuib_delete(struct ceb_node **root, struct ceb_node *node, size_t len);
|
||||
struct ceb_node *cebuib_pick(struct ceb_node **root, const void *key, size_t len);
|
||||
|
||||
/* version taking a key offset */
|
||||
struct ceb_node *cebuib_ofs_insert(struct ceb_node **root, ptrdiff_t kofs, struct ceb_node *node, size_t len);
|
||||
struct ceb_node *cebuib_ofs_first(struct ceb_node **root, ptrdiff_t kofs, size_t len);
|
||||
struct ceb_node *cebuib_ofs_last(struct ceb_node **root, ptrdiff_t kofs, size_t len);
|
||||
struct ceb_node *cebuib_ofs_lookup(struct ceb_node **root, ptrdiff_t kofs, const void *key, size_t len);
|
||||
struct ceb_node *cebuib_ofs_lookup_le(struct ceb_node **root, ptrdiff_t kofs, const void *key, size_t len);
|
||||
struct ceb_node *cebuib_ofs_lookup_lt(struct ceb_node **root, ptrdiff_t kofs, const void *key, size_t len);
|
||||
struct ceb_node *cebuib_ofs_lookup_ge(struct ceb_node **root, ptrdiff_t kofs, const void *key, size_t len);
|
||||
struct ceb_node *cebuib_ofs_lookup_gt(struct ceb_node **root, ptrdiff_t kofs, const void *key, size_t len);
|
||||
struct ceb_node *cebuib_ofs_next(struct ceb_node **root, ptrdiff_t kofs, struct ceb_node *node, size_t len);
|
||||
struct ceb_node *cebuib_ofs_prev(struct ceb_node **root, ptrdiff_t kofs, struct ceb_node *node, size_t len);
|
||||
struct ceb_node *cebuib_ofs_delete(struct ceb_node **root, ptrdiff_t kofs, struct ceb_node *node, size_t len);
|
||||
struct ceb_node *cebuib_ofs_pick(struct ceb_node **root, ptrdiff_t kofs, const void *key, size_t len);
|
@ -1,57 +0,0 @@
|
||||
/*
|
||||
* Compact Elastic Binary Trees - exported functions operating on indirect strings
|
||||
*
|
||||
* Copyright (C) 2014-2024 Willy Tarreau - w@1wt.eu
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "cebtree.h"
|
||||
|
||||
/* simpler version */
|
||||
struct ceb_node *cebuis_insert(struct ceb_node **root, struct ceb_node *node);
|
||||
struct ceb_node *cebuis_first(struct ceb_node **root);
|
||||
struct ceb_node *cebuis_last(struct ceb_node **root);
|
||||
struct ceb_node *cebuis_lookup(struct ceb_node **root, const void *key);
|
||||
struct ceb_node *cebuis_lookup_le(struct ceb_node **root, const void *key);
|
||||
struct ceb_node *cebuis_lookup_lt(struct ceb_node **root, const void *key);
|
||||
struct ceb_node *cebuis_lookup_ge(struct ceb_node **root, const void *key);
|
||||
struct ceb_node *cebuis_lookup_gt(struct ceb_node **root, const void *key);
|
||||
struct ceb_node *cebuis_next(struct ceb_node **root, struct ceb_node *node);
|
||||
struct ceb_node *cebuis_prev(struct ceb_node **root, struct ceb_node *node);
|
||||
struct ceb_node *cebuis_delete(struct ceb_node **root, struct ceb_node *node);
|
||||
struct ceb_node *cebuis_pick(struct ceb_node **root, const void *key);
|
||||
void cebuis_default_dump(struct ceb_node **root, const char *label, const void *ctx);
|
||||
|
||||
/* version taking a key offset */
|
||||
struct ceb_node *cebuis_ofs_insert(struct ceb_node **root, ptrdiff_t kofs, struct ceb_node *node);
|
||||
struct ceb_node *cebuis_ofs_first(struct ceb_node **root, ptrdiff_t kofs);
|
||||
struct ceb_node *cebuis_ofs_last(struct ceb_node **root, ptrdiff_t kofs);
|
||||
struct ceb_node *cebuis_ofs_lookup(struct ceb_node **root, ptrdiff_t kofs, const void *key);
|
||||
struct ceb_node *cebuis_ofs_lookup_le(struct ceb_node **root, ptrdiff_t kofs, const void *key);
|
||||
struct ceb_node *cebuis_ofs_lookup_lt(struct ceb_node **root, ptrdiff_t kofs, const void *key);
|
||||
struct ceb_node *cebuis_ofs_lookup_ge(struct ceb_node **root, ptrdiff_t kofs, const void *key);
|
||||
struct ceb_node *cebuis_ofs_lookup_gt(struct ceb_node **root, ptrdiff_t kofs, const void *key);
|
||||
struct ceb_node *cebuis_ofs_next(struct ceb_node **root, ptrdiff_t kofs, struct ceb_node *node);
|
||||
struct ceb_node *cebuis_ofs_prev(struct ceb_node **root, ptrdiff_t kofs, struct ceb_node *node);
|
||||
struct ceb_node *cebuis_ofs_delete(struct ceb_node **root, ptrdiff_t kofs, struct ceb_node *node);
|
||||
struct ceb_node *cebuis_ofs_pick(struct ceb_node **root, ptrdiff_t kofs, const void *key);
|
||||
void cebuis_ofs_default_dump(struct ceb_node **root, ptrdiff_t kofs, const char *label, const void *ctx);
|
@ -1,57 +0,0 @@
|
||||
/*
|
||||
* Compact Elastic Binary Trees - exported functions operating on ulong keys
|
||||
*
|
||||
* Copyright (C) 2014-2024 Willy Tarreau - w@1wt.eu
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "cebtree.h"
|
||||
|
||||
/* simpler version */
|
||||
struct ceb_node *cebul_insert(struct ceb_node **root, struct ceb_node *node);
|
||||
struct ceb_node *cebul_first(struct ceb_node **root);
|
||||
struct ceb_node *cebul_last(struct ceb_node **root);
|
||||
struct ceb_node *cebul_lookup(struct ceb_node **root, unsigned long key);
|
||||
struct ceb_node *cebul_lookup_le(struct ceb_node **root, unsigned long key);
|
||||
struct ceb_node *cebul_lookup_lt(struct ceb_node **root, unsigned long key);
|
||||
struct ceb_node *cebul_lookup_ge(struct ceb_node **root, unsigned long key);
|
||||
struct ceb_node *cebul_lookup_gt(struct ceb_node **root, unsigned long key);
|
||||
struct ceb_node *cebul_next(struct ceb_node **root, struct ceb_node *node);
|
||||
struct ceb_node *cebul_prev(struct ceb_node **root, struct ceb_node *node);
|
||||
struct ceb_node *cebul_delete(struct ceb_node **root, struct ceb_node *node);
|
||||
struct ceb_node *cebul_pick(struct ceb_node **root, unsigned long key);
|
||||
void cebul_default_dump(struct ceb_node **ceb_root, const char *label, const void *ctx);
|
||||
|
||||
/* version taking a key offset */
|
||||
struct ceb_node *cebul_ofs_insert(struct ceb_node **root, ptrdiff_t kofs, struct ceb_node *node);
|
||||
struct ceb_node *cebul_ofs_first(struct ceb_node **root, ptrdiff_t kofs);
|
||||
struct ceb_node *cebul_ofs_last(struct ceb_node **root, ptrdiff_t kofs);
|
||||
struct ceb_node *cebul_ofs_lookup(struct ceb_node **root, ptrdiff_t kofs, unsigned long key);
|
||||
struct ceb_node *cebul_ofs_lookup_le(struct ceb_node **root, ptrdiff_t kofs, unsigned long key);
|
||||
struct ceb_node *cebul_ofs_lookup_lt(struct ceb_node **root, ptrdiff_t kofs, unsigned long key);
|
||||
struct ceb_node *cebul_ofs_lookup_ge(struct ceb_node **root, ptrdiff_t kofs, unsigned long key);
|
||||
struct ceb_node *cebul_ofs_lookup_gt(struct ceb_node **root, ptrdiff_t kofs, unsigned long key);
|
||||
struct ceb_node *cebul_ofs_next(struct ceb_node **root, ptrdiff_t kofs, struct ceb_node *node);
|
||||
struct ceb_node *cebul_ofs_prev(struct ceb_node **root, ptrdiff_t kofs, struct ceb_node *node);
|
||||
struct ceb_node *cebul_ofs_delete(struct ceb_node **root, ptrdiff_t kofs, struct ceb_node *node);
|
||||
struct ceb_node *cebul_ofs_pick(struct ceb_node **root, ptrdiff_t kofs, unsigned long key);
|
||||
void cebul_ofs_default_dump(struct ceb_node **root, ptrdiff_t kofs, const char *label, const void *ctx);
|
@ -1,57 +0,0 @@
|
||||
/*
|
||||
* Compact Elastic Binary Trees - exported functions operating on string keys
|
||||
*
|
||||
* Copyright (C) 2014-2024 Willy Tarreau - w@1wt.eu
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "cebtree.h"
|
||||
|
||||
/* simpler version */
|
||||
struct ceb_node *cebus_insert(struct ceb_node **root, struct ceb_node *node);
|
||||
struct ceb_node *cebus_first(struct ceb_node **root);
|
||||
struct ceb_node *cebus_last(struct ceb_node **root);
|
||||
struct ceb_node *cebus_lookup(struct ceb_node **root, const void *key);
|
||||
struct ceb_node *cebus_lookup_le(struct ceb_node **root, const void *key);
|
||||
struct ceb_node *cebus_lookup_lt(struct ceb_node **root, const void *key);
|
||||
struct ceb_node *cebus_lookup_ge(struct ceb_node **root, const void *key);
|
||||
struct ceb_node *cebus_lookup_gt(struct ceb_node **root, const void *key);
|
||||
struct ceb_node *cebus_next(struct ceb_node **root, struct ceb_node *node);
|
||||
struct ceb_node *cebus_prev(struct ceb_node **root, struct ceb_node *node);
|
||||
struct ceb_node *cebus_delete(struct ceb_node **root, struct ceb_node *node);
|
||||
struct ceb_node *cebus_pick(struct ceb_node **root, const void *key);
|
||||
void cebus_default_dump(struct ceb_node **root, const char *label, const void *ctx);
|
||||
|
||||
/* version taking a key offset */
|
||||
struct ceb_node *cebus_ofs_insert(struct ceb_node **root, ptrdiff_t kofs, struct ceb_node *node);
|
||||
struct ceb_node *cebus_ofs_first(struct ceb_node **root, ptrdiff_t kofs);
|
||||
struct ceb_node *cebus_ofs_last(struct ceb_node **root, ptrdiff_t kofs);
|
||||
struct ceb_node *cebus_ofs_lookup(struct ceb_node **root, ptrdiff_t kofs, const void *key);
|
||||
struct ceb_node *cebus_ofs_lookup_le(struct ceb_node **root, ptrdiff_t kofs, const void *key);
|
||||
struct ceb_node *cebus_ofs_lookup_lt(struct ceb_node **root, ptrdiff_t kofs, const void *key);
|
||||
struct ceb_node *cebus_ofs_lookup_ge(struct ceb_node **root, ptrdiff_t kofs, const void *key);
|
||||
struct ceb_node *cebus_ofs_lookup_gt(struct ceb_node **root, ptrdiff_t kofs, const void *key);
|
||||
struct ceb_node *cebus_ofs_next(struct ceb_node **root, ptrdiff_t kofs, struct ceb_node *node);
|
||||
struct ceb_node *cebus_ofs_prev(struct ceb_node **root, ptrdiff_t kofs, struct ceb_node *node);
|
||||
struct ceb_node *cebus_ofs_delete(struct ceb_node **root, ptrdiff_t kofs, struct ceb_node *node);
|
||||
struct ceb_node *cebus_ofs_pick(struct ceb_node **root, ptrdiff_t kofs, const void *key);
|
||||
void cebus_ofs_default_dump(struct ceb_node **root, ptrdiff_t kofs, const char *label, const void *ctx);
|
190
src/_ceb_addr.c
Normal file
190
src/_ceb_addr.c
Normal file
@ -0,0 +1,190 @@
|
||||
/*
|
||||
* Compact Elastic Binary Trees - exported functions operating on addr keys
|
||||
*
|
||||
* Copyright (C) 2014-2025 Willy Tarreau - w@1wt.eu
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/* NOTE: this file is only meant to be included from other C files. It will
|
||||
* use the following private macros that must be defined by the caller:
|
||||
* - CEB_KEY_TYPE: CEB_KT_ADDR
|
||||
* - CEB_MKEY_PFX: function name prefix for multi-key (ceba)
|
||||
* - CEB_UKEY_PFX: function name prefix for unique keys (cebua)
|
||||
*
|
||||
* There's no support for duplicates (we're indexing the node's address), nor
|
||||
* for offsets (it makes no sense to apply an offset to the node's address).
|
||||
*/
|
||||
#include "cebtree-prv.h"
|
||||
|
||||
/*
|
||||
* Below are the functions that only support unique keys (_cebu_*)
|
||||
*/
|
||||
|
||||
/*****************************************************************************\
|
||||
* The declarations below always cause two functions to be declared, one *
|
||||
* starting with "cebua_*" and one with "cebua_ofs_*" which takes a key *
|
||||
* offset just after the root. The one without kofs just has this argument *
|
||||
* omitted from its declaration and replaced with sizeof(struct ceb_node) in *
|
||||
* the call to the underlying functions. *
|
||||
\*****************************************************************************/
|
||||
|
||||
/* Inserts node <node> into unique tree <tree> based on its own address
|
||||
* Returns the inserted node or the one that has the same address.
|
||||
*/
|
||||
CEB_FDECL3(struct ceb_node *, CEB_UKEY_PFX, _insert, struct ceb_root **, root, ptrdiff_t, kofs, struct ceb_node *, node)
|
||||
{
|
||||
return _ceb_insert(root, node, kofs, CEB_KEY_TYPE, 0, 0, node, NULL);
|
||||
}
|
||||
|
||||
/* return the first node or NULL if not found. */
|
||||
CEB_FDECL2(struct ceb_node *, CEB_UKEY_PFX, _first, struct ceb_root *const *, root, ptrdiff_t, kofs)
|
||||
{
|
||||
return _ceb_first(root, kofs, CEB_KEY_TYPE, 0, NULL);
|
||||
}
|
||||
|
||||
/* return the last node or NULL if not found. */
|
||||
CEB_FDECL2(struct ceb_node *, CEB_UKEY_PFX, _last, struct ceb_root *const *, root, ptrdiff_t, kofs)
|
||||
{
|
||||
return _ceb_last(root, kofs, CEB_KEY_TYPE, 0, NULL);
|
||||
}
|
||||
|
||||
/* look up the specified key, and returns either the node containing it, or
|
||||
* NULL if not found.
|
||||
*/
|
||||
CEB_FDECL3(struct ceb_node *, CEB_UKEY_PFX, _lookup, struct ceb_root *const *, root, ptrdiff_t, kofs, const void *, key)
|
||||
{
|
||||
return _ceb_lookup(root, kofs, CEB_KEY_TYPE, 0, 0, key, NULL);
|
||||
}
|
||||
|
||||
/* look up the specified key or the highest below it, and returns either the
|
||||
* node containing it, or NULL if not found.
|
||||
*/
|
||||
CEB_FDECL3(struct ceb_node *, CEB_UKEY_PFX, _lookup_le, struct ceb_root *const *, root, ptrdiff_t, kofs, const void *, key)
|
||||
{
|
||||
return _ceb_lookup_le(root, kofs, CEB_KEY_TYPE, 0, 0, key, NULL);
|
||||
}
|
||||
|
||||
/* look up highest key below the specified one, and returns either the
|
||||
* node containing it, or NULL if not found.
|
||||
*/
|
||||
CEB_FDECL3(struct ceb_node *, CEB_UKEY_PFX, _lookup_lt, struct ceb_root *const *, root, ptrdiff_t, kofs, const void *, key)
|
||||
{
|
||||
return _ceb_lookup_lt(root, kofs, CEB_KEY_TYPE, 0, 0, key, NULL);
|
||||
}
|
||||
|
||||
/* look up the specified key or the smallest above it, and returns either the
|
||||
* node containing it, or NULL if not found.
|
||||
*/
|
||||
CEB_FDECL3(struct ceb_node *, CEB_UKEY_PFX, _lookup_ge, struct ceb_root *const *, root, ptrdiff_t, kofs, const void *, key)
|
||||
{
|
||||
return _ceb_lookup_ge(root, kofs, CEB_KEY_TYPE, 0, 0, key, NULL);
|
||||
}
|
||||
|
||||
/* look up the smallest key above the specified one, and returns either the
|
||||
* node containing it, or NULL if not found.
|
||||
*/
|
||||
CEB_FDECL3(struct ceb_node *, CEB_UKEY_PFX, _lookup_gt, struct ceb_root *const *, root, ptrdiff_t, kofs, const void *, key)
|
||||
{
|
||||
return _ceb_lookup_gt(root, kofs, CEB_KEY_TYPE, 0, 0, key, NULL);
|
||||
}
|
||||
|
||||
/* search for the next node after the specified one, and return it, or NULL if
|
||||
* not found. The approach consists in looking up that node, recalling the last
|
||||
* time a left turn was made, and returning the first node along the right
|
||||
* branch at that fork.
|
||||
*/
|
||||
CEB_FDECL3(struct ceb_node *, CEB_UKEY_PFX, _next, struct ceb_root *const *, root, ptrdiff_t, kofs, struct ceb_node *, node)
|
||||
{
|
||||
return _ceb_next_unique(root, kofs, CEB_KEY_TYPE, 0, 0, node, NULL);
|
||||
}
|
||||
|
||||
/* search for the prev node before the specified one, and return it, or NULL if
|
||||
* not found. The approach consists in looking up that node, recalling the last
|
||||
* time a right turn was made, and returning the last node along the left
|
||||
* branch at that fork.
|
||||
*/
|
||||
CEB_FDECL3(struct ceb_node *, CEB_UKEY_PFX, _prev, struct ceb_root *const *, root, ptrdiff_t, kofs, struct ceb_node *, node)
|
||||
{
|
||||
return _ceb_prev_unique(root, kofs, CEB_KEY_TYPE, 0, 0, node, NULL);
|
||||
}
|
||||
|
||||
/* look up the specified node with its key and deletes it if found, and in any
|
||||
* case, returns the node.
|
||||
*/
|
||||
CEB_FDECL3(struct ceb_node *, CEB_UKEY_PFX, _delete, struct ceb_root **, root, ptrdiff_t, kofs, struct ceb_node *, node)
|
||||
{
|
||||
return _ceb_delete(root, node, kofs, CEB_KEY_TYPE, 0, 0, node, NULL);
|
||||
}
|
||||
|
||||
/* look up the specified key, and detaches it and returns it if found, or NULL
|
||||
* if not found.
|
||||
*/
|
||||
CEB_FDECL3(struct ceb_node *, CEB_UKEY_PFX, _pick, struct ceb_root **, root, ptrdiff_t, kofs, const void *, key)
|
||||
{
|
||||
return _ceb_delete(root, NULL, kofs, CEB_KEY_TYPE, 0, 0, key, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Functions used to dump trees in Dot format. These are only enabled if
|
||||
* CEB_ENABLE_DUMP is defined.
|
||||
*/
|
||||
|
||||
#if defined(CEB_ENABLE_DUMP)
|
||||
|
||||
#include <stdio.h>
|
||||
#define TO_STR(x) _TO_STR(x)
|
||||
#define _TO_STR(x) #x
|
||||
|
||||
/* dumps a ceb_node tree using the default functions above. If a node matches
|
||||
* <ctx>, this one will be highlighted in red. If the <sub> value is non-null,
|
||||
* only a subgraph will be printed. If it's null, and root is non-null, then
|
||||
* the tree is dumped at once, otherwise if root is NULL, then a prologue is
|
||||
* dumped when label is not NULL, or the epilogue when label is NULL. As a
|
||||
* summary:
|
||||
* sub root label
|
||||
* 0 NULL NULL epilogue only (closing brace and LF)
|
||||
* 0 NULL text prologue with <text> as label
|
||||
* 0 tree * prologue+tree+epilogue at once
|
||||
* N>0 tree * only the tree, after a prologue and before an epilogue
|
||||
*/
|
||||
CEB_FDECL5(void, CEB_MKEY_PFX, _default_dump, struct ceb_root *const *, root, ptrdiff_t, kofs, const char *, label, const void *, ctx, int, sub)
|
||||
{
|
||||
if (!sub && label) {
|
||||
printf("\ndigraph " TO_STR(CEB_MKEY_PFX) "_tree {\n"
|
||||
" fontname=\"fixed\";\n"
|
||||
" fontsize=8\n"
|
||||
" label=\"%s\"\n"
|
||||
"", label);
|
||||
|
||||
printf(" node [fontname=\"fixed\" fontsize=8 shape=\"box\" style=\"filled\" color=\"black\" fillcolor=\"white\"];\n"
|
||||
" edge [fontname=\"fixed\" fontsize=8 style=\"solid\" color=\"magenta\" dir=\"forward\"];\n");
|
||||
} else
|
||||
printf("\n### sub %d ###\n\n", sub);
|
||||
|
||||
if (root)
|
||||
ceb_imm_default_dump_tree(kofs, CEB_KEY_TYPE, root, 0, NULL, 0, ctx, sub, NULL, NULL, NULL, NULL);
|
||||
|
||||
if (!sub && (root || !label))
|
||||
printf("}\n");
|
||||
}
|
||||
|
||||
#endif /* CEB_ENABLE_DUMP */
|
342
src/_ceb_blk.c
Normal file
342
src/_ceb_blk.c
Normal file
@ -0,0 +1,342 @@
|
||||
/*
|
||||
* Compact Elastic Binary Trees - exported functions operating on mb keys
|
||||
*
|
||||
* Copyright (C) 2014-2025 Willy Tarreau - w@1wt.eu
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/* NOTE: this file is only meant to be included from other C files. It will
|
||||
* use the following private macros that must be defined by the caller:
|
||||
* - CEB_KEY_TYPE: CEB_KT_IM, CEB_KT_MB
|
||||
* - CEB_KEY_MEMBER: member of the struct ceb_node holding the key
|
||||
* - CEB_MKEY_PFX: function name prefix for multi-key
|
||||
* - CEB_UKEY_PFX: function name prefix for unique keys
|
||||
*/
|
||||
#include "cebtree-prv.h"
|
||||
|
||||
/*
|
||||
* Below are the functions that support duplicate keys (_ceb_*)
|
||||
*/
|
||||
|
||||
/*****************************************************************************\
|
||||
* The declarations below always cause two functions to be declared, one *
|
||||
* starting with "cebs_*" and one with "cebs_ofs_*" which takes a key offset *
|
||||
* just after the root. The one without kofs just has this argument omitted *
|
||||
* from its declaration and replaced with sizeof(struct ceb_node) in the *
|
||||
* call to the underlying functions. *
|
||||
\*****************************************************************************/
|
||||
|
||||
/* Inserts node <node> into tree <tree> based on its key that immediately
|
||||
* follows the node and for <len> bytes. Returns the inserted node or the one
|
||||
* that already contains the same key.
|
||||
*/
|
||||
CEB_FDECL4(struct ceb_node *, CEB_MKEY_PFX, _insert, struct ceb_root **, root, ptrdiff_t, kofs, struct ceb_node *, node, size_t, len)
|
||||
{
|
||||
const void *key = NODEK(node, kofs)->CEB_KEY_MEMBER;
|
||||
int is_dup;
|
||||
|
||||
return _ceb_insert(root, node, kofs, CEB_KEY_TYPE, 0, len, key, &is_dup);
|
||||
}
|
||||
|
||||
/* return the first node or NULL if not found. */
|
||||
CEB_FDECL3(struct ceb_node *, CEB_MKEY_PFX, _first, struct ceb_root *const *, root, ptrdiff_t, kofs, size_t, len)
|
||||
{
|
||||
int is_dup;
|
||||
|
||||
return _ceb_first(root, kofs, CEB_KEY_TYPE, len, &is_dup);
|
||||
}
|
||||
|
||||
/* return the last node or NULL if not found. */
|
||||
CEB_FDECL3(struct ceb_node *, CEB_MKEY_PFX, _last, struct ceb_root *const *, root, ptrdiff_t, kofs, size_t, len)
|
||||
{
|
||||
int is_dup;
|
||||
|
||||
return _ceb_last(root, kofs, CEB_KEY_TYPE, len, &is_dup);
|
||||
}
|
||||
|
||||
/* look up the specified key <key> of length <len>, and returns either the node
|
||||
* containing it, or NULL if not found.
|
||||
*/
|
||||
CEB_FDECL4(struct ceb_node *, CEB_MKEY_PFX, _lookup, struct ceb_root *const *, root, ptrdiff_t, kofs, const void *, key, size_t, len)
|
||||
{
|
||||
int is_dup;
|
||||
|
||||
return _ceb_lookup(root, kofs, CEB_KEY_TYPE, 0, len, key, &is_dup);
|
||||
}
|
||||
|
||||
/* look up the specified key or the highest below it, and returns either the
|
||||
* node containing it, or NULL if not found.
|
||||
*/
|
||||
CEB_FDECL4(struct ceb_node *, CEB_MKEY_PFX, _lookup_le, struct ceb_root *const *, root, ptrdiff_t, kofs, const void *, key, size_t, len)
|
||||
{
|
||||
int is_dup;
|
||||
|
||||
return _ceb_lookup_le(root, kofs, CEB_KEY_TYPE, 0, len, key, &is_dup);
|
||||
}
|
||||
|
||||
/* look up highest key below the specified one, and returns either the
|
||||
* node containing it, or NULL if not found.
|
||||
*/
|
||||
CEB_FDECL4(struct ceb_node *, CEB_MKEY_PFX, _lookup_lt, struct ceb_root *const *, root, ptrdiff_t, kofs, const void *, key, size_t, len)
|
||||
{
|
||||
int is_dup;
|
||||
|
||||
return _ceb_lookup_lt(root, kofs, CEB_KEY_TYPE, 0, len, key, &is_dup);
|
||||
}
|
||||
|
||||
/* look up the specified key or the smallest above it, and returns either the
|
||||
* node containing it, or NULL if not found.
|
||||
*/
|
||||
CEB_FDECL4(struct ceb_node *, CEB_MKEY_PFX, _lookup_ge, struct ceb_root *const *, root, ptrdiff_t, kofs, const void *, key, size_t, len)
|
||||
{
|
||||
int is_dup;
|
||||
|
||||
return _ceb_lookup_ge(root, kofs, CEB_KEY_TYPE, 0, len, key, &is_dup);
|
||||
}
|
||||
|
||||
/* look up the smallest key above the specified one, and returns either the
|
||||
* node containing it, or NULL if not found.
|
||||
*/
|
||||
CEB_FDECL4(struct ceb_node *, CEB_MKEY_PFX, _lookup_gt, struct ceb_root *const *, root, ptrdiff_t, kofs, const void *, key, size_t, len)
|
||||
{
|
||||
int is_dup;
|
||||
|
||||
return _ceb_lookup_gt(root, kofs, CEB_KEY_TYPE, 0, len, key, &is_dup);
|
||||
}
|
||||
|
||||
/* search for the next node after the specified one, and return it, or NULL if
|
||||
* not found. The approach consists in looking up that node, recalling the last
|
||||
* time a left turn was made, and returning the first node along the right
|
||||
* branch at that fork. The <len> field must correspond to the key length in
|
||||
* bytes.
|
||||
*/
|
||||
CEB_FDECL4(struct ceb_node *, CEB_MKEY_PFX, _next_unique, struct ceb_root *const *, root, ptrdiff_t, kofs, struct ceb_node *, node, size_t, len)
|
||||
{
|
||||
const void *key = NODEK(node, kofs)->CEB_KEY_MEMBER;
|
||||
int is_dup;
|
||||
|
||||
return _ceb_next_unique(root, kofs, CEB_KEY_TYPE, 0, len, key, &is_dup);
|
||||
}
|
||||
|
||||
/* search for the prev node before the specified one, and return it, or NULL if
|
||||
* not found. The approach consists in looking up that node, recalling the last
|
||||
* time a right turn was made, and returning the last node along the left
|
||||
* branch at that fork. The <len> field must correspond to the key length in
|
||||
* bytes.
|
||||
*/
|
||||
CEB_FDECL4(struct ceb_node *, CEB_MKEY_PFX, _prev_unique, struct ceb_root *const *, root, ptrdiff_t, kofs, struct ceb_node *, node, size_t, len)
|
||||
{
|
||||
const void *key = NODEK(node, kofs)->CEB_KEY_MEMBER;
|
||||
int is_dup;
|
||||
|
||||
return _ceb_prev_unique(root, kofs, CEB_KEY_TYPE, 0, len, key, &is_dup);
|
||||
}
|
||||
|
||||
/* search for the next node after the specified one containing the same value,
|
||||
* and return it, or NULL if not found.
|
||||
*/
|
||||
CEB_FDECL4(struct ceb_node *, CEB_MKEY_PFX, _next_dup, struct ceb_root *const *, root, ptrdiff_t, kofs, struct ceb_node *, node, size_t, len)
|
||||
{
|
||||
const void *key = NODEK(node, kofs)->CEB_KEY_MEMBER;
|
||||
|
||||
return _ceb_next_dup(root, kofs, CEB_KEY_TYPE, 0, len, key, node);
|
||||
}
|
||||
|
||||
/* search for the prev node before the specified one containing the same value,
|
||||
* and return it, or NULL if not found.
|
||||
*/
|
||||
CEB_FDECL4(struct ceb_node *, CEB_MKEY_PFX, _prev_dup, struct ceb_root *const *, root, ptrdiff_t, kofs, struct ceb_node *, node, size_t, len)
|
||||
{
|
||||
const void *key = NODEK(node, kofs)->CEB_KEY_MEMBER;
|
||||
|
||||
return _ceb_prev_dup(root, kofs, CEB_KEY_TYPE, 0, len, key, node);
|
||||
}
|
||||
|
||||
/* search for the next node after the specified one, and return it, or NULL if
|
||||
* not found. The approach consists in looking up that node, recalling the last
|
||||
* time a left turn was made, and returning the first node along the right
|
||||
* branch at that fork. The <len> field must correspond to the key length in
|
||||
* bytes.
|
||||
*/
|
||||
CEB_FDECL4(struct ceb_node *, CEB_MKEY_PFX, _next, struct ceb_root *const *, root, ptrdiff_t, kofs, struct ceb_node *, node, size_t, len)
|
||||
{
|
||||
const void *key = NODEK(node, kofs)->CEB_KEY_MEMBER;
|
||||
int is_dup;
|
||||
|
||||
return _ceb_next(root, kofs, CEB_KEY_TYPE, 0, len, key, node, &is_dup);
|
||||
}
|
||||
|
||||
/* search for the prev node before the specified one, and return it, or NULL if
|
||||
* not found. The approach consists in looking up that node, recalling the last
|
||||
* time a right turn was made, and returning the last node along the left
|
||||
* branch at that fork. The <len> field must correspond to the key length in
|
||||
* bytes.
|
||||
*/
|
||||
CEB_FDECL4(struct ceb_node *, CEB_MKEY_PFX, _prev, struct ceb_root *const *, root, ptrdiff_t, kofs, struct ceb_node *, node, size_t, len)
|
||||
{
|
||||
const void *key = NODEK(node, kofs)->CEB_KEY_MEMBER;
|
||||
int is_dup;
|
||||
|
||||
return _ceb_prev(root, kofs, CEB_KEY_TYPE, 0, len, key, node, &is_dup);
|
||||
}
|
||||
|
||||
/* look up the specified node with its key and deletes it if found, and in any
|
||||
* case, returns the node. The <len> field must correspond to the key length in
|
||||
* bytes.
|
||||
*/
|
||||
CEB_FDECL4(struct ceb_node *, CEB_MKEY_PFX, _delete, struct ceb_root **, root, ptrdiff_t, kofs, struct ceb_node *, node, size_t, len)
|
||||
{
|
||||
const void *key = NODEK(node, kofs)->CEB_KEY_MEMBER;
|
||||
int is_dup;
|
||||
|
||||
return _ceb_delete(root, node, kofs, CEB_KEY_TYPE, 0, len, key, &is_dup);
|
||||
}
|
||||
|
||||
/* look up the specified key, and detaches it and returns it if found, or NULL
|
||||
* if not found. The <len> field must correspond to the key length in bytes.
|
||||
*/
|
||||
CEB_FDECL4(struct ceb_node *, CEB_MKEY_PFX, _pick, struct ceb_root **, root, ptrdiff_t, kofs, const void *, key, size_t, len)
|
||||
{
|
||||
int is_dup;
|
||||
|
||||
return _ceb_delete(root, NULL, kofs, CEB_KEY_TYPE, 0, len, key, &is_dup);
|
||||
}
|
||||
|
||||
/*
|
||||
* Below are the functions that only support unique keys (_cebu_*)
|
||||
*/
|
||||
|
||||
/*****************************************************************************\
|
||||
* The declarations below always cause two functions to be declared, one *
|
||||
* starting with "cebub_*" and one with "cebub_ofs_*" which takes a key *
|
||||
* offset just after the root. The one without kofs just has this argument *
|
||||
* omitted from its declaration and replaced with sizeof(struct ceb_node) in *
|
||||
* the call to the underlying functions. *
|
||||
\*****************************************************************************/
|
||||
|
||||
/* Inserts node <node> into unique tree <tree> based on its key that
|
||||
* immediately follows the node and for <len> bytes. Returns the
|
||||
* inserted node or the one that already contains the same key.
|
||||
*/
|
||||
CEB_FDECL4(struct ceb_node *, CEB_UKEY_PFX, _insert, struct ceb_root **, root, ptrdiff_t, kofs, struct ceb_node *, node, size_t, len)
|
||||
{
|
||||
const void *key = NODEK(node, kofs)->CEB_KEY_MEMBER;
|
||||
|
||||
return _ceb_insert(root, node, kofs, CEB_KEY_TYPE, 0, len, key, NULL);
|
||||
}
|
||||
|
||||
/* return the first node or NULL if not found. */
|
||||
CEB_FDECL3(struct ceb_node *, CEB_UKEY_PFX, _first, struct ceb_root *const *, root, ptrdiff_t, kofs, size_t, len)
|
||||
{
|
||||
return _ceb_first(root, kofs, CEB_KEY_TYPE, len, NULL);
|
||||
}
|
||||
|
||||
/* return the last node or NULL if not found. */
|
||||
CEB_FDECL3(struct ceb_node *, CEB_UKEY_PFX, _last, struct ceb_root *const *, root, ptrdiff_t, kofs, size_t, len)
|
||||
{
|
||||
return _ceb_last(root, kofs, CEB_KEY_TYPE, len, NULL);
|
||||
}
|
||||
|
||||
/* look up the specified key <key> of length <len>, and returns either the node
|
||||
* containing it, or NULL if not found.
|
||||
*/
|
||||
CEB_FDECL4(struct ceb_node *, CEB_UKEY_PFX, _lookup, struct ceb_root *const *, root, ptrdiff_t, kofs, const void *, key, size_t, len)
|
||||
{
|
||||
return _ceb_lookup(root, kofs, CEB_KEY_TYPE, 0, len, key, NULL);
|
||||
}
|
||||
|
||||
/* look up the specified key or the highest below it, and returns either the
|
||||
* node containing it, or NULL if not found.
|
||||
*/
|
||||
CEB_FDECL4(struct ceb_node *, CEB_UKEY_PFX, _lookup_le, struct ceb_root *const *, root, ptrdiff_t, kofs, const void *, key, size_t, len)
|
||||
{
|
||||
return _ceb_lookup_le(root, kofs, CEB_KEY_TYPE, 0, len, key, NULL);
|
||||
}
|
||||
|
||||
/* look up highest key below the specified one, and returns either the
|
||||
* node containing it, or NULL if not found.
|
||||
*/
|
||||
CEB_FDECL4(struct ceb_node *, CEB_UKEY_PFX, _lookup_lt, struct ceb_root *const *, root, ptrdiff_t, kofs, const void *, key, size_t, len)
|
||||
{
|
||||
return _ceb_lookup_lt(root, kofs, CEB_KEY_TYPE, 0, len, key, NULL);
|
||||
}
|
||||
|
||||
/* look up the specified key or the smallest above it, and returns either the
|
||||
* node containing it, or NULL if not found.
|
||||
*/
|
||||
CEB_FDECL4(struct ceb_node *, CEB_UKEY_PFX, _lookup_ge, struct ceb_root *const *, root, ptrdiff_t, kofs, const void *, key, size_t, len)
|
||||
{
|
||||
return _ceb_lookup_ge(root, kofs, CEB_KEY_TYPE, 0, len, key, NULL);
|
||||
}
|
||||
|
||||
/* look up the smallest key above the specified one, and returns either the
|
||||
* node containing it, or NULL if not found.
|
||||
*/
|
||||
CEB_FDECL4(struct ceb_node *, CEB_UKEY_PFX, _lookup_gt, struct ceb_root *const *, root, ptrdiff_t, kofs, const void *, key, size_t, len)
|
||||
{
|
||||
return _ceb_lookup_gt(root, kofs, CEB_KEY_TYPE, 0, len, key, NULL);
|
||||
}
|
||||
|
||||
/* search for the next node after the specified one, and return it, or NULL if
|
||||
* not found. The approach consists in looking up that node, recalling the last
|
||||
* time a left turn was made, and returning the first node along the right
|
||||
* branch at that fork. The <len> field must correspond to the key length in
|
||||
* bytes.
|
||||
*/
|
||||
CEB_FDECL4(struct ceb_node *, CEB_UKEY_PFX, _next, struct ceb_root *const *, root, ptrdiff_t, kofs, struct ceb_node *, node, size_t, len)
|
||||
{
|
||||
const void *key = NODEK(node, kofs)->CEB_KEY_MEMBER;
|
||||
|
||||
return _ceb_next_unique(root, kofs, CEB_KEY_TYPE, 0, len, key, NULL);
|
||||
}
|
||||
|
||||
/* search for the prev node before the specified one, and return it, or NULL if
|
||||
* not found. The approach consists in looking up that node, recalling the last
|
||||
* time a right turn was made, and returning the last node along the left
|
||||
* branch at that fork. The <len> field must correspond to the key length in
|
||||
* bytes.
|
||||
*/
|
||||
CEB_FDECL4(struct ceb_node *, CEB_UKEY_PFX, _prev, struct ceb_root *const *, root, ptrdiff_t, kofs, struct ceb_node *, node, size_t, len)
|
||||
{
|
||||
const void *key = NODEK(node, kofs)->CEB_KEY_MEMBER;
|
||||
|
||||
return _ceb_prev_unique(root, kofs, CEB_KEY_TYPE, 0, len, key, NULL);
|
||||
}
|
||||
|
||||
/* look up the specified node with its key and deletes it if found, and in any
|
||||
* case, returns the node. The <len> field must correspond to the key length in
|
||||
* bytes.
|
||||
*/
|
||||
CEB_FDECL4(struct ceb_node *, CEB_UKEY_PFX, _delete, struct ceb_root **, root, ptrdiff_t, kofs, struct ceb_node *, node, size_t, len)
|
||||
{
|
||||
const void *key = NODEK(node, kofs)->CEB_KEY_MEMBER;
|
||||
|
||||
return _ceb_delete(root, node, kofs, CEB_KEY_TYPE, 0, len, key, NULL);
|
||||
}
|
||||
|
||||
/* look up the specified key, and detaches it and returns it if found, or NULL
|
||||
* if not found. The <len> field must correspond to the key length in bytes.
|
||||
*/
|
||||
CEB_FDECL4(struct ceb_node *, CEB_UKEY_PFX, _pick, struct ceb_root **, root, ptrdiff_t, kofs, const void *, key, size_t, len)
|
||||
{
|
||||
return _ceb_delete(root, NULL, kofs, CEB_KEY_TYPE, 0, len, key, NULL);
|
||||
}
|
466
src/_ceb_int.c
Normal file
466
src/_ceb_int.c
Normal file
@ -0,0 +1,466 @@
|
||||
/*
|
||||
* Compact Elastic Binary Trees - exported functions operating on integer keys
|
||||
*
|
||||
* Copyright (C) 2014-2025 Willy Tarreau - w@1wt.eu
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/* NOTE: this file is only meant to be included from other C files. It will
|
||||
* use the following private macros that must be defined by the caller:
|
||||
* - CEB_KEY_TYPE: uint32_t, uint64_t, unsigned long
|
||||
* - CEB_KEY_MEMBER: member of the struct ceb_node holding the key
|
||||
* - CEB_MKEY_PFX: function name prefix for multi-key
|
||||
* - CEB_UKEY_PFX: function name prefix for unique keys
|
||||
*
|
||||
* The dump functions will only be build if CEB_ENABLE_DUMP is defined.
|
||||
*/
|
||||
#include "cebtree-prv.h"
|
||||
|
||||
/*
|
||||
* Below are the functions that support duplicate keys (_ceb_*)
|
||||
*/
|
||||
|
||||
/*****************************************************************************\
|
||||
* The declarations below always cause two functions to be declared, one *
|
||||
* starting with "cebs_*" and one with "cebs_ofs_*" which takes a key offset *
|
||||
* just after the root. The one without kofs just has this argument omitted *
|
||||
* from its declaration and replaced with sizeof(struct ceb_node) in the *
|
||||
* call to the underlying functions. *
|
||||
\*****************************************************************************/
|
||||
|
||||
/* Inserts node <node> into tree <tree> based on its key that immediately
|
||||
* follows the node. Returns the inserted node or the one that already contains
|
||||
* the same key.
|
||||
*/
|
||||
CEB_FDECL3(struct ceb_node *, CEB_MKEY_PFX, _insert, struct ceb_root **, root, ptrdiff_t, kofs, struct ceb_node *, node)
|
||||
{
|
||||
CEB_KEY_TYPE key = NODEK(node, kofs)->CEB_KEY_MEMBER;
|
||||
int is_dup;
|
||||
|
||||
if (sizeof(CEB_KEY_TYPE) <= 4)
|
||||
return _ceb_insert(root, node, kofs, CEB_KT_U32, key, 0, NULL, &is_dup);
|
||||
else
|
||||
return _ceb_insert(root, node, kofs, CEB_KT_U64, 0, key, NULL, &is_dup);
|
||||
}
|
||||
|
||||
/* return the first node or NULL if not found. */
|
||||
CEB_FDECL2(struct ceb_node *, CEB_MKEY_PFX, _first, struct ceb_root *const *, root, ptrdiff_t, kofs)
|
||||
{
|
||||
int is_dup;
|
||||
|
||||
if (sizeof(CEB_KEY_TYPE) <= 4)
|
||||
return _ceb_first(root, kofs, CEB_KT_U32, 0, &is_dup);
|
||||
else
|
||||
return _ceb_first(root, kofs, CEB_KT_U64, 0, &is_dup);
|
||||
}
|
||||
|
||||
/* return the last node or NULL if not found. */
|
||||
CEB_FDECL2(struct ceb_node *, CEB_MKEY_PFX, _last, struct ceb_root *const *, root, ptrdiff_t, kofs)
|
||||
{
|
||||
int is_dup;
|
||||
|
||||
if (sizeof(CEB_KEY_TYPE) <= 4)
|
||||
return _ceb_last(root, kofs, CEB_KT_U32, 0, &is_dup);
|
||||
else
|
||||
return _ceb_last(root, kofs, CEB_KT_U64, 0, &is_dup);
|
||||
}
|
||||
|
||||
/* look up the specified key, and returns either the node containing it, or
|
||||
* NULL if not found.
|
||||
*/
|
||||
CEB_FDECL3(struct ceb_node *, CEB_MKEY_PFX, _lookup, struct ceb_root *const *, root, ptrdiff_t, kofs, CEB_KEY_TYPE, key)
|
||||
{
|
||||
int is_dup;
|
||||
|
||||
if (sizeof(CEB_KEY_TYPE) <= 4)
|
||||
return _ceb_lookup(root, kofs, CEB_KT_U32, key, 0, NULL, &is_dup);
|
||||
else
|
||||
return _ceb_lookup(root, kofs, CEB_KT_U64, 0, key, NULL, &is_dup);
|
||||
}
|
||||
|
||||
/* look up the specified key or the highest below it, and returns either the
|
||||
* node containing it, or NULL if not found.
|
||||
*/
|
||||
CEB_FDECL3(struct ceb_node *, CEB_MKEY_PFX, _lookup_le, struct ceb_root *const *, root, ptrdiff_t, kofs, CEB_KEY_TYPE, key)
|
||||
{
|
||||
int is_dup;
|
||||
|
||||
if (sizeof(CEB_KEY_TYPE) <= 4)
|
||||
return _ceb_lookup_le(root, kofs, CEB_KT_U32, key, 0, NULL, &is_dup);
|
||||
else
|
||||
return _ceb_lookup_le(root, kofs, CEB_KT_U64, 0, key, NULL, &is_dup);
|
||||
}
|
||||
|
||||
/* look up highest key below the specified one, and returns either the
|
||||
* node containing it, or NULL if not found.
|
||||
*/
|
||||
CEB_FDECL3(struct ceb_node *, CEB_MKEY_PFX, _lookup_lt, struct ceb_root *const *, root, ptrdiff_t, kofs, CEB_KEY_TYPE, key)
|
||||
{
|
||||
int is_dup;
|
||||
|
||||
if (sizeof(CEB_KEY_TYPE) <= 4)
|
||||
return _ceb_lookup_lt(root, kofs, CEB_KT_U32, key, 0, NULL, &is_dup);
|
||||
else
|
||||
return _ceb_lookup_lt(root, kofs, CEB_KT_U64, 0, key, NULL, &is_dup);
|
||||
}
|
||||
|
||||
/* look up the specified key or the smallest above it, and returns either the
|
||||
* node containing it, or NULL if not found.
|
||||
*/
|
||||
CEB_FDECL3(struct ceb_node *, CEB_MKEY_PFX, _lookup_ge, struct ceb_root *const *, root, ptrdiff_t, kofs, CEB_KEY_TYPE, key)
|
||||
{
|
||||
int is_dup;
|
||||
|
||||
if (sizeof(CEB_KEY_TYPE) <= 4)
|
||||
return _ceb_lookup_ge(root, kofs, CEB_KT_U32, key, 0, NULL, &is_dup);
|
||||
else
|
||||
return _ceb_lookup_ge(root, kofs, CEB_KT_U64, 0, key, NULL, &is_dup);
|
||||
}
|
||||
|
||||
/* look up the smallest key above the specified one, and returns either the
|
||||
* node containing it, or NULL if not found.
|
||||
*/
|
||||
CEB_FDECL3(struct ceb_node *, CEB_MKEY_PFX, _lookup_gt, struct ceb_root *const *, root, ptrdiff_t, kofs, CEB_KEY_TYPE, key)
|
||||
{
|
||||
int is_dup;
|
||||
|
||||
if (sizeof(CEB_KEY_TYPE) <= 4)
|
||||
return _ceb_lookup_gt(root, kofs, CEB_KT_U32, key, 0, NULL, &is_dup);
|
||||
else
|
||||
return _ceb_lookup_gt(root, kofs, CEB_KT_U64, 0, key, NULL, &is_dup);
|
||||
}
|
||||
|
||||
/* search for the next node after the specified one, and return it, or NULL if
|
||||
* not found. The approach consists in looking up that node, recalling the last
|
||||
* time a left turn was made, and returning the first node along the right
|
||||
* branch at that fork.
|
||||
*/
|
||||
CEB_FDECL3(struct ceb_node *, CEB_MKEY_PFX, _next_unique, struct ceb_root *const *, root, ptrdiff_t, kofs, struct ceb_node *, node)
|
||||
{
|
||||
CEB_KEY_TYPE key = NODEK(node, kofs)->CEB_KEY_MEMBER;
|
||||
int is_dup;
|
||||
|
||||
if (sizeof(CEB_KEY_TYPE) <= 4)
|
||||
return _ceb_next_unique(root, kofs, CEB_KT_U32, key, 0, NULL, &is_dup);
|
||||
else
|
||||
return _ceb_next_unique(root, kofs, CEB_KT_U64, 0, key, NULL, &is_dup);
|
||||
}
|
||||
|
||||
/* search for the prev node before the specified one, and return it, or NULL if
|
||||
* not found. The approach consists in looking up that node, recalling the last
|
||||
* time a right turn was made, and returning the last node along the left
|
||||
* branch at that fork.
|
||||
*/
|
||||
CEB_FDECL3(struct ceb_node *, CEB_MKEY_PFX, _prev_unique, struct ceb_root *const *, root, ptrdiff_t, kofs, struct ceb_node *, node)
|
||||
{
|
||||
CEB_KEY_TYPE key = NODEK(node, kofs)->CEB_KEY_MEMBER;
|
||||
int is_dup;
|
||||
|
||||
if (sizeof(CEB_KEY_TYPE) <= 4)
|
||||
return _ceb_prev_unique(root, kofs, CEB_KT_U32, key, 0, NULL, &is_dup);
|
||||
else
|
||||
return _ceb_prev_unique(root, kofs, CEB_KT_U64, 0, key, NULL, &is_dup);
|
||||
}
|
||||
|
||||
/* search for the next node after the specified one containing the same value,
|
||||
* and return it, or NULL if not found.
|
||||
*/
|
||||
CEB_FDECL3(struct ceb_node *, CEB_MKEY_PFX, _next_dup, struct ceb_root *const *, root, ptrdiff_t, kofs, struct ceb_node *, node)
|
||||
{
|
||||
CEB_KEY_TYPE key = NODEK(node, kofs)->CEB_KEY_MEMBER;
|
||||
|
||||
if (sizeof(CEB_KEY_TYPE) <= 4)
|
||||
return _ceb_next_dup(root, kofs, CEB_KT_U32, key, 0, NULL, node);
|
||||
else
|
||||
return _ceb_next_dup(root, kofs, CEB_KT_U64, 0, key, NULL, node);
|
||||
}
|
||||
|
||||
/* search for the prev node before the specified one containing the same value,
|
||||
* and return it, or NULL if not found.
|
||||
*/
|
||||
CEB_FDECL3(struct ceb_node *, CEB_MKEY_PFX, _prev_dup, struct ceb_root *const *, root, ptrdiff_t, kofs, struct ceb_node *, node)
|
||||
{
|
||||
CEB_KEY_TYPE key = NODEK(node, kofs)->CEB_KEY_MEMBER;
|
||||
|
||||
if (sizeof(CEB_KEY_TYPE) <= 4)
|
||||
return _ceb_prev_dup(root, kofs, CEB_KT_U32, key, 0, NULL, node);
|
||||
else
|
||||
return _ceb_prev_dup(root, kofs, CEB_KT_U64, 0, key, NULL, node);
|
||||
}
|
||||
|
||||
/* search for the next node after the specified one, and return it, or NULL if
|
||||
* not found. The approach consists in looking up that node, recalling the last
|
||||
* time a left turn was made, and returning the first node along the right
|
||||
* branch at that fork.
|
||||
*/
|
||||
CEB_FDECL3(struct ceb_node *, CEB_MKEY_PFX, _next, struct ceb_root *const *, root, ptrdiff_t, kofs, struct ceb_node *, node)
|
||||
{
|
||||
CEB_KEY_TYPE key = NODEK(node, kofs)->CEB_KEY_MEMBER;
|
||||
int is_dup;
|
||||
|
||||
if (sizeof(CEB_KEY_TYPE) <= 4)
|
||||
return _ceb_next(root, kofs, CEB_KT_U32, key, 0, NULL, node, &is_dup);
|
||||
else
|
||||
return _ceb_next(root, kofs, CEB_KT_U64, 0, key, NULL, node, &is_dup);
|
||||
}
|
||||
|
||||
/* search for the prev node before the specified one, and return it, or NULL if
|
||||
* not found. The approach consists in looking up that node, recalling the last
|
||||
* time a right turn was made, and returning the last node along the left
|
||||
* branch at that fork.
|
||||
*/
|
||||
CEB_FDECL3(struct ceb_node *, CEB_MKEY_PFX, _prev, struct ceb_root *const *, root, ptrdiff_t, kofs, struct ceb_node *, node)
|
||||
{
|
||||
CEB_KEY_TYPE key = NODEK(node, kofs)->CEB_KEY_MEMBER;
|
||||
int is_dup;
|
||||
|
||||
if (sizeof(CEB_KEY_TYPE) <= 4)
|
||||
return _ceb_prev(root, kofs, CEB_KT_U32, key, 0, NULL, node, &is_dup);
|
||||
else
|
||||
return _ceb_prev(root, kofs, CEB_KT_U64, 0, key, NULL, node, &is_dup);
|
||||
}
|
||||
|
||||
/* look up the specified node with its key and deletes it if found, and in any
|
||||
* case, returns the node.
|
||||
*/
|
||||
CEB_FDECL3(struct ceb_node *, CEB_MKEY_PFX, _delete, struct ceb_root **, root, ptrdiff_t, kofs, struct ceb_node *, node)
|
||||
{
|
||||
CEB_KEY_TYPE key = NODEK(node, kofs)->CEB_KEY_MEMBER;
|
||||
int is_dup;
|
||||
|
||||
if (sizeof(CEB_KEY_TYPE) <= 4)
|
||||
return _ceb_delete(root, node, kofs, CEB_KT_U32, key, 0, NULL, &is_dup);
|
||||
else
|
||||
return _ceb_delete(root, node, kofs, CEB_KT_U64, 0, key, NULL, &is_dup);
|
||||
}
|
||||
|
||||
/* look up the specified key, and detaches it and returns it if found, or NULL
|
||||
* if not found.
|
||||
*/
|
||||
CEB_FDECL3(struct ceb_node *, CEB_MKEY_PFX, _pick, struct ceb_root **, root, ptrdiff_t, kofs, CEB_KEY_TYPE, key)
|
||||
{
|
||||
int is_dup;
|
||||
|
||||
if (sizeof(CEB_KEY_TYPE) <= 4)
|
||||
return _ceb_delete(root, NULL, kofs, CEB_KT_U32, key, 0, NULL, &is_dup);
|
||||
else
|
||||
return _ceb_delete(root, NULL, kofs, CEB_KT_U64, 0, key, NULL, &is_dup);
|
||||
}
|
||||
|
||||
/*
|
||||
* Below are the functions that only support unique keys (_cebu_*)
|
||||
*/
|
||||
|
||||
/*****************************************************************************\
|
||||
* The declarations below always cause two functions to be declared, one *
|
||||
* starting with "cebu32_*" and one with "cebu32_ofs_*" which takes a key *
|
||||
* offset just after the root. The one without kofs just has this argument *
|
||||
* omitted from its declaration and replaced with sizeof(struct ceb_node) in *
|
||||
* the call to the underlying functions. *
|
||||
\*****************************************************************************/
|
||||
|
||||
/* Inserts node <node> into unique tree <tree> based on its key that
|
||||
* immediately follows the node. Returns the inserted node or the one
|
||||
* that already contains the same key.
|
||||
*/
|
||||
CEB_FDECL3(struct ceb_node *, CEB_UKEY_PFX, _insert, struct ceb_root **, root, ptrdiff_t, kofs, struct ceb_node *, node)
|
||||
{
|
||||
CEB_KEY_TYPE key = NODEK(node, kofs)->CEB_KEY_MEMBER;
|
||||
|
||||
if (sizeof(CEB_KEY_TYPE) <= 4)
|
||||
return _ceb_insert(root, node, kofs, CEB_KT_U32, key, 0, NULL, NULL);
|
||||
else
|
||||
return _ceb_insert(root, node, kofs, CEB_KT_U64, 0, key, NULL, NULL);
|
||||
}
|
||||
|
||||
/* return the first node or NULL if not found. */
|
||||
CEB_FDECL2(struct ceb_node *, CEB_UKEY_PFX, _first, struct ceb_root *const *, root, ptrdiff_t, kofs)
|
||||
{
|
||||
if (sizeof(CEB_KEY_TYPE) <= 4)
|
||||
return _ceb_first(root, kofs, CEB_KT_U32, 0, NULL);
|
||||
else
|
||||
return _ceb_first(root, kofs, CEB_KT_U64, 0, NULL);
|
||||
}
|
||||
|
||||
/* return the last node or NULL if not found. */
|
||||
CEB_FDECL2(struct ceb_node *, CEB_UKEY_PFX, _last, struct ceb_root *const *, root, ptrdiff_t, kofs)
|
||||
{
|
||||
if (sizeof(CEB_KEY_TYPE) <= 4)
|
||||
return _ceb_last(root, kofs, CEB_KT_U32, 0, NULL);
|
||||
else
|
||||
return _ceb_last(root, kofs, CEB_KT_U64, 0, NULL);
|
||||
}
|
||||
|
||||
/* look up the specified key, and returns either the node containing it, or
|
||||
* NULL if not found.
|
||||
*/
|
||||
CEB_FDECL3(struct ceb_node *, CEB_UKEY_PFX, _lookup, struct ceb_root *const *, root, ptrdiff_t, kofs, CEB_KEY_TYPE, key)
|
||||
{
|
||||
if (sizeof(CEB_KEY_TYPE) <= 4)
|
||||
return _ceb_lookup(root, kofs, CEB_KT_U32, key, 0, NULL, NULL);
|
||||
else
|
||||
return _ceb_lookup(root, kofs, CEB_KT_U64, 0, key, NULL, NULL);
|
||||
}
|
||||
|
||||
/* look up the specified key or the highest below it, and returns either the
|
||||
* node containing it, or NULL if not found.
|
||||
*/
|
||||
CEB_FDECL3(struct ceb_node *, CEB_UKEY_PFX, _lookup_le, struct ceb_root *const *, root, ptrdiff_t, kofs, CEB_KEY_TYPE, key)
|
||||
{
|
||||
if (sizeof(CEB_KEY_TYPE) <= 4)
|
||||
return _ceb_lookup_le(root, kofs, CEB_KT_U32, key, 0, NULL, NULL);
|
||||
else
|
||||
return _ceb_lookup_le(root, kofs, CEB_KT_U64, 0, key, NULL, NULL);
|
||||
}
|
||||
|
||||
/* look up highest key below the specified one, and returns either the
|
||||
* node containing it, or NULL if not found.
|
||||
*/
|
||||
CEB_FDECL3(struct ceb_node *, CEB_UKEY_PFX, _lookup_lt, struct ceb_root *const *, root, ptrdiff_t, kofs, CEB_KEY_TYPE, key)
|
||||
{
|
||||
if (sizeof(CEB_KEY_TYPE) <= 4)
|
||||
return _ceb_lookup_lt(root, kofs, CEB_KT_U32, key, 0, NULL, NULL);
|
||||
else
|
||||
return _ceb_lookup_lt(root, kofs, CEB_KT_U64, 0, key, NULL, NULL);
|
||||
}
|
||||
|
||||
/* look up the specified key or the smallest above it, and returns either the
|
||||
* node containing it, or NULL if not found.
|
||||
*/
|
||||
CEB_FDECL3(struct ceb_node *, CEB_UKEY_PFX, _lookup_ge, struct ceb_root *const *, root, ptrdiff_t, kofs, CEB_KEY_TYPE, key)
|
||||
{
|
||||
if (sizeof(CEB_KEY_TYPE) <= 4)
|
||||
return _ceb_lookup_ge(root, kofs, CEB_KT_U32, key, 0, NULL, NULL);
|
||||
else
|
||||
return _ceb_lookup_ge(root, kofs, CEB_KT_U64, 0, key, NULL, NULL);
|
||||
}
|
||||
|
||||
/* look up the smallest key above the specified one, and returns either the
|
||||
* node containing it, or NULL if not found.
|
||||
*/
|
||||
CEB_FDECL3(struct ceb_node *, CEB_UKEY_PFX, _lookup_gt, struct ceb_root *const *, root, ptrdiff_t, kofs, CEB_KEY_TYPE, key)
|
||||
{
|
||||
if (sizeof(CEB_KEY_TYPE) <= 4)
|
||||
return _ceb_lookup_gt(root, kofs, CEB_KT_U32, key, 0, NULL, NULL);
|
||||
else
|
||||
return _ceb_lookup_gt(root, kofs, CEB_KT_U64, 0, key, NULL, NULL);
|
||||
}
|
||||
|
||||
/* search for the next node after the specified one, and return it, or NULL if
|
||||
* not found. The approach consists in looking up that node, recalling the last
|
||||
* time a left turn was made, and returning the first node along the right
|
||||
* branch at that fork.
|
||||
*/
|
||||
CEB_FDECL3(struct ceb_node *, CEB_UKEY_PFX, _next, struct ceb_root *const *, root, ptrdiff_t, kofs, struct ceb_node *, node)
|
||||
{
|
||||
CEB_KEY_TYPE key = NODEK(node, kofs)->CEB_KEY_MEMBER;
|
||||
|
||||
if (sizeof(CEB_KEY_TYPE) <= 4)
|
||||
return _ceb_next_unique(root, kofs, CEB_KT_U32, key, 0, NULL, NULL);
|
||||
else
|
||||
return _ceb_next_unique(root, kofs, CEB_KT_U64, 0, key, NULL, NULL);
|
||||
}
|
||||
|
||||
/* search for the prev node before the specified one, and return it, or NULL if
|
||||
* not found. The approach consists in looking up that node, recalling the last
|
||||
* time a right turn was made, and returning the last node along the left
|
||||
* branch at that fork.
|
||||
*/
|
||||
CEB_FDECL3(struct ceb_node *, CEB_UKEY_PFX, _prev, struct ceb_root *const *, root, ptrdiff_t, kofs, struct ceb_node *, node)
|
||||
{
|
||||
CEB_KEY_TYPE key = NODEK(node, kofs)->CEB_KEY_MEMBER;
|
||||
|
||||
if (sizeof(CEB_KEY_TYPE) <= 4)
|
||||
return _ceb_prev_unique(root, kofs, CEB_KT_U32, key, 0, NULL, NULL);
|
||||
else
|
||||
return _ceb_prev_unique(root, kofs, CEB_KT_U64, 0, key, NULL, NULL);
|
||||
}
|
||||
|
||||
/* look up the specified node with its key and deletes it if found, and in any
|
||||
* case, returns the node.
|
||||
*/
|
||||
CEB_FDECL3(struct ceb_node *, CEB_UKEY_PFX, _delete, struct ceb_root **, root, ptrdiff_t, kofs, struct ceb_node *, node)
|
||||
{
|
||||
CEB_KEY_TYPE key = NODEK(node, kofs)->CEB_KEY_MEMBER;
|
||||
|
||||
if (sizeof(CEB_KEY_TYPE) <= 4)
|
||||
return _ceb_delete(root, node, kofs, CEB_KT_U32, key, 0, NULL, NULL);
|
||||
else
|
||||
return _ceb_delete(root, node, kofs, CEB_KT_U64, 0, key, NULL, NULL);
|
||||
}
|
||||
|
||||
/* look up the specified key, and detaches it and returns it if found, or NULL
|
||||
* if not found.
|
||||
*/
|
||||
CEB_FDECL3(struct ceb_node *, CEB_UKEY_PFX, _pick, struct ceb_root **, root, ptrdiff_t, kofs, CEB_KEY_TYPE, key)
|
||||
{
|
||||
if (sizeof(CEB_KEY_TYPE) <= 4)
|
||||
return _ceb_delete(root, NULL, kofs, CEB_KT_U32, key, 0, NULL, NULL);
|
||||
else
|
||||
return _ceb_delete(root, NULL, kofs, CEB_KT_U64, 0, key, NULL, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Functions used to dump trees in Dot format. These are only enabled if
|
||||
* CEB_ENABLE_DUMP is defined.
|
||||
*/
|
||||
|
||||
#if defined(CEB_ENABLE_DUMP)
|
||||
|
||||
#include <stdio.h>
|
||||
#define TO_STR(x) _TO_STR(x)
|
||||
#define _TO_STR(x) #x
|
||||
|
||||
/* dumps a ceb_node tree using the default functions above. If a node matches
|
||||
* <ctx>, this one will be highlighted in red. If the <sub> value is non-null,
|
||||
* only a subgraph will be printed. If it's null, and root is non-null, then
|
||||
* the tree is dumped at once, otherwise if root is NULL, then a prologue is
|
||||
* dumped when label is not NULL, or the epilogue when label is NULL. As a
|
||||
* summary:
|
||||
* sub root label
|
||||
* 0 NULL NULL epilogue only (closing brace and LF)
|
||||
* 0 NULL text prologue with <text> as label
|
||||
* 0 tree * prologue+tree+epilogue at once
|
||||
* N>0 tree * only the tree, after a prologue and before an epilogue
|
||||
*/
|
||||
CEB_FDECL5(void, CEB_MKEY_PFX, _default_dump, struct ceb_root *const *, root, ptrdiff_t, kofs, const char *, label, const void *, ctx, int, sub)
|
||||
{
|
||||
if (!sub && label) {
|
||||
printf("\ndigraph " TO_STR(CEB_MKEY_PFX) "_tree {\n"
|
||||
" fontname=\"fixed\";\n"
|
||||
" fontsize=8\n"
|
||||
" label=\"%s\"\n"
|
||||
"", label);
|
||||
|
||||
printf(" node [fontname=\"fixed\" fontsize=8 shape=\"box\" style=\"filled\" color=\"black\" fillcolor=\"white\"];\n"
|
||||
" edge [fontname=\"fixed\" fontsize=8 style=\"solid\" color=\"magenta\" dir=\"forward\"];\n");
|
||||
} else
|
||||
printf("\n### sub %d ###\n\n", sub);
|
||||
|
||||
if (root)
|
||||
ceb_imm_default_dump_tree(kofs, sizeof(CEB_KEY_TYPE) <= 4 ? CEB_KT_U32 : CEB_KT_U64, root, 0, NULL, 0, ctx, sub, NULL, NULL, NULL, NULL);
|
||||
|
||||
if (!sub && (root || !label))
|
||||
printf("}\n");
|
||||
}
|
||||
|
||||
#endif /* CEB_ENABLE_DUMP */
|
386
src/_ceb_str.c
Normal file
386
src/_ceb_str.c
Normal file
@ -0,0 +1,386 @@
|
||||
/*
|
||||
* Compact Elastic Binary Trees - exported functions operating on string keys
|
||||
*
|
||||
* Copyright (C) 2014-2025 Willy Tarreau - w@1wt.eu
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/* NOTE: this file is only meant to be included from other C files. It will
|
||||
* use the following private macros that must be defined by the caller:
|
||||
* - CEB_KEY_TYPE: CEB_KT_ST, CEB_KT_IS
|
||||
* - CEB_KEY_MEMBER: str, ptr
|
||||
* - CEB_MKEY_PFX: function name prefix for multi-key (cebs, cebis)
|
||||
* - CEB_UKEY_PFX: function name prefix for unique keys (cebus, cebuis)
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "cebtree-prv.h"
|
||||
|
||||
#define TO_STR(x) _TO_STR(x)
|
||||
#define _TO_STR(x) #x
|
||||
|
||||
/*
|
||||
* Below are the functions that support duplicate keys (_ceb_*)
|
||||
*/
|
||||
|
||||
/*****************************************************************************\
|
||||
* The declarations below always cause two functions to be declared, one *
|
||||
* starting with "cebs_*" and one with "cebs_ofs_*" which takes a key offset *
|
||||
* just after the root. The one without kofs just has this argument omitted *
|
||||
* from its declaration and replaced with sizeof(struct ceb_node) in the *
|
||||
* call to the underlying functions. *
|
||||
\*****************************************************************************/
|
||||
|
||||
/* Inserts node <node> into tree <tree> based on its key that immediately
|
||||
* follows the node. Returns the inserted node or the one that already contains
|
||||
* the same key.
|
||||
*/
|
||||
CEB_FDECL3(struct ceb_node *, CEB_MKEY_PFX, _insert, struct ceb_root **, root, ptrdiff_t, kofs, struct ceb_node *, node)
|
||||
{
|
||||
const void *key = NODEK(node, kofs)->CEB_KEY_MEMBER;
|
||||
int is_dup;
|
||||
|
||||
return _ceb_insert(root, node, kofs, CEB_KEY_TYPE, 0, 0, key, &is_dup);
|
||||
}
|
||||
|
||||
/* return the first node or NULL if not found. */
|
||||
CEB_FDECL2(struct ceb_node *, CEB_MKEY_PFX, _first, struct ceb_root *const *, root, ptrdiff_t, kofs)
|
||||
{
|
||||
int is_dup;
|
||||
|
||||
return _ceb_first(root, kofs, CEB_KEY_TYPE, 0, &is_dup);
|
||||
}
|
||||
|
||||
/* return the last node or NULL if not found. */
|
||||
CEB_FDECL2(struct ceb_node *, CEB_MKEY_PFX, _last, struct ceb_root *const *, root, ptrdiff_t, kofs)
|
||||
{
|
||||
int is_dup;
|
||||
|
||||
return _ceb_last(root, kofs, CEB_KEY_TYPE, 0, &is_dup);
|
||||
}
|
||||
|
||||
/* look up the specified key, and returns either the node containing it, or
|
||||
* NULL if not found.
|
||||
*/
|
||||
CEB_FDECL3(struct ceb_node *, CEB_MKEY_PFX, _lookup, struct ceb_root *const *, root, ptrdiff_t, kofs, const void *, key)
|
||||
{
|
||||
int is_dup;
|
||||
|
||||
return _ceb_lookup(root, kofs, CEB_KEY_TYPE, 0, 0, key, &is_dup);
|
||||
}
|
||||
|
||||
/* look up the specified key or the highest below it, and returns either the
|
||||
* node containing it, or NULL if not found.
|
||||
*/
|
||||
CEB_FDECL3(struct ceb_node *, CEB_MKEY_PFX, _lookup_le, struct ceb_root *const *, root, ptrdiff_t, kofs, const void *, key)
|
||||
{
|
||||
int is_dup;
|
||||
|
||||
return _ceb_lookup_le(root, kofs, CEB_KEY_TYPE, 0, 0, key, &is_dup);
|
||||
}
|
||||
|
||||
/* look up highest key below the specified one, and returns either the
|
||||
* node containing it, or NULL if not found.
|
||||
*/
|
||||
CEB_FDECL3(struct ceb_node *, CEB_MKEY_PFX, _lookup_lt, struct ceb_root *const *, root, ptrdiff_t, kofs, const void *, key)
|
||||
{
|
||||
int is_dup;
|
||||
|
||||
return _ceb_lookup_lt(root, kofs, CEB_KEY_TYPE, 0, 0, key, &is_dup);
|
||||
}
|
||||
|
||||
/* look up the specified key or the smallest above it, and returns either the
|
||||
* node containing it, or NULL if not found.
|
||||
*/
|
||||
CEB_FDECL3(struct ceb_node *, CEB_MKEY_PFX, _lookup_ge, struct ceb_root *const *, root, ptrdiff_t, kofs, const void *, key)
|
||||
{
|
||||
int is_dup;
|
||||
|
||||
return _ceb_lookup_ge(root, kofs, CEB_KEY_TYPE, 0, 0, key, &is_dup);
|
||||
}
|
||||
|
||||
/* look up the smallest key above the specified one, and returns either the
|
||||
* node containing it, or NULL if not found.
|
||||
*/
|
||||
CEB_FDECL3(struct ceb_node *, CEB_MKEY_PFX, _lookup_gt, struct ceb_root *const *, root, ptrdiff_t, kofs, const void *, key)
|
||||
{
|
||||
int is_dup;
|
||||
|
||||
return _ceb_lookup_gt(root, kofs, CEB_KEY_TYPE, 0, 0, key, &is_dup);
|
||||
}
|
||||
|
||||
/* search for the next node after the specified one, and return it, or NULL if
|
||||
* not found. The approach consists in looking up that node, recalling the last
|
||||
* time a left turn was made, and returning the first node along the right
|
||||
* branch at that fork.
|
||||
*/
|
||||
CEB_FDECL3(struct ceb_node *, CEB_MKEY_PFX, _next_unique, struct ceb_root *const *, root, ptrdiff_t, kofs, struct ceb_node *, node)
|
||||
{
|
||||
const void *key = NODEK(node, kofs)->CEB_KEY_MEMBER;
|
||||
int is_dup;
|
||||
|
||||
return _ceb_next_unique(root, kofs, CEB_KEY_TYPE, 0, 0, key, &is_dup);
|
||||
}
|
||||
|
||||
/* search for the prev node before the specified one, and return it, or NULL if
|
||||
* not found. The approach consists in looking up that node, recalling the last
|
||||
* time a right turn was made, and returning the last node along the left
|
||||
* branch at that fork.
|
||||
*/
|
||||
CEB_FDECL3(struct ceb_node *, CEB_MKEY_PFX, _prev_unique, struct ceb_root *const *, root, ptrdiff_t, kofs, struct ceb_node *, node)
|
||||
{
|
||||
const void *key = NODEK(node, kofs)->CEB_KEY_MEMBER;
|
||||
int is_dup;
|
||||
|
||||
return _ceb_prev_unique(root, kofs, CEB_KEY_TYPE, 0, 0, key, &is_dup);
|
||||
}
|
||||
|
||||
/* search for the next node after the specified one containing the same value,
|
||||
* and return it, or NULL if not found.
|
||||
*/
|
||||
CEB_FDECL3(struct ceb_node *, CEB_MKEY_PFX, _next_dup, struct ceb_root *const *, root, ptrdiff_t, kofs, struct ceb_node *, node)
|
||||
{
|
||||
const void *key = NODEK(node, kofs)->CEB_KEY_MEMBER;
|
||||
|
||||
return _ceb_next_dup(root, kofs, CEB_KEY_TYPE, 0, 0, key, node);
|
||||
}
|
||||
|
||||
/* search for the prev node before the specified one containing the same value,
|
||||
* and return it, or NULL if not found.
|
||||
*/
|
||||
CEB_FDECL3(struct ceb_node *, CEB_MKEY_PFX, _prev_dup, struct ceb_root *const *, root, ptrdiff_t, kofs, struct ceb_node *, node)
|
||||
{
|
||||
const void *key = NODEK(node, kofs)->CEB_KEY_MEMBER;
|
||||
|
||||
return _ceb_prev_dup(root, kofs, CEB_KEY_TYPE, 0, 0, key, node);
|
||||
}
|
||||
|
||||
/* search for the next node after the specified one, and return it, or NULL if
|
||||
* not found. The approach consists in looking up that node, recalling the last
|
||||
* time a left turn was made, and returning the first node along the right
|
||||
* branch at that fork.
|
||||
*/
|
||||
CEB_FDECL3(struct ceb_node *, CEB_MKEY_PFX, _next, struct ceb_root *const *, root, ptrdiff_t, kofs, struct ceb_node *, node)
|
||||
{
|
||||
const void *key = NODEK(node, kofs)->CEB_KEY_MEMBER;
|
||||
int is_dup;
|
||||
|
||||
return _ceb_next(root, kofs, CEB_KEY_TYPE, 0, 0, key, node, &is_dup);
|
||||
}
|
||||
|
||||
/* search for the prev node before the specified one, and return it, or NULL if
|
||||
* not found. The approach consists in looking up that node, recalling the last
|
||||
* time a right turn was made, and returning the last node along the left
|
||||
* branch at that fork.
|
||||
*/
|
||||
CEB_FDECL3(struct ceb_node *, CEB_MKEY_PFX, _prev, struct ceb_root *const *, root, ptrdiff_t, kofs, struct ceb_node *, node)
|
||||
{
|
||||
const void *key = NODEK(node, kofs)->CEB_KEY_MEMBER;
|
||||
int is_dup;
|
||||
|
||||
return _ceb_prev(root, kofs, CEB_KEY_TYPE, 0, 0, key, node, &is_dup);
|
||||
}
|
||||
|
||||
/* look up the specified node with its key and deletes it if found, and in any
|
||||
* case, returns the node.
|
||||
*/
|
||||
CEB_FDECL3(struct ceb_node *, CEB_MKEY_PFX, _delete, struct ceb_root **, root, ptrdiff_t, kofs, struct ceb_node *, node)
|
||||
{
|
||||
const void *key = NODEK(node, kofs)->CEB_KEY_MEMBER;
|
||||
int is_dup;
|
||||
|
||||
return _ceb_delete(root, node, kofs, CEB_KEY_TYPE, 0, 0, key, &is_dup);
|
||||
}
|
||||
|
||||
/* look up the specified key, and detaches it and returns it if found, or NULL
|
||||
* if not found.
|
||||
*/
|
||||
CEB_FDECL3(struct ceb_node *, CEB_MKEY_PFX, _pick, struct ceb_root **, root, ptrdiff_t, kofs, const void *, key)
|
||||
{
|
||||
int is_dup;
|
||||
|
||||
return _ceb_delete(root, NULL, kofs, CEB_KEY_TYPE, 0, 0, key, &is_dup);
|
||||
}
|
||||
|
||||
/*
|
||||
* Below are the functions that only support unique keys (_cebu_*)
|
||||
*/
|
||||
|
||||
/*****************************************************************************\
|
||||
* The declarations below always cause two functions to be declared, one *
|
||||
* starting with "cebus_*" and one with "cebus_ofs_*" which takes a key *
|
||||
* offset just after the root. The one without kofs just has this argument *
|
||||
* omitted from its declaration and replaced with sizeof(struct ceb_node) in *
|
||||
* the call to the underlying functions. *
|
||||
\*****************************************************************************/
|
||||
|
||||
/* Inserts node <node> into unique tree <tree> based on its key that
|
||||
* immediately follows the node. Returns the inserted node or the one
|
||||
* that already contains the same key.
|
||||
*/
|
||||
CEB_FDECL3(struct ceb_node *, CEB_UKEY_PFX, _insert, struct ceb_root **, root, ptrdiff_t, kofs, struct ceb_node *, node)
|
||||
{
|
||||
const void *key = NODEK(node, kofs)->CEB_KEY_MEMBER;
|
||||
|
||||
return _ceb_insert(root, node, kofs, CEB_KEY_TYPE, 0, 0, key, NULL);
|
||||
}
|
||||
|
||||
/* return the first node or NULL if not found. */
|
||||
CEB_FDECL2(struct ceb_node *, CEB_UKEY_PFX, _first, struct ceb_root *const *, root, ptrdiff_t, kofs)
|
||||
{
|
||||
return _ceb_first(root, kofs, CEB_KEY_TYPE, 0, NULL);
|
||||
}
|
||||
|
||||
/* return the last node or NULL if not found. */
|
||||
CEB_FDECL2(struct ceb_node *, CEB_UKEY_PFX, _last, struct ceb_root *const *, root, ptrdiff_t, kofs)
|
||||
{
|
||||
return _ceb_last(root, kofs, CEB_KEY_TYPE, 0, NULL);
|
||||
}
|
||||
|
||||
/* look up the specified key, and returns either the node containing it, or
|
||||
* NULL if not found.
|
||||
*/
|
||||
CEB_FDECL3(struct ceb_node *, CEB_UKEY_PFX, _lookup, struct ceb_root *const *, root, ptrdiff_t, kofs, const void *, key)
|
||||
{
|
||||
return _ceb_lookup(root, kofs, CEB_KEY_TYPE, 0, 0, key, NULL);
|
||||
}
|
||||
|
||||
/* look up the specified key or the highest below it, and returns either the
|
||||
* node containing it, or NULL if not found.
|
||||
*/
|
||||
CEB_FDECL3(struct ceb_node *, CEB_UKEY_PFX, _lookup_le, struct ceb_root *const *, root, ptrdiff_t, kofs, const void *, key)
|
||||
{
|
||||
return _ceb_lookup_le(root, kofs, CEB_KEY_TYPE, 0, 0, key, NULL);
|
||||
}
|
||||
|
||||
/* look up highest key below the specified one, and returns either the
|
||||
* node containing it, or NULL if not found.
|
||||
*/
|
||||
CEB_FDECL3(struct ceb_node *, CEB_UKEY_PFX, _lookup_lt, struct ceb_root *const *, root, ptrdiff_t, kofs, const void *, key)
|
||||
{
|
||||
return _ceb_lookup_lt(root, kofs, CEB_KEY_TYPE, 0, 0, key, NULL);
|
||||
}
|
||||
|
||||
/* look up the specified key or the smallest above it, and returns either the
|
||||
* node containing it, or NULL if not found.
|
||||
*/
|
||||
CEB_FDECL3(struct ceb_node *, CEB_UKEY_PFX, _lookup_ge, struct ceb_root *const *, root, ptrdiff_t, kofs, const void *, key)
|
||||
{
|
||||
return _ceb_lookup_ge(root, kofs, CEB_KEY_TYPE, 0, 0, key, NULL);
|
||||
}
|
||||
|
||||
/* look up the smallest key above the specified one, and returns either the
|
||||
* node containing it, or NULL if not found.
|
||||
*/
|
||||
CEB_FDECL3(struct ceb_node *, CEB_UKEY_PFX, _lookup_gt, struct ceb_root *const *, root, ptrdiff_t, kofs, const void *, key)
|
||||
{
|
||||
return _ceb_lookup_gt(root, kofs, CEB_KEY_TYPE, 0, 0, key, NULL);
|
||||
}
|
||||
|
||||
/* search for the next node after the specified one, and return it, or NULL if
|
||||
* not found. The approach consists in looking up that node, recalling the last
|
||||
* time a left turn was made, and returning the first node along the right
|
||||
* branch at that fork.
|
||||
*/
|
||||
CEB_FDECL3(struct ceb_node *, CEB_UKEY_PFX, _next, struct ceb_root *const *, root, ptrdiff_t, kofs, struct ceb_node *, node)
|
||||
{
|
||||
const void *key = NODEK(node, kofs)->CEB_KEY_MEMBER;
|
||||
|
||||
return _ceb_next_unique(root, kofs, CEB_KEY_TYPE, 0, 0, key, NULL);
|
||||
}
|
||||
|
||||
/* search for the prev node before the specified one, and return it, or NULL if
|
||||
* not found. The approach consists in looking up that node, recalling the last
|
||||
* time a right turn was made, and returning the last node along the left
|
||||
* branch at that fork.
|
||||
*/
|
||||
CEB_FDECL3(struct ceb_node *, CEB_UKEY_PFX, _prev, struct ceb_root *const *, root, ptrdiff_t, kofs, struct ceb_node *, node)
|
||||
{
|
||||
const void *key = NODEK(node, kofs)->CEB_KEY_MEMBER;
|
||||
|
||||
return _ceb_prev_unique(root, kofs, CEB_KEY_TYPE, 0, 0, key, NULL);
|
||||
}
|
||||
|
||||
/* look up the specified node with its key and deletes it if found, and in any
|
||||
* case, returns the node.
|
||||
*/
|
||||
CEB_FDECL3(struct ceb_node *, CEB_UKEY_PFX, _delete, struct ceb_root **, root, ptrdiff_t, kofs, struct ceb_node *, node)
|
||||
{
|
||||
const void *key = NODEK(node, kofs)->CEB_KEY_MEMBER;
|
||||
|
||||
return _ceb_delete(root, node, kofs, CEB_KEY_TYPE, 0, 0, key, NULL);
|
||||
}
|
||||
|
||||
/* look up the specified key, and detaches it and returns it if found, or NULL
|
||||
* if not found.
|
||||
*/
|
||||
CEB_FDECL3(struct ceb_node *, CEB_UKEY_PFX, _pick, struct ceb_root **, root, ptrdiff_t, kofs, const void *, key)
|
||||
{
|
||||
return _ceb_delete(root, NULL, kofs, CEB_KEY_TYPE, 0, 0, key, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Functions used to dump trees in Dot format. These are only enabled if
|
||||
* CEB_ENABLE_DUMP is defined.
|
||||
*/
|
||||
|
||||
#if defined(CEB_ENABLE_DUMP)
|
||||
|
||||
#include <stdio.h>
|
||||
#define TO_STR(x) _TO_STR(x)
|
||||
#define _TO_STR(x) #x
|
||||
|
||||
/* dumps a ceb_node tree using the default functions above. If a node matches
|
||||
* <ctx>, this one will be highlighted in red. If the <sub> value is non-null,
|
||||
* only a subgraph will be printed. If it's null, and root is non-null, then
|
||||
* the tree is dumped at once, otherwise if root is NULL, then a prologue is
|
||||
* dumped when label is not NULL, or the epilogue when label is NULL. As a
|
||||
* summary:
|
||||
* sub root label
|
||||
* 0 NULL NULL epilogue only (closing brace and LF)
|
||||
* 0 NULL text prologue with <text> as label
|
||||
* 0 tree * prologue+tree+epilogue at once
|
||||
* N>0 tree * only the tree, after a prologue and before an epilogue
|
||||
*/
|
||||
CEB_FDECL5(void, CEB_MKEY_PFX, _default_dump, struct ceb_root *const *, root, ptrdiff_t, kofs, const char *, label, const void *, ctx, int, sub)
|
||||
{
|
||||
if (!sub && label) {
|
||||
printf("\ndigraph " TO_STR(CEB_MKEY_PFX) "_tree {\n"
|
||||
" fontname=\"fixed\";\n"
|
||||
" fontsize=8\n"
|
||||
" label=\"%s\"\n"
|
||||
"", label);
|
||||
|
||||
printf(" node [fontname=\"fixed\" fontsize=8 shape=\"box\" style=\"filled\" color=\"black\" fillcolor=\"white\"];\n"
|
||||
" edge [fontname=\"fixed\" fontsize=8 style=\"solid\" color=\"magenta\" dir=\"forward\"];\n");
|
||||
} else
|
||||
printf("\n### sub %d ###\n\n", sub);
|
||||
|
||||
if (root)
|
||||
ceb_imm_default_dump_tree(kofs, CEB_KEY_TYPE, root, 0, NULL, 0, ctx, sub, NULL, NULL, NULL, NULL);
|
||||
|
||||
if (!sub && (root || !label))
|
||||
printf("}\n");
|
||||
}
|
||||
|
||||
#endif /* CEB_ENABLE_DUMP */
|
39
src/ceb32_tree.c
Normal file
39
src/ceb32_tree.c
Normal file
@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Compact Elastic Binary Trees - exported functions operating on u32 keys
|
||||
*
|
||||
* Copyright (C) 2014-2025 Willy Tarreau - w@1wt.eu
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifdef CEBTREE_DEV
|
||||
/* just to verify API compatibility */
|
||||
#include "ceb32_tree.h"
|
||||
#endif
|
||||
|
||||
#define CEB_USE_BASE
|
||||
#define CEB_USE_OFST
|
||||
#define CEB_KEY_TYPE uint32_t
|
||||
#define CEB_KEY_MEMBER u32
|
||||
#define CEB_MKEY_PFX ceb32
|
||||
#define CEB_UKEY_PFX cebu32
|
||||
|
||||
#include "_ceb_int.c"
|
39
src/ceb64_tree.c
Normal file
39
src/ceb64_tree.c
Normal file
@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Compact Elastic Binary Trees - exported functions operating on u64 keys
|
||||
*
|
||||
* Copyright (C) 2014-2025 Willy Tarreau - w@1wt.eu
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifdef CEBTREE_DEV
|
||||
/* just to verify API compatibility */
|
||||
#include "ceb64_tree.h"
|
||||
#endif
|
||||
|
||||
#define CEB_USE_BASE
|
||||
#define CEB_USE_OFST
|
||||
#define CEB_KEY_TYPE uint64_t
|
||||
#define CEB_KEY_MEMBER u64
|
||||
#define CEB_MKEY_PFX ceb64
|
||||
#define CEB_UKEY_PFX cebu64
|
||||
|
||||
#include "_ceb_int.c"
|
37
src/ceba_tree.c
Normal file
37
src/ceba_tree.c
Normal file
@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Compact Elastic Binary Trees - exported functions operating on addr keys
|
||||
*
|
||||
* Copyright (C) 2014-2025 Willy Tarreau - w@1wt.eu
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifdef CEBTREE_DEV
|
||||
/* just to verify API compatibility */
|
||||
#include "ceba_tree.h"
|
||||
#endif
|
||||
|
||||
#define CEB_USE_BASE
|
||||
#define CEB_KEY_TYPE CEB_KT_ADDR
|
||||
#define CEB_MKEY_PFX ceba
|
||||
#define CEB_UKEY_PFX cebua
|
||||
|
||||
#include "_ceb_addr.c"
|
39
src/cebb_tree.c
Normal file
39
src/cebb_tree.c
Normal file
@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Compact Elastic Binary Trees - exported functions operating on mb keys
|
||||
*
|
||||
* Copyright (C) 2014-2025 Willy Tarreau - w@1wt.eu
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifdef CEBTREE_DEV
|
||||
/* just to verify API compatibility */
|
||||
#include "cebb_tree.h"
|
||||
#endif
|
||||
|
||||
#define CEB_USE_BASE
|
||||
#define CEB_USE_OFST
|
||||
#define CEB_KEY_TYPE CEB_KT_MB
|
||||
#define CEB_KEY_MEMBER mb
|
||||
#define CEB_MKEY_PFX cebb
|
||||
#define CEB_UKEY_PFX cebub
|
||||
|
||||
#include "_ceb_blk.c"
|
39
src/cebib_tree.c
Normal file
39
src/cebib_tree.c
Normal file
@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Compact Elastic Binary Trees - exported functions operating on indirect blocks
|
||||
*
|
||||
* Copyright (C) 2014-2025 Willy Tarreau - w@1wt.eu
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifdef CEBTREE_DEV
|
||||
/* just to verify API compatibility */
|
||||
#include "cebib_tree.h"
|
||||
#endif
|
||||
|
||||
#define CEB_USE_BASE
|
||||
#define CEB_USE_OFST
|
||||
#define CEB_KEY_TYPE CEB_KT_IM
|
||||
#define CEB_KEY_MEMBER ptr
|
||||
#define CEB_MKEY_PFX cebib
|
||||
#define CEB_UKEY_PFX cebuib
|
||||
|
||||
#include "_ceb_blk.c"
|
39
src/cebis_tree.c
Normal file
39
src/cebis_tree.c
Normal file
@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Compact Elastic Binary Trees - exported functions operating on indirect strings
|
||||
*
|
||||
* Copyright (C) 2014-2025 Willy Tarreau - w@1wt.eu
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifdef CEBTREE_DEV
|
||||
/* just to verify API compatibility */
|
||||
#include "cebis_tree.h"
|
||||
#endif
|
||||
|
||||
#define CEB_USE_BASE
|
||||
#define CEB_USE_OFST
|
||||
#define CEB_KEY_TYPE CEB_KT_IS
|
||||
#define CEB_KEY_MEMBER ptr
|
||||
#define CEB_MKEY_PFX cebis
|
||||
#define CEB_UKEY_PFX cebuis
|
||||
|
||||
#include "_ceb_str.c"
|
39
src/cebl_tree.c
Normal file
39
src/cebl_tree.c
Normal file
@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Compact Elastic Binary Trees - exported functions operating on ulong keys
|
||||
*
|
||||
* Copyright (C) 2014-2025 Willy Tarreau - w@1wt.eu
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifdef CEBTREE_DEV
|
||||
/* just to verify API compatibility */
|
||||
#include "cebl_tree.h"
|
||||
#endif
|
||||
|
||||
#define CEB_USE_BASE
|
||||
#define CEB_USE_OFST
|
||||
#define CEB_KEY_TYPE unsigned long
|
||||
#define CEB_KEY_MEMBER ul
|
||||
#define CEB_MKEY_PFX cebl
|
||||
#define CEB_UKEY_PFX cebul
|
||||
|
||||
#include "_ceb_int.c"
|
39
src/cebs_tree.c
Normal file
39
src/cebs_tree.c
Normal file
@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Compact Elastic Binary Trees - exported functions operating on string keys
|
||||
*
|
||||
* Copyright (C) 2014-2025 Willy Tarreau - w@1wt.eu
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifdef CEBTREE_DEV
|
||||
/* just to verify API compatibility */
|
||||
#include "cebs_tree.h"
|
||||
#endif
|
||||
|
||||
#define CEB_USE_BASE
|
||||
#define CEB_USE_OFST
|
||||
#define CEB_KEY_TYPE CEB_KT_ST
|
||||
#define CEB_KEY_MEMBER str
|
||||
#define CEB_MKEY_PFX cebs
|
||||
#define CEB_UKEY_PFX cebus
|
||||
|
||||
#include "_ceb_str.c"
|
401
src/cebtree-dbg.c
Normal file
401
src/cebtree-dbg.c
Normal file
@ -0,0 +1,401 @@
|
||||
/*
|
||||
* Compact Elastic Binary Trees - debugging functions
|
||||
*
|
||||
* Copyright (C) 2014-2025 Willy Tarreau - w@1wt.eu
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* Functions used to dump trees in Dot format.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include "cebtree-prv.h"
|
||||
|
||||
#if defined(CEB_ENABLE_DUMP)
|
||||
|
||||
/* Returns the xor (or the complement of the common length for strings) between
|
||||
* the two sides <l> and <r> if both are non-null, otherwise between the first
|
||||
* non-null one and the value in the associate key. As a reminder, memory
|
||||
* blocks place their length in key_u64. This is only intended for internal
|
||||
* use, essentially for debugging. It only returns zero when the keys are
|
||||
* identical, and returns a greater value for keys that are more distant.
|
||||
*
|
||||
* <kofs> contains the offset between the key and the node's base. When simply
|
||||
* adjacent, this would just be sizeof(ceb_node).
|
||||
*/
|
||||
static uint64_t _xor_branches(ptrdiff_t kofs, enum ceb_key_type key_type, uint32_t key_u32,
|
||||
uint64_t key_u64, const void *key_ptr,
|
||||
const struct ceb_root *_l,
|
||||
const struct ceb_root *_r)
|
||||
{
|
||||
const struct ceb_node *l, *r;
|
||||
|
||||
l = _ceb_clrtag(_l);
|
||||
r = _ceb_clrtag(_r);
|
||||
|
||||
if (l && r) {
|
||||
if (key_type == CEB_KT_MB)
|
||||
return (key_u64 << 3) - equal_bits(NODEK(l, kofs)->mb, NODEK(r, kofs)->mb, 0, key_u64 << 3);
|
||||
else if (key_type == CEB_KT_IM)
|
||||
return (key_u64 << 3) - equal_bits(NODEK(l, kofs)->mb, NODEK(r, kofs)->ptr, 0, key_u64 << 3);
|
||||
else if (key_type == CEB_KT_ST)
|
||||
return ~string_equal_bits(NODEK(l, kofs)->str, NODEK(r, kofs)->str, 0);
|
||||
else if (key_type == CEB_KT_IS)
|
||||
return ~string_equal_bits(NODEK(l, kofs)->ptr, NODEK(r, kofs)->ptr, 0);
|
||||
else if (key_type == CEB_KT_U64)
|
||||
return NODEK(l, kofs)->u64 ^ NODEK(r, kofs)->u64;
|
||||
else if (key_type == CEB_KT_U32)
|
||||
return NODEK(l, kofs)->u32 ^ NODEK(r, kofs)->u32;
|
||||
else if (key_type == CEB_KT_ADDR)
|
||||
return ((uintptr_t)l ^ (uintptr_t)r);
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!l)
|
||||
l = r;
|
||||
|
||||
if (key_type == CEB_KT_MB)
|
||||
return (key_u64 << 3) - equal_bits(key_ptr, NODEK(l, kofs)->mb, 0, key_u64 << 3);
|
||||
else if (key_type == CEB_KT_IM)
|
||||
return (key_u64 << 3) - equal_bits(key_ptr, NODEK(l, kofs)->ptr, 0, key_u64 << 3);
|
||||
else if (key_type == CEB_KT_ST)
|
||||
return ~string_equal_bits(key_ptr, NODEK(l, kofs)->str, 0);
|
||||
else if (key_type == CEB_KT_IS)
|
||||
return ~string_equal_bits(key_ptr, NODEK(l, kofs)->ptr, 0);
|
||||
else if (key_type == CEB_KT_U64)
|
||||
return key_u64 ^ NODEK(l, kofs)->u64;
|
||||
else if (key_type == CEB_KT_U32)
|
||||
return key_u32 ^ NODEK(l, kofs)->u32;
|
||||
else if (key_type == CEB_KT_ADDR)
|
||||
return ((uintptr_t)key_ptr ^ (uintptr_t)r);
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* dump the root and its link to the first node or leaf */
|
||||
void ceb_imm_default_dump_root(ptrdiff_t kofs, enum ceb_key_type key_type, struct ceb_root *const *root, const void *ctx, int sub)
|
||||
{
|
||||
const struct ceb_node *node;
|
||||
uint64_t pxor;
|
||||
|
||||
if (!sub)
|
||||
printf(" \"%lx_n_%d\" [label=\"root\\n%lx\"]\n", (long)root, sub, (long)root);
|
||||
else
|
||||
printf(" \"%lx_n_%d\" [label=\"root\\n%lx\\ntree #%d\"]\n", (long)root, sub, (long)root, sub);
|
||||
|
||||
node = _ceb_clrtag(*root);
|
||||
if (node) {
|
||||
/* under the root we've either a node or the first leaf */
|
||||
|
||||
/* xor of the keys of the two lower branches */
|
||||
pxor = _xor_branches(kofs, key_type, 0, 0, NULL,
|
||||
node->b[0], node->b[1]);
|
||||
|
||||
printf(" \"%lx_n_%d\" -> \"%lx_%c_%d\" [label=\"B\" arrowsize=0.66%s];\n",
|
||||
(long)root, sub, (long)node,
|
||||
(node->b[0] == node->b[1] || !pxor) ? 'l' : 'n', sub,
|
||||
(ctx == node) ? " color=red" : "");
|
||||
}
|
||||
}
|
||||
|
||||
/* dump a node */
|
||||
void ceb_imm_default_dump_node(ptrdiff_t kofs, enum ceb_key_type key_type, const struct ceb_node *node, int level, const void *ctx, int sub)
|
||||
{
|
||||
unsigned long long int_key = 0;
|
||||
uint64_t pxor, lxor, rxor;
|
||||
const char *str_key = NULL;
|
||||
|
||||
switch (key_type) {
|
||||
case CEB_KT_ADDR:
|
||||
int_key = (uintptr_t)node;
|
||||
break;
|
||||
case CEB_KT_U32:
|
||||
int_key = NODEK(node, kofs)->u32;
|
||||
break;
|
||||
case CEB_KT_U64:
|
||||
int_key = NODEK(node, kofs)->u64;
|
||||
break;
|
||||
case CEB_KT_ST:
|
||||
str_key = (char*)NODEK(node, kofs)->str;
|
||||
break;
|
||||
case CEB_KT_IS:
|
||||
str_key = (char*)NODEK(node, kofs)->ptr;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/* xor of the keys of the two lower branches */
|
||||
pxor = _xor_branches(kofs, key_type, 0, 0, NULL,
|
||||
node->b[0], node->b[1]);
|
||||
|
||||
/* xor of the keys of the left branch's lower branches */
|
||||
lxor = _xor_branches(kofs, key_type, 0, 0, NULL,
|
||||
(_ceb_clrtag(node->b[0])->b[0]),
|
||||
(_ceb_clrtag(node->b[0])->b[1]));
|
||||
|
||||
/* xor of the keys of the right branch's lower branches */
|
||||
rxor = _xor_branches(kofs, key_type, 0, 0, NULL,
|
||||
(_ceb_clrtag(node->b[1])->b[0]),
|
||||
(_ceb_clrtag(node->b[1])->b[1]));
|
||||
|
||||
switch (key_type) {
|
||||
case CEB_KT_ADDR:
|
||||
case CEB_KT_U32:
|
||||
case CEB_KT_U64:
|
||||
printf(" \"%lx_n_%d\" [label=\"%lx\\nlev=%d bit=%d\\nkey=%llu\" fillcolor=\"lightskyblue1\"%s];\n",
|
||||
(long)node, sub, (long)node, level, flsnz(pxor) - 1, int_key, (ctx == node) ? " color=red" : "");
|
||||
|
||||
printf(" \"%lx_n_%d\" -> \"%lx_%c_%d\" [label=\"L\" arrowsize=0.66%s%s];\n",
|
||||
(long)node, sub, (long)_ceb_clrtag(node->b[0]),
|
||||
(lxor < pxor && _ceb_clrtag(node->b[0])->b[0] != _ceb_clrtag(node->b[0])->b[1] && lxor) ? 'n' : 'l',
|
||||
sub, (node == _ceb_clrtag(node->b[0])) ? " dir=both" : "", (ctx == _ceb_clrtag(node->b[0])) ? " color=red" : "");
|
||||
|
||||
printf(" \"%lx_n_%d\" -> \"%lx_%c_%d\" [label=\"R\" arrowsize=0.66%s%s];\n",
|
||||
(long)node, sub, (long)_ceb_clrtag(node->b[1]),
|
||||
(rxor < pxor && _ceb_clrtag(node->b[1])->b[0] != _ceb_clrtag(node->b[1])->b[1] && rxor) ? 'n' : 'l',
|
||||
sub, (node == _ceb_clrtag(node->b[1])) ? " dir=both" : "", (ctx == _ceb_clrtag(node->b[1])) ? " color=red" : "");
|
||||
break;
|
||||
case CEB_KT_MB:
|
||||
break;
|
||||
case CEB_KT_IM:
|
||||
break;
|
||||
case CEB_KT_ST:
|
||||
case CEB_KT_IS:
|
||||
printf(" \"%lx_n_%d\" [label=\"%lx\\nlev=%d bit=%ld\\nkey=\\\"%s\\\"\" fillcolor=\"lightskyblue1\"%s];\n",
|
||||
(long)node, sub, (long)node, level, (long)~pxor, str_key, (ctx == node) ? " color=red" : "");
|
||||
|
||||
printf(" \"%lx_n_%d\" -> \"%lx_%c_%d\" [label=\"L\" arrowsize=0.66%s%s];\n",
|
||||
(long)node, sub, (long)_ceb_clrtag(node->b[0]),
|
||||
(lxor < pxor && _ceb_clrtag(node->b[0])->b[0] != _ceb_clrtag(node->b[0])->b[1] && lxor) ? 'n' : 'l',
|
||||
sub, (node == _ceb_clrtag(node->b[0])) ? " dir=both" : "", (ctx == _ceb_clrtag(node->b[0])) ? " color=red" : "");
|
||||
|
||||
printf(" \"%lx_n_%d\" -> \"%lx_%c_%d\" [label=\"R\" arrowsize=0.66%s%s];\n",
|
||||
(long)node, sub, (long)_ceb_clrtag(node->b[1]),
|
||||
(rxor < pxor && _ceb_clrtag(node->b[1])->b[0] != _ceb_clrtag(node->b[1])->b[1] && rxor) ? 'n' : 'l',
|
||||
sub, (node == _ceb_clrtag(node->b[1])) ? " dir=both" : "", (ctx == _ceb_clrtag(node->b[1])) ? " color=red" : "");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* dump a duplicate entry */
|
||||
void ceb_imm_default_dump_dups(ptrdiff_t kofs, enum ceb_key_type key_type, const struct ceb_node *node, int level, const void *ctx, int sub)
|
||||
{
|
||||
unsigned long long int_key = 0;
|
||||
const struct ceb_node *leaf;
|
||||
const char *str_key = NULL;
|
||||
int is_last;
|
||||
|
||||
switch (key_type) {
|
||||
case CEB_KT_ADDR:
|
||||
int_key = (uintptr_t)node;
|
||||
break;
|
||||
case CEB_KT_U32:
|
||||
int_key = NODEK(node, kofs)->u32;
|
||||
break;
|
||||
case CEB_KT_U64:
|
||||
int_key = NODEK(node, kofs)->u64;
|
||||
break;
|
||||
case CEB_KT_ST:
|
||||
str_key = (char*)NODEK(node, kofs)->str;
|
||||
break;
|
||||
case CEB_KT_IS:
|
||||
str_key = (char*)NODEK(node, kofs)->ptr;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/* Let's try to determine which one is the last of the series. The
|
||||
* right node's left node is a tree leaf in this only case. This means
|
||||
* that node either has both sides equal to itself, or a distinct
|
||||
* neighbours.
|
||||
*/
|
||||
leaf = _ceb_clrtag(_ceb_untag(node->b[1], 1)->b[0]);
|
||||
|
||||
is_last = 1;
|
||||
if (leaf->b[0] != _ceb_dotag(leaf, 1) || leaf->b[1] != _ceb_dotag(leaf, 1))
|
||||
is_last = _xor_branches(kofs, key_type, 0, 0, NULL,
|
||||
leaf->b[0], leaf->b[1]) != 0;
|
||||
|
||||
switch (key_type) {
|
||||
case CEB_KT_ADDR:
|
||||
case CEB_KT_U32:
|
||||
case CEB_KT_U64:
|
||||
printf(" \"%lx_l_%d\" [label=\"%lx\\nlev=%d\\nkey=%llu\" fillcolor=\"wheat1\"%s];\n",
|
||||
(long)node, sub, (long)node, level, int_key, (ctx == node) ? " color=red" : "");
|
||||
|
||||
printf(" \"%lx_l_%d\":sw -> \"%lx_l_%d\":n [taillabel=\"L\" arrowsize=0.66%s];\n",
|
||||
(long)node, sub, (long)_ceb_clrtag(node->b[0]), sub, (ctx == _ceb_clrtag(node->b[0])) ? " color=red" : "");
|
||||
|
||||
printf(" \"%lx_l_%d\":%s -> \"%lx_l_%d\":%s [taillabel=\"R\" arrowsize=0.66%s];\n",
|
||||
(long)node, sub, is_last ? "se" : "ne",
|
||||
(long)_ceb_clrtag(node->b[1]), sub, is_last ? "e" : "s", (ctx == _ceb_clrtag(node->b[1])) ? " color=red" : "");
|
||||
break;
|
||||
case CEB_KT_MB:
|
||||
break;
|
||||
case CEB_KT_IM:
|
||||
break;
|
||||
case CEB_KT_ST:
|
||||
case CEB_KT_IS:
|
||||
printf(" \"%lx_l_%d\" [label=\"%lx\\nlev=%d\\nkey=\\\"%s\\\"\" fillcolor=\"wheat1\"%s];\n",
|
||||
(long)node, sub, (long)node, level, str_key, (ctx == node) ? " color=red" : "");
|
||||
|
||||
printf(" \"%lx_l_%d\":sw -> \"%lx_l_%d\":n [taillabel=\"L\" arrowsize=0.66%s];\n",
|
||||
(long)node, sub, (long)_ceb_clrtag(node->b[0]), sub, (ctx == _ceb_clrtag(node->b[0])) ? " color=red" : "");
|
||||
|
||||
printf(" \"%lx_l_%d\":%s -> \"%lx_l_%d\":%s [taillabel=\"R\" arrowsize=0.66%s];\n",
|
||||
(long)node, sub, is_last ? "se" : "ne",
|
||||
(long)_ceb_clrtag(node->b[1]), sub, is_last ? "e" : "s", (ctx == _ceb_clrtag(node->b[1])) ? " color=red" : "");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* dump a leaf */
|
||||
void ceb_imm_default_dump_leaf(ptrdiff_t kofs, enum ceb_key_type key_type, const struct ceb_node *node, int level, const void *ctx, int sub)
|
||||
{
|
||||
unsigned long long int_key = 0;
|
||||
const char *str_key = NULL;
|
||||
uint64_t pxor;
|
||||
|
||||
switch (key_type) {
|
||||
case CEB_KT_ADDR:
|
||||
int_key = (uintptr_t)node;
|
||||
break;
|
||||
case CEB_KT_U32:
|
||||
int_key = NODEK(node, kofs)->u32;
|
||||
break;
|
||||
case CEB_KT_U64:
|
||||
int_key = NODEK(node, kofs)->u64;
|
||||
break;
|
||||
case CEB_KT_ST:
|
||||
str_key = (char*)NODEK(node, kofs)->str;
|
||||
break;
|
||||
case CEB_KT_IS:
|
||||
str_key = (char*)NODEK(node, kofs)->ptr;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/* xor of the keys of the two lower branches */
|
||||
pxor = _xor_branches(kofs, key_type, 0, 0, NULL,
|
||||
node->b[0], node->b[1]);
|
||||
|
||||
switch (key_type) {
|
||||
case CEB_KT_ADDR:
|
||||
case CEB_KT_U32:
|
||||
case CEB_KT_U64:
|
||||
if (node->b[0] == node->b[1])
|
||||
printf(" \"%lx_l_%d\" [label=\"%lx\\nlev=%d\\nkey=%llu\\n\" fillcolor=\"green\"%s];\n",
|
||||
(long)node, sub, (long)node, level, int_key, (ctx == node) ? " color=red" : "");
|
||||
else
|
||||
printf(" \"%lx_l_%d\" [label=\"%lx\\nlev=%d bit=%d\\nkey=%llu\\n\" fillcolor=\"yellow\"%s];\n",
|
||||
(long)node, sub, (long)node, level, flsnz(pxor) - 1, int_key, (ctx == node) ? " color=red" : "");
|
||||
break;
|
||||
case CEB_KT_MB:
|
||||
break;
|
||||
case CEB_KT_IM:
|
||||
break;
|
||||
case CEB_KT_ST:
|
||||
case CEB_KT_IS:
|
||||
if (node->b[0] == node->b[1])
|
||||
printf(" \"%lx_l_%d\" [label=\"%lx\\nlev=%d\\nkey=\\\"%s\\\"\\n\" fillcolor=\"green\"%s];\n",
|
||||
(long)node, sub, (long)node, level, str_key, (ctx == node) ? " color=red" : "");
|
||||
else
|
||||
printf(" \"%lx_l_%d\" [label=\"%lx\\nlev=%d bit=%ld\\nkey=\\\"%s\\\"\\n\" fillcolor=\"yellow\"%s];\n",
|
||||
(long)node, sub, (long)node, level, (long)~pxor, str_key, (ctx == node) ? " color=red" : "");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Dumps a tree through the specified callbacks, falling back to the default
|
||||
* callbacks above if left NULL.
|
||||
*/
|
||||
|
||||
const struct ceb_node *ceb_imm_default_dump_tree(ptrdiff_t kofs, enum ceb_key_type key_type, struct ceb_root *const *root,
|
||||
uint64_t pxor, const void *last, int level, const void *ctx, int sub,
|
||||
void (*root_dump)(ptrdiff_t kofs, enum ceb_key_type key_type, struct ceb_root *const *root, const void *ctx, int sub),
|
||||
void (*node_dump)(ptrdiff_t kofs, enum ceb_key_type key_type, const struct ceb_node *node, int level, const void *ctx, int sub),
|
||||
void (*dups_dump)(ptrdiff_t kofs, enum ceb_key_type key_type, const struct ceb_node *node, int level, const void *ctx, int sub),
|
||||
void (*leaf_dump)(ptrdiff_t kofs, enum ceb_key_type key_type, const struct ceb_node *node, int level, const void *ctx, int sub))
|
||||
{
|
||||
const struct ceb_node *node = _ceb_clrtag(*root);
|
||||
uint64_t xor;
|
||||
|
||||
if (!node) /* empty tree */
|
||||
return node;
|
||||
|
||||
if (!root_dump)
|
||||
root_dump = ceb_imm_default_dump_root;
|
||||
|
||||
if (!node_dump)
|
||||
node_dump = ceb_imm_default_dump_node;
|
||||
|
||||
if (!dups_dump)
|
||||
dups_dump = ceb_imm_default_dump_dups;
|
||||
|
||||
if (!leaf_dump)
|
||||
leaf_dump = ceb_imm_default_dump_leaf;
|
||||
|
||||
if (!level) {
|
||||
/* dump the first arrow */
|
||||
root_dump(kofs, key_type, root, ctx, sub);
|
||||
}
|
||||
|
||||
/* regular nodes, all branches are canonical */
|
||||
|
||||
while (1) {
|
||||
if (node->b[0] == _ceb_dotag(node, 1) && node->b[1] == _ceb_dotag(node, 1)) {
|
||||
/* first inserted leaf */
|
||||
leaf_dump(kofs, key_type, node, level, ctx, sub);
|
||||
return node;
|
||||
}
|
||||
|
||||
xor = _xor_branches(kofs, key_type, 0, 0, NULL,
|
||||
node->b[0], node->b[1]);
|
||||
if (xor)
|
||||
break;
|
||||
|
||||
/* a zero XOR with different branches indicates a list element,
|
||||
* we dump it and walk to the left until we find the node.
|
||||
*/
|
||||
dups_dump(kofs, key_type, node, level, ctx, sub);
|
||||
node = _ceb_clrtag(node->b[0]);
|
||||
}
|
||||
|
||||
if (pxor && xor >= pxor) {
|
||||
/* that's a leaf */
|
||||
leaf_dump(kofs, key_type, node, level, ctx, sub);
|
||||
return node;
|
||||
}
|
||||
|
||||
/* that's a regular node */
|
||||
node_dump(kofs, key_type, node, level, ctx, sub);
|
||||
|
||||
last = ceb_imm_default_dump_tree(kofs, key_type, &node->b[0], xor, last, level + 1, ctx, sub, root_dump, node_dump, dups_dump, leaf_dump);
|
||||
return ceb_imm_default_dump_tree(kofs, key_type, &node->b[1], xor, last, level + 1, ctx, sub, root_dump, node_dump, dups_dump, leaf_dump);
|
||||
}
|
||||
|
||||
#endif /* CEB_ENABLE_DUMP */
|
@ -1,162 +0,0 @@
|
||||
/*
|
||||
* Compact Elastic Binary Trees - exported functions operating on u32 keys
|
||||
*
|
||||
* Copyright (C) 2014-2024 Willy Tarreau - w@1wt.eu
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "cebtree-prv.h"
|
||||
|
||||
/*****************************************************************************\
|
||||
* The declarations below always cause two functions to be declared, one *
|
||||
* starting with "cebu32_*" and one with "cebu32_ofs_*" which takes a key *
|
||||
* offset just after the root. The one without kofs just has this argument *
|
||||
* omitted from its declaration and replaced with sizeof(struct ceb_node) in *
|
||||
* the call to the underlying functions. *
|
||||
\*****************************************************************************/
|
||||
|
||||
/* Inserts node <node> into unique tree <tree> based on its key that
|
||||
* immediately follows the node. Returns the inserted node or the one
|
||||
* that already contains the same key.
|
||||
*/
|
||||
CEB_FDECL3(struct ceb_node *, cebu32, _insert, struct ceb_node **, root, ptrdiff_t, kofs, struct ceb_node *, node)
|
||||
{
|
||||
uint32_t key = NODEK(node, kofs)->u32;
|
||||
|
||||
return _cebu_insert(root, node, kofs, CEB_KT_U32, key, 0, NULL);
|
||||
}
|
||||
|
||||
/* return the first node or NULL if not found. */
|
||||
CEB_FDECL2(struct ceb_node *, cebu32, _first, struct ceb_node **, root, ptrdiff_t, kofs)
|
||||
{
|
||||
return _cebu_first(root, kofs, CEB_KT_U32);
|
||||
}
|
||||
|
||||
/* return the last node or NULL if not found. */
|
||||
CEB_FDECL2(struct ceb_node *, cebu32, _last, struct ceb_node **, root, ptrdiff_t, kofs)
|
||||
{
|
||||
return _cebu_last(root, kofs, CEB_KT_U32);
|
||||
}
|
||||
|
||||
/* look up the specified key, and returns either the node containing it, or
|
||||
* NULL if not found.
|
||||
*/
|
||||
CEB_FDECL3(struct ceb_node *, cebu32, _lookup, struct ceb_node **, root, ptrdiff_t, kofs, uint32_t, key)
|
||||
{
|
||||
return _cebu_lookup(root, kofs, CEB_KT_U32, key, 0, NULL);
|
||||
}
|
||||
|
||||
/* look up the specified key or the highest below it, and returns either the
|
||||
* node containing it, or NULL if not found.
|
||||
*/
|
||||
CEB_FDECL3(struct ceb_node *, cebu32, _lookup_le, struct ceb_node **, root, ptrdiff_t, kofs, uint32_t, key)
|
||||
{
|
||||
return _cebu_lookup_le(root, kofs, CEB_KT_U32, key, 0, NULL);
|
||||
}
|
||||
|
||||
/* look up highest key below the specified one, and returns either the
|
||||
* node containing it, or NULL if not found.
|
||||
*/
|
||||
CEB_FDECL3(struct ceb_node *, cebu32, _lookup_lt, struct ceb_node **, root, ptrdiff_t, kofs, uint32_t, key)
|
||||
{
|
||||
return _cebu_lookup_lt(root, kofs, CEB_KT_U32, key, 0, NULL);
|
||||
}
|
||||
|
||||
/* look up the specified key or the smallest above it, and returns either the
|
||||
* node containing it, or NULL if not found.
|
||||
*/
|
||||
CEB_FDECL3(struct ceb_node *, cebu32, _lookup_ge, struct ceb_node **, root, ptrdiff_t, kofs, uint32_t, key)
|
||||
{
|
||||
return _cebu_lookup_ge(root, kofs, CEB_KT_U32, key, 0, NULL);
|
||||
}
|
||||
|
||||
/* look up the smallest key above the specified one, and returns either the
|
||||
* node containing it, or NULL if not found.
|
||||
*/
|
||||
CEB_FDECL3(struct ceb_node *, cebu32, _lookup_gt, struct ceb_node **, root, ptrdiff_t, kofs, uint32_t, key)
|
||||
{
|
||||
return _cebu_lookup_gt(root, kofs, CEB_KT_U32, key, 0, NULL);
|
||||
}
|
||||
|
||||
/* search for the next node after the specified one, and return it, or NULL if
|
||||
* not found. The approach consists in looking up that node, recalling the last
|
||||
* time a left turn was made, and returning the first node along the right
|
||||
* branch at that fork.
|
||||
*/
|
||||
CEB_FDECL3(struct ceb_node *, cebu32, _next, struct ceb_node **, root, ptrdiff_t, kofs, struct ceb_node *, node)
|
||||
{
|
||||
uint32_t key = NODEK(node, kofs)->u32;
|
||||
|
||||
return _cebu_next(root, kofs, CEB_KT_U32, key, 0, NULL);
|
||||
}
|
||||
|
||||
/* search for the prev node before the specified one, and return it, or NULL if
|
||||
* not found. The approach consists in looking up that node, recalling the last
|
||||
* time a right turn was made, and returning the last node along the left
|
||||
* branch at that fork.
|
||||
*/
|
||||
CEB_FDECL3(struct ceb_node *, cebu32, _prev, struct ceb_node **, root, ptrdiff_t, kofs, struct ceb_node *, node)
|
||||
{
|
||||
uint32_t key = NODEK(node, kofs)->u32;
|
||||
|
||||
return _cebu_prev(root, kofs, CEB_KT_U32, key, 0, NULL);
|
||||
}
|
||||
|
||||
/* look up the specified node with its key and deletes it if found, and in any
|
||||
* case, returns the node.
|
||||
*/
|
||||
CEB_FDECL3(struct ceb_node *, cebu32, _delete, struct ceb_node **, root, ptrdiff_t, kofs, struct ceb_node *, node)
|
||||
{
|
||||
uint32_t key = NODEK(node, kofs)->u32;
|
||||
|
||||
return _cebu_delete(root, node, kofs, CEB_KT_U32, key, 0, NULL);
|
||||
}
|
||||
|
||||
/* look up the specified key, and detaches it and returns it if found, or NULL
|
||||
* if not found.
|
||||
*/
|
||||
CEB_FDECL3(struct ceb_node *, cebu32, _pick, struct ceb_node **, root, ptrdiff_t, kofs, uint32_t, key)
|
||||
{
|
||||
return _cebu_delete(root, NULL, kofs, CEB_KT_U32, key, 0, NULL);
|
||||
}
|
||||
|
||||
/* dumps a ceb_node tree using the default functions above. If a node matches
|
||||
* <ctx>, this one will be highlighted in red.
|
||||
*/
|
||||
CEB_FDECL4(void, cebu32, _default_dump, struct ceb_node **, root, ptrdiff_t, kofs, const char *, label, const void *, ctx)
|
||||
{
|
||||
printf("\ndigraph cebu32_tree {\n"
|
||||
" fontname=\"fixed\";\n"
|
||||
" fontsize=8\n"
|
||||
" label=\"%s\"\n"
|
||||
"", label);
|
||||
|
||||
printf(" node [fontname=\"fixed\" fontsize=8 shape=\"box\" style=\"filled\" color=\"black\" fillcolor=\"white\"];\n"
|
||||
" edge [fontname=\"fixed\" fontsize=8 style=\"solid\" color=\"magenta\" dir=\"forward\"];\n");
|
||||
|
||||
cebu_default_dump_tree(kofs, CEB_KT_U32, root, 0, NULL, 0, ctx, NULL, NULL, NULL);
|
||||
|
||||
printf("}\n");
|
||||
}
|
@ -1,162 +0,0 @@
|
||||
/*
|
||||
* Compact Elastic Binary Trees - exported functions operating on u64 keys
|
||||
*
|
||||
* Copyright (C) 2014-2024 Willy Tarreau - w@1wt.eu
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "cebtree-prv.h"
|
||||
|
||||
/*****************************************************************************\
|
||||
* The declarations below always cause two functions to be declared, one *
|
||||
* starting with "cebu64_*" and one with "cebu64_ofs_*" which takes a key *
|
||||
* offset just after the root. The one without kofs just has this argument *
|
||||
* omitted from its declaration and replaced with sizeof(struct ceb_node) in *
|
||||
* the call to the underlying functions. *
|
||||
\*****************************************************************************/
|
||||
|
||||
/* Inserts node <node> into unique tree <tree> based on its key that
|
||||
* immediately follows the node. Returns the inserted node or the one
|
||||
* that already contains the same key.
|
||||
*/
|
||||
CEB_FDECL3(struct ceb_node *, cebu64, _insert, struct ceb_node **, root, ptrdiff_t, kofs, struct ceb_node *, node)
|
||||
{
|
||||
uint64_t key = NODEK(node, kofs)->u64;
|
||||
|
||||
return _cebu_insert(root, node, kofs, CEB_KT_U64, 0, key, NULL);
|
||||
}
|
||||
|
||||
/* return the first node or NULL if not found. */
|
||||
CEB_FDECL2(struct ceb_node *, cebu64, _first, struct ceb_node **, root, ptrdiff_t, kofs)
|
||||
{
|
||||
return _cebu_first(root, kofs, CEB_KT_U64);
|
||||
}
|
||||
|
||||
/* return the last node or NULL if not found. */
|
||||
CEB_FDECL2(struct ceb_node *, cebu64, _last, struct ceb_node **, root, ptrdiff_t, kofs)
|
||||
{
|
||||
return _cebu_last(root, kofs, CEB_KT_U64);
|
||||
}
|
||||
|
||||
/* look up the specified key, and returns either the node containing it, or
|
||||
* NULL if not found.
|
||||
*/
|
||||
CEB_FDECL3(struct ceb_node *, cebu64, _lookup, struct ceb_node **, root, ptrdiff_t, kofs, uint64_t, key)
|
||||
{
|
||||
return _cebu_lookup(root, kofs, CEB_KT_U64, 0, key, NULL);
|
||||
}
|
||||
|
||||
/* look up the specified key or the highest below it, and returns either the
|
||||
* node containing it, or NULL if not found.
|
||||
*/
|
||||
CEB_FDECL3(struct ceb_node *, cebu64, _lookup_le, struct ceb_node **, root, ptrdiff_t, kofs, uint64_t, key)
|
||||
{
|
||||
return _cebu_lookup_le(root, kofs, CEB_KT_U64, 0, key, NULL);
|
||||
}
|
||||
|
||||
/* look up highest key below the specified one, and returns either the
|
||||
* node containing it, or NULL if not found.
|
||||
*/
|
||||
CEB_FDECL3(struct ceb_node *, cebu64, _lookup_lt, struct ceb_node **, root, ptrdiff_t, kofs, uint64_t, key)
|
||||
{
|
||||
return _cebu_lookup_lt(root, kofs, CEB_KT_U64, 0, key, NULL);
|
||||
}
|
||||
|
||||
/* look up the specified key or the smallest above it, and returns either the
|
||||
* node containing it, or NULL if not found.
|
||||
*/
|
||||
CEB_FDECL3(struct ceb_node *, cebu64, _lookup_ge, struct ceb_node **, root, ptrdiff_t, kofs, uint64_t, key)
|
||||
{
|
||||
return _cebu_lookup_ge(root, kofs, CEB_KT_U64, 0, key, NULL);
|
||||
}
|
||||
|
||||
/* look up the smallest key above the specified one, and returns either the
|
||||
* node containing it, or NULL if not found.
|
||||
*/
|
||||
CEB_FDECL3(struct ceb_node *, cebu64, _lookup_gt, struct ceb_node **, root, ptrdiff_t, kofs, uint64_t, key)
|
||||
{
|
||||
return _cebu_lookup_gt(root, kofs, CEB_KT_U64, 0, key, NULL);
|
||||
}
|
||||
|
||||
/* search for the next node after the specified one, and return it, or NULL if
|
||||
* not found. The approach consists in looking up that node, recalling the last
|
||||
* time a left turn was made, and returning the first node along the right
|
||||
* branch at that fork.
|
||||
*/
|
||||
CEB_FDECL3(struct ceb_node *, cebu64, _next, struct ceb_node **, root, ptrdiff_t, kofs, struct ceb_node *, node)
|
||||
{
|
||||
uint64_t key = NODEK(node, kofs)->u64;
|
||||
|
||||
return _cebu_next(root, kofs, CEB_KT_U64, 0, key, NULL);
|
||||
}
|
||||
|
||||
/* search for the prev node before the specified one, and return it, or NULL if
|
||||
* not found. The approach consists in looking up that node, recalling the last
|
||||
* time a right turn was made, and returning the last node along the left
|
||||
* branch at that fork.
|
||||
*/
|
||||
CEB_FDECL3(struct ceb_node *, cebu64, _prev, struct ceb_node **, root, ptrdiff_t, kofs, struct ceb_node *, node)
|
||||
{
|
||||
uint64_t key = NODEK(node, kofs)->u64;
|
||||
|
||||
return _cebu_prev(root, kofs, CEB_KT_U64, 0, key, NULL);
|
||||
}
|
||||
|
||||
/* look up the specified node with its key and deletes it if found, and in any
|
||||
* case, returns the node.
|
||||
*/
|
||||
CEB_FDECL3(struct ceb_node *, cebu64, _delete, struct ceb_node **, root, ptrdiff_t, kofs, struct ceb_node *, node)
|
||||
{
|
||||
uint64_t key = NODEK(node, kofs)->u64;
|
||||
|
||||
return _cebu_delete(root, node, kofs, CEB_KT_U64, 0, key, NULL);
|
||||
}
|
||||
|
||||
/* look up the specified key, and detaches it and returns it if found, or NULL
|
||||
* if not found.
|
||||
*/
|
||||
CEB_FDECL3(struct ceb_node *, cebu64, _pick, struct ceb_node **, root, ptrdiff_t, kofs, uint64_t, key)
|
||||
{
|
||||
return _cebu_delete(root, NULL, kofs, CEB_KT_U64, 0, key, NULL);
|
||||
}
|
||||
|
||||
/* dumps a ceb_node tree using the default functions above. If a node matches
|
||||
* <ctx>, this one will be highlighted in red.
|
||||
*/
|
||||
CEB_FDECL4(void, cebu64, _default_dump, struct ceb_node **, root, ptrdiff_t, kofs, const char *, label, const void *, ctx)
|
||||
{
|
||||
printf("\ndigraph cebu64_tree {\n"
|
||||
" fontname=\"fixed\";\n"
|
||||
" fontsize=8\n"
|
||||
" label=\"%s\"\n"
|
||||
"", label);
|
||||
|
||||
printf(" node [fontname=\"fixed\" fontsize=8 shape=\"box\" style=\"filled\" color=\"black\" fillcolor=\"white\"];\n"
|
||||
" edge [fontname=\"fixed\" fontsize=8 style=\"solid\" color=\"magenta\" dir=\"forward\"];\n");
|
||||
|
||||
cebu_default_dump_tree(kofs, CEB_KT_U64, root, 0, NULL, 0, ctx, NULL, NULL, NULL);
|
||||
|
||||
printf("}\n");
|
||||
}
|
153
src/cebua_tree.c
153
src/cebua_tree.c
@ -1,153 +0,0 @@
|
||||
/*
|
||||
* Compact Elastic Binary Trees - exported functions operating on addr keys
|
||||
*
|
||||
* Copyright (C) 2014-2024 Willy Tarreau - w@1wt.eu
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "cebtree-prv.h"
|
||||
|
||||
/*****************************************************************************\
|
||||
* The declarations below always cause two functions to be declared, one *
|
||||
* starting with "cebua_*" and one with "cebua_ofs_*" which takes a key *
|
||||
* offset just after the root. The one without kofs just has this argument *
|
||||
* omitted from its declaration and replaced with sizeof(struct ceb_node) in *
|
||||
* the call to the underlying functions. *
|
||||
\*****************************************************************************/
|
||||
|
||||
/* Inserts node <node> into unique tree <tree> based on its own address
|
||||
* Returns the inserted node or the one that has the same address.
|
||||
*/
|
||||
CEB_FDECL3(struct ceb_node *, cebua, _insert, struct ceb_node **, root, ptrdiff_t, kofs, struct ceb_node *, node)
|
||||
{
|
||||
return _cebu_insert(root, node, kofs, CEB_KT_ADDR, 0, 0, node);
|
||||
}
|
||||
|
||||
/* return the first node or NULL if not found. */
|
||||
CEB_FDECL2(struct ceb_node *, cebua, _first, struct ceb_node **, root, ptrdiff_t, kofs)
|
||||
{
|
||||
return _cebu_first(root, kofs, CEB_KT_ADDR);
|
||||
}
|
||||
|
||||
/* return the last node or NULL if not found. */
|
||||
CEB_FDECL2(struct ceb_node *, cebua, _last, struct ceb_node **, root, ptrdiff_t, kofs)
|
||||
{
|
||||
return _cebu_last(root, kofs, CEB_KT_ADDR);
|
||||
}
|
||||
|
||||
/* look up the specified key, and returns either the node containing it, or
|
||||
* NULL if not found.
|
||||
*/
|
||||
CEB_FDECL3(struct ceb_node *, cebua, _lookup, struct ceb_node **, root, ptrdiff_t, kofs, const void *, key)
|
||||
{
|
||||
return _cebu_lookup(root, kofs, CEB_KT_ADDR, 0, 0, key);
|
||||
}
|
||||
|
||||
/* look up the specified key or the highest below it, and returns either the
|
||||
* node containing it, or NULL if not found.
|
||||
*/
|
||||
CEB_FDECL3(struct ceb_node *, cebua, _lookup_le, struct ceb_node **, root, ptrdiff_t, kofs, const void *, key)
|
||||
{
|
||||
return _cebu_lookup_le(root, kofs, CEB_KT_ADDR, 0, 0, key);
|
||||
}
|
||||
|
||||
/* look up highest key below the specified one, and returns either the
|
||||
* node containing it, or NULL if not found.
|
||||
*/
|
||||
CEB_FDECL3(struct ceb_node *, cebua, _lookup_lt, struct ceb_node **, root, ptrdiff_t, kofs, const void *, key)
|
||||
{
|
||||
return _cebu_lookup_lt(root, kofs, CEB_KT_ADDR, 0, 0, key);
|
||||
}
|
||||
|
||||
/* look up the specified key or the smallest above it, and returns either the
|
||||
* node containing it, or NULL if not found.
|
||||
*/
|
||||
CEB_FDECL3(struct ceb_node *, cebua, _lookup_ge, struct ceb_node **, root, ptrdiff_t, kofs, const void *, key)
|
||||
{
|
||||
return _cebu_lookup_ge(root, kofs, CEB_KT_ADDR, 0, 0, key);
|
||||
}
|
||||
|
||||
/* look up the smallest key above the specified one, and returns either the
|
||||
* node containing it, or NULL if not found.
|
||||
*/
|
||||
CEB_FDECL3(struct ceb_node *, cebua, _lookup_gt, struct ceb_node **, root, ptrdiff_t, kofs, const void *, key)
|
||||
{
|
||||
return _cebu_lookup_gt(root, kofs, CEB_KT_ADDR, 0, 0, key);
|
||||
}
|
||||
|
||||
/* search for the next node after the specified one, and return it, or NULL if
|
||||
* not found. The approach consists in looking up that node, recalling the last
|
||||
* time a left turn was made, and returning the first node along the right
|
||||
* branch at that fork.
|
||||
*/
|
||||
CEB_FDECL3(struct ceb_node *, cebua, _next, struct ceb_node **, root, ptrdiff_t, kofs, struct ceb_node *, node)
|
||||
{
|
||||
return _cebu_next(root, kofs, CEB_KT_ADDR, 0, 0, node);
|
||||
}
|
||||
|
||||
/* search for the prev node before the specified one, and return it, or NULL if
|
||||
* not found. The approach consists in looking up that node, recalling the last
|
||||
* time a right turn was made, and returning the last node along the left
|
||||
* branch at that fork.
|
||||
*/
|
||||
CEB_FDECL3(struct ceb_node *, cebua, _prev, struct ceb_node **, root, ptrdiff_t, kofs, struct ceb_node *, node)
|
||||
{
|
||||
return _cebu_prev(root, kofs, CEB_KT_ADDR, 0, 0, node);
|
||||
}
|
||||
|
||||
/* look up the specified node with its key and deletes it if found, and in any
|
||||
* case, returns the node.
|
||||
*/
|
||||
CEB_FDECL3(struct ceb_node *, cebua, _delete, struct ceb_node **, root, ptrdiff_t, kofs, struct ceb_node *, node)
|
||||
{
|
||||
return _cebu_delete(root, node, kofs, CEB_KT_ADDR, 0, 0, node);
|
||||
}
|
||||
|
||||
/* look up the specified key, and detaches it and returns it if found, or NULL
|
||||
* if not found.
|
||||
*/
|
||||
CEB_FDECL3(struct ceb_node *, cebua, _pick, struct ceb_node **, root, ptrdiff_t, kofs, const void *, key)
|
||||
{
|
||||
return _cebu_delete(root, NULL, kofs, CEB_KT_ADDR, 0, 0, key);
|
||||
}
|
||||
|
||||
/* dumps a ceb_node tree using the default functions above. If a node matches
|
||||
* <ctx>, this one will be highlighted in red.
|
||||
*/
|
||||
CEB_FDECL4(void, cebua, _default_dump, struct ceb_node **, root, ptrdiff_t, kofs, const char *, label, const void *, ctx)
|
||||
{
|
||||
printf("\ndigraph cebua_tree {\n"
|
||||
" fontname=\"fixed\";\n"
|
||||
" fontsize=8\n"
|
||||
" label=\"%s\"\n"
|
||||
"", label);
|
||||
|
||||
printf(" node [fontname=\"fixed\" fontsize=8 shape=\"box\" style=\"filled\" color=\"black\" fillcolor=\"white\"];\n"
|
||||
" edge [fontname=\"fixed\" fontsize=8 style=\"solid\" color=\"magenta\" dir=\"forward\"];\n");
|
||||
|
||||
cebu_default_dump_tree(kofs, CEB_KT_ADDR, root, 0, NULL, 0, ctx, NULL, NULL, NULL);
|
||||
|
||||
printf("}\n");
|
||||
}
|
147
src/cebub_tree.c
147
src/cebub_tree.c
@ -1,147 +0,0 @@
|
||||
/*
|
||||
* Compact Elastic Binary Trees - exported functions operating on mb keys
|
||||
*
|
||||
* Copyright (C) 2014-2024 Willy Tarreau - w@1wt.eu
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "cebtree-prv.h"
|
||||
|
||||
/*****************************************************************************\
|
||||
* The declarations below always cause two functions to be declared, one *
|
||||
* starting with "cebub_*" and one with "cebub_ofs_*" which takes a key *
|
||||
* offset just after the root. The one without kofs just has this argument *
|
||||
* omitted from its declaration and replaced with sizeof(struct ceb_node) in *
|
||||
* the call to the underlying functions. *
|
||||
\*****************************************************************************/
|
||||
|
||||
/* Inserts node <node> into unique tree <tree> based on its key that
|
||||
* immediately follows the node and for <len> bytes. Returns the
|
||||
* inserted node or the one that already contains the same key.
|
||||
*/
|
||||
CEB_FDECL4(struct ceb_node *, cebub, _insert, struct ceb_node **, root, ptrdiff_t, kofs, struct ceb_node *, node, size_t, len)
|
||||
{
|
||||
const void *key = NODEK(node, kofs)->mb;
|
||||
|
||||
return _cebu_insert(root, node, kofs, CEB_KT_MB, 0, len, key);
|
||||
}
|
||||
|
||||
/* return the first node or NULL if not found. */
|
||||
CEB_FDECL2(struct ceb_node *, cebub, _first, struct ceb_node **, root, ptrdiff_t, kofs)
|
||||
{
|
||||
return _cebu_first(root, kofs, CEB_KT_MB);
|
||||
}
|
||||
|
||||
/* return the last node or NULL if not found. */
|
||||
CEB_FDECL2(struct ceb_node *, cebub, _last, struct ceb_node **, root, ptrdiff_t, kofs)
|
||||
{
|
||||
return _cebu_last(root, kofs, CEB_KT_MB);
|
||||
}
|
||||
|
||||
/* look up the specified key <key> of length <len>, and returns either the node
|
||||
* containing it, or NULL if not found.
|
||||
*/
|
||||
CEB_FDECL4(struct ceb_node *, cebub, _lookup, struct ceb_node **, root, ptrdiff_t, kofs, const void *, key, size_t, len)
|
||||
{
|
||||
return _cebu_lookup(root, kofs, CEB_KT_MB, 0, len, key);
|
||||
}
|
||||
|
||||
/* look up the specified key or the highest below it, and returns either the
|
||||
* node containing it, or NULL if not found.
|
||||
*/
|
||||
CEB_FDECL4(struct ceb_node *, cebub, _lookup_le, struct ceb_node **, root, ptrdiff_t, kofs, const void *, key, size_t, len)
|
||||
{
|
||||
return _cebu_lookup_le(root, kofs, CEB_KT_MB, 0, len, key);
|
||||
}
|
||||
|
||||
/* look up highest key below the specified one, and returns either the
|
||||
* node containing it, or NULL if not found.
|
||||
*/
|
||||
CEB_FDECL4(struct ceb_node *, cebub, _lookup_lt, struct ceb_node **, root, ptrdiff_t, kofs, const void *, key, size_t, len)
|
||||
{
|
||||
return _cebu_lookup_lt(root, kofs, CEB_KT_MB, 0, len, key);
|
||||
}
|
||||
|
||||
/* look up the specified key or the smallest above it, and returns either the
|
||||
* node containing it, or NULL if not found.
|
||||
*/
|
||||
CEB_FDECL4(struct ceb_node *, cebub, _lookup_ge, struct ceb_node **, root, ptrdiff_t, kofs, const void *, key, size_t, len)
|
||||
{
|
||||
return _cebu_lookup_ge(root, kofs, CEB_KT_MB, 0, len, key);
|
||||
}
|
||||
|
||||
/* look up the smallest key above the specified one, and returns either the
|
||||
* node containing it, or NULL if not found.
|
||||
*/
|
||||
CEB_FDECL4(struct ceb_node *, cebub, _lookup_gt, struct ceb_node **, root, ptrdiff_t, kofs, const void *, key, size_t, len)
|
||||
{
|
||||
return _cebu_lookup_gt(root, kofs, CEB_KT_MB, 0, len, key);
|
||||
}
|
||||
|
||||
/* search for the next node after the specified one, and return it, or NULL if
|
||||
* not found. The approach consists in looking up that node, recalling the last
|
||||
* time a left turn was made, and returning the first node along the right
|
||||
* branch at that fork. The <len> field must correspond to the key length in
|
||||
* bytes.
|
||||
*/
|
||||
CEB_FDECL4(struct ceb_node *, cebub, _next, struct ceb_node **, root, ptrdiff_t, kofs, struct ceb_node *, node, size_t, len)
|
||||
{
|
||||
const void *key = NODEK(node, kofs)->mb;
|
||||
|
||||
return _cebu_next(root, kofs, CEB_KT_MB, 0, len, key);
|
||||
}
|
||||
|
||||
/* search for the prev node before the specified one, and return it, or NULL if
|
||||
* not found. The approach consists in looking up that node, recalling the last
|
||||
* time a right turn was made, and returning the last node along the left
|
||||
* branch at that fork. The <len> field must correspond to the key length in
|
||||
* bytes.
|
||||
*/
|
||||
CEB_FDECL4(struct ceb_node *, cebub, _prev, struct ceb_node **, root, ptrdiff_t, kofs, struct ceb_node *, node, size_t, len)
|
||||
{
|
||||
const void *key = NODEK(node, kofs)->mb;
|
||||
|
||||
return _cebu_prev(root, kofs, CEB_KT_MB, 0, len, key);
|
||||
}
|
||||
|
||||
/* look up the specified node with its key and deletes it if found, and in any
|
||||
* case, returns the node. The <len> field must correspond to the key length in
|
||||
* bytes.
|
||||
*/
|
||||
CEB_FDECL4(struct ceb_node *, cebub, _delete, struct ceb_node **, root, ptrdiff_t, kofs, struct ceb_node *, node, size_t, len)
|
||||
{
|
||||
const void *key = NODEK(node, kofs)->mb;
|
||||
|
||||
return _cebu_delete(root, node, kofs, CEB_KT_MB, 0, len, key);
|
||||
}
|
||||
|
||||
/* look up the specified key, and detaches it and returns it if found, or NULL
|
||||
* if not found. The <len> field must correspond to the key length in bytes.
|
||||
*/
|
||||
CEB_FDECL4(struct ceb_node *, cebub, _pick, struct ceb_node **, root, ptrdiff_t, kofs, const void *, key, size_t, len)
|
||||
{
|
||||
return _cebu_delete(root, NULL, kofs, CEB_KT_MB, 0, len, key);
|
||||
}
|
@ -1,147 +0,0 @@
|
||||
/*
|
||||
* Compact Elastic Binary Trees - exported functions operating on indirect blocks
|
||||
*
|
||||
* Copyright (C) 2014-2024 Willy Tarreau - w@1wt.eu
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "cebtree-prv.h"
|
||||
|
||||
/*****************************************************************************\
|
||||
* The declarations below always cause two functions to be declared, one *
|
||||
* starting with "cebuib_*" and one with "cebuib_ofs_*" which takes a key *
|
||||
* offset just after the root. The one without kofs just has this argument *
|
||||
* omitted from its declaration and replaced with sizeof(struct ceb_node) in *
|
||||
* the call to the underlying functions. *
|
||||
\*****************************************************************************/
|
||||
|
||||
/* Inserts node <node> into unique tree <tree> based on its key whose pointer
|
||||
* immediately follows the node and for <len> bytes. Returns the inserted node
|
||||
* or the one that already contains the same key.
|
||||
*/
|
||||
CEB_FDECL4(struct ceb_node *, cebuib, _insert, struct ceb_node **, root, ptrdiff_t, kofs, struct ceb_node *, node, size_t, len)
|
||||
{
|
||||
const void *key = NODEK(node, kofs)->ptr;
|
||||
|
||||
return _cebu_insert(root, node, kofs, CEB_KT_IM, 0, len, key);
|
||||
}
|
||||
|
||||
/* return the first node or NULL if not found. */
|
||||
CEB_FDECL2(struct ceb_node *, cebuib, _first, struct ceb_node **, root, ptrdiff_t, kofs)
|
||||
{
|
||||
return _cebu_first(root, kofs, CEB_KT_IM);
|
||||
}
|
||||
|
||||
/* return the last node or NULL if not found. */
|
||||
CEB_FDECL2(struct ceb_node *, cebuib, _last, struct ceb_node **, root, ptrdiff_t, kofs)
|
||||
{
|
||||
return _cebu_last(root, kofs, CEB_KT_IM);
|
||||
}
|
||||
|
||||
/* look up the specified key <key> of length <len>, and returns either the node
|
||||
* containing it, or NULL if not found.
|
||||
*/
|
||||
CEB_FDECL4(struct ceb_node *, cebuib, _lookup, struct ceb_node **, root, ptrdiff_t, kofs, const void *, key, size_t, len)
|
||||
{
|
||||
return _cebu_lookup(root, kofs, CEB_KT_IM, 0, len, key);
|
||||
}
|
||||
|
||||
/* look up the specified key or the highest below it, and returns either the
|
||||
* node containing it, or NULL if not found.
|
||||
*/
|
||||
CEB_FDECL4(struct ceb_node *, cebuib, _lookup_le, struct ceb_node **, root, ptrdiff_t, kofs, const void *, key, size_t, len)
|
||||
{
|
||||
return _cebu_lookup_le(root, kofs, CEB_KT_IM, 0, len, key);
|
||||
}
|
||||
|
||||
/* look up highest key below the specified one, and returns either the
|
||||
* node containing it, or NULL if not found.
|
||||
*/
|
||||
CEB_FDECL4(struct ceb_node *, cebuib, _lookup_lt, struct ceb_node **, root, ptrdiff_t, kofs, const void *, key, size_t, len)
|
||||
{
|
||||
return _cebu_lookup_lt(root, kofs, CEB_KT_IM, 0, len, key);
|
||||
}
|
||||
|
||||
/* look up the specified key or the smallest above it, and returns either the
|
||||
* node containing it, or NULL if not found.
|
||||
*/
|
||||
CEB_FDECL4(struct ceb_node *, cebuib, _lookup_ge, struct ceb_node **, root, ptrdiff_t, kofs, const void *, key, size_t, len)
|
||||
{
|
||||
return _cebu_lookup_ge(root, kofs, CEB_KT_IM, 0, len, key);
|
||||
}
|
||||
|
||||
/* look up the smallest key above the specified one, and returns either the
|
||||
* node containing it, or NULL if not found.
|
||||
*/
|
||||
CEB_FDECL4(struct ceb_node *, cebuib, _lookup_gt, struct ceb_node **, root, ptrdiff_t, kofs, const void *, key, size_t, len)
|
||||
{
|
||||
return _cebu_lookup_gt(root, kofs, CEB_KT_IM, 0, len, key);
|
||||
}
|
||||
|
||||
/* search for the next node after the specified one, and return it, or NULL if
|
||||
* not found. The approach consists in looking up that node, recalling the last
|
||||
* time a left turn was made, and returning the first node along the right
|
||||
* branch at that fork. The <len> field must correspond to the key length in
|
||||
* bytes.
|
||||
*/
|
||||
CEB_FDECL4(struct ceb_node *, cebuib, _next, struct ceb_node **, root, ptrdiff_t, kofs, struct ceb_node *, node, size_t, len)
|
||||
{
|
||||
const void *key = NODEK(node, kofs)->ptr;
|
||||
|
||||
return _cebu_next(root, kofs, CEB_KT_IM, 0, len, key);
|
||||
}
|
||||
|
||||
/* search for the prev node before the specified one, and return it, or NULL if
|
||||
* not found. The approach consists in looking up that node, recalling the last
|
||||
* time a right turn was made, and returning the last node along the left
|
||||
* branch at that fork. The <len> field must correspond to the key length in
|
||||
* bytes.
|
||||
*/
|
||||
CEB_FDECL4(struct ceb_node *, cebuib, _prev, struct ceb_node **, root, ptrdiff_t, kofs, struct ceb_node *, node, size_t, len)
|
||||
{
|
||||
const void *key = NODEK(node, kofs)->ptr;
|
||||
|
||||
return _cebu_prev(root, kofs, CEB_KT_IM, 0, len, key);
|
||||
}
|
||||
|
||||
/* look up the specified node with its key and deletes it if found, and in any
|
||||
* case, returns the node. The <len> field must correspond to the key length in
|
||||
* bytes.
|
||||
*/
|
||||
CEB_FDECL4(struct ceb_node *, cebuib, _delete, struct ceb_node **, root, ptrdiff_t, kofs, struct ceb_node *, node, size_t, len)
|
||||
{
|
||||
const void *key = NODEK(node, kofs)->ptr;
|
||||
|
||||
return _cebu_delete(root, node, kofs, CEB_KT_IM, 0, len, key);
|
||||
}
|
||||
|
||||
/* look up the specified key, and detaches it and returns it if found, or NULL
|
||||
* if not found. The <len> field must correspond to the key length in bytes.
|
||||
*/
|
||||
CEB_FDECL4(struct ceb_node *, cebuib, _pick, struct ceb_node **, root, ptrdiff_t, kofs, const void *, key, size_t, len)
|
||||
{
|
||||
return _cebu_delete(root, NULL, kofs, CEB_KT_IM, 0, len, key);
|
||||
}
|
@ -1,144 +0,0 @@
|
||||
/*
|
||||
* Compact Elastic Binary Trees - exported functions operating on indirect strings
|
||||
*
|
||||
* Copyright (C) 2014-2024 Willy Tarreau - w@1wt.eu
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "cebtree-prv.h"
|
||||
|
||||
/*****************************************************************************\
|
||||
* The declarations below always cause two functions to be declared, one *
|
||||
* starting with "cebuis_*" and one with "cebuis_ofs_*" which takes a key *
|
||||
* offset just after the root. The one without kofs just has this argument *
|
||||
* omitted from its declaration and replaced with sizeof(struct ceb_node) in *
|
||||
* the call to the underlying functions. *
|
||||
\*****************************************************************************/
|
||||
|
||||
/* Inserts node <node> into unique tree <tree> based on its key whose pointer
|
||||
* immediately follows the node. Returns the inserted node or the one that
|
||||
* already contains the same key.
|
||||
*/
|
||||
CEB_FDECL3(struct ceb_node *, cebuis, _insert, struct ceb_node **, root, ptrdiff_t, kofs, struct ceb_node *, node)
|
||||
{
|
||||
const void *key = NODEK(node, kofs)->ptr;
|
||||
|
||||
return _cebu_insert(root, node, kofs, CEB_KT_IS, 0, 0, key);
|
||||
}
|
||||
|
||||
/* return the first node or NULL if not found. */
|
||||
CEB_FDECL2(struct ceb_node *, cebuis, _first, struct ceb_node **, root, ptrdiff_t, kofs)
|
||||
{
|
||||
return _cebu_first(root, kofs, CEB_KT_IS);
|
||||
}
|
||||
|
||||
/* return the last node or NULL if not found. */
|
||||
CEB_FDECL2(struct ceb_node *, cebuis, _last, struct ceb_node **, root, ptrdiff_t, kofs)
|
||||
{
|
||||
return _cebu_last(root, kofs, CEB_KT_IS);
|
||||
}
|
||||
|
||||
/* look up the specified key, and returns either the node containing it, or
|
||||
* NULL if not found.
|
||||
*/
|
||||
CEB_FDECL3(struct ceb_node *, cebuis, _lookup, struct ceb_node **, root, ptrdiff_t, kofs, const void *, key)
|
||||
{
|
||||
return _cebu_lookup(root, kofs, CEB_KT_IS, 0, 0, key);
|
||||
}
|
||||
|
||||
/* look up the specified key or the highest below it, and returns either the
|
||||
* node containing it, or NULL if not found.
|
||||
*/
|
||||
CEB_FDECL3(struct ceb_node *, cebuis, _lookup_le, struct ceb_node **, root, ptrdiff_t, kofs, const void *, key)
|
||||
{
|
||||
return _cebu_lookup_le(root, kofs, CEB_KT_IS, 0, 0, key);
|
||||
}
|
||||
|
||||
/* look up highest key below the specified one, and returns either the
|
||||
* node containing it, or NULL if not found.
|
||||
*/
|
||||
CEB_FDECL3(struct ceb_node *, cebuis, _lookup_lt, struct ceb_node **, root, ptrdiff_t, kofs, const void *, key)
|
||||
{
|
||||
return _cebu_lookup_lt(root, kofs, CEB_KT_IS, 0, 0, key);
|
||||
}
|
||||
|
||||
/* look up the specified key or the smallest above it, and returns either the
|
||||
* node containing it, or NULL if not found.
|
||||
*/
|
||||
CEB_FDECL3(struct ceb_node *, cebuis, _lookup_ge, struct ceb_node **, root, ptrdiff_t, kofs, const void *, key)
|
||||
{
|
||||
return _cebu_lookup_ge(root, kofs, CEB_KT_IS, 0, 0, key);
|
||||
}
|
||||
|
||||
/* look up the smallest key above the specified one, and returns either the
|
||||
* node containing it, or NULL if not found.
|
||||
*/
|
||||
CEB_FDECL3(struct ceb_node *, cebuis, _lookup_gt, struct ceb_node **, root, ptrdiff_t, kofs, const void *, key)
|
||||
{
|
||||
return _cebu_lookup_gt(root, kofs, CEB_KT_IS, 0, 0, key);
|
||||
}
|
||||
|
||||
/* search for the next node after the specified one, and return it, or NULL if
|
||||
* not found. The approach consists in looking up that node, recalling the last
|
||||
* time a left turn was made, and returning the first node along the right
|
||||
* branch at that fork.
|
||||
*/
|
||||
CEB_FDECL3(struct ceb_node *, cebuis, _next, struct ceb_node **, root, ptrdiff_t, kofs, struct ceb_node *, node)
|
||||
{
|
||||
const void *key = NODEK(node, kofs)->ptr;
|
||||
|
||||
return _cebu_next(root, kofs, CEB_KT_IS, 0, 0, key);
|
||||
}
|
||||
|
||||
/* search for the prev node before the specified one, and return it, or NULL if
|
||||
* not found. The approach consists in looking up that node, recalling the last
|
||||
* time a right turn was made, and returning the last node along the left
|
||||
* branch at that fork.
|
||||
*/
|
||||
CEB_FDECL3(struct ceb_node *, cebuis, _prev, struct ceb_node **, root, ptrdiff_t, kofs, struct ceb_node *, node)
|
||||
{
|
||||
const void *key = NODEK(node, kofs)->ptr;
|
||||
|
||||
return _cebu_prev(root, kofs, CEB_KT_IS, 0, 0, key);
|
||||
}
|
||||
|
||||
/* look up the specified node with its key and deletes it if found, and in any
|
||||
* case, returns the node.
|
||||
*/
|
||||
CEB_FDECL3(struct ceb_node *, cebuis, _delete, struct ceb_node **, root, ptrdiff_t, kofs, struct ceb_node *, node)
|
||||
{
|
||||
const void *key = NODEK(node, kofs)->ptr;
|
||||
|
||||
return _cebu_delete(root, node, kofs, CEB_KT_IS, 0, 0, key);
|
||||
}
|
||||
|
||||
/* look up the specified key, and detaches it and returns it if found, or NULL
|
||||
* if not found.
|
||||
*/
|
||||
CEB_FDECL3(struct ceb_node *, cebuis, _pick, struct ceb_node **, root, ptrdiff_t, kofs, const void *, key)
|
||||
{
|
||||
return _cebu_delete(root, NULL, kofs, CEB_KT_IS, 0, 0, key);
|
||||
}
|
198
src/cebul_tree.c
198
src/cebul_tree.c
@ -1,198 +0,0 @@
|
||||
/*
|
||||
* Compact Elastic Binary Trees - exported functions operating on ulong keys
|
||||
*
|
||||
* Copyright (C) 2014-2024 Willy Tarreau - w@1wt.eu
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "cebtree-prv.h"
|
||||
|
||||
/*****************************************************************************\
|
||||
* The declarations below always cause two functions to be declared, one *
|
||||
* starting with "cebu32_*" and one with "cebu32_ofs_*" which takes a key *
|
||||
* offset just after the root. The one without kofs just has this argument *
|
||||
* omitted from its declaration and replaced with sizeof(struct ceb_node) in *
|
||||
* the call to the underlying functions. *
|
||||
\*****************************************************************************/
|
||||
|
||||
/* Inserts node <node> into unique tree <tree> based on its key that
|
||||
* immediately follows the node. Returns the inserted node or the one
|
||||
* that already contains the same key.
|
||||
*/
|
||||
CEB_FDECL3(struct ceb_node *, cebul, _insert, struct ceb_node **, root, ptrdiff_t, kofs, struct ceb_node *, node)
|
||||
{
|
||||
unsigned long key = NODEK(node, kofs)->ul;
|
||||
|
||||
if (sizeof(long) <= 4)
|
||||
return _cebu_insert(root, node, kofs, CEB_KT_U32, key, 0, NULL);
|
||||
else
|
||||
return _cebu_insert(root, node, kofs, CEB_KT_U64, 0, key, NULL);
|
||||
}
|
||||
|
||||
/* return the first node or NULL if not found. */
|
||||
CEB_FDECL2(struct ceb_node *, cebul, _first, struct ceb_node **, root, ptrdiff_t, kofs)
|
||||
{
|
||||
if (sizeof(long) <= 4)
|
||||
return _cebu_first(root, kofs, CEB_KT_U32);
|
||||
else
|
||||
return _cebu_first(root, kofs, CEB_KT_U64);
|
||||
}
|
||||
|
||||
/* return the last node or NULL if not found. */
|
||||
CEB_FDECL2(struct ceb_node *, cebul, _last, struct ceb_node **, root, ptrdiff_t, kofs)
|
||||
{
|
||||
if (sizeof(long) <= 4)
|
||||
return _cebu_last(root, kofs, CEB_KT_U32);
|
||||
else
|
||||
return _cebu_last(root, kofs, CEB_KT_U64);
|
||||
}
|
||||
|
||||
/* look up the specified key, and returns either the node containing it, or
|
||||
* NULL if not found.
|
||||
*/
|
||||
CEB_FDECL3(struct ceb_node *, cebul, _lookup, struct ceb_node **, root, ptrdiff_t, kofs, unsigned long, key)
|
||||
{
|
||||
if (sizeof(long) <= 4)
|
||||
return _cebu_lookup(root, kofs, CEB_KT_U32, key, 0, NULL);
|
||||
else
|
||||
return _cebu_lookup(root, kofs, CEB_KT_U64, 0, key, NULL);
|
||||
}
|
||||
|
||||
/* look up the specified key or the highest below it, and returns either the
|
||||
* node containing it, or NULL if not found.
|
||||
*/
|
||||
CEB_FDECL3(struct ceb_node *, cebul, _lookup_le, struct ceb_node **, root, ptrdiff_t, kofs, unsigned long, key)
|
||||
{
|
||||
if (sizeof(long) <= 4)
|
||||
return _cebu_lookup_le(root, kofs, CEB_KT_U32, key, 0, NULL);
|
||||
else
|
||||
return _cebu_lookup_le(root, kofs, CEB_KT_U64, 0, key, NULL);
|
||||
}
|
||||
|
||||
/* look up highest key below the specified one, and returns either the
|
||||
* node containing it, or NULL if not found.
|
||||
*/
|
||||
CEB_FDECL3(struct ceb_node *, cebul, _lookup_lt, struct ceb_node **, root, ptrdiff_t, kofs, unsigned long, key)
|
||||
{
|
||||
if (sizeof(long) <= 4)
|
||||
return _cebu_lookup_lt(root, kofs, CEB_KT_U32, key, 0, NULL);
|
||||
else
|
||||
return _cebu_lookup_lt(root, kofs, CEB_KT_U64, 0, key, NULL);
|
||||
}
|
||||
|
||||
/* look up the specified key or the smallest above it, and returns either the
|
||||
* node containing it, or NULL if not found.
|
||||
*/
|
||||
CEB_FDECL3(struct ceb_node *, cebul, _lookup_ge, struct ceb_node **, root, ptrdiff_t, kofs, unsigned long, key)
|
||||
{
|
||||
if (sizeof(long) <= 4)
|
||||
return _cebu_lookup_ge(root, kofs, CEB_KT_U32, key, 0, NULL);
|
||||
else
|
||||
return _cebu_lookup_ge(root, kofs, CEB_KT_U64, 0, key, NULL);
|
||||
}
|
||||
|
||||
/* look up the smallest key above the specified one, and returns either the
|
||||
* node containing it, or NULL if not found.
|
||||
*/
|
||||
CEB_FDECL3(struct ceb_node *, cebul, _lookup_gt, struct ceb_node **, root, ptrdiff_t, kofs, unsigned long, key)
|
||||
{
|
||||
if (sizeof(long) <= 4)
|
||||
return _cebu_lookup_gt(root, kofs, CEB_KT_U32, key, 0, NULL);
|
||||
else
|
||||
return _cebu_lookup_gt(root, kofs, CEB_KT_U64, 0, key, NULL);
|
||||
}
|
||||
|
||||
/* search for the next node after the specified one, and return it, or NULL if
|
||||
* not found. The approach consists in looking up that node, recalling the last
|
||||
* time a left turn was made, and returning the first node along the right
|
||||
* branch at that fork.
|
||||
*/
|
||||
CEB_FDECL3(struct ceb_node *, cebul, _next, struct ceb_node **, root, ptrdiff_t, kofs, struct ceb_node *, node)
|
||||
{
|
||||
unsigned long key = NODEK(node, kofs)->ul;
|
||||
|
||||
if (sizeof(long) <= 4)
|
||||
return _cebu_next(root, kofs, CEB_KT_U32, key, 0, NULL);
|
||||
else
|
||||
return _cebu_next(root, kofs, CEB_KT_U64, 0, key, NULL);
|
||||
}
|
||||
|
||||
/* search for the prev node before the specified one, and return it, or NULL if
|
||||
* not found. The approach consists in looking up that node, recalling the last
|
||||
* time a right turn was made, and returning the last node along the left
|
||||
* branch at that fork.
|
||||
*/
|
||||
CEB_FDECL3(struct ceb_node *, cebul, _prev, struct ceb_node **, root, ptrdiff_t, kofs, struct ceb_node *, node)
|
||||
{
|
||||
unsigned long key = NODEK(node, kofs)->ul;
|
||||
|
||||
if (sizeof(long) <= 4)
|
||||
return _cebu_prev(root, kofs, CEB_KT_U32, key, 0, NULL);
|
||||
else
|
||||
return _cebu_prev(root, kofs, CEB_KT_U64, 0, key, NULL);
|
||||
}
|
||||
|
||||
/* look up the specified node with its key and deletes it if found, and in any
|
||||
* case, returns the node.
|
||||
*/
|
||||
CEB_FDECL3(struct ceb_node *, cebul, _delete, struct ceb_node **, root, ptrdiff_t, kofs, struct ceb_node *, node)
|
||||
{
|
||||
unsigned long key = NODEK(node, kofs)->ul;
|
||||
|
||||
if (sizeof(long) <= 4)
|
||||
return _cebu_delete(root, node, kofs, CEB_KT_U32, key, 0, NULL);
|
||||
else
|
||||
return _cebu_delete(root, node, kofs, CEB_KT_U64, 0, key, NULL);
|
||||
}
|
||||
|
||||
/* look up the specified key, and detaches it and returns it if found, or NULL
|
||||
* if not found.
|
||||
*/
|
||||
CEB_FDECL3(struct ceb_node *, cebul, _pick, struct ceb_node **, root, ptrdiff_t, kofs, unsigned long, key)
|
||||
{
|
||||
if (sizeof(long) <= 4)
|
||||
return _cebu_delete(root, NULL, kofs, CEB_KT_U32, key, 0, NULL);
|
||||
else
|
||||
return _cebu_delete(root, NULL, kofs, CEB_KT_U64, 0, key, NULL);
|
||||
}
|
||||
|
||||
/* dumps a ceb_node tree using the default functions above. If a node matches
|
||||
* <ctx>, this one will be highlighted in red.
|
||||
*/
|
||||
CEB_FDECL4(void, cebul, _default_dump, struct ceb_node **, root, ptrdiff_t, kofs, const char *, label, const void *, ctx)
|
||||
{
|
||||
printf("\ndigraph cebul_tree {\n"
|
||||
" fontname=\"fixed\";\n"
|
||||
" fontsize=8\n"
|
||||
" label=\"%s\"\n"
|
||||
"", label);
|
||||
|
||||
printf(" node [fontname=\"fixed\" fontsize=8 shape=\"box\" style=\"filled\" color=\"black\" fillcolor=\"white\"];\n"
|
||||
" edge [fontname=\"fixed\" fontsize=8 style=\"solid\" color=\"magenta\" dir=\"forward\"];\n");
|
||||
|
||||
cebu_default_dump_tree(kofs, sizeof(long) <= 4 ? CEB_KT_U32 : CEB_KT_U64, root, 0, NULL, 0, ctx, NULL, NULL, NULL);
|
||||
|
||||
printf("}\n");
|
||||
}
|
163
src/cebus_tree.c
163
src/cebus_tree.c
@ -1,163 +0,0 @@
|
||||
/*
|
||||
* Compact Elastic Binary Trees - exported functions operating on string keys
|
||||
*
|
||||
* Copyright (C) 2014-2024 Willy Tarreau - w@1wt.eu
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "cebtree-prv.h"
|
||||
|
||||
/*****************************************************************************\
|
||||
* The declarations below always cause two functions to be declared, one *
|
||||
* starting with "cebus_*" and one with "cebus_ofs_*" which takes a key *
|
||||
* offset just after the root. The one without kofs just has this argument *
|
||||
* omitted from its declaration and replaced with sizeof(struct ceb_node) in *
|
||||
* the call to the underlying functions. *
|
||||
\*****************************************************************************/
|
||||
|
||||
/* Inserts node <node> into unique tree <tree> based on its key that
|
||||
* immediately follows the node. Returns the inserted node or the one
|
||||
* that already contains the same key.
|
||||
*/
|
||||
CEB_FDECL3(struct ceb_node *, cebus, _insert, struct ceb_node **, root, ptrdiff_t, kofs, struct ceb_node *, node)
|
||||
{
|
||||
const void *key = NODEK(node, kofs)->str;
|
||||
|
||||
return _cebu_insert(root, node, kofs, CEB_KT_ST, 0, 0, key);
|
||||
}
|
||||
|
||||
/* return the first node or NULL if not found. */
|
||||
CEB_FDECL2(struct ceb_node *, cebus, _first, struct ceb_node **, root, ptrdiff_t, kofs)
|
||||
{
|
||||
return _cebu_first(root, kofs, CEB_KT_ST);
|
||||
}
|
||||
|
||||
/* return the last node or NULL if not found. */
|
||||
CEB_FDECL2(struct ceb_node *, cebus, _last, struct ceb_node **, root, ptrdiff_t, kofs)
|
||||
{
|
||||
return _cebu_last(root, kofs, CEB_KT_ST);
|
||||
}
|
||||
|
||||
/* look up the specified key, and returns either the node containing it, or
|
||||
* NULL if not found.
|
||||
*/
|
||||
CEB_FDECL3(struct ceb_node *, cebus, _lookup, struct ceb_node **, root, ptrdiff_t, kofs, const void *, key)
|
||||
{
|
||||
return _cebu_lookup(root, kofs, CEB_KT_ST, 0, 0, key);
|
||||
}
|
||||
|
||||
/* look up the specified key or the highest below it, and returns either the
|
||||
* node containing it, or NULL if not found.
|
||||
*/
|
||||
CEB_FDECL3(struct ceb_node *, cebus, _lookup_le, struct ceb_node **, root, ptrdiff_t, kofs, const void *, key)
|
||||
{
|
||||
return _cebu_lookup_le(root, kofs, CEB_KT_ST, 0, 0, key);
|
||||
}
|
||||
|
||||
/* look up highest key below the specified one, and returns either the
|
||||
* node containing it, or NULL if not found.
|
||||
*/
|
||||
CEB_FDECL3(struct ceb_node *, cebus, _lookup_lt, struct ceb_node **, root, ptrdiff_t, kofs, const void *, key)
|
||||
{
|
||||
return _cebu_lookup_lt(root, kofs, CEB_KT_ST, 0, 0, key);
|
||||
}
|
||||
|
||||
/* look up the specified key or the smallest above it, and returns either the
|
||||
* node containing it, or NULL if not found.
|
||||
*/
|
||||
CEB_FDECL3(struct ceb_node *, cebus, _lookup_ge, struct ceb_node **, root, ptrdiff_t, kofs, const void *, key)
|
||||
{
|
||||
return _cebu_lookup_ge(root, kofs, CEB_KT_ST, 0, 0, key);
|
||||
}
|
||||
|
||||
/* look up the smallest key above the specified one, and returns either the
|
||||
* node containing it, or NULL if not found.
|
||||
*/
|
||||
CEB_FDECL3(struct ceb_node *, cebus, _lookup_gt, struct ceb_node **, root, ptrdiff_t, kofs, const void *, key)
|
||||
{
|
||||
return _cebu_lookup_gt(root, kofs, CEB_KT_ST, 0, 0, key);
|
||||
}
|
||||
|
||||
/* search for the next node after the specified one, and return it, or NULL if
|
||||
* not found. The approach consists in looking up that node, recalling the last
|
||||
* time a left turn was made, and returning the first node along the right
|
||||
* branch at that fork.
|
||||
*/
|
||||
CEB_FDECL3(struct ceb_node *, cebus, _next, struct ceb_node **, root, ptrdiff_t, kofs, struct ceb_node *, node)
|
||||
{
|
||||
const void *key = NODEK(node, kofs)->str;
|
||||
|
||||
return _cebu_next(root, kofs, CEB_KT_ST, 0, 0, key);
|
||||
}
|
||||
|
||||
/* search for the prev node before the specified one, and return it, or NULL if
|
||||
* not found. The approach consists in looking up that node, recalling the last
|
||||
* time a right turn was made, and returning the last node along the left
|
||||
* branch at that fork.
|
||||
*/
|
||||
CEB_FDECL3(struct ceb_node *, cebus, _prev, struct ceb_node **, root, ptrdiff_t, kofs, struct ceb_node *, node)
|
||||
{
|
||||
const void *key = NODEK(node, kofs)->str;
|
||||
|
||||
return _cebu_prev(root, kofs, CEB_KT_ST, 0, 0, key);
|
||||
}
|
||||
|
||||
/* look up the specified node with its key and deletes it if found, and in any
|
||||
* case, returns the node.
|
||||
*/
|
||||
CEB_FDECL3(struct ceb_node *, cebus, _delete, struct ceb_node **, root, ptrdiff_t, kofs, struct ceb_node *, node)
|
||||
{
|
||||
const void *key = NODEK(node, kofs)->str;
|
||||
|
||||
return _cebu_delete(root, node, kofs, CEB_KT_ST, 0, 0, key);
|
||||
}
|
||||
|
||||
/* look up the specified key, and detaches it and returns it if found, or NULL
|
||||
* if not found.
|
||||
*/
|
||||
CEB_FDECL3(struct ceb_node *, cebus, _pick, struct ceb_node **, root, ptrdiff_t, kofs, const void *, key)
|
||||
{
|
||||
return _cebu_delete(root, NULL, kofs, CEB_KT_ST, 0, 0, key);
|
||||
}
|
||||
|
||||
/* dumps a ceb_node tree using the default functions above. If a node matches
|
||||
* <ctx>, this one will be highlighted in red.
|
||||
*/
|
||||
CEB_FDECL4(void, cebus, _default_dump, struct ceb_node **, root, ptrdiff_t, kofs, const char *, label, const void *, ctx)
|
||||
{
|
||||
printf("\ndigraph cebus_tree {\n"
|
||||
" fontname=\"fixed\";\n"
|
||||
" fontsize=8\n"
|
||||
" label=\"%s\"\n"
|
||||
"", label);
|
||||
|
||||
printf(" node [fontname=\"fixed\" fontsize=8 shape=\"box\" style=\"filled\" color=\"black\" fillcolor=\"white\"];\n"
|
||||
" edge [fontname=\"fixed\" fontsize=8 style=\"solid\" color=\"magenta\" dir=\"forward\"];\n");
|
||||
|
||||
cebu_default_dump_tree(kofs, CEB_KT_ST, root, 0, NULL, 0, ctx, NULL, NULL, NULL);
|
||||
|
||||
printf("}\n");
|
||||
}
|
12
src/tools.c
12
src/tools.c
@ -58,7 +58,7 @@ extern void *__elf_aux_vector;
|
||||
#include <sys/prctl.h>
|
||||
#endif
|
||||
|
||||
#include <import/cebus_tree.h>
|
||||
#include <import/cebs_tree.h>
|
||||
#include <import/eb32sctree.h>
|
||||
#include <import/eb32tree.h>
|
||||
#include <import/ebmbtree.h>
|
||||
@ -127,7 +127,7 @@ int build_is_static = 0;
|
||||
|
||||
/* known file names, made of file_name_node, to be used with file_name_*() */
|
||||
struct {
|
||||
struct ceb_node *root; // file names tree, used with cebus_*()
|
||||
struct ceb_root *root; // file names tree, used with cebus_*()
|
||||
__decl_thread(HA_RWLOCK_T lock);
|
||||
} file_names = { 0 };
|
||||
|
||||
@ -7254,7 +7254,7 @@ const char *copy_file_name(const char *name)
|
||||
return NULL;
|
||||
|
||||
HA_RWLOCK_RDLOCK(OTHER_LOCK, &file_names.lock);
|
||||
node = cebus_lookup(&file_names.root, name);
|
||||
node = cebus_imm_lookup(&file_names.root, name);
|
||||
HA_RWLOCK_RDUNLOCK(OTHER_LOCK, &file_names.lock);
|
||||
|
||||
if (node) {
|
||||
@ -7269,7 +7269,7 @@ const char *copy_file_name(const char *name)
|
||||
|
||||
memcpy(file->name, name, len + 1);
|
||||
HA_RWLOCK_WRLOCK(OTHER_LOCK, &file_names.lock);
|
||||
node = cebus_insert(&file_names.root, &file->node);
|
||||
node = cebus_imm_insert(&file_names.root, &file->node);
|
||||
HA_RWLOCK_WRUNLOCK(OTHER_LOCK, &file_names.lock);
|
||||
|
||||
if (node != &file->node) {
|
||||
@ -7288,9 +7288,9 @@ void free_all_file_names()
|
||||
|
||||
HA_RWLOCK_WRLOCK(OTHER_LOCK, &file_names.lock);
|
||||
|
||||
while ((node = cebus_first(&file_names.root))) {
|
||||
while ((node = cebus_imm_first(&file_names.root))) {
|
||||
file = container_of(node, struct file_name_node, node);
|
||||
cebus_delete(&file_names.root, node);
|
||||
cebus_imm_delete(&file_names.root, node);
|
||||
free(file);
|
||||
}
|
||||
|
||||
|
10
src/vars.c
10
src/vars.c
@ -20,7 +20,7 @@
|
||||
#include <haproxy/vars.h>
|
||||
#include <haproxy/xxhash.h>
|
||||
|
||||
#include <import/cebu64_tree.h>
|
||||
#include <import/ceb64_tree.h>
|
||||
|
||||
|
||||
/* This contains a pool of struct vars */
|
||||
@ -190,7 +190,7 @@ unsigned int var_clear(struct vars *vars, struct var *var, int force)
|
||||
var->data.type = SMP_T_ANY;
|
||||
|
||||
if (!(var->flags & VF_PERMANENT) || force) {
|
||||
cebu64_delete(&vars->name_root[var->name_hash % VAR_NAME_ROOTS], &var->node);
|
||||
cebu64_imm_delete(&vars->name_root[var->name_hash % VAR_NAME_ROOTS], &var->node);
|
||||
pool_free(var_pool, var);
|
||||
size += sizeof(struct var);
|
||||
}
|
||||
@ -208,7 +208,7 @@ void vars_prune_per_sess(struct vars *vars)
|
||||
int i;
|
||||
|
||||
for (i = 0; i < VAR_NAME_ROOTS; i++) {
|
||||
while ((node = cebu64_first(&vars->name_root[i]))) {
|
||||
while ((node = cebu64_imm_first(&vars->name_root[i]))) {
|
||||
var = container_of(node, struct var, node);
|
||||
size += var_clear(vars, var, 1);
|
||||
}
|
||||
@ -336,7 +336,7 @@ static struct var *var_get(struct vars *vars, uint64_t name_hash)
|
||||
{
|
||||
struct ceb_node *node;
|
||||
|
||||
node = cebu64_lookup(&vars->name_root[name_hash % VAR_NAME_ROOTS], name_hash);
|
||||
node = cebu64_imm_lookup(&vars->name_root[name_hash % VAR_NAME_ROOTS], name_hash);
|
||||
if (node)
|
||||
return container_of(node, struct var, node);
|
||||
|
||||
@ -439,7 +439,7 @@ int var_set(const struct var_desc *desc, struct sample *smp, uint flags)
|
||||
var->name_hash = desc->name_hash;
|
||||
var->flags = flags & VF_PERMANENT;
|
||||
var->data.type = SMP_T_ANY;
|
||||
cebu64_insert(&vars->name_root[var->name_hash % VAR_NAME_ROOTS], &var->node);
|
||||
cebu64_imm_insert(&vars->name_root[var->name_hash % VAR_NAME_ROOTS], &var->node);
|
||||
}
|
||||
|
||||
/* A variable of type SMP_T_ANY is considered as unset (either created
|
||||
|
Loading…
x
Reference in New Issue
Block a user