Skip to content

Commit de00f80

Browse files
added ctl
1 parent e0fc4b2 commit de00f80

File tree

9 files changed

+1909
-0
lines changed

9 files changed

+1909
-0
lines changed

ctl/Makefile

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
all:run-test
2+
3+
run-test:test.c ../common.c
4+
$(CC) -O3 -Wall -I. $< -o $@
5+
6+
clean:
7+
rm -fr run-test

ctl/ctl/bits/container.h

Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
/* Common bits for all containers.
2+
SPDX-License-Identifier: MIT */
3+
4+
// DO NOT STANDALONE INCLUDE.
5+
#if !defined CTL_LIST && \
6+
!defined CTL_SLIST && \
7+
!defined CTL_SET && \
8+
!defined CTL_USET && \
9+
!defined CTL_VEC && \
10+
!defined CTL_ARR && \
11+
!defined CTL_DEQ
12+
#error "No CTL container defined for <ctl/bits/container.h>"
13+
#endif
14+
15+
// FIXME once per A
16+
//#ifndef CAT(HAVE, JOIN(T, it_vtable))
17+
//#define CAT(HAVE, JOIN(T, it_vtable))
18+
//static const struct JOIN(I, vtable_t)
19+
//JOIN(I, vtable_g) =
20+
// { JOIN(I, next), JOIN(I, ref), JOIN(I, done) };
21+
//#endif
22+
23+
#include <stdbool.h>
24+
25+
#if !defined(CTL_ARR) && !defined(CTL_SLIST)
26+
static inline int JOIN(A, empty)(A* self)
27+
{
28+
return self->size == 0;
29+
}
30+
31+
static inline size_t JOIN(A, size)(A *self)
32+
{
33+
return self->size;
34+
}
35+
36+
static inline size_t JOIN(A, max_size)(void)
37+
{
38+
return 4294967296 / sizeof(T); // 32bit at most. avoid DDOS
39+
}
40+
#endif
41+
42+
/*
43+
static inline I
44+
JOIN(I, each)(A* a)
45+
{
46+
return JOIN(A, empty)(a)
47+
? JOIN(I, range)(a, 0, 0)
48+
: JOIN(I, range)(a, JOIN(A, begin)(a), JOIN(A, end)(a));
49+
}
50+
*/
51+
52+
static inline T JOIN(A, implicit_copy)(T *self)
53+
{
54+
return *self;
55+
}
56+
57+
// not valid for uset, str
58+
#if !defined(CTL_USET) && !defined(CTL_STR) && !defined(CTL_SLIST)
59+
static inline int JOIN(A, equal)(A* self, A* other)
60+
{
61+
if (JOIN(A, size)(self) != JOIN(A, size)(other))
62+
return 0;
63+
I i1 = JOIN(A, begin)(self);
64+
I i2 = JOIN(A, begin)(other);
65+
while (!JOIN(I, done)(&i1) && !JOIN(I, done)(&i2))
66+
{
67+
T *r1 = JOIN(I, ref)(&i1);
68+
T *r2 = JOIN(I, ref)(&i2);
69+
if (self->equal)
70+
{
71+
if (!self->equal(r1, r2))
72+
return 0;
73+
}
74+
else
75+
{
76+
// this works with 2-way and 3-way compare
77+
if (self->compare(r1, r2) || self->compare(r2, r1))
78+
return 0;
79+
}
80+
JOIN(I, next)(&i1);
81+
JOIN(I, next)(&i2);
82+
}
83+
return 1;
84+
}
85+
#endif
86+
87+
// _set_default_methods
88+
#include <ctl/bits/integral.h>
89+
90+
#if !defined(CTL_USET)
91+
static inline int JOIN(A, _equal)(A *self, T *a, T *b)
92+
{
93+
CTL_ASSERT_EQUAL
94+
if (self->equal)
95+
return self->equal(a, b);
96+
else
97+
return !self->compare(a, b) && !self->compare(b, a);
98+
}
99+
#endif
100+
101+
// If parent, include only for the child later.
102+
// parents are vec: str, pqu. deq: queue, stack. set: map, uset: umap
103+
// ignore str: u8str, u8id for now.
104+
#undef _IS_PARENT_CHILD_FOLLOWS
105+
#if defined CTL_VEC && (defined CTL_PQU || defined CTL_STR || defined CTL_U8STR)
106+
//#pragma message "vec child"
107+
#define _IS_PARENT_CHILD_FOLLOWS
108+
#endif
109+
#if defined CTL_DEQ && (defined CTL_QUEUE || defined CTL_STACK)
110+
//#pragma message "deq child"
111+
#define _IS_PARENT_CHILD_FOLLOWS
112+
#endif
113+
#if defined CTL_SET && defined CTL_MAP
114+
//#pragma message "set child"
115+
#define _IS_PARENT_CHILD_FOLLOWS
116+
#endif
117+
#if defined CTL_USET && defined CTL_UMAP
118+
//#pragma message "uset child"
119+
#define _IS_PARENT_CHILD_FOLLOWS
120+
#endif
121+
122+
#if !defined _IS_PARENT_CHILD_FOLLOWS && defined INCLUDE_ALGORITHM
123+
#include <ctl/algorithm.h>
124+
//#else
125+
//# pragma message "_IS_PARENT_CHILD_FOLLOWS defined"
126+
#endif
127+
#undef _IS_PARENT_CHILD_FOLLOWS

