Skip to content

Commit

Permalink
work on umap api
Browse files Browse the repository at this point in the history
without pairs. but TK type, and _key methods.
T iters, not B (no node fields, just B* groups and T* values).
use find_index and iter_index, not find_node.

see the map branch for pairs and T_VALUE.
  • Loading branch information
rurban committed Feb 21, 2024
1 parent 92d4550 commit be5aea2
Show file tree
Hide file tree
Showing 19 changed files with 627 additions and 360 deletions.
12 changes: 7 additions & 5 deletions GNUmakefile
Original file line number Diff line number Diff line change
Expand Up @@ -292,11 +292,13 @@ help:
ctl/string.i:
$(call expand,$(subst .i,,$@))
ctl/map.i:
$(call expand,$(subst .i,,$@),-DT=strint -DPOD)
ctl/unordered_map.i:
$(call expand,$(subst .i,,$@),-DT=strint -DPOD)
$(call expand,$(subst .i,,$@),-DTK=charp -DT=int -DPOD)
ctl/array.i:
$(call expand,$(subst .i,,$@),-DT=int -DN=128 -DPOD)
ctl/unordered_map.i:
$(call expand,$(subst .i,,$@),-DTK=charp -DT=int -DPOD)
ctl/swisstable.i:
$(call expand,$(subst .i,,$@),-DTK=charp -DT=int -DPOD)

%.i : %.h
@$(CC) $(CFLAGS) -DT=int -DPOD $< -E | clang-format -style=webkit
Expand Down Expand Up @@ -343,10 +345,10 @@ tests/func/test_unordered_set_cached: .cflags $(COMMON_H) tests/test.h tests/fun
tests/func/test_unordered_set_sleep: .cflags $(COMMON_H) tests/test.h ctl/unordered_set.h \
tests/func/test_unordered_set_sleep.c
$(CC) $(CFLAGS) -O3 -finline tests/func/test_unordered_set_sleep.c -o $@
tests/func/test_unordered_map: .cflags $(H) tests/test.h tests/func/strint.hh \
tests/func/test_unordered_map: .cflags $(COMMON_H) tests/test.h tests/func/strint.hh \
tests/func/test_unordered_map.cc
$(CXX) $(CXXFLAGS) -o $@ $@.cc
tests/func/test_swisstable: .cflags $(H) tests/test.h tests/func/strint.hh \
tests/func/test_swisstable: .cflags $(COMMON_H) tests/test.h tests/func/strint.hh \
tests/func/test_swisstable.cc
$(CXX) $(CXXFLAGS) -o $@ $@.cc
tests/func/test_stack: .cflags $(COMMON_H) tests/test.h tests/func/digi.hh ctl/stack.h ctl/deque.h \
Expand Down
2 changes: 0 additions & 2 deletions ctl/array.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,6 @@ typedef struct A
int (*equal)(T *, T *); // optional
} A;

typedef int (*JOIN(A, compare_fn))(T *, T *);

#include <ctl/bits/iterator_vtable.h>

typedef struct I
Expand Down
8 changes: 8 additions & 0 deletions ctl/bits/container.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,14 @@
#endif
// clang-format on

#ifdef TK
typedef int (*JOIN(A, compare_fn))(TK *, TK *);
typedef int (*JOIN(A, equal_fn))(TK *, TK *);
#else
typedef int (*JOIN(A, compare_fn))(T *, T *);
typedef int (*JOIN(A, equal_fn))(T *, T *);
#endif

// FIXME once per A
//#ifndef CAT(HAVE, JOIN(T, it_vtable))
//#define CAT(HAVE, JOIN(T, it_vtable))
Expand Down
234 changes: 160 additions & 74 deletions ctl/bits/integral.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
/* Type utilities, to apply default equal, compare, hash methods for intergral types.
See MIT LICENSE.
/* Type utilities, to apply default equal, compare, hash methods for integral
* types, and simple char* keys.
*
* SPDX-License-Identifier: MIT
*/

// is_integral type utilities, to make equal and compare optional for simple POD types
Expand All @@ -14,6 +16,72 @@ _define_integral_compare(long)
#undef _define_integral_compare
*/

#include <string.h>

