summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorTyge Løvset <[email protected]>2021-05-20 11:19:37 +0200
committerTyge Løvset <[email protected]>2021-05-20 11:19:37 +0200
commit6270e01be0f105e3512cfde04a7f7d6b67aa8a2e (patch)
treef2dc00ef74dff377c3c2ed1d85e9a7dcaf42e5bf
parent9c5d58627c784bc123e96fb81587f71994ad26cc (diff)
downloadSTC-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.md2
-rw-r--r--docs/cstr_api.md4
-rw-r--r--docs/csview_api.md47
-rw-r--r--examples/csmap_erase.c79
-rw-r--r--examples/mmap.c64
-rw-r--r--examples/svmap.c14
-rw-r--r--stc/csmap.h6
-rw-r--r--stc/cstr.h2
-rw-r--r--stc/csview.h14
9 files changed, 194 insertions, 38 deletions
diff --git a/README.md b/README.md
index ba2eaefa..1af744ef 100644
--- a/README.md
+++ b/README.md
@@ -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) \
diff --git a/stc/cstr.h b/stc/cstr.h
index 4e70189a..131a3d78 100644
--- a/stc/cstr.h
+++ b/stc/cstr.h
@@ -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)