ctl/ctl/bits/integral.h

Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
/* Type utilities, to apply default equal, compare, hash methods for intergral types.
2+
See MIT LICENSE.
3+
*/
4+
5+
// is_integral type utilities, to make equal and compare optional for simple POD types
6+
/*
7+
#define _define_integral_compare(T) \
8+
static inline int _##T##_compare(T* a, T* b) { return *a < *b; } \
9+
static inline int _##T##_equal(T* a, T* b) { \
10+
return !_##T##_compare(a, b) && !_##T##_compare(b, a); }
11+
12+
_define_integral_compare(int)
13+
_define_integral_compare(long)
14+
#undef _define_integral_compare
15+
*/
16+
17+
#if defined(POD) && !defined(NOT_INTEGRAL)
18+
19+
static inline int _JOIN(A, _default_integral_compare3)(T *a, T *b)
20+
{
21+
return *a > *b ? 1 : *a < *b ? -1 : 0;
22+
}
23+
static inline int _JOIN(A, _default_integral_compare)(T *a, T *b)
24+
{
25+
return *a < *b;
26+
}
27+
28+
static inline int _JOIN(A, _default_integral_equal)(T *a, T *b)
29+
{
30+
return *a == *b;
31+
// or the slow 2x compare, which is used in _equal.
32+
/*return _JOIN(A, _default_integral_compare)(a, b) == 0 &&
33+
_JOIN(A, _default_integral_compare)(b, a) == 0;
34+
*/
35+
}
36+
37+
static inline size_t _JOIN(A, _default_integral_hash)(T *a)
38+
{
39+
return (size_t)*a;
40+
}
41+
42+
#include <string.h>
43+
44+
#if defined str || defined u8string || defined charp || defined u8ident || defined ucharp
45+
46+
static inline size_t _JOIN(A, _default_string_hash)(T *key)
47+
{
48+
size_t h;
49+
/* FNV1a, not wyhash */
50+
h = 2166136261u;
51+
for (unsigned i = 0; i < strlen((char *)key); i++)
52+
{
53+
h ^= (unsigned char)key[i];
54+
h *= 16777619;
55+
}
56+
return h;
57+
}
58+
59+
#endif
60+
61+
#define CTL_STRINGIFY_HELPER(n) #n
62+
#define CTL_STRINGIFY(n) CTL_STRINGIFY_HELPER(n)
63+
#define _strEQcc(s1c, s2c) !strcmp(s1c "", s2c "")
64+
65+
static inline bool _JOIN(A, _type_is_integral)(void)
66+
{
67+
return _strEQcc(CTL_STRINGIFY(T), "int") || _strEQcc(CTL_STRINGIFY(T), "long") ||
68+
_strEQcc(CTL_STRINGIFY(T), "bool") || _strEQcc(CTL_STRINGIFY(T), "char") ||
69+
_strEQcc(CTL_STRINGIFY(T), "short") || _strEQcc(CTL_STRINGIFY(T), "float") ||
70+
_strEQcc(CTL_STRINGIFY(T), "double") || _strEQcc(CTL_STRINGIFY(T), "char8_t") ||
71+
_strEQcc(CTL_STRINGIFY(T), "wchar_t") || _strEQcc(CTL_STRINGIFY(T), "char16_t") ||
72+
_strEQcc(CTL_STRINGIFY(T), "char32_t") || _strEQcc(CTL_STRINGIFY(T), "long_double") ||
73+
_strEQcc(CTL_STRINGIFY(T), "long_long") || _strEQcc(CTL_STRINGIFY(T), "int8_t") ||
74+
_strEQcc(CTL_STRINGIFY(T), "uint8_t") || _strEQcc(CTL_STRINGIFY(T), "uint16_t") ||
75+
_strEQcc(CTL_STRINGIFY(T), "uint32_t") || _strEQcc(CTL_STRINGIFY(T), "uint64_t") ||
76+
_strEQcc(CTL_STRINGIFY(T), "int16_t") || _strEQcc(CTL_STRINGIFY(T), "int32_t") ||
77+
_strEQcc(CTL_STRINGIFY(T), "int64_t") || _strEQcc(CTL_STRINGIFY(T), "unsigned_int") ||
78+
_strEQcc(CTL_STRINGIFY(T), "unsigned_long") || _strEQcc(CTL_STRINGIFY(T), "unsigned_long_long") ||
79+
_strEQcc(CTL_STRINGIFY(T), "unsigned_char") ||
80+
/* and some common abbrevations */
81+
_strEQcc(CTL_STRINGIFY(T), "uchar") || _strEQcc(CTL_STRINGIFY(T), "uint") ||
82+
_strEQcc(CTL_STRINGIFY(T), "ulong") || _strEQcc(CTL_STRINGIFY(T), "ldbl") ||
83+
_strEQcc(CTL_STRINGIFY(T), "llong");
84+
}
85+
86+
// not C++
87+
#ifndef __cplusplus
88+
#define __set_str_hash(self, t) \
89+
{ \
90+
typeof(t) tmp = (x); \
91+
if (__builtin_types_compatible_p(typeof(t), char *)) \
92+
self->hash = _JOIN(A, _default_string_hash); \
93+
else if (__builtin_types_compatible_p(typeof(t), unsigned char *)) \
94+
self->hash = _JOIN(A, _default_string_hash); \
95+
}
96+
#else
97+
#define __set_str_hash(self, t) self->hash = _JOIN(A, _default_string_hash)
98+
#endif
99+
100+
static inline void _JOIN(A, _set_default_methods)(A *self)
101+
{
102+
#if !defined CTL_STR
103+
#if defined str || defined u8string || defined charp || defined u8ident || defined ucharp
104+
{
105+
#ifdef CTL_USET
106+
if (!self->hash)
107+
__set_str_hash(self, T);
108+
#else
109+
if (!self->compare)
110+
self->compare = str_key_compare;
111+
#endif
112+
if (!self->equal)
113+
self->equal = str_equal;
114+
}
115+
else
116+
#endif
117+
#endif
118+
#ifdef CTL_USET
119+
if (!self->hash)
120+
self->hash = _JOIN(A, _default_integral_hash);
121+
#else
122+
if (!self->compare)
123+
self->compare = _JOIN(A, _default_integral_compare);
124+
#endif
125+
if (!self->equal)
126+
self->equal = _JOIN(A, _default_integral_equal);
127+
}
128+
129+
#else
130+
131+
// non-integral types have no default methods. you need to set
132+
static inline void _JOIN(A, _set_default_methods)(A *self)
133+
{
134+
(void)self;
135+
}
136+
137+
#endif

