Skip to content

Commit

Permalink
"str_auto" type added.
Browse files Browse the repository at this point in the history
  • Loading branch information
maxim2266 committed Aug 15, 2022
1 parent 5d9e460 commit d42115c
Show file tree
Hide file tree
Showing 4 changed files with 28 additions and 15 deletions.
14 changes: 10 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,9 @@ store or release the object. When in doubt pass such an object via `str_ref`.
`str_assign` function instead. In fact, this function can assign to any string object,
owning or not, so it can be used everywhere, just to avoid any doubt.
* There is no automatic memory management in C, so every owning object must be released at
some point using either `str_free` or `str_clear` function.
some point using either `str_free` or `str_clear` function. String objects on the stack
can also be declared as `str_auto` (or `const str_auto`) for automatic cleanup when the variable
goes out of scope.
* An owning object can be moved to another location by using `str_move` function. The
function resets its source object to an empty string.
* An owning object can be passed over to another location by using `str_pass` function. The
Expand Down Expand Up @@ -152,7 +154,8 @@ of failure (including `ENOMEM` on memory allocation error).

Just to make things more clear, here is the same code as in the example above, but with comments:
```C
// declare a variable and initialise it with an empty string
// declare a variable and initialise it with an empty string; could also be declared as "str_auto"
// to avoid explicit call to str_free() below.
str s = str_null;

// join the given string literals around the separator (second parameter),
Expand Down Expand Up @@ -243,8 +246,11 @@ original string, and then returns the saved object.
#### String Deallocation
`void str_free(const str s)`<br>
Deallocates any memory held by the owning string object. No-op for references. After this function
the object is in unknown and unusable state.
Deallocates any memory held by the owning string object. No-op for references. After a call to
this function the string object is in unknown and unusable state.
String objects on the stack can also be declared as `str_auto` instead of `str` to deallocate
any memory held by the string when the variable goes out of scope.
#### String Modification
Expand Down
7 changes: 7 additions & 0 deletions str.c
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,13 @@ void str_free(const str s)
str_mem_free((void*)s.ptr);
}

// version of str_free() for str_auto macro
void _str_free(const str* const ps)
{
if(ps)
str_free(*ps);
}

// memory allocation helpers
#define ALLOC(n) \
({ \
Expand Down
5 changes: 5 additions & 0 deletions str.h
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,11 @@ bool str_is_ref(const str s) { return !str_is_owner(s); }
// free memory allocated for the string
void str_free(const str s);

// automatic cleanup
void _str_free(const str* const ps);

#define str_auto str __attribute__((cleanup(_str_free)))

// string movements -----------------------------------------------------------------------
// free target string, then assign the new value to it
static inline
Expand Down
17 changes: 6 additions & 11 deletions str_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ void test_str_lit(void)
static
void test_str_cpy(void)
{
str s = str_null;
str_auto s = str_null;

assert(str_cpy(&s, str_lit("ZZZ")) == 0);

Expand All @@ -76,7 +76,6 @@ void test_str_cpy(void)
assert(str_eq(s, str_lit("ZZZ")));
assert(*str_end(s) == 0);

str_free(s);
passed;
}

Expand Down Expand Up @@ -163,7 +162,7 @@ void test_str_ref(void)
static
void test_str_cmp(void)
{
const str s = str_lit("zzz");
const str_auto s = str_lit("zzz");

assert(str_cmp(s, s) == 0);
assert(str_cmp(s, str_lit("zzz")) == 0);
Expand Down Expand Up @@ -200,13 +199,12 @@ void test_str_cmp_ci(void)
static
void test_str_acquire(void)
{
str s = str_acquire(strdup("ZZZ"));
str_auto s = str_acquire(strdup("ZZZ"));

assert(str_is_owner(s));
assert(str_eq(s, str_lit("ZZZ")));
assert(*str_end(s) == 0);

str_free(s);
passed;
}

Expand Down Expand Up @@ -275,7 +273,7 @@ void test_str_join(void)
static
void test_composition(void)
{
str s = str_lit(", ");
str_auto s = str_lit(", ");

assert(str_join(&s, s, str_lit("Here"), str_lit("there"), str_lit("and everywhere")) == 0);
assert(str_cat(&s, s, str_lit("...")) == 0);
Expand All @@ -284,7 +282,6 @@ void test_composition(void)
assert(str_is_owner(s));
assert(*str_end(s) == 0);

str_free(s);
passed;
}

Expand Down Expand Up @@ -680,7 +677,7 @@ void test_unique_range(void)
static
void test_from_file(void)
{
str fname = str_null;
str_auto fname = str_null;

assert(str_cat(&fname, str_lit("tmp_"), str_ref_chars(__func__, sizeof(__func__) - 1)) == 0);

Expand All @@ -690,7 +687,7 @@ void test_from_file(void)
assert(str_join(stream, str_lit(" "), str_lit("aaa"), str_lit("bbb"), str_lit("ccc")) == 0);
assert(fclose(stream) == 0);

str res = str_null;
str_auto res = str_null;

assert(str_from_file(&res, str_ptr(fname)) == 0);
unlink(str_ptr(fname));
Expand All @@ -702,8 +699,6 @@ void test_from_file(void)
assert(str_from_file(&res, "/dev/null") == EOPNOTSUPP);
assert(str_from_file(&res, "does-not-exist") == ENOENT);

str_free(res);
str_free(fname);
passed;
}

Expand Down

0 comments on commit d42115c

Please sign in to comment.