#define CTL_STRINGIFY_HELPER(n) #n
#define CTL_STRINGIFY(n) CTL_STRINGIFY_HELPER(n)
#define _strEQ(s1, s2c) !strcmp(s1, s2c "")
#define _strEQcc(s1c, s2c) !strcmp(s1c "", s2c "")

static inline bool _JOIN(A, _type_is_string)(const char* typ)
{
return _strEQ(typ, "str") || _strEQ(typ, "char*") ||
_strEQ(typ, "unsigned char*") || _strEQ(typ, "ucharp") ||
_strEQ(typ, "u8string") || _strEQ(typ, "u8ident");
}

static inline int _JOIN(A, _default_charp_equal)(const char **s1, const char **s2)
{
return strcmp(*s1, *s2) == 0;
}
static inline int _JOIN(A, _default_charp_compare)(const char **s1, const char **s2)
{
return strcmp(*s1, *s2) < 0;
}

#if defined CTL_USET || defined CTL_UMAP

#if (defined POD && !defined TK) || (defined PODK && defined TK)
# ifdef TK
static inline size_t _JOIN(A, _default_charp_hash)(TK *key)
# else
static inline size_t _JOIN(A, _default_charp_hash)(T *key)
# endif
{
#if 1
/* For now FNV1a, not wyhash nor o1hash */
const unsigned char *s = (const unsigned char *)key;
size_t h = 2166136261u;
for (unsigned i = 0; i < strlen(s); i++)
{
h ^= s[i];
h *= 16777619;
}
return h;
#endif
}
#endif // POD

// not C++
#ifndef __cplusplus
#define __set_charp_hash(self, t) \
{ \
/*__typeof__(t) tmp = (self);*/ \
if (__builtin_types_compatible_p(__typeof__(t), char *) || \
__builtin_types_compatible_p(__typeof__(t), unsigned char *) || \
__builtin_types_compatible_p(__typeof__(t), int8_t *) || \
__builtin_types_compatible_p(__typeof__(t), uint8_t *)) \
self->hash = _JOIN(A, _default_charp_hash); \
}
#elif (defined POD && !defined TK) || (defined PODK && defined TK)
# define __set_charp_hash(self, t) self->hash = _JOIN(A, _default_charp_hash);
#else
# define __set_charp_hash(self, t) {}
#endif

#endif // USET,UMAP

// default integral methods (POD defines only the value)
#if defined(POD) && !defined(NOT_INTEGRAL)

static inline int _JOIN(A, _default_integral_compare3)(T *a, T *b)
Expand All @@ -34,104 +102,122 @@ static inline int _JOIN(A, _default_integral_equal)(T *a, T *b)
*/
}

#if defined CTL_USET || defined CTL_UMAP
static inline size_t _JOIN(A, _default_integral_hash)(T *a)
{
return (size_t)*a;
}
#endif // USET,UMAP

#include <string.h>

#if defined str || defined u8string || defined charp || defined u8ident || defined ucharp

static inline size_t _JOIN(A, _default_string_hash)(T *key)
{
size_t h;
/* FNV1a, not wyhash */
h = 2166136261u;
for (unsigned i = 0; i < strlen((char *)key); i++)
{
h ^= (unsigned char)key[i];
h *= 16777619;
}
return h;
}

#endif

#define CTL_STRINGIFY_HELPER(n) #n
#define CTL_STRINGIFY(n) CTL_STRINGIFY_HELPER(n)
#define _strEQcc(s1c, s2c) !strcmp(s1c "", s2c "")

