diff options
| author | Tyge Løvset <[email protected]> | 2021-05-20 11:19:37 +0200 |
|---|---|---|
| committer | Tyge Løvset <[email protected]> | 2021-05-20 11:19:37 +0200 |
| commit | 6270e01be0f105e3512cfde04a7f7d6b67aa8a2e (patch) | |
| tree | f2dc00ef74dff377c3c2ed1d85e9a7dcaf42e5bf | |
| parent | 9c5d58627c784bc123e96fb81587f71994ad26cc (diff) | |
| download | STC-modified-6270e01be0f105e3512cfde04a7f7d6b67aa8a2e.tar.gz STC-modified-6270e01be0f105e3512cfde04a7f7d6b67aa8a2e.zip | |
Changed new API: c_sv(literal) => c_sv(cstr), cstr_new(literal) => cstr_lit(literal), csview_new() => csview_lit(). Added c_lit(literal) alias to csview_lit(literal).
| -rw-r--r-- | README.md | 2 | ||||
| -rw-r--r-- | docs/cstr_api.md | 4 | ||||
| -rw-r--r-- | docs/csview_api.md | 47 | ||||
| -rw-r--r-- | examples/csmap_erase.c | 79 | ||||
| -rw-r--r-- | examples/mmap.c | 64 | ||||
| -rw-r--r-- | examples/svmap.c | 14 | ||||
| -rw-r--r-- | stc/csmap.h | 6 | ||||
| -rw-r--r-- | stc/cstr.h | 2 | ||||
| -rw-r--r-- | stc/csview.h | 14 |
9 files changed, 194 insertions, 38 deletions
@@ -215,7 +215,7 @@ and non-emplace methods: using_cvec_str(); // vector of string (cstr)
...
cvec_str vec = cvec_str_init();
-cstr s = cstr_new("a string literal"); // cstr_new() for literals; no strlen() usage
+cstr s = cstr_lit("a string literal"); // cstr_lit() for literals; no strlen() usage
c_defer (cvec_str_del(&vec), cstr_del(&s)) // defer the destructors to end of block:
{
cvec_str_push_back(&vec, cstr_from("Hello")); // construct and add string from const char*
diff --git a/docs/cstr_api.md b/docs/cstr_api.md index a2b23a70..094f41e0 100644 --- a/docs/cstr_api.md +++ b/docs/cstr_api.md @@ -16,7 +16,7 @@ All cstr definitions and prototypes are available by including a single header f ```c cstr cstr_init(void); // constructor; same as cstr_null. -cstr cstr_new(const char literal_only[]); // cstr from literal; no strlen(). +cstr cstr_lit(const char literal_only[]); // cstr from literal; no strlen(). cstr cstr_from(const char* str); // constructor using strlen() cstr cstr_from_n(const char* str, size_t n); // constructor with specified length cstr cstr_with_capacity(size_t cap); @@ -120,7 +120,7 @@ char* c_strncasestrn(const char* str, const char* needle, size_t slen, si #include <stc/cstr.h> int main() { - cstr s0 = cstr_new("Initialization without using strlen()."); + cstr s0 = cstr_lit("Initialization without using strlen()."); printf("%s\nLength: %zu\n\n", s0.str, cstr_size(s0)); cstr s1 = cstr_from("one-nine-three-seven-five."); diff --git a/docs/csview_api.md b/docs/csview_api.md index dfa9a5a6..ba5daed8 100644 --- a/docs/csview_api.md +++ b/docs/csview_api.md @@ -22,19 +22,22 @@ All csview definitions and prototypes are available by including a single header ## Methods ```c -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 c_lit(const char literal_only[]); // csview from literal, no strlen() +csview c_sv(cstr s); // construct csview from cstr + +csview csview_from(const char* str); // construct from (const char*) +csview csview_from_n(const char* str, size_t n); // construct +csview csview_from_s(cstr s); // same as c_sv() +csview csview_lit(const char literal_only[]); // same as c_lit() + 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); size_t csview_length(csview sv); bool csview_empty(csview sv); - + void csview_clear(csview* self); bool csview_equals(csview sv, csview sv2); @@ -81,11 +84,11 @@ uint64_t csview_hash_ref(const csview* x, size_t ignored); ## Constants and macros -| 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));`| +| Name | Value | Usage | +|:-----------------|:------------------ -|:---------------------------------| +| `csview_null` | same as `c_lit("")` | `sview = csview_null;` | +| `c_lit(literal)` | csview constructor | `sview = c_lit("hello, world");` | +| `csview_ARG(sv)` | printf argument | `printf("%.*s", csview_ARG(sv));`| ## Container adaptors ``` @@ -121,21 +124,21 @@ using_cvec_sv(); int main() { - csview text = c_sv("The length of this literal is evaluated at compile time and stored in csview text."); + csview text = c_lit("The length of this literal is evaluated at compile time and stored in csview text."); printf("%s\nLength: %zu\n\n", text.str, text.size); // cvec of cstr elements, using csview as "emplace" type c_var (cvec_sv, vec, { // defines vec with 3 cstr elements. - c_sv("Element 1"), // will be converted to cstr. - c_sv("Element 2"), - c_sv("Element 3") + c_lit("Element 1"), // will be converted to cstr. + c_lit("Element 2"), + c_lit("Element 3") }); c_defer (cvec_sv_del(&vec)) // defer destruction to end of block. { // push constructed cstr directly - cvec_sv_push_back(&vec, cstr_new("Second last element")); + cvec_sv_push_back(&vec, cstr_lit("Second last element")); // emplace constructs cstr from a csview - cvec_sv_emplace_back(&vec, c_sv("Last element")); + cvec_sv_emplace_back(&vec, c_lit("Last element")); c_foreach (i, cvec_sv, vec) printf("%s\n", i.ref->str); @@ -143,12 +146,12 @@ int main() c_withvar (cmap_si, map) // defines map and defers destruction. { - cmap_si_emplace(&map, c_sv("hello"), 100); - cmap_si_emplace(&map, c_sv("world"), 200); - cmap_si_emplace(&map, c_sv("gone mad"), 300); + cmap_si_emplace(&map, c_lit("hello"), 100); + cmap_si_emplace(&map, c_lit("world"), 200); + cmap_si_emplace(&map, c_lit("gone mad"), 300); // Efficient lookup: no string allocation or strlen() takes place: - cmap_si_value_t* v = cmap_si_get(&map, c_sv("world")); + cmap_si_value_t* v = cmap_si_get(&map, c_lit("world")); printf("\n%s: %d\n", v->first.str, v->second); } } diff --git a/examples/csmap_erase.c b/examples/csmap_erase.c new file mode 100644 index 00000000..eb3700b1 --- /dev/null +++ b/examples/csmap_erase.c @@ -0,0 +1,79 @@ +// map_erase.c
+// https://docs.microsoft.com/en-us/cpp/standard-library/map-class?view=msvc-160#emplace
+#include <stc/csmap.h>
+#include <stc/cstr.h>
+#include <stdio.h>
+
+using_csmap_strval(my, int);
+
+void printmap(csmap_my map)
+{
+ c_foreach (e, csmap_my, map)
+ printf(" [%d, %s]", e.ref->first, e.ref->second.str);
+ printf("\nsize() == %zu\n\n", csmap_my_size(map));
+}
+
+int main()
+{
+ c_with (csmap_my m1 = csmap_my_init(), csmap_my_del(&m1))
+ {
+ // Fill in some data to test with, one at a time
+ csmap_my_emplace(&m1, 1, "A");
+ csmap_my_emplace(&m1, 2, "B");
+ csmap_my_emplace(&m1, 3, "C");
+ csmap_my_emplace(&m1, 4, "D");
+ csmap_my_emplace(&m1, 5, "E");
+
+ puts("Starting data of map m1 is:");
+ printmap(m1);
+ // The 1st member function removes an element at a given position
+ csmap_my_iter_t it = csmap_my_begin(&m1); csmap_my_next(&it);
+ csmap_my_erase_at(&m1, it);
+ puts("After the 2nd element is deleted, the map m1 is:");
+ printmap(m1);
+ }
+
+ c_with (csmap_my m2 = csmap_my_init(), csmap_my_del(&m2))
+ {
+ // Fill in some data to test with, one at a time, using emplace
+ c_emplace(csmap_my, m2, {
+ {10, "Bob"},
+ {11, "Rob"},
+ {12, "Robert"},
+ {13, "Bert"},
+ {14, "Bobby"}
+ });
+
+ puts("Starting data of map m2 is:");
+ printmap(m2);
+ csmap_my_iter_t it1 = csmap_my_fwd(csmap_my_begin(&m2), 1);
+ csmap_my_iter_t it2 = csmap_my_find(&m2, csmap_my_back(&m2)->first);
+ // The 2nd member function removes elements
+ // in the range [First, Last)
+ csmap_my_erase_range(&m2, it1, it2);
+ puts("After the middle elements are deleted, the map m2 is:");
+ printmap(m2);
+ }
+
+ c_with (csmap_my m3 = csmap_my_init(), csmap_my_del(&m3))
+ {
+ // Fill in some data to test with, one at a time, using emplace
+ csmap_my_emplace(&m3, 1, "red");
+ csmap_my_emplace(&m3, 2, "yellow");
+ csmap_my_emplace(&m3, 3, "blue");
+ csmap_my_emplace(&m3, 4, "green");
+ csmap_my_emplace(&m3, 5, "orange");
+ csmap_my_emplace(&m3, 5, "purple");
+ csmap_my_emplace(&m3, 5, "pink");
+
+ puts("Starting data of map m3 is:");
+ printmap(m3);
+ // The 3rd member function removes elements with a given Key
+ size_t count = csmap_my_erase(&m3, 2);
+ // The 3rd member function also returns the number of elements removed
+ printf("The number of elements removed from m3 is: %zu\n", count);
+ puts("After the element with a key of 2 is deleted, the map m3 is:");
+ printmap(m3);
+ }
+
+}
\ No newline at end of file diff --git a/examples/mmap.c b/examples/mmap.c new file mode 100644 index 00000000..c925db39 --- /dev/null +++ b/examples/mmap.c @@ -0,0 +1,64 @@ +#include <stc/csmap.h>
+#include <stc/clist.h>
+#include <stc/cstr.h>
+
+// This implements the multimap c++ example found at:
+// https://en.cppreference.com/w/cpp/container/multimap/insert
+
+// Map of int => clist_str. Note the negation of c_default_compare
+using_clist_str();
+using_csmap(m, int, clist_str, -c_default_compare, clist_str_del);
+
+void print(const csmap_m mmap)
+{
+ c_foreach (e, csmap_m, mmap) {
+ c_foreach (s, clist_str, e.ref->second)
+ printf("{%d,%s} ", e.ref->first, s.ref->str);
+ }
+ puts("");
+}
+
+void insert(csmap_m* mmap, int key, const char* str)
+{
+ clist_str *list = &csmap_m_insert(mmap, key, clist_str_init()).ref->second;
+ clist_str_emplace_back(list, str);
+}
+
+int main()
+{
+ c_with (csmap_m mmap = csmap_m_init(), csmap_m_del(&mmap))
+ {
+ // list-initialize
+ struct {int i; const char* s;} vals[] = {{2, "foo"}, {2, "bar"}, {3, "baz"}, {1, "abc"}, {5, "def"}};
+ c_forrange (i, c_arraylen(vals)) insert(&mmap, vals[i].i, vals[i].s);
+
+ // insert using value_type
+ insert(&mmap, 5, "pqr");
+ print(mmap);
+
+ // insert using make_pair
+ insert(&mmap, 6, "uvw");
+ print(mmap);
+
+ insert(&mmap, 7, "xyz");
+ print(mmap);
+
+ // insert using initialization_list
+ insert(&mmap, 5, "one");
+ insert(&mmap, 5, "two");
+ print(mmap);
+
+ // erase all entries with key 5
+ csmap_m_erase(&mmap, 5);
+ print(mmap);
+
+ // find and erase a specific entry
+ clist_str_iter_t pos;
+ c_foreach (e, csmap_m, mmap)
+ if ((pos = clist_str_find(&e.ref->second, "bar")).ref) {
+ clist_str_erase(&e.ref->second, pos);
+ break;
+ }
+ print(mmap);
+ }
+}
diff --git a/examples/svmap.c b/examples/svmap.c index 9fd89755..c45ff1ae 100644 --- a/examples/svmap.c +++ b/examples/svmap.c @@ -6,25 +6,25 @@ using_cmap_svkey(si, int);
int main() {
- csview fox = c_sv("The quick brown fox jumps over the lazy dog.");
+ csview fox = c_lit("The quick brown fox jumps over the lazy dog.");
printf("\"%s\", length=%zu\n", fox.str, fox.size);
c_withvar (cmap_si, frequencies)
{
// Non-emplace: cstr element API
- cmap_si_insert(&frequencies, cstr_new("thousand"), 1000);
- cmap_si_insert_or_assign(&frequencies, cstr_new("thousand"), 2000); // update; same as put()
- cmap_si_insert(&frequencies, cstr_new("thousand"), 3000); // ignored
+ cmap_si_insert(&frequencies, cstr_lit("thousand"), 1000);
+ cmap_si_insert_or_assign(&frequencies, cstr_lit("thousand"), 2000); // update; same as put()
+ cmap_si_insert(&frequencies, cstr_lit("thousand"), 3000); // ignored
// Emplace: csview element API
const char* key = "hundred";
- cmap_si_emplace(&frequencies, c_sv("hundred"), 300); // c_sv() shorthand for csview_new()
+ cmap_si_emplace(&frequencies, c_lit("hundred"), 300); // c_lit() shorthand for csview_lit()
cmap_si_emplace(&frequencies, csview_from_n(key, 4), 400); // insert "hund"
cmap_si_emplace_or_assign(&frequencies, csview_from(key), 500); // update
- cmap_si_emplace(&frequencies, c_sv("hundred"), 600); // ignored, already inserted
+ cmap_si_emplace(&frequencies, c_lit("hundred"), 600); // ignored, already inserted
// Lookup always uses "raw" type API, i.e. csview here.
- printf("at(\"hundred\"): %d\n", *cmap_si_at(&frequencies, c_sv("hundred")));
+ printf("at(\"hundred\"): %d\n", *cmap_si_at(&frequencies, c_lit("hundred")));
c_foreach (i, cmap_si, frequencies)
printf("%s: %d\n", i.ref->first.str, i.ref->second);
diff --git a/stc/csmap.h b/stc/csmap.h index 3c6bf10e..4a57ee33 100644 --- a/stc/csmap.h +++ b/stc/csmap.h @@ -289,6 +289,12 @@ struct csmap_rep { size_t root, disp, head, size, cap; void* nodes[]; }; return c_make(CX##_iter_t){.ref = NULL}; \
} \
\
+ STC_INLINE CX##_iter_t \
+ CX##_fwd(CX##_iter_t it, size_t n) { \
+ while (n-- && it.ref) CX##_next(&it); \
+ return it; \
+ } \
+\
_c_implement_aatree(CX, C, Key, Mapped, keyCompareRaw, \
mappedDel, mappedFromRaw, mappedToRaw, RawMapped, \
keyDel, keyFromRaw, keyToRaw, RawKey) \
@@ -66,7 +66,7 @@ STC_API char* c_strnstrn(const char* s, const char* needle, size_t sle STC_API char* c_strncasestrn(const char* s, const char* needle, size_t slen, size_t nmax);
STC_INLINE cstr cstr_init() { return cstr_null; }
-#define cstr_new(literal) \
+#define cstr_lit(literal) \
cstr_from_n(literal, sizeof c_make(strlit_t){literal} - 1)
STC_INLINE cstr cstr_from(const char* str)
{ return cstr_from_n(str, strlen(str)); }
diff --git a/stc/csview.h b/stc/csview.h index ccd63770..19f89983 100644 --- a/stc/csview.h +++ b/stc/csview.h @@ -29,18 +29,22 @@ 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_ARG(sv) (int)(sv).size, (sv).str
-#define csview_new(literal) \
- c_make(csview){literal, sizeof c_make(strlit_t){literal} - 1}
-#define c_sv(literal) \
- csview_new(literal)
+#define c_lit(literal) \
+ csview_lit(literal)
+STC_INLINE csview c_sv(cstr s)
+ { return c_make(csview){s.str, _cstr_rep(&s)->size}; }
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}; }
+
+#define csview_lit(literal) \
+ c_make(csview){literal, sizeof c_make(strlit_t){literal} - 1}
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)
|
