diff options
| author | Mistivia <i@mistivia.com> | 2025-06-09 17:54:55 +0800 |
|---|---|---|
| committer | Mistivia <i@mistivia.com> | 2025-06-09 17:55:13 +0800 |
| commit | 2f0781104330d1ae4fae041560ee3a5cb892c3b6 (patch) | |
| tree | e43dfccb7ea1b0ab13a659ed4fce05acb2cb13b5 /src | |
| parent | a690e564d82a46c4e729d88fcc660e4e2f1e6ceb (diff) | |
genenric tree map
Diffstat (limited to 'src')
| -rw-r--r-- | src/basic_traits.c | 9 | ||||
| -rw-r--r-- | src/hash_table.c | 1 | ||||
| -rw-r--r-- | src/hash_table.h | 1 | ||||
| -rw-r--r-- | src/rb_tree.h | 79 | ||||
| -rw-r--r-- | src/tree_map.c (renamed from src/rb_tree.c) | 14 | ||||
| -rw-r--r-- | src/tree_map.h | 148 | ||||
| -rw-r--r-- | src/type_alias.h | 8 |
7 files changed, 251 insertions, 9 deletions
diff --git a/src/basic_traits.c b/src/basic_traits.c index b7c4d3a..5d2a8fb 100644 --- a/src/basic_traits.c +++ b/src/basic_traits.c @@ -1,6 +1,7 @@ #include "basic_traits.h" #include <string.h> +#include <inttypes.h> #include "mmhash.h" @@ -35,16 +36,16 @@ void Bool_show(Bool self, FILE* fp) { else fprintf(fp, "false"); } void Int_show(Int self, FILE* fp) { - fprintf(fp, "%d", self); + fprintf(fp, "%"PRId32, self); } void Long_show(Long self, FILE* fp) { - fprintf(fp, "%lld", self); + fprintf(fp, "%"PRId64, self); } void UInt_show(UInt self, FILE* fp) { - fprintf(fp, "%ud", self); + fprintf(fp, "%"PRIu32, self); } void ULong_show(ULong self, FILE* fp) { - fprintf(fp, "%llud", self); + fprintf(fp, "%"PRIu64, self); } void VoidPtr_show(VoidPtr self, FILE* fp) { fprintf(fp, "%p", self); diff --git a/src/hash_table.c b/src/hash_table.c index c768df8..bedeb4a 100644 --- a/src/hash_table.c +++ b/src/hash_table.c @@ -16,6 +16,7 @@ HASH_TABLE_IMPL(String, VoidPtr); HASH_TABLE_IMPL(Int, Int); HASH_TABLE_IMPL(Int, Double); HASH_TABLE_IMPL(VoidPtr, Int); +HASH_TABLE_IMPL(VoidPtr, VoidPtr); HASH_TABLE_IMPL(VoidPtr, String); diff --git a/src/hash_table.h b/src/hash_table.h index ba42628..9b45dff 100644 --- a/src/hash_table.h +++ b/src/hash_table.h @@ -92,6 +92,7 @@ HASH_TABLE_DEF(Int, Int); HASH_TABLE_DEF(Int, Double); HASH_TABLE_DEF(VoidPtr, Int); HASH_TABLE_DEF(VoidPtr, String); +HASH_TABLE_DEF(VoidPtr, VoidPtr); void init_hash_table(HashTable *ht, int64_t elemsz, int64_t cap); bool hash_table_insert(HashTable *ht, void *elem, uint64_t (*hash)(void*), bool (*eq)(void*, void*)); diff --git a/src/rb_tree.h b/src/rb_tree.h index 2f00bf0..7c91cea 100644 --- a/src/rb_tree.h +++ b/src/rb_tree.h @@ -28,6 +28,75 @@ #include <stdlib.h> +#include "type_alias.h" + +#define TREE_MAP_DEF(K, V) \ + typedef struct { \ + RBNode rbnode; \ + K key; \ + V value; \ + } K##2##V##TreeMapNode; \ + typedef K##2##V##TreeMapNode *K##2##V##TreeMapIter; \ + typedef struct { \ + RBTree tree; \ + } K##2##V##TreeMap; \ + void K##2##V##TreeMap_init(K##2##V##TreeMap *self); \ + K##2##V##TreeMapIter K##2##V##TreeMap_insert(K##2##V##TreeMap *self, K key, V value); \ + K##2##V##TreeMapIter K##2##V##TreeMap_find(K##2##V##TreeMap *self, K key); \ + V* K##2##V##TreeMap_get(K##2##V##TreeMap *self, K key); \ + K##2##V##TreeMapIter K##2##V##TreeMap_next(K##2##V##TreeMap *self, K##2##V##TreeMapIter iter); \ + void K##2##V##TreeMap_remove(K##2##V##TreeMap *self, K##2##V##TreeMapIter iter); \ + K##2##V##TreeMapIter K##2##V##TreeMap_min(K##2##V##TreeMap *self); \ + K##2##V##TreeMapIter K##2##V##TreeMap_max(K##2##V##TreeMap *self); \ + K##2##V##TreeMapIter K##2##V##TreeMap_left(K##2##V##TreeMapIter iter); \ + K##2##V##TreeMapIter K##2##V##TreeMap_right(K##2##V##TreeMapIter iter); \ + K##2##V##TreeMapIter K##2##V##TreeMap_parent(K##2##V##TreeMapIter iter); \ + +#define TREE_MAP_IMPL(K, V) \ + static int K##2##V##TreeMap_cmp(void *vlhs, void *vrhs) { \ + K *lhs = vlhs, *rhs = vrhs; \ + return K##_cmp(*lhs, *rhs); \ + } \ + void K##2##V##TreeMap_init(K##2##V##TreeMap *self) { \ + self->tree.rbh_root = NULL; \ + self->tree.cmp = K##2##V##TreeMap_cmp; \ + self->tree.augment = NULL; \ + } \ + K##2##V##TreeMapIter K##2##V##TreeMap_insert(K##2##V##TreeMap *self, K key, V value) { \ + K##2##V##TreeMapNode *newnode = malloc(sizeof(K##2##V##TreeMapNode)); \ + newnode->key = key; \ + newnode->value = value; \ + return rb_tree_insert(&self->tree, newnode); \ + } \ + K##2##V##TreeMapIter K##2##V##TreeMap_find(K##2##V##TreeMap *self, K key) { \ + return rb_tree_find(&self->tree, &key); \ + } \ + V* K##2##V##TreeMap_get(K##2##V##TreeMap *self, K key) { \ + K##2##V##TreeMapIter iter = rb_tree_find(&self->tree, &key); \ + return &iter->value; \ + } \ + void K##2##V##TreeMap_remove(K##2##V##TreeMap *self, K##2##V##TreeMapIter iter) { \ + rb_tree_remove(self, iter); \ + } \ + K##2##V##TreeMapIter K##2##V##TreeMap_next(K##2##V##TreeMap *self, K##2##V##TreeMapIter iter) { \ + return rb_tree_next(&self->tree, iter); \ + } \ + K##2##V##TreeMapIter K##2##V##TreeMap_min(K##2##V##TreeMap *self) { \ + return rb_tree_min(&self->tree); \ + } \ + K##2##V##TreeMapIter K##2##V##TreeMap_max(K##2##V##TreeMap *self) { \ + return rb_tree_max(&self->tree); \ + } \ + K##2##V##TreeMapIter K##2##V##TreeMap_left(K##2##V##TreeMapIter iter) { \ + return rb_tree_left(iter); \ + } \ + K##2##V##TreeMapIter K##2##V##TreeMap_right(K##2##V##TreeMapIter iter) { \ + return rb_tree_right(iter); \ + } \ + K##2##V##TreeMapIter K##2##V##TreeMap_parent(K##2##V##TreeMapIter iter) { \ + return rb_tree_parent(iter); \ + } \ + struct rb_node { struct { struct rb_node *rbe_left; @@ -60,5 +129,15 @@ void *rb_tree_parent(void *node); void destroy_rb_tree(RBTree *, void (*freeCb)(void *)); +TREE_MAP_DEF(String, Int); +TREE_MAP_DEF(String, String); +TREE_MAP_DEF(String, Double); +TREE_MAP_DEF(String, VoidPtr); +TREE_MAP_DEF(Int, Int); +TREE_MAP_DEF(Int, Double); +TREE_MAP_DEF(VoidPtr, Int); +TREE_MAP_DEF(VoidPtr, String); +TREE_MAP_DEF(VoidPtr, VoidPtr); + #endif diff --git a/src/rb_tree.c b/src/tree_map.c index 10c4418..0232a54 100644 --- a/src/rb_tree.c +++ b/src/tree_map.c @@ -23,11 +23,23 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include "rb_tree.h" +#include "tree_map.h" + +#include "basic_traits.h" #define RED 1 #define BLACK 0 +TREE_MAP_IMPL(String, Int); +TREE_MAP_IMPL(String, String); +TREE_MAP_IMPL(String, Double); +TREE_MAP_IMPL(String, VoidPtr); +TREE_MAP_IMPL(Int, Int); +TREE_MAP_IMPL(Int, Double); +TREE_MAP_IMPL(VoidPtr, Int); +TREE_MAP_IMPL(VoidPtr, String); +TREE_MAP_IMPL(VoidPtr, VoidPtr); + static RBNode *rb_tree_minmax(RBTree *, int); void *rb_tree_min(RBTree *head) { return rb_tree_minmax(head, -1); } void *rb_tree_max(RBTree *head) { return rb_tree_minmax(head, 1); } diff --git a/src/tree_map.h b/src/tree_map.h new file mode 100644 index 0000000..5e905a8 --- /dev/null +++ b/src/tree_map.h @@ -0,0 +1,148 @@ +/* + * Copyright 2002 Niels Provos <provos@citi.umich.edu> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef RB_TREE_H_ +#define RB_TREE_H_ + +#include <stdlib.h> + +#include "type_alias.h" + +#define TREE_MAP_DEF(K, V) \ + typedef struct { \ + RBNode rbnode; \ + K key; \ + V value; \ + } K##2##V##TreeMapNode; \ + typedef K##2##V##TreeMapNode *K##2##V##TreeMapIter; \ + typedef struct { \ + RBTree tree; \ + } K##2##V##TreeMap; \ + void K##2##V##TreeMap_init(K##2##V##TreeMap *self); \ + K##2##V##TreeMapIter K##2##V##TreeMap_insert(K##2##V##TreeMap *self, K key, V value); \ + K##2##V##TreeMapIter K##2##V##TreeMap_find(K##2##V##TreeMap *self, K key); \ + V* K##2##V##TreeMap_get(K##2##V##TreeMap *self, K key); \ + K##2##V##TreeMapIter K##2##V##TreeMap_next(K##2##V##TreeMap *self, K##2##V##TreeMapIter iter); \ + K##2##V##TreeMapIter K##2##V##TreeMap_min(K##2##V##TreeMap *self); \ + K##2##V##TreeMapIter K##2##V##TreeMap_max(K##2##V##TreeMap *self); \ + void K##2##V##TreeMap_remove(K##2##V##TreeMap *self, K##2##V##TreeMapIter iter); \ + K##2##V##TreeMapIter K##2##V##TreeMap_left(K##2##V##TreeMapIter iter); \ + K##2##V##TreeMapIter K##2##V##TreeMap_right(K##2##V##TreeMapIter iter); \ + K##2##V##TreeMapIter K##2##V##TreeMap_parent(K##2##V##TreeMapIter iter); \ + void K##2##V##TreeMap_free(K##2##V##TreeMap *self); \ + +#define TREE_MAP_IMPL(K, V) \ + static int K##2##V##TreeMap_cmp(void *vlhs, void *vrhs) { \ + K *lhs = vlhs, *rhs = vrhs; \ + return K##_cmp(*lhs, *rhs); \ + } \ + void K##2##V##TreeMap_init(K##2##V##TreeMap *self) { \ + self->tree.rbh_root = NULL; \ + self->tree.cmp = K##2##V##TreeMap_cmp; \ + self->tree.augment = NULL; \ + } \ + K##2##V##TreeMapIter K##2##V##TreeMap_insert(K##2##V##TreeMap *self, K key, V value) { \ + K##2##V##TreeMapNode *newnode = malloc(sizeof(K##2##V##TreeMapNode)); \ + newnode->key = key; \ + newnode->value = value; \ + return rb_tree_insert(&self->tree, newnode); \ + } \ + K##2##V##TreeMapIter K##2##V##TreeMap_find(K##2##V##TreeMap *self, K key) { \ + return rb_tree_find(&self->tree, &key); \ + } \ + V* K##2##V##TreeMap_get(K##2##V##TreeMap *self, K key) { \ + K##2##V##TreeMapIter iter = rb_tree_find(&self->tree, &key); \ + if (iter == NULL) return NULL; \ + return &iter->value; \ + } \ + void K##2##V##TreeMap_remove(K##2##V##TreeMap *self, K##2##V##TreeMapIter iter) { \ + rb_tree_remove(&self->tree, iter); \ + } \ + K##2##V##TreeMapIter K##2##V##TreeMap_next(K##2##V##TreeMap *self, K##2##V##TreeMapIter iter) { \ + return rb_tree_next(&self->tree, iter); \ + } \ + K##2##V##TreeMapIter K##2##V##TreeMap_min(K##2##V##TreeMap *self) { \ + return rb_tree_min(&self->tree); \ + } \ + K##2##V##TreeMapIter K##2##V##TreeMap_max(K##2##V##TreeMap *self) { \ + return rb_tree_max(&self->tree); \ + } \ + K##2##V##TreeMapIter K##2##V##TreeMap_left(K##2##V##TreeMapIter iter) { \ + return rb_tree_left(iter); \ + } \ + K##2##V##TreeMapIter K##2##V##TreeMap_right(K##2##V##TreeMapIter iter) { \ + return rb_tree_right(iter); \ + } \ + K##2##V##TreeMapIter K##2##V##TreeMap_parent(K##2##V##TreeMapIter iter) { \ + return rb_tree_parent(iter); \ + } \ + void K##2##V##TreeMap_free(K##2##V##TreeMap *self) { \ + return destroy_rb_tree(&self->tree, NULL); \ + } \ + +struct rb_node { + struct { + struct rb_node *rbe_left; + struct rb_node *rbe_right; + struct rb_node *rbe_parent; + int rbe_color; + } entry; + char content[0]; +}; +typedef struct rb_node RBNode; + +struct rb_tree { + RBNode *rbh_root; + int (*cmp)(void *k1, void *k2); + void (*augment)(void *elm); +}; +typedef struct rb_tree RBTree; + +void rb_tree_remove(RBTree *, void *iter); + +// return a iterator +void *rb_tree_insert(RBTree *, void *treenode); +void *rb_tree_find(RBTree *, void *val); +void *rb_tree_next(RBTree *, void *iter); +void *rb_tree_min(RBTree *); +void *rb_tree_max(RBTree *); +void *rb_tree_left(void *node); +void *rb_tree_right(void *node); +void *rb_tree_parent(void *node); + +void destroy_rb_tree(RBTree *, void (*freeCb)(void *)); + +TREE_MAP_DEF(String, Int); +TREE_MAP_DEF(String, String); +TREE_MAP_DEF(String, Double); +TREE_MAP_DEF(String, VoidPtr); +TREE_MAP_DEF(Int, Int); +TREE_MAP_DEF(Int, Double); +TREE_MAP_DEF(VoidPtr, Int); +TREE_MAP_DEF(VoidPtr, String); +TREE_MAP_DEF(VoidPtr, VoidPtr); + +#endif + diff --git a/src/type_alias.h b/src/type_alias.h index fbee6ef..8f818ed 100644 --- a/src/type_alias.h +++ b/src/type_alias.h @@ -5,10 +5,10 @@ #include <stdbool.h> typedef bool Bool; -typedef int Int; -typedef long long Long; -typedef unsigned int UInt; -typedef unsigned long long ULong; +typedef int32_t Int; +typedef int64_t Long; +typedef uint32_t UInt; +typedef uint64_t ULong; typedef char Char; typedef float Float; typedef double Double; |
