summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--benchmarks/cdeq_benchmark.cpp6
-rw-r--r--benchmarks/clist_benchmark.cpp4
-rw-r--r--benchmarks/cmap_benchmark.cpp6
-rw-r--r--benchmarks/csmap_benchmark.cpp6
-rw-r--r--benchmarks/cvec_benchmark.cpp4
-rw-r--r--benchmarks/plot.py9
-rw-r--r--benchmarks/run_all.bat2
-rw-r--r--benchmarks/run_all.sh4
-rw-r--r--benchmarks/run_clang.sh2
-rw-r--r--benchmarks/shootout2_cmap.cpp2
-rw-r--r--benchmarks/shootout3_csmap.cpp9
-rw-r--r--docs/ccommon_api.md15
-rw-r--r--examples/csmap_erase.c52
-rw-r--r--examples/csmap_find.c9
-rw-r--r--examples/new_list.c40
-rw-r--r--examples/sharedptr.c42
-rw-r--r--examples/splitstr.c2
-rw-r--r--include/stc/ccommon.h9
-rw-r--r--include/stc/clist.h6
-rw-r--r--include/stc/cmap.h22
-rw-r--r--include/stc/cvec.h3
-rw-r--r--include/stc/forward.h2
-rw-r--r--include/stc/template.h30
23 files changed, 142 insertions, 144 deletions
diff --git a/benchmarks/cdeq_benchmark.cpp b/benchmarks/cdeq_benchmark.cpp
index a12dddf0..0c4def50 100644
--- a/benchmarks/cdeq_benchmark.cpp
+++ b/benchmarks/cdeq_benchmark.cpp
@@ -43,8 +43,8 @@ Sample test_std_deque() {
c_forrange (N) con.push_back(stc64_random() & mask2);
s.test[FIND].t1 = clock();
size_t sum = 0;
- container::iterator it;
// Iteration - not inherent find - skipping
+ //container::iterator it;
//c_forrange (S) if ((it = std::find(con.begin(), con.end(), stc64_random() & mask2)) != con.end()) sum += *it;
s.test[FIND].t2 = clock();
s.test[FIND].sum = sum;
@@ -88,8 +88,8 @@ Sample test_stc_deque() {
c_forrange (N) cdeq_x_push_back(&con, stc64_random() & mask2);
s.test[FIND].t1 = clock();
size_t sum = 0;
- cdeq_x_iter_t it;
- //c_forrange (S) if ((it = cdeq_x_find(&con, stc64_random() & mask2)).ref) sum += *it.ref;
+ //cdeq_x_iter_t it, end = cdeq_x_end(&con);
+ //c_forrange (S) if ((it = cdeq_x_find(&con, stc64_random() & mask2)).ref != end.ref) sum += *it.ref;
s.test[FIND].t2 = clock();
s.test[FIND].sum = sum;
s.test[ITER].t1 = clock();
diff --git a/benchmarks/clist_benchmark.cpp b/benchmarks/clist_benchmark.cpp
index 7c1f164e..8151afa9 100644
--- a/benchmarks/clist_benchmark.cpp
+++ b/benchmarks/clist_benchmark.cpp
@@ -85,8 +85,8 @@ Sample test_stc_forward_list() {
c_forrange (N) clist_x_push_front(&con, stc64_random() & mask2);
s.test[FIND].t1 = clock();
size_t sum = 0;
- clist_x_iter_t it;
- //c_forrange (S) if ((it = clist_x_find(&con, stc64_random() & mask2)).ref) sum += *it.ref;
+ //clist_x_iter_t it, end = clist_x_end(&con);
+ //c_forrange (S) if ((it = clist_x_find(&con, stc64_random() & mask2)).ref != end.ref) sum += *it.ref;
s.test[FIND].t2 = clock();
s.test[FIND].sum = sum;
s.test[ITER].t1 = clock();
diff --git a/benchmarks/cmap_benchmark.cpp b/benchmarks/cmap_benchmark.cpp
index 98f90479..6e0ef325 100644
--- a/benchmarks/cmap_benchmark.cpp
+++ b/benchmarks/cmap_benchmark.cpp
@@ -91,8 +91,10 @@ Sample test_stc_unordered_map() {
stc64_srandom(seed);
s.test[FIND].t1 = clock();
size_t sum = 0;
- cmap_x_iter_t it;
- c_forrange (N) if ((it = cmap_x_find(&con, stc64_random() & mask1)).ref) sum += it.ref->second;
+ cmap_x_value_t* val;
+ c_forrange (N)
+ if ((val = cmap_x_get(&con, stc64_random() & mask1)))
+ sum += val->second;
s.test[FIND].t2 = clock();
s.test[FIND].sum = sum;
s.test[ITER].t1 = clock();
diff --git a/benchmarks/csmap_benchmark.cpp b/benchmarks/csmap_benchmark.cpp
index cd7f5509..18af9a34 100644
--- a/benchmarks/csmap_benchmark.cpp
+++ b/benchmarks/csmap_benchmark.cpp
@@ -91,8 +91,10 @@ Sample test_stc_map() {
stc64_srandom(seed);
s.test[FIND].t1 = clock();
size_t sum = 0;
- csmap_x_iter_t it;
- c_forrange (N) if ((it = csmap_x_find(&con, stc64_random() & mask1)).ref) sum += it.ref->second;
+ csmap_x_value_t* val;
+ c_forrange (N)
+ if ((val = csmap_x_get(&con, stc64_random() & mask1)))
+ sum += val->second;
s.test[FIND].t2 = clock();
s.test[FIND].sum = sum;
s.test[ITER].t1 = clock();
diff --git a/benchmarks/cvec_benchmark.cpp b/benchmarks/cvec_benchmark.cpp
index 755659a7..5cc2fb34 100644
--- a/benchmarks/cvec_benchmark.cpp
+++ b/benchmarks/cvec_benchmark.cpp
@@ -84,8 +84,8 @@ Sample test_stc_vector() {
c_forrange (N) cvec_x_push_back(&con, stc64_random() & mask2);
s.test[FIND].t1 = clock();
size_t sum = 0;
- cvec_x_iter_t it;
- //c_forrange (S) if ((it = cvec_x_find(&con, stc64_random() & mask2)).ref) sum += *it.ref;
+ //cvec_x_iter_t it, end = cvec_x_end(&con);
+ //c_forrange (S) if ((it = cvec_x_find(&con, stc64_random() & mask2)).ref != end.ref) sum += *it.ref;
s.test[FIND].t2 = clock();
s.test[FIND].sum = sum;
s.test[ITER].t1 = clock();
diff --git a/benchmarks/plot.py b/benchmarks/plot.py
index bd386312..ea3871f4 100644
--- a/benchmarks/plot.py
+++ b/benchmarks/plot.py
@@ -1,13 +1,16 @@
+import sys
import seaborn as sns
import pandas as pd
import matplotlib.pyplot as plt
#sns.set_theme(style="whitegrid")
comp = ['All compilers', 'Mingw-g++-10.30', 'Win-Clang-12', 'VC-19.28']
-n = 3
-df = pd.read_csv('plot_perf.csv')
+n = int(sys.argv[1]) if len(sys.argv) > 1 else 0
+file = sys.argv[2] if len(sys.argv) > 2 else 'plot_win.csv'
+df = pd.read_csv(file)
df = df[df.Method != 'total']
-if n > 0: df = df[df.Compiler == comp[n]]
+if n > 0:
+ df = df[df.Compiler == comp[n]]
g = sns.catplot(data=df, x='Method', y='Seconds', hue='Library', col='C', kind='bar',
ci=68, legend=False, col_wrap=2, sharex=False, aspect=1.4, height=3.1)
diff --git a/benchmarks/run_all.bat b/benchmarks/run_all.bat
index 8f250871..2edd0a1e 100644
--- a/benchmarks/run_all.bat
+++ b/benchmarks/run_all.bat
@@ -1,4 +1,4 @@
-set out=plot_perf.csv
+set out=plot_win.csv
echo Compiler,Library,C,Method,Seconds,Ratio> %out%
sh run_gcc.sh >> %out%
sh run_clang.sh >> %out%
diff --git a/benchmarks/run_all.sh b/benchmarks/run_all.sh
new file mode 100644
index 00000000..f15a5881
--- /dev/null
+++ b/benchmarks/run_all.sh
@@ -0,0 +1,4 @@
+out="plot_linux.csv"
+echo "Compiler,Library,C,Method,Seconds,Ratio"> $out
+sh run_gcc.sh >> $out
+sh run_clang.sh >> $out
diff --git a/benchmarks/run_clang.sh b/benchmarks/run_clang.sh
index f7575882..ae19486e 100644
--- a/benchmarks/run_clang.sh
+++ b/benchmarks/run_clang.sh
@@ -1,5 +1,5 @@
exe=''
-if [ "$OS" == 'Windows_NT' ]; then exe='.exe'; fi
+if [ "$OS" = "Windows_NT" ] ; then exe=".exe" ; fi
clang++ -I../include -O3 -o cdeq_benchmark$exe cdeq_benchmark.cpp
clang++ -I../include -O3 -o clist_benchmark$exe clist_benchmark.cpp
clang++ -I../include -O3 -o cmap_benchmark$exe cmap_benchmark.cpp
diff --git a/benchmarks/shootout2_cmap.cpp b/benchmarks/shootout2_cmap.cpp
index 6224c1f3..77d458bc 100644
--- a/benchmarks/shootout2_cmap.cpp
+++ b/benchmarks/shootout2_cmap.cpp
@@ -38,7 +38,7 @@ stc64_t rng;
#define CMAP_PUT(X, key, val) cmap_##X##_emplace_or_assign(&map, key, val).ref->second
#define CMAP_EMPLACE(X, key, val) cmap_##X##_emplace(&map, key, val).ref->second
#define CMAP_ERASE(X, key) cmap_##X##_erase(&map, key)
-#define CMAP_FIND(X, key) (cmap_##X##_find(map, key) != NULL)
+#define CMAP_FIND(X, key) cmap_##X##_contains(map, key)
#define CMAP_FOR(X, i) c_foreach (i, cmap_##X, map)
#define CMAP_ITEM(X, i) i.ref->second
#define CMAP_SIZE(X) cmap_##X##_size(map)
diff --git a/benchmarks/shootout3_csmap.cpp b/benchmarks/shootout3_csmap.cpp
index 6f124cd8..35abf8a8 100644
--- a/benchmarks/shootout3_csmap.cpp
+++ b/benchmarks/shootout3_csmap.cpp
@@ -179,8 +179,8 @@ static void ins_and_access_csmap_i(picobench::state& s)
picobench::scope scope(s);
c_forrange (s.iterations()) {
result += ++csmap_i_emplace(&map, stc64_random() & mask, 0).ref->second;
- csmap_i_iter_t it = csmap_i_find(&map, stc64_random() & mask);
- if (it.ref) csmap_i_erase(&map, it.ref->first);
+ csmap_i_value_t* val = csmap_i_get(&map, stc64_random() & mask);
+ if (val) csmap_i_erase(&map, val->first);
}
s.set_result(result + csmap_i_size(map));
csmap_i_del(&map);
@@ -216,11 +216,6 @@ static void ins_and_access_s(picobench::state& s)
c_forrange (s.iterations()) {
randomize(&str[0], str.size());
result += map.erase(str);
- /*auto it = map.find(str);
- if (it != map.end()) {
- ++result;
- map.erase(it);
- }*/
}
s.set_result(result + map.size());
}
diff --git a/docs/ccommon_api.md b/docs/ccommon_api.md
index 5f31e572..83f5dc6f 100644
--- a/docs/ccommon_api.md
+++ b/docs/ccommon_api.md
@@ -2,7 +2,7 @@
The following handy macros are safe to use, i.e. have no side-effects.
-### c_autoscope, c_autovar, c_auto, c_exitauto
+### c_auto, c_autovar, c_autoscope, c_autodefer
General ***defer*** mechanics for resource acquisition. These macros allows to specify the release of the
resource where the resource acquisition takes place. Makes it easier to verify that resources are released.
@@ -13,10 +13,11 @@ macros, as one must always make sure to unwind temporary allocated resources bef
| Usage | Description |
|:---------------------------------------|:---------------------------------------------------|
-| `c_autoscope (init, end...)` | Execute `init`. Defer `end...` to end of block |
-| `c_autovar (Type var=init, end...)` | Declare `var`. Defer `end...` to end of block |
| `c_auto (Type, var...)` | `c_autovar (Type var=Type_init(), Type_del(&var))` |
-| `c_exitauto;` | Break out of a `c_auto*`-block/scope |
+| `c_autovar (Type var=init, end...)` | Declare `var`. Defer `end...` to end of block |
+| `c_autoscope (init, end...)` | Execute `init`. Defer `end...` to end of block |
+| `c_autodefer (end...)` | Defer `end...` to end of block |
+| `c_exitauto;` | Break safely out of a `c_auto*`-block/scope |
For multiple variables, use either multiple **c_autovar** in sequence, or declare variable outside
scope and use **c_autoscope**. Also, **c_auto** support up to 3 variables.
@@ -45,7 +46,7 @@ c_autoscope (mydata_init(&data), mydata_destroy(&data))
}
cstr s1 = cstr_lit("Hello"), s2 = cstr_lit("world");
-c_autoscope (0, cstr_del(&s1), cstr_del(&s2))
+c_autodefer (cstr_del(&s1), cstr_del(&s2))
{
printf("%s %s\n", s1.str, s2.str);
}
@@ -122,16 +123,14 @@ c_forrange (i, int, 30, 0, -5) printf(" %d", i);
// 30 25 20 15 10 5
```
-### c_apply, c_apply_pair
+### c_apply, c_apply_pair, c_apply_n
**c_apply** will apply a method on an existing container with the given array elements:
```c
c_apply(cvec_i, push_back, &vec, {1, 2, 3}); // apply multiple push_backs
c_apply_pair(cmap_i, insert, &map, { {4, 5}, {6, 7} }); // inserts to existing map
int arr[] = {1, 2, 3};
-cmap_i_value_t arr2[] = { {4, 5}, {6, 7} };
c_apply_n(cvec_i, push_back, &vec, arr, c_arraylen(arr));
-c_apply_pair_n(cmap_i, insert, &map, arr2, c_arraylen(arr2));
```
### c_new, c_new_n, c_del, c_make
diff --git a/examples/csmap_erase.c b/examples/csmap_erase.c
index 66b45185..993f1837 100644
--- a/examples/csmap_erase.c
+++ b/examples/csmap_erase.c
@@ -3,41 +3,41 @@
#include <stc/cstr.h>
#include <stdio.h>
-#define i_tag my
#define i_key int
#define i_val_str
+#define i_cnt mymap
#include <stc/csmap.h>
-void printmap(csmap_my map)
+void printmap(mymap m)
{
- c_foreach (e, csmap_my, map)
- printf(" [%d, %s]", e.ref->first, e.ref->second.str);
- printf("\nsize() == %zu\n\n", csmap_my_size(map));
+ c_foreach (elem, mymap, m)
+ printf(" [%d, %s]", elem.ref->first, elem.ref->second.str);
+ printf("\nsize() == %zu\n\n", mymap_size(m));
}
int main()
{
- c_auto (csmap_my, m1)
+ c_auto (mymap, m1)
{
// Fill in some data to test with, one at a time
- csmap_my_insert(&m1, 1, cstr_lit("A"));
- csmap_my_insert(&m1, 2, cstr_lit("B"));
- csmap_my_insert(&m1, 3, cstr_lit("C"));
- csmap_my_insert(&m1, 4, cstr_lit("D"));
- csmap_my_insert(&m1, 5, cstr_lit("E"));
+ mymap_insert(&m1, 1, cstr_lit("A"));
+ mymap_insert(&m1, 2, cstr_lit("B"));
+ mymap_insert(&m1, 3, cstr_lit("C"));
+ mymap_insert(&m1, 4, cstr_lit("D"));
+ mymap_insert(&m1, 5, cstr_lit("E"));
puts("Starting data of map m1 is:");
printmap(m1);
// The 1st member function removes an element at a given position
- csmap_my_erase_at(&m1, csmap_my_advance(csmap_my_begin(&m1), 1));
+ mymap_erase_at(&m1, mymap_advance(mymap_begin(&m1), 1));
puts("After the 2nd element is deleted, the map m1 is:");
printmap(m1);
}
- c_auto (csmap_my, m2)
+ c_auto (mymap, m2)
{
// Fill in some data to test with, one at a time, using c_apply_pair()
- c_apply_pair(csmap_my, emplace, &m2, {
+ c_apply_pair(mymap, emplace, &m2, {
{10, "Bob"},
{11, "Rob"},
{12, "Robert"},
@@ -47,30 +47,30 @@ int main()
puts("Starting data of map m2 is:");
printmap(m2);
- csmap_my_iter_t it1 = csmap_my_advance(csmap_my_begin(&m2), 1);
- csmap_my_iter_t it2 = csmap_my_find(&m2, csmap_my_back(&m2)->first);
+ mymap_iter_t it1 = mymap_advance(mymap_begin(&m2), 1);
+ mymap_iter_t it2 = mymap_find(&m2, mymap_back(&m2)->first);
// The 2nd member function removes elements
// in the range [First, Last)
- csmap_my_erase_range(&m2, it1, it2);
+ mymap_erase_range(&m2, it1, it2);
puts("After the middle elements are deleted, the map m2 is:");
printmap(m2);
}
- c_auto (csmap_my, m3)
+ c_auto (mymap, m3)
{
// Fill in some data to test with, one at a time, using emplace
- csmap_my_emplace(&m3, 1, "red");
- csmap_my_emplace(&m3, 2, "yellow");
- csmap_my_emplace(&m3, 3, "blue");
- csmap_my_emplace(&m3, 4, "green");
- csmap_my_emplace(&m3, 5, "orange");
- csmap_my_emplace(&m3, 6, "purple");
- csmap_my_emplace(&m3, 7, "pink");
+ mymap_emplace(&m3, 1, "red");
+ mymap_emplace(&m3, 2, "yellow");
+ mymap_emplace(&m3, 3, "blue");
+ mymap_emplace(&m3, 4, "green");
+ mymap_emplace(&m3, 5, "orange");
+ mymap_emplace(&m3, 6, "purple");
+ mymap_emplace(&m3, 7, "pink");
puts("Starting data of map m3 is:");
printmap(m3);
// The 3rd member function removes elements with a given Key
- size_t count = csmap_my_erase(&m3, 2);
+ size_t count = mymap_erase(&m3, 2);
// The 3rd member function also returns the number of elements removed
printf("The number of elements removed from m3 is: %zu\n", count);
puts("After the element with a key of 2 is deleted, the map m3 is:");
diff --git a/examples/csmap_find.c b/examples/csmap_find.c
index 1b3320c9..eca14c52 100644
--- a/examples/csmap_find.c
+++ b/examples/csmap_find.c
@@ -33,9 +33,9 @@ using_print_collection(cvec_istr)
void findit(csmap_istr c, csmap_istr_key_t val)
{
printf("Trying find() on value %d\n", val);
- csmap_istr_value_t* result = csmap_istr_get(&c, val); // easier with get than find.
- if (result) {
- printf("Element found: "); print_elem(csmap_istr_value_toraw(result)); puts("");
+ csmap_istr_iter_t result = csmap_istr_find(&c, val); // prefer contains() or get()
+ if (result.ref != csmap_istr_end(&c).ref) {
+ printf("Element found: "); print_elem(csmap_istr_value_toraw(result.ref)); puts("");
} else {
puts("Element not found.");
}
@@ -61,7 +61,8 @@ int main()
puts("Inserting the following vector data into m1:");
print_collection_cvec_istr(v);
- c_foreach (i, cvec_istr, v) csmap_istr_emplace(&m1, i.ref->first, i.ref->second);
+ c_foreach (i, cvec_istr, cvec_istr_begin(&v), cvec_istr_end(&v))
+ csmap_istr_emplace(&m1, i.ref->first, i.ref->second);
puts("The modified map m1 is (key, value):");
print_collection_csmap_istr(m1);
diff --git a/examples/new_list.c b/examples/new_list.c
index a46e6350..879f26aa 100644
--- a/examples/new_list.c
+++ b/examples/new_list.c
@@ -35,25 +35,23 @@ int point_compare(const Point* a, const Point* b) {
int main()
{
- clist_i32 lst = clist_i32_init();
- clist_i32_push_back(&lst, 123);
- clist_i32_del(&lst);
-
- clist_float flst = clist_float_init();
- clist_float_push_back(&flst, 123.3);
- clist_float_del(&flst);
-
- clist_pnt plst = clist_pnt_init();
- clist_pnt_push_back(&plst, (Point){42, 14});
- clist_pnt_push_back(&plst, (Point){32, 94});
- clist_pnt_push_back(&plst, (Point){62, 81});
- clist_pnt_sort(&plst);
- c_foreach (i, clist_pnt, plst)
- printf(" (%d %d)", i.ref->x, i.ref->y);
- puts("");
- clist_pnt_del(&plst);
-
- clist_str slst = clist_str_init();
- clist_str_emplace_back(&slst, "Hello, friend");
- clist_str_del(&slst);
+ c_auto (clist_i32, lst)
+ clist_i32_push_back(&lst, 123);
+
+ c_auto (clist_pnt, plst) {
+ c_apply(clist_pnt, push_back, &plst, {{42, 14}, {32, 94}, {62, 81}});
+ clist_pnt_sort(&plst);
+
+ c_foreach (i, clist_pnt, plst)
+ printf(" (%d %d)", i.ref->x, i.ref->y);
+ puts("");
+ }
+
+ c_auto (clist_float, flst) {
+ c_apply(clist_float, push_back, &flst, {123.3, 321.2, -32.2, 78.2});
+ c_foreach (i, clist_float, flst) printf(" %g", *i.ref);
+ }
+
+ c_auto (clist_str, slst)
+ clist_str_emplace_back(&slst, "Hello, friend");
} \ No newline at end of file
diff --git a/examples/sharedptr.c b/examples/sharedptr.c
index e062025a..94de3d38 100644
--- a/examples/sharedptr.c
+++ b/examples/sharedptr.c
@@ -1,48 +1,48 @@
#include <stdio.h>
-void int_del(int* x) {
- printf("del: %d\n", *x);
-}
+void int_del(int* x) { printf("del: %d\n", *x); }
#define i_val int
#define i_valdel int_del // optional func to show elements destroyed
#include <stc/csptr.h> // csptr_int: shared pointer to int
#define i_key_csptr csptr_int
-#define i_tag int
-#include <stc/csset.h> // csset_int: csset<csptr_int>
+#define i_tag intp
+#include <stc/csset.h> // csset_intp: csset<csptr_int>
#define i_val_csptr csptr_int
-#define i_tag int
-#include <stc/cvec.h> // cvec_int: cvec<csptr_int>
+#define i_tag intp
+#include <stc/cvec.h> // cvec_intp: cvec<csptr_int>
+
int main()
{
- c_auto (cvec_int, vec)
- c_auto (csset_int, set) // declare and init set, call del at scope exit
+ c_auto (cvec_intp, vec)
+ c_auto (csset_intp, set) // declare and init set, call del at scope exit
{
- cvec_int_push_back(&vec, csptr_int_make(2021));
- cvec_int_push_back(&vec, csptr_int_make(2012));
- cvec_int_push_back(&vec, csptr_int_make(2022));
- cvec_int_push_back(&vec, csptr_int_make(2015));
-
+ c_apply(cvec_intp, push_back, &vec, {
+ csptr_int_make(2021),
+ csptr_int_make(2012),
+ csptr_int_make(2022),
+ csptr_int_make(2015),
+ });
printf("vec:");
- c_foreach (i, cvec_int, vec) printf(" %d", *i.ref->get);
+ c_foreach (i, cvec_intp, vec) printf(" %d", *i.ref->get);
puts("");
// add odd numbers from vec to set
- c_foreach (i, cvec_int, vec)
+ c_foreach (i, cvec_intp, vec)
if (*i.ref->get & 1)
- csset_int_emplace(&set, *i.ref); // copy shared pointer => increments counter.
+ csset_intp_emplace(&set, *i.ref); // copy shared pointer => increments counter.
// erase the two last elements in vec
- cvec_int_pop_back(&vec);
- cvec_int_pop_back(&vec);
+ cvec_intp_pop_back(&vec);
+ cvec_intp_pop_back(&vec);
printf("vec:");
- c_foreach (i, cvec_int, vec) printf(" %d", *i.ref->get);
+ c_foreach (i, cvec_intp, vec) printf(" %d", *i.ref->get);
printf("\nset:");
- c_foreach (i, csset_int, set) printf(" %d", *i.ref->get);
+ c_foreach (i, csset_intp, set) printf(" %d", *i.ref->get);
c_autovar (csptr_int p = csptr_int_clone(vec.data[0]), csptr_int_del(&p)) {
printf("\n%d is now owned by %u objects\n", *p.get, *p.use_count);
diff --git a/examples/splitstr.c b/examples/splitstr.c
index e4f6ab8a..82914485 100644
--- a/examples/splitstr.c
+++ b/examples/splitstr.c
@@ -36,7 +36,7 @@ int main()
cstr string = cstr_lit("Split,this,,string,now,");
cvec_str vec = string_split(cstr_sv(string), c_sv(","));
- c_autoscope (0, cvec_str_del(&vec), cstr_del(&string))
+ c_autodefer (cvec_str_del(&vec), cstr_del(&string))
c_foreach (i, cvec_str, vec)
printf("\t\"%s\"\n", i.ref->str);
} \ No newline at end of file
diff --git a/include/stc/ccommon.h b/include/stc/ccommon.h
index af56f43a..e3ccfffd 100644
--- a/include/stc/ccommon.h
+++ b/include/stc/ccommon.h
@@ -94,7 +94,7 @@
#define c_default_compare(x, y) c_less_compare(c_default_less, x, y)
#define c_default_less(x, y) (*(x) < *(y))
-#define c_no_compare(x, y) (assert(!"c_no_compare() called"), 0)
+#define c_no_compare(x, y) (assert(!"c_no_compare() called"), (x)==(y))
#define c_less_compare(less, x, y) (less(y, x) - less(x, y))
#define c_default_equals(x, y) (*(x) == *(y))
@@ -138,6 +138,7 @@ STC_API uint64_t c_default_hash(const void *key, size_t len);
#define c_autoscope(init, ...) for (int _c_ii = (init, 0); !_c_ii; ++_c_ii, __VA_ARGS__)
#define c_autovar(declvar, ...) for (declvar, *_c_ii = NULL; !_c_ii; ++_c_ii, __VA_ARGS__)
+#define c_autodefer(...) for (int _c_ii = 0; !_c_ii; ++_c_ii, __VA_ARGS__)
#define c_exitauto continue
#define c_auto(...) c_MACRO_OVERLOAD(c_auto, __VA_ARGS__)
@@ -168,17 +169,11 @@ STC_API uint64_t c_default_hash(const void *key, size_t len);
for (size_t _c_i = 0; _c_i < c_arraylen(_c_arr); ++_c_i) \
CX##_##method(_c_cx, _c_arr[_c_i].first, _c_arr[_c_i].second); \
} while (0)
-
#define c_apply_n(CX, method, cx, arr, n) do { \
CX* _c_cx = cx; \
for (const CX##_rawvalue_t *_c_i = arr, *_c_end = _c_i+(n); _c_i != _c_end; ++_c_i) \
CX##_##method(_c_cx, *_c_i); \
} while (0)
-#define c_apply_pair_n(CX, method, cx, arr, n) do { \
- CX* _c_cx = cx; \
- for (const CX##_rawvalue_t *_c_i = arr, *_c_end = _c_i+(n); _c_i != _c_end; ++_c_i) \
- CX##_##method(_c_cx, _c_i->first, _c_i->second); \
-} while (0)
#define c_del(CX, ...) do { \
CX* _c_arr[] = {__VA_ARGS__}; \
diff --git a/include/stc/clist.h b/include/stc/clist.h
index 7678b540..071cd8cb 100644
--- a/include/stc/clist.h
+++ b/include/stc/clist.h
@@ -135,13 +135,13 @@ cx_memb(_copy)(Self *self, Self other) {
STC_INLINE cx_iter_t
cx_memb(_iter)(const Self* self, cx_node_t* prev) {
- return c_make(cx_iter_t){&self->last, prev, &prev->next->value};
+ return c_make(cx_iter_t){&prev->next->value, &self->last, prev};
}
STC_INLINE cx_iter_t
cx_memb(_begin)(const Self* self) {
cx_value_t* head = self->last ? &self->last->next->value : NULL;
- return c_make(cx_iter_t){&self->last, self->last, head};
+ return c_make(cx_iter_t){head, &self->last, self->last};
}
STC_INLINE cx_iter_t
@@ -290,7 +290,7 @@ cx_memb(_split_off)(Self* self, cx_iter_t it1, cx_iter_t it2) {
Self cx = {NULL};
if (it1.ref == it2.ref) return cx;
cx_node_t *p1 = it1.prev,
- *p2 = it2.ref ? it2.prev : self->last;
+ *p2 = it2.ref ? it2.prev : self->last;
p1->next = p2->next, p2->next = clist_node_(it1.ref);
if (self->last == p2) self->last = (p1 == p2) ? NULL : p1;
cx.last = p2;
diff --git a/include/stc/cmap.h b/include/stc/cmap.h
index efd011a8..3a860f39 100644
--- a/include/stc/cmap.h
+++ b/include/stc/cmap.h
@@ -55,7 +55,7 @@ int main(void) {
#include <string.h>
#define _cmap_inits {NULL, NULL, 0, 0, 0.85f}
-typedef struct { size_t idx; uint_fast8_t hx; } chash_bucket_t;
+typedef struct { MAP_SIZE_T idx; uint_fast8_t hx; } chash_bucket_t;
#endif // CMAP_H_INCLUDED
#ifndef i_prefix
@@ -162,16 +162,18 @@ cx_memb(_insert)(Self* self, i_key _key cx_MAP_ONLY(, i_val _mapped)) {
STC_INLINE cx_iter_t
cx_memb(_find)(const Self* self, i_keyraw rkey) {
- cx_iter_t it = {NULL};
- if (self->size == 0) return it;
- chash_bucket_t b = cx_memb(_bucket_)(self, &rkey);
- if (*(it._hx = self->_hashx+b.idx)) it.ref = self->table+b.idx;
- return it;
+ cx_size_t idx;
+ if (!(self->size && self->_hashx[idx = cx_memb(_bucket_)(self, &rkey).idx]))
+ idx = self->bucket_count;
+ return c_make(cx_iter_t){self->table+idx, self->_hashx+idx};
}
STC_INLINE cx_value_t*
-cx_memb(_get)(const Self* self, i_keyraw rkey)
- { return cx_memb(_find)(self, rkey).ref; }
+cx_memb(_get)(const Self* self, i_keyraw rkey) {
+ cx_size_t idx;
+ return self->size && self->_hashx[idx = cx_memb(_bucket_)(self, &rkey).idx] ?
+ self->table + idx : NULL;
+}
STC_INLINE cx_iter_t
cx_memb(_begin)(const Self* self) {
@@ -236,7 +238,7 @@ STC_DEF uint64_t c_default_hash(const void *key, size_t len) {
#ifndef CMAP_H_INCLUDED
//STC_INLINE size_t fastrange_uint64_t(uint64_t x, uint64_t n)
// { uint64_t lo, hi; c_umul128(x, n, &lo, &hi); return hi; }
-#define fastrange_uint32_t(x, n) ((size_t) (((uint32_t)(x)*(uint64_t)(n)) >> 32))
+#define fastrange_uint32_t(x, n) (uint32_t)((uint32_t)(x)*(uint64_t)(n) >> 32)
#define chash_index_(h, entryPtr) ((entryPtr) - (h).table)
#endif
@@ -292,7 +294,7 @@ cx_MAP_ONLY(
STC_DEF chash_bucket_t
cx_memb(_bucket_)(const Self* self, const cx_rawkey_t* rkeyptr) {
const uint64_t _hash = i_hash(rkeyptr, sizeof *rkeyptr);
- uint_fast8_t _hx; size_t _cap = self->bucket_count;
+ uint_fast8_t _hx; cx_size_t _cap = self->bucket_count;
chash_bucket_t b = {c_PASTE(fastrange_,MAP_SIZE_T)(_hash, _cap), (uint_fast8_t)(_hash | 0x80)};
const uint8_t* _hashx = self->_hashx;
while ((_hx = _hashx[b.idx])) {
diff --git a/include/stc/cvec.h b/include/stc/cvec.h
index 11de465c..27aae8c3 100644
--- a/include/stc/cvec.h
+++ b/include/stc/cvec.h
@@ -237,7 +237,8 @@ cx_memb(_init)(void) {
STC_DEF void
cx_memb(_clear)(Self* self) {
- struct cvec_rep* rep = cvec_rep_(self); if (rep->cap) {
+ struct cvec_rep* rep = cvec_rep_(self);
+ if (rep->cap) {
for (cx_value_t *p = self->data, *q = p + rep->size; p != q; ++p)
i_valdel(p);
rep->size = 0;
diff --git a/include/stc/forward.h b/include/stc/forward.h
index 2d22b9ca..ec5f77b9 100644
--- a/include/stc/forward.h
+++ b/include/stc/forward.h
@@ -65,8 +65,8 @@
typedef struct SELF##_node_t SELF##_node_t; \
\
typedef struct { \
- SELF##_node_t *const *_last, *prev; \
SELF##_value_t *ref; \
+ SELF##_node_t *const *_last, *prev; \
} SELF##_iter_t; \
\
typedef struct { \
diff --git a/include/stc/template.h b/include/stc/template.h
index cecf9790..865e5b83 100644
--- a/include/stc/template.h
+++ b/include/stc/template.h
@@ -54,30 +54,16 @@
#endif
#ifdef i_key_csptr
- #ifndef i_tag
- #define i_tag i_key_csptr
- #endif
#define i_key i_key_csptr
#define i_cmp c_PASTE(i_key_csptr, _compare)
#define i_keydel c_PASTE(i_key_csptr, _del)
#define i_keyfrom c_PASTE(i_key_csptr, _clone)
#endif
-#ifdef i_val_csptr
- #if !defined i_tag && !defined i_key
- #define i_tag i_val_csptr
- #endif
- #define i_val i_val_csptr
- #ifndef i_key
- #define i_cmp c_PASTE(i_val_csptr, _compare)
- #endif
- #define i_valdel c_PASTE(i_val_csptr, _del)
- #define i_valfrom c_PASTE(i_val_csptr, _clone)
-#endif
#ifdef i_key_str
#define i_key cstr
#ifndef i_tag
- #define i_tag str
+ #define i_tag str
#endif
#define i_cmp c_rawstr_compare
#define i_hash c_rawstr_hash
@@ -86,13 +72,23 @@
#define i_keyto cstr_str
#define i_keyraw const char*
#endif
+
+#ifdef i_val_csptr
+ #define i_val i_val_csptr
+ #ifndef i_key
+ #define i_cmp c_PASTE(i_val_csptr, _compare)
+ #endif
+ #define i_valdel c_PASTE(i_val_csptr, _del)
+ #define i_valfrom c_PASTE(i_val_csptr, _clone)
+#endif
+
#ifdef i_val_str
#define i_val cstr
#if !defined i_tag && !defined i_key
- #define i_tag str
+ #define i_tag str
#endif
#ifndef i_key
- #define i_cmp c_rawstr_compare
+ #define i_cmp c_rawstr_compare
#endif
#define i_valdel cstr_del
#define i_valfrom cstr_from