diff options
| -rw-r--r-- | docs/ccommon_api.md | 60 | ||||
| -rw-r--r-- | docs/csview_api.md | 27 | ||||
| -rw-r--r-- | stc/ccommon.h | 3 | ||||
| -rw-r--r-- | stc/csview.h | 23 |
4 files changed, 71 insertions, 42 deletions
diff --git a/docs/ccommon_api.md b/docs/ccommon_api.md index afbcb8a7..eb7918b9 100644 --- a/docs/ccommon_api.md +++ b/docs/ccommon_api.md @@ -33,10 +33,10 @@ c_forrange (i, int, 30, 0, -5) printf(" %d", i); ### c_foreach -| Usage | Description | -|:----------------------------------------------|:--------------------------------| -| `c_foreach (it, ctype, container)` | `Iteratate all elements ` | -| `c_foreach (it, ctype, it1, it2)` | `Iterate the range [it1, it2)` | +| Usage | Description | +|:-------------------------------------|:-----------------------------| +| `c_foreach (it, ctype, container)` | Iteratate all elements | +| `c_foreach (it, ctype, it1, it2)` | Iterate the range [it1, it2) | ```c using_csset(x, int); @@ -49,44 +49,58 @@ c_foreach (i, csset_x, it, csset_x_end(&set)) printf(" %d", *i.ref); // 7 12 23 ``` -### c_withfile, c_withbuffer, c_breakwith -Simplifies reading a file. Use only **c_breakwith** to break out of the block if needed. -**c_withbuffer** uses stack memory if buf is up to 256 bytes, and heap memory otherwise: +### c_with, c_withbuffer, c_breakwith +General defer in block mechanics. **c_withbuffer** is special for buffers, uses stack memory if buf is up to 256 bytes, +and heap memory otherwise. -| Usage | Description | -|:-------------------------------|:----------------------------------| -| `c_withfile (fp, fileopen)` | `Declare, open and close file` | -| `c_withbuffer (buf, type, n)` | `Declare, allocate and free buf` | +***NB***: Use only **c_breakwith** to break out of the block if needed, never use **return**, **break**, +or **goto** inside a with-block. + +| Usage | Description | +|:-------------------------------|:-------------------------------------| +| `c_with (acquire, release)` | Do `acquire`. Defer `release` to end | +| `c_withbuffer (buf, type, n)` | Declare, allocate and free buf | + +The `acquire`argument must be of the form: `type var = get_resource`. ```c -// Load each line of a text file into a vector of strings +// Example: Load each line of a text file into a vector of strings #include <errno.h> #include <stc/cstr.h> #include <stc/cvec.h> using_cvec_str(); -cvec_str readFile(const char* name) { +cvec_str readFile(const char* name) +{ + // receiver should check errno variable cvec_str vec = cvec_str_init(); - // Next line declares, opens, and closes the FILE* - c_withfile (fp, fopen(name, "r")) { - cstr line = cstr_init(); - while (cstr_getline(&line, fp)) - cvec_str_emplace_back(&vec, line.str); - cstr_del(&line); - } - return vec; // receiver should check errno variable + c_with (FILE* fp = fopen(name, "r"), fclose(fp)) + c_with (cstr line = cstr_null, cstr_del(&line)) + while (cstr_getline(&line, fp)) + cvec_str_emplace_back(&vec, line.str); + + return vec; +} + +int main() +{ + c_with (cvec_str x = readFile(__FILE__), cvec_str_del(&x)) + c_foreach (i, cvec_str, x) + printf("%s\n", i.ref->str); } ``` -### c_new, c_new_n, c_del +### c_new, c_new_n, c_del, c_make | Usage | Meaning | |:-------------------------------|:----------------------------------------| | `c_new (type)` | `(type *) c_malloc(sizeof(type))` | | `c_new_n (type, N)` | `(type *) c_malloc((N)*sizeof(type))` | -| `c_del (ctype, c1, ..., cN)` | `ctype_del(c1); ... ctype_del(cN)` | +| `c_del (ctype, &c1, ..., &cN)` | `ctype_del(&c1); ... ctype_del(&cN)` | +| `c_make(type){value...}` | `(type){value...}` // c++ compatability | + ```c int* array = c_new_n (int, 100); c_free(array); diff --git a/docs/csview_api.md b/docs/csview_api.md index 4098114c..a76eb262 100644 --- a/docs/csview_api.md +++ b/docs/csview_api.md @@ -22,11 +22,13 @@ All csview definitions and prototypes are available by including a single header ## Methods ```c -csview csview_new(const char literal_only[]); // csview from literal, no strlen() csview c_sv(const char literal_only[]); // shorthand for csview_new() +csview csview_new(const char literal_only[]); // csview from literal, no strlen() csview csview_from(const char* str); // construct csview csview_from_n(const char* str, size_t n); // construct csview csview_from_s(cstr s); // construct +csview csview_remove_prefix(csview sv, size_t n); +csview csview_remove_suffix(csview sv, size_t n); csview csview_substr(csview sv, size_t pos, size_t n); size_t csview_size(csview sv); @@ -79,9 +81,11 @@ uint64_t csview_hash_ref(const csview* x, size_t ignored); ## Constants and macros -| Name | Value | -|:------------------|:------------------| -| `csview_null` | csview null value | +| Name | Value | Usage | +|:-----------------|:-------------------|:---------------------------------| +| `csview_null` | same as `c_sv("")` | `sview = csview_null;` | +| `c_sv(literal)` | csview constructor | `sview = c_sv("hello, world");` | +| `csview_PRN(sv)` | printf argument | `printf("%.*s", csview_PRN(sv));`| ## Container adaptors ``` @@ -106,23 +110,31 @@ using_cset_sv() ## Example ```c +#include <stc/csview.h> +#include <stc/cvec.h> #include <stc/cmap.h> -using_cmap_svkey(si, int); // cmap<cstr, int> with csview as convertion type -using_cvec_sv(); // cvec<cstr> with csview as convertion type +// cmap<cstr, int> with csview as convertion type +using_cmap_svkey(si, int); +// cvec<cstr> with csview as convertion type +using_cvec_sv(); int main() { csview text = c_sv("A long and winded literal string"); printf("%s\nLength: %zu\n\n", text.str, text.size); + // cvec of cstr elements, using csview as "emplace" type c_var (cvec_sv, vec, { c_sv("Element 1"), c_sv("Element 2"), c_sv("Element 3") }); + + // push constructed cstr directly cvec_sv_push_back(&vec, cstr_new("Second last element")); - cvec_sv_emplace_back(&vec, c_sv("Last element")); // converts from csview to cstr + // emplace constructs cstr from a csview + cvec_sv_emplace_back(&vec, c_sv("Last element")); c_foreach (i, cvec_sv, vec) printf("%s\n", i.ref->str); @@ -133,6 +145,7 @@ int main() }); cmap_si_emplace(&map, c_sv("gone mad"), 300); + // cmap_si_get() knows the length of "world" without strlen(). cmap_si_value_t* v = cmap_si_get(&map, c_sv("world")); printf("\n%s: %d\n", v->first.str, v->second); diff --git a/stc/ccommon.h b/stc/ccommon.h index ed44bcd7..0fa74f7b 100644 --- a/stc/ccommon.h +++ b/stc/ccommon.h @@ -122,8 +122,7 @@ for (type i=start, i##_inc_=step, i##_end_=(stop) - (0 < i##_inc_) \
; (i <= i##_end_) == (0 < i##_inc_); i += i##_inc_)
-#define c_with(start, end) for (int _c_w = (start, 0); !_c_w; end, ++_c_w)
-#define c_withfile(f, open) for (FILE *f = open; f; fclose(f), f = NULL)
+#define c_with(start, end) for (start, *_c_w = NULL; !_c_w; ++_c_w, end)
#define c_withbuffer(b, type, n) c_withbuffer_x(b, type, n, 256)
#define c_withbuffer_x(b, type, n, BYTES) \
for (type _c_b[((BYTES) - 1) / sizeof(type) + 1], \
diff --git a/stc/csview.h b/stc/csview.h index a24bac26..ccd63770 100644 --- a/stc/csview.h +++ b/stc/csview.h @@ -29,6 +29,7 @@ typedef struct { const char* str; size_t size; } csview; typedef struct { const char *ref; } csview_iter_t;
typedef char csview_value_t;
#define csview_null c_make(csview){"", 0}
+#define csview_PRN(sv) (int)(sv).size, (sv).str
#define csview_new(literal) \
c_make(csview){literal, sizeof c_make(strlit_t){literal} - 1}
@@ -38,10 +39,12 @@ STC_INLINE csview csview_from(const char* str) { return c_make(csview){str, strlen(str)}; }
STC_INLINE csview csview_from_n(const char* str, size_t n)
{ return c_make(csview){str, n}; }
-STC_INLINE csview csview_from_v(csview sv, size_t pos)
- { sv.str += pos, sv.size -= pos; return sv; }
STC_INLINE csview csview_from_s(cstr s)
{ return c_make(csview){s.str, _cstr_rep(&s)->size}; }
+STC_INLINE csview csview_remove_prefix(csview sv, size_t n)
+ { sv.str += n, sv.size -= n; return sv; }
+STC_INLINE csview csview_remove_suffix(csview sv, size_t n)
+ { sv.size -= n; return sv; }
STC_INLINE csview csview_substr(csview sv, size_t pos, size_t n)
{ sv.str += pos, sv.size = n; return sv; }
@@ -52,13 +55,13 @@ STC_INLINE void csview_clear(csview* self) { *self = csview_null; } STC_INLINE const char* csview_front(const csview* self) { return self->str; }
STC_INLINE const char* csview_back(const csview* self) { return self->str + self->size - 1; }
+STC_INLINE bool csview_equals(csview sv, csview sv2)
+ { return sv.size == sv2.size && !memcmp(sv.str, sv2.str, sv.size); }
STC_INLINE size_t csview_find(csview sv, csview needle)
{ char* res = c_strnstrn(sv.str, needle.str, sv.size, needle.size);
return res ? res - sv.str : cstr_npos; }
-STC_INLINE bool csview_equals(csview sv, csview sv2)
- { return sv.size == sv2.size && !memcmp(sv.str, sv2.str, sv.size); }
-STC_INLINE bool csview_contains(csview sv, csview sub)
- { return c_strnstrn(sv.str, sub.str, sv.size, sub.size) != NULL; }
+STC_INLINE bool csview_contains(csview sv, csview needle)
+ { return c_strnstrn(sv.str, needle.str, sv.size, needle.size) != NULL; }
STC_INLINE bool csview_begins_with(csview sv, csview sub)
{ if (sub.size > sv.size) return false;
return !memcmp(sv.str, sub.str, sub.size); }
@@ -85,13 +88,13 @@ STC_INLINE void cstr_insert_v(cstr* self, size_t pos, csview sv) { cstr_replace_n(self, pos, 0, sv.str, sv.size); }
STC_INLINE void cstr_replace_v(cstr* self, size_t pos, size_t len, csview sv)
{ cstr_replace_n(self, pos, len, sv.str, sv.size); }
+STC_INLINE bool cstr_equals_v(cstr s, csview sv)
+ { return sv.size == cstr_size(s) && !memcmp(s.str, sv.str, sv.size); }
STC_INLINE size_t cstr_find_v(cstr s, csview needle)
{ char* res = c_strnstrn(s.str, needle.str, cstr_size(s), needle.size);
return res ? res - s.str : cstr_npos; }
-STC_INLINE bool cstr_equals_v(cstr s, csview sv)
- { return sv.size == cstr_size(s) && !memcmp(s.str, sv.str, sv.size); }
-STC_INLINE bool cstr_contains_v(cstr s, csview sub)
- { return c_strnstrn(s.str, sub.str, cstr_size(s), sub.size) != NULL; }
+STC_INLINE bool cstr_contains_v(cstr s, csview needle)
+ { return c_strnstrn(s.str, needle.str, cstr_size(s), needle.size) != NULL; }
STC_INLINE bool cstr_begins_with_v(cstr s, csview sub)
{ if (sub.size > cstr_size(s)) return false;
return !memcmp(s.str, sub.str, sub.size); }
|
