summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorTyge Lovset <[email protected]>2023-03-31 22:08:07 +0200
committerTyge Lovset <[email protected]>2023-03-31 22:08:07 +0200
commit5693ae9ae0d1a18627ba540e0240da010b282296 (patch)
treeccb0dbe519d9a27fc944446ecc1a574cd9d86fcc
parent56c394ede691143a32d53f4094df37dc49dc0a29 (diff)
downloadSTC-modified-5693ae9ae0d1a18627ba540e0240da010b282296.tar.gz
STC-modified-5693ae9ae0d1a18627ba540e0240da010b282296.zip
Added stc/extend.h: A generalized way to type-safely extend a container with new members which can be accessed from the template parameters. See examples/functor.c
-rw-r--r--README.md2
-rw-r--r--include/stc/carc.h18
-rw-r--r--include/stc/cbox.h18
-rw-r--r--include/stc/cdeq.h10
-rw-r--r--include/stc/clist.h6
-rw-r--r--include/stc/cmap.h10
-rw-r--r--include/stc/cpque.h2
-rw-r--r--include/stc/csmap.h2
-rw-r--r--include/stc/cstack.h2
-rw-r--r--include/stc/cvec.h12
-rw-r--r--include/stc/extend.h65
-rw-r--r--include/stc/priv/template.h4
-rw-r--r--misc/examples/functor.c47
-rw-r--r--misc/examples/new_list.c4
-rw-r--r--misc/examples/new_map.c2
-rw-r--r--misc/examples/new_queue.c2
-rw-r--r--misc/examples/new_smap.c2
-rw-r--r--misc/examples/new_vec.c4
18 files changed, 135 insertions, 77 deletions
diff --git a/README.md b/README.md
index b5f9ceb7..3f985b7a 100644
--- a/README.md
+++ b/README.md
@@ -518,7 +518,7 @@ typedef struct Dataset {
...
// Implementation
-#define i_opt c_is_forward // flag that the container was forward declared.
+#define i_is_forward // flag that the container was forward declared.
#define i_val struct Point
#define i_tag pnt
#include <stc/cstack.h>
diff --git a/include/stc/carc.h b/include/stc/carc.h
index 02bbaf52..5d38d2e7 100644
--- a/include/stc/carc.h
+++ b/include/stc/carc.h
@@ -90,7 +90,7 @@ typedef i_keyraw _cx_raw;
#define _i_atomic_inc(v) (void)(++*(v))
#define _i_atomic_dec_and_test(v) !(--*(v))
#endif
-#if !c_option(c_is_forward)
+#ifndef i_is_forward
_cx_deftypes(_c_carc_types, _cx_self, i_key);
#endif
struct _cx_memb(_rep_) { catomic_long counter; i_key value; };
@@ -177,8 +177,8 @@ STC_INLINE void _cx_memb(_assign)(_cx_self* self, _cx_self ptr) {
STC_INLINE int _cx_memb(_raw_cmp)(const _cx_raw* rx, const _cx_raw* ry)
{ return i_cmp(rx, ry); }
-STC_INLINE int _cx_memb(_cmp)(const _cx_self* x, const _cx_self* y) {
- _cx_raw rx = i_keyto(x->get), ry = i_keyto(y->get);
+STC_INLINE int _cx_memb(_cmp)(const _cx_self* self, const _cx_self* other) {
+ _cx_raw rx = i_keyto(self->get), ry = i_keyto(other->get);
return i_cmp((&rx), (&ry));
}
#endif
@@ -187,24 +187,24 @@ STC_INLINE int _cx_memb(_cmp)(const _cx_self* x, const _cx_self* y) {
STC_INLINE bool _cx_memb(_raw_eq)(const _cx_raw* rx, const _cx_raw* ry)
{ return i_eq(rx, ry); }
-STC_INLINE bool _cx_memb(_eq)(const _cx_self* x, const _cx_self* y) {
- _cx_raw rx = i_keyto(x->get), ry = i_keyto(y->get);
+STC_INLINE bool _cx_memb(_eq)(const _cx_self* self, const _cx_self* other) {
+ _cx_raw rx = i_keyto(self->get), ry = i_keyto(other->get);
return i_eq((&rx), (&ry));
}
#elif !defined i_no_cmp
STC_INLINE bool _cx_memb(_raw_eq)(const _cx_raw* rx, const _cx_raw* ry)
{ return i_cmp(rx, ry) == 0; }
-STC_INLINE bool _cx_memb(_eq)(const _cx_self* x, const _cx_self* y)
- { return _cx_memb(_cmp)(x, y) == 0; }
+STC_INLINE bool _cx_memb(_eq)(const _cx_self* self, const _cx_self* other)
+ { return _cx_memb(_cmp)(self, other) == 0; }
#endif
#ifndef i_no_hash
STC_INLINE uint64_t _cx_memb(_raw_hash)(const _cx_raw* rx)
{ return i_hash(rx); }
-STC_INLINE uint64_t _cx_memb(_hash)(const _cx_self* x)
- { _cx_raw rx = i_keyto(x->get); return i_hash((&rx)); }
+STC_INLINE uint64_t _cx_memb(_hash)(const _cx_self* self)
+ { _cx_raw rx = i_keyto(self->get); return i_hash((&rx)); }
#endif
#undef _i_eq
diff --git a/include/stc/cbox.h b/include/stc/cbox.h
index 641fcbfc..6cc86c6f 100644
--- a/include/stc/cbox.h
+++ b/include/stc/cbox.h
@@ -76,7 +76,7 @@ int main() {
#include "priv/template.h"
typedef i_keyraw _cx_raw;
-#if !c_option(c_is_forward)
+#ifndef i_is_forward
_cx_deftypes(_c_cbox_types, _cx_self, i_key);
#endif
@@ -163,8 +163,8 @@ STC_INLINE void _cx_memb(_assign)(_cx_self* self, _cx_self* moved) {
STC_INLINE int _cx_memb(_raw_cmp)(const _cx_raw* rx, const _cx_raw* ry)
{ return i_cmp(rx, ry); }
-STC_INLINE int _cx_memb(_cmp)(const _cx_self* x, const _cx_self* y) {
- _cx_raw rx = i_keyto(x->get), ry = i_keyto(y->get);
+STC_INLINE int _cx_memb(_cmp)(const _cx_self* self, const _cx_self* other) {
+ _cx_raw rx = i_keyto(self->get), ry = i_keyto(other->get);
return i_cmp((&rx), (&ry));
}
#endif
@@ -173,24 +173,24 @@ STC_INLINE int _cx_memb(_cmp)(const _cx_self* x, const _cx_self* y) {
STC_INLINE bool _cx_memb(_raw_eq)(const _cx_raw* rx, const _cx_raw* ry)
{ return i_eq(rx, ry); }
-STC_INLINE bool _cx_memb(_eq)(const _cx_self* x, const _cx_self* y) {
- _cx_raw rx = i_keyto(x->get), ry = i_keyto(y->get);
+STC_INLINE bool _cx_memb(_eq)(const _cx_self* self, const _cx_self* other) {
+ _cx_raw rx = i_keyto(self->get), ry = i_keyto(other->get);
return i_eq((&rx), (&ry));
}
#elif !defined i_no_cmp
STC_INLINE bool _cx_memb(_raw_eq)(const _cx_raw* rx, const _cx_raw* ry)
{ return i_cmp(rx, ry) == 0; }
-STC_INLINE bool _cx_memb(_eq)(const _cx_self* x, const _cx_self* y)
- { return _cx_memb(_cmp)(x, y) == 0; }
+STC_INLINE bool _cx_memb(_eq)(const _cx_self* self, const _cx_self* other)
+ { return _cx_memb(_cmp)(self, other) == 0; }
#endif
#ifndef i_no_hash
STC_INLINE uint64_t _cx_memb(_raw_hash)(const _cx_raw* rx)
{ return i_hash(rx); }
-STC_INLINE uint64_t _cx_memb(_hash)(const _cx_self* x)
- { _cx_raw rx = i_keyto(x->get); return i_hash((&rx)); }
+STC_INLINE uint64_t _cx_memb(_hash)(const _cx_self* self)
+ { _cx_raw rx = i_keyto(self->get); return i_hash((&rx)); }
#endif
#undef _i_eq
diff --git a/include/stc/cdeq.h b/include/stc/cdeq.h
index 09c0a7f8..a032722b 100644
--- a/include/stc/cdeq.h
+++ b/include/stc/cdeq.h
@@ -36,7 +36,7 @@
#endif
#include "priv/template.h"
-#if !c_option(c_is_forward)
+#ifndef i_is_forward
_cx_deftypes(_c_cdeq_types, _cx_self, i_key);
#endif
typedef i_keyraw _cx_raw;
@@ -196,10 +196,10 @@ _cx_memb(_get_mut)(_cx_self* self, _cx_raw raw)
{ return (_cx_value *) _cx_memb(_get)(self, raw); }
STC_INLINE bool
-_cx_memb(_eq)(const _cx_self* x, const _cx_self* y) {
- if (x->_len != y->_len) return false;
- for (intptr_t i = 0; i < x->_len; ++i) {
- const _cx_raw _rx = i_keyto(x->data+i), _ry = i_keyto(y->data+i);
+_cx_memb(_eq)(const _cx_self* self, const _cx_self* other) {
+ if (self->_len != other->_len) return false;
+ for (intptr_t i = 0; i < self->_len; ++i) {
+ const _cx_raw _rx = i_keyto(self->data+i), _ry = i_keyto(other->data+i);
if (!(i_eq((&_rx), (&_ry)))) return false;
}
return true;
diff --git a/include/stc/clist.h b/include/stc/clist.h
index fa26fd65..ca02ae3c 100644
--- a/include/stc/clist.h
+++ b/include/stc/clist.h
@@ -82,7 +82,7 @@
#endif
#include "priv/template.h"
-#if !c_option(c_is_forward)
+#ifndef i_is_forward
_cx_deftypes(_c_clist_types, _cx_self, i_key);
#endif
_cx_deftypes(_c_clist_complete_types, _cx_self, dummy);
@@ -204,8 +204,8 @@ _cx_memb(_get_mut)(_cx_self* self, _cx_raw val) {
return _cx_memb(_find_in)(_cx_memb(_begin)(self), _cx_memb(_end)(self), val).ref;
}
-STC_INLINE bool _cx_memb(_eq)(const _cx_self* x, const _cx_self* y) {
- _cx_iter i = _cx_memb(_begin)(x), j = _cx_memb(_begin)(y);
+STC_INLINE bool _cx_memb(_eq)(const _cx_self* self, const _cx_self* other) {
+ _cx_iter i = _cx_memb(_begin)(self), j = _cx_memb(_begin)(other);
for (; i.ref && j.ref; _cx_memb(_next)(&i), _cx_memb(_next)(&j)) {
const _cx_raw _rx = i_keyto(i.ref), _ry = i_keyto(j.ref);
if (!(i_eq((&_rx), (&_ry)))) return false;
diff --git a/include/stc/cmap.h b/include/stc/cmap.h
index c840523f..437a5982 100644
--- a/include/stc/cmap.h
+++ b/include/stc/cmap.h
@@ -82,7 +82,7 @@ typedef struct { int64_t idx; uint8_t hx; } chash_bucket_t;
#define _i_size i_ssize
#endif
#include "priv/template.h"
-#if !c_option(c_is_forward)
+#ifndef i_is_forward
_cx_deftypes(_c_chash_types, _cx_self, i_key, i_val, i_ssize, _i_MAP_ONLY, _i_SET_ONLY);
#endif
@@ -277,11 +277,11 @@ _cx_memb(_erase_at)(_cx_self* self, _cx_iter it) {
}
STC_INLINE bool
-_cx_memb(_eq)(const _cx_self* m1, const _cx_self* m2) {
- if (_cx_memb(_size)(m1) != _cx_memb(_size)(m2)) return false;
- for (_cx_iter i = _cx_memb(_begin)(m1); i.ref; _cx_memb(_next)(&i)) {
+_cx_memb(_eq)(const _cx_self* self, const _cx_self* other) {
+ if (_cx_memb(_size)(self) != _cx_memb(_size)(other)) return false;
+ for (_cx_iter i = _cx_memb(_begin)(self); i.ref; _cx_memb(_next)(&i)) {
const _cx_rawkey _raw = i_keyto(_i_keyref(i.ref));
- if (!_cx_memb(_contains)(m2, _raw)) return false;
+ if (!_cx_memb(_contains)(other, _raw)) return false;
}
return true;
}
diff --git a/include/stc/cpque.h b/include/stc/cpque.h
index 00eaa49e..f3ca7081 100644
--- a/include/stc/cpque.h
+++ b/include/stc/cpque.h
@@ -32,7 +32,7 @@
#endif
#include "priv/template.h"
-#if !c_option(c_is_forward)
+#ifndef i_is_forward
_cx_deftypes(_c_cpque_types, _cx_self, i_key);
#endif
typedef i_keyraw _cx_raw;
diff --git a/include/stc/csmap.h b/include/stc/csmap.h
index 50593ba3..d0a877c4 100644
--- a/include/stc/csmap.h
+++ b/include/stc/csmap.h
@@ -80,7 +80,7 @@ int main(void) {
#define _i_size i_ssize
#endif
#include "priv/template.h"
-#if !c_option(c_is_forward)
+#ifndef i_is_forward
_cx_deftypes(_c_aatree_types, _cx_self, i_key, i_val, i_ssize, _i_MAP_ONLY, _i_SET_ONLY);
#endif
diff --git a/include/stc/cstack.h b/include/stc/cstack.h
index f0c930e5..0f855dc9 100644
--- a/include/stc/cstack.h
+++ b/include/stc/cstack.h
@@ -33,7 +33,7 @@
#endif
#include "priv/template.h"
-#if !c_option(c_is_forward)
+#ifndef i_is_forward
#ifdef i_capacity
#define i_no_clone
_cx_deftypes(_c_cstack_fixed, _cx_self, i_key, i_capacity);
diff --git a/include/stc/cvec.h b/include/stc/cvec.h
index 8f35e5fc..4fe5ddab 100644
--- a/include/stc/cvec.h
+++ b/include/stc/cvec.h
@@ -39,7 +39,7 @@ struct MyStruct {
#include <stc/cvec.h>
#define i_key int
-#define i_opt c_is_forward // forward declared
+#define i_is_forward // forward declared
#define i_tag i32
#include <stc/cvec.h>
@@ -73,7 +73,7 @@ int main() {
#endif
#include "priv/template.h"
-#if !c_option(c_is_forward)
+#ifndef i_is_forward
_cx_deftypes(_c_cvec_types, _cx_self, i_key);
#endif
typedef i_keyraw _cx_raw;
@@ -234,10 +234,10 @@ _cx_memb(_get_mut)(const _cx_self* self, _cx_raw raw)
{ return (_cx_value*) _cx_memb(_get)(self, raw); }
STC_INLINE bool
-_cx_memb(_eq)(const _cx_self* x, const _cx_self* y) {
- if (x->_len != y->_len) return false;
- for (intptr_t i = 0; i < x->_len; ++i) {
- const _cx_raw _rx = i_keyto(x->data+i), _ry = i_keyto(y->data+i);
+_cx_memb(_eq)(const _cx_self* self, const _cx_self* other) {
+ if (self->_len != other->_len) return false;
+ for (intptr_t i = 0; i < self->_len; ++i) {
+ const _cx_raw _rx = i_keyto(self->data+i), _ry = i_keyto(other->data+i);
if (!(i_eq((&_rx), (&_ry)))) return false;
}
return true;
diff --git a/include/stc/extend.h b/include/stc/extend.h
new file mode 100644
index 00000000..a3efe02d
--- /dev/null
+++ b/include/stc/extend.h
@@ -0,0 +1,65 @@
+/* MIT License
+ *
+ * Copyright (c) 2023 Tyge Løvset
+ *
+ * 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 <stc/ccommon.h>
+#include <stc/forward.h>
+
+#ifdef i_key_str
+ #define _i_key cstr
+#elif defined i_keyclass
+ #define _i_key i_keyclass
+#elif defined i_keyboxed
+ #define _i_key i_keyboxed
+#elif defined i_key
+ #define _i_key i_key
+#endif
+
+#ifdef i_val_str
+ #define _i_val cstr
+#elif defined i_valclass
+ #define _i_val i_valclass
+#elif defined i_valboxed
+ #define _i_val i_valboxed
+#elif defined i_val
+ #define _i_val i_val
+#endif
+
+#ifdef _i_key
+ c_PASTE(forward_, i_con)(i_type, _i_key, _i_val);
+#else
+ c_PASTE(forward_, i_con)(i_type, _i_val);
+#endif
+
+typedef struct {
+ i_ext;
+ i_type get;
+} c_PASTE(i_type, Ext);
+
+#define c_getcon(cptr) c_container_of(cptr, _cx_memb(Ext), get)
+
+#define i_is_forward
+#define _i_inc <stc/i_con.h>
+#include _i_inc
+#undef _i_inc
+#undef _i_key
+#undef _i_val
+#undef i_con \ No newline at end of file
diff --git a/include/stc/priv/template.h b/include/stc/priv/template.h
index e352f488..d9e38dba 100644
--- a/include/stc/priv/template.h
+++ b/include/stc/priv/template.h
@@ -96,6 +96,9 @@
#endif
#endif
+#if c_option(c_is_forward)
+ #define i_is_forward
+#endif
#if c_option(c_no_cmp)
#define i_no_cmp
#endif
@@ -341,6 +344,7 @@
#undef i_no_hash
#undef i_no_clone
#undef i_no_emplace
+#undef i_is_forward
#undef _i_prefix
#undef _i_expandby
diff --git a/misc/examples/functor.c b/misc/examples/functor.c
index f8074c3a..45158cd1 100644
--- a/misc/examples/functor.c
+++ b/misc/examples/functor.c
@@ -6,35 +6,24 @@
// i_hash/i_eq: has self for cmap and cset types only
#include <stdio.h>
-#include <stdbool.h>
-#include <stc/forward.h>
-#include <stc/algo/crange.h>
-#include <stc/cstr.h>
-// predeclare
-forward_cpque(ipque, int);
-
-struct {
- ipque Q;
- bool (*less)(const int*, const int*);
-} typedef IPQueue;
-
-
-#define i_type ipque
+#define i_type IPQue
#define i_val int
-#define i_opt c_is_forward // needed to avoid re-type-define container type
-#define i_less(x, y) c_container_of(self, IPQueue, Q)->less(x, y)
-#include <stc/cpque.h>
+#define i_ext bool (*less)(const int*, const int*)
+#define i_less(x, y) c_getcon(self)->less(x, y)
+#define i_con cpque
+#include <stc/extend.h>
-void print_queue(const char* name, IPQueue q) {
+void print_queue(const char* name, IPQueExt q) {
// NB: make a clone because there is no way to traverse
// priority_queue's content without erasing the queue.
- IPQueue copy = {ipque_clone(q.Q), q.less};
+ IPQueExt copy = {q.less, IPQue_clone(q.get)};
- for (printf("%s: \t", name); !ipque_empty(&copy.Q); ipque_pop(&copy.Q))
- printf("%d ", *ipque_top(&copy.Q));
+ for (printf("%s: \t", name); !IPQue_empty(&copy.get); IPQue_pop(&copy.get))
+ printf("%d ", *IPQue_top(&copy.get));
puts("");
- ipque_drop(&copy.Q);
+
+ IPQue_drop(&copy.get);
}
static bool int_less(const int* x, const int* y) { return *x < *y; }
@@ -49,21 +38,21 @@ int main()
printf("%d ", data[i]);
puts("");
- IPQueue q1 = {ipque_init(), int_less}; // Max priority queue
- IPQueue minq1 = {ipque_init(), int_greater}; // Min priority queue
- IPQueue q5 = {ipque_init(), int_lambda}; // Using lambda to compare elements.
+ IPQueExt q1 = {int_less}; // Max priority queue
+ IPQueExt minq1 = {int_greater}; // Min priority queue
+ IPQueExt q5 = {int_lambda}; // Using lambda to compare elements.
c_forrange (i, n)
- ipque_push(&q1.Q, data[i]);
+ IPQue_push(&q1.get, data[i]);
print_queue("q1", q1);
c_forrange (i, n)
- ipque_push(&minq1.Q, data[i]);
+ IPQue_push(&minq1.get, data[i]);
print_queue("minq1", minq1);
c_forrange (i, n)
- ipque_push(&q5.Q, data[i]);
+ IPQue_push(&q5.get, data[i]);
print_queue("q5", q5);
- c_drop(ipque, &q1.Q, &minq1.Q, &q5.Q);
+ c_drop(IPQue, &q1.get, &minq1.get, &q5.get);
}
diff --git a/misc/examples/new_list.c b/misc/examples/new_list.c
index eae4b8f5..8b291d34 100644
--- a/misc/examples/new_list.c
+++ b/misc/examples/new_list.c
@@ -11,7 +11,7 @@ typedef struct {
#define i_val int
#define i_tag i32
-#define i_opt c_is_forward
+#define i_is_forward
#include <stc/clist.h>
typedef struct Point { int x, y; } Point;
@@ -22,7 +22,7 @@ int point_cmp(const Point* a, const Point* b) {
#define i_val Point
#define i_cmp point_cmp
-#define i_opt c_is_forward
+#define i_is_forward
#define i_tag pnt
#include <stc/clist.h>
diff --git a/misc/examples/new_map.c b/misc/examples/new_map.c
index 4b02c46a..3a4f934d 100644
--- a/misc/examples/new_map.c
+++ b/misc/examples/new_map.c
@@ -26,7 +26,7 @@ int point_cmp(const Point* a, const Point* b) {
#define i_val int
#define i_cmp point_cmp
#define i_hash c_default_hash
-#define i_opt c_is_forward
+#define i_is_forward
#define i_tag pnt
#include <stc/cmap.h>
diff --git a/misc/examples/new_queue.c b/misc/examples/new_queue.c
index 044e44cb..916f4dbc 100644
--- a/misc/examples/new_queue.c
+++ b/misc/examples/new_queue.c
@@ -12,7 +12,7 @@ int point_cmp(const Point* a, const Point* b) {
}
#define i_val Point
#define i_cmp point_cmp
-#define i_opt c_is_forward
+#define i_is_forward
#define i_tag pnt
#include <stc/cqueue.h>
diff --git a/misc/examples/new_smap.c b/misc/examples/new_smap.c
index d85d5c75..d8245b8b 100644
--- a/misc/examples/new_smap.c
+++ b/misc/examples/new_smap.c
@@ -20,7 +20,7 @@ int point_cmp(const Point* a, const Point* b) {
#define i_key Point
#define i_val int
#define i_cmp point_cmp
-#define i_opt c_is_forward
+#define i_is_forward
#include <stc/csmap.h>
// cstr => cstr map
diff --git a/misc/examples/new_vec.c b/misc/examples/new_vec.c
index 988b78d9..df443b7f 100644
--- a/misc/examples/new_vec.c
+++ b/misc/examples/new_vec.c
@@ -10,7 +10,7 @@ struct MyStruct {
} typedef MyStruct;
#define i_val int
-#define i_opt c_is_forward
+#define i_is_forward
#define i_tag i32
#include <stc/cvec.h>
@@ -18,7 +18,7 @@ typedef struct Point { int x, y; } Point;
#define i_val Point
#define i_less(a, b) a->x < b->x || (a->x == b->x && a->y < b->y)
-#define i_opt c_is_forward
+#define i_is_forward
#define i_tag pnt
#include <stc/cvec.h>