summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorTyge Lovset <[email protected]>2023-05-18 11:49:31 +0200
committerTyge Lovset <[email protected]>2023-05-18 11:49:31 +0200
commit50a16934dde8e65bbcf628d6342c1649f7e09365 (patch)
treea14f3347622979858ff60b95630877029cb46ef6
parentbe7d9913d4a284bdeb7f0431482b5731b5ef31df (diff)
downloadSTC-modified-50a16934dde8e65bbcf628d6342c1649f7e09365.tar.gz
STC-modified-50a16934dde8e65bbcf628d6342c1649f7e09365.zip
Huge update: cqueue and cdeq completely rewritten. cvec and cdeq API harmonized. Docs update/improved.
-rw-r--r--README.md2
-rw-r--r--docs/ccommon_api.md2
-rw-r--r--docs/cdeq_api.md45
-rw-r--r--docs/clist_api.md10
-rw-r--r--docs/cqueue_api.md9
-rw-r--r--docs/csmap_api.md3
-rw-r--r--docs/cstack_api.md3
-rw-r--r--docs/cvec_api.md20
-rw-r--r--include/stc/algo/sort.h (renamed from include/stc/algo/csort.h)49
-rw-r--r--include/stc/ccommon.h10
-rw-r--r--include/stc/cdeq.h453
-rw-r--r--include/stc/clist.h9
-rw-r--r--include/stc/cmap.h9
-rw-r--r--include/stc/cqueue.h226
-rw-r--r--include/stc/cvec.h121
-rw-r--r--include/stc/forward.h13
-rw-r--r--include/stc/priv/template.h8
-rw-r--r--include/stc/priv/template2.h5
-rw-r--r--misc/benchmarks/various/csort_bench.c44
-rw-r--r--misc/benchmarks/various/cspan_bench.c2
-rw-r--r--misc/examples/printspan.c6
-rw-r--r--src/cregex.c2
22 files changed, 480 insertions, 571 deletions
diff --git a/README.md b/README.md
index 74c2238f..3b9cf90f 100644
--- a/README.md
+++ b/README.md
@@ -642,7 +642,7 @@ Major changes:
- Algorithms:
- [crange](docs/ccommon_api.md#crange) - similar to [boost::irange](https://www.boost.org/doc/libs/release/libs/range/doc/html/range/reference/ranges/irange.html) integer range generator.
- [c_forfilter](docs/ccommon_api.md#c_forfilter) - ranges-like view filtering.
- - [csort](include/stc/algo/csort.h) - [fast quicksort](misc/benchmarks/various/csort_bench.c) with custom inline comparison.
+ - [csort](include/stc/algo/sort.h) - [fast quicksort](misc/benchmarks/various/csort_bench.c) with custom inline comparison.
- Renamed `c_ARGSV()` => `c_SV()`: **csview** print arg. Note `c_sv()` is shorthand for *csview_from()*.
- Support for [uppercase flow-control](include/stc/priv/altnames.h) macro names in ccommon.h.
- Some API changes in **cregex** and **cstr**.
diff --git a/docs/ccommon_api.md b/docs/ccommon_api.md
index e4c881dd..e37a1463 100644
--- a/docs/ccommon_api.md
+++ b/docs/ccommon_api.md
@@ -212,7 +212,7 @@ You may customize `i_tag` and the comparison function `i_cmp` or `i_less`.
There is a [benchmark/test file here](../misc/benchmarks/various/csort_bench.c).
```c
#define i_val int
-#include <stc/algo/csort.h>
+#include <stc/algo/sort.h>
int main() {
int array[] = {5, 3, 5, 9, 7, 4, 7, 2, 4, 9, 3, 1, 2, 6, 4};
diff --git a/docs/cdeq_api.md b/docs/cdeq_api.md
index fc11fe66..91022a5c 100644
--- a/docs/cdeq_api.md
+++ b/docs/cdeq_api.md
@@ -1,7 +1,9 @@
# STC [cdeq](../include/stc/cdeq.h): Double Ended Queue
![Deque](pics/deque.jpg)
-A **cdeq** is an indexed sequence container that allows fast insertion and deletion at both its beginning and its end. Note that this container is implemented similar to a vector, but has the same performance profile for both *push_back()* and *push_front()* as *cdeq_X_push_back()*. Iterators may be invalidated after push-operations.
+A **cdeq** is an indexed sequence container that allows fast insertion and deletion at both
+its beginning and its end, but has also fast random access to elements. The container is
+implemented as a circular dynamic buffer. Iterators may be invalidated after push-operations.
See the c++ class [std::deque](https://en.cppreference.com/w/cpp/container/deque) for a functional description.
@@ -32,20 +34,20 @@ cdeq_X cdeq_X_clone(cdeq_X deq);
void cdeq_X_clear(cdeq_X* self);
void cdeq_X_copy(cdeq_X* self, const cdeq_X* other);
-cdeq_X_iter cdeq_X_copy_range(cdeq_X* self, i_val* pos, const i_val* p1, const i_val* p2);
bool cdeq_X_reserve(cdeq_X* self, intptr_t cap);
void cdeq_X_shrink_to_fit(cdeq_X* self);
-void cdeq_X_drop(cdeq_X* self); // destructor
+void cdeq_X_drop(cdeq_X* self); // destructor
bool cdeq_X_empty(const cdeq_X* self);
intptr_t cdeq_X_size(const cdeq_X* self);
intptr_t cdeq_X_capacity(const cdeq_X* self);
const cdeq_X_value* cdeq_X_at(const cdeq_X* self, intptr_t idx);
-const cdeq_X_value* cdeq_X_get(const cdeq_X* self, i_valraw raw); // return NULL if not found
-cdeq_X_value* cdeq_X_get_mut(cdeq_X* self, i_valraw raw); // mutable get
+cdeq_X_value* cdeq_X_at_mut(cdeq_X* self, intptr_t idx);
+const cdeq_X_value* cdeq_X_get(const cdeq_X* self, i_valraw raw); // return NULL if not found
+cdeq_X_value* cdeq_X_get_mut(cdeq_X* self, i_valraw raw); // mutable get
cdeq_X_iter cdeq_X_find(const cdeq_X* self, i_valraw raw);
-cdeq_X_iter cdeq_X_find_in(cdeq_X_iter i1, cdeq_X_iter i2, i_valraw raw); // return cvec_X_end() if not found
+cdeq_X_iter cdeq_X_find_in(cdeq_X_iter i1, cdeq_X_iter i2, i_valraw raw); // return cvec_X_end() if not found
cdeq_X_value* cdeq_X_front(const cdeq_X* self);
cdeq_X_value* cdeq_X_back(const cdeq_X* self);
@@ -55,38 +57,31 @@ cdeq_X_value* cdeq_X_emplace_front(cdeq_X* self, i_valraw raw);
void cdeq_X_pop_front(cdeq_X* self);
cdeq_X_value* cdeq_X_push_back(cdeq_X* self, i_val value);
-cdeq_X_value* cdeq_X_push(cdeq_X* self, i_val value); // alias for push_back()
+cdeq_X_value* cdeq_X_push(cdeq_X* self, i_val value); // alias for push_back()
cdeq_X_value* cdeq_X_emplace_back(cdeq_X* self, i_valraw raw);
-cdeq_X_value* cdeq_X_emplace(cdeq_X* self, i_valraw raw); // alias for emplace_back()
+cdeq_X_value* cdeq_X_emplace(cdeq_X* self, i_valraw raw); // alias for emplace_back()
void cdeq_X_pop_back(cdeq_X* self);
-cdeq_X_iter cdeq_X_insert(cdeq_X* self, intptr_t idx, i_val value); // move value
-cdeq_X_iter cdeq_X_insert_n(cdeq_X* self, intptr_t idx, const i_val[] arr, intptr_t n); // move arr values
-cdeq_X_iter cdeq_X_insert_at(cdeq_X* self, cdeq_X_iter it, i_val value); // move value
-cdeq_X_iter cdeq_X_insert_range(cdeq_X* self, i_val* pos,
- const i_val* p1, const i_val* p2);
-
-cdeq_X_iter cdeq_X_emplace_n(cdeq_X* self, intptr_t idx, const i_valraw[] arr, intptr_t n); // clone values
+cdeq_X_iter cdeq_X_insert_n(cdeq_X* self, intptr_t idx, const i_val[] arr, intptr_t n); // move values
+cdeq_X_iter cdeq_X_insert(cdeq_X* self, intptr_t idx, i_val value); // move value
+cdeq_X_iter cdeq_X_insert_at(cdeq_X* self, cdeq_X_iter it, i_val value); // move value
+cdeq_X_iter cdeq_X_insert_uninit(cdeq_X* self, intptr_t idx, intptr_t n); // uninitialized data
+ // copy values:
+cdeq_X_iter cdeq_X_emplace_n(cdeq_X* self, intptr_t idx, const i_valraw[] arr, intptr_t n);
cdeq_X_iter cdeq_X_emplace_at(cdeq_X* self, cdeq_X_iter it, i_valraw raw);
-cdeq_X_iter cdeq_X_emplace_range(cdeq_X* self, i_val* pos,
- const i_valraw* p1, const i_valraw* p2);
-cdeq_X_iter cdeq_X_erase_n(cdeq_X* self, intptr_t idx, intptr_t n);
+void cdeq_X_erase_n(cdeq_X* self, intptr_t idx, intptr_t n);
cdeq_X_iter cdeq_X_erase_at(cdeq_X* self, cdeq_X_iter it);
cdeq_X_iter cdeq_X_erase_range(cdeq_X* self, cdeq_X_iter it1, cdeq_X_iter it2);
-cdeq_X_iter cdeq_X_erase_range_p(cdeq_X* self, i_val* p1, i_val* p2);
-
-void cdeq_X_sort(cdeq_X* self);
-void cdeq_X_sort_range(cdeq_X_iter i1, cdeq_X_iter i2,
- int(*cmp)(const i_val*, const i_val*));
cdeq_X_iter cdeq_X_begin(const cdeq_X* self);
cdeq_X_iter cdeq_X_end(const cdeq_X* self);
void cdeq_X_next(cdeq_X_iter* it);
-cdeq_X_iter cdeq_X_advance(cdeq_X_iter it, size_t n);
+cdeq_X_iter cdeq_X_advance(cdeq_X_iter it, intptr_t n);
-cdeq_X_raw cdeq_X_value_toraw(cdeq_X_value* pval);
cdeq_X_value cdeq_X_value_clone(cdeq_X_value val);
+cdeq_X_raw cdeq_X_value_toraw(const cdeq_X_value* pval);
+void cdeq_X_value_drop(cdeq_X_value* pval);
```
## Types
diff --git a/docs/clist_api.md b/docs/clist_api.md
index a1dbe105..44c3bb7c 100644
--- a/docs/clist_api.md
+++ b/docs/clist_api.md
@@ -84,19 +84,21 @@ void clist_X_sort(clist_X* self);
void clist_X_sort_with(clist_X* self, int(*cmp)(const clist_X_value*, const clist_X_value*));
// Node API
-clist_X_node* clist_X_get_node(clist_X_value* val); // get the enclosing node
+clist_X_node* clist_X_get_node(clist_X_value* val); // get enclosing node
clist_X_value* clist_X_push_back_node(clist_X* self, clist_X_node* node);
clist_X_value* clist_X_insert_after_node(clist_X* self, clist_X_node* ref, clist_X_node* node);
-clist_X_node* clist_X_unlink_after_node(clist_X* self, clist_X_node* ref); // return the unlinked node
+clist_X_node* clist_X_unlink_after_node(clist_X* self, clist_X_node* ref); // return unlinked node
+clist_X_node* clist_X_unlink_front_node(clist_X* self); // return unlinked node
void clist_X_erase_after_node(clist_X* self, clist_X_node* node);
clist_X_iter clist_X_begin(const clist_X* self);
clist_X_iter clist_X_end(const clist_X* self);
void clist_X_next(clist_X_iter* it);
-clist_X_iter clist_X_advance(clist_X_iter it, size_t n); // return n elements ahead.
+clist_X_iter clist_X_advance(clist_X_iter it, size_t n); // return n elements ahead.
-clist_X_raw clist_X_value_toraw(clist_X_value* pval);
clist_X_value clist_X_value_clone(clist_X_value val);
+clist_X_raw clist_X_value_toraw(const clist_X_value* pval);
+void clist_X_value_drop(clist_X_value* pval);
```
## Types
diff --git a/docs/cqueue_api.md b/docs/cqueue_api.md
index 9ea4b148..7d8d4e5c 100644
--- a/docs/cqueue_api.md
+++ b/docs/cqueue_api.md
@@ -26,27 +26,34 @@ See the c++ class [std::queue](https://en.cppreference.com/w/cpp/container/queue
```c
cqueue_X cqueue_X_init(void);
+cqueue_X cqueue_X_with_capacity(intptr_t size);
cqueue_X cqueue_X_clone(cqueue_X q);
void cqueue_X_clear(cqueue_X* self);
void cqueue_X_copy(cqueue_X* self, const cqueue_X* other);
+bool cqueue_X_reserve(cqueue_X* self, intptr_t cap);
+void cqueue_X_shrink_to_fit(cqueue_X* self);
void cqueue_X_drop(cqueue_X* self); // destructor
intptr_t cqueue_X_size(const cqueue_X* self);
+intptr_t cqueue_X_capacity(const cqueue_X* self);
bool cqueue_X_empty(const cqueue_X* self);
+
cqueue_X_value* cqueue_X_front(const cqueue_X* self);
cqueue_X_value* cqueue_X_back(const cqueue_X* self);
cqueue_X_value* cqueue_X_push(cqueue_X* self, i_val value);
cqueue_X_value* cqueue_X_emplace(cqueue_X* self, i_valraw raw);
-
void cqueue_X_pop(cqueue_X* self);
cqueue_X_iter cqueue_X_begin(const cqueue_X* self);
cqueue_X_iter cqueue_X_end(const cqueue_X* self);
void cqueue_X_next(cqueue_X_iter* it);
+cqueue_X_iter cqueue_X_advance(cqueue_X_iter it, intptr_t n);
i_val cqueue_X_value_clone(i_val value);
+cqueue_X_raw cqueue_X_value_toraw(const cqueue_X_value* pval);
+void cqueue_X_value_drop(cqueue_X_value* pval);
```
## Types
diff --git a/docs/csmap_api.md b/docs/csmap_api.md
index 3e643cee..8c2048c0 100644
--- a/docs/csmap_api.md
+++ b/docs/csmap_api.md
@@ -83,7 +83,8 @@ void csmap_X_next(csmap_X_iter* iter);
csmap_X_iter csmap_X_advance(csmap_X_iter it, intptr_t n);
csmap_X_value csmap_X_value_clone(csmap_X_value val);
-csmap_X_raw csmap_X_value_toraw(csmap_X_value* pval);
+csmap_X_raw csmap_X_value_toraw(const csmap_X_value* pval);
+void csmap_X_value_drop(csmap_X_value* pval);
```
## Types
diff --git a/docs/cstack_api.md b/docs/cstack_api.md
index b1371f4e..c20de7d1 100644
--- a/docs/cstack_api.md
+++ b/docs/cstack_api.md
@@ -54,8 +54,9 @@ cstack_X_iter cstack_X_begin(const cstack_X* self);
cstack_X_iter cstack_X_end(const cstack_X* self);
void cstack_X_next(cstack_X_iter* it);
-i_valraw cstack_X_value_toraw(cvec_X_value* pval);
i_val cstack_X_value_clone(i_val value);
+i_valraw cstack_X_value_toraw(const cvec_X_value* pval);
+void cstack_X_value_drop(cvec_X_value* pval);
```
## Types
diff --git a/docs/cvec_api.md b/docs/cvec_api.md
index 5879bc1f..194d48e1 100644
--- a/docs/cvec_api.md
+++ b/docs/cvec_api.md
@@ -37,10 +37,9 @@ cvec_X cvec_X_clone(cvec_X vec);
void cvec_X_clear(cvec_X* self);
void cvec_X_copy(cvec_X* self, const cvec_X* other);
-cvec_X_iter cvec_X_copy_range(cvec_X* self, i_val* pos, const i_val* p1, const i_val* p2);
+cvec_X_iter cvec_X_copy_n(cvec_X* self, intptr_t idx, const i_val* arr, intptr_t n);
bool cvec_X_reserve(cvec_X* self, intptr_t cap);
bool cvec_X_resize(cvec_X* self, intptr_t size, i_val null);
-cvec_X_iter cvec_X_insert_uninit(cvec_X* self, i_val* pos, intptr_t n); // return pos iter
void cvec_X_shrink_to_fit(cvec_X* self);
void cvec_X_drop(cvec_X* self); // destructor
@@ -50,8 +49,8 @@ intptr_t cvec_X_capacity(const cvec_X* self);
const cvec_X_value* cvec_X_at(const cvec_X* self, intptr_t idx);
const cvec_X_value* cvec_X_get(const cvec_X* self, i_valraw raw); // return NULL if not found
-cvec_X_value* cvec_X_at_mut(cvec_X* self, intptr_t idx);
-cvec_X_value* cvec_X_get_mut(cvec_X* self, i_valraw raw); // find mutable value, return value ptr
+cvec_X_value* cvec_X_at_mut(cvec_X* self, intptr_t idx); // return mutable at idx
+cvec_X_value* cvec_X_get_mut(cvec_X* self, i_valraw raw); // find mutable value
cvec_X_iter cvec_X_find(const cvec_X* self, i_valraw raw);
cvec_X_iter cvec_X_find_in(cvec_X_iter i1, cvec_X_iter i2, i_valraw raw); // return cvec_X_end() if not found
// On sorted vectors:
@@ -72,20 +71,16 @@ void cvec_X_pop(cvec_X* self);
void cvec_X_pop_back(cvec_X* self); // alias for pop
cvec_X_iter cvec_X_insert(cvec_X* self, intptr_t idx, i_val value); // move value
-cvec_X_iter cvec_X_insert_n(cvec_X* self, intptr_t idx, const i_val[] arr, intptr_t n); // move n values
+cvec_X_iter cvec_X_insert_n(cvec_X* self, intptr_t idx, const i_val arr[], intptr_t n); // move values
cvec_X_iter cvec_X_insert_at(cvec_X* self, cvec_X_iter it, i_val value); // move value
-cvec_X_iter cvec_X_insert_range(cvec_X* self, i_val* pos,
- const i_val* p1, const i_val* p2);
+cvec_X_iter cvec_X_insert_uninit(cvec_X* self, intptr_t idx, intptr_t n); // return iter at idx
-cvec_X_iter cvec_X_emplace_n(cvec_X* self, intptr_t idx, const i_valraw[] arr, intptr_t n); // clone values
+cvec_X_iter cvec_X_emplace_n(cvec_X* self, intptr_t idx, const i_valraw raw[], intptr_t n);
cvec_X_iter cvec_X_emplace_at(cvec_X* self, cvec_X_iter it, i_valraw raw);
-cvec_X_iter cvec_X_emplace_range(cvec_X* self, i_val* pos,
- const i_valraw* p1, const i_valraw* p2);
cvec_X_iter cvec_X_erase_n(cvec_X* self, intptr_t idx, intptr_t n);
cvec_X_iter cvec_X_erase_at(cvec_X* self, cvec_X_iter it);
cvec_X_iter cvec_X_erase_range(cvec_X* self, cvec_X_iter it1, cvec_X_iter it2);
-cvec_X_iter cvec_X_erase_range_p(cvec_X* self, i_val* p1, i_val* p2);
void cvec_X_sort(cvec_X* self);
void cvec_X_sort_range(cvec_X_iter i1, cvec_X_iter i2,
@@ -96,8 +91,9 @@ cvec_X_iter cvec_X_end(const cvec_X* self);
void cvec_X_next(cvec_X_iter* iter);
cvec_X_iter cvec_X_advance(cvec_X_iter it, size_t n);
-cvec_X_raw cvec_X_value_toraw(cvec_X_value* pval);
cvec_X_value cvec_X_value_clone(cvec_X_value val);
+cvec_X_raw cvec_X_value_toraw(const cvec_X_value* pval);
+cvec_X_raw cvec_X_value_drop(cvec_X_value* pval);
```
## Types
diff --git a/include/stc/algo/csort.h b/include/stc/algo/sort.h
index e01a2893..20b7e1b3 100644
--- a/include/stc/algo/csort.h
+++ b/include/stc/algo/sort.h
@@ -24,17 +24,17 @@
template params:
#define i_val - value type [required]
#define i_less - less function. default: *x < *y
-#define i_tag NAME - define csort_NAME(). default {i_val}
+#define i_tag name - define namearray_qsort(). i_tag defaults {i_val}
// test:
#include <stdio.h>
#define i_val int
-#include <stc/algo/csort.h>
+#include <stc/algo/sort.h>
int main() {
int arr[] = {23, 321, 5434, 25, 245, 1, 654, 33, 543, 21};
- csort_int(arr, c_arraylen(arr));
+ intarray_qsort(arr, c_arraylen(arr));
for (int i = 0; i < c_arraylen(arr); i++)
printf(" %d", arr[i]);
@@ -42,33 +42,42 @@ int main() {
}
*/
#include "../ccommon.h"
-#define _i_prefix csort_
+#ifndef i_type
+ #define i_at(arr, idx) (&arr[idx])
+ #ifndef i_tag
+ #define i_tag i_val
+ #endif
+ #define i_type c_PASTE(i_tag, array)
+ typedef i_val i_type;
+#endif
+#ifndef i_at
+ #define i_at(arr, idx) _cx_memb(_at_mut)(arr, idx)
+#endif
#include "../priv/template.h"
-typedef i_val _cx_value;
-static inline void _cx_memb(_insertion)(i_val arr[], intptr_t lo, intptr_t hi) {
+static inline void _cx_memb(_insertsort_ij)(_cx_self* arr, intptr_t lo, intptr_t hi) {
for (intptr_t j = lo, i = lo + 1; i <= hi; j = i, ++i) {
- i_val key = arr[i];
- while (j >= 0 && (i_less((&key), (&arr[j])))) {
- arr[j + 1] = arr[j];
+ i_val key = *i_at(arr, i);
+ while (j >= 0 && (i_less((&key), i_at(arr, j)))) {
+ *i_at(arr, j + 1) = *i_at(arr, j);
--j;
}
- arr[j + 1] = key;
+ *i_at(arr, j + 1) = key;
}
}
-static inline void _cx_memb(_quicksort)(i_val arr[], intptr_t lo, intptr_t hi) {
+static inline void _cx_memb(_sort_ij)(_cx_self* arr, intptr_t lo, intptr_t hi) {
intptr_t i = lo, j;
while (lo < hi) {
- i_val pivot = arr[lo + (hi - lo)*7/16];
+ i_val pivot = *i_at(arr, lo + (hi - lo)*7/16);
j = hi;
while (i <= j) {
- while (i_less((&arr[i]), (&pivot))) ++i;
- while (i_less((&pivot), (&arr[j]))) --j;
+ while (i_less(i_at(arr, i), (&pivot))) ++i;
+ while (i_less((&pivot), i_at(arr, j))) --j;
if (i <= j) {
- c_swap(i_val, arr+i, arr+j);
+ c_swap(i_val, i_at(arr, i), i_at(arr, j));
++i; --j;
}
}
@@ -77,13 +86,15 @@ static inline void _cx_memb(_quicksort)(i_val arr[], intptr_t lo, intptr_t hi) {
c_swap(intptr_t, &hi, &j);
}
- if (j - lo > 64) _cx_memb(_quicksort)(arr, lo, j);
- else if (j > lo) _cx_memb(_insertion)(arr, lo, j);
+ if (j - lo > 64) _cx_memb(_sort_ij)(arr, lo, j);
+ else if (j > lo) _cx_memb(_insertsort_ij)(arr, lo, j);
lo = i;
}
}
-static inline void _cx_self(i_val arr[], intptr_t n)
- { _cx_memb(_quicksort)(arr, 0, n - 1); }
+static inline void _cx_memb(_sort_n)(_cx_self* arr, intptr_t len) {
+ _cx_memb(_sort_ij)(arr, 0, len - 1);
+}
#include "../priv/template2.h"
+#undef i_at
diff --git a/include/stc/ccommon.h b/include/stc/ccommon.h
index fd673696..07c72e2f 100644
--- a/include/stc/ccommon.h
+++ b/include/stc/ccommon.h
@@ -171,6 +171,16 @@ STC_INLINE char* cstrnstrn(const char *str, const char *needle,
return NULL;
}
+STC_INLINE intptr_t cnextpow2(intptr_t n) {
+ n--;
+ n |= n >> 1, n |= n >> 2;
+ n |= n >> 4, n |= n >> 8;
+ n |= n >> 16;
+ #if INTPTR_SIZE == INT64_SIZE
+ n |= n >> 32;
+ #endif
+ return n + 1;
+}
/* Control block macros */
#define c_foreach(...) c_MACRO_OVERLOAD(c_foreach, __VA_ARGS__)
diff --git a/include/stc/cdeq.h b/include/stc/cdeq.h
index ff6e744f..80dd1dbe 100644
--- a/include/stc/cdeq.h
+++ b/include/stc/cdeq.h
@@ -20,166 +20,82 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
-#include "ccommon.h"
-
-#ifndef CDEQ_H_INCLUDED
-#include "forward.h"
-#include <stdlib.h>
-#include <string.h>
-
-#define _it2_ptr(it1, it2) (it1.ref && !it2.ref ? it2.end : it2.ref)
-#define _it_ptr(it) (it.ref ? it.ref : it.end)
-#endif // CDEQ_H_INCLUDED
-
-#ifndef _i_prefix
#define _i_prefix cdeq_
+#define _pop _pop_front
+#ifdef i_more
+ #include "cqueue.h"
+ #define i_more
+#else
+ #define i_more
+ #include "cqueue.h"
#endif
-#include "priv/template.h"
-
-#ifndef i_is_forward
-_cx_deftypes(_c_cdeq_types, _cx_self, i_key);
-#endif
-typedef i_keyraw _cx_raw;
-
-STC_API _cx_self _cx_memb(_init)(void);
-STC_API _cx_self _cx_memb(_with_capacity)(const intptr_t n);
-STC_API bool _cx_memb(_reserve)(_cx_self* self, const intptr_t n);
-STC_API void _cx_memb(_clear)(_cx_self* self);
-STC_API void _cx_memb(_drop)(_cx_self* self);
-STC_API _cx_value* _cx_memb(_push)(_cx_self* self, i_key value);
-STC_API void _cx_memb(_shrink_to_fit)(_cx_self *self);
-STC_INLINE void _cx_memb(_put_n)(_cx_self* self, const _cx_raw* raw, intptr_t n)
- { while (n--) _cx_memb(_push)(self, i_keyfrom(*raw++)); }
-STC_INLINE _cx_self _cx_memb(_from_n)(const _cx_raw* raw, intptr_t n)
- { _cx_self cx = {0}; _cx_memb(_put_n)(&cx, raw, n); return cx; }
-STC_INLINE void _cx_memb(_value_drop)(_cx_value* val) { i_keydrop(val); }
-#if !defined _i_queue
-#if !defined i_no_emplace
-STC_API _cx_iter _cx_memb(_emplace_range)(_cx_self* self, _cx_value* pos,
- const _cx_raw* p1, const _cx_raw* p2);
-#endif // i_no_emplace
-
-#if !defined i_no_cmp || defined _i_has_eq
-STC_API _cx_iter _cx_memb(_find_in)(_cx_iter p1, _cx_iter p2, _cx_raw raw);
-#endif
-#ifndef i_no_cmp
-STC_API int _cx_memb(_value_cmp)(const _cx_value* x, const _cx_value* y);
-#endif
-STC_API _cx_value* _cx_memb(_push_front)(_cx_self* self, i_key value);
-STC_API _cx_iter _cx_memb(_erase_range_p)(_cx_self* self, _cx_value* p1, _cx_value* p2);
-STC_API _cx_iter _cx_memb(_insert_range)(_cx_self* self, _cx_value* pos,
- const _cx_value* p1, const _cx_value* p2);
-#endif // !_i_queue
+#undef _pop
-#if !defined i_no_emplace
-STC_INLINE _cx_value* _cx_memb(_emplace)(_cx_self* self, _cx_raw raw)
- { return _cx_memb(_push)(self, i_keyfrom(raw)); }
-#endif
+STC_API _cx_value* _cx_memb(_push_front)(_cx_self* self, i_key value);
+STC_API _cx_iter _cx_memb(_insert_n)(_cx_self* self, intptr_t idx, const _cx_value* arr, intptr_t n);
+STC_API _cx_iter _cx_memb(_emplace_n)(_cx_self* self, intptr_t idx, const _cx_raw* raw, intptr_t n);
+STC_API _cx_iter _cx_memb(_insert_uninit)(_cx_self* self, intptr_t idx, intptr_t n);
+STC_API void _cx_memb(_erase_n)(_cx_self* self, intptr_t idx, intptr_t n);
-#if !defined i_no_clone
-#if !defined _i_queue
-STC_API _cx_iter _cx_memb(_copy_range)(_cx_self* self, _cx_value* pos,
- const _cx_value* p1, const _cx_value* p2);
+STC_INLINE const _cx_value*
+_cx_memb(_at)(const _cx_self* self, intptr_t idx)
+ { return self->data + _cdeq_topos(self, idx); }
-STC_INLINE void _cx_memb(_copy)(_cx_self *self, const _cx_self* other) {
- if (self->data == other->data) return;
- _cx_memb(_clear)(self);
- _cx_memb(_copy_range)(self, self->data,
- other->data, other->data + other->_len);
- }
-#endif // !_i_queue
-STC_API _cx_self _cx_memb(_clone)(_cx_self cx);
-STC_INLINE i_key _cx_memb(_value_clone)(i_key val)
- { return i_keyclone(val); }
-#endif // !i_no_clone
-STC_INLINE intptr_t _cx_memb(_size)(const _cx_self* self) { return self->_len; }
-STC_INLINE intptr_t _cx_memb(_capacity)(const _cx_self* self) { return self->_cap; }
-STC_INLINE bool _cx_memb(_empty)(const _cx_self* self) { return !self->_len; }
-STC_INLINE _cx_raw _cx_memb(_value_toraw)(const _cx_value* pval) { return i_keyto(pval); }
-STC_INLINE _cx_value* _cx_memb(_front)(const _cx_self* self) { return self->data; }
-STC_INLINE _cx_value* _cx_memb(_back)(const _cx_self* self)
- { return self->data + self->_len - 1; }
-STC_INLINE void _cx_memb(_pop_front)(_cx_self* self) // == _pop() when _i_queue
- { i_keydrop(self->data); ++self->data; --self->_len; }
+STC_INLINE _cx_value*
+_cx_memb(_at_mut)(_cx_self* self, intptr_t idx)
+ { return self->data + _cdeq_topos(self, idx); }
-STC_INLINE _cx_iter _cx_memb(_begin)(const _cx_self* self) {
- intptr_t n = self->_len;
- return c_LITERAL(_cx_iter){n ? self->data : NULL, self->data + n};
+STC_INLINE _cx_value*
+_cx_memb(_push_back)(_cx_self* self, _cx_value val) {
+ return _cx_memb(_push)(self, val);
}
-STC_INLINE _cx_iter _cx_memb(_end)(const _cx_self* self)
- { return c_LITERAL(_cx_iter){NULL, self->data + self->_len}; }
-
-STC_INLINE void _cx_memb(_next)(_cx_iter* it)
- { if (++it->ref == it->end) it->ref = NULL; }
-
-STC_INLINE _cx_iter _cx_memb(_advance)(_cx_iter it, size_t n)
- { if ((it.ref += n) >= it.end) it.ref = NULL; return it; }
-
-#if !defined _i_queue
-
-STC_INLINE intptr_t _cx_memb(_index)(const _cx_self* self, _cx_iter it)
- { return (it.ref - self->data); }
-STC_INLINE void _cx_memb(_pop_back)(_cx_self* self)
- { _cx_value* p = &self->data[--self->_len]; i_keydrop(p); }
-
-STC_INLINE const _cx_value* _cx_memb(_at)(const _cx_self* self, const intptr_t idx) {
- assert(idx < self->_len); return self->data + idx;
-}
-STC_INLINE _cx_value* _cx_memb(_at_mut)(_cx_self* self, const intptr_t idx) {
- assert(idx < self->_len); return self->data + idx;
+STC_INLINE void
+_cx_memb(_pop_back)(_cx_self* self) {
+ assert(!_cx_memb(_empty)(self));
+ self->end = (self->end - 1) & self->capmask;
+ i_keydrop((self->data + self->end));
}
-STC_INLINE _cx_value* _cx_memb(_push_back)(_cx_self* self, i_key value) {
- return _cx_memb(_push)(self, value);
-}
-STC_INLINE _cx_iter
-_cx_memb(_insert)(_cx_self* self, const intptr_t idx, i_key value) {
- return _cx_memb(_insert_range)(self, self->data + idx, &value, &value + 1);
-}
-STC_INLINE _cx_iter
-_cx_memb(_insert_n)(_cx_self* self, const intptr_t idx, const _cx_value arr[], const intptr_t n) {
- return _cx_memb(_insert_range)(self, self->data + idx, arr, arr + n);
-}
STC_INLINE _cx_iter
-_cx_memb(_insert_at)(_cx_self* self, _cx_iter it, i_key value) {
- return _cx_memb(_insert_range)(self, _it_ptr(it), &value, &value + 1);
+_cx_memb(_insert_at)(_cx_self* self, _cx_iter it, const _cx_value val) {
+ intptr_t idx = _cdeq_toidx(self, it.pos);
+ return _cx_memb(_insert_n)(self, idx, &val, 1);
}
STC_INLINE _cx_iter
-_cx_memb(_erase_n)(_cx_self* self, const intptr_t idx, const intptr_t n) {
- return _cx_memb(_erase_range_p)(self, self->data + idx, self->data + idx + n);
-}
-STC_INLINE _cx_iter
_cx_memb(_erase_at)(_cx_self* self, _cx_iter it) {
- return _cx_memb(_erase_range_p)(self, it.ref, it.ref + 1);
+ _cx_memb(_erase_n)(self, _cdeq_toidx(self, it.pos), 1);
+ if (it.pos == self->end) it.ref = NULL;
+ return it;
}
+
STC_INLINE _cx_iter
-_cx_memb(_erase_range)(_cx_self* self, _cx_iter i1, _cx_iter i2) {
- return _cx_memb(_erase_range_p)(self, i1.ref, _it2_ptr(i1, i2));
+_cx_memb(_erase_range)(_cx_self* self, _cx_iter it1, _cx_iter it2) {
+ intptr_t idx1 = _cdeq_toidx(self, it1.pos);
+ intptr_t idx2 = _cdeq_toidx(self, it2.pos);
+ _cx_memb(_erase_n)(self, idx1, idx2 - idx1);
+ if (it1.pos == self->end) it1.ref = NULL;
+ return it1;
}
#if !defined i_no_emplace
STC_INLINE _cx_value*
-_cx_memb(_emplace_front)(_cx_self* self, _cx_raw raw) {
- return _cx_memb(_push_front)(self, i_keyfrom(raw));
-}
+_cx_memb(_emplace_front)(_cx_self* self, const _cx_raw raw)
+ { return _cx_memb(_push_front)(self, i_keyfrom(raw)); }
-STC_INLINE _cx_value* _cx_memb(_emplace_back)(_cx_self* self, _cx_raw raw) {
- return _cx_memb(_push)(self, i_keyfrom(raw));
-}
+STC_INLINE _cx_value*
+_cx_memb(_emplace_back)(_cx_self* self, const _cx_raw raw)
+ { return _cx_memb(_push)(self, i_keyfrom(raw)); }
STC_INLINE _cx_iter
-_cx_memb(_emplace_n)(_cx_self* self, const intptr_t idx, const _cx_raw arr[], const intptr_t n) {
- return _cx_memb(_emplace_range)(self, self->data + idx, arr, arr + n);
-}
-STC_INLINE _cx_iter
-_cx_memb(_emplace_at)(_cx_self* self, _cx_iter it, _cx_raw raw) {
- return _cx_memb(_emplace_range)(self, _it_ptr(it), &raw, &raw + 1);
-}
-#endif // !i_no_emplace
+_cx_memb(_emplace_at)(_cx_self* self, _cx_iter it, const _cx_raw raw)
+ { return _cx_memb(_insert_at)(self, it, i_keyfrom(raw)); }
+#endif
-#if !defined i_no_cmp || defined _i_has_eq
+#if defined _i_has_eq || defined _i_has_cmp
+STC_API _cx_iter _cx_memb(_find_in)(_cx_iter p1, _cx_iter p2, _cx_raw raw);
+STC_API bool _cx_memb(_eq)(const _cx_self* self, const _cx_self* other);
STC_INLINE _cx_iter
_cx_memb(_find)(const _cx_self* self, _cx_raw raw) {
@@ -194,253 +110,88 @@ _cx_memb(_get)(const _cx_self* self, _cx_raw raw) {
STC_INLINE _cx_value*
_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* 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;
-}
#endif
-#ifndef i_no_cmp
-
-STC_INLINE void
-_cx_memb(_sort_range)(_cx_iter i1, _cx_iter i2, int(*cmp)(const _cx_value*, const _cx_value*)) {
- qsort(i1.ref, (size_t)(_it2_ptr(i1, i2) - i1.ref), sizeof *i1.ref,
- (int(*)(const void*, const void*)) cmp);
-}
-
-STC_INLINE void
-_cx_memb(_sort)(_cx_self* self) {
- _cx_memb(_sort_range)(_cx_memb(_begin)(self), _cx_memb(_end)(self), _cx_memb(_value_cmp));
-}
-#endif // !c_no_cmp
-#endif // _i_queue
/* -------------------------- IMPLEMENTATION ------------------------- */
#if defined(i_implement)
-#define _cdeq_nfront(self) ((self)->data - (self)->_base)
-
-STC_DEF _cx_self
-_cx_memb(_init)(void) {
- _cx_self cx = {NULL};
- return cx;
-}
-
-STC_DEF void
-_cx_memb(_clear)(_cx_self* self) {
- if (self->_cap) {
- for (_cx_value *p = self->data, *q = p + self->_len; p != q; )
- { --q; i_keydrop(q); }
- self->_len = 0;
- self->data = self->_base;
- }
-}
-
-STC_DEF void
-_cx_memb(_shrink_to_fit)(_cx_self *self) {
- if (self->_len != self->_cap) {
- c_memmove(self->_base, self->data, self->_len*c_sizeof(i_key));
- _cx_value* d = (_cx_value*)i_realloc(self->_base, self->_len*c_sizeof(i_key));
- if (d) {
- self->_base = d;
- self->_cap = self->_len;
- }
- self->data = self->_base;
- }
-}
-
-STC_DEF void
-_cx_memb(_drop)(_cx_self* self) {
- if (self->_base) {
- _cx_memb(_clear)(self);
- i_free(self->_base);
- }
-}
-
-static intptr_t
-_cx_memb(_realloc_)(_cx_self* self, const intptr_t n) {
- const intptr_t cap = (intptr_t)((float)self->_len*1.7f) + n + 7;
- const intptr_t nfront = _cdeq_nfront(self);
- _cx_value* d = (_cx_value*)i_realloc(self->_base, cap*c_sizeof(i_key));
- if (!d)
- return 0;
- self->_cap = cap;
- self->_base = d;
- self->data = d + nfront;
- return cap;
-}
-
-static bool
-_cx_memb(_expand_right_half_)(_cx_self* self, const intptr_t idx, const intptr_t n) {
- const intptr_t sz = self->_len, cap = self->_cap;
- const intptr_t nfront = _cdeq_nfront(self), nback = cap - sz - nfront;
- if (nback >= n || (intptr_t)((float)sz*1.3f) + n > cap) {
- if (!_cx_memb(_realloc_)(self, n))
- return false;
- c_memmove(self->data + idx + n, self->data + idx, (sz - idx)*c_sizeof(i_key));
- } else {
-#if !defined _i_queue
- const intptr_t unused = cap - (sz + n);
- const intptr_t pos = (nfront*2 < unused) ? nfront : unused/2;
-#else
- const intptr_t pos = 0;
-#endif
- c_memmove(self->_base + pos, self->data, idx*c_sizeof(i_key));
- c_memmove(self->data + pos + idx + n, self->data + idx, (sz - idx)*c_sizeof(i_key));
- self->data = self->_base + pos;
- }
- return true;
-}
-
-STC_DEF _cx_self
-_cx_memb(_with_capacity)(const intptr_t n) {
- _cx_self cx = _cx_memb(_init)();
- _cx_memb(_expand_right_half_)(&cx, 0, n);
- return cx;
-}
-
-STC_DEF bool
-_cx_memb(_reserve)(_cx_self* self, const intptr_t n) {
- const intptr_t sz = self->_len;
- return n <= sz || _cx_memb(_expand_right_half_)(self, sz, n - sz);
-}
STC_DEF _cx_value*
-_cx_memb(_push)(_cx_self* self, i_key value) {
- if (_cdeq_nfront(self) + self->_len == self->_cap)
- _cx_memb(_expand_right_half_)(self, self->_len, 1);
- _cx_value *v = self->data + self->_len++;
+_cx_memb(_push_front)(_cx_self* self, i_key value) {
+ intptr_t start = (self->start - 1) & self->capmask;
+ if (start == self->end) { // full
+ _cx_memb(_reserve)(self, self->capmask + 3); // => 2x expand
+ start = (self->start - 1) & self->capmask;
+ }
+ _cx_value *v = self->data + start;
+ self->start = start;
*v = value;
return v;
}
-#if !defined i_no_clone
-STC_DEF _cx_self
-_cx_memb(_clone)(_cx_self cx) {
- _cx_self out = _cx_memb(_with_capacity)(cx._len);
- if (out._base)
- for (intptr_t i = 0; i < cx._len; ++i)
- out.data[i] = i_keyclone(cx.data[i]);
- return out;
-}
-#endif
-
-#if !defined _i_queue
-
-static void
-_cx_memb(_expand_left_half_)(_cx_self* self, const intptr_t idx, const intptr_t n) {
- intptr_t cap = self->_cap;
- const intptr_t sz = self->_len;
- const intptr_t nfront = _cdeq_nfront(self), nback = cap - sz - nfront;
- if (nfront >= n) {
- self->data = (_cx_value *)c_memmove(self->data - n, self->data, idx*c_sizeof(i_key));
- } else {
- if ((intptr_t)((float)sz*1.3f) + n > cap)
- cap = _cx_memb(_realloc_)(self, n);
- const intptr_t unused = cap - (sz + n);
- const intptr_t pos = (nback*2 < unused) ? unused - nback : unused/2;
- c_memmove(self->_base + pos + idx + n, self->data + idx, (sz - idx)*c_sizeof(i_key));
- self->data = (_cx_value *)c_memmove(self->_base + pos, self->data, idx*c_sizeof(i_key));
- }
-}
-
-static _cx_iter
-_cx_memb(_insert_uninit)(_cx_self* self, _cx_value* pos, const intptr_t n) {
- if (n) {
- if (!pos) pos = self->data + self->_len;
- const intptr_t idx = (pos - self->data);
- if (idx*2 < self->_len)
- _cx_memb(_expand_left_half_)(self, idx, n);
- else
- _cx_memb(_expand_right_half_)(self, idx, n);
- self->_len += n;
- pos = self->data + idx;
- }
- return c_LITERAL(_cx_iter){pos, self->data + self->_len};
-}
-
-STC_DEF _cx_value*
-_cx_memb(_push_front)(_cx_self* self, i_key value) {
- if (self->data == self->_base)
- _cx_memb(_expand_left_half_)(self, 0, 1);
- else
- --self->data;
- ++self->_len;
- *self->data = value;
- return self->data;
+STC_DEF void
+_cx_memb(_erase_n)(_cx_self* self, const intptr_t idx, const intptr_t n) {
+ const intptr_t len = _cx_memb(_size)(self);
+ for (intptr_t i = idx + n - 1; i >= idx; --i)
+ i_keydrop(_cx_memb(_at_mut)(self, i));
+ for (intptr_t i = idx, j = i + n; j < len; ++i, ++j)
+ *_cx_memb(_at_mut)(self, i) = *_cx_memb(_at)(self, j);
+ self->end = (self->end - n) & self->capmask;
}
STC_DEF _cx_iter
-_cx_memb(_insert_range)(_cx_self* self, _cx_value* pos,
- const _cx_value* p1, const _cx_value* p2) {
- _cx_iter it = _cx_memb(_insert_uninit)(self, pos, (p2 - p1));
- if (it.ref)
- c_memcpy(it.ref, p1, (p2 - p1)*c_sizeof *p1);
+_cx_memb(_insert_uninit)(_cx_self* self, const intptr_t idx, const intptr_t n) {
+ const intptr_t len = _cx_memb(_size)(self);
+ _cx_iter it = {._s=self};
+ if (len + n > self->capmask)
+ if (!_cx_memb(_reserve)(self, len + n))
+ return it;
+ for (intptr_t j = len - 1, i = j + n; j >= idx; --j, --i)
+ *_cx_memb(_at_mut)(self, i) = *_cx_memb(_at)(self, j);
+ self->end = (self->end + n) & self->capmask;
+ it.pos = _cdeq_topos(self, idx);
+ it.ref = self->data + it.pos;
return it;
}
STC_DEF _cx_iter
-_cx_memb(_erase_range_p)(_cx_self* self, _cx_value* p1, _cx_value* p2) {
- assert(p1 && p2);
- intptr_t len = p2 - p1;
- _cx_value* p = p1, *end = self->data + self->_len;
- for (; p != p2; ++p)
- { i_keydrop(p); }
- c_memmove(p1, p2, (end - p2)*c_sizeof *p1);
- self->_len -= len;
- return c_LITERAL(_cx_iter){p2 == end ? NULL : p1, end - len};
-}
-
-#if !defined i_no_clone
-STC_DEF _cx_iter
-_cx_memb(_copy_range)(_cx_self* self, _cx_value* pos,
- const _cx_value* p1, const _cx_value* p2) {
- _cx_iter it = _cx_memb(_insert_uninit)(self, pos, (p2 - p1));
- if (it.ref)
- for (_cx_value* p = it.ref; p1 != p2; ++p1)
- *p++ = i_keyclone((*p1));
+_cx_memb(_insert_n)(_cx_self* self, const intptr_t idx, const _cx_value* arr, const intptr_t n) {
+ _cx_iter it = _cx_memb(_insert_uninit)(self, idx, n);
+ for (intptr_t i = idx, j = 0; j < n; ++i, ++j)
+ *_cx_memb(_at_mut)(self, i) = arr[j];
return it;
}
-#endif // !i_no_clone
-#if !defined i_no_emplace
STC_DEF _cx_iter
-_cx_memb(_emplace_range)(_cx_self* self, _cx_value* pos,
- const _cx_raw* p1, const _cx_raw* p2) {
- _cx_iter it = _cx_memb(_insert_uninit)(self, pos, (p2 - p1));
- if (it.ref)
- for (_cx_value* p = it.ref; p1 != p2; ++p1)
- *p++ = i_keyfrom((*p1));
+_cx_memb(_emplace_n)(_cx_self* self, const intptr_t idx, const _cx_raw* raw, const intptr_t n) {
+ _cx_iter it = _cx_memb(_insert_uninit)(self, idx, n);
+ for (intptr_t i = idx, j = 0; j < n; ++i, ++j)
+ *_cx_memb(_at_mut)(self, i) = i_keyfrom(raw[j]);
return it;
}
-#endif // !i_no_emplace
-#if !defined i_no_cmp || defined _i_has_eq
+#if defined _i_has_eq || defined _i_has_cmp
STC_DEF _cx_iter
_cx_memb(_find_in)(_cx_iter i1, _cx_iter i2, _cx_raw raw) {
- const _cx_value* p2 = _it2_ptr(i1, i2);
- for (; i1.ref != p2; ++i1.ref) {
+ for (; i1.ref; _cx_memb(_next)(&i1)) {
const _cx_raw r = i_keyto(i1.ref);
if (i_eq((&raw), (&r)))
- return i1;
+ break;
}
- i2.ref = NULL;
- return i2;
+ return i1;
}
-#endif
-#ifndef i_no_cmp
-STC_DEF int
-_cx_memb(_value_cmp)(const _cx_value* x, const _cx_value* y) {
- const _cx_raw rx = i_keyto(x);
- const _cx_raw ry = i_keyto(y);
- return i_cmp((&rx), (&ry));
+
+STC_DEF bool
+_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), j = _cx_memb(_begin)(other);
+ i.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;
+ }
+ return true;
}
-#endif // !c_no_cmp
-#endif // !_i_queue
+#endif
#endif // IMPLEMENTATION
#define CDEQ_H_INCLUDED
#include "priv/template2.h"
diff --git a/include/stc/clist.h b/include/stc/clist.h
index 65a1ac87..128e848d 100644
--- a/include/stc/clist.h
+++ b/include/stc/clist.h
@@ -109,8 +109,9 @@ STC_API _cx_value* _cx_memb(_push_back_node)(_cx_self* self, _cx_node* node
STC_API _cx_value* _cx_memb(_insert_after_node)(_cx_self* self, _cx_node* ref, _cx_node* node);
STC_API _cx_node* _cx_memb(_unlink_after_node)(_cx_self* self, _cx_node* ref);
STC_API void _cx_memb(_erase_after_node)(_cx_self* self, _cx_node* ref);
-STC_INLINE _cx_node* _cx_memb(_get_node)(_cx_value* vp) { return _clist_tonode(vp); }
-
+STC_INLINE _cx_node* _cx_memb(_get_node)(_cx_value* pval) { return _clist_tonode(pval); }
+STC_INLINE _cx_node* _cx_memb(_unlink_front_node)(_cx_self* self)
+ { return _cx_memb(_unlink_after_node)(self, self->last); }
#if !defined i_no_clone
STC_API _cx_self _cx_memb(_clone)(_cx_self cx);
STC_INLINE i_key _cx_memb(_value_clone)(i_key val) { return i_keyclone(val); }
@@ -144,10 +145,10 @@ STC_INLINE _cx_value* _cx_memb(_push)(_cx_self* self, i_key value)
{ return _cx_memb(_push_back)(self, value); }
STC_INLINE void _cx_memb(_pop_front)(_cx_self* self)
{ assert(!_cx_memb(_empty)(self)); _cx_memb(_erase_after_node)(self, self->last); }
-STC_INLINE _cx_node* _cx_memb(_unlink_node_front)(_cx_self* self)
- { return _cx_memb(_unlink_after_node)(self, self->last); }
STC_INLINE _cx_value* _cx_memb(_front)(const _cx_self* self) { return &self->last->next->value; }
STC_INLINE _cx_value* _cx_memb(_back)(const _cx_self* self) { return &self->last->value; }
+STC_INLINE _cx_raw _cx_memb(_value_toraw)(const _cx_value* pval) { return i_keyto(pval); }
+STC_INLINE void _cx_memb(_value_drop)(_cx_value* pval) { i_keydrop(pval); }
STC_INLINE intptr_t
_cx_memb(_count)(const _cx_self* self) {
diff --git a/include/stc/cmap.h b/include/stc/cmap.h
index ec3238f6..4ba6156b 100644
--- a/include/stc/cmap.h
+++ b/include/stc/cmap.h
@@ -276,13 +276,6 @@ STC_INLINE intptr_t fastrange_1(uint64_t x, uint64_t n)
STC_INLINE intptr_t fastrange_2(uint64_t x, uint64_t n)
{ return (intptr_t)(x & (n - 1)); } // n power of 2.
-STC_INLINE uint64_t next_power_of_2(uint64_t n) {
- n--;
- n |= n >> 1, n |= n >> 2;
- n |= n >> 4, n |= n >> 8;
- n |= n >> 16, n |= n >> 32;
- return n + 1;
-}
#endif // CMAP_H_INCLUDED
STC_DEF _cx_iter _cx_memb(_begin)(const _cx_self* self) {
@@ -422,7 +415,7 @@ _cx_memb(_reserve)(_cx_self* self, const intptr_t _newcap) {
return true;
intptr_t _newbucks = (intptr_t)((float)_newcap / (i_max_load_factor)) | 1;
#if i_expandby == 2
- _newbucks = (intptr_t)next_power_of_2((uint64_t)_newbucks);
+ _newbucks = cnextpow2(_newbucks);
#endif
_cx_self m = {
(_cx_value *)i_malloc(_newbucks*c_sizeof(_cx_value)),
diff --git a/include/stc/cqueue.h b/include/stc/cqueue.h
index 254bc834..09a747e5 100644
--- a/include/stc/cqueue.h
+++ b/include/stc/cqueue.h
@@ -20,44 +20,198 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
-// STC queue
-/*
-#include <stc/crand.h>
-#include <stdio.h>
-
-#define i_key int
-#include <stc/cqueue.h>
-
-int main() {
- int n = 10000000;
- crand_t rng = crand_init(1234);
- crand_unif_t dist = crand_unif_init(0, n);
-
- c_auto (cqueue_int, Q)
- {
- // Push ten million random numbers onto the queue.
- for (int i=0; i<n; ++i)
- cqueue_int_push(&Q, crand_unif(&rng, &dist));
-
- // Push or pop on the queue ten million times
- printf("before: size, capacity: %d, %d\n", n, cqueue_int_size(&Q), cqueue_int_capacity(&Q));
- for (int i=n; i>0; --i) {
- int r = crand_unif(&rng, &dist);
- if (r & 1)
- ++n, cqueue_int_push(&Q, r);
- else
- --n, cqueue_int_pop(&Q);
- }
- printf("after: size, capacity: %d, %d\n", n, cqueue_int_size(&Q), cqueue_int_capacity(&Q));
+#include "ccommon.h"
+
+#ifndef CQUEUE_H_INCLUDED
+#include "forward.h"
+#include <stdlib.h>
+#include <string.h>
+#endif // CQUEUE_H_INCLUDED
+
+#ifndef _i_prefix
+#define _i_prefix cqueue_
+#endif
+#include "priv/template.h"
+
+#ifndef i_is_forward
+_cx_deftypes(_c_cdeq_types, _cx_self, i_key);
+#endif
+typedef i_keyraw _cx_raw;
+
+STC_API _cx_self _cx_memb(_with_capacity)(const intptr_t n);
+STC_API bool _cx_memb(_reserve)(_cx_self* self, const intptr_t n);
+STC_API void _cx_memb(_clear)(_cx_self* self);
+STC_API void _cx_memb(_drop)(_cx_self* self);
+STC_API _cx_value* _cx_memb(_push)(_cx_self* self, i_key value); // push_back
+STC_API void _cx_memb(_shrink_to_fit)(_cx_self *self);
+STC_API _cx_iter _cx_memb(_advance)(_cx_iter it, intptr_t n);
+
+#define _cdeq_toidx(self, pos) (((pos) - (self)->start) & (self)->capmask)
+#define _cdeq_topos(self, idx) (((self)->start + (idx)) & (self)->capmask)
+
+STC_INLINE _cx_self _cx_memb(_init)(void)
+ { _cx_self cx = {0}; return cx; }
+STC_INLINE void _cx_memb(_put_n)(_cx_self* self, const _cx_raw* raw, intptr_t n)
+ { while (n--) _cx_memb(_push)(self, i_keyfrom(*raw++)); }
+STC_INLINE _cx_self _cx_memb(_from_n)(const _cx_raw* raw, intptr_t n)
+ { _cx_self cx = {0}; _cx_memb(_put_n)(&cx, raw, n); return cx; }
+STC_INLINE void _cx_memb(_value_drop)(_cx_value* val) { i_keydrop(val); }
+
+#if !defined i_no_emplace
+STC_INLINE _cx_value* _cx_memb(_emplace)(_cx_self* self, _cx_raw raw)
+ { return _cx_memb(_push)(self, i_keyfrom(raw)); }
+#endif
+
+#if !defined i_no_clone
+STC_API _cx_self _cx_memb(_clone)(_cx_self cx);
+STC_INLINE i_key _cx_memb(_value_clone)(i_key val)
+ { return i_keyclone(val); }
+#endif // !i_no_clone
+STC_INLINE intptr_t _cx_memb(_size)(const _cx_self* self)
+ { return _cdeq_toidx(self, self->end); }
+STC_INLINE intptr_t _cx_memb(_capacity)(const _cx_self* self)
+ { return self->capmask; }
+STC_INLINE bool _cx_memb(_empty)(const _cx_self* self)
+ { return self->start == self->end; }
+STC_INLINE _cx_raw _cx_memb(_value_toraw)(const _cx_value* pval)
+ { return i_keyto(pval); }
+
+STC_INLINE _cx_value*
+_cx_memb(_front)(const _cx_self* self)
+ { return self->data + self->start; }
+
+STC_INLINE _cx_value*
+_cx_memb(_back)(const _cx_self* self)
+ { return self->data + ((self->end - 1) & self->capmask); }
+
+STC_INLINE void
+_cx_memb(_pop)(_cx_self* self) { // pop_front
+ c_ASSERT(!_cx_memb(_empty)(self));
+ i_keydrop((self->data + self->start));
+ self->start = (self->start + 1) & self->capmask;
+}
+
+STC_INLINE void _cx_memb(_copy)(_cx_self* self, const _cx_self* other) {
+ if (self->data == other->data) return;
+ _cx_memb(_drop)(self);
+ *self = _cx_memb(_clone)(*other);
+}
+
+STC_INLINE _cx_iter
+_cx_memb(_begin)(const _cx_self* self) {
+ return c_LITERAL(_cx_iter){
+ _cx_memb(_empty)(self) ? NULL : self->data + self->start,
+ self->start, self
+ };
+}
+
+STC_INLINE _cx_iter
+_cx_memb(_end)(const _cx_self* self)
+ { return c_LITERAL(_cx_iter){NULL, self->end, self}; }
+
+STC_INLINE void
+_cx_memb(_next)(_cx_iter* it) {
+ if (it->pos != it->_s->capmask) { ++it->ref; ++it->pos; }
+ else { it->ref -= it->pos; it->pos = 0; }
+ if (it->pos == it->_s->end) it->ref = NULL;
+}
+
+/* -------------------------- IMPLEMENTATION ------------------------- */
+#if defined(i_implement)
+
+STC_DEF _cx_iter _cx_memb(_advance)(_cx_iter it, intptr_t n) {
+ intptr_t len = _cx_memb(_size)(it._s);
+ intptr_t pos = it.pos, idx = _cdeq_toidx(it._s, pos);
+ it.pos = (pos + n) & it._s->capmask;
+ it.ref += it.pos - pos;
+ if (!c_LTu(idx + n, len)) it.ref = NULL;
+ return it;
+}
+
+STC_DEF void
+_cx_memb(_clear)(_cx_self* self) {
+ c_foreach (i, _cx_self, *self)
+ { i_keydrop(i.ref); }
+ self->start = 0, self->end = 0;
+}
+
+STC_DEF void
+_cx_memb(_drop)(_cx_self* self) {
+ _cx_memb(_clear)(self);
+ i_free(self->data);
+}
+
+STC_DEF _cx_self
+_cx_memb(_with_capacity)(const intptr_t n) {
+ _cx_self cx = {0};
+ _cx_memb(_reserve)(&cx, n);
+ return cx;
+}
+
+STC_DEF bool
+_cx_memb(_reserve)(_cx_self* self, const intptr_t n) {
+ if (n <= self->capmask)
+ return true;
+ intptr_t oldcap = self->capmask + 1, newcap = cnextpow2(n + 1);
+ _cx_value* data = (_cx_value *)i_realloc(self->data, newcap*c_sizeof *self->data);
+ if (!data)
+ return false;
+ intptr_t head = oldcap - self->start;
+ if (self->start < self->end || self->start == 0)
+ ;
+ else if (head < self->end) {
+ self->start = newcap - head;
+ c_memmove(data + self->start, data + oldcap - head, head*c_sizeof *data);
+ } else {
+ c_memmove(data + oldcap, data, self->end*c_sizeof *data);
+ self->end += oldcap;
}
+ self->capmask = newcap - 1;
+ self->data = data;
+ return true;
}
-*/
-#define _i_prefix cqueue_
-#define _i_queue
-#define _pop_front _pop
+STC_DEF _cx_value*
+_cx_memb(_push)(_cx_self* self, i_key value) { // push_back
+ intptr_t end = (self->end + 1) & self->capmask;
+ if (end == self->start) { // full
+ _cx_memb(_reserve)(self, self->capmask + 3); // => 2x expand
+ end = (self->end + 1) & self->capmask;
+ }
+ _cx_value *v = self->data + self->end;
+ self->end = end;
+ *v = value;
+ return v;
+}
+
+STC_DEF void
+_cx_memb(_shrink_to_fit)(_cx_self *self) {
+ intptr_t sz = _cx_memb(_size)(self), j = 0;
+ if (sz > self->capmask/2)
+ return;
+ _cx_self out = _cx_memb(_with_capacity)(sz);
+ if (!out.data)
+ return;
+ c_foreach (i, _cx_self, *self)
+ out.data[j++] = *i.ref;
+ out.end = sz;
+ i_free(self->data);
+ *self = out;
+}
-#include "cdeq.h"
+#if !defined i_no_clone
+STC_DEF _cx_self
+_cx_memb(_clone)(_cx_self cx) {
+ intptr_t sz = _cx_memb(_size)(&cx), j = 0;
+ _cx_self out = _cx_memb(_with_capacity)(sz);
+ if (out.data)
+ c_foreach (i, _cx_self, cx)
+ out.data[j++] = i_keyclone((*i.ref));
+ out.end = sz;
+ return out;
+}
-#undef _pop_front
-#undef _i_queue
+#endif // i_no_clone
+#endif // IMPLEMENTATION
+#include "priv/template2.h"
+#define CQUEUE_H_INCLUDED
diff --git a/include/stc/cvec.h b/include/stc/cvec.h
index 3cbd90b7..a7eb1a05 100644
--- a/include/stc/cvec.h
+++ b/include/stc/cvec.h
@@ -81,10 +81,8 @@ STC_API void _cx_memb(_clear)(_cx_self* self);
STC_API bool _cx_memb(_reserve)(_cx_self* self, intptr_t cap);
STC_API bool _cx_memb(_resize)(_cx_self* self, intptr_t size, i_key null);
STC_API _cx_value* _cx_memb(_push)(_cx_self* self, i_key value);
-STC_API _cx_iter _cx_memb(_erase_range_p)(_cx_self* self, _cx_value* p1, _cx_value* p2);
-STC_API _cx_iter _cx_memb(_insert_range)(_cx_self* self, _cx_value* pos,
- const _cx_value* p1, const _cx_value* p2);
-STC_API _cx_iter _cx_memb(_insert_uninit)(_cx_self* self, _cx_value* pos, const intptr_t n);
+STC_API _cx_iter _cx_memb(_erase_n)(_cx_self* self, intptr_t idx, intptr_t n);
+STC_API _cx_iter _cx_memb(_insert_uninit)(_cx_self* self, intptr_t idx, intptr_t n);
#if !defined i_no_cmp || defined _i_has_eq
STC_API _cx_iter _cx_memb(_find_in)(_cx_iter it1, _cx_iter it2, _cx_raw raw);
#endif
@@ -95,26 +93,23 @@ STC_API _cx_iter _cx_memb(_binary_search_in)(_cx_iter it1, _cx_iter it2,
STC_INLINE void _cx_memb(_value_drop)(_cx_value* val) { i_keydrop(val); }
#if !defined i_no_emplace
-STC_API _cx_iter _cx_memb(_emplace_range)(_cx_self* self, _cx_value* pos,
- const _cx_raw* p1, const _cx_raw* p2);
-STC_INLINE _cx_value* _cx_memb(_emplace)(_cx_self* self, _cx_raw raw)
- { return _cx_memb(_push)(self, i_keyfrom(raw)); }
-STC_INLINE _cx_value* _cx_memb(_emplace_back)(_cx_self* self, _cx_raw raw)
- { return _cx_memb(_push)(self, i_keyfrom(raw)); }
-STC_INLINE _cx_iter
-_cx_memb(_emplace_n)(_cx_self* self, const intptr_t idx, const _cx_raw arr[], const intptr_t n) {
- return _cx_memb(_emplace_range)(self, self->data + idx, arr, arr + n);
+STC_API _cx_iter
+_cx_memb(_emplace_n)(_cx_self* self, intptr_t idx, const _cx_raw raw[], intptr_t n);
+
+STC_INLINE _cx_value* _cx_memb(_emplace)(_cx_self* self, _cx_raw raw) {
+ return _cx_memb(_push)(self, i_keyfrom(raw));
}
-STC_INLINE _cx_iter
-_cx_memb(_emplace_at)(_cx_self* self, _cx_iter it, _cx_raw raw) {
- return _cx_memb(_emplace_range)(self, _it_ptr(it), &raw, &raw + 1);
+STC_INLINE _cx_value* _cx_memb(_emplace_back)(_cx_self* self, _cx_raw raw) {
+ return _cx_memb(_push)(self, i_keyfrom(raw));
+}
+STC_INLINE _cx_iter _cx_memb(_emplace_at)(_cx_self* self, _cx_iter it, _cx_raw raw) {
+ return _cx_memb(_emplace_n)(self, _it_ptr(it) - self->data, &raw, 1);
}
#endif // !i_no_emplace
#if !defined i_no_clone
STC_API _cx_self _cx_memb(_clone)(_cx_self cx);
-STC_API _cx_iter _cx_memb(_copy_range)(_cx_self* self, _cx_value* pos,
- const _cx_value* p1, const _cx_value* p2);
+STC_API _cx_iter _cx_memb(_copy_n)(_cx_self* self, intptr_t idx, const _cx_value arr[], intptr_t n);
STC_INLINE void _cx_memb(_put_n)(_cx_self* self, const _cx_raw* raw, intptr_t n)
{ while (n--) _cx_memb(_push)(self, i_keyfrom(*raw++)); }
STC_INLINE _cx_self _cx_memb(_from_n)(const _cx_raw* raw, intptr_t n)
@@ -124,8 +119,7 @@ STC_INLINE i_key _cx_memb(_value_clone)(_cx_value val)
STC_INLINE void _cx_memb(_copy)(_cx_self* self, const _cx_self* other) {
if (self->data == other->data) return;
_cx_memb(_clear)(self);
- _cx_memb(_copy_range)(self, self->data, other->data,
- other->data + other->_len);
+ _cx_memb(_copy_n)(self, 0, other->data, other->_len);
}
#endif // !i_no_clone
@@ -161,31 +155,29 @@ _cx_memb(_shrink_to_fit)(_cx_self* self) {
_cx_memb(_reserve)(self, _cx_memb(_size)(self));
}
-
-STC_INLINE _cx_iter
-_cx_memb(_insert)(_cx_self* self, const intptr_t idx, i_key value) {
- return _cx_memb(_insert_range)(self, self->data + idx, &value, &value + 1);
-}
STC_INLINE _cx_iter
_cx_memb(_insert_n)(_cx_self* self, const intptr_t idx, const _cx_value arr[], const intptr_t n) {
- return _cx_memb(_insert_range)(self, self->data + idx, arr, arr + n);
+ _cx_iter it = _cx_memb(_insert_uninit)(self, idx, n);
+ if (it.ref)
+ c_memcpy(it.ref, arr, n*c_sizeof *arr);
+ return it;
}
STC_INLINE _cx_iter
-_cx_memb(_insert_at)(_cx_self* self, _cx_iter it, i_key value) {
- return _cx_memb(_insert_range)(self, _it_ptr(it), &value, &value + 1);
+_cx_memb(_insert)(_cx_self* self, const intptr_t idx, const i_key value) {
+ return _cx_memb(_insert_n)(self, idx, &value, 1);
}
-
STC_INLINE _cx_iter
-_cx_memb(_erase_n)(_cx_self* self, const intptr_t idx, const intptr_t n) {
- return _cx_memb(_erase_range_p)(self, self->data + idx, self->data + idx + n);
+_cx_memb(_insert_at)(_cx_self* self, _cx_iter it, const i_key value) {
+ return _cx_memb(_insert_n)(self, _it_ptr(it) - self->data, &value, 1);
}
+
STC_INLINE _cx_iter
_cx_memb(_erase_at)(_cx_self* self, _cx_iter it) {
- return _cx_memb(_erase_range_p)(self, it.ref, it.ref + 1);
+ return _cx_memb(_erase_n)(self, it.ref - self->data, 1);
}
STC_INLINE _cx_iter
_cx_memb(_erase_range)(_cx_self* self, _cx_iter i1, _cx_iter i2) {
- return _cx_memb(_erase_range_p)(self, i1.ref, _it2_ptr(i1, i2));
+ return _cx_memb(_erase_n)(self, i1.ref - self->data, _it2_ptr(i1, i2) - i1.ref);
}
STC_INLINE const _cx_value*
@@ -329,73 +321,58 @@ _cx_memb(_push)(_cx_self* self, i_key value) {
}
STC_DEF _cx_iter
-_cx_memb(_insert_uninit)(_cx_self* self, _cx_value* pos, const intptr_t n) {
- if (n) {
- if (!pos) pos = self->data + self->_len;
- const intptr_t idx = (pos - self->data);
- if (self->_len + n > self->_cap) {
- if (!_cx_memb(_reserve)(self, self->_len*3/2 + n))
- return _cx_memb(_end)(self);
- pos = self->data + idx;
- }
- c_memmove(pos + n, pos, (self->_len - idx)*c_sizeof *pos);
- self->_len += n;
- }
+_cx_memb(_insert_uninit)(_cx_self* self, const intptr_t idx, const intptr_t n) {
+ if (self->_len + n > self->_cap)
+ if (!_cx_memb(_reserve)(self, self->_len*3/2 + n))
+ return _cx_memb(_end)(self);
+
+ _cx_value* pos = self->data + idx;
+ c_memmove(pos + n, pos, (self->_len - idx)*c_sizeof *pos);
+ self->_len += n;
return c_LITERAL(_cx_iter){pos, self->data + self->_len};
}
STC_DEF _cx_iter
-_cx_memb(_insert_range)(_cx_self* self, _cx_value* pos,
- const _cx_value* p1, const _cx_value* p2) {
- _cx_iter it = _cx_memb(_insert_uninit)(self, pos, (p2 - p1));
- if (it.ref)
- c_memcpy(it.ref, p1, (p2 - p1)*c_sizeof *p1);
- return it;
-}
-
-STC_DEF _cx_iter
-_cx_memb(_erase_range_p)(_cx_self* self, _cx_value* p1, _cx_value* p2) {
- intptr_t len = (p2 - p1);
- _cx_value* p = p1, *end = self->data + self->_len;
- for (; p != p2; ++p)
+_cx_memb(_erase_n)(_cx_self* self, const intptr_t idx, const intptr_t len) {
+ _cx_value* d = self->data + idx, *p = d, *end = self->data + self->_len;
+ for (intptr_t i = 0; i < len; ++i, ++p)
{ i_keydrop(p); }
- c_memmove(p1, p2, (end - p2)*c_sizeof *p1);
+ c_memmove(d, p, (end - p)*c_sizeof *d);
self->_len -= len;
- return c_LITERAL(_cx_iter){p2 == end ? NULL : p1, end - len};
+ return c_LITERAL(_cx_iter){p == end ? NULL : d, end - len};
}
#if !defined i_no_clone
STC_DEF _cx_self
_cx_memb(_clone)(_cx_self cx) {
_cx_self out = _cx_memb(_init)();
- _cx_memb(_copy_range)(&out, out.data, cx.data, cx.data + cx._len);
+ _cx_memb(_copy_n)(&out, 0, cx.data, cx._len);
return out;
}
STC_DEF _cx_iter
-_cx_memb(_copy_range)(_cx_self* self, _cx_value* pos,
- const _cx_value* p1, const _cx_value* p2) {
- _cx_iter it = _cx_memb(_insert_uninit)(self, pos, (p2 - p1));
+_cx_memb(_copy_n)(_cx_self* self, const intptr_t idx,
+ const _cx_value arr[], const intptr_t n) {
+ _cx_iter it = _cx_memb(_insert_uninit)(self, idx, n);
if (it.ref)
- for (_cx_value* p = it.ref; p1 != p2; ++p1)
- *p++ = i_keyclone((*p1));
+ for (_cx_value* p = it.ref, *q = p + n; p != q; ++arr)
+ *p++ = i_keyclone((*arr));
return it;
}
#endif // !i_no_clone
#if !defined i_no_emplace
STC_DEF _cx_iter
-_cx_memb(_emplace_range)(_cx_self* self, _cx_value* pos,
- const _cx_raw* p1, const _cx_raw* p2) {
- _cx_iter it = _cx_memb(_insert_uninit)(self, pos, (p2 - p1));
+_cx_memb(_emplace_n)(_cx_self* self, const intptr_t idx, const _cx_raw raw[], intptr_t n) {
+ _cx_iter it = _cx_memb(_insert_uninit)(self, idx, n);
if (it.ref)
- for (_cx_value* p = it.ref; p1 != p2; ++p1)
- *p++ = i_keyfrom((*p1));
+ for (_cx_value* p = it.ref; n--; ++raw, ++p)
+ *p = i_keyfrom((*raw));
return it;
}
#endif // !i_no_emplace
-
#if !defined i_no_cmp || defined _i_has_eq
+
STC_DEF _cx_iter
_cx_memb(_find_in)(_cx_iter i1, _cx_iter i2, _cx_raw raw) {
const _cx_value* p2 = _it2_ptr(i1, i2);
diff --git a/include/stc/forward.h b/include/stc/forward.h
index b534e48b..9eafb857 100644
--- a/include/stc/forward.h
+++ b/include/stc/forward.h
@@ -81,12 +81,17 @@ typedef union {
#define _c_cdeq_types(SELF, VAL) \
typedef VAL SELF##_value; \
- typedef struct { SELF##_value *ref, *end; } SELF##_iter; \
\
typedef struct SELF { \
- SELF##_value *_base, *data; \
- intptr_t _len, _cap; \
- } SELF
+ SELF##_value *data; \
+ intptr_t start, end, capmask; \
+ } SELF; \
+\
+ typedef struct { \
+ SELF##_value *ref; \
+ intptr_t pos; \
+ const SELF* _s; \
+ } SELF##_iter
#define _c_clist_types(SELF, VAL) \
typedef VAL SELF##_value; \
diff --git a/include/stc/priv/template.h b/include/stc/priv/template.h
index 2605a434..f70281c7 100644
--- a/include/stc/priv/template.h
+++ b/include/stc/priv/template.h
@@ -20,9 +20,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
-#ifdef _i_template
- #error template.h already included
-#endif
+#ifndef _i_template
#define _i_template
#ifndef STC_TEMPLATE_H_INCLUDED
@@ -107,6 +105,9 @@
#ifdef i_eq
#define _i_has_eq
#endif
+#if defined i_cmp || defined i_less
+ #define _i_has_cmp
+#endif
#if defined i_key_str
#define i_keyclass cstr
@@ -288,3 +289,4 @@
#ifndef _i_has_from
#define i_no_emplace
#endif
+#endif
diff --git a/include/stc/priv/template2.h b/include/stc/priv/template2.h
index 2e8a6c8d..66ed7739 100644
--- a/include/stc/priv/template2.h
+++ b/include/stc/priv/template2.h
@@ -20,6 +20,9 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
+#ifdef i_more
+#undef i_more
+#else
#undef i_type
#undef i_tag
#undef i_imp
@@ -74,4 +77,6 @@
#undef _i_expandby
#undef _i_has_from
#undef _i_has_eq
+#undef _i_has_cmp
#undef _i_template
+#endif \ No newline at end of file
diff --git a/misc/benchmarks/various/csort_bench.c b/misc/benchmarks/various/csort_bench.c
index d5d7fa7c..4d1149fc 100644
--- a/misc/benchmarks/various/csort_bench.c
+++ b/misc/benchmarks/various/csort_bench.c
@@ -5,8 +5,12 @@
#ifdef __cplusplus
#include <algorithm>
#endif
+#define NDEBUG
+#define i_type Ints
#define i_val int
-#include <stc/algo/csort.h>
+#define i_more
+#include <stc/cvec.h>
+#include <stc/algo/sort.h>
#define ROTL(d,bits) ((d<<(bits)) | (d>>(8*sizeof(d)-(bits))))
uint64_t romutrio(uint64_t s[3]) {
@@ -21,14 +25,14 @@ static int cmp_int(const void* a, const void* b) {
return c_default_cmp((const int*)a, (const int*)b);
}
-void testsort(int *a, int size, const char *desc) {
+void testsort(Ints *a, int size, const char *desc) {
clock_t t = clock();
#ifdef __cplusplus
- printf("std::sort: "); std::sort(a, a + size);
+ printf("std::sort: "); std::sort(a->data, a->data + size);
#elif defined QSORT
- printf("qsort: "); qsort(a, size, sizeof *a, cmp_int);
+ printf("qsort: "); qsort(a->data, size, sizeof *a->data, cmp_int);
#else
- printf("stc_sort: "); csort_int(a, size);
+ printf("stc_qsort: "); Ints_sort_n(a, size);
#endif
t = clock() - t;
@@ -41,27 +45,27 @@ int main(int argc, char *argv[]) {
size_t i, size = argc > 1 ? strtoull(argv[1], NULL, 0) : 10000000;
uint64_t s[3] = {123456789, 3456789123, 789123456};
- int32_t *a = (int32_t*)malloc(sizeof(*a) * size);
- if (!a) return -1;
+ Ints a = Ints_with_capacity(size);
for (i = 0; i < size; i++)
- a[i] = romutrio(s) & (1U << 30) - 1;
- testsort(a, size, "random");
+ *Ints_push(&a, romutrio(s) & (1U << 30) - 1);
+ testsort(&a, size, "random");
for (i = 0; i < 20; i++)
- printf(" %d", (int)a[i]);
+ printf(" %d", (int)*Ints_at(&a, i));
puts("");
for (i = 0; i < size; i++)
- a[i] = i;
- testsort(a, size, "sorted");
+ *Ints_at_mut(&a, i) = i;
+ testsort(&a, size, "sorted");
for (i = 0; i < size; i++)
- a[i] = size - i;
- testsort(a, size, "reverse sorted");
+ *Ints_at_mut(&a, i) = size - i;
+ testsort(&a, size, "reverse sorted");
for (i = 0; i < size; i++)
- a[i] = 126735;
- testsort(a, size, "constant");
+ *Ints_at_mut(&a, i) = 126735;
+ testsort(&a, size, "constant");
for (i = 0; i < size; i++)
- a[i] = i + 1;
- a[size - 1] = 0;
- testsort(a, size, "rotated");
- free(a);
+ *Ints_at_mut(&a, i) = i + 1;
+ *Ints_at_mut(&a, size - 1) = 0;
+ testsort(&a, size, "rotated");
+
+ Ints_drop(&a);
}
diff --git a/misc/benchmarks/various/cspan_bench.c b/misc/benchmarks/various/cspan_bench.c
index 589df13a..02ae3237 100644
--- a/misc/benchmarks/various/cspan_bench.c
+++ b/misc/benchmarks/various/cspan_bench.c
@@ -1,4 +1,4 @@
-#define STC_NDEBUG
+#define NDEBUG
#include <stc/cspan.h>
#include <stdio.h>
#include <time.h>
diff --git a/misc/examples/printspan.c b/misc/examples/printspan.c
index 7459ac77..60a2d934 100644
--- a/misc/examples/printspan.c
+++ b/misc/examples/printspan.c
@@ -6,8 +6,6 @@
#include <stc/cvec.h>
#define i_val int
#include <stc/cstack.h>
-#define i_val int
-#include <stc/cdeq.h>
#define i_val_str
#include <stc/csset.h>
#include <stc/cspan.h>
@@ -40,9 +38,6 @@ int main()
cstack_int stk = c_make(cstack_int, {1, 2, 3, 4, 5, 6, 7});
printMe( (intspan)cspan_from(&stk) );
- cdeq_int deq = c_make(cdeq_int, {1, 2, 3, 4, 5, 6, 7, 8});
- printMe( (intspan)cspan_from(&deq) );
-
csset_str set = c_make(csset_str, {"5", "7", "4", "3", "8", "2", "1", "9", "6"});
printf("%d:", (int)csset_str_size(&set));
c_foreach (e, csset_str, set)
@@ -52,6 +47,5 @@ int main()
// cleanup
cvec_int_drop(&vec);
cstack_int_drop(&stk);
- cdeq_int_drop(&deq);
csset_str_drop(&set);
}
diff --git a/src/cregex.c b/src/cregex.c
index a1d43944..981a256a 100644
--- a/src/cregex.c
+++ b/src/cregex.c
@@ -1220,7 +1220,7 @@ _build_subst(const char* replace, int nmatch, const csview match[],
if (g < (int)nmatch) {
csview m = mfun && mfun(g, match[g], &mstr) ? cstr_sv(&mstr) : match[g];
if (len + m.size > cap)
- dst = cstr_reserve(subst, cap = cap*3/2 + m.size);
+ dst = cstr_reserve(subst, cap += cap*3/2 + m.size);
for (int i = 0; i < (int)m.size; ++i)
dst[len++] = m.str[i];
}