summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorTyge Løvset <[email protected]>2021-05-18 15:34:16 +0200
committerTyge Løvset <[email protected]>2021-05-18 15:34:16 +0200
commita8d94f4acea04681c89b46233f90bd8f4cee6ebf (patch)
tree9a55e275b6e565421cdbf9ba457e791e272ba997
parentccc45a1dc249160364aa12b3cfecc9844d6760ff (diff)
downloadSTC-modified-a8d94f4acea04681c89b46233f90bd8f4cee6ebf.tar.gz
STC-modified-a8d94f4acea04681c89b46233f90bd8f4cee6ebf.zip
Final improvements before push.
-rw-r--r--docs/ccommon_api.md60
-rw-r--r--docs/csview_api.md27
-rw-r--r--stc/ccommon.h3
-rw-r--r--stc/csview.h23
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); }