ctl/ctl/bits/iterator_vtable.h

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
/*
2+
Copyright 2021 Reini Urban
3+
See MIT LICENSE
4+
*/
5+
6+
#ifndef T
7+
#error "Template type T undefined for <ctl/bits/iterator_vtable.h>"
8+
#endif
9+
10+
/* 2 basic types of iterators. All must have the same size, so that we can
11+
* struct copy them easily. */
12+
#define CTL_T_ITER_FIELDS \
13+
struct JOIN(I, vtable_t) vtable; \
14+
T *ref; /* will be removed later */ \
15+
A *container; \
16+
T *end; \
17+
T *_padding
18+
19+
#define CTL_B_ITER_FIELDS \
20+
struct JOIN(I, vtable_t) vtable; \
21+
T *ref; /* will be removed later */ \
22+
A *container; \
23+
B *end; \
24+
B *node
25+
26+
#define CTL_USET_ITER_FIELDS \
27+
struct JOIN(I, vtable_t) vtable; \
28+
T *ref; /* will be removed later */ \
29+
A *container; \
30+
B **buckets; /* the chain. no end range needed for uset */ \
31+
B *node
32+
33+
#define CTL_DEQ_ITER_FIELDS \
34+
struct JOIN(I, vtable_t) vtable; \
35+
T *ref; /* will be removed later */ \
36+
A *container; \
37+
uintptr_t end; \
38+
uintptr_t index
39+
40+
struct I;
41+
42+
// Iterator vtable
43+
typedef struct JOIN(I, vtable_t)
44+
{
45+
void (*next)(struct I *);
46+
T *(*ref)(struct I *);
47+
int (*done)(struct I *);
48+
} JOIN(I, vtable_t);

0 commit comments

Comments
 (0)