summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--README.md14
-rw-r--r--benchmarks/misc/string_bench_STC.cpp4
-rw-r--r--docs/cstr_api.md75
-rw-r--r--docs/csview_api.md53
-rw-r--r--examples/cstr_match.c8
-rw-r--r--examples/demos.c2
-rw-r--r--examples/regex_replace.c2
-rw-r--r--examples/replace.c18
-rw-r--r--examples/utf8replace_c.c11
-rw-r--r--include/stc/alt/cstr.h70
-rw-r--r--include/stc/ccommon.h5
-rw-r--r--include/stc/cstr.h147
-rw-r--r--include/stc/csview.h62
13 files changed, 246 insertions, 225 deletions
diff --git a/README.md b/README.md
index f74888d8..9544a071 100644
--- a/README.md
+++ b/README.md
@@ -3,7 +3,7 @@
STC - Smart Template Containers for C
=====================================
-News: Version 3.7 released (July 2022)
+News: Version 3.8 released (July 2022)
---------------------------------------
- [See changes version 3](#version-3). Note some code-breaking API changes!
@@ -457,6 +457,18 @@ Memory efficiency
# Version 3
+## Changes version 3.8
+- Overhauled some **cstr** and **csview** API:
+ - Changed cstr_replace*() => `cstr_replace_at*(self, pos, len, repl)`: Replace at specific position.
+ - Changed `cstr_replace_all() cstr_replace*(self, search, repl, count)`: Replace count occurences.
+ - Renamed `cstr_find_from()` => `cstr_find_at()`
+ - Renamed `cstr_*_u8()` => `cstr_u8_*()`
+ - Renamed `csview_*_u8()` => `csview_u8_*()`
+ - Added cstr_u8_slice() and csview_u8_slice().
+ - Removed `csview_from_s()`: Use `cstr_sv(s)` instead.
+ - Removed `csview_from_n()`: Use `c_sv(str, n)` instead.
+ - Updated cstr and csview docs.
+
## Changes version 3.7
- NB! Changed self argument from value to const pointer on containers (does not apply to **cstr**):
- `CNT_size(const CNT *self)`
diff --git a/benchmarks/misc/string_bench_STC.cpp b/benchmarks/misc/string_bench_STC.cpp
index 9fc861ea..648cb1f3 100644
--- a/benchmarks/misc/string_bench_STC.cpp
+++ b/benchmarks/misc/string_bench_STC.cpp
@@ -100,7 +100,7 @@ void initShortStringVec(cvec_str* vs, cvec_sv* vsv)
size_t num = 0;
c_foreach (i, cvec_str, *vs)
{
- cvec_sv_push_back(vsv, csview_from_s(i.ref));
+ cvec_sv_push_back(vsv, cstr_sv(i.ref));
num += cstr_size(*i.ref);
}
std::cout << "num strings: " << cvec_sv_size(vsv) << std::endl;
@@ -146,7 +146,7 @@ void initLongStringVec(cvec_str* vs, cvec_sv* vsv)
size_t num = 0;
c_foreach (i, cvec_str, *vs)
{
- cvec_sv_push_back(vsv, csview_from_s(i.ref));
+ cvec_sv_push_back(vsv, cstr_sv(i.ref));
num += cstr_size(*i.ref);
}
std::cout << "num strings: " << cvec_sv_size(vsv) << std::endl;
diff --git a/docs/cstr_api.md b/docs/cstr_api.md
index 7afdcf77..a05dc1ae 100644
--- a/docs/cstr_api.md
+++ b/docs/cstr_api.md
@@ -3,16 +3,16 @@
A **cstr** object represent sequences of characters. It supports an interface similar to that of a standard container of bytes, but adding features specifically designed to operate with strings of single-byte characters, terminated by the null character.
-**cstr** has basic support for *UTF8* encoded strings, and has a set of compact and efficient functions for handling case-foldings and comparisons of UTF strings. The **cstr** type uses short strings optimization (sso), which eliminates heap memory allocation for strings shorter than 24 bytes (sizeof(cstr) is also 24).
+**cstr** has basic support for *UTF8* encoded strings, and has a set of compact and efficient functions for handling case-foldings and comparisons of UTF strings.
-See the c++ class [std::basic_string](https://en.cppreference.com/w/cpp/string/basic_string) for a functional description.
+**cstr** uses short strings optimization (sso), which eliminates heap memory allocation for string capacity less than 24 bytes. `sizeof(cstr)` is also 24. In comparison, c++ `sizeof(std::string)` is typically 32, but sso capacity is only 15 bytes.
## Header file
All cstr definitions and prototypes are available by including a single header file.
```c
-#define i_implement // optional: define in one source file only for shared symbols linking!
+#define i_implement // define this to implement many functions as shared symbols!
#include <stc/cstr.h>
```
@@ -21,61 +21,70 @@ All cstr definitions and prototypes are available by including a single header f
cstr cstr_init(void); // constructor; same as cstr_null.
cstr cstr_new(const char literal_only[]); // cstr from literal; no strlen() call.
cstr cstr_from(const char* str); // constructor using strlen()
-cstr cstr_from_n(const char* str, size_t len); // constructor with specified length
+cstr cstr_from_n(const char* str, size_t n); // constructor with n first bytes of str
+cstr cstr_from_sv(csview sv); // construct cstr from csview
cstr cstr_with_capacity(size_t cap);
cstr cstr_with_size(size_t len, char fill); // repeat fill len times
cstr cstr_from_fmt(const char* fmt, ...); // printf() formatting
cstr cstr_clone(cstr s);
-cstr* cstr_take(cstr* self, cstr s); // take the constructed or moved string
-cstr cstr_move(cstr* self); // move string to caller, leave empty string
+cstr* cstr_take(cstr* self, cstr s); // take ownership of s, i.e. don't drop s.
+cstr cstr_move(cstr* self); // move string to caller, leave self empty
void cstr_drop(cstr *self); // destructor
-const char* cstr_str(const cstr* self); // access to const char*
-char* cstr_data(cstr* self); // access to char*
-csview cstr_sv(const cstr* self); // access to string view
-cstr_buf cstr_buffer(cstr* self); // access to mutable buffer (with capacity)
+const char* cstr_str(const cstr* self); // cast to const char*
+char* cstr_data(cstr* self); // cast to mutable char*
+csview cstr_sv(const cstr* self); // cast to string view
+cstr_buf cstr_buffer(cstr* self); // cast to mutable buffer (with capacity)
size_t cstr_size(cstr s);
size_t cstr_capacity(cstr s);
bool cstr_empty(cstr s);
-size_t cstr_reserve(cstr* self, size_t capacity);
+char* cstr_reserve(cstr* self, size_t capacity); // return pointer to buffer
void cstr_resize(cstr* self, size_t len, char fill);
void cstr_shrink_to_fit(cstr* self);
char* cstr_append_uninit(cstr* self, size_t len); // return ptr to uninit data
void cstr_clear(cstr* self);
char* cstr_assign(cstr* self, const char* str);
-char* cstr_assign_s(cstr* self, cstr s);
-char* cstr_assign_n(cstr* self, const char* str, size_t len); // assign n first chars of str
-int cstr_printf(cstr* self, const char* fmt, ...); // printf() formatting
+char* cstr_assign_n(cstr* self, const char* str, size_t n); // assign n first bytes of str
+char* cstr_assign_sv(cstr* self, csview sv)
+char* cstr_copy(cstr* self, cstr s); // copy-assign a cstr
+int cstr_printf(cstr* self, const char* fmt, ...); // source and target must not overlap.
-char* cstr_append(cstr* self, const char* app);
-char* cstr_append_s(cstr* self, cstr app);
-char* cstr_append_n(cstr* self, const char* app, size_t len);
+char* cstr_append(cstr* self, const char* str);
+char* cstr_append_n(cstr* self, const char* str, size_t n); // append n first bytes of str
+char* cstr_append_sv(cstr* self, csview str);
+char* cstr_append_s(cstr* self, cstr str);
+char* cstr_append_uninit(cstr *self, size_t len); // append len uninitialized bytes
void cstr_insert(cstr* self, size_t pos, const char* ins);
+void cstr_insert_sv(cstr* self, size_t pos, csview ins);
void cstr_insert_s(cstr* self, size_t pos, cstr ins);
-void cstr_insert_n(cstr* self, size_t pos, const char* ins, size_t len);
void cstr_erase(cstr* self, size_t pos);
-void cstr_erase_n(cstr* self, size_t pos, size_t len);
+void cstr_erase_n(cstr* self, size_t pos, size_t n); // erase n bytes from pos
-size_t cstr_replace(cstr* self, const char* search, const char* repl);
-size_t cstr_replace_from(cstr* self, size_t pos, const char* search, const char* repl);
-void cstr_replace_at(cstr* self, size_t pos, size_t len, const char* repl);
-void cstr_replace_s(cstr* self, size_t pos, size_t len, cstr repl);
-void cstr_replace_with_n(cstr* self, size_t pos, size_t len, const char* repl, size_t rlen);
-void cstr_replace_all(cstr* self, const char* search, const char* repl);
+void cstr_replace(cstr* self, const char* search, const char* repl, unsigned count); // count==0: replace all.
+cstr cstr_replace_sv(csview in, csview search, csview repl, unsigned count);
+void cstr_replace_at(cstr* self, size_t pos, size_t len, const char* repl); // replace at a position
+void cstr_replace_at_sv(cstr* self, size_t pos, size_t len, const csview repl);
+void cstr_replace_at_s(cstr* self, size_t pos, size_t len, cstr repl);
bool cstr_equals(cstr s, const char* str);
bool cstr_equals_s(cstr s, cstr s2);
size_t cstr_find(cstr s, const char* search);
-size_t cstr_find_from(cstr s, size_t pos, const char* search);
+size_t cstr_find_at(cstr s, size_t pos, const char* search); // search from pos
bool cstr_contains(cstr s, const char* search);
+
bool cstr_starts_with(cstr s, const char* str);
+bool cstr_starts_with_sv(cstr s, csview sv);
+bool cstr_starts_with_s(cstr s, cstr s);
+
bool cstr_ends_with(cstr s, const char* str);
+bool cstr_ends_with_sv(cstr s, csview sv);
+bool cstr_ends_with_s(cstr s, cstr s);
bool cstr_getline(cstr *self, FILE *stream); // cstr_getdelim(self, '\n', stream)
bool cstr_getdelim(cstr *self, int delim, FILE *stream); // does not append delim to result
@@ -83,11 +92,12 @@ bool cstr_getdelim(cstr *self, int delim, FILE *stream); // does no
#### UTF8 methods
```c
-size_t cstr_u8size(cstr s); // number of utf8 codepoints
-size_t cstr_u8size_n(cstr s, size_t nbytes); // utf8 size within n bytes
-size_t cstr_pos_u8(cstr s, size_t u8idx); // byte pos offset at utf8 index
-const char* cstr_at_u8(const cstr* self, size_t u8idx); // char* position at utf8 index
-csview cstr_chr_u8(const cstr* self, size_t u8idx); // utf8 character at utf8 pos as csview
+size_t cstr_u8_size(cstr s); // number of utf8 codepoints
+size_t cstr_u8_size_n(cstr s, size_t nbytes); // utf8 size within n bytes
+size_t cstr_u8_to_pos(cstr s, size_t u8idx); // byte pos offset at utf8 codepoint index
+const char* cstr_u8_at(const cstr* self, size_t u8idx); // char* position at utf8 codepoint index
+csview cstr_u8_chr(const cstr* self, size_t u8idx); // get utf8 character as a csview
+void cstr_u8_replace_at(cstr* self, size_t u8pos, size_t u8len, csview repl); // replace at utf8 indices
// iterate utf8 codepoints
cstr_iter cstr_begin(const cstr* self);
@@ -150,8 +160,7 @@ int main() {
cstr_erase_n(&s1, 7, 5); // -nine
printf("%s\n", cstr_str(&s1));
- //cstr_replace_at(&s1, cstr_find(s1, "seven"), 5, "four");
- cstr_replace(&s1, "seven", "four");
+ cstr_replace(&s1, "seven", "four", 1);
printf("%s\n", cstr_str(&s1));
// reassign:
diff --git a/docs/csview_api.md b/docs/csview_api.md
index 49f7cb70..e6a89d5e 100644
--- a/docs/csview_api.md
+++ b/docs/csview_api.md
@@ -27,22 +27,21 @@ All csview definitions and prototypes are available by including a single header
```c
csview c_sv(const char literal_only[]); // alias for csview_new
+csview c_sv(const char* str, size_t n); // overloaded csview constructor.
csview csview_new(const char literal_only[]); // construct from literal, no strlen()
csview csview_from(const char* str); // construct from const char*
-csview csview_from_s(const cstr* s); // construct from cstr
-csview csview_from_n(const char* str, size_t n); // construct
void csview_clear(csview* self);
size_t csview_size(csview sv);
bool csview_empty(csview sv);
bool csview_equals(csview sv, csview sv2);
-size_t csview_find(csview sv, csview needle);
-bool csview_contains(csview sv, csview needle);
+size_t csview_find(csview sv, csview search);
+bool csview_contains(csview sv, csview search);
bool csview_starts_with(csview sv, csview sub);
bool csview_ends_with(csview sv, csview sub);
-// requires i_implement defined before one include of csview.h
+// requires i_implement defined before inclusion of csview.h
csview csview_substr_ex(csview sv, intptr_t pos, size_t n); // negative pos count from end
csview csview_slice_ex(csview sv, intptr_t p1, intptr_t p2); // negative p1, p2 count from end
csview csview_token(csview sv, csview sep, size_t* start); // see split example below.
@@ -50,8 +49,9 @@ csview csview_token(csview sv, csview sep, size_t* start); // see sp
#### UTF8 methods
```c
-size_t csview_u8size(csview sv);
-csview csview_substr_u8(csview sv, size_t u8pos, size_t u8len);
+size_t csview_u8_size(csview sv);
+csview csview_u8_substr(csview sv, size_t u8pos, size_t u8len);
+csview csview_u8_slice(csview sv, size_t u8p1, size_t u8p2);
csview_iter csview_begin(const csview* self);
csview_iter csview_end(const csview* self);
@@ -60,14 +60,14 @@ void csview_next(csview_iter* it); // utf8 c
// requires linking with src/utf8code.c:
bool csview_valid_utf8(csview sv);
-// from utf8.h/utf8code.c:
+// from utf8.h, linking src/utf8code.c:
bool utf8_valid(const char* s);
bool utf8_valid_n(const char* s, size_t nbytes);
size_t utf8_size(const char *s);
size_t utf8_size_n(const char *s, size_t nbytes); // number of UTF8 codepoints within n bytes
const char* utf8_at(const char *s, size_t index); // from UTF8 index to char* position
size_t utf8_pos(const char* s, size_t index); // from UTF8 index to byte index position
-unsigned utf8_chr_size(const char* s); // 0-4 (0 if s[0] is illegal utf8)
+unsigned utf8_chr_size(const char* s); // 0-4 (0 if s[0] means illegal utf8)
uint32_t utf8_decode(utf8_decode_t *d, uint8_t byte); // decode next byte to utf8, return state.
unsigned utf8_encode(char *out, uint32_t codepoint); // encode unicode cp into out buffer
uint32_t utf8_peek(const char* s, int pos); // codepoint value at utf8 pos (may be negative)
@@ -75,22 +75,13 @@ uint32_t utf8_peek(const char* s, int pos); // codepoint
#### Extended cstr methods
```c
-cstr cstr_from_sv(csview sv); // construct cstr from csview
-csview cstr_sv(const cstr* self); // convert to csview from const cstr*
-
-csview cstr_substr(const cstr* s, intptr_t pos, size_t n); // negative pos count from end
-csview cstr_slice(const cstr* s, intptr_t p, intptr_t q); // negative p or q count from end
-
-csview cstr_assign_sv(cstr* self, csview sv); // return csview of assigned cstr
-void cstr_append_sv(cstr* self, csview sv);
-void cstr_insert_sv(cstr* self, size_t pos, csview sv);
-void cstr_replace_sv(cstr* self, size_t pos, size_t len, csview sv);
-
-bool cstr_equals_sv(cstr s, csview sv);
-size_t cstr_find_sv(cstr s, csview needle);
-bool cstr_contains_sv(cstr s, csview needle);
-bool cstr_starts_with_sv(cstr s, csview sub);
-bool cstr_ends_with_sv(cstr s, csview sub);
+csview cstr_substr(const cstr* self, size_t pos, size_t n);
+csview cstr_substr_ex(const cstr* s, intptr_t pos, size_t n); // negative pos count from end
+csview cstr_u8_substr(const cstr* self, size_t u8pos, size_t u8len);
+
+csview cstr_slice(const cstr* self, size_t p1, size_t p2);
+csview cstr_slice_ex(const cstr* s, intptr_t p, intptr_t q); // negative p or q count from end
+csview cstr_u8_slice(const cstr* self, size_t u8p1, size_t u8p2);
```
#### Helper methods
@@ -115,8 +106,8 @@ uint64_t csview_hash(const csview* x);
|:---------------|:---------------------|:---------------------------------------------|
| `csview_null` | same as `c_sv("")` | `sview = csview_null;` |
| `csview_npos` | same as `cstr_npos` | |
-| `c_PRIsv` | printf format | |
-| `c_ARGsv(sv)` | printf argument | `printf("sv: %" c_PRIsv "\n", c_ARGsv(sv));` |
+| `c_PRIsv` | `".*s"` | `printf("sv: %" c_PRIsv "\n", c_ARGsv(sv));` |
+| `c_ARGsv(sv)` | printf argument | `printf("sv: %.*s\n", c_ARGsv(sv));` |
## Example
```c
@@ -157,18 +148,18 @@ int main()
{
c_auto (cstr, s1) {
s1 = cstr_new("hell😀 w😀rld");
- cstr_replace_sv(&s1, utf8_substr(cstr_str(&s1), 7, 1), c_sv("x"));
+ cstr_u8_replace_at(&s1, 7, 1, c_sv("ø"));
printf("%s\n", cstr_str(&s1));
c_foreach (i, cstr, s1)
- printf("%" c_PRIsv ",", c_ARGsv(i.chr));
+ printf("%.*s,", c_ARGsv(i.chr));
}
}
```
Output:
```
-hell😀 wxrld
-h,e,l,l,😀, ,w,x,r,l,d,
+hell😀 wørld
+h,e,l,l,😀, ,w,ø,r,l,d,
```
### Example 3: csview tokenizer (string split)
diff --git a/examples/cstr_match.c b/examples/cstr_match.c
index fd420f62..9c4fa2d3 100644
--- a/examples/cstr_match.c
+++ b/examples/cstr_match.c
@@ -5,7 +5,7 @@
int main()
{
c_autovar (cstr ss = cstr_new("The quick brown fox jumps over the lazy dog.JPG"), cstr_drop(&ss)) {
- size_t pos = cstr_find_from(ss, 0, "brown");
+ size_t pos = cstr_find_at(ss, 0, "brown");
printf("%" PRIuMAX " [%s]\n", pos, pos == cstr_npos ? "<NULL>" : cstr_str(&ss) + pos);
printf("equals: %d\n", cstr_equals(ss, "The quick brown fox jumps over the lazy dog.JPG"));
printf("contains: %d\n", cstr_contains(ss, "umps ove"));
@@ -14,9 +14,9 @@ int main()
printf("ends_with: %d\n", cstr_ends_with(ss, ".JPG"));
cstr s1 = cstr_new("hell😀 w😀rl🐨");
- csview ch1 = cstr_chr_u8(&s1, 7);
- csview ch2 = cstr_chr_u8(&s1, 10);
- printf("%s\nsize: %" PRIuMAX ", %" PRIuMAX "\n", cstr_str(&s1), cstr_u8size(s1), cstr_size(s1));
+ csview ch1 = cstr_u8_chr(&s1, 7);
+ csview ch2 = cstr_u8_chr(&s1, 10);
+ printf("%s\nsize: %" PRIuMAX ", %" PRIuMAX "\n", cstr_str(&s1), cstr_u8_size(s1), cstr_size(s1));
printf("ch1: %" c_PRIsv "\n", c_ARGsv(ch1));
printf("ch2: %" c_PRIsv "\n", c_ARGsv(ch2));
}
diff --git a/examples/demos.c b/examples/demos.c
index 4cb50082..052c4e32 100644
--- a/examples/demos.c
+++ b/examples/demos.c
@@ -13,7 +13,7 @@ void stringdemo1()
cstr_erase_n(&cs, 7, 5); // -nine
printf("%s.\n", cstr_str(&cs));
- cstr_replace(&cs, "seven", "four");
+ cstr_replace(&cs, "seven", "four", 1);
printf("%s.\n", cstr_str(&cs));
cstr_take(&cs, cstr_from_fmt("%s *** %s", cstr_str(&cs), cstr_str(&cs)));
diff --git a/examples/regex_replace.c b/examples/regex_replace.c
index 21252236..3dcb965d 100644
--- a/examples/regex_replace.c
+++ b/examples/regex_replace.c
@@ -41,7 +41,7 @@ int main()
cregex_drop(&re);
printf("euros: %s\n", cstr_str(&str));
- /* Wrap all words in {} */
+ /* Wrap all words in ${} */
cstr_take(&str, cregex_replace_p("[52] apples and [31] mangoes", "[a-z]+", "$${$0}"));
printf("curly: %s\n", cstr_str(&str));
}
diff --git a/examples/replace.c b/examples/replace.c
index 2926977c..13b6eaaf 100644
--- a/examples/replace.c
+++ b/examples/replace.c
@@ -8,23 +8,27 @@ int main ()
// replace signatures used in the same order as described above:
- // Ustring positions: 0123456789*123456789*12345
- cstr s = cstr_from(base); // "this is a test string."
+ // Ustring positions: 0123456789*123456789*12345
+ cstr s = cstr_from(base); // "this is a test string."
cstr m = cstr_clone(s);
c_autodefer (cstr_drop(&s), cstr_drop(&m)) {
cstr_append(&m, cstr_str(&m));
cstr_append(&m, cstr_str(&m));
printf("%s\n", cstr_str(&m));
- cstr_replace_at(&s, 9, 5, s2); // "this is an example string." (1)
+ cstr_replace_at(&s, 9, 5, s2); // "this is an example string." (1)
printf("(1) %s\n", cstr_str(&s));
- cstr_replace_with_n(&s, 19, 6, s3+7, 6); // "this is an example phrase." (2)
+
+ cstr_replace_at_sv(&s, 19, 6, c_sv(s3+7, 6)); // "this is an example phrase." (2)
printf("(2) %s\n", cstr_str(&s));
- cstr_replace_at(&s, 8, 10, "just a"); // "this is just a phrase." (3)
+
+ cstr_replace_at(&s, 8, 10, "just a"); // "this is just a phrase." (3)
printf("(3) %s\n", cstr_str(&s));
- cstr_replace_with_n(&s, 8, 6,"a shorty", 7); // "this is a short phrase." (4)
+
+ cstr_replace_at_sv(&s, 8, 6, c_sv("a shorty", 7)); // "this is a short phrase." (4)
printf("(4) %s\n", cstr_str(&s));
- cstr_replace_at(&s, 22, 1, "!!!"); // "this is a short phrase!!!" (5)
+
+ cstr_replace_at(&s, 22, 1, "!!!"); // "this is a short phrase!!!" (5)
printf("(5) %s\n", cstr_str(&s));
}
}
diff --git a/examples/utf8replace_c.c b/examples/utf8replace_c.c
index c38b37e4..86d8bd69 100644
--- a/examples/utf8replace_c.c
+++ b/examples/utf8replace_c.c
@@ -1,3 +1,4 @@
+#define i_implement
#include <stc/cstr.h>
#include <stc/csview.h>
@@ -6,14 +7,12 @@ int main() {
hello = cstr_new("hell😀 w😀rld");
printf("%s\n", cstr_str(&hello));
- cstr_replace_sv(
- &hello,
- csview_substr_u8(cstr_sv(&hello), 7, 1),
- c_sv("🐨")
- );
+ /* replace second smiley at utf8 codepoint pos 7 */
+ cstr_u8_replace_at(&hello, 7, 1, c_sv("🐨"));
+
printf("%s\n", cstr_str(&hello));
- cstr_replace(&hello, "🐨", "ø");
+ cstr_replace(&hello, "🐨", "ø", 1);
printf("%s\n", cstr_str(&hello));
c_foreach (c, cstr, hello)
diff --git a/include/stc/alt/cstr.h b/include/stc/alt/cstr.h
index 77067740..82ab585a 100644
--- a/include/stc/alt/cstr.h
+++ b/include/stc/alt/cstr.h
@@ -48,21 +48,19 @@ typedef struct { size_t size, cap; char chr[1]; } cstr_priv;
STC_API cstr cstr_from_n(const char* str, size_t n);
STC_API cstr cstr_from_fmt(const char* fmt, ...);
-STC_API cstr cstr_from_replace_all(const char* str, size_t str_len,
- const char* find, size_t find_len,
- const char* repl, size_t repl_len);
+STC_API cstr cstr_from_replace(csview str, csview find, csview repl, unsigned count);
STC_API char* cstr_reserve(cstr* self, size_t cap);
STC_API void cstr_resize(cstr* self, size_t len, char fill);
STC_API cstr* cstr_assign_n(cstr* self, const char* str, size_t n);
STC_API int cstr_printf(cstr* self, const char* fmt, ...);
STC_API cstr* cstr_append_n(cstr* self, const char* str, size_t n);
-STC_API void cstr_replace_with_n(cstr* self, size_t pos, size_t len, const char* str, size_t n);
-STC_API void cstr_replace_all(cstr* self, const char* find, const char* replace);
+STC_API void MyExt(cstr* self, size_t pos, size_t len, const char* str, size_t n);
+STC_API void cstr_replace(cstr* self, const char* find, const char* replace);
+STC_DEF void cstr_replace_at_sv(cstr* self, const size_t pos, size_t len, csview repl);
STC_API void cstr_erase_n(cstr* self, size_t pos, size_t n);
STC_API size_t cstr_find(cstr s, const char* needle);
-STC_API size_t cstr_find_from(cstr s, size_t pos, const char* needle);
+STC_API size_t cstr_find_at(cstr s, size_t pos, const char* needle);
STC_API bool cstr_getdelim(cstr *self, int delim, FILE *stream);
-STC_API void cstr_replace_all(cstr* self, const char* find, const char* repl);
STC_INLINE cstr cstr_init() { return cstr_null; }
STC_INLINE const char* cstr_str(const cstr* self) { return self->str; }
@@ -96,15 +94,15 @@ STC_INLINE void cstr_push_back(cstr* self, char value)
STC_INLINE void cstr_pop_back(cstr* self)
{ self->str[ --_cstr_p(self)->size ] = '\0'; }
STC_INLINE void cstr_insert_n(cstr* self, const size_t pos, const char* str, const size_t n)
- { cstr_replace_with_n(self, pos, 0, str, n); }
+ { cstr_replace_at_sv(self, pos, 0, c_sv(str, n)); }
STC_INLINE void cstr_insert(cstr* self, const size_t pos, const char* str)
- { cstr_replace_with_n(self, pos, 0, str, strlen(str)); }
+ { cstr_replace_at_sv(self, pos, 0, c_sv(str, strlen(str))); }
STC_INLINE void cstr_insert_s(cstr* self, const size_t pos, cstr s)
- { cstr_replace_with_n(self, pos, 0, s.str, _cstr_p(&s)->size); }
+ { cstr_replace_at_sv(self, pos, 0, c_sv(s.str, _cstr_p(&s)->size)); }
STC_INLINE void cstr_replace_at(cstr* self, const size_t pos, const size_t len, const char* str)
- { cstr_replace_with_n(self, pos, len, str, strlen(str)); }
+ { cstr_replace_at_sv(self, pos, len, c_sv(str, strlen(str))); }
STC_INLINE void cstr_replace_s(cstr* self, const size_t pos, const size_t len, cstr s)
- { cstr_replace_with_n(self, pos, len, s.str, _cstr_p(&s)->size); }
+ { cstr_replace_at_sv(self, pos, len, c_sv(s.str, _cstr_p(&s)->size)); }
STC_INLINE void cstr_erase(cstr* self, const size_t pos)
{ cstr_erase_n(self, pos, 1); }
STC_INLINE char* cstr_front(cstr* self) { return self->str; }
@@ -184,6 +182,17 @@ STC_INLINE uint64_t cstr_hash(const cstr *self) {
return c_fasthash(self->str, _cstr_p(self)->size);
}
+STC_INLINE void
+cstr_replace_sv(cstr* self, csview find, csview repl, unsigned count) {
+ cstr_take(self, cstr_from_replace(c_sv(self->str, _cstr_p(self)->size),
+ find, repl, count);
+}
+
+STC_INLINE void
+cstr_replace(cstr* self, const char* find, const char* repl, unsigned count) {
+ cstr_replace_sv(self, c_sv(find, strlen(find)),
+ c_sv(repl, strlen(repl)), count);
+}
/* -------------------------- IMPLEMENTATION ------------------------- */
#if defined(i_implement)
@@ -306,40 +315,33 @@ STC_INLINE void _cstr_internal_move(cstr* self, const size_t pos1, const size_t
}
STC_DEF void
-cstr_replace_with_n(cstr* self, const size_t pos, size_t len, const char* str, const size_t n) {
+cstr_replace_at_sv(cstr* self, const size_t pos, size_t len, csview repl) {
const size_t sz = cstr_size(*self);
if (len > sz - pos) len = sz - pos;
- c_autobuf (xstr, char, n) {
- memcpy(xstr, str, n);
- _cstr_internal_move(self, pos + len, pos + n);
- memcpy(&self->str[pos], xstr, n);
+ c_autobuf (xstr, char, repl.size) {
+ memcpy(xstr, repl.str, repl.size);
+ _cstr_internal_move(self, pos + len, pos + repl.size);
+ memcpy(&self->str[pos], xstr, repl.size);
}
}
STC_DEF cstr
-cstr_from_replace_all(const char* str, const size_t str_len,
- const char* find, const size_t find_len,
- const char* repl, const size_t repl_len) {
+cstr_from_replace(csview str, csview find, csview repl, unsigned count) {
cstr out = cstr_null;
size_t from = 0; char* res;
- if (find_len)
- while ((res = c_strnstrn(str + from, find, str_len - from, find_len))) {
- const size_t pos = res - str;
- cstr_append_n(&out, str + from, pos - from);
- cstr_append_n(&out, repl, repl_len);
- from = pos + find_len;
+ if (count == 0) count = ~0;
+ if (find.size)
+ while (count-- && (res = c_strnstrn(str + from, find.str, str.size - from, find.size))) {
+ const size_t pos = res - str.str;
+ cstr_append_n(&out, str.str + from, pos - from);
+ cstr_append_n(&out, repl.str, repl_len);
+ from = pos + find.size;
}
- cstr_append_n(&out, str + from, str_len - from);
+ cstr_append_n(&out, str.str + from, str.size - from);
return out;
}
STC_DEF void
-cstr_replace_all(cstr* self, const char* find, const char* repl) {
- cstr_take(self, cstr_from_replace_all(self->str, _cstr_p(self)->size,
- find, strlen(find), repl, strlen(repl)));
-}
-
-STC_DEF void
cstr_erase_n(cstr* self, const size_t pos, size_t n) {
const size_t len = _cstr_p(self)->size;
if (n > len - pos) n = len - pos;
@@ -377,7 +379,7 @@ cstr_find(cstr s, const char* needle) {
}
STC_DEF size_t
-cstr_find_from(cstr s, const size_t pos, const char* needle) {
+cstr_find_at(cstr s, const size_t pos, const char* needle) {
if (pos > _cstr_p(&s)->size) return cstr_npos;
char* res = strstr(s.str + pos, needle);
return res ? res - s.str : cstr_npos;
diff --git a/include/stc/ccommon.h b/include/stc/ccommon.h
index e87e7678..9624909e 100644
--- a/include/stc/ccommon.h
+++ b/include/stc/ccommon.h
@@ -111,8 +111,11 @@
typedef const char* crawstr;
#define crawstr_cmp(xp, yp) strcmp(*(xp), *(yp))
#define crawstr_hash(p) c_strhash(*(p))
+
#define c_strlen_lit(literal) (sizeof "" literal - 1U)
-#define c_sv(lit) (c_make(csview){lit, c_strlen_lit(lit)})
+#define c_sv(...) c_MACRO_OVERLOAD(c_sv, __VA_ARGS__)
+#define c_sv1(lit) (c_make(csview){lit, c_strlen_lit(lit)})
+#define c_sv2(str, n) (c_make(csview){str, n})
#define c_PRIsv ".*s"
#define c_ARGsv(sv) (int)(sv).size, (sv).str
diff --git a/include/stc/cstr.h b/include/stc/cstr.h
index 6db5ef49..92f49d92 100644
--- a/include/stc/cstr.h
+++ b/include/stc/cstr.h
@@ -80,14 +80,15 @@ STC_API char* _cstr_internal_move(cstr* self, size_t pos1, size_t pos2);
STC_API char* cstr_reserve(cstr* self, size_t cap);
STC_API void cstr_shrink_to_fit(cstr* self);
STC_API void cstr_resize(cstr* self, size_t size, char value);
-STC_API size_t cstr_find_from(cstr s, size_t pos, const char* search);
+STC_API size_t cstr_find_at(cstr s, size_t pos, const char* search);
STC_API char* cstr_assign_n(cstr* self, const char* str, size_t len);
STC_API char* cstr_append_n(cstr* self, const char* str, size_t len);
STC_API bool cstr_getdelim(cstr *self, int delim, FILE *fp);
STC_API void cstr_erase_n(cstr* self, size_t pos, size_t len);
STC_API cstr cstr_from_fmt(const char* fmt, ...);
STC_API int cstr_printf(cstr* self, const char* fmt, ...);
-STC_API void cstr_replace_all(cstr* self, const char* search, const char* repl);
+STC_API void cstr_replace(cstr* self, const char* search, const char* repl, unsigned count);
+STC_API cstr cstr_replace_sv(csview sv, csview search, csview repl, unsigned count);
STC_INLINE cstr_buf cstr_buffer(cstr* s) {
return cstr_is_long(s)
@@ -183,21 +184,22 @@ STC_INLINE bool cstr_valid_utf8(const cstr* self)
// other utf8
-STC_INLINE size_t cstr_u8size(cstr s)
+STC_INLINE size_t cstr_u8_size(cstr s)
{ return utf8_size(cstr_str(&s)); }
-STC_INLINE size_t cstr_u8size_n(cstr s, size_t nbytes)
+STC_INLINE size_t cstr_u8_size_n(cstr s, size_t nbytes)
{ return utf8_size_n(cstr_str(&s), nbytes); }
-STC_INLINE size_t cstr_pos_u8(const cstr* self, size_t u8idx)
+STC_INLINE size_t cstr_u8_to_pos(const cstr* self, size_t u8idx)
{ return utf8_pos(cstr_str(self), u8idx); }
-STC_INLINE const char* cstr_at_u8(const cstr* self, size_t u8idx)
+STC_INLINE const char* cstr_u8_at(const cstr* self, size_t u8idx)
{ return utf8_at(cstr_str(self), u8idx); }
-STC_INLINE csview cstr_chr_u8(const cstr* self, size_t u8idx) {
- csview sv = cstr_sv(self);
- sv.str = utf8_at(sv.str, u8idx);
+STC_INLINE csview cstr_u8_chr(const cstr* self, size_t u8idx) {
+ const char* str = cstr_str(self);
+ csview sv;
+ sv.str = utf8_at(str, u8idx);
sv.size = utf8_chr_size(sv.str);
return sv;
}
@@ -240,110 +242,138 @@ STC_INLINE bool cstr_eq(const cstr* s1, const cstr* s2) {
return x.size == y.size && !memcmp(x.str, y.str, x.size);
}
+
STC_INLINE bool cstr_equals(cstr s1, const char* str)
{ return !strcmp(cstr_str(&s1), str); }
-STC_INLINE bool cstr_iequals(cstr s1, const char* str)
- { return !utf8_icmp(cstr_str(&s1), str); }
+STC_INLINE bool cstr_equals_sv(cstr s, csview sv)
+ { return sv.size == cstr_size(s) && !memcmp(cstr_str(&s), sv.str, sv.size); }
STC_INLINE bool cstr_equals_s(cstr s1, cstr s2)
{ return !cstr_cmp(&s1, &s2); }
+STC_INLINE bool cstr_iequals(cstr s1, const char* str)
+ { return !utf8_icmp(cstr_str(&s1), str); }
+
+
STC_INLINE size_t cstr_find(cstr s, const char* search) {
const char *str = cstr_str(&s), *res = strstr((char*)str, search);
return res ? res - str : cstr_npos;
}
+STC_INLINE size_t cstr_find_sv(cstr s, csview search) {
+ char* res = c_strnstrn(cstr_str(&s), search.str, cstr_size(s), search.size);
+ return res ? res - cstr_str(&s) : cstr_npos;
+}
+
STC_INLINE size_t cstr_find_s(cstr s, cstr search)
{ return cstr_find(s, cstr_str(&search)); }
+
STC_INLINE bool cstr_contains(cstr s, const char* search)
{ return strstr(cstr_data(&s), search) != NULL; }
+STC_INLINE bool cstr_contains_sv(cstr s, csview search)
+ { return c_strnstrn(cstr_str(&s), search.str, cstr_size(s), search.size) != NULL; }
+
STC_INLINE bool cstr_contains_s(cstr s, cstr search)
{ return strstr(cstr_data(&s), cstr_str(&search)) != NULL; }
+
+STC_INLINE bool cstr_starts_with_sv(cstr s, csview sub) {
+ if (sub.size > cstr_size(s)) return false;
+ return !memcmp(cstr_str(&s), sub.str, sub.size);
+}
+
STC_INLINE bool cstr_starts_with(cstr s, const char* sub) {
const char* str = cstr_str(&s);
while (*sub && *str == *sub) ++str, ++sub;
return !*sub;
}
+
+STC_INLINE bool cstr_starts_with_s(cstr s, cstr sub)
+ { return cstr_starts_with_sv(s, cstr_sv(&sub)); }
+
STC_INLINE bool cstr_istarts_with(cstr s, const char* sub) {
csview sv = cstr_sv(&s);
size_t len = strlen(sub);
return len <= sv.size && !utf8_icmp_n(cstr_npos, sv.str, sv.size, sub, len);
}
-STC_INLINE bool cstr_starts_with_s(cstr s, cstr sub)
- { return cstr_starts_with(s, cstr_str(&sub)); }
-STC_INLINE bool cstr_ends_with(cstr s, const char* sub) {
+STC_INLINE bool cstr_ends_with_sv(cstr s, csview sub) {
csview sv = cstr_sv(&s);
- size_t n = strlen(sub);
- return n <= sv.size && !memcmp(sv.str + sv.size - n, sub, n);
+ if (sub.size > sv.size) return false;
+ return !memcmp(sv.str + sv.size - sub.size, sub.str, sub.size);
}
+STC_INLINE bool cstr_ends_with_s(cstr s, cstr sub)
+ { return cstr_ends_with_sv(s, cstr_sv(&sub)); }
+
+STC_INLINE bool cstr_ends_with(cstr s, const char* sub)
+ { return cstr_ends_with_sv(s, c_sv(sub, strlen(sub))); }
+
STC_INLINE bool cstr_iends_with(cstr s, const char* sub) {
csview sv = cstr_sv(&s);
size_t n = strlen(sub);
return n <= sv.size && !utf8_icmp(sv.str + sv.size - n, sub);
}
-STC_INLINE bool cstr_ends_with_s(cstr s, cstr sub)
- { return cstr_ends_with(s, cstr_str(&sub)); }
STC_INLINE char* cstr_assign(cstr* self, const char* str)
{ return cstr_assign_n(self, str, strlen(str)); }
-STC_INLINE char* cstr_assign_s(cstr* self, cstr s) {
+STC_INLINE char* cstr_assign_sv(cstr* self, csview sv)
+ { return cstr_assign_n(self, sv.str, sv.size); }
+
+STC_INLINE char* cstr_copy(cstr* self, cstr s) {
csview sv = cstr_sv(&s);
return cstr_assign_n(self, sv.str, sv.size);
}
+
STC_INLINE char* cstr_append(cstr* self, const char* str)
{ return cstr_append_n(self, str, strlen(str)); }
+STC_INLINE void cstr_append_sv(cstr* self, csview sv)
+ { cstr_append_n(self, sv.str, sv.size); }
+
STC_INLINE char* cstr_append_s(cstr* self, cstr s) {
csview sv = cstr_sv(&s);
return cstr_append_n(self, sv.str, sv.size);
}
-STC_INLINE void cstr_replace_with_n(cstr* self, size_t pos, size_t len, const char* repl, size_t rlen) {
- char* d = _cstr_internal_move(self, pos + len, pos + rlen);
- memcpy(d + pos, repl, rlen);
+
+STC_INLINE void cstr_replace_at_sv(cstr* self, size_t pos, size_t len, const csview repl) {
+ char* d = _cstr_internal_move(self, pos + len, pos + repl.size);
+ memcpy(d + pos, repl.str, repl.size);
}
STC_INLINE void cstr_replace_at(cstr* self, size_t pos, size_t len, const char* repl)
- { cstr_replace_with_n(self, pos, len, repl, strlen(repl)); }
+ { cstr_replace_at_sv(self, pos, len, c_sv(repl, strlen(repl))); }
-STC_INLINE size_t cstr_replace_from(cstr* self, size_t pos, const char* search, const char* repl) {
- pos = cstr_find_from(*self, pos, search);
- if (pos == cstr_npos)
- return pos;
- const size_t rlen = strlen(repl);
- cstr_replace_with_n(self, pos, strlen(search), repl, rlen);
- return pos + rlen;
-}
+STC_INLINE void cstr_replace_at_s(cstr* self, size_t pos, size_t len, cstr repl)
+ { cstr_replace_at_sv(self, pos, len, cstr_sv(&repl)); }
-STC_INLINE size_t cstr_replace(cstr* self, const char* search, const char* repl)
- { return cstr_replace_from(self, 0, search, repl); }
-
-STC_INLINE void cstr_replace_s(cstr* self, size_t pos, size_t len, cstr s) {
- csview sv = cstr_sv(&s);
- cstr_replace_with_n(self, pos, len, sv.str, sv.size);
+STC_INLINE void cstr_u8_replace_at(cstr* self, size_t u8pos, size_t u8len, csview repl) {
+ csview sv = cstr_sv(self);
+ const char* p = utf8_at(sv.str, u8pos);
+ cstr_replace_at_sv(self, p - sv.str, utf8_pos(p, u8len), repl);
}
-STC_INLINE void cstr_insert_n(cstr* self, size_t pos, const char* str, size_t len)
- { cstr_replace_with_n(self, pos, 0, str, len); }
STC_INLINE void cstr_insert(cstr* self, size_t pos, const char* str)
- { cstr_replace_with_n(self, pos, 0, str, strlen(str)); }
+ { cstr_replace_at_sv(self, pos, 0, c_sv(str, strlen(str))); }
+
+STC_INLINE void cstr_insert_sv(cstr* self, size_t pos, csview sv)
+ { cstr_replace_at_sv(self, pos, 0, sv); }
STC_INLINE void cstr_insert_s(cstr* self, size_t pos, cstr s) {
csview sv = cstr_sv(&s);
- cstr_replace_with_n(self, pos, 0, sv.str, sv.size);
+ cstr_replace_at_sv(self, pos, 0, sv);
}
+
STC_INLINE bool cstr_getline(cstr *self, FILE *fp)
{ return cstr_getdelim(self, '\n', fp); }
@@ -360,7 +390,7 @@ STC_DEF char* _cstr_internal_move(cstr* self, const size_t pos1, const size_t po
if (pos1 != pos2) {
const size_t newlen = r.size + pos2 - pos1;
if (newlen > r.cap)
- r.data = cstr_reserve(self, (r.size*3 >> 1) + pos2 - pos1);
+ r.data = cstr_reserve(self, r.size*3/2 + pos2 - pos1);
memmove(&r.data[pos2], &r.data[pos1], r.size - pos1);
_cstr_set_size(self, newlen);
}
@@ -422,7 +452,7 @@ STC_DEF void cstr_resize(cstr* self, const size_t size, const char value) {
_cstr_set_size(self, size);
}
-STC_DEF size_t cstr_find_from(cstr s, const size_t pos, const char* search) {
+STC_DEF size_t cstr_find_at(cstr s, const size_t pos, const char* search) {
csview sv = cstr_sv(&s);
if (pos > sv.size) return cstr_npos;
const char* res = strstr((char*)sv.str + pos, search);
@@ -440,7 +470,7 @@ STC_DEF char* cstr_append_n(cstr* self, const char* str, const size_t len) {
cstr_buf r = cstr_buffer(self);
if (r.size + len > r.cap) {
const size_t off = (size_t)(str - r.data);
- r.data = cstr_reserve(self, (r.size*3 >> 1) + len);
+ r.data = cstr_reserve(self, r.size*3/2 + len);
if (off <= r.size) str = r.data + off; /* handle self append */
}
memcpy(r.data + r.size, str, len);
@@ -461,7 +491,7 @@ STC_DEF bool cstr_getdelim(cstr *self, const int delim, FILE *fp) {
}
if (pos == r.cap) {
_cstr_set_size(self, pos);
- r.data = cstr_reserve(self, (r.cap = (r.cap*3 >> 1) + 16));
+ r.data = cstr_reserve(self, (r.cap = r.cap*3/2 + 16));
}
r.data[pos++] = (char) c;
c = fgetc(fp);
@@ -469,27 +499,26 @@ STC_DEF bool cstr_getdelim(cstr *self, const int delim, FILE *fp) {
}
STC_DEF cstr
-cstr_from_replace_all(const char* str, const size_t str_len,
- const char* search, const size_t search_len,
- const char* repl, const size_t repl_len) {
+cstr_replace_sv(csview in, csview search, csview repl, unsigned count) {
cstr out = cstr_null;
size_t from = 0; char* res;
- if (search_len)
- while ((res = c_strnstrn(str + from, search, str_len - from, search_len))) {
- const size_t pos = res - str;
- cstr_append_n(&out, str + from, pos - from);
- cstr_append_n(&out, repl, repl_len);
- from = pos + search_len;
+ if (!count) count = ~0;
+ if (search.size)
+ while (count-- && (res = c_strnstrn(in.str + from, search.str, in.size - from, search.size))) {
+ const size_t pos = res - in.str;
+ cstr_append_n(&out, in.str + from, pos - from);
+ cstr_append_n(&out, repl.str, repl.size);
+ from = pos + search.size;
}
- cstr_append_n(&out, str + from, str_len - from);
+ cstr_append_n(&out, in.str + from, in.size - from);
return out;
}
STC_DEF void
-cstr_replace_all(cstr* self, const char* search, const char* repl) {
- csview sv = cstr_sv(self);
- cstr_take(self, cstr_from_replace_all(sv.str, sv.size, search, strlen(search),
- repl, strlen(repl)));
+cstr_replace(cstr* self, const char* search, const char* repl, unsigned count) {
+ csview in = cstr_sv(self);
+ cstr_take(self, cstr_replace_sv(in, c_sv(search, strlen(search)),
+ c_sv(repl, strlen(repl)), count));
}
STC_DEF void cstr_erase_n(cstr* self, const size_t pos, size_t len) {
diff --git a/include/stc/csview.h b/include/stc/csview.h
index 39bfa354..ec40a8be 100644
--- a/include/stc/csview.h
+++ b/include/stc/csview.h
@@ -38,8 +38,6 @@ STC_API csview csview_token(csview sv, csview sep, size_t* start);
STC_INLINE csview csview_init() { return csview_null; }
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 void csview_clear(csview* self) { *self = csview_null; }
STC_INLINE size_t csview_size(csview sv) { return sv.size; }
@@ -48,13 +46,13 @@ STC_INLINE bool csview_empty(csview sv) { return sv.size == 0; }
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);
+STC_INLINE size_t csview_find(csview sv, csview search) {
+ char* res = c_strnstrn(sv.str, search.str, sv.size, search.size);
return res ? res - sv.str : csview_npos;
}
-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_contains(csview sv, csview search)
+ { return c_strnstrn(sv.str, search.str, sv.size, search.size) != NULL; }
STC_INLINE bool csview_starts_with(csview sv, csview sub) {
if (sub.size > sv.size) return false;
@@ -89,15 +87,18 @@ STC_INLINE void csview_next(csview_iter* it)
{ it->ref += it->chr.size; it->chr.size = utf8_chr_size(it->ref); }
/* utf8 */
-STC_INLINE size_t csview_u8size(csview sv)
+STC_INLINE size_t csview_u8_size(csview sv)
{ return utf8_size_n(sv.str, sv.size); }
-STC_INLINE csview csview_substr_u8(csview sv, size_t u8pos, size_t u8len) {
+STC_INLINE csview csview_u8_substr(csview sv, size_t u8pos, size_t u8len) {
sv.str = utf8_at(sv.str, u8pos);
sv.size = utf8_pos(sv.str, u8len);
return sv;
}
+STC_INLINE csview csview_u8_slice(csview sv, size_t u8p1, size_t u8p2)
+ { return csview_u8_substr(sv, u8p1, u8p2 - u8p1); }
+
STC_INLINE bool csview_valid_utf8(csview sv) // depends on src/utf8code.c
{ return utf8_valid_n(sv.str, sv.size); }
@@ -105,53 +106,24 @@ STC_INLINE bool csview_valid_utf8(csview sv) // depends on src/utf8code.c
/* csview interaction with cstr: */
#ifdef CSTR_H_INCLUDED
-STC_INLINE csview csview_from_s(const cstr* self)
- { return c_make(csview){cstr_str(self), cstr_size(*self)}; }
-
STC_INLINE csview cstr_substr(const cstr* self, size_t pos, size_t n)
- { return csview_substr(csview_from_s(self), pos, n); }
+ { return csview_substr(cstr_sv(self), pos, n); }
STC_INLINE csview cstr_slice(const cstr* self, size_t p1, size_t p2)
- { return csview_slice(csview_from_s(self), p1, p2); }
+ { return csview_slice(cstr_sv(self), p1, p2); }
STC_INLINE csview cstr_substr_ex(const cstr* self, intptr_t pos, size_t n)
- { return csview_substr_ex(csview_from_s(self), pos, n); }
+ { return csview_substr_ex(cstr_sv(self), pos, n); }
STC_INLINE csview cstr_slice_ex(const cstr* self, intptr_t p1, intptr_t p2)
- { return csview_slice_ex(csview_from_s(self), p1, p2); }
-
-STC_INLINE char* cstr_assign_sv(cstr* self, csview sv)
- { return cstr_assign_n(self, sv.str, sv.size); }
+ { return csview_slice_ex(cstr_sv(self), p1, p2); }
-STC_INLINE void cstr_append_sv(cstr* self, csview sv)
- { cstr_append_n(self, sv.str, sv.size); }
+STC_INLINE csview cstr_u8_substr(const cstr* self , size_t u8pos, size_t u8len)
+ { return csview_u8_substr(cstr_sv(self), u8pos, u8len); }
-STC_INLINE void cstr_insert_sv(cstr* self, size_t pos, csview sv)
- { cstr_replace_with_n(self, pos, 0, sv.str, sv.size); }
+STC_INLINE csview cstr_u8_slice(const cstr* self , size_t u8p1, size_t u8p2)
+ { return csview_u8_substr(cstr_sv(self), u8p1, u8p2 - u8p1); }
-STC_INLINE void cstr_replace_sv(cstr* self, csview sub, csview with)
- { cstr_replace_with_n(self, sub.str - cstr_str(self), sub.size, with.str, with.size); }
-
-STC_INLINE bool cstr_equals_sv(cstr s, csview sv)
- { return sv.size == cstr_size(s) && !memcmp(cstr_str(&s), sv.str, sv.size); }
-
-STC_INLINE size_t cstr_find_sv(cstr s, csview needle) {
- char* res = c_strnstrn(cstr_str(&s), needle.str, cstr_size(s), needle.size);
- return res ? res - cstr_str(&s) : cstr_npos;
-}
-
-STC_INLINE bool cstr_contains_sv(cstr s, csview needle)
- { return c_strnstrn(cstr_str(&s), needle.str, cstr_size(s), needle.size) != NULL; }
-
-STC_INLINE bool cstr_starts_with_sv(cstr s, csview sub) {
- if (sub.size > cstr_size(s)) return false;
- return !memcmp(cstr_str(&s), sub.str, sub.size);
-}
-
-STC_INLINE bool cstr_ends_with_sv(cstr s, csview sub) {
- if (sub.size > cstr_size(s)) return false;
- return !memcmp(cstr_str(&s) + cstr_size(s) - sub.size, sub.str, sub.size);
-}
#endif
/* ---- Container helper functions ---- */