From 78d8668e6d527070568a405408ed906e51055bf4 Mon Sep 17 00:00:00 2001 From: Tyge Løvset Date: Mon, 14 Aug 2023 16:46:24 +0200 Subject: Reverted csubstr => csview. Sorry about that! Added crawstr to become the null-terminated string view. --- README.md | 32 ++-- docs/crawstr_api.md | 130 +++++++++++++ docs/cregex_api.md | 28 +-- docs/cstr_api.md | 34 ++-- docs/csubstr_api.md | 221 ----------------------- docs/csview_api.md | 217 +++++++++++++++------- include/stc/ccommon.h | 13 +- include/stc/crawstr.h | 116 ++++++++++++ include/stc/cregex.h | 36 ++-- include/stc/cstr.h | 148 +++++++-------- include/stc/csubstr.h | 211 ---------------------- include/stc/csview.h | 159 ++++++++++++---- include/stc/forward.h | 34 ++-- include/stc/priv/template.h | 14 +- include/stc/utf8.h | 4 +- misc/benchmarks/various/string_bench_STC.cpp | 32 ++-- misc/examples/algorithms/forfilter.c | 12 +- misc/examples/regularexpressions/regex2.c | 2 +- misc/examples/regularexpressions/regex_match.c | 4 +- misc/examples/regularexpressions/regex_replace.c | 6 +- misc/examples/strings/cstr_match.c | 10 +- misc/examples/strings/replace.c | 4 +- misc/examples/strings/splitstr.c | 8 +- misc/examples/strings/sso_substr.c | 14 +- misc/examples/strings/sview_split.c | 14 +- misc/examples/strings/utf8replace_c.c | 4 +- misc/tests/cregex_test.c | 32 ++-- src/cregex.c | 28 +-- src/libstc.c | 2 +- src/singleupdate.sh | 2 +- src/utf8code.c | 2 +- 31 files changed, 786 insertions(+), 787 deletions(-) create mode 100644 docs/crawstr_api.md delete mode 100644 docs/csubstr_api.md create mode 100644 include/stc/crawstr.h delete mode 100644 include/stc/csubstr.h diff --git a/README.md b/README.md index 1c8c3878..d99d8a76 100644 --- a/README.md +++ b/README.md @@ -28,8 +28,8 @@ Containers - [***csmap*** - **std::map** sorted map alike type](docs/csmap_api.md) - [***csset*** - **std::set** sorted set alike type](docs/csset_api.md) - [***cstr*** - **std::string** alike type](docs/cstr_api.md) -- [***csubstr*** - **std::string_view** alike type](docs/csubstr_api.md) -- [***csview*** - null-terminated string view type](docs/csview_api.md) +- [***csview*** - **std::string_view** alike type](docs/csview_api.md) +- [***crawstr*** - null-terminated string view type](docs/crawstr_api.md) - [***cspan*** - **std::span** + **std::mdspan** alike type](docs/cspan_api.md) Algorithms @@ -352,11 +352,11 @@ linking, so *one* c-file must implement the templated container, e.g.: #include "cvec_int.h" ``` The non-templated string type **cstr** uses shared linking by default, but can have static linking instead by -`#define i_static`. Same for the string-view type **csubstr**, but most of its functions are static inlined, so +`#define i_static`. Same for the string-view type **csview**, but most of its functions are static inlined, so linking specifications and implementation are only needed for a few lesser used functions. Conveniently, `src\libstc.c` implements all the non-templated functions with shared linking for **cstr**, -**csubstr**, **cregex**, **utf8**, and **crand**. +**csview**, **cregex**, **utf8**, and **crand**. As a special case, you can `#define i_import` before including **cregex** or **cstr** to implement the dependent **utf8** functions (proper utf8 case conversions, etc.). Or link with src\libstc. @@ -402,8 +402,8 @@ Only functions required by the container type is required to be defined. E.g.: - *Type_clone()* is not used if *#define i_opt c_no_clone* is specified. - `i_key_str` - Sets `i_keyclass` = *cstr*, `i_tag` = *str*, and `i_keyraw` = *const char*\*. Defines both type convertion `i_keyfrom`, `i_keyto`, and sets `i_cmp`, `i_eq`, `i_hash` functions with *const char\*\** as argument. -- `i_key_ssv` - Sets `i_keyclass` = *cstr*, `i_tag` = *ssv*, and `i_keyraw` = *csubstr\**. Defines both type convertion -`i_keyfrom`, `i_keyto`, and sets `i_cmp`, `i_eq`, `i_hash` functions with *csubstr\** as argument. +- `i_key_ssv` - Sets `i_keyclass` = *cstr*, `i_tag` = *ssv*, and `i_keyraw` = *csview\**. Defines both type convertion +`i_keyfrom`, `i_keyto`, and sets `i_cmp`, `i_eq`, `i_hash` functions with *csview\** as argument. - `i_keyboxed` *Type* - Use when *Type* is a smart pointer **carc** or **cbox**. Defines *i_keyclass = Type*, and *i_keyraw = Type\**. NB: Do not use when defining carc/cbox types themselves. - `i_valclass` *Type*, `i_val_str`, `i_val_ssv`, `i_valboxed` - Similar rules as for ***key***. @@ -641,7 +641,7 @@ void maptest() STC is generally very memory efficient. Memory usage for the different containers: - **cstr**, **cvec**, **cstack**, **cpque**: 1 pointer, 2 intptr_t + memory for elements. -- **csubstr**, 1 pointer, 1 intptr_t. Does not own data! +- **csview**, 1 pointer, 1 intptr_t. Does not own data! - **cspan**, 1 pointer and 2 \* dimension \* int32_t. Does not own data! - **clist**: Type size: 1 pointer. Each node allocates a struct to store its value and a next pointer. - **cdeq**, **cqueue**: Type size: 2 pointers, 2 intptr_t. Otherwise like *cvec*. @@ -655,7 +655,7 @@ STC is generally very memory efficient. Memory usage for the different container ## Version 4.3 - Breaking changes: - - **cstr** and **csubstr** now uses *shared linking* by default. Implement by either defining `i_implement` or `i_static` before including. + - **cstr** and **csview** now uses *shared linking* by default. Implement by either defining `i_implement` or `i_static` before including. - Renamed => `` - Moved => `` - Much improved with some new API and added features. @@ -687,7 +687,7 @@ STC is generally very memory efficient. Memory usage for the different container - Renamed c_flt_count(i) => `c_flt_counter(i)` - Renamed c_flt_last(i) => `c_flt_getcount(i)` - Renamed c_ARRAYLEN() => c_arraylen() -- Removed deprecated c_ARGSV(). Use c_SS() +- Removed deprecated c_ARGSV(). Use c_SV() - Removed c_PAIR ## Version 4.1.1 @@ -700,7 +700,7 @@ Major changes: - [crange](docs/algorithm_api.md#crange) - similar to [boost::irange](https://www.boost.org/doc/libs/release/libs/range/doc/html/range/reference/ranges/irange.html) integer range generator. - [c_forfilter](docs/algorithm_api.md#c_forfilter) - ranges-like view filtering. - [csort](include/stc/algo/sort.h) - [fast quicksort](misc/benchmarks/various/csort_bench.c) with custom inline comparison. -- Renamed `c_ARGSV()` => `c_SS()`: **csubstr** print arg. Note `c_ss()` is shorthand for *csubstr_from()*. +- Renamed `c_ARGSV()` => `c_SV()`: **csview** print arg. Note `c_sv()` is shorthand for *csview_from()*. - Support for [uppercase flow-control](include/stc/priv/altnames.h) macro names in ccommon.h. - Some API changes in **cregex** and **cstr**. - Create single header container versions with python script. @@ -714,18 +714,18 @@ Major changes: - New + renamed loop iteration/scope macros: - `c_forlist`: macro replacing `c_forarray` and `c_apply`. Iterate a compound literal list. - `c_forrange`: macro replacing `c_forrange`. Iterate a `long long` type number sequence. -- Updated **cstr**, now always takes self as pointer, like all containers except csubstr. +- Updated **cstr**, now always takes self as pointer, like all containers except csview. - Updated **cvec**, **cdeq**, changed `*_range*` function names. ## Changes version 3.8 -- Overhauled some **cstr** and **csubstr** API: +- 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 `csubstr_*_u8()` => `csubstr_u8_*()` - - Added cstr_u8_slice() and csubstr_u8_slice(). - - Removed `csubstr_from_s()`: Use `cstr_ss(s)` instead. + - Renamed `csview_*_u8()` => `csview_u8_*()` + - Added cstr_u8_slice() and csview_u8_slice(). + - Removed `csview_from_s()`: Use `cstr_sv(s)` instead. - Added back file coption.h - Simplified **cbits** usage: all inlined. - Updated docs. @@ -760,7 +760,7 @@ Major changes: - Renamed: *cstr_new()* to `cstr_lit(literal)`, and *cstr_assign_fmt()* to `cstr_printf()`. - Renamed: *c_default_fromraw()* to `c_default_from()`. - Changed: the [**c_apply**](docs/algorithm_api.md) macros API. -- Replaced: *csubstr_first_token()* and *csubstr_next_token()* with one function: `csubstr_token()`. +- Replaced: *csview_first_token()* and *csview_next_token()* with one function: `csview_token()`. - Added: **checkauto** tool for checking that c-source files uses `c_auto*` macros correctly. - Added: general `i_keyclass` / `i_valclass` template parameters which auto-binds template functions. - Added: `i_opt` template parameter: compile-time options: `c_no_clone`, `c_no_atomic`, `c_is_forward`; may be combined with `|` diff --git a/docs/crawstr_api.md b/docs/crawstr_api.md new file mode 100644 index 00000000..d44c302d --- /dev/null +++ b/docs/crawstr_api.md @@ -0,0 +1,130 @@ +# STC [crawstr](../include/stc/crawstr.h): Null-terminated UTF8 String View +![String](pics/string.jpg) + +The type **crawstr** is a ***null-terminated*** string view and refers 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. See [csview](csview_api.md) for a ***non null-terminated*** +string view/span type. + +Because **crawstr** is null-terminated, it can be 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, i.e. no need to call *strlen()* for various operations. + +## Header file + +All crawstr definitions and prototypes are available by including a single header file. + +```c +#define i_implement +#include +#include +``` +## Methods + +```c +crawstr crawstr_from(const char* str); // construct from const char* +crawstr c_rs(const char literal_only[]); // construct from literal, no strlen() + +intptr_t crawstr_size(crawstr rs); +bool crawstr_empty(crawstr rs); // check if size == 0 +void crawstr_clear(crawstr* self); +csview crawstr_sv(crawstr rs); // convert to csview type + +bool crawstr_equals(crawstr rs, const char* str); +intptr_t crawstr_find(crawstr rs, const char* str); +bool crawstr_contains(crawstr rs, const char* str); +bool crawstr_starts_with(crawstr rs, const char* str); +bool crawstr_ends_with(crawstr rs, const char* str); +``` + +#### UTF8 methods +```c +intptr_t crawstr_u8_size(crawstr rs); +bool crawstr_valid_utf8(crawstr rs); // depends on src/utf8code.c + +crawstr_iter crawstr_begin(const crawstr* self); +crawstr_iter crawstr_end(const crawstr* self); +void crawstr_next(crawstr_iter* it); // utf8 codepoint step, not byte! +crawstr_iter crawstr_advance(crawstr_iter it, intptr_t n); + + // from utf8.h +intptr_t utf8_size(const char *s); +intptr_t utf8_size_n(const char *s, intptr_t nbytes); // number of UTF8 codepoints within n bytes +const char* utf8_at(const char *s, intptr_t index); // from UTF8 index to char* position +intptr_t utf8_pos(const char* s, intptr_t index); // from UTF8 index to byte index position +unsigned utf8_chr_size(const char* s); // UTF8 character size: 1-4 + // implemented in src/utf8code.c: +bool utf8_valid(const char* s); +bool utf8_valid_n(const char* s, intptr_t nbytes); +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); // codepoint value of character at s +uint32_t utf8_peek_off(const char* s, int offset); // codepoint value at utf8 pos (may be negative) +``` + +#### Helper methods +```c +int crawstr_cmp(const crawstr* x, const crawstr* y); +int crawstr_icmp(const crawstr* x, const crawstr* y); // depends on src/utf8code.c: +bool crawstr_eq(const crawstr* x, const crawstr* y); +uint64_t crawstr_hash(const crawstr* x); +``` + +## Types + +| Type name | Type definition | Used to represent... | +|:----------------|:-------------------------------------------|:-------------------------| +| `crawstr` | `struct { const char *str; intptr_t size; }` | The string view type | +| `crawstr_value` | `char` | The string element type | +| `crawstr_iter` | `struct { crawstr_value *ref; }` | UTF8 iterator | + +## Example: UTF8 iteration and case conversion +```c +#define i_import +#include +#include + +int main(void) +{ + cstr str = cstr_from("Liberté, égalité, fraternité."); + crawstr rs = cstr_rs(&str); + + c_foreach (i, crawstr, rs) + printf("%.*s ", c_SV(i.u8.chr)); + puts(""); + + cstr_uppercase(&str); + printf("%s\n", cstr_str(&str)); + + cstr_drop(&str); +} +``` +Output: +``` +L i b e r t é , é g a l i t é , f r a t e r n i t é . +LIBERTÉ, ÉGALITÉ, FRATERNITÉ. +``` + +### Example 2: UTF8 replace +```c +#define i_import // include dependent utf8 definitions. +#include + +int main(void) +{ + cstr s1 = cstr_lit("hell😀 w😀rld"); + + cstr_u8_replace_at(&s1, cstr_find(&s1, "😀rld"), 1, c_rs("ø")); + printf("%s\n", cstr_str(&s1)); + + c_foreach (i, cstr, s1) + printf("%.*s,", c_SV(i.u8.chr)); // u8.chr is a csview + + cstr_drop(&s1); +} +``` +Output: +``` +hell😀 wørld +h,e,l,l,😀, ,w,ø,r,l,d, +``` diff --git a/docs/cregex_api.md b/docs/cregex_api.md index 98161fe9..52476e09 100644 --- a/docs/cregex_api.md +++ b/docs/cregex_api.md @@ -33,11 +33,11 @@ int cregex_compile(cregex *self, const char* pattern, int cflags = CREG_ int cregex_captures(const cregex* self); // return CREG_OK, CREG_NOMATCH, or CREG_MATCHERROR -int cregex_find(const cregex* re, const char* input, csubstr match[], int mflags = CREG_DEFAULT); +int cregex_find(const cregex* re, const char* input, csview match[], int mflags = CREG_DEFAULT); // Search inside input string-view only -int cregex_find_ss(const cregex* re, csubstr input, csubstr match[]); +int cregex_find_sv(const cregex* re, csview input, csview match[]); // All-in-one search (compile + find + drop) -int cregex_find_pattern(const char* pattern, const char* input, csubstr match[], int cmflags = CREG_DEFAULT); +int cregex_find_pattern(const char* pattern, const char* input, csview match[], int cmflags = CREG_DEFAULT); // Check if there are matches in input bool cregex_is_match(const cregex* re, const char* input); @@ -45,14 +45,14 @@ bool cregex_is_match(const cregex* re, const char* input); // Replace all matches in input cstr cregex_replace(const cregex* re, const char* input, const char* replace, int count = INT_MAX); // Replace count matches in input string-view. Optionally transform replacement. -cstr cregex_replace_ss(const cregex* re, csubstr input, const char* replace, int count = INT_MAX); -cstr cregex_replace_ss(const cregex* re, csubstr input, const char* replace, int count, - bool(*transform)(int group, csubstr match, cstr* result), int rflags); +cstr cregex_replace_sv(const cregex* re, csview input, const char* replace, int count = INT_MAX); +cstr cregex_replace_sv(const cregex* re, csview input, const char* replace, int count, + bool(*transform)(int group, csview match, cstr* result), int rflags); // All-in-one replacement (compile + find/replace + drop) cstr cregex_replace_pattern(const char* pattern, const char* input, const char* replace, int count = INT_MAX); cstr cregex_replace_pattern(const char* pattern, const char* input, const char* replace, int count, - bool(*transform)(int group, csubstr match, cstr* result), int rflags); + bool(*transform)(int group, csview match, cstr* result), int rflags); // destroy void cregex_drop(cregex* self); ``` @@ -109,9 +109,9 @@ int main(void) { cregex re = cregex_from(pattern); // Lets find the first date in the string: - csubstr match[4]; // full-match, year, month, date. + csview match[4]; // full-match, year, month, date. if (cregex_find(&re, input, match) == CREG_OK) - printf("Found date: %.*s\n", c_SS(match[0])); + printf("Found date: %.*s\n", c_SV(match[0])); else printf("Could not find any date\n"); @@ -127,7 +127,7 @@ int main(void) { For a single match you may use the all-in-one function: ```c if (cregex_find_pattern(pattern, input, match)) - printf("Found date: %.*s\n", c_SS(match[0])); + printf("Found date: %.*s\n", c_SV(match[0])); ``` To use: `gcc first_match.c src/cregex.c src/utf8code.c`. @@ -137,16 +137,16 @@ In order to use a callback function in the replace call, see `examples/regex_rep To iterate multiple matches in an input string, you may use ```c -csubstr match[5] = {0}; +csview match[5] = {0}; while (cregex_find(&re, input, match, CREG_NEXT) == CREG_OK) for (int k = 1; i <= cregex_captures(&re); ++k) - printf("submatch %d: %.*s\n", k, c_SS(match[k])); + printf("submatch %d: %.*s\n", k, c_SV(match[k])); ``` There is also a for-loop macro to simplify it: ```c c_formatch (it, &re, input) for (int k = 1; i <= cregex_captures(&re); ++k) - printf("submatch %d: %.*s\n", k, c_SS(it.match[k])); + printf("submatch %d: %.*s\n", k, c_SV(it.match[k])); ``` ## Using cregex in a project @@ -154,7 +154,7 @@ c_formatch (it, &re, input) The easiest is to `#define i_import` before `#include `. Make sure to do that in one translation unit only. For reference, **cregex** uses the following files: -- `stc/cregex.h`, `stc/utf8.h`, `stc/csubstr.h`, `stc/cstr.h`, `stc/ccommon.h`, `stc/forward.h` +- `stc/cregex.h`, `stc/utf8.h`, `stc/csview.h`, `stc/cstr.h`, `stc/ccommon.h`, `stc/forward.h` - `src/cregex.c`, `src/utf8code.c`. ## Regex Cheatsheet diff --git a/docs/cstr_api.md b/docs/cstr_api.md index 07b9b4c8..1da57b0c 100644 --- a/docs/cstr_api.md +++ b/docs/cstr_api.md @@ -22,8 +22,8 @@ cstr cstr_init(void); // construct cstr cstr_lit(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, intptr_t n); // constructor with n first bytes of str -cstr cstr_from_sv(csview sv); // construct cstr from csview -cstr cstr_from_ss(csubstr ss); // construct cstr from csubstr +cstr cstr_from_sv(csview ss); // construct cstr from csview +cstr cstr_from_rs(crawstr rs); // construct cstr from crawstr cstr cstr_with_capacity(intptr_t cap); cstr cstr_with_size(intptr_t len, char fill); // repeat fill len times cstr cstr_from_fmt(const char* fmt, ...); // printf() formatting @@ -35,7 +35,7 @@ void cstr_drop(cstr* self); // destructo const char* cstr_str(const cstr* self); // to const char* csview cstr_sv(const cstr* self); // to csview -csubstr cstr_ss(const cstr* self); // to csubstr +crawstr cstr_rs(const cstr* self); // to crawstr char* cstr_data(cstr* self); // to mutable char* cstr_buf cstr_buffer(cstr* self); // to mutable buffer (with capacity) @@ -50,13 +50,13 @@ void cstr_clear(cstr* self); char* cstr_assign(cstr* self, const char* str); char* cstr_assign_n(cstr* self, const char* str, intptr_t n); // assign n first bytes of str -char* cstr_assign_ss(cstr* self, csubstr ss); +char* cstr_assign_sv(cstr* self, csview ss); 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* str); char* cstr_append_n(cstr* self, const char* str, intptr_t n); // append n first bytes of str -char* cstr_append_ss(cstr* self, csubstr str); +char* cstr_append_sv(cstr* self, csview str); char* cstr_append_s(cstr* self, cstr str); int cstr_append_fmt(cstr* self, const char* fmt, ...); // printf() formatting char* cstr_append_uninit(cstr* self, intptr_t len); // return ptr to start of uninited data @@ -65,19 +65,19 @@ void cstr_push(cstr* self, const char* chr); // append on void cstr_pop(cstr* self); // pop one utf8 char void cstr_insert(cstr* self, intptr_t pos, const char* ins); -void cstr_insert_ss(cstr* self, intptr_t pos, csubstr ins); +void cstr_insert_sv(cstr* self, intptr_t pos, csview ins); void cstr_insert_s(cstr* self, intptr_t pos, cstr ins); void cstr_erase(cstr* self, intptr_t pos, intptr_t len); // erase len bytes from pos void cstr_replace(cstr* self, const char* search, const char* repl, unsigned count = MAX_INT); -cstr cstr_replace_ss(csubstr in, csubstr search, csubstr repl, unsigned count); +cstr cstr_replace_sv(csview in, csview search, csview repl, unsigned count); void cstr_replace_at(cstr* self, intptr_t pos, intptr_t len, const char* repl); // replace at a pos -void cstr_replace_at_ss(cstr* self, intptr_t pos, intptr_t len, const csubstr repl); +void cstr_replace_at_sv(cstr* self, intptr_t pos, intptr_t len, const csview repl); void cstr_replace_at_s(cstr* self, intptr_t pos, intptr_t len, cstr repl); bool cstr_equals(const cstr* self, const char* str); -bool cstr_equals_ss(const cstr* self, csubstr ss); +bool cstr_equals_sv(const cstr* self, csview ss); bool cstr_equals_s(const cstr* self, cstr s); intptr_t cstr_find(const cstr* self, const char* search); @@ -85,11 +85,11 @@ intptr_t cstr_find_at(const cstr* self, intptr_t pos, const char* search); // bool cstr_contains(const cstr* self, const char* search); bool cstr_starts_with(const cstr* self, const char* str); -bool cstr_starts_with_ss(const cstr* self, csubstr ss); +bool cstr_starts_with_sv(const cstr* self, csview ss); bool cstr_starts_with_s(const cstr* self, cstr s); bool cstr_ends_with(const cstr* self, const char* str); -bool cstr_ends_with_ss(const cstr* self, csubstr ss); +bool cstr_ends_with_sv(const cstr* self, csview ss); bool cstr_ends_with_s(const cstr* self, cstr s); bool cstr_getline(cstr *self, FILE *stream); // cstr_getdelim(self, '\n', stream) @@ -102,8 +102,8 @@ intptr_t cstr_u8_size(const cstr* self); // number of intptr_t cstr_u8_size_n(const cstr self, intptr_t nbytes); // utf8 size within n bytes intptr_t cstr_u8_to_pos(const cstr* self, intptr_t u8idx); // byte pos offset at utf8 codepoint index const char* cstr_u8_at(const cstr* self, intptr_t u8idx); // char* position at utf8 codepoint index -csubstr cstr_u8_chr(const cstr* self, intptr_t u8idx); // get utf8 character as a csubstr -void cstr_u8_replace_at(cstr* self, intptr_t bytepos, intptr_t u8len, csubstr repl); // replace u8len utf8 chars +csview cstr_u8_chr(const cstr* self, intptr_t u8idx); // get utf8 character as a csview +void cstr_u8_replace_at(cstr* self, intptr_t bytepos, intptr_t u8len, csview repl); // replace u8len utf8 chars void cstr_u8_erase(cstr* self, intptr_t bytepos, intptr_t u8len); // erase u8len codepoints from pos // iterate utf8 codepoints @@ -114,14 +114,14 @@ cstr_iter cstr_advance(cstr_iter it, intptr_t n); // utf8 functions requires linking with src/utf8code.c symbols: bool cstr_valid_utf8(const cstr* self); // check if str is valid utf8 -cstr cstr_casefold_ss(csubstr ss); // returns new casefolded utf8 cstr +cstr cstr_casefold_sv(csview ss); // returns new casefolded utf8 cstr cstr cstr_tolower(const char* str); // returns new lowercase utf8 cstr -cstr cstr_tolower_ss(csubstr ss); // returns new lowercase utf8 cstr +cstr cstr_tolower_sv(csview ss); // returns new lowercase utf8 cstr void cstr_lowercase(cstr* self); // transform cstr to lowercase utf8 cstr cstr_toupper(const char* str); // returns new uppercase utf8 cstr -cstr cstr_toupper_ss(csubstr ss); // returns new uppercase utf8 cstr +cstr cstr_toupper_sv(csview ss); // returns new uppercase utf8 cstr void cstr_uppercase(cstr* self); // transform cstr to uppercase utf8 int cstr_icmp(const cstr* s1, const cstr* s2); // utf8 case-insensitive comparison @@ -146,7 +146,7 @@ char* cstrnstrn(const char* str, const char* search, intptr_t slen, intptr |:----------------|:---------------------------------------------|:---------------------| | `cstr` | `struct { ... }` | The string type | | `cstr_value` | `char` | String element type | -| `csubstr` | `struct { const char *str; intptr_t size; }` | String view type | +| `csview` | `struct { const char *str; intptr_t size; }` | String view type | | `cstr_buf` | `struct { char *data; intptr_t size, cap; }` | String buffer type | ## Constants and macros diff --git a/docs/csubstr_api.md b/docs/csubstr_api.md deleted file mode 100644 index 7094cf82..00000000 --- a/docs/csubstr_api.md +++ /dev/null @@ -1,221 +0,0 @@ -# STC [csubstr](../include/stc/csubstr.h): Sub-string View -![String](pics/string.jpg) - -The type **csubstr** is a non-null terminated 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. - -Because **csubstr** is non-null terminated, it is not a replacent view for `const char*` - see [csview](csview_api.md) -for that. **csubstr** 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 need to call *strlen()* to acquire -the length. - -- **csubstr** iterators works on UTF8 codepoints - like **cstr** and **csview** (see Example 2). -- Because it is null-terminated, it must be printed the following way: -```c -printf("%.*s", c_SS(sstr)); -``` - -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 csubstr definitions and prototypes are available by including a single header file. - -```c -#define i_implement -#include -#include // after cstr.h: include extra cstr-csubstr functions -``` -## Methods - -```c -csubstr c_ss(const char literal_only[]); // construct from literal, no strlen() -csubstr c_ss(const char* str, intptr_t n); // construct from str and length n -csubstr csubstr_from(const char* str); // construct from const char* -csubstr csubstr_from_n(const char* str, intptr_t n); // alias for c_ss(str, n) - -intptr_t csubstr_size(csubstr ss); -bool csubstr_empty(csubstr ss); -void csubstr_clear(csubstr* self); - -bool csubstr_equals(csubstr ss, const char* str); -intptr_t csubstr_equals_ss(csubstr ss, csubstr find); -intptr_t csubstr_find(csubstr ss, const char* str); -intptr_t csubstr_find_ss(csubstr ss, csubstr find); -bool csubstr_contains(csubstr ss, const char* str); -bool csubstr_starts_with(csubstr ss, const char* str); -bool csubstr_ends_with(csubstr ss, const char* str); -csubstr csubstr_substr(csubstr ss, intptr_t pos, intptr_t n); -csubstr csubstr_slice(csubstr ss, intptr_t pos1, intptr_t pos2); - -csubstr csubstr_substr_ex(csubstr ss, intptr_t pos, intptr_t n); // negative pos count from end -csubstr csubstr_slice_ex(csubstr ss, intptr_t pos1, intptr_t pos2); // negative pos1, pos2 count from end -csubstr csubstr_token(csubstr ss, const char* sep, intptr_t* start); // *start > ss.size after last token -``` - -#### UTF8 methods -```c -intptr_t csubstr_u8_size(csubstr ss); -csubstr csubstr_u8_substr(csubstr ss, intptr_t bytepos, intptr_t u8len); -bool csubstr_valid_utf8(csubstr ss); // requires linking with src/utf8code.c - -csubstr_iter csubstr_begin(const csubstr* self); -csubstr_iter csubstr_end(const csubstr* self); -void csubstr_next(csubstr_iter* it); // utf8 codepoint step, not byte! -csubstr_iter csubstr_advance(csubstr_iter it, intptr_t n); -``` - -#### cstr methods returning csubstr -```c -csubstr cstr_slice(const cstr* self, intptr_t pos1, intptr_t pos2); -csubstr cstr_slice_ex(const cstr* self, intptr_t pos1, intptr_t pos2); // see csubstr_slice_ex() -csubstr cstr_substr(const cstr* self, intptr_t pos, intptr_t n); -csubstr cstr_substr_ex(const cstr* self, intptr_t pos, intptr_t n); // see csubstr_substr_ex() -csubstr cstr_u8_substr(const cstr* self, intptr_t bytepos, intptr_t u8len); -``` -#### Iterate tokens with *c_fortoken*, *c_fortoken_ss* - -To iterate tokens in an input string separated by a string: -```c -c_fortoken (i, "hello, one, two, three", ", ") - printf("token: %.*s\n", c_SS(i.token)); -``` - -#### Helper methods -```c -int csubstr_cmp(const csubstr* x, const csubstr* y); -int csubstr_icmp(const csubstr* x, const csubstr* y); -bool csubstr_eq(const csubstr* x, const csubstr* y); -uint64_t csubstr_hash(const csubstr* x); -``` - -## Types - -| Type name | Type definition | Used to represent... | -|:----------------|:-------------------------------------------|:-------------------------| -| `csubstr` | `struct { const char *str; intptr_t size; }` | The string view type | -| `csubstr_value` | `char` | The string element type | -| `csubstr_iter` | `struct { csubstr_value *ref; }` | UTF8 iterator | - -## Constants and macros - -| Name | Value | Usage | -|:---------------|:---------------------|:---------------------------------------------| -| `c_SS(ss)` | printf argument | `printf("ss: %.*s\n", c_SS(ss));` | - -## Example -```c -#define i_implement -#include -#include - -int main(void) -{ - cstr str1 = cstr_from("We think in generalities, but we live in details."); - // (quoting Alfred N. Whitehead) - - csubstr ss1 = cstr_substr_ex(&str1, 3, 5); // "think" - intptr_t pos = cstr_find(&str1, "live"); // position of "live" in str1 - csubstr ss2 = cstr_substr_ex(&str1, pos, 4); // get "live" - csubstr ss3 = cstr_slice_ex(&str1, -8, -1); // get "details" - printf("%.*s %.*s %.*s\n", - c_SS(ss1), c_SS(ss2), c_SS(ss3)); - cstr s1 = cstr_lit("Apples are red"); - cstr s2 = cstr_from_ss(cstr_substr_ex(&s1, -3, 3)); // "red" - cstr s3 = cstr_from_ss(cstr_substr_ex(&s1, 0, 6)); // "Apples" - printf("%s %s\n", cstr_str(&s2), cstr_str(&s3)); - - c_drop(cstr, &str1, &s1, &s2, &s3); -} -``` -Output: -``` -think live details -red Apples -``` - -### Example 2: UTF8 handling -```c -#define i_import // include dependent cstr, utf8 and cregex function definitions. -#include - -int main(void) -{ - cstr s1 = cstr_lit("hell😀 w😀rld"); - - cstr_u8_replace_at(&s1, cstr_find(&s1, "😀rld"), 1, c_ss("ø")); - printf("%s\n", cstr_str(&s1)); - - c_foreach (i, cstr, s1) - printf("%.*s,", c_SS(i.u8.chr)); - - cstr_drop(&s1); -} -``` -Output: -``` -hell😀 wørld -h,e,l,l,😀, ,w,ø,r,l,d, -``` - -### Example 3: csubstr tokenizer (string split) -Splits strings into tokens. *print_split()* makes **no** memory allocations or *strlen()* calls, -and does not depend on null-terminated strings. *string_split()* function returns a vector of cstr. -```c -#include -#include - -void print_split(csubstr input, const char* sep) -{ - c_fortoken_ss (i, input, sep) - printf("[%.*s]\n", c_SS(i.token)); - puts(""); -} -#define i_implement -#include -#define i_key_str -#include - -cstack_str string_split(csubstr input, const char* sep) -{ - cstack_str out = cstack_str_init(); - - c_fortoken_ss (i, input, sep) - cstack_str_push(&out, cstr_from_ss(i.token)); - - return out; -} - -int main(void) -{ - print_split(c_ss("//This is a//double-slash//separated//string"), "//"); - print_split(c_ss("This has no matching separator"), "xx"); - - cstack_str s = string_split(c_ss("Split,this,,string,now,"), ","); - - c_foreach (i, cstack_str, s) - printf("[%s]\n", cstr_str(i.ref)); - puts(""); - - cstack_str_drop(&s); -} -``` -Output: -``` -[] -[This is a] -[double-slash] -[separated] -[string] - -[This has no matching separator] - -[Split] -[this] -[] -[string] -[now] -[] -``` diff --git a/docs/csview_api.md b/docs/csview_api.md index d28e3ed2..eafc6854 100644 --- a/docs/csview_api.md +++ b/docs/csview_api.md @@ -1,14 +1,23 @@ -# STC [csview](../include/stc/csview.h): Null-terminated UTF8 String View +# STC [csview](../include/stc/csview.h): Sub-string View ![String](pics/string.jpg) -The type **csview** is a ***null-terminated*** string view and refers 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. See [csubstr](csubstr_api.md) for a ***non null-terminated*** -string view/span type. +The type **csview** is a non-null terminated 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. -Because **csview** is null-terminated, it can be 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, i.e. no need to call *strlen()* for various operations. +Because **csview** is non-null terminated, it is not an ideal replacent view for `const char*` - see [crawstr](crawstr_api.md) +for that. **csview** 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 need to call *strlen()* to acquire +the length. + +- **csview** iterators works on UTF8 codepoints - like **cstr** and **crawstr** (see Example 2). +- Because it is null-terminated, it must be printed the following way: +```c +printf("%.*s", c_SV(sstr)); +``` + +See the c++ class [std::basic_string_view](https://en.cppreference.com/w/cpp/string/basic_string_view) for a functional +description. ## Header file @@ -22,52 +31,64 @@ All csview definitions and prototypes are available by including a single header ## Methods ```c -csview c_sv(const char literal_only[]); // construct from literal, no strlen() -csview csview_from(const char* str); // construct from const char* +csview c_sv(const char literal_only[]); // construct from literal, no strlen() +csview c_sv(const char* str, intptr_t n); // construct from str and length n +csview csview_from(const char* str); // construct from const char* +csview csview_from_n(const char* str, intptr_t n); // alias for c_sv(str, n) + +intptr_t csview_size(csview sv); +bool csview_empty(csview sv); +void csview_clear(csview* self); + +bool csview_equals(csview sv, const char* str); +intptr_t csview_equals_sv(csview sv, csview find); +intptr_t csview_find(csview sv, const char* str); +intptr_t csview_find_sv(csview sv, csview find); +bool csview_contains(csview sv, const char* str); +bool csview_starts_with(csview sv, const char* str); +bool csview_ends_with(csview sv, const char* str); +csview csview_substr(csview sv, intptr_t pos, intptr_t n); +csview csview_slice(csview sv, intptr_t pos1, intptr_t pos2); + +csview csview_substr_ex(csview sv, intptr_t pos, intptr_t n); // negative pos count from end +csview csview_slice_ex(csview sv, intptr_t pos1, intptr_t pos2); // negative pos1, pos2 count from end +csview csview_token(csview sv, const char* sep, intptr_t* start); // *start > sv.size after last token +``` -intptr_t csview_size(csview sv); -bool csview_empty(csview sv); // check if size == 0 -void csview_clear(csview* self); -csubstr csview_ss(csview sv); // convert to csubstr type +#### UTF8 methods +```c +intptr_t csview_u8_size(csview sv); +csview csview_u8_substr(csview sv, intptr_t bytepos, intptr_t u8len); +bool csview_valid_utf8(csview sv); // requires linking with src/utf8code.c + +csview_iter csview_begin(const csview* self); +csview_iter csview_end(const csview* self); +void csview_next(csview_iter* it); // utf8 codepoint step, not byte! +csview_iter csview_advance(csview_iter it, intptr_t n); +``` -bool csview_equals(csview sv, const char* str); -intptr_t csview_find(csview sv, const char* str); -bool csview_contains(csview sv, const char* str); -bool csview_starts_with(csview sv, const char* str); -bool csview_ends_with(csview sv, const char* str); +#### cstr methods returning csview +```c +csview cstr_slice(const cstr* self, intptr_t pos1, intptr_t pos2); +csview cstr_slice_ex(const cstr* self, intptr_t pos1, intptr_t pos2); // see csview_slice_ex() +csview cstr_substr(const cstr* self, intptr_t pos, intptr_t n); +csview cstr_substr_ex(const cstr* self, intptr_t pos, intptr_t n); // see csview_substr_ex() +csview cstr_u8_substr(const cstr* self, intptr_t bytepos, intptr_t u8len); ``` +#### Iterate tokens with *c_fortoken*, *c_fortoken_sv* -#### UTF8 methods +To iterate tokens in an input string separated by a string: ```c -intptr_t csview_u8_size(csview sv); -bool csview_valid_utf8(csview sv); // depends on src/utf8code.c - -csview_iter csview_begin(const csview* self); -csview_iter csview_end(const csview* self); -void csview_next(csview_iter* it); // utf8 codepoint step, not byte! -csview_iter csview_advance(csview_iter it, intptr_t n); - - // from utf8.h -intptr_t utf8_size(const char *s); -intptr_t utf8_size_n(const char *s, intptr_t nbytes); // number of UTF8 codepoints within n bytes -const char* utf8_at(const char *s, intptr_t index); // from UTF8 index to char* position -intptr_t utf8_pos(const char* s, intptr_t index); // from UTF8 index to byte index position -unsigned utf8_chr_size(const char* s); // UTF8 character size: 1-4 - // implemented in src/utf8code.c: -bool utf8_valid(const char* s); -bool utf8_valid_n(const char* s, intptr_t nbytes); -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); // codepoint value of character at s -uint32_t utf8_peek_off(const char* s, int offset); // codepoint value at utf8 pos (may be negative) +c_fortoken (i, "hello, one, two, three", ", ") + printf("token: %.*s\n", c_SV(i.token)); ``` #### Helper methods ```c -int csview_cmp(const csview* x, const csview* y); -int csview_icmp(const csview* x, const csview* y); // depends on src/utf8code.c: -bool csview_eq(const csview* x, const csview* y); -uint64_t csview_hash(const csview* x); +int csview_cmp(const csview* x, const csview* y); +int csview_icmp(const csview* x, const csview* y); +bool csview_eq(const csview* x, const csview* y); +uint64_t csview_hash(const csview* x); ``` ## Types @@ -78,36 +99,46 @@ uint64_t csview_hash(const csview* x); | `csview_value` | `char` | The string element type | | `csview_iter` | `struct { csview_value *ref; }` | UTF8 iterator | -## Example: UTF8 iteration and case conversion +## Constants and macros + +| Name | Value | Usage | +|:---------------|:---------------------|:---------------------------------------------| +| `c_SV(sv)` | printf argument | `printf("sv: %.*s\n", c_SV(sv));` | + +## Example ```c -#define i_import +#define i_implement #include #include int main(void) { - cstr str = cstr_from("Liberté, égalité, fraternité."); - csview sv = cstr_sv(&str); - - c_foreach (i, csview, sv) - printf("%.*s ", c_SS(i.u8.chr)); - puts(""); - - cstr_uppercase(&str); - printf("%s\n", cstr_str(&str)); - - cstr_drop(&str); + cstr str1 = cstr_from("We think in generalities, but we live in details."); + // (quoting Alfred N. Whitehead) + + csview ss1 = cstr_substr_ex(&str1, 3, 5); // "think" + intptr_t pos = cstr_find(&str1, "live"); // position of "live" in str1 + csview ss2 = cstr_substr_ex(&str1, pos, 4); // get "live" + csview ss3 = cstr_slice_ex(&str1, -8, -1); // get "details" + printf("%.*s %.*s %.*s\n", + c_SV(ss1), c_SV(ss2), c_SV(ss3)); + cstr s1 = cstr_lit("Apples are red"); + cstr s2 = cstr_from_sv(cstr_substr_ex(&s1, -3, 3)); // "red" + cstr s3 = cstr_from_sv(cstr_substr_ex(&s1, 0, 6)); // "Apples" + printf("%s %s\n", cstr_str(&s2), cstr_str(&s3)); + + c_drop(cstr, &str1, &s1, &s2, &s3); } ``` Output: ``` -L i b e r t é , é g a l i t é , f r a t e r n i t é . -LIBERTÉ, ÉGALITÉ, FRATERNITÉ. +think live details +red Apples ``` -### Example 2: UTF8 replace +### Example 2: UTF8 handling ```c -#define i_import // include dependent utf8 definitions. +#define i_import // include dependent cstr, utf8 and cregex function definitions. #include int main(void) @@ -118,7 +149,7 @@ int main(void) printf("%s\n", cstr_str(&s1)); c_foreach (i, cstr, s1) - printf("%.*s,", c_SS(i.u8.chr)); // u8.chr is a csubstr + printf("%.*s,", c_SV(i.u8.chr)); cstr_drop(&s1); } @@ -128,3 +159,63 @@ Output: hell😀 wørld h,e,l,l,😀, ,w,ø,r,l,d, ``` + +### Example 3: csview tokenizer (string split) +Splits strings into tokens. *print_split()* makes **no** memory allocations or *strlen()* calls, +and does not depend on null-terminated strings. *string_split()* function returns a vector of cstr. +```c +#include +#include + +void print_split(csview input, const char* sep) +{ + c_fortoken_sv (i, input, sep) + printf("[%.*s]\n", c_SV(i.token)); + puts(""); +} +#define i_implement +#include +#define i_key_str +#include + +cstack_str string_split(csview input, const char* sep) +{ + cstack_str out = cstack_str_init(); + + c_fortoken_sv (i, input, sep) + cstack_str_push(&out, cstr_from_sv(i.token)); + + return out; +} + +int main(void) +{ + print_split(c_sv("//This is a//double-slash//separated//string"), "//"); + print_split(c_sv("This has no matching separator"), "xx"); + + cstack_str s = string_split(c_sv("Split,this,,string,now,"), ","); + + c_foreach (i, cstack_str, s) + printf("[%s]\n", cstr_str(i.ref)); + puts(""); + + cstack_str_drop(&s); +} +``` +Output: +``` +[] +[This is a] +[double-slash] +[separated] +[string] + +[This has no matching separator] + +[Split] +[this] +[] +[string] +[now] +[] +``` diff --git a/include/stc/ccommon.h b/include/stc/ccommon.h index 1b4a2277..e5422adc 100644 --- a/include/stc/ccommon.h +++ b/include/stc/ccommon.h @@ -130,14 +130,13 @@ typedef const char* ccharptr; #define ccharptr_clone(s) (s) #define ccharptr_drop(p) ((void)p) -#define c_ss(...) c_MACRO_OVERLOAD(c_ss, __VA_ARGS__) -#define c_ss_1(literal) c_ss_2(literal, c_litstrlen(literal)) -#define c_ss_2(str, n) (c_LITERAL(csubstr){str, n}) -#define c_SS(ss) (int)(ss).size, (ss).str // printf("%.*s\n", c_SS(ss)); - -#define c_sv(literal) c_sv_2(literal, c_litstrlen(literal)) +#define c_sv(...) c_MACRO_OVERLOAD(c_sv, __VA_ARGS__) +#define c_sv_1(literal) c_sv_2(literal, c_litstrlen(literal)) #define c_sv_2(str, n) (c_LITERAL(csview){str, n}) -#define c_SV(sv) c_SS(sv) // [deprecated] - unneeded +#define c_SV(ss) (int)(ss).size, (ss).str // printf("%.*s\n", c_SV(ss)); + +#define c_rs(literal) c_rs_2(literal, c_litstrlen(literal)) +#define c_rs_2(str, n) (c_LITERAL(crawstr){str, n}) #define c_ROTL(x, k) (x << (k) | x >> (8*sizeof(x) - (k))) diff --git a/include/stc/crawstr.h b/include/stc/crawstr.h new file mode 100644 index 00000000..7cf62e94 --- /dev/null +++ b/include/stc/crawstr.h @@ -0,0 +1,116 @@ +/* MIT License + * + * Copyright (c) 2023 Tyge Løvset + * + * 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. + */ +#define _i_inc_utf8 +#include "utf8.h" + +#ifndef CRAWSTR_H_INCLUDED +#define CRAWSTR_H_INCLUDED + +#define crawstr_init() c_rs("") +#define crawstr_drop(p) c_default_drop(p) +#define crawstr_clone(rs) c_default_clone(rs) + +STC_INLINE crawstr crawstr_from(const char* str) + { return c_rs_2(str, c_strlen(str)); } +STC_INLINE void crawstr_clear(crawstr* self) { *self = crawstr_init(); } +STC_INLINE csview crawstr_sv(crawstr rs) { return c_sv_2(rs.str, rs.size); } + +STC_INLINE intptr_t crawstr_size(crawstr rs) { return rs.size; } +STC_INLINE bool crawstr_empty(crawstr rs) { return rs.size == 0; } + +STC_INLINE bool crawstr_equals(crawstr rs, const char* str) { + intptr_t n = c_strlen(str); + return rs.size == n && !c_memcmp(rs.str, str, n); +} + +STC_INLINE intptr_t crawstr_find(crawstr rs, const char* search) { + char* res = cstrnstrn(rs.str, search, rs.size, c_strlen(search)); + return res ? (res - rs.str) : c_NPOS; +} + +STC_INLINE bool crawstr_contains(crawstr rs, const char* str) + { return crawstr_find(rs, str) != c_NPOS; } + +STC_INLINE bool crawstr_starts_with(crawstr rs, const char* str) { + intptr_t n = c_strlen(str); + return n > rs.size ? false : !c_memcmp(rs.str, str, n); +} + +STC_INLINE bool crawstr_ends_with(crawstr rs, const char* str) { + intptr_t n = c_strlen(str); + return n > rs.size ? false : !c_memcmp(rs.str + rs.size - n, str, n); +} + +/* utf8 iterator */ +STC_INLINE crawstr_iter crawstr_begin(const crawstr* self) { + if (!self->size) return c_LITERAL(crawstr_iter){.ref = NULL}; + return c_LITERAL(crawstr_iter){.u8 = {{self->str, utf8_chr_size(self->str)}}}; +} +STC_INLINE crawstr_iter crawstr_end(const crawstr* self) { + (void)self; return c_LITERAL(crawstr_iter){.ref = NULL}; +} +STC_INLINE void crawstr_next(crawstr_iter* it) { + it->ref += it->u8.chr.size; + it->u8.chr.size = utf8_chr_size(it->ref); + if (!*it->ref) it->ref = NULL; +} +STC_INLINE crawstr_iter crawstr_advance(crawstr_iter it, intptr_t pos) { + int inc = -1; + if (pos > 0) pos = -pos, inc = 1; + while (pos && *it.ref) pos += (*(it.ref += inc) & 0xC0) != 0x80; + it.u8.chr.size = utf8_chr_size(it.ref); + if (!*it.ref) it.ref = NULL; + return it; +} + +/* utf8 size */ +STC_INLINE intptr_t crawstr_u8_size(crawstr rs) + { return utf8_size_n(rs.str, rs.size); } + +/* utf8 validation: depends on src/utf8code.c */ +STC_INLINE bool crawstr_valid_utf8(crawstr rs) + { return utf8_valid_n(rs.str, rs.size); } + +/* utf8 ignore case cmp: depends on src/utf8code.c */ +STC_INLINE int crawstr_icmp(const crawstr* x, const crawstr* y) + { return utf8_icmp_sv(c_sv_2(x->str, x->size), c_sv_2(y->str, y->size)); } + + +STC_INLINE int crawstr_cmp(const crawstr* x, const crawstr* y) { + intptr_t n = x->size < y->size ? x->size : y->size; + int c = c_memcmp(x->str, y->str, n); + return c ? c : (int)(x->size - y->size); +} + +STC_INLINE bool crawstr_eq(const crawstr* x, const crawstr* y) + { return x->size == y->size && !c_memcmp(x->str, y->str, x->size); } + +STC_INLINE uint64_t crawstr_hash(const crawstr *self) + { return cfasthash(self->str, self->size); } + +#endif // CRAWSTR_H_INCLUDED +#undef i_static +#undef i_header +#undef i_implement +#undef i_import +#undef i_opt diff --git a/include/stc/cregex.h b/include/stc/cregex.h index 3aab3c8b..bce94b04 100644 --- a/include/stc/cregex.h +++ b/include/stc/cregex.h @@ -34,7 +34,7 @@ THE SOFTWARE. */ #include #include -#include "forward.h" // csubstr +#include "forward.h" // csview #include "ccommon.h" enum { @@ -82,7 +82,7 @@ typedef struct { typedef struct { const cregex* re; const char* input; - csubstr match[CREG_MAX_CAPTURES]; + csview match[CREG_MAX_CAPTURES]; } cregex_iter; #define c_formatch(it, Re, Input) \ @@ -115,11 +115,11 @@ int cregex_captures(const cregex* re); /* return CREG_OK, CREG_NOMATCH or CREG_MATCHERROR. */ #define cregex_find(...) c_MACRO_OVERLOAD(cregex_find, __VA_ARGS__) #define cregex_find_3(re, input, match) cregex_find_4(re, input, match, CREG_DEFAULT) -int cregex_find_4(const cregex* re, const char* input, csubstr match[], int mflags); +int cregex_find_4(const cregex* re, const char* input, csview match[], int mflags); -/* find with csubstr as input. */ -STC_INLINE int cregex_find_ss(const cregex* re, csubstr input, csubstr match[]) { - csubstr *mp = NULL; +/* find with csview as input. */ +STC_INLINE int cregex_find_sv(const cregex* re, csview input, csview match[]) { + csview *mp = NULL; if (match) { match[0] = input; mp = match; } return cregex_find(re, input.str, mp, CREG_STARTEND); } @@ -129,27 +129,27 @@ STC_INLINE int cregex_find_ss(const cregex* re, csubstr input, csubstr match[]) #define cregex_find_pattern_3(pattern, input, match) \ cregex_find_pattern_4(pattern, input, match, CREG_DEFAULT) int cregex_find_pattern_4(const char* pattern, const char* input, - csubstr match[], int cmflags); + csview match[], int cmflags); STC_INLINE bool cregex_is_match(const cregex* re, const char* input) { return cregex_find_4(re, input, NULL, CREG_DEFAULT) == CREG_OK; } -/* replace csubstr input with replace using regular expression pattern */ -#define cregex_replace_ss(...) c_MACRO_OVERLOAD(cregex_replace_ss, __VA_ARGS__) -#define cregex_replace_ss_3(pattern, input, replace) \ - cregex_replace_ss_4(pattern, input, replace, INT32_MAX) -#define cregex_replace_ss_4(pattern, input, replace, count) \ - cregex_replace_ss_6(pattern, input, replace, count, NULL, CREG_DEFAULT) -cstr cregex_replace_ss_6(const cregex* re, csubstr input, const char* replace, int count, - bool (*transform)(int group, csubstr match, cstr* result), int rflags); +/* replace csview input with replace using regular expression pattern */ +#define cregex_replace_sv(...) c_MACRO_OVERLOAD(cregex_replace_sv, __VA_ARGS__) +#define cregex_replace_sv_3(pattern, input, replace) \ + cregex_replace_sv_4(pattern, input, replace, INT32_MAX) +#define cregex_replace_sv_4(pattern, input, replace, count) \ + cregex_replace_sv_6(pattern, input, replace, count, NULL, CREG_DEFAULT) +cstr cregex_replace_sv_6(const cregex* re, csview input, const char* replace, int count, + bool (*transform)(int group, csview match, cstr* result), int rflags); /* replace input with replace using regular expression */ #define cregex_replace(...) c_MACRO_OVERLOAD(cregex_replace, __VA_ARGS__) #define cregex_replace_3(re, input, replace) cregex_replace_4(re, input, replace, INT32_MAX) STC_INLINE cstr cregex_replace_4(const cregex* re, const char* input, const char* replace, int count) { - csubstr ss = {input, c_strlen(input)}; - return cregex_replace_ss_4(re, ss, replace, count); + csview sv = {input, c_strlen(input)}; + return cregex_replace_sv_4(re, sv, replace, count); } /* replace + compile RE pattern, and extra arguments */ @@ -159,7 +159,7 @@ STC_INLINE cstr cregex_replace_4(const cregex* re, const char* input, const char #define cregex_replace_pattern_4(pattern, input, replace, count) \ cregex_replace_pattern_6(pattern, input, replace, count, NULL, CREG_DEFAULT) cstr cregex_replace_pattern_6(const char* pattern, const char* input, const char* replace, int count, - bool (*transform)(int group, csubstr match, cstr* result), int crflags); + bool (*transform)(int group, csview match, cstr* result), int crflags); /* destroy regex */ void cregex_drop(cregex* re); diff --git a/include/stc/cstr.h b/include/stc/cstr.h index ce398628..7f4bad97 100644 --- a/include/stc/cstr.h +++ b/include/stc/cstr.h @@ -75,7 +75,7 @@ STC_API char* cstr_reserve(cstr* self, intptr_t cap); STC_API void cstr_shrink_to_fit(cstr* self); STC_API char* cstr_resize(cstr* self, intptr_t size, char value); STC_API intptr_t cstr_find_at(const cstr* self, intptr_t pos, const char* search); -STC_API intptr_t cstr_find_ss(const cstr* self, csubstr search); +STC_API intptr_t cstr_find_sv(const cstr* self, csview search); STC_API char* cstr_assign_n(cstr* self, const char* str, intptr_t len); STC_API char* cstr_append_n(cstr* self, const char* str, intptr_t len); STC_API char* cstr_append_uninit(cstr *self, intptr_t len); @@ -85,7 +85,7 @@ STC_API void cstr_u8_erase(cstr* self, intptr_t bytepos, intptr_t u8len); STC_API cstr cstr_from_fmt(const char* fmt, ...); STC_API intptr_t cstr_append_fmt(cstr* self, const char* fmt, ...); STC_API intptr_t cstr_printf(cstr* self, const char* fmt, ...); -STC_API cstr cstr_replace_ss(csubstr sv, csubstr search, csubstr repl, int32_t count); +STC_API cstr cstr_replace_sv(csview sv, csview search, csview repl, int32_t count); STC_API uint64_t cstr_hash(const cstr *self); STC_INLINE cstr_buf cstr_buffer(cstr* s) { @@ -93,12 +93,12 @@ STC_INLINE cstr_buf cstr_buffer(cstr* s) { ? c_LITERAL(cstr_buf){s->lon.data, cstr_l_size(s), cstr_l_cap(s)} : c_LITERAL(cstr_buf){s->sml.data, cstr_s_size(s), cstr_s_cap}; } -STC_INLINE csview cstr_sv(const cstr* s) { - return cstr_is_long(s) ? c_sv_2(s->lon.data, cstr_l_size(s)) - : c_sv_2(s->sml.data, cstr_s_size(s)); +STC_INLINE crawstr cstr_rs(const cstr* s) { + return cstr_is_long(s) ? c_rs_2(s->lon.data, cstr_l_size(s)) + : c_rs_2(s->sml.data, cstr_s_size(s)); } -STC_INLINE csubstr cstr_ss(const cstr* s) - { csview sv = cstr_sv(s); return c_ss_2(sv.str, sv.size); } +STC_INLINE csview cstr_sv(const cstr* s) + { crawstr rs = cstr_rs(s); return c_sv_2(rs.str, rs.size); } STC_INLINE cstr cstr_init(void) { return cstr_null; } @@ -112,12 +112,12 @@ STC_INLINE cstr cstr_from_n(const char* str, const intptr_t len) { STC_INLINE cstr cstr_from(const char* str) { return cstr_from_n(str, c_strlen(str)); } -STC_INLINE cstr cstr_from_ss(csubstr sv) - { return cstr_from_n(sv.str, sv.size); } - STC_INLINE cstr cstr_from_sv(csview sv) { return cstr_from_n(sv.str, sv.size); } +STC_INLINE cstr cstr_from_rs(crawstr rs) + { return cstr_from_n(rs.str, rs.size); } + STC_INLINE cstr cstr_with_size(const intptr_t size, const char value) { cstr s; c_memset(_cstr_init(&s, size, size), value, size); @@ -144,8 +144,8 @@ STC_INLINE cstr cstr_move(cstr* self) { } STC_INLINE cstr cstr_clone(cstr s) { - csview sv = cstr_sv(&s); - return cstr_from_n(sv.str, sv.size); + crawstr rs = cstr_rs(&s); + return cstr_from_n(rs.str, rs.size); } STC_INLINE void cstr_drop(cstr* self) { @@ -175,9 +175,9 @@ STC_INLINE intptr_t cstr_capacity(const cstr* self) // utf8 methods defined in/depending on src/utf8code.c: -extern cstr cstr_casefold_ss(csubstr sv); -extern cstr cstr_tolower_ss(csubstr sv); -extern cstr cstr_toupper_ss(csubstr sv); +extern cstr cstr_casefold_sv(csview sv); +extern cstr cstr_tolower_sv(csview sv); +extern cstr cstr_toupper_sv(csview sv); extern cstr cstr_tolower(const char* str); extern cstr cstr_toupper(const char* str); extern void cstr_lowercase(cstr* self); @@ -198,9 +198,9 @@ STC_INLINE intptr_t cstr_u8_to_pos(const cstr* self, intptr_t u8idx) STC_INLINE const char* cstr_u8_at(const cstr* self, intptr_t u8idx) { return utf8_at(cstr_str(self), u8idx); } -STC_INLINE csubstr cstr_u8_chr(const cstr* self, intptr_t u8idx) { +STC_INLINE csview cstr_u8_chr(const cstr* self, intptr_t u8idx) { const char* str = cstr_str(self); - csubstr sv; + csview sv; sv.str = utf8_at(str, u8idx); sv.size = utf8_chr_size(sv.str); return sv; @@ -209,9 +209,9 @@ STC_INLINE csubstr cstr_u8_chr(const cstr* self, intptr_t u8idx) { // utf8 iterator STC_INLINE cstr_iter cstr_begin(const cstr* self) { - csview sv = cstr_sv(self); - if (!sv.size) return c_LITERAL(cstr_iter){.ref = NULL}; - return c_LITERAL(cstr_iter){.u8 = {{sv.str, utf8_chr_size(sv.str)}}}; + crawstr rs = cstr_rs(self); + if (!rs.size) return c_LITERAL(cstr_iter){.ref = NULL}; + return c_LITERAL(cstr_iter){.u8 = {{rs.str, utf8_chr_size(rs.str)}}}; } STC_INLINE cstr_iter cstr_end(const cstr* self) { (void)self; return c_LITERAL(cstr_iter){NULL}; @@ -241,7 +241,7 @@ STC_INLINE int cstr_icmp(const cstr* s1, const cstr* s2) { return utf8_icmp(cstr_str(s1), cstr_str(s2)); } STC_INLINE bool cstr_eq(const cstr* s1, const cstr* s2) { - csview x = cstr_sv(s1), y = cstr_sv(s2); + crawstr x = cstr_rs(s1), y = cstr_rs(s2); return x.size == y.size && !c_memcmp(x.str, y.str, x.size); } @@ -249,7 +249,7 @@ STC_INLINE bool cstr_eq(const cstr* s1, const cstr* s2) { STC_INLINE bool cstr_equals(const cstr* self, const char* str) { return !strcmp(cstr_str(self), str); } -STC_INLINE bool cstr_equals_ss(const cstr* self, csubstr sv) +STC_INLINE bool cstr_equals_sv(const cstr* self, csview sv) { return sv.size == cstr_size(self) && !c_memcmp(cstr_str(self), sv.str, sv.size); } STC_INLINE bool cstr_equals_s(const cstr* self, cstr s) @@ -271,14 +271,14 @@ STC_INLINE intptr_t cstr_find_s(const cstr* self, cstr search) STC_INLINE bool cstr_contains(const cstr* self, const char* search) { return strstr((char*)cstr_str(self), search) != NULL; } -STC_INLINE bool cstr_contains_ss(const cstr* self, csubstr search) - { return cstr_find_ss(self, search) != c_NPOS; } +STC_INLINE bool cstr_contains_sv(const cstr* self, csview search) + { return cstr_find_sv(self, search) != c_NPOS; } STC_INLINE bool cstr_contains_s(const cstr* self, cstr search) { return strstr((char*)cstr_str(self), cstr_str(&search)) != NULL; } -STC_INLINE bool cstr_starts_with_ss(const cstr* self, csubstr sub) { +STC_INLINE bool cstr_starts_with_sv(const cstr* self, csview sub) { if (sub.size > cstr_size(self)) return false; return !c_memcmp(cstr_str(self), sub.str, sub.size); } @@ -290,43 +290,43 @@ STC_INLINE bool cstr_starts_with(const cstr* self, const char* sub) { } STC_INLINE bool cstr_starts_with_s(const cstr* self, cstr sub) - { return cstr_starts_with_ss(self, cstr_ss(&sub)); } + { return cstr_starts_with_sv(self, cstr_sv(&sub)); } STC_INLINE bool cstr_istarts_with(const cstr* self, const char* sub) { - csubstr sv = cstr_ss(self); + csview sv = cstr_sv(self); intptr_t len = c_strlen(sub); - return len <= sv.size && !utf8_icmp_ss(sv, c_ss(sub, len)); + return len <= sv.size && !utf8_icmp_sv(sv, c_sv(sub, len)); } -STC_INLINE bool cstr_ends_with_ss(const cstr* self, csubstr sub) { - csview sv = cstr_sv(self); - if (sub.size > sv.size) return false; - return !c_memcmp(sv.str + sv.size - sub.size, sub.str, sub.size); +STC_INLINE bool cstr_ends_with_sv(const cstr* self, csview sub) { + crawstr rs = cstr_rs(self); + if (sub.size > rs.size) return false; + return !c_memcmp(rs.str + rs.size - sub.size, sub.str, sub.size); } STC_INLINE bool cstr_ends_with_s(const cstr* self, cstr sub) - { return cstr_ends_with_ss(self, cstr_ss(&sub)); } + { return cstr_ends_with_sv(self, cstr_sv(&sub)); } STC_INLINE bool cstr_ends_with(const cstr* self, const char* sub) - { return cstr_ends_with_ss(self, c_ss(sub, c_strlen(sub))); } + { return cstr_ends_with_sv(self, c_sv(sub, c_strlen(sub))); } STC_INLINE bool cstr_iends_with(const cstr* self, const char* sub) { - csview sv = cstr_sv(self); + crawstr rs = cstr_rs(self); intptr_t n = c_strlen(sub); - return n <= sv.size && !utf8_icmp(sv.str + sv.size - n, sub); + return n <= rs.size && !utf8_icmp(rs.str + rs.size - n, sub); } STC_INLINE char* cstr_assign(cstr* self, const char* str) { return cstr_assign_n(self, str, c_strlen(str)); } -STC_INLINE char* cstr_assign_ss(cstr* self, csubstr sv) +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); + crawstr rs = cstr_rs(&s); + return cstr_assign_n(self, rs.str, rs.size); } @@ -334,51 +334,51 @@ STC_INLINE char* cstr_push(cstr* self, const char* chr) { return cstr_append_n(self, chr, utf8_chr_size(chr)); } STC_INLINE void cstr_pop(cstr* self) { - csview sv = cstr_sv(self); - const char* s = sv.str + sv.size; + crawstr rs = cstr_rs(self); + const char* s = rs.str + rs.size; while ((*--s & 0xC0) == 0x80) ; - _cstr_set_size(self, (s - sv.str)); + _cstr_set_size(self, (s - rs.str)); } STC_INLINE char* cstr_append(cstr* self, const char* str) { return cstr_append_n(self, str, c_strlen(str)); } -STC_INLINE char* cstr_append_ss(cstr* self, csubstr sv) +STC_INLINE char* cstr_append_sv(cstr* self, csview sv) { return cstr_append_n(self, sv.str, sv.size); } STC_INLINE char* cstr_append_s(cstr* self, cstr s) - { return cstr_append_ss(self, cstr_ss(&s)); } + { return cstr_append_sv(self, cstr_sv(&s)); } #define cstr_replace(...) c_MACRO_OVERLOAD(cstr_replace, __VA_ARGS__) #define cstr_replace_3(self, search, repl) cstr_replace_4(self, search, repl, INT32_MAX) STC_INLINE void cstr_replace_4(cstr* self, const char* search, const char* repl, int32_t count) { - cstr_take(self, cstr_replace_ss(cstr_ss(self), c_ss(search, c_strlen(search)), - c_ss(repl, c_strlen(repl)), count)); + cstr_take(self, cstr_replace_sv(cstr_sv(self), c_sv(search, c_strlen(search)), + c_sv(repl, c_strlen(repl)), count)); } -STC_INLINE void cstr_replace_at_ss(cstr* self, intptr_t pos, intptr_t len, const csubstr repl) { +STC_INLINE void cstr_replace_at_sv(cstr* self, intptr_t pos, intptr_t len, const csview repl) { char* d = _cstr_internal_move(self, pos + len, pos + repl.size); c_memcpy(d + pos, repl.str, repl.size); } STC_INLINE void cstr_replace_at(cstr* self, intptr_t pos, intptr_t len, const char* repl) - { cstr_replace_at_ss(self, pos, len, c_ss(repl, c_strlen(repl))); } + { cstr_replace_at_sv(self, pos, len, c_sv(repl, c_strlen(repl))); } STC_INLINE void cstr_replace_at_s(cstr* self, intptr_t pos, intptr_t len, cstr repl) - { cstr_replace_at_ss(self, pos, len, cstr_ss(&repl)); } + { cstr_replace_at_sv(self, pos, len, cstr_sv(&repl)); } -STC_INLINE void cstr_u8_replace_at(cstr* self, intptr_t bytepos, intptr_t u8len, csubstr repl) - { cstr_replace_at_ss(self, bytepos, utf8_pos(cstr_str(self) + bytepos, u8len), repl); } +STC_INLINE void cstr_u8_replace_at(cstr* self, intptr_t bytepos, intptr_t u8len, csview repl) + { cstr_replace_at_sv(self, bytepos, utf8_pos(cstr_str(self) + bytepos, u8len), repl); } STC_INLINE void cstr_insert(cstr* self, intptr_t pos, const char* str) - { cstr_replace_at_ss(self, pos, 0, c_ss(str, c_strlen(str))); } + { cstr_replace_at_sv(self, pos, 0, c_sv(str, c_strlen(str))); } -STC_INLINE void cstr_insert_ss(cstr* self, intptr_t pos, csubstr sv) - { cstr_replace_at_ss(self, pos, 0, sv); } +STC_INLINE void cstr_insert_sv(cstr* self, intptr_t pos, csview sv) + { cstr_replace_at_sv(self, pos, 0, sv); } STC_INLINE void cstr_insert_s(cstr* self, intptr_t pos, cstr s) - { cstr_replace_at_ss(self, pos, 0, cstr_ss(&s)); } + { cstr_replace_at_sv(self, pos, 0, cstr_sv(&s)); } STC_INLINE bool cstr_getline(cstr *self, FILE *fp) { return cstr_getdelim(self, '\n', fp); } @@ -397,7 +397,7 @@ fn_tocase[] = {{tolower, utf8_casefold}, {tolower, utf8_tolower}, {toupper, utf8_toupper}}; -static cstr cstr_tocase(csubstr sv, int k) { +static cstr cstr_tocase(csview sv, int k) { cstr out = cstr_init(); char *buf = cstr_reserve(&out, sv.size*3/2); const char *end = sv.str + sv.size; @@ -418,26 +418,26 @@ static cstr cstr_tocase(csubstr sv, int k) { return out; } -cstr cstr_casefold_ss(csubstr sv) +cstr cstr_casefold_sv(csview sv) { return cstr_tocase(sv, 0); } -cstr cstr_tolower_ss(csubstr sv) +cstr cstr_tolower_sv(csview sv) { return cstr_tocase(sv, 1); } -cstr cstr_toupper_ss(csubstr sv) +cstr cstr_toupper_sv(csview sv) { return cstr_tocase(sv, 2); } cstr cstr_tolower(const char* str) - { return cstr_tolower_ss(c_ss(str, c_strlen(str))); } + { return cstr_tolower_sv(c_sv(str, c_strlen(str))); } cstr cstr_toupper(const char* str) - { return cstr_toupper_ss(c_ss(str, c_strlen(str))); } + { return cstr_toupper_sv(c_sv(str, c_strlen(str))); } void cstr_lowercase(cstr* self) - { cstr_take(self, cstr_tolower_ss(cstr_ss(self))); } + { cstr_take(self, cstr_tolower_sv(cstr_sv(self))); } void cstr_uppercase(cstr* self) - { cstr_take(self, cstr_toupper_ss(cstr_ss(self))); } + { cstr_take(self, cstr_toupper_sv(cstr_sv(self))); } bool cstr_valid_utf8(const cstr* self) { return utf8_valid(cstr_str(self)); } @@ -449,14 +449,14 @@ bool cstr_valid_utf8(const cstr* self) #define CSTR_C_INCLUDED STC_DEF uint64_t cstr_hash(const cstr *self) { - csview sv = cstr_sv(self); - return cfasthash(sv.str, sv.size); + crawstr rs = cstr_rs(self); + return cfasthash(rs.str, rs.size); } -STC_DEF intptr_t cstr_find_ss(const cstr* self, csubstr search) { - csview sv = cstr_sv(self); - char* res = cstrnstrn(sv.str, search.str, sv.size, search.size); - return res ? (res - sv.str) : c_NPOS; +STC_DEF intptr_t cstr_find_sv(const cstr* self, csview search) { + crawstr rs = cstr_rs(self); + char* res = cstrnstrn(rs.str, search.str, rs.size, search.size); + return res ? (res - rs.str) : c_NPOS; } STC_DEF char* _cstr_internal_move(cstr* self, const intptr_t pos1, const intptr_t pos2) { @@ -530,10 +530,10 @@ STC_DEF char* cstr_resize(cstr* self, const intptr_t size, const char value) { } STC_DEF intptr_t cstr_find_at(const cstr* self, const intptr_t pos, const char* search) { - csview sv = cstr_sv(self); - if (pos > sv.size) return c_NPOS; - const char* res = strstr((char*)sv.str + pos, search); - return res ? (res - sv.str) : c_NPOS; + crawstr rs = cstr_rs(self); + if (pos > rs.size) return c_NPOS; + const char* res = strstr((char*)rs.str + pos, search); + return res ? (res - rs.str) : c_NPOS; } STC_DEF char* cstr_assign_n(cstr* self, const char* str, const intptr_t len) { @@ -583,7 +583,7 @@ STC_DEF bool cstr_getdelim(cstr *self, const int delim, FILE *fp) { } } -STC_DEF cstr cstr_replace_ss(csubstr in, csubstr search, csubstr repl, int32_t count) { +STC_DEF cstr cstr_replace_sv(csview in, csview search, csview repl, int32_t count) { cstr out = cstr_null; intptr_t from = 0; char* res; if (!count) count = INT32_MAX; diff --git a/include/stc/csubstr.h b/include/stc/csubstr.h deleted file mode 100644 index c7a43052..00000000 --- a/include/stc/csubstr.h +++ /dev/null @@ -1,211 +0,0 @@ -/* MIT License - * - * Copyright (c) 2023 Tyge Løvset - * - * 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. - */ -#define i_header // external linkage by default. override with i_static. -#define _i_inc_utf8 -#include "utf8.h" - -#ifndef CSUBSTR_H_INCLUDED -#define CSUBSTR_H_INCLUDED - -#define csubstr_init() c_ss_1("") -#define csubstr_drop(p) c_default_drop(p) -#define csubstr_clone(ss) c_default_clone(ss) -#define csubstr_from_n(str, n) c_ss_2(str, n) - -STC_API csubstr_iter csubstr_advance(csubstr_iter it, intptr_t pos); -STC_API intptr_t csubstr_find_ss(csubstr ss, csubstr search); -STC_API uint64_t csubstr_hash(const csubstr *self); -STC_API csubstr csubstr_slice_ex(csubstr ss, intptr_t p1, intptr_t p2); -STC_API csubstr csubstr_substr_ex(csubstr ss, intptr_t pos, intptr_t n); -STC_API csubstr csubstr_token(csubstr ss, const char* sep, intptr_t* start); - -STC_INLINE csubstr csubstr_from(const char* str) - { return c_LITERAL(csubstr){str, c_strlen(str)}; } -STC_INLINE void csubstr_clear(csubstr* self) { *self = csubstr_init(); } -STC_INLINE intptr_t csubstr_size(csubstr ss) { return ss.size; } -STC_INLINE bool csubstr_empty(csubstr ss) { return ss.size == 0; } - -STC_INLINE bool csubstr_equals_ss(csubstr ss1, csubstr ss2) - { return ss1.size == ss2.size && !c_memcmp(ss1.str, ss2.str, ss1.size); } - -STC_INLINE bool csubstr_equals(csubstr ss, const char* str) - { return csubstr_equals_ss(ss, c_ss_2(str, c_strlen(str))); } - -STC_INLINE intptr_t csubstr_find(csubstr ss, const char* str) - { return csubstr_find_ss(ss, c_ss_2(str, c_strlen(str))); } - -STC_INLINE bool csubstr_contains(csubstr ss, const char* str) - { return csubstr_find(ss, str) != c_NPOS; } - -STC_INLINE bool csubstr_starts_with(csubstr ss, const char* str) { - intptr_t n = c_strlen(str); - return n > ss.size ? false : !c_memcmp(ss.str, str, n); -} - -STC_INLINE bool csubstr_ends_with(csubstr ss, const char* str) { - intptr_t n = c_strlen(str); - return n > ss.size ? false : !c_memcmp(ss.str + ss.size - n, str, n); -} - -STC_INLINE csubstr csubstr_substr(csubstr ss, intptr_t pos, intptr_t n) { - if (pos + n > ss.size) n = ss.size - pos; - ss.str += pos, ss.size = n; - return ss; -} - -STC_INLINE csubstr csubstr_slice(csubstr ss, intptr_t p1, intptr_t p2) { - if (p2 > ss.size) p2 = ss.size; - ss.str += p1, ss.size = p2 > p1 ? p2 - p1 : 0; - return ss; -} - -/* utf8 iterator */ -STC_INLINE csubstr_iter csubstr_begin(const csubstr* self) { - if (!self->size) return c_LITERAL(csubstr_iter){NULL}; - return c_LITERAL(csubstr_iter){.u8 = {{self->str, utf8_chr_size(self->str)}, - self->str + self->size}}; -} -STC_INLINE csubstr_iter csubstr_end(const csubstr* self) { - return c_LITERAL(csubstr_iter){.u8 = {{NULL}, self->str + self->size}}; -} -STC_INLINE void csubstr_next(csubstr_iter* it) { - it->ref += it->u8.chr.size; - it->u8.chr.size = utf8_chr_size(it->ref); - if (it->ref == it->u8.end) it->ref = NULL; -} - -/* utf8 */ -STC_INLINE intptr_t csubstr_u8_size(csubstr ss) - { return utf8_size_n(ss.str, ss.size); } - -STC_INLINE csubstr csubstr_u8_substr(csubstr ss, intptr_t bytepos, intptr_t u8len) { - ss.str += bytepos; - ss.size = utf8_pos(ss.str, u8len); - return ss; -} - -STC_INLINE bool csubstr_valid_utf8(csubstr ss) // depends on src/utf8code.c - { return utf8_valid_n(ss.str, ss.size); } - -#define c_fortoken_ss(it, inputss, sep) \ - for (struct { csubstr _inp, token, *ref; const char *_sep; intptr_t pos; } \ - it = {._inp=inputss, .token=it._inp, .ref=&it.token, ._sep=sep} \ - ; it.pos <= it._inp.size && (it.token = csubstr_token(it._inp, it._sep, &it.pos)).str ; ) - -#define c_fortoken(it, input, sep) \ - c_fortoken_ss(it, csubstr_from(input), sep) - -/* ---- Container helper functions ---- */ - -STC_INLINE int csubstr_cmp(const csubstr* x, const csubstr* y) { - intptr_t n = x->size < y->size ? x->size : y->size; - int c = c_memcmp(x->str, y->str, n); - return c ? c : (int)(x->size - y->size); -} - -STC_INLINE int csubstr_icmp(const csubstr* x, const csubstr* y) - { return utf8_icmp_ss(*x, *y); } - -STC_INLINE bool csubstr_eq(const csubstr* x, const csubstr* y) - { return x->size == y->size && !c_memcmp(x->str, y->str, x->size); } - -#endif // CSUBSTR_H_INCLUDED - -/* csubstr interaction with cstr: */ -#ifdef CSTR_H_INCLUDED - -STC_INLINE csubstr cstr_substr(const cstr* self, intptr_t pos, intptr_t n) - { return csubstr_substr(cstr_ss(self), pos, n); } - -STC_INLINE csubstr cstr_slice(const cstr* self, intptr_t p1, intptr_t p2) - { return csubstr_slice(cstr_ss(self), p1, p2); } - -STC_INLINE csubstr cstr_substr_ex(const cstr* self, intptr_t pos, intptr_t n) - { return csubstr_substr_ex(cstr_ss(self), pos, n); } - -STC_INLINE csubstr cstr_slice_ex(const cstr* self, intptr_t p1, intptr_t p2) - { return csubstr_slice_ex(cstr_ss(self), p1, p2); } - -STC_INLINE csubstr cstr_u8_substr(const cstr* self , intptr_t bytepos, intptr_t u8len) - { return csubstr_u8_substr(cstr_ss(self), bytepos, u8len); } -#endif - -/* -------------------------- IMPLEMENTATION ------------------------- */ -#if defined i_implement || defined i_static -#ifndef CSUBSTR_C_INCLUDED -#define CSUBSTR_C_INCLUDED - -STC_DEF csubstr_iter csubstr_advance(csubstr_iter it, intptr_t pos) { - int inc = -1; - if (pos > 0) pos = -pos, inc = 1; - while (pos && it.ref != it.u8.end) pos += (*(it.ref += inc) & 0xC0) != 0x80; - it.u8.chr.size = utf8_chr_size(it.ref); - if (it.ref == it.u8.end) it.ref = NULL; - return it; -} - -STC_DEF intptr_t csubstr_find_ss(csubstr ss, csubstr search) { - char* res = cstrnstrn(ss.str, search.str, ss.size, search.size); - return res ? (res - ss.str) : c_NPOS; -} - -STC_DEF uint64_t csubstr_hash(const csubstr *self) - { return cfasthash(self->str, self->size); } - -STC_DEF csubstr csubstr_substr_ex(csubstr ss, intptr_t pos, intptr_t n) { - if (pos < 0) { - pos += ss.size; - if (pos < 0) pos = 0; - } - if (pos > ss.size) pos = ss.size; - if (pos + n > ss.size) n = ss.size - pos; - ss.str += pos, ss.size = n; - return ss; -} - -STC_DEF csubstr csubstr_slice_ex(csubstr ss, intptr_t p1, intptr_t p2) { - if (p1 < 0) { - p1 += ss.size; - if (p1 < 0) p1 = 0; - } - if (p2 < 0) p2 += ss.size; - if (p2 > ss.size) p2 = ss.size; - ss.str += p1, ss.size = (p2 > p1 ? p2 - p1 : 0); - return ss; -} - -STC_DEF csubstr csubstr_token(csubstr ss, const char* sep, intptr_t* start) { - intptr_t sep_size = c_strlen(sep); - csubstr slice = {ss.str + *start, ss.size - *start}; - const char* res = cstrnstrn(slice.str, sep, slice.size, sep_size); - csubstr tok = {slice.str, res ? (res - slice.str) : slice.size}; - *start += tok.size + sep_size; - return tok; -} -#endif // CSUBSTR_C_INCLUDED -#endif // i_implement -#undef i_static -#undef i_header -#undef i_implement -#undef i_import -#undef i_opt diff --git a/include/stc/csview.h b/include/stc/csview.h index 367258e4..2a051ddd 100644 --- a/include/stc/csview.h +++ b/include/stc/csview.h @@ -20,33 +20,39 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ +#define i_header // external linkage by default. override with i_static. #define _i_inc_utf8 #include "utf8.h" #ifndef CSVIEW_H_INCLUDED #define CSVIEW_H_INCLUDED -#define csview_init() c_sv("") +#define csview_init() c_sv_1("") #define csview_drop(p) c_default_drop(p) #define csview_clone(sv) c_default_clone(sv) +#define csview_from_n(str, n) c_sv_2(str, n) + +STC_API csview_iter csview_advance(csview_iter it, intptr_t pos); +STC_API intptr_t csview_find_sv(csview sv, csview search); +STC_API uint64_t csview_hash(const csview *self); +STC_API csview csview_slice_ex(csview sv, intptr_t p1, intptr_t p2); +STC_API csview csview_substr_ex(csview sv, intptr_t pos, intptr_t n); +STC_API csview csview_token(csview sv, const char* sep, intptr_t* start); STC_INLINE csview csview_from(const char* str) - { return c_sv_2(str, c_strlen(str)); } + { return c_LITERAL(csview){str, c_strlen(str)}; } STC_INLINE void csview_clear(csview* self) { *self = csview_init(); } -STC_INLINE csubstr csview_ss(csview sv) { return c_ss_2(sv.str, sv.size); } - STC_INLINE intptr_t csview_size(csview sv) { return sv.size; } STC_INLINE bool csview_empty(csview sv) { return sv.size == 0; } -STC_INLINE bool csview_equals(csview sv, const char* str) { - intptr_t n = c_strlen(str); - return sv.size == n && !c_memcmp(sv.str, str, n); -} +STC_INLINE bool csview_equals_sv(csview sv1, csview sv2) + { return sv1.size == sv2.size && !c_memcmp(sv1.str, sv2.str, sv1.size); } -STC_INLINE intptr_t csview_find(csview sv, const char* search) { - char* res = cstrnstrn(sv.str, search, sv.size, c_strlen(search)); - return res ? (res - sv.str) : c_NPOS; -} +STC_INLINE bool csview_equals(csview sv, const char* str) + { return csview_equals_sv(sv, c_sv_2(str, c_strlen(str))); } + +STC_INLINE intptr_t csview_find(csview sv, const char* str) + { return csview_find_sv(sv, c_sv_2(str, c_strlen(str))); } STC_INLINE bool csview_contains(csview sv, const char* str) { return csview_find(sv, str) != c_NPOS; } @@ -61,40 +67,55 @@ STC_INLINE bool csview_ends_with(csview sv, const char* str) { return n > sv.size ? false : !c_memcmp(sv.str + sv.size - n, str, n); } +STC_INLINE csview csview_substr(csview sv, intptr_t pos, intptr_t n) { + if (pos + n > sv.size) n = sv.size - pos; + sv.str += pos, sv.size = n; + return sv; +} + +STC_INLINE csview csview_slice(csview sv, intptr_t p1, intptr_t p2) { + if (p2 > sv.size) p2 = sv.size; + sv.str += p1, sv.size = p2 > p1 ? p2 - p1 : 0; + return sv; +} + /* utf8 iterator */ STC_INLINE csview_iter csview_begin(const csview* self) { - if (!self->size) return c_LITERAL(csview_iter){.ref = NULL}; - return c_LITERAL(csview_iter){.u8 = {{self->str, utf8_chr_size(self->str)}}}; + if (!self->size) return c_LITERAL(csview_iter){NULL}; + return c_LITERAL(csview_iter){.u8 = {{self->str, utf8_chr_size(self->str)}, + self->str + self->size}}; } STC_INLINE csview_iter csview_end(const csview* self) { - (void)self; return c_LITERAL(csview_iter){.ref = NULL}; + return c_LITERAL(csview_iter){.u8 = {{NULL}, self->str + self->size}}; } STC_INLINE void csview_next(csview_iter* it) { it->ref += it->u8.chr.size; it->u8.chr.size = utf8_chr_size(it->ref); - if (!*it->ref) it->ref = NULL; -} -STC_INLINE csview_iter csview_advance(csview_iter it, intptr_t pos) { - int inc = -1; - if (pos > 0) pos = -pos, inc = 1; - while (pos && *it.ref) pos += (*(it.ref += inc) & 0xC0) != 0x80; - it.u8.chr.size = utf8_chr_size(it.ref); - if (!*it.ref) it.ref = NULL; - return it; + if (it->ref == it->u8.end) it->ref = NULL; } -/* utf8 size */ +/* utf8 */ STC_INLINE intptr_t csview_u8_size(csview sv) { return utf8_size_n(sv.str, sv.size); } -/* utf8 validation: depends on src/utf8code.c */ -STC_INLINE bool csview_valid_utf8(csview sv) +STC_INLINE csview csview_u8_substr(csview sv, intptr_t bytepos, intptr_t u8len) { + sv.str += bytepos; + sv.size = utf8_pos(sv.str, u8len); + return sv; +} + +STC_INLINE bool csview_valid_utf8(csview sv) // depends on src/utf8code.c { return utf8_valid_n(sv.str, sv.size); } -/* utf8 ignore case cmp: depends on src/utf8code.c */ -STC_INLINE int csview_icmp(const csview* x, const csview* y) - { return utf8_icmp_ss(c_ss_2(x->str, x->size), c_ss_2(y->str, y->size)); } +#define c_fortoken_sv(it, inputsv, sep) \ + for (struct { csview _inp, token, *ref; const char *_sep; intptr_t pos; } \ + it = {._inp=inputsv, .token=it._inp, .ref=&it.token, ._sep=sep} \ + ; it.pos <= it._inp.size && (it.token = csview_token(it._inp, it._sep, &it.pos)).str ; ) +#define c_fortoken(it, input, sep) \ + c_fortoken_sv(it, csview_from(input), sep) + +/* ---- Container helper functions ---- */ STC_INLINE int csview_cmp(const csview* x, const csview* y) { intptr_t n = x->size < y->size ? x->size : y->size; @@ -102,13 +123,87 @@ STC_INLINE int csview_cmp(const csview* x, const csview* y) { return c ? c : (int)(x->size - y->size); } +STC_INLINE int csview_icmp(const csview* x, const csview* y) + { return utf8_icmp_sv(*x, *y); } + STC_INLINE bool csview_eq(const csview* x, const csview* y) { return x->size == y->size && !c_memcmp(x->str, y->str, x->size); } -STC_INLINE uint64_t csview_hash(const csview *self) +#endif // CSVIEW_H_INCLUDED + +/* csview interaction with cstr: */ +#ifdef CSTR_H_INCLUDED + +STC_INLINE csview cstr_substr(const cstr* self, intptr_t pos, intptr_t n) + { return csview_substr(cstr_sv(self), pos, n); } + +STC_INLINE csview cstr_slice(const cstr* self, intptr_t p1, intptr_t p2) + { return csview_slice(cstr_sv(self), p1, p2); } + +STC_INLINE csview cstr_substr_ex(const cstr* self, intptr_t pos, intptr_t 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(cstr_sv(self), p1, p2); } + +STC_INLINE csview cstr_u8_substr(const cstr* self , intptr_t bytepos, intptr_t u8len) + { return csview_u8_substr(cstr_sv(self), bytepos, u8len); } +#endif + +/* -------------------------- IMPLEMENTATION ------------------------- */ +#if defined i_implement || defined i_static +#ifndef CSVIEW_C_INCLUDED +#define CSVIEW_C_INCLUDED + +STC_DEF csview_iter csview_advance(csview_iter it, intptr_t pos) { + int inc = -1; + if (pos > 0) pos = -pos, inc = 1; + while (pos && it.ref != it.u8.end) pos += (*(it.ref += inc) & 0xC0) != 0x80; + it.u8.chr.size = utf8_chr_size(it.ref); + if (it.ref == it.u8.end) it.ref = NULL; + return it; +} + +STC_DEF intptr_t csview_find_sv(csview sv, csview search) { + char* res = cstrnstrn(sv.str, search.str, sv.size, search.size); + return res ? (res - sv.str) : c_NPOS; +} + +STC_DEF uint64_t csview_hash(const csview *self) { return cfasthash(self->str, self->size); } -#endif // CSVIEW_H_INCLUDED +STC_DEF csview csview_substr_ex(csview sv, intptr_t pos, intptr_t n) { + if (pos < 0) { + pos += sv.size; + if (pos < 0) pos = 0; + } + if (pos > sv.size) pos = sv.size; + if (pos + n > sv.size) n = sv.size - pos; + sv.str += pos, sv.size = n; + return sv; +} + +STC_DEF csview csview_slice_ex(csview sv, intptr_t p1, intptr_t p2) { + if (p1 < 0) { + p1 += sv.size; + if (p1 < 0) p1 = 0; + } + if (p2 < 0) p2 += sv.size; + if (p2 > sv.size) p2 = sv.size; + sv.str += p1, sv.size = (p2 > p1 ? p2 - p1 : 0); + return sv; +} + +STC_DEF csview csview_token(csview sv, const char* sep, intptr_t* start) { + intptr_t sep_size = c_strlen(sep); + csview slice = {sv.str + *start, sv.size - *start}; + const char* res = cstrnstrn(slice.str, sep, slice.size, sep_size); + csview tok = {slice.str, res ? (res - slice.str) : slice.size}; + *start += tok.size + sep_size; + return tok; +} +#endif // CSVIEW_C_INCLUDED +#endif // i_implement #undef i_static #undef i_header #undef i_implement diff --git a/include/stc/forward.h b/include/stc/forward.h index 5c9c4f4d..839be012 100644 --- a/include/stc/forward.h +++ b/include/stc/forward.h @@ -39,21 +39,8 @@ #define forward_cqueue(CX, VAL) _c_cdeq_types(CX, VAL) #define forward_cvec(CX, VAL) _c_cvec_types(CX, VAL) -// csubstr : non-null terminated string view -typedef const char csubstr_value; -typedef struct csubstr { - csubstr_value* str; - intptr_t size; -} csubstr; - -typedef union { - csubstr_value* ref; - struct { csubstr chr; csubstr_value* end; } u8; -} csubstr_iter; - - -// csview : null-terminated string view -typedef csubstr_value csview_value; +// csview : non-null terminated string view +typedef const char csview_value; typedef struct csview { csview_value* str; intptr_t size; @@ -61,10 +48,23 @@ typedef struct csview { typedef union { csview_value* ref; - struct { csubstr chr; } u8; + struct { csview chr; csview_value* end; } u8; } csview_iter; +// crawstr : null-terminated string view +typedef csview_value crawstr_value; +typedef struct crawstr { + crawstr_value* str; + intptr_t size; +} crawstr; + +typedef union { + crawstr_value* ref; + struct { csview chr; } u8; +} crawstr_iter; + + // cstr : null-terminated string (short string optimized - sso) typedef char cstr_value; typedef struct { cstr_value* data; intptr_t size, cap; } cstr_buf; @@ -75,7 +75,7 @@ typedef union cstr { typedef union { cstr_value* ref; - struct { csubstr chr; } u8; + struct { csview chr; } u8; } cstr_iter; diff --git a/include/stc/priv/template.h b/include/stc/priv/template.h index 47225ec8..65dee203 100644 --- a/include/stc/priv/template.h +++ b/include/stc/priv/template.h @@ -114,10 +114,10 @@ #endif #elif defined i_key_ssv #define i_keyclass cstr - #define i_rawclass csubstr - #define i_keyfrom cstr_from_ss - #define i_keyto cstr_ss - #define i_eq csubstr_eq + #define i_rawclass csview + #define i_keyfrom cstr_from_sv + #define i_keyto cstr_sv + #define i_eq csview_eq #ifndef i_tag #define i_tag ssv #endif @@ -232,9 +232,9 @@ #define i_valraw const char* #elif defined i_val_ssv #define i_valclass cstr - #define i_valraw csubstr - #define i_valfrom cstr_from_ss - #define i_valto cstr_ss + #define i_valraw csview + #define i_valfrom cstr_from_sv + #define i_valto cstr_sv #elif defined i_valboxed #define i_valclass i_valboxed #define i_valraw c_PASTE(i_valboxed, _raw) diff --git a/include/stc/utf8.h b/include/stc/utf8.h index 7d2adee0..6d12856f 100644 --- a/include/stc/utf8.h +++ b/include/stc/utf8.h @@ -48,7 +48,7 @@ extern uint32_t utf8_toupper(uint32_t c); extern bool utf8_iscased(uint32_t c); extern bool utf8_isword(uint32_t c); extern bool utf8_valid_n(const char* s, intptr_t nbytes); -extern int utf8_icmp_ss(csubstr s1, csubstr s2); +extern int utf8_icmp_sv(csview s1, csview s2); extern int utf8_encode(char *out, uint32_t c); extern uint32_t utf8_peek_off(const char *s, int offset); @@ -92,7 +92,7 @@ STC_INLINE uint32_t utf8_peek(const char* s) { /* case-insensitive utf8 string comparison */ STC_INLINE int utf8_icmp(const char* s1, const char* s2) { - return utf8_icmp_ss(c_ss(s1, INTPTR_MAX), c_ss(s2, INTPTR_MAX)); + return utf8_icmp_sv(c_sv(s1, INTPTR_MAX), c_sv(s2, INTPTR_MAX)); } STC_INLINE bool utf8_valid(const char* s) { diff --git a/misc/benchmarks/various/string_bench_STC.cpp b/misc/benchmarks/various/string_bench_STC.cpp index 9173d4b6..a5dfd901 100644 --- a/misc/benchmarks/various/string_bench_STC.cpp +++ b/misc/benchmarks/various/string_bench_STC.cpp @@ -7,16 +7,16 @@ #define i_implement #include // string #define i_implement -#include // string_view +#include // string_view #include #define i_key_str #include // vec of cstr with const char* lookup -#define i_type cvec_ss // override default type name (cvec_csubstr) -#define i_key csubstr -#define i_cmp csubstr_cmp -#include // cvec_vs: vec of csubstr +#define i_type cvec_sv // override default type name (cvec_csview) +#define i_key csview +#define i_cmp csview_cmp +#include // cvec_vs: vec of csview #define i_key_str #define i_val size_t @@ -24,7 +24,7 @@ #define i_key_ssv #define i_val size_t -#include // sorted map of cstr, csubstr lookup +#include // sorted map of cstr, csview lookup #define i_key_str #define i_val size_t @@ -32,7 +32,7 @@ #define i_key_ssv #define i_val size_t -#include // unordered map of cstr, csubstr lookup +#include // unordered map of cstr, csview lookup cvec_str read_file(const char* name) @@ -67,7 +67,7 @@ private: std::chrono::high_resolution_clock::time_point begin; }; -void initShortStringVec(cvec_str* vs, cvec_ss* vsv) +void initShortStringVec(cvec_str* vs, cvec_sv* vsv) { cvec_str_drop(vs); cvec_sv_clear(vsv); @@ -101,14 +101,14 @@ void initShortStringVec(cvec_str* vs, cvec_ss* vsv) size_t num = 0; c_foreach (i, cvec_str, *vs) { - cvec_sv_push_back(vsv, cstr_ss(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; std::cout << "avg str len: " << num / (float)cvec_sv_size(vsv) << std::endl; } -void initLongStringVec(cvec_str* vs, cvec_ss* vsv) +void initLongStringVec(cvec_str* vs, cvec_sv* vsv) { cvec_str_drop(vs); cvec_sv_clear(vsv); @@ -147,7 +147,7 @@ void initLongStringVec(cvec_str* vs, cvec_ss* vsv) size_t num = 0; c_foreach (i, cvec_str, *vs) { - cvec_sv_push_back(vsv, cstr_ss(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; @@ -175,7 +175,7 @@ void initMaps(const cvec_str* vs, csmap_str* mapTrans, csmap_ssv* mapSview, void benchmark( const cvec_str* vec_string, - const cvec_ss* vec_stringview, + const cvec_sv* vec_stringview, const csmap_str* mapTrans, const csmap_ssv* mapSview, const cmap_str* unordmapTrans, @@ -187,7 +187,7 @@ const size_t MAX_LOOP = 2000; int main(void) { c_auto (cvec_str, vec_string) - c_auto (cvec_ss, vec_stringview) + c_auto (cvec_sv, vec_stringview) c_auto (csmap_str, mapTrans) c_auto (csmap_ssv, mapSview) c_auto (cmap_str, unordmapTrans) @@ -229,7 +229,7 @@ int main(void) void benchmark( const cvec_str* vec_string, - const cvec_ss* vec_stringview, + const cvec_sv* vec_stringview, const csmap_str* mapTrans, const csmap_ssv* mapSview, const cmap_str* unordmapTrans, @@ -258,7 +258,7 @@ void benchmark( stopwatch.start("Trans Map with string_view"); for (size_t i = 0; i < MAX_LOOP; ++i) { - c_foreach (j, cvec_ss, *vec_stringview) + c_foreach (j, cvec_sv, *vec_stringview) { const csmap_ssv_value* v = csmap_ssv_get(mapSview, *j.ref); if (v) @@ -286,7 +286,7 @@ void benchmark( stopwatch.start("Trans Unord Map with string_view"); for (size_t i = 0; i < MAX_LOOP; ++i) { - c_foreach (j, cvec_ss, *vec_stringview) + c_foreach (j, cvec_sv, *vec_stringview) { const cmap_ssv_value* v = cmap_ssv_get(unordmapSview, *j.ref); if (v) diff --git a/misc/examples/algorithms/forfilter.c b/misc/examples/algorithms/forfilter.c index d058660d..c1426045 100644 --- a/misc/examples/algorithms/forfilter.c +++ b/misc/examples/algorithms/forfilter.c @@ -2,7 +2,7 @@ #define i_import #include #define i_implement -#include +#include #include #define i_type IVec @@ -82,7 +82,7 @@ fn main() { } */ #define i_type SVec -#define i_keyclass csubstr +#define i_keyclass csview #include void demo3(void) @@ -94,11 +94,11 @@ void demo3(void) SVec words_containing_i = {0}; c_forfilter (w, SVec, words, - csubstr_contains(*w.ref, "i")) + csview_contains(*w.ref, "i")) SVec_push(&words_containing_i, *w.ref); c_foreach (w, SVec, words_containing_i) - printf(" %.*s", c_SS(*w.ref)); + printf(" %.*s", c_SV(*w.ref)); puts(""); c_drop(SVec, &words, &words_containing_i); @@ -107,10 +107,10 @@ void demo3(void) void demo4(void) { // Keep only uppercase letters and convert them to lowercase: - csubstr s = c_ss("ab123cReAghNGnΩoEp"); // Ω = multi-byte + csview s = c_sv("ab123cReAghNGnΩoEp"); // Ω = multi-byte cstr out = {0}; - c_forfilter (i, csubstr, s, utf8_isupper(utf8_peek(i.ref))) { + c_forfilter (i, csview, s, utf8_isupper(utf8_peek(i.ref))) { char chr[4]; utf8_encode(chr, utf8_tolower(utf8_peek(i.ref))); cstr_push(&out, chr); diff --git a/misc/examples/regularexpressions/regex2.c b/misc/examples/regularexpressions/regex2.c index 85890070..a798b1a1 100644 --- a/misc/examples/regularexpressions/regex2.c +++ b/misc/examples/regularexpressions/regex2.c @@ -27,7 +27,7 @@ int main(void) c_formatch (j, &re, s[i].input) { c_forrange (k, cregex_captures(&re) + 1) - printf(" submatch %lld: %.*s\n", k, c_SS(j.match[k])); + printf(" submatch %lld: %.*s\n", k, c_SV(j.match[k])); } } cregex_drop(&re); diff --git a/misc/examples/regularexpressions/regex_match.c b/misc/examples/regularexpressions/regex_match.c index 6eaea781..11426d2d 100644 --- a/misc/examples/regularexpressions/regex_match.c +++ b/misc/examples/regularexpressions/regex_match.c @@ -1,7 +1,7 @@ #define i_import #include #define i_implement -#include +#include #define i_key float #include @@ -28,7 +28,7 @@ int main(void) printf(" %g\n", (double)*i.ref); // extracts the numbers only to a comma separated string. - cstr nums = cregex_replace_ss(&re, csubstr_from(str), " $0,", 0, NULL, CREG_STRIP); + cstr nums = cregex_replace_sv(&re, csview_from(str), " $0,", 0, NULL, CREG_STRIP); printf("\n%s\n", cstr_str(&nums)); cstr_drop(&nums); diff --git a/misc/examples/regularexpressions/regex_replace.c b/misc/examples/regularexpressions/regex_replace.c index f5fd8691..f1ea2711 100644 --- a/misc/examples/regularexpressions/regex_replace.c +++ b/misc/examples/regularexpressions/regex_replace.c @@ -1,8 +1,8 @@ #define i_import #include -#include +#include -bool add_10_years(int i, csubstr match, cstr* out) { +bool add_10_years(int i, csview match, cstr* out) { if (i == 1) { // group 1 matches year int year; sscanf(match.str, "%4d", &year); // scan 4 chars only @@ -47,7 +47,7 @@ int main(void) printf("euros: %s\n", cstr_str(&str)); /* Strip out everything but the matches */ - cstr_take(&str, cregex_replace_ss(&re, csubstr_from(input), "$3.$2.$1;", 0, NULL, CREG_STRIP)); + cstr_take(&str, cregex_replace_sv(&re, csview_from(input), "$3.$2.$1;", 0, NULL, CREG_STRIP)); printf("strip: %s\n", cstr_str(&str)); /* Wrap all words in ${} */ diff --git a/misc/examples/strings/cstr_match.c b/misc/examples/strings/cstr_match.c index 3c41bd43..80013019 100644 --- a/misc/examples/strings/cstr_match.c +++ b/misc/examples/strings/cstr_match.c @@ -1,6 +1,6 @@ #define i_implement #include -#include +#include #include int main(void) @@ -16,11 +16,11 @@ int main(void) printf("ends_with: %d\n", cstr_ends_with(&ss, ".JPG")); cstr s1 = cstr_lit("hell😀 w😀rl🐨"); - csubstr ch1 = cstr_u8_chr(&s1, 7); - csubstr ch2 = cstr_u8_chr(&s1, 10); + csview ch1 = cstr_u8_chr(&s1, 7); + csview ch2 = cstr_u8_chr(&s1, 10); printf("%s\nsize: %" c_ZI ", %" c_ZI "\n", cstr_str(&s1), cstr_u8_size(&s1), cstr_size(&s1)); - printf("ch1: %.*s\n", c_SS(ch1)); - printf("ch2: %.*s\n", c_SS(ch2)); + printf("ch1: %.*s\n", c_SV(ch1)); + printf("ch2: %.*s\n", c_SV(ch2)); c_drop(cstr, &ss, &s1); } diff --git a/misc/examples/strings/replace.c b/misc/examples/strings/replace.c index 2411f1a7..59a56bf7 100644 --- a/misc/examples/strings/replace.c +++ b/misc/examples/strings/replace.c @@ -20,13 +20,13 @@ int main(void) cstr_replace_at(&s, 9, 5, s2); // "this is an example string." (1) printf("(1) %s\n", cstr_str(&s)); - cstr_replace_at_ss(&s, 19, 6, c_ss(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) printf("(3) %s\n", cstr_str(&s)); - cstr_replace_at_ss(&s, 8, 6, c_ss("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) diff --git a/misc/examples/strings/splitstr.c b/misc/examples/strings/splitstr.c index 6fa76d34..ef7ed174 100644 --- a/misc/examples/strings/splitstr.c +++ b/misc/examples/strings/splitstr.c @@ -2,20 +2,20 @@ #define i_import // cstr + utf8 functions #include #define i_implement -#include +#include int main(void) { - puts("Split with c_fortoken (csubstr):"); + puts("Split with c_fortoken (csview):"); c_fortoken (i, "Hello World C99!", " ") - printf("'%.*s'\n", c_SS(i.token)); + printf("'%.*s'\n", c_SV(i.token)); puts("\nSplit with c_formatch (regex):"); cregex re = cregex_from("[^ ]+"); c_formatch (i, &re, " Hello World C99! ") - printf("'%.*s'\n", c_SS(i.match[0])); + printf("'%.*s'\n", c_SV(i.match[0])); cregex_drop(&re); } diff --git a/misc/examples/strings/sso_substr.c b/misc/examples/strings/sso_substr.c index 2262e349..70d34440 100644 --- a/misc/examples/strings/sso_substr.c +++ b/misc/examples/strings/sso_substr.c @@ -1,20 +1,20 @@ #define i_implement #include #define i_implement -#include +#include int main(void) { cstr str = cstr_from("We think in generalities, but we live in details."); - csubstr sv1 = cstr_substr_ex(&str, 3, 5); // "think" + csview sv1 = cstr_substr_ex(&str, 3, 5); // "think" intptr_t pos = cstr_find(&str, "live"); // position of "live" - csubstr sv2 = cstr_substr_ex(&str, pos, 4); // "live" - csubstr sv3 = cstr_slice_ex(&str, -8, -1); // "details" - printf("%.*s, %.*s, %.*s\n", c_SS(sv1), c_SS(sv2), c_SS(sv3)); + csview sv2 = cstr_substr_ex(&str, pos, 4); // "live" + csview sv3 = cstr_slice_ex(&str, -8, -1); // "details" + printf("%.*s, %.*s, %.*s\n", c_SV(sv1), c_SV(sv2), c_SV(sv3)); cstr_assign(&str, "apples are green or red"); - cstr s2 = cstr_from_ss(cstr_substr_ex(&str, -3, 3)); // "red" - cstr s3 = cstr_from_ss(cstr_substr_ex(&str, 0, 6)); // "apples" + cstr s2 = cstr_from_sv(cstr_substr_ex(&str, -3, 3)); // "red" + cstr s3 = cstr_from_sv(cstr_substr_ex(&str, 0, 6)); // "apples" printf("%s %s: %d, %d\n", cstr_str(&s2), cstr_str(&s3), cstr_is_long(&str), cstr_is_long(&s2)); c_drop (cstr, &str, &s2, &s3); diff --git a/misc/examples/strings/sview_split.c b/misc/examples/strings/sview_split.c index 6abbf5e7..ac275da0 100644 --- a/misc/examples/strings/sview_split.c +++ b/misc/examples/strings/sview_split.c @@ -1,20 +1,20 @@ #define i_implement #include #define i_implement -#include +#include int main(void) { // No memory allocations or string length calculations! - const csubstr date = c_ss("2021/03/12"); + const csview date = c_sv("2021/03/12"); intptr_t pos = 0; - const csubstr year = csubstr_token(date, "/", &pos); - const csubstr month = csubstr_token(date, "/", &pos); - const csubstr day = csubstr_token(date, "/", &pos); + const csview year = csview_token(date, "/", &pos); + const csview month = csview_token(date, "/", &pos); + const csview day = csview_token(date, "/", &pos); - printf("%.*s, %.*s, %.*s\n", c_SS(year), c_SS(month), c_SS(day)); + printf("%.*s, %.*s, %.*s\n", c_SV(year), c_SV(month), c_SV(day)); - cstr y = cstr_from_ss(year), m = cstr_from_ss(month), d = cstr_from_ss(day); + cstr y = cstr_from_sv(year), m = cstr_from_sv(month), d = cstr_from_sv(day); printf("%s, %s, %s\n", cstr_str(&y), cstr_str(&m), cstr_str(&d)); c_drop(cstr, &y, &m, &d); } diff --git a/misc/examples/strings/utf8replace_c.c b/misc/examples/strings/utf8replace_c.c index 03a0442f..1d54486f 100644 --- a/misc/examples/strings/utf8replace_c.c +++ b/misc/examples/strings/utf8replace_c.c @@ -10,12 +10,12 @@ int main(void) cstr_u8_replace_at(&hello, cstr_u8_to_pos(&hello, 7), 1, - c_ss("🐨") + c_sv("🐨") ); printf("%s\n", cstr_str(&hello)); c_foreach (c, cstr, hello) - printf("%.*s,", c_SS(c.u8.chr)); + printf("%.*s,", c_SV(c.u8.chr)); cstr str = cstr_lit("scooby, dooby doo"); cstr_replace(&str, "oo", "00"); diff --git a/misc/tests/cregex_test.c b/misc/tests/cregex_test.c index 7cd03930..4e192de6 100644 --- a/misc/tests/cregex_test.c +++ b/misc/tests/cregex_test.c @@ -1,6 +1,6 @@ #define i_import #include -#include +#include #include #include "ctest.h" @@ -14,7 +14,7 @@ CTEST(cregex, compile_match_char) cregex re = cregex_from("äsdf"); ASSERT_EQ(re.error, 0); - csubstr match; + csview match; ASSERT_EQ(cregex_find(&re, inp="äsdf", &match, CREG_FULLMATCH), CREG_OK); ASSERT_EQ(M_START(match), 0); ASSERT_EQ(M_END(match), 5); // ä is two bytes wide @@ -32,7 +32,7 @@ CTEST(cregex, compile_match_anchors) cregex re = cregex_from(inp="^äs.f$"); ASSERT_EQ(re.error, 0); - csubstr match; + csview match; ASSERT_EQ(cregex_find(&re, inp="äsdf", &match), CREG_OK); ASSERT_EQ(M_START(match), 0); ASSERT_EQ(M_END(match), 5); @@ -50,7 +50,7 @@ CTEST(cregex, compile_match_quantifiers1) re = cregex_from("ä+"); ASSERT_EQ(re.error, 0); - csubstr match; + csview match; ASSERT_EQ(cregex_find(&re, inp="ääb", &match), CREG_OK); ASSERT_EQ(M_START(match), 0); ASSERT_EQ(M_END(match), 4); @@ -70,7 +70,7 @@ CTEST(cregex, compile_match_quantifiers2) re = cregex_from("bä*"); ASSERT_EQ(re.error, 0); - csubstr match; + csview match; ASSERT_EQ(cregex_find(&re, inp="bääb", &match), CREG_OK); ASSERT_EQ(M_START(match), 0); ASSERT_EQ(M_END(match), 5); @@ -90,7 +90,7 @@ CTEST(cregex, compile_match_escaped_chars) cregex re = cregex_from("\\n\\r\\t\\{"); ASSERT_EQ(re.error, 0); - csubstr match; + csview match; ASSERT_EQ(cregex_find(&re, "\n\r\t{", &match), CREG_OK); ASSERT_EQ(cregex_find(&re, "\n\r\t", &match), CREG_NOMATCH); @@ -108,7 +108,7 @@ CTEST(cregex, compile_match_class_simple) re3 = cregex_from("\\D"); ASSERT_EQ(re3.error, 0); - csubstr match; + csview match; ASSERT_EQ(cregex_find(&re1, " " , &match), CREG_OK); ASSERT_EQ(cregex_find(&re1, "\r", &match), CREG_OK); ASSERT_EQ(cregex_find(&re1, "\n", &match), CREG_OK); @@ -129,7 +129,7 @@ CTEST(cregex, compile_match_or) re = cregex_from("as|df"); ASSERT_EQ(re.error, 0); - csubstr match[4]; + csview match[4]; ASSERT_EQ(cregex_find(&re, "as", match), CREG_OK); ASSERT_EQ(cregex_find(&re, "df", match), CREG_OK); @@ -146,7 +146,7 @@ CTEST(cregex, compile_match_class_complex_0) cregex re = cregex_from("[asdf]"); ASSERT_EQ(re.error, 0); - csubstr match; + csview match; ASSERT_EQ(cregex_find(&re, "a", &match), CREG_OK); ASSERT_EQ(cregex_find(&re, "s", &match), CREG_OK); ASSERT_EQ(cregex_find(&re, "d", &match), CREG_OK); @@ -160,7 +160,7 @@ CTEST(cregex, compile_match_class_complex_1) cregex re = cregex_from("[a-zä0-9öA-Z]"); ASSERT_EQ(re.error, 0); - csubstr match; + csview match; ASSERT_EQ(cregex_find(&re, "a", &match), CREG_OK); ASSERT_EQ(cregex_find(&re, "5", &match), CREG_OK); ASSERT_EQ(cregex_find(&re, "A", &match), CREG_OK); @@ -175,7 +175,7 @@ CTEST(cregex, compile_match_cap) cregex re = cregex_from("(abc)d"); ASSERT_EQ(re.error, 0); - csubstr match[4]; + csview match[4]; ASSERT_EQ(cregex_find(&re, "abcd", match), CREG_OK); ASSERT_EQ(cregex_find(&re, "llljabcdkk", match), CREG_OK); ASSERT_EQ(cregex_find(&re, "abc", match), CREG_NOMATCH); @@ -189,7 +189,7 @@ CTEST(cregex, search_all) c_auto (cregex, re) { re = cregex_from("ab"); - csubstr m = {0}; + csview m = {0}; int res; ASSERT_EQ(re.error, CREG_OK); inp="ab,ab,ab"; @@ -220,9 +220,9 @@ CTEST(cregex, captures_cap) re = cregex_from("(ab)((cd)+)"); ASSERT_EQ(cregex_captures(&re), 3); - csubstr cap[5]; + csview cap[5]; ASSERT_EQ(cregex_find(&re, inp="xxabcdcde", cap), CREG_OK); - ASSERT_TRUE(csubstr_equals(cap[0], "abcdcd")); + ASSERT_TRUE(csview_equals(cap[0], "abcdcd")); ASSERT_EQ(M_END(cap[0]), 8); ASSERT_EQ(M_START(cap[1]), 2); @@ -235,7 +235,7 @@ CTEST(cregex, captures_cap) } } -static bool add_10_years(int i, csubstr match, cstr* out) { +static bool add_10_years(int i, csview match, cstr* out) { if (i == 1) { // group 1 matches year int year; sscanf(match.str, "%4d", &year); // scan 4 chars only @@ -280,7 +280,7 @@ CTEST(cregex, replace) ASSERT_STREQ(cstr_str(&str), "start date: 31.12.2015, end date: 28.02.2022"); // Strip out everything but the matches - cstr_take(&str, cregex_replace_ss(&re, csubstr_from(input), "$3.$2.$1;", 0, NULL, CREG_STRIP)); + cstr_take(&str, cregex_replace_sv(&re, csview_from(input), "$3.$2.$1;", 0, NULL, CREG_STRIP)); ASSERT_STREQ(cstr_str(&str), "31.12.2015;28.02.2022;"); } } diff --git a/src/cregex.c b/src/cregex.c index c045b9f3..e6da66b2 100644 --- a/src/cregex.c +++ b/src/cregex.c @@ -100,7 +100,7 @@ typedef struct _Reprog /* * Sub expression matches */ -typedef csubstr _Resub; +typedef csview _Resub; /* * substitution list @@ -1215,8 +1215,8 @@ _regexec(const _Reprog *progp, /* program to run */ static void -_build_subst(const char* replace, int nmatch, const csubstr match[], - bool (*mfun)(int, csubstr, cstr*), cstr* subst) { +_build_subst(const char* replace, int nmatch, const csview match[], + bool (*mfun)(int, csview, cstr*), cstr* subst) { cstr_buf buf = cstr_buffer(subst); intptr_t len = 0, cap = buf.cap; char* dst = buf.data; @@ -1233,7 +1233,7 @@ _build_subst(const char* replace, int nmatch, const csubstr match[], if (replace[1] >= '0' && replace[1] <= '9' && replace[2] == ';') { g = g*10 + (replace[1] - '0'); replace += 2; } if (g < nmatch) { - csubstr m = mfun && mfun(g, match[g], &mstr) ? cstr_ss(&mstr) : match[g]; + csview m = mfun && mfun(g, match[g], &mstr) ? cstr_sv(&mstr) : match[g]; if (len + m.size > cap) dst = cstr_reserve(subst, cap += cap/2 + m.size); for (int i = 0; i < m.size; ++i) @@ -1270,7 +1270,7 @@ cregex_captures(const cregex* self) { } int -cregex_find_4(const cregex* re, const char* input, csubstr match[], int mflags) { +cregex_find_4(const cregex* re, const char* input, csview match[], int mflags) { int res = _regexec(re->prog, input, cregex_captures(re) + 1, match, mflags); switch (res) { case 1: return CREG_OK; @@ -1281,7 +1281,7 @@ cregex_find_4(const cregex* re, const char* input, csubstr match[], int mflags) int cregex_find_pattern_4(const char* pattern, const char* input, - csubstr match[], int cmflags) { + csview match[], int cmflags) { cregex re = cregex_init(); int res = cregex_compile(&re, pattern, cmflags); if (res != CREG_OK) return res; @@ -1291,16 +1291,16 @@ cregex_find_pattern_4(const char* pattern, const char* input, } cstr -cregex_replace_ss_6(const cregex* re, csubstr input, const char* replace, int count, - bool (*mfun)(int, csubstr, cstr*), int rflags) { +cregex_replace_sv_6(const cregex* re, csview input, const char* replace, int count, + bool (*mfun)(int, csview, cstr*), int rflags) { cstr out = cstr_init(); cstr subst = cstr_init(); - csubstr match[CREG_MAX_CAPTURES]; + csview match[CREG_MAX_CAPTURES]; int nmatch = cregex_captures(re) + 1; if (!count) count = INT32_MAX; bool copy = !(rflags & CREG_STRIP); - while (count-- && cregex_find_ss(re, input, match) == CREG_OK) { + while (count-- && cregex_find_sv(re, input, match) == CREG_OK) { _build_subst(replace, nmatch, match, mfun, &subst); const intptr_t mpos = (match[0].str - input.str); if (copy & (mpos > 0)) cstr_append_n(&out, input.str, mpos); @@ -1308,19 +1308,19 @@ cregex_replace_ss_6(const cregex* re, csubstr input, const char* replace, int co input.str = match[0].str + match[0].size; input.size -= mpos + match[0].size; } - if (copy) cstr_append_ss(&out, input); + if (copy) cstr_append_sv(&out, input); cstr_drop(&subst); return out; } cstr cregex_replace_pattern_6(const char* pattern, const char* input, const char* replace, int count, - bool (*mfun)(int, csubstr, cstr*), int crflags) { + bool (*mfun)(int, csview, cstr*), int crflags) { cregex re = cregex_init(); if (cregex_compile(&re, pattern, crflags) != CREG_OK) assert(0); - csubstr ss = c_ss(input, c_strlen(input)); - cstr out = cregex_replace_ss(&re, ss, replace, count, mfun, crflags); + csview sv = c_sv(input, c_strlen(input)); + cstr out = cregex_replace_sv(&re, sv, replace, count, mfun, crflags); cregex_drop(&re); return out; } diff --git a/src/libstc.c b/src/libstc.c index b0d27350..462c97c4 100644 --- a/src/libstc.c +++ b/src/libstc.c @@ -1,7 +1,7 @@ #define i_import #include "../include/stc/cregex.h" /* cstr. utf8, and cregex */ #define i_implement -#include "../include/stc/csubstr.h" +#include "../include/stc/csview.h" #define i_implement #include "../include/stc/crand.h" #if __STDC_VERSION__ >= 201112L diff --git a/src/singleupdate.sh b/src/singleupdate.sh index be99d4a7..8c2bba45 100644 --- a/src/singleupdate.sh +++ b/src/singleupdate.sh @@ -22,8 +22,8 @@ python singleheader.py $d/include/stc/cspan.h $d/../stcsingle/stc/cspan.h python singleheader.py $d/include/stc/csset.h $d/../stcsingle/stc/csset.h python singleheader.py $d/include/stc/cstack.h $d/../stcsingle/stc/cstack.h python singleheader.py $d/include/stc/cstr.h $d/../stcsingle/stc/cstr.h -python singleheader.py $d/include/stc/csubstr.h $d/../stcsingle/stc/csubstr.h python singleheader.py $d/include/stc/csview.h $d/../stcsingle/stc/csview.h +python singleheader.py $d/include/stc/crawstr.h $d/../stcsingle/stc/crawstr.h python singleheader.py $d/include/stc/cvec.h $d/../stcsingle/stc/cvec.h python singleheader.py $d/include/stc/extend.h $d/../stcsingle/stc/extend.h python singleheader.py $d/include/stc/forward.h $d/../stcsingle/stc/forward.h diff --git a/src/utf8code.c b/src/utf8code.c index ddc4cb97..4abf10ea 100644 --- a/src/utf8code.c +++ b/src/utf8code.c @@ -101,7 +101,7 @@ uint32_t utf8_toupper(uint32_t c) { return c; } -int utf8_icmp_ss(const csubstr s1, const csubstr s2) { +int utf8_icmp_sv(const csview s1, const csview s2) { utf8_decode_t d1 = {.state=0}, d2 = {.state=0}; intptr_t j1 = 0, j2 = 0; while ((j1 < s1.size) & (j2 < s2.size)) { -- cgit v1.2.3