static inline bool _JOIN(A, _type_is_integral)(void)
// unused
static inline bool _JOIN(A, _type_is_integral)(const char* typ)
{
return _strEQcc(CTL_STRINGIFY(T), "int") || _strEQcc(CTL_STRINGIFY(T), "long") ||
_strEQcc(CTL_STRINGIFY(T), "bool") || _strEQcc(CTL_STRINGIFY(T), "char") ||
_strEQcc(CTL_STRINGIFY(T), "short") || _strEQcc(CTL_STRINGIFY(T), "float") ||
_strEQcc(CTL_STRINGIFY(T), "double") || _strEQcc(CTL_STRINGIFY(T), "char8_t") ||
_strEQcc(CTL_STRINGIFY(T), "wchar_t") || _strEQcc(CTL_STRINGIFY(T), "char16_t") ||
_strEQcc(CTL_STRINGIFY(T), "char32_t") || _strEQcc(CTL_STRINGIFY(T), "long_double") ||
_strEQcc(CTL_STRINGIFY(T), "long_long") || _strEQcc(CTL_STRINGIFY(T), "int8_t") ||
_strEQcc(CTL_STRINGIFY(T), "uint8_t") || _strEQcc(CTL_STRINGIFY(T), "uint16_t") ||
_strEQcc(CTL_STRINGIFY(T), "uint32_t") || _strEQcc(CTL_STRINGIFY(T), "uint64_t") ||
_strEQcc(CTL_STRINGIFY(T), "int16_t") || _strEQcc(CTL_STRINGIFY(T), "int32_t") ||
_strEQcc(CTL_STRINGIFY(T), "int64_t") || _strEQcc(CTL_STRINGIFY(T), "unsigned_int") ||
_strEQcc(CTL_STRINGIFY(T), "unsigned_long") || _strEQcc(CTL_STRINGIFY(T), "unsigned_long_long") ||
_strEQcc(CTL_STRINGIFY(T), "unsigned_char") ||
return _strEQ(typ, "int") || _strEQ(typ, "long") ||
_strEQ(typ, "bool") || _strEQ(typ, "char") ||
_strEQ(typ, "short") || _strEQ(typ, "float") ||
_strEQ(typ, "double") || _strEQ(typ, "char8_t") ||
_strEQ(typ, "wchar_t") || _strEQ(typ, "char16_t") ||
_strEQ(typ, "char32_t") || _strEQ(typ, "long_double") ||
_strEQ(typ, "long_long") || _strEQ(typ, "int8_t") ||
_strEQ(typ, "uint8_t") || _strEQ(typ, "uint16_t") ||
_strEQ(typ, "uint32_t") || _strEQ(typ, "uint64_t") ||
_strEQ(typ, "int16_t") || _strEQ(typ, "int32_t") ||
_strEQ(typ, "int64_t") || _strEQ(typ, "unsigned_int") ||
_strEQ(typ, "unsigned_long") || _strEQ(typ, "unsigned_long_long") ||
_strEQ(typ, "unsigned_char") ||
/* and some common abbrevations */
_strEQcc(CTL_STRINGIFY(T), "uchar") || _strEQcc(CTL_STRINGIFY(T), "uint") ||
_strEQcc(CTL_STRINGIFY(T), "ulong") || _strEQcc(CTL_STRINGIFY(T), "ldbl") ||
_strEQcc(CTL_STRINGIFY(T), "llong");
_strEQ(typ, "uchar") || _strEQ(typ, "uint") ||
_strEQ(typ, "ulong") || _strEQ(typ, "ldbl") ||
_strEQ(typ, "llong");
}

// not C++
#ifndef __cplusplus
#define __set_str_hash(self, t) \
{ \
typeof(t) tmp = (x); \
if (__builtin_types_compatible_p(typeof(t), char *)) \
self->hash = _JOIN(A, _default_string_hash); \
else if (__builtin_types_compatible_p(typeof(t), unsigned char *)) \
self->hash = _JOIN(A, _default_string_hash); \
}
#else
#define __set_str_hash(self, t) self->hash = _JOIN(A, _default_string_hash)
#endif

static inline void _JOIN(A, _set_default_methods)(A *self)
{
#if !defined CTL_STR
#if defined str || defined u8string || defined charp || defined u8ident || defined ucharp
#ifdef TK
if (_JOIN(A, _type_is_string)(CTL_STRINGIFY(TK)))
{
#ifdef CTL_USET
# if defined CTL_UMAP
if (!self->hash)
__set_str_hash(self, T);
#else
__set_charp_hash(self, TK)
# else
if (!self->compare)
# if defined CTL_STR
self->compare = str_key_compare;
#endif
# else
self->compare = (JOIN(A, compare_fn)) _JOIN(A, _default_charp_compare);
# endif // STR
# endif
if (!self->equal)
# if defined CTL_STR
self->equal = str_equal;
# else
self->equal = (JOIN(A, equal_fn)) _JOIN(A, _default_charp_equal);
# endif // STR
}
else
#endif
#endif
#ifdef CTL_USET
if (!self->hash)
self->hash = _JOIN(A, _default_integral_hash);
#else

#else // !TK

# if defined CTL_USET || defined CTL_UMAP
if (!self->hash)
self->hash = _JOIN(A, _default_integral_hash);
# else
if (!self->compare)
self->compare = _JOIN(A, _default_integral_compare);
#endif
# endif // USET,UMAP
if (!self->equal)
self->equal = _JOIN(A, _default_integral_equal);

#endif // TK
}

#else
#else // defined(POD) && !defined(NOT_INTEGRAL)
// default string methods

// non-integral types have no default methods. you need to set
// non-integral string types
static inline void _JOIN(A, _set_default_methods)(A *self)
{
(void)self;

#ifdef TK
if (_JOIN(A, _type_is_string)(CTL_STRINGIFY(TK)))
{
# if defined CTL_UMAP
if (!self->hash)
__set_charp_hash(self, T)
# elif defined CTL_STR
if (!self->compare)
self->compare = str_key_compare;
# else
if (!self->compare)
self->compare = (JOIN(A, compare_fn)) _JOIN(A, _default_charp_compare);
# endif // UMAP,STR
if (!self->equal)
# if defined CTL_STR
self->equal = str_equal;
# else
self->equal = (JOIN(A, equal_fn)) _JOIN(A, _default_charp_equal);
# endif // STR
}
#endif // TK

if (_JOIN(A, _type_is_string)(CTL_STRINGIFY(T)))
{
#if defined CTL_USET || defined CTL_UMAP
if (!self->hash)
__set_charp_hash(self, T)
#elif defined CTL_STR
if (!self->compare)
self->compare = str_key_compare;
# else
if (!self->compare)
self->compare = (JOIN(A, compare_fn)) _JOIN(A, _default_charp_compare);
#endif // USET,STR
if (!self->equal)
# if defined CTL_STR
self->equal = str_equal;
# else
self->equal = (JOIN(A, equal_fn)) _JOIN(A, _default_charp_equal);
# endif // STR
}
}

#endif
#endif // defined(POD) && !defined(NOT_INTEGRAL)
4 changes: 2 additions & 2 deletions ctl/bits/iterators.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@
#error "Template type T undefined for <ctl/bits/iterators.h>"
#endif

#if defined CTL_LIST || defined CTL_SET || defined CTL_MAP || \
defined CTL_USET || defined CTL_UMAP || defined CTL_SLIST
#if (defined CTL_LIST || defined CTL_SET || defined CTL_MAP || \
defined CTL_USET || defined CTL_UMAP || defined CTL_SLIST) && !defined(CTL_HMAP)

#define CTL_B_ITER
//# undef IT
Expand Down
2 changes: 0 additions & 2 deletions ctl/list.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,6 @@ typedef struct I

#include <ctl/bits/iterators.h>

typedef int (*JOIN(A, compare_fn))(T *, T *);

static inline T *JOIN(A, front)(A *self)
{
return self->head ? &self->head->value : NULL;
Expand Down
16 changes: 14 additions & 2 deletions ctl/map.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@
SPDX-License-Identifier: MIT */

#ifndef T
#error "Template struct type T undefined for <ctl/map.h>"
#error "Template value type T undefined for <ctl/map.h>"
#endif
#ifndef TK
#error "Template key type TK undefined for <ctl/map.h>"
#endif

#include <ctl/ctl.h>
Expand All @@ -11,9 +14,15 @@

#define CTL_MAP
#define HOLD
#define C map
#define set map
#define _set _map
#define A JOIN(map, TK)

static inline TK JOIN(A, implicit_copy_key)(TK *key)
{
return *key;
}

#include <ctl/set.h>

static inline I JOIN(A, insert_or_assign)(A *self, T key)
Expand Down Expand Up @@ -117,8 +126,11 @@ static inline I JOIN(A, insert_or_assign_found)(A *self, T key, int *foundp)
#undef _set
#undef set
#undef T
#undef TK
#undef A
#undef B
#undef I
#undef GI
#undef POD
#undef PODK
#undef CTL_MAP
Loading

0 comments on commit be5aea2

Please sign in to comment.