From 4dbbdf26ec01a6ee550001baac73d3f7cf8be141 Mon Sep 17 00:00:00 2001 From: Tyge Lovset Date: Mon, 28 Oct 2024 08:28:03 +0100 Subject: [PATCH 1/2] - Changed the new cstr_join_s() and cstr_join_vec() macro functions. - Refactored box arc and added comments. No functional change. --- docs/cstr_api.md | 6 ++-- include/stc/arc.h | 70 ++++++++++++++++++++----------------- include/stc/box.h | 41 ++++++++++++---------- include/stc/cbits.h | 2 +- include/stc/priv/cstr_prv.h | 9 +++-- 5 files changed, 69 insertions(+), 59 deletions(-) diff --git a/docs/cstr_api.md b/docs/cstr_api.md index d5974c32..a325ce24 100644 --- a/docs/cstr_api.md +++ b/docs/cstr_api.md @@ -28,13 +28,13 @@ cstr cstr_from(const char* str); // const cstr cstr_from_s(cstr s, isize pos, isize len); // construct a substring cstr cstr_from_sv(csview sv); // construct from a string view cstr cstr_from_zv(zsview zv); // construct from a zero-terminated zsview -cstr cstr_from_fmt(const char* fmt, ...); // printf() formatting +cstr cstr_from_fmt(const char* fmt, ...); // construct from printf() formatting cstr cstr_from_replace(csview sv, csview search, csview repl, int32_t count); cstr cstr_with_n(const char* str, isize n); // construct from first n bytes of str cstr cstr_with_capacity(isize cap); // make empty string with pre-allocated capacity. cstr cstr_with_size(isize len, char fill); // make string with fill characters -cstr cstr_join(const char* sep, const char* str1, ...); // construct by joining c-strings with separator -cstr cstr_join_s(const char* sep, cstr s1, ...); // construct by joining cstrs with separator +cstr cstr_join_vec(const char* sep, Vec* vec); // construct by joining vec/stack of cstrs with separator +cstr cstr_join_s(const char* sep, {cstr s1, ...}); // construct by joining cstrs with separator cstr cstr_join_array(const char* sep, const char* arr[], isize n); // join c-string array with separator cstr cstr_join_array_s(const char* sep, cstr arr[], isize n); // join cstr array with separator diff --git a/include/stc/arc.h b/include/stc/arc.h index 8e26c29e..16e60e13 100644 --- a/include/stc/arc.h +++ b/include/stc/arc.h @@ -110,35 +110,34 @@ STC_INLINE Self _c_MEMB(_init)(void) STC_INLINE long _c_MEMB(_use_count)(const Self* self) { return self->use_count ? *self->use_count : 0; } + +// c++: std::make_shared<_m_value>(val) +STC_INLINE Self _c_MEMB(_make)(_m_value val) { + Self unowned; + struct _c_MEMB(_rep_)* rep = _i_malloc(struct _c_MEMB(_rep_), 1); + *(unowned.use_count = &rep->metadata.counter) = 1; + *(unowned.get = &rep->value) = val; // (.use_count, .get) are OFFSET bytes apart. + return unowned; +} + STC_INLINE Self _c_MEMB(_from_ptr)(_m_value* ptr) { enum {OFFSET = offsetof(struct _c_MEMB(_rep_), value)}; - Self arc = {ptr}; + Self unowned = {ptr}; if (ptr) { - // Adds 4 dummy bytes to ensure that the if-test in _drop is safe. + // Adds 4 dummy bytes to ensure that the if-test in _drop() is safe. struct _arc_metadata* meta = (struct _arc_metadata*)i_malloc(OFFSET + 4); - *(arc.use_count = &meta->counter) = 1; + *(unowned.use_count = &meta->counter) = 1; } - return arc; + return unowned; } -// c++: std::make_shared<_m_value>(val) -STC_INLINE Self _c_MEMB(_make)(_m_value val) { - Self arc; - struct _c_MEMB(_rep_)* rep = _i_malloc(struct _c_MEMB(_rep_), 1); - *(arc.use_count = &rep->metadata.counter) = 1; - *(arc.get = &rep->value) = val; - return arc; -} +STC_INLINE Self _c_MEMB(_from)(_m_raw raw) + { return _c_MEMB(_make)(i_keyfrom(raw)); } STC_INLINE _m_raw _c_MEMB(_toraw)(const Self* self) { return i_keytoraw(self->get); } -STC_INLINE Self _c_MEMB(_move)(Self* self) { - Self arc = *self; - self->get = NULL, self->use_count = NULL; - return arc; -} - +// destructor STC_INLINE void _c_MEMB(_drop)(const Self* self) { if (self->use_count && _i_atomic_dec_and_test(self->use_count)) { enum {OFFSET = offsetof(struct _c_MEMB(_rep_), value)}; @@ -153,30 +152,37 @@ STC_INLINE void _c_MEMB(_drop)(const Self* self) { } } +// move ownership to receiving arc +STC_INLINE Self _c_MEMB(_move)(Self* self) { + Self arc = *self; + self->get = NULL, self->use_count = NULL; + return arc; // now unowned +} + +// take ownership of pointer p STC_INLINE void _c_MEMB(_reset_to)(Self* self, _m_value* ptr) { _c_MEMB(_drop)(self); *self = _c_MEMB(_from_ptr)(ptr); } -STC_INLINE Self _c_MEMB(_from)(_m_raw raw) - { return _c_MEMB(_make)(i_keyfrom(raw)); } - -// does not use i_keyclone, so OK to always define. -STC_INLINE Self _c_MEMB(_clone)(Self arc) { - if (arc.use_count) _i_atomic_inc(arc.use_count); - return arc; -} - -// take ownership of unowned +// take ownership of unowned arc STC_INLINE void _c_MEMB(_take)(Self* self, Self unowned) { + c_assert(self->get != unowned.get); _c_MEMB(_drop)(self); *self = unowned; } -// share ownership with arc -STC_INLINE void _c_MEMB(_assign)(Self* self, Self arc) { - if (arc.use_count) _i_atomic_inc(arc.use_count); + +// make shared ownership with owned arc +STC_INLINE void _c_MEMB(_assign)(Self* self, Self owned) { + if (owned.use_count) _i_atomic_inc(owned.use_count); _c_MEMB(_drop)(self); - *self = arc; + *self = owned; +} + +// clone by sharing. Does not use i_keyclone, so OK to always define. +STC_INLINE Self _c_MEMB(_clone)(Self owned) { + if (owned.use_count) _i_atomic_inc(owned.use_count); + return owned; } #if defined _i_has_cmp diff --git a/include/stc/box.h b/include/stc/box.h index 510e4cd5..9518afb6 100644 --- a/include/stc/box.h +++ b/include/stc/box.h @@ -84,8 +84,6 @@ STC_INLINE Self _c_MEMB(_init)(void) STC_INLINE long _c_MEMB(_use_count)(const Self* self) { return (long)(self->get != NULL); } -STC_INLINE Self _c_MEMB(_from_ptr)(_m_value* p) - { return c_literal(Self){p}; } // c++: std::make_unique(val) STC_INLINE Self _c_MEMB(_make)(_m_value val) { @@ -94,6 +92,12 @@ STC_INLINE Self _c_MEMB(_make)(_m_value val) { return box; } +STC_INLINE Self _c_MEMB(_from_ptr)(_m_value* p) + { return c_literal(Self){p}; } + +STC_INLINE Self _c_MEMB(_from)(_m_raw raw) + { return _c_MEMB(_make)(i_keyfrom(raw)); } + STC_INLINE _m_raw _c_MEMB(_toraw)(const Self* self) { return i_keytoraw(self->get); } @@ -105,23 +109,37 @@ STC_INLINE void _c_MEMB(_drop)(const Self* self) { } } +// move ownership to receiving box STC_INLINE Self _c_MEMB(_move)(Self* self) { Self box = *self; self->get = NULL; return box; } +// release owned pointer, must be manually freed by receiver STC_INLINE _m_value* _c_MEMB(_release)(Self* self) { return _c_MEMB(_move)(self).get; } -// take ownership of p +// take ownership of pointer p STC_INLINE void _c_MEMB(_reset_to)(Self* self, _m_value* p) { _c_MEMB(_drop)(self); self->get = p; } -STC_INLINE Self _c_MEMB(_from)(_m_raw raw) - { return _c_MEMB(_make)(i_keyfrom(raw)); } +// take ownership of unowned box +STC_INLINE void _c_MEMB(_take)(Self* self, Self unowned) { + _c_MEMB(_drop)(self); + *self = unowned; +} + +// transfer ownership from other; set other to NULL +STC_INLINE void _c_MEMB(_assign)(Self* self, Self* owned) { + if (owned->get == self->get) + return; + _c_MEMB(_drop)(self); + *self = *owned; + owned->get = NULL; +} #if !defined i_no_clone STC_INLINE Self _c_MEMB(_clone)(Self other) { @@ -132,19 +150,6 @@ STC_INLINE Self _c_MEMB(_from)(_m_raw raw) } #endif // !i_no_clone -// take ownership of unowned -STC_INLINE void _c_MEMB(_take)(Self* self, Self unowned) { - _c_MEMB(_drop)(self); - *self = unowned; -} -// transfer ownership from moved; set moved to NULL -STC_INLINE void _c_MEMB(_assign)(Self* self, Self* moved) { - if (moved->get == self->get) - return; - _c_MEMB(_drop)(self); - *self = *moved; - moved->get = NULL; -} #if defined _i_has_cmp STC_INLINE int _c_MEMB(_raw_cmp)(const _m_raw* rx, const _m_raw* ry) diff --git a/include/stc/cbits.h b/include/stc/cbits.h index 7f337fd4..3efece02 100644 --- a/include/stc/cbits.h +++ b/include/stc/cbits.h @@ -202,7 +202,7 @@ STC_INLINE void cbits_set_pattern(cbits *self, const uintptr_t pattern); STC_INLINE cbits cbits_move(cbits* self) { cbits tmp = *self; - self->buffer = NULL, self->_size = 0; + memset(self, 0, sizeof *self); return tmp; } diff --git a/include/stc/priv/cstr_prv.h b/include/stc/priv/cstr_prv.h index 5dda8fed..8b079d11 100644 --- a/include/stc/priv/cstr_prv.h +++ b/include/stc/priv/cstr_prv.h @@ -62,12 +62,11 @@ extern char* _cstr_internal_move(cstr* self, isize pos1, isize pos2); #define cstr_init() (c_literal(cstr){0}) #define cstr_lit(literal) cstr_with_n(literal, c_litstrlen(literal)) -#define cstr_join(sep, ...) \ - cstr_join_array(sep, c_make_array(const char*, {__VA_ARGS__}), \ - c_NUMARGS(__VA_ARGS__)) +#define cstr_join_vec(sep, vecp) \ + cstr_join_array_s(sep, (vecp)->data, (vecp)->size) #define cstr_join_s(sep, ...) \ - cstr_join_array_s(sep, c_make_array(cstr, {__VA_ARGS__}), \ - c_NUMARGS(__VA_ARGS__)) + cstr_join_array_s(sep, c_make_array(cstr, __VA_ARGS__), c_NUMARGS(__VA_ARGS__)) + extern cstr cstr_from_replace(csview sv, csview search, csview repl, int32_t count); extern cstr cstr_from_fmt(const char* fmt, ...); From 4bf06a40a7c51a15be274c0141537071c17c5751 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tyge=20L=C3=B8vset?= Date: Mon, 28 Oct 2024 17:16:39 +0100 Subject: [PATCH 2/2] Changed API of arc_X_assign(). --- docs/arc_api.md | 2 +- docs/box_api.md | 7 ++++--- include/stc/arc.h | 6 +++--- misc/tests/vec_test.c | 14 +++++++------- 4 files changed, 15 insertions(+), 14 deletions(-) diff --git a/docs/arc_api.md b/docs/arc_api.md index 27e14249..df2590c2 100644 --- a/docs/arc_api.md +++ b/docs/arc_api.md @@ -58,7 +58,7 @@ arc_X arc_X_from_ptr(i_key* p); // create an arc arc_X arc_X_make(i_key key); // create an arc from constructed key object. Faster than from_ptr(). arc_X arc_X_clone(arc_X other); // return other with increased use count -void arc_X_assign(arc_X* self, arc_X other); // shared assign (increases use count) +void arc_X_assign(arc_X* self, const arc_X* other); // shared assign (increases use count) void arc_X_take(arc_X* self, arc_X unowned); // take ownership of unowned. arc_X arc_X_move(arc_X* self); // transfer ownership to receiver; self becomes NULL void arc_X_drop(arc_X* self); // destruct (decrease use count, free at 0) diff --git a/docs/box_api.md b/docs/box_api.md index b446ec2f..43c54a00 100644 --- a/docs/box_api.md +++ b/docs/box_api.md @@ -51,12 +51,13 @@ box_X box_X_from_ptr(i_key* ptr); // create a box box_X box_X_make(i_key val); // create a box from unowned val object. box_X box_X_clone(box_X other); // return deep copied clone -void box_X_assign(box_X* self, box_X* moved); // transfer ownership from moved to self; moved becomes NULL. +void box_X_assign(box_X* self, box_X* other); // transfer ownership from other to self; other set to NULL. void box_X_take(box_X* self, box_X unowned); // take ownership of unowned box object. -box_X box_X_move(box_X* self); // transfer ownership to receiving box returned. self becomes NULL. +box_X box_X_move(box_X* self); // transfer ownership to receiving box. self set to NULL. +i_key* box_X_release(box_X* self); // release owned pointer; must be freed by receiver. self set NULL. void box_X_drop(box_X* self); // destruct the contained object and free its heap memory. -void box_X_reset_to(box_X* self, i_key* p); // assign new box from ptr. Takes ownership of p. +void box_X_reset_to(box_X* self, i_key* ptr); // assign ptr, and take ownership of ptr. size_t box_X_hash(const box_X* x); // hash value int box_X_cmp(const box_X* x, const box_X* y); // compares pointer addresses if no `i_cmp` is specified diff --git a/include/stc/arc.h b/include/stc/arc.h index 16e60e13..173f0b4d 100644 --- a/include/stc/arc.h +++ b/include/stc/arc.h @@ -173,10 +173,10 @@ STC_INLINE void _c_MEMB(_take)(Self* self, Self unowned) { } // make shared ownership with owned arc -STC_INLINE void _c_MEMB(_assign)(Self* self, Self owned) { - if (owned.use_count) _i_atomic_inc(owned.use_count); +STC_INLINE void _c_MEMB(_assign)(Self* self, const Self* owned) { + if (owned->use_count) _i_atomic_inc(owned->use_count); _c_MEMB(_drop)(self); - *self = owned; + *self = *owned; } // clone by sharing. Does not use i_keyclone, so OK to always define. diff --git a/misc/tests/vec_test.c b/misc/tests/vec_test.c index 6c95741f..ef56c6f2 100644 --- a/misc/tests/vec_test.c +++ b/misc/tests/vec_test.c @@ -13,23 +13,23 @@ TEST(vec, basics) { c_forrange32 (i, 2, 9) IVec_push_back(&d, i*10); - IVec res1 = c_init(IVec, {6, 7, 8, 9, 10, 11, 12, 20, 30, 40, 50, 60, 70, 80}); - EXPECT_TRUE(IVec_eq(&res1, &d)); + IVec res = c_init(IVec, {6, 7, 8, 9, 10, 11, 12, 20, 30, 40, 50, 60, 70, 80}); + EXPECT_TRUE(IVec_eq(&res, &d)); EXPECT_EQ(14, IVec_size(&d)); IVec_erase_n(&d, 7, 4); - IVec res2 = c_init(IVec, {6, 7, 8, 9, 10, 11, 12, 60, 70, 80}); - EXPECT_TRUE(IVec_eq(&res2, &d)); + IVec_take(&res, c_init(IVec, {6, 7, 8, 9, 10, 11, 12, 60, 70, 80})); + EXPECT_TRUE(IVec_eq(&res, &d)); int nums[] = {200, 300, 400, 500}; IVec_insert_n(&d, 7, nums, 4); - IVec res3 = c_init(IVec, {6, 7, 8, 9, 10, 11, 12, 200, 300, 400, 500, 60, 70, 80}); - EXPECT_TRUE(IVec_eq(&res3, &d)); + IVec_take(&res, c_init(IVec, {6, 7, 8, 9, 10, 11, 12, 200, 300, 400, 500, 60, 70, 80})); + EXPECT_TRUE(IVec_eq(&res, &d)); EXPECT_EQ(14, IVec_size(&d)); EXPECT_EQ(200, *IVec_at(&d, 7)); - c_drop(IVec, &d, &res1, &res2, &res3); + c_drop(IVec, &d, &res); }