summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--README.md2
-rw-r--r--docs/carray_api.md3
-rw-r--r--docs/ccommon_api.md15
-rw-r--r--examples/bits.c6
-rw-r--r--examples/bits2.c5
-rw-r--r--examples/cpque.c9
-rw-r--r--examples/new_arr.c9
-rw-r--r--examples/prime.c2
-rw-r--r--examples/regex2.c2
-rw-r--r--examples/regex_replace.c2
-rw-r--r--include/stc/alt/cstr.h10
-rw-r--r--include/stc/carr2.h2
-rw-r--r--include/stc/cbits.h2
-rw-r--r--include/stc/ccommon.h7
-rw-r--r--src/checkauto.l4
15 files changed, 38 insertions, 42 deletions
diff --git a/README.md b/README.md
index 1e52b696..6752f607 100644
--- a/README.md
+++ b/README.md
@@ -371,7 +371,7 @@ and non-emplace methods:
#include <stc/cvec.h> // vector of string (cstr)
...
c_auto (cvec_str, vec) // declare and call cvec_str_init() and defer cvec_str_drop(&vec)
-c_with (cstr s = cstr_new("a string literal"), cstr_drop(&s)) // c_with is a more general c_auto.
+c_autodrop (cstr, s, cstr_new("a string literal")) // like c_auto without auto default init.
{
const char* hello = "Hello";
cvec_str_push_back(&vec, cstr_from(hello); // construct and add string from const char*
diff --git a/docs/carray_api.md b/docs/carray_api.md
index e12cbc4f..fb2c6a89 100644
--- a/docs/carray_api.md
+++ b/docs/carray_api.md
@@ -90,8 +90,7 @@ int main()
// Ex1
int xd = 30, yd = 20, zd = 10;
// define arr3[30][20][10], initialized with zeros.
- c_with (carr3_f arr3 = carr3_f_with_size(xd, yd, zd, 0.0f),
- carr3_f_drop(&arr3)) {
+ c_autodrop (carr3_f, arr3, carr3_f_with_size(xd, yd, zd, 0.0f)) {
arr3.data[5][4][3] = 3.14f;
float *arr1 = arr3.data[5][4];
diff --git a/docs/ccommon_api.md b/docs/ccommon_api.md
index 7721a38d..8a11042b 100644
--- a/docs/ccommon_api.md
+++ b/docs/ccommon_api.md
@@ -3,19 +3,20 @@
The following macros are recommended to use, and they safe/have no side-effects.
## Scope macros (RAII)
-### c_auto, c_with, c_scope, c_defer
+### c_auto, c_autodrop, c_with, c_scope, c_defer
General ***defer*** mechanics for resource acquisition. These macros allows you to specify the
freeing of the resources at the point where the acquisition takes place.
The **checkauto** utility described below, ensures that the `c_auto*` macros are used correctly.
| Usage | Description |
|:---------------------------------------|:----------------------------------------------------------|
-| `c_auto (Type, var...)` | Same as `c_with (Type var=Type_init(), Type_drop(&var))` |
| `c_with (Type var=init, drop)` | Declare `var`. Defer `drop...` to end of scope |
| `c_with (Type var=init, pred, drop)` | Adds a predicate in order to exit early if init failed |
-| `c_scope (init, drop...)` | Execute `init` and defer `drop...` to end of scope |
+| `c_auto (Type, var1,...,var4)` | `c_with (Type var1=Type_init(), Type_drop(&var1))` ... |
+| `c_autodrop (Type, var, init...)` | Like `c_with (Type var=init..., Type_drop(&var))` |
+| `c_scope (init, drop)` | Execute `init` and defer `drop` to end of scope |
| `c_defer (drop...)` | Defer `drop...` to end of scope |
-| `continue` | Exit a `c_auto/c_with/c_scope...` without memory leaks |
+| `continue` | Exit a block above without memory leaks |
For multiple variables, use either multiple **c_with** in sequence, or declare variable outside
scope and use **c_scope**. For convenience, **c_auto** support up to 4 variables.
@@ -49,6 +50,12 @@ c_auto (cstr, s1, s2)
printf("%s %s\n", cstr_str(&s1), cstr_str(&s2));
}
+c_autodrop (cstr, str, cstr_new("Hello"))
+{
+ cstr_append(&str, " world");
+ printf("%s\n", cstr_str(&str));
+}
+
// `c_scope` is like `c_with` but works with an already declared variable.
static pthread_mutex_t mut;
c_scope (pthread_mutex_lock(&mut), pthread_mutex_unlock(&mut))
diff --git a/examples/bits.c b/examples/bits.c
index ca4de6af..43a57c51 100644
--- a/examples/bits.c
+++ b/examples/bits.c
@@ -13,9 +13,9 @@ int main()
cbits_reset(&set, 9);
cbits_resize(&set, 43, false);
- c_autobuf (str, char, cbits_size(&set) + 1)
- printf(" str: %s\n", cbits_to_str(&set, str, 0, -1));
-
+ { char str[128];
+ printf(" str: %s\n", cbits_to_str(&set, str, 0, 128));
+ }
printf("%4" c_ZU ": ", cbits_size(&set));
c_forrange (i, cbits_size(&set))
printf("%d", cbits_test(&set, i));
diff --git a/examples/bits2.c b/examples/bits2.c
index 95eb8b83..59e0b337 100644
--- a/examples/bits2.c
+++ b/examples/bits2.c
@@ -11,12 +11,11 @@ int main()
printf("size %" c_ZU "\n", Bits_size(&s1));
char buf[256];
- Bits_to_str(&s1, buf, 0, -1);
+ Bits_to_str(&s1, buf, 0, 256);
printf("buf: %s: count=%" c_ZU "\n", buf, Bits_count(&s1));
Bits_reset(&s1, 8);
- c_autobuf (str, char, Bits_size(&s1) + 1)
- printf(" s1: %s\n", Bits_to_str(&s1, str, 0, -1));
+ printf(" s1: %s\n", Bits_to_str(&s1, buf, 0, 256));
Bits s2 = Bits_clone(s1);
diff --git a/examples/cpque.c b/examples/cpque.c
index 63d07c6b..dba4552f 100644
--- a/examples/cpque.c
+++ b/examples/cpque.c
@@ -9,6 +9,7 @@
#include <stdbool.h>
#include <stc/forward.h>
#include <stc/views.h>
+#include <stc/cstr.h>
// predeclare
declare_cpque(ipque, int);
@@ -18,7 +19,7 @@ struct {
bool (*less)(const int*, const int*);
} typedef IPQueue;
-#define IPQueue_obj(less) ((IPQueue){ipque_init(), less})
+#define IPQueue_drop(q) ipque_drop(&(q)->Q)
#define i_type ipque
#define i_val int
@@ -52,9 +53,9 @@ int main()
const int data[] = {1,8,5,6,3,4,0,9,7,2}, n = c_arraylen(data);
print("data", data, n);
- c_with (IPQueue q1 = IPQueue_obj(int_less), ipque_drop(&q1.Q)) // Max priority queue
- c_with (IPQueue minq1 = IPQueue_obj(int_greater), ipque_drop(&minq1.Q)) // Min priority queue
- c_with (IPQueue q5 = IPQueue_obj(int_lambda), ipque_drop(&q5.Q)) // Using lambda to compare elements.
+ c_autodrop (IPQueue, q1, {ipque_init(), int_less}) // Max priority queue
+ c_autodrop (IPQueue, minq1, {ipque_init(), int_greater}) // Min priority queue
+ c_autodrop (IPQueue, q5, {ipque_init(), int_lambda}) // Using lambda to compare elements.
{
c_forrange (i, n)
ipque_push(&q1.Q, data[i]);
diff --git a/examples/new_arr.c b/examples/new_arr.c
index 598e5323..51955b46 100644
--- a/examples/new_arr.c
+++ b/examples/new_arr.c
@@ -13,8 +13,7 @@ int main()
{
int w = 7, h = 5, d = 3;
- c_with (carr2_int volume = carr2_int_new_uninit(w, h),
- carr2_int_drop(&volume))
+ c_autodrop (carr2_int, volume, carr2_int_new_uninit(w, h))
{
int *dat = carr2_int_data(&volume);
for (size_t i = 0; i < carr2_int_size(&volume); ++i)
@@ -30,8 +29,7 @@ int main()
puts("\n");
}
- c_with (carr3_int volume = carr3_int_new_uninit(w, h, d),
- carr3_int_drop(&volume))
+ c_autodrop (carr3_int, volume, carr3_int_new_uninit(w, h, d))
{
int *dat = carr3_int_data(&volume);
for (size_t i = 0; i < carr3_int_size(&volume); ++i)
@@ -48,8 +46,7 @@ int main()
puts("");
}
- c_with (carr2_str text2d = carr2_str_with_size(h, d, cstr_init()),
- carr2_str_drop(&text2d))
+ c_autodrop (carr2_str, text2d, carr2_str_with_size(h, d, cstr_init()))
{
cstr_assign(&text2d.data[2][1], "hello");
cstr_assign(&text2d.data[4][0], "world");
diff --git a/examples/prime.c b/examples/prime.c
index 287fb69b..d2fc5efa 100644
--- a/examples/prime.c
+++ b/examples/prime.c
@@ -28,7 +28,7 @@ int main(void)
printf("computing prime numbers up to %" c_ZU "\n", n);
clock_t t1 = clock();
- c_with (cbits primes = sieveOfEratosthenes(n + 1), cbits_drop(&primes)) {
+ c_autodrop (cbits, primes, sieveOfEratosthenes(n + 1)) {
puts("done");
size_t np = cbits_count(&primes);
clock_t t2 = clock();
diff --git a/examples/regex2.c b/examples/regex2.c
index 1f656265..6dffc8c4 100644
--- a/examples/regex2.c
+++ b/examples/regex2.c
@@ -14,7 +14,7 @@ int main()
{"!((abc|123)+)!", "!123abcabc!"}
};
- c_with (cregex re = cregex_init(), cregex_drop(&re))
+ c_auto (cregex, re)
c_forrange (i, c_arraylen(s))
{
int res = cregex_compile(&re, s[i].pattern, cre_default);
diff --git a/examples/regex_replace.c b/examples/regex_replace.c
index e6054d9f..13bc9bf0 100644
--- a/examples/regex_replace.c
+++ b/examples/regex_replace.c
@@ -35,7 +35,7 @@ int main()
printf("brack: %s\n", cstr_str(&str));
/* Shows how to compile RE separately */
- c_with (cregex re = cregex_from(pattern, cre_default), cregex_drop(&re)) {
+ c_autodrop (cregex, re, cregex_from(pattern, cre_default)) {
if (cregex_captures(&re) == 0)
continue; // break c_with
/* European date format. */
diff --git a/include/stc/alt/cstr.h b/include/stc/alt/cstr.h
index 17548b5d..728ce77f 100644
--- a/include/stc/alt/cstr.h
+++ b/include/stc/alt/cstr.h
@@ -310,11 +310,11 @@ STC_DEF void
cstr_replace_at_sv(cstr* self, const size_t pos, size_t len, csview repl) {
const size_t sz = cstr_size(self);
if (len > sz - pos) len = sz - pos;
- c_autobuf (xstr, char, repl.size) {
- memcpy(xstr, repl.str, repl.size);
- _cstr_internal_move(self, pos + len, pos + repl.size);
- memcpy(&self->str[pos], xstr, repl.size);
- }
+ char buf[256], *xstr = repl.size > 256 ? c_malloc(repl.size) : buf;
+ memcpy(xstr, repl.str, repl.size);
+ _cstr_internal_move(self, pos + len, pos + repl.size);
+ memcpy(&self->str[pos], xstr, repl.size);
+ if (repl.size > 256) c_free(xstr);
}
STC_DEF cstr
diff --git a/include/stc/carr2.h b/include/stc/carr2.h
index 01e4752c..fa46fd44 100644
--- a/include/stc/carr2.h
+++ b/include/stc/carr2.h
@@ -35,7 +35,7 @@
int main() {
int w = 7, h = 5;
- c_with (carr2_int image = carr2_int_new_uninit(w, h), carr2_int_drop(&image))
+ c_autodrop (carr2_int, image, carr2_int_new_uninit(w, h))
{
int *dat = carr2_int_data(&image);
for (int i = 0; i < carr2_int_size(&image); ++i)
diff --git a/include/stc/cbits.h b/include/stc/cbits.h
index 6415c529..0b5c4db8 100644
--- a/include/stc/cbits.h
+++ b/include/stc/cbits.h
@@ -27,7 +27,7 @@ Similar to boost::dynamic_bitset / std::bitset
#include "cbits.h"
int main() {
- c_with (cbits bset = cbits_with_size(23, true), cbits_drop(&bset))
+ c_autodrop (cbits, bset, cbits_with_size(23, true))
{
cbits_reset(&bset, 9);
cbits_resize(&bset, 43, false);
diff --git a/include/stc/ccommon.h b/include/stc/ccommon.h
index 8f1599b5..f9aff743 100644
--- a/include/stc/ccommon.h
+++ b/include/stc/ccommon.h
@@ -222,6 +222,7 @@ STC_INLINE char* cstrnstrn(const char *str, const char *needle,
#define c_with3(declvar, pred, drop) for (declvar, **_c_i = NULL; !_c_i && (pred); ++_c_i, drop)
#define c_scope(init, drop) for (int _c_i = (init, 0); !_c_i; ++_c_i, drop)
#define c_defer(...) for (int _c_i = 0; !_c_i; ++_c_i, __VA_ARGS__)
+#define c_autodrop(C, a, ...) for (C a = __VA_ARGS__, **_c_i = NULL; !_c_i; ++_c_i, C##_drop(&a))
#define c_auto(...) c_MACRO_OVERLOAD(c_auto, __VA_ARGS__)
#define c_auto2(C, a) \
@@ -236,12 +237,6 @@ STC_INLINE char* cstrnstrn(const char *str, const char *needle,
c_with2(c_expand(C a = C##_init(), b = C##_init(), c = C##_init(), d = C##_init()), \
(C##_drop(&d), C##_drop(&c), C##_drop(&b), C##_drop(&a)))
-#define c_autobuf(b, type, n) c_autobuf_N(b, type, n, 256)
-#define c_autobuf_N(b, type, n, BYTES) \
- for (type _c_b[((BYTES) - 1) / sizeof(type) + 1], \
- *b = (n)*sizeof *b > (BYTES) ? c_alloc_n(type, n) : _c_b \
- ; b; b != _c_b ? c_free(b) : (void)0, b = NULL)
-
#define c_drop(C, ...) do { c_forlist (_i, C*, {__VA_ARGS__}) C##_drop(*_i.ref); } while(0)
#define c_find_if(...) c_MACRO_OVERLOAD(c_find_if, __VA_ARGS__)
diff --git a/src/checkauto.l b/src/checkauto.l
index 34aa280f..541bbf3f 100644
--- a/src/checkauto.l
+++ b/src/checkauto.l
@@ -43,9 +43,7 @@ do { block_type |= LOOP; state = BRACESDONE; }
c_with |
c_scope |
c_defer |
-c_autovar |
-c_autoscope |
-c_autodefer |
+c_autodrop |
c_auto { block_type = AUTO; state = BRACES; }
\( { if (state == BRACES) ++braces_lev; }
\) { if (state == BRACES && --braces_lev == 0) {