summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorTyge Løvset <[email protected]>2021-05-18 10:08:35 +0200
committerTyge Løvset <[email protected]>2021-05-18 10:08:35 +0200
commitccc45a1dc249160364aa12b3cfecc9844d6760ff (patch)
tree0519dbbf45cabb8869a11219ba64d9ef034759fa
parent60a127bb9a7180d4d30c2b7186456cc1226e812a (diff)
downloadSTC-modified-ccc45a1dc249160364aa12b3cfecc9844d6760ff.tar.gz
STC-modified-ccc45a1dc249160364aa12b3cfecc9844d6760ff.zip
Added new file: csview: String View
-rw-r--r--README.md1
-rw-r--r--docs/csview_api.md155
-rw-r--r--examples/svmap.c38
-rw-r--r--stc/csview.h157
4 files changed, 351 insertions, 0 deletions
diff --git a/README.md b/README.md
index a316bb1c..02cf93b9 100644
--- a/README.md
+++ b/README.md
@@ -25,6 +25,7 @@ the multi-map/set variants:
- [***csset*** - **std::set** sorted set alike type](docs/csset_api.md)
- [***cstack*** - **std::stack** alike (adapter) type](docs/cstack_api.md)
- [***cstr*** - **std::string** alike type](docs/cstr_api.md)
+- [***csview*** - **std::string_view** alike type](docs/csview_api.md)
- [***cvec*** - **std::vector** alike type](docs/cvec_api.md)
Others:
diff --git a/docs/csview_api.md b/docs/csview_api.md
new file mode 100644
index 00000000..4098114c
--- /dev/null
+++ b/docs/csview_api.md
@@ -0,0 +1,155 @@
+# STC [csview](../stc/csview.h): String View
+![String](pics/string.jpg)
+
+The type **csview** is a string view and can refer to a constant contiguous sequence of char-elements with the first
+element of the sequence at position zero. The implementation holds two members: a pointer to constant char and a size.
+
+**csview** is an efficient replacent for `const char*`. It never allocates memory, and therefore need not be destructed.
+Its lifetime is limited by the source string storage. It keeps the length of the string, and does not call *strlen()*
+when passing it around. It is faster when using`csview` as convertion type (raw) than `const char*` in associative
+containers with cstr keys. E.g. prefer `using_cmap_svkey()` over `using_cmap_strkey()`.
+
+See the c++ class [std::basic_string_view](https://en.cppreference.com/w/cpp/string/basic_string_view) for a functional
+description.
+
+## Header file
+
+All csview definitions and prototypes are available by including a single header file.
+
+```c
+#include <stc/csview.h>
+```
+## 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_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_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);
+size_t csview_find(csview sv, csview needle);
+bool csview_contains(csview sv, csview needle);
+bool csview_begins_with(csview sv, csview sub);
+bool csview_ends_with(csview sv, csview sub);
+
+const char* csview_front(const csview* self);
+const char* csview_back(const csview* self);
+
+csview_iter_t csview_begin(const csview* self);
+csview_iter_t csview_end(const csview* self);
+void csview_next(csview_iter_t* it);
+```
+#### Extended cstr methods
+```c
+cstr cstr_from_v(csview sv);
+csview cstr_to_v(const cstr* self);
+cstr* cstr_assign_v(cstr* self, csview sv);
+cstr* cstr_append_v(cstr* self, csview sv);
+void cstr_insert_v(cstr* self, size_t pos, csview sv);
+void cstr_replace_v(cstr* self, size_t pos, size_t len, csview sv);
+
+bool cstr_equals_v(cstr s, csview sv);
+size_t cstr_find_v(cstr s, csview needle);
+bool cstr_contains_v(cstr s, csview needle);
+bool cstr_begins_with_v(cstr s, csview sub);
+bool cstr_ends_with_v(cstr s, csview sub);
+```
+#### Helper methods
+```c
+int csview_compare_ref(const csview* x, const csview* y);
+bool csview_equals_ref(const csview* x, const csview* y);
+uint64_t csview_hash_ref(const csview* x, size_t ignored);
+```
+## Types
+
+| Type name | Type definition | Used to represent... |
+|:------------------|:------------------------------------------|:-------------------------|
+| `csview` | `struct { const char *str; size_t size }` | The string view type |
+| `csview_value_t` | `char` | The string element type |
+| `csview_iter_t` | `struct { csview_value_t *ref; }` | csview iterator |
+
+## Constants and macros
+
+| Name | Value |
+|:------------------|:------------------|
+| `csview_null` | csview null value |
+
+## Container adaptors
+```
+using_cvec_sv()
+using_cdeq_sv()
+using_clist_sv()
+
+using_csmap_svkey(X, Mapped)
+using_csmap_svkey(X, Mapped, mappedDel)
+using_csmap_svkey(X, Mapped, mappedDel, mappedClone)
+using_csmap_svkey(X, Mapped, mappedDel, mappedFromRaw, mappedToRaw, RawMapped)
+using_csmap_sv()
+using_csset_sv()
+
+using_cmap_svkey(X, Mapped)
+using_cmap_svkey(X, Mapped, mappedDel)
+using_cmap_svkey(X, Mapped, mappedDel, mappedClone)
+using_cmap_svkey(X, Mapped, mappedDel, mappedFromRaw, mappedToRaw, RawMapped)
+using_cmap_sv()
+using_cset_sv()
+```
+
+## Example
+```c
+#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
+
+int main()
+{
+ csview text = c_sv("A long and winded literal string");
+ printf("%s\nLength: %zu\n\n", text.str, text.size);
+
+ c_var (cvec_sv, vec, {
+ c_sv("Element 1"),
+ c_sv("Element 2"),
+ c_sv("Element 3")
+ });
+ cvec_sv_push_back(&vec, cstr_new("Second last element"));
+ cvec_sv_emplace_back(&vec, c_sv("Last element")); // converts from csview to cstr
+
+ c_foreach (i, cvec_sv, vec)
+ printf("%s\n", i.ref->str);
+
+ c_var (cmap_si, map, {
+ {c_sv("hello"), 100},
+ {c_sv("world"), 200}
+ });
+ cmap_si_emplace(&map, c_sv("gone mad"), 300);
+
+ cmap_si_value_t* v = cmap_si_get(&map, c_sv("world"));
+ printf("\n%s: %d\n", v->first.str, v->second);
+
+ cmap_si_del(&map);
+ cvec_sv_del(&vec);
+}
+```
+Output:
+```
+A long and winded literal string
+Length: 32
+
+Great
+Fantastic
+Sensational
+Second last element
+Last element
+
+world: 200
+```
diff --git a/examples/svmap.c b/examples/svmap.c
new file mode 100644
index 00000000..f4bcc311
--- /dev/null
+++ b/examples/svmap.c
@@ -0,0 +1,38 @@
+#include <stc/csview.h>
+#include <stc/cmap.h>
+#include <stdio.h>
+
+// cmap<cstr, int> with csview as convertion key-type (raw):
+using_cmap_svkey(si, int);
+
+int main() {
+ csview fox = c_sv("The quick brown fox jumps over the lazy dog.");
+ printf("\"%s\", length=%zu\n", fox.str, fox.size);
+
+ cmap_si frequencies = cmap_si_init();
+
+ // 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
+
+ // 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, 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
+
+ // Lookup always uses "raw" type API, i.e. csview here.
+ printf("at(\"hundred\"): %d\n", *cmap_si_at(&frequencies, c_sv("hundred")));
+
+ c_foreach (i, cmap_si, frequencies)
+ printf("%s: %d\n", i.ref->first.str, i.ref->second);
+
+ /* Output: */
+ // "The quick brown fox jumps over the lazy dog.", length=44
+ // at("hundred"): 500
+ // hund: 400
+ // hundred: 500
+ // thousand: 2000
+} \ No newline at end of file
diff --git a/stc/csview.h b/stc/csview.h
new file mode 100644
index 00000000..a24bac26
--- /dev/null
+++ b/stc/csview.h
@@ -0,0 +1,157 @@
+/* MIT License
+ *
+ * Copyright (c) 2021 Tyge Løvset, NORCE, www.norceresearch.no
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#ifndef CSVIEW_H_INCLUDED
+#define CSVIEW_H_INCLUDED
+
+#include "cstr.h"
+
+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_new(literal) \
+ c_make(csview){literal, sizeof c_make(strlit_t){literal} - 1}
+#define c_sv(literal) \
+ csview_new(literal)
+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_substr(csview sv, size_t pos, size_t n)
+ { sv.str += pos, sv.size = n; return sv; }
+
+STC_INLINE size_t csview_size(csview sv) { return sv.size; }
+STC_INLINE size_t csview_length(csview sv) { return sv.size; }
+STC_INLINE bool csview_empty(csview sv) { return sv.size == 0; }
+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 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_begins_with(csview sv, csview sub)
+ { if (sub.size > sv.size) return false;
+ return !memcmp(sv.str, sub.str, sub.size); }
+STC_INLINE bool csview_ends_with(csview sv, csview sub)
+ { if (sub.size > sv.size) return false;
+ return !memcmp(sv.str + sv.size - sub.size, sub.str, sub.size); }
+STC_INLINE csview_iter_t csview_begin(const csview* self)
+ { return c_make(csview_iter_t){self->str}; }
+STC_INLINE csview_iter_t csview_end(const csview* self)
+ { return c_make(csview_iter_t){self->str + self->size}; }
+STC_INLINE void csview_next(csview_iter_t* it) { ++it->ref; }
+
+/* cstr interaction with csview: */
+
+STC_INLINE cstr cstr_from_v(csview sv)
+ { return cstr_from_n(sv.str, sv.size); }
+STC_INLINE csview cstr_to_v(const cstr* self)
+ { return c_make(csview){self->str, _cstr_rep(self)->size}; }
+STC_INLINE cstr* cstr_assign_v(cstr* self, csview sv)
+ { return cstr_assign_n(self, sv.str, sv.size); }
+STC_INLINE cstr* cstr_append_v(cstr* self, csview sv)
+ { return cstr_append_n(self, sv.str, sv.size); }
+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 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_begins_with_v(cstr s, csview sub)
+ { if (sub.size > cstr_size(s)) return false;
+ return !memcmp(s.str, sub.str, sub.size); }
+STC_INLINE bool cstr_ends_with_v(cstr s, csview sub)
+ { if (sub.size > cstr_size(s)) return false;
+ return !memcmp(s.str + cstr_size(s) - sub.size, sub.str, sub.size); }
+
+
+/* ---- Adaptor functions ---- */
+
+#define csview_compare_ref(xp, yp) strcmp((xp)->str, (yp)->str)
+STC_INLINE bool csview_equals_ref(const csview* a, const csview* b)
+ { return a->size == b->size && !memcmp(a->str, b->str, a->size); }
+#define csview_hash_ref(xp, none) c_default_hash((xp)->str, (xp)->size)
+
+/* ---- Containers ---- */
+
+#define using_cvec_sv() \
+ using_cvec(sv, cstr, csview_compare_ref, cstr_del, cstr_from_v, cstr_to_v, csview)
+#define using_cdeq_sv() \
+ using_cdeq(sv, cstr, csview_compare_ref, cstr_del, cstr_from_v, cstr_to_v, csview)
+#define using_clist_sv() \
+ using_clist(sv, cstr, csview_compare_ref, cstr_del, cstr_from_v, cstr_to_v, csview)
+
+
+#define using_csmap_svkey(...) c_MACRO_OVERLOAD(using_csmap_svkey, __VA_ARGS__)
+
+#define using_csmap_svkey_2(X, Mapped) \
+ using_csmap_svkey_4(X, Mapped, c_default_del, c_default_fromraw)
+#define using_csmap_svkey_3(X, Mapped, mappedDel) \
+ using_csmap_svkey_4(X, Mapped, mappedDel, c_no_clone)
+#define using_csmap_svkey_4(X, Mapped, mappedDel, mappedClone) \
+ using_csmap_svkey_6(X, Mapped, mappedDel, mappedClone, c_default_toraw, Mapped)
+#define using_csmap_svkey_6(X, Mapped, mappedDel, mappedFromRaw, mappedToRaw, RawMapped) \
+ _c_using_aatree(csmap_##X, csmap_, cstr, Mapped, csview_compare_ref, \
+ mappedDel, mappedFromRaw, mappedToRaw, RawMapped, \
+ cstr_del, cstr_from_v, cstr_to_v, csview)
+#define using_csmap_sv() \
+ using_csmap_svkey_6(sv, cstr, cstr_del, cstr_from_v, cstr_to_v, csview)
+#define using_csset_sv() \
+ _c_using_aatree(csset_sv, csset_, cstr, cstr, csview_compare_ref, \
+ @@, @@, @@, void, cstr_del, cstr_from_v, cstr_to_v, csview)
+
+
+#define using_cmap_svkey(...) c_MACRO_OVERLOAD(using_cmap_svkey, __VA_ARGS__)
+
+#define using_cmap_svkey_2(X, Mapped) \
+ using_cmap_svkey_4(X, Mapped, c_default_del, c_default_fromraw)
+#define using_cmap_svkey_3(X, Mapped, mappedDel) \
+ using_cmap_svkey_4(X, Mapped, mappedDel, c_no_clone)
+#define using_cmap_svkey_4(X, Mapped, mappedDel, mappedClone) \
+ using_cmap_svkey_6(X, Mapped, mappedDel, mappedClone, c_default_toraw, Mapped)
+#define using_cmap_svkey_6(X, Mapped, mappedDel, mappedFromRaw, mappedToRaw, RawMapped) \
+ _c_using_chash(cmap_##X, cmap_, cstr, Mapped, csview_equals_ref, csview_hash_ref, \
+ mappedDel, mappedFromRaw, mappedToRaw, RawMapped, \
+ cstr_del, cstr_from_v, cstr_to_v, csview)
+#define using_cmap_sv() \
+ using_cmap_svkey_6(sv, cstr, cstr_del, cstr_from_v, cstr_to_v, csview)
+#define using_cset_sv() \
+ _c_using_chash(cset_sv, cset_, cstr, cstr, csview_equals_ref, csview_hash_ref, \
+ @@, @@, @@, void, cstr_del, cstr_from_v, cstr_to_v, csview)
+
+#endif \ No newline at end of file