summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorTyge Lovset <[email protected]>2022-05-29 00:36:08 +0200
committerTyge Lovset <[email protected]>2022-05-29 00:42:06 +0200
commita341dbc0ce456198d5773c7260e93e8433228ee2 (patch)
tree7759f0cf00201b348bb90868e4553aaed0e3c98e
parent06c8dffeb571a3aa6143425704062de4aa879d2c (diff)
downloadSTC-modified-a341dbc0ce456198d5773c7260e93e8433228ee2.tar.gz
STC-modified-a341dbc0ce456198d5773c7260e93e8433228ee2.zip
Renamed cstr_replace_first() => cstr_replace_one().
cstr.h now #include "utf8.h". Added iterator (utf8) to cstr and other utf8 functions postfixed by _u8(). Also renamed some utf8 functions in csview to better names.
-rw-r--r--docs/cstr_api.md9
-rw-r--r--docs/csview_api.md22
-rw-r--r--examples/cstr_match.c7
-rw-r--r--examples/demos.c2
-rw-r--r--examples/replace.c1
-rw-r--r--examples/utf8replace_c.c16
-rw-r--r--include/stc/ccommon.h2
-rw-r--r--include/stc/cstr.h50
-rw-r--r--include/stc/csview.h19
-rw-r--r--include/stc/forward.h9
-rw-r--r--include/stc/utf8.h29
11 files changed, 118 insertions, 48 deletions
diff --git a/docs/cstr_api.md b/docs/cstr_api.md
index 5570df8e..4d68807c 100644
--- a/docs/cstr_api.md
+++ b/docs/cstr_api.md
@@ -38,6 +38,15 @@ size_t cstr_length(cstr s);
size_t cstr_capacity(cstr s);
bool cstr_empty(cstr s);
+// utf8:
+size_t cstr_size_u8(cstr s); // utf8 size
+size_t cstr_size_n_u8(cstr s, size_t nbytes); // utf8 size within n bytes
+csview cstr_at(const cstr* self, size_t bytepos); // utf8 character as a csview
+csview cstr_at_u8(const cstr* self, size_t u8idx); // utf8 character at utf8 pos
+size_t cstr_pos_u8(const cstr* self, size_t u8idx); // byte position at utf8 index
+bool cstr_valid_u8(const cstr* self); // check if str is valid utf8
+utf8_decode_t cstr_peek(const cstr* self, size_t bytepos);
+
size_t cstr_reserve(cstr* self, size_t capacity);
void cstr_resize(cstr* self, size_t len, char fill);
void cstr_shrink_to_fit(cstr* self);
diff --git a/docs/csview_api.md b/docs/csview_api.md
index 112ca0eb..4c92a1e5 100644
--- a/docs/csview_api.md
+++ b/docs/csview_api.md
@@ -57,20 +57,21 @@ void csview_next(csview_iter* it); // NB: UTF8
#### UTF8 methods
```
-bool utf8_valid_sv(csview sv);
-size_t utf8_size_sv(csview sv);
-csview utf8_substr(const char* str, size_t pos, size_t n);
+bool csview_valid_u8(csview sv);
+size_t csview_size_u8(csview sv);
+csview csview_substr_u8(csview sv, size_t u8pos, size_t u8len);
bool utf8_valid(const char* s);
+bool utf8_valid_n(const char* s, size_t n);
size_t utf8_size(const char *s);
size_t utf8_size_n(const char *s, size_t n); // number of UTF8 codepoints within n bytes
const char* utf8_at(const char *s, size_t index); // from UTF8 index to char* position
size_t utf8_pos(const char* s, size_t index); // from UTF8 index to byte index position
-const char* utf8_next(const char *s); // next codepoint as char*; NULL if *s == 0
-uint32_t utf8_peek(const char *s); // next codepoint as uint32_t
-
-size_t utf8_codep_size(const char* s); // 1-4 (0 if s[0] is illegal first cp char)
-uint32_t utf8_decode(uint32_t *state, uint32_t *codep, const uint32_t byte); // decode next utf8 codepoint.
+unsigned utf8_codep_size(const char* s); // 0-4 (0 if s[0] is illegal utf8)
+void utf8_peek(const char *s, utf8_decode_t* d); // next codepoint as uint32_t
+uint32_t utf8_decode(utf8_decode_t *d, uint8_t byte, // d holds state, size and unicode point
+ const uint32_t byte); // decode next utf8 codepoint.
+unsigned utf8_encode(char *out, uint32_t cp); // encode unicode cp into out
```
#### Extended cstr methods
@@ -159,9 +160,8 @@ int main()
cstr_replace_sv(&s1, utf8_substr(cstr_str(&s1), 7, 1), c_sv("x"));
printf("%s\n", cstr_str(&s1));
- csview sv = csview_from_s(&s1);
- c_foreach (i, csview, sv)
- printf("%" c_PRIsv ",", c_ARGsv(i.codep));
+ c_foreach (i, cstr, s1)
+ printf("%" c_PRIsv ",", c_ARGsv(i.chr));
}
}
```
diff --git a/examples/cstr_match.c b/examples/cstr_match.c
index cd3f04be..637fa7f9 100644
--- a/examples/cstr_match.c
+++ b/examples/cstr_match.c
@@ -1,4 +1,5 @@
#include <stc/cstr.h>
+#include <stc/csview.h>
#include <stdio.h>
int main()
@@ -11,5 +12,11 @@ int main()
printf("starts_with: %d\n", cstr_starts_with(ss, "The quick brown"));
printf("ends_with: %d\n", cstr_ends_with(ss, ".jpg"));
printf("ends_with: %d\n", cstr_ends_with(ss, ".JPG"));
+
+ cstr s1 = cstr_new("hell😀 w😀rl🐨");
+ csview ch1 = cstr_at(&s1, 10);
+ csview ch2 = cstr_at_u8(&s1, 10);
+ printf("ch1: %" c_PRIsv "\n", c_ARGsv(ch1));
+ printf("ch2: %" c_PRIsv "\n", c_ARGsv(ch2));
}
}
diff --git a/examples/demos.c b/examples/demos.c
index 99b9e570..c0cecac2 100644
--- a/examples/demos.c
+++ b/examples/demos.c
@@ -13,7 +13,7 @@ void stringdemo1()
cstr_erase_n(&cs, 7, 5); // -nine
printf("%s.\n", cstr_str(&cs));
- cstr_replace_first(&cs, 0, "seven", "four");
+ cstr_replace_one(&cs, 0, "seven", "four");
printf("%s.\n", cstr_str(&cs));
cstr_take(&cs, cstr_from_fmt("%s *** %s", cstr_str(&cs), cstr_str(&cs)));
diff --git a/examples/replace.c b/examples/replace.c
index a5bcf4d3..f658fb3c 100644
--- a/examples/replace.c
+++ b/examples/replace.c
@@ -1,6 +1,5 @@
#include <stc/cstr.h>
-#include <stc/utf8.h>
int main ()
{
diff --git a/examples/utf8replace_c.c b/examples/utf8replace_c.c
index 6b3fcebe..89d5375f 100644
--- a/examples/utf8replace_c.c
+++ b/examples/utf8replace_c.c
@@ -1,21 +1,23 @@
#include <stc/cstr.h>
#include <stc/csview.h>
-#include <stc/utf8.h>
int main() {
c_auto (cstr, hello) {
- hello = cstr_new("hell😀 world");
+ hello = cstr_new("hell😀 w😀rld");
printf("%s\n", cstr_str(&hello));
cstr_replace_sv(
- &hello,
- utf8_substr(cstr_str(&hello), 4, 1),
+ &hello,
+ csview_substr_u8(cstr_sv(&hello), 7, 1),
c_sv("🐨")
);
printf("%s\n", cstr_str(&hello));
- csview sv = csview_from_s(&hello);
- c_foreach (c, csview, sv)
- printf("%" c_PRIsv ",", c_ARGsv(c.codep));
+ cstr_replace_one(&hello, 0, "🐨", "ø");
+ printf("%s\n", cstr_str(&hello));
+
+ c_foreach (c, cstr, hello)
+ printf("%" c_PRIsv ",", c_ARGsv(c.chr));
+ puts("");
}
}
diff --git a/include/stc/ccommon.h b/include/stc/ccommon.h
index a0fa58fb..46d53bc1 100644
--- a/include/stc/ccommon.h
+++ b/include/stc/ccommon.h
@@ -117,6 +117,8 @@ typedef const char* crawstr;
#define crawstr_hash(p) c_strhash(*(p))
#define c_strlen_lit(literal) (sizeof "" literal - 1U)
#define c_sv(lit) c_make(csview){lit, c_strlen_lit(lit)}
+#define c_PRIsv ".*s"
+#define c_ARGsv(sv) (int)(sv).size, (sv).str
#define _c_ROTL(x, k) (x << (k) | x >> (8*sizeof(x) - (k)))
diff --git a/include/stc/cstr.h b/include/stc/cstr.h
index ca6d9392..1d57437e 100644
--- a/include/stc/cstr.h
+++ b/include/stc/cstr.h
@@ -32,6 +32,7 @@
#include "ccommon.h"
#include "forward.h"
+#include "utf8.h"
#include <stdlib.h> /* malloc */
#include <stdarg.h>
#include <stdio.h> /* vsnprintf */
@@ -168,6 +169,53 @@ STC_INLINE size_t cstr_length(cstr s)
STC_INLINE size_t cstr_capacity(cstr s)
{ return cstr_is_long(&s) ? cstr_l_cap(&s) : cstr_s_cap; }
+// utf8:
+
+STC_INLINE size_t cstr_size_u8(cstr s)
+ { return utf8_size(cstr_str(&s)); }
+
+STC_INLINE size_t cstr_size_n_u8(cstr s, size_t nbytes)
+ { return utf8_size_n(cstr_str(&s), nbytes); }
+
+STC_INLINE csview cstr_at(const cstr* self, size_t bytepos) {
+ csview sv = cstr_sv(self);
+ sv.str += bytepos;
+ sv.size = utf8_codep_size(sv.str);
+ return sv;
+}
+STC_INLINE csview cstr_at_u8(const cstr* self, size_t u8idx) {
+ csview sv = cstr_sv(self);
+ sv.str = utf8_at(sv.str, u8idx);
+ sv.size = utf8_codep_size(sv.str);
+ return sv;
+}
+
+STC_INLINE size_t cstr_pos_u8(const cstr* self, size_t u8idx)
+ { return utf8_pos(cstr_str(self), u8idx); }
+
+STC_INLINE bool cstr_valid_u8(const cstr* self)
+ { return utf8_valid(cstr_str(self)); }
+
+STC_INLINE utf8_decode_t cstr_peek(const cstr* self, size_t bytepos) {
+ utf8_decode_t d = {UTF8_OK};
+ utf8_peek(cstr_str(self) + bytepos, &d);
+ return d;
+}
+
+STC_INLINE cstr_iter cstr_begin(const cstr* self) {
+ const char* str = cstr_str(self);
+ return c_make(cstr_iter){.chr = {str, utf8_codep_size(str)}};
+}
+STC_INLINE cstr_iter cstr_end(const cstr* self) {
+ csview sv = cstr_sv(self);
+ return c_make(cstr_iter){sv.str + sv.size};
+}
+STC_INLINE void cstr_next(cstr_iter* it) {
+ it->ref += it->chr.size;
+ it->chr.size = utf8_codep_size(it->ref);
+}
+
+
STC_INLINE void cstr_clear(cstr* self)
{ _cstr_set_size(self, 0); }
@@ -250,7 +298,7 @@ STC_INLINE void cstr_replace_n(cstr* self, size_t pos, size_t len, const char* r
STC_INLINE void cstr_replace(cstr* self, size_t pos, size_t len, const char* repl)
{ cstr_replace_n(self, pos, len, repl, strlen(repl)); }
-STC_INLINE size_t cstr_replace_first(cstr* self, size_t pos, const char* search, const char* repl) {
+STC_INLINE size_t cstr_replace_one(cstr* self, size_t pos, const char* search, const char* repl) {
pos = cstr_find_from(*self, pos, search);
if (pos == cstr_npos)
return pos;
diff --git a/include/stc/csview.h b/include/stc/csview.h
index 5bc25215..270a79f8 100644
--- a/include/stc/csview.h
+++ b/include/stc/csview.h
@@ -30,8 +30,6 @@
#define csview_null c_sv("")
#define csview_new(literal) c_sv(literal)
#define csview_npos (SIZE_MAX >> 1)
-#define c_PRIsv ".*s"
-#define c_ARGsv(sv) (int)(sv).size, (sv).str
STC_API csview csview_substr(csview sv, intptr_t pos, size_t n);
STC_API csview csview_slice(csview sv, intptr_t p1, intptr_t p2);
@@ -64,23 +62,22 @@ STC_INLINE bool csview_ends_with(csview sv, csview sub)
{ if (sub.size > sv.size) return false;
return !memcmp(sv.str + sv.size - sub.size, sub.str, sub.size); }
STC_INLINE csview_iter csview_begin(const csview* self)
- { return c_make(csview_iter){.codep = {self->str, utf8_codep_size(self->str)}}; }
+ { return c_make(csview_iter){.chr = {self->str, utf8_codep_size(self->str)}}; }
STC_INLINE csview_iter csview_end(const csview* self)
{ return c_make(csview_iter){self->str + self->size}; }
STC_INLINE void csview_next(csview_iter* it)
- { it->ref += it->codep.size; it->codep.size = utf8_codep_size(it->ref); }
+ { it->ref += it->chr.size; it->chr.size = utf8_codep_size(it->ref); }
/* utf8 */
-STC_INLINE bool utf8_valid_sv(csview sv)
- { return utf8_size_n(sv.str, sv.size) != SIZE_MAX; }
+STC_INLINE bool csview_valid_u8(csview sv)
+ { return utf8_valid_n(sv.str, sv.size); }
-STC_INLINE size_t utf8_size_sv(csview sv)
+STC_INLINE size_t csview_size_u8(csview sv)
{ return utf8_size_n(sv.str, sv.size); }
-STC_INLINE csview utf8_substr(const char* str, size_t pos, size_t n) {
- csview sv;
- sv.str = utf8_at(str, pos);
- sv.size = utf8_pos(sv.str, n);
+STC_INLINE csview csview_substr_u8(csview sv, size_t u8pos, size_t u8len) {
+ sv.str = utf8_at(sv.str, u8pos);
+ sv.size = utf8_pos(sv.str, u8len);
return sv;
}
diff --git a/include/stc/forward.h b/include/stc/forward.h
index 635c63df..67f5f0f2 100644
--- a/include/stc/forward.h
+++ b/include/stc/forward.h
@@ -45,7 +45,7 @@
typedef struct { char* data; size_t size, cap; } cstr_buf;
typedef char cstr_value;
#if defined STC_CSTR_V1
- typedef struct cstr { char* str; } cstr;
+ typedef struct { char* str; } cstr;
#else
typedef union {
struct { char data[sizeof(cstr_buf) - 1]; unsigned char last; } sml;
@@ -53,9 +53,12 @@ typedef char cstr_value;
} cstr;
#endif
-typedef struct csview { const char* str; size_t size; } csview;
-typedef union csview_iter { const char *ref; csview codep; } csview_iter;
+typedef struct { const char* str; size_t size; } csview;
typedef char csview_value;
+typedef union {
+ const char *ref;
+ csview chr;
+} csview_iter, cstr_iter;
#define c_true(...) __VA_ARGS__
#define c_false(...)
diff --git a/include/stc/utf8.h b/include/stc/utf8.h
index 02f24711..f11af046 100644
--- a/include/stc/utf8.h
+++ b/include/stc/utf8.h
@@ -13,9 +13,8 @@ int main()
cstr_replace_sv(&s1, utf8_substr(cstr_str(&s1), 7, 1), c_sv("🐨"));
printf("%s\n", cstr_str(&s1));
- csview sv = csview_from_s(s1);
- c_foreach (i, csview, sv)
- printf("%" c_PRIsv ",", c_ARGsv(i.codep));
+ c_foreach (i, cstr, s1)
+ printf("%" c_PRIsv ",", c_ARGsv(i.chr));
}
}
// Output:
@@ -54,19 +53,16 @@ STC_INLINE const char* utf8_at(const char *s, size_t index) {
return s;
}
-STC_INLINE size_t utf8_pos(const char* s, size_t index)
+STC_INLINE size_t utf8_pos(const char* s, size_t index)
{ return utf8_at(s, index) - s; }
-STC_INLINE uint32_t utf8_peek(const char *s, unsigned* codep_size) {
- utf8_decode_t d = {UTF8_OK};
- utf8_decode(&d, (uint8_t)*s++);
- switch (d.size) {
- case 4: utf8_decode(&d, (uint8_t)*s++);
- case 3: utf8_decode(&d, (uint8_t)*s++);
- case 2: utf8_decode(&d, (uint8_t)*s++);
+STC_INLINE void utf8_peek(const char *s, utf8_decode_t* d) {
+ utf8_decode(d, (uint8_t)*s++);
+ switch (d->size) {
+ case 4: utf8_decode(d, (uint8_t)*s++);
+ case 3: utf8_decode(d, (uint8_t)*s++);
+ case 2: utf8_decode(d, (uint8_t)*s++);
}
- *codep_size = d.size;
- return d.codep;
}
STC_INLINE unsigned utf8_codep_size(const char *s) {
@@ -82,6 +78,13 @@ STC_INLINE bool utf8_valid(const char* s) {
return d.state == UTF8_OK;
}
+STC_INLINE bool utf8_valid_n(const char* s, size_t n) {
+ utf8_decode_t d = {UTF8_OK};
+ while ((n-- != 0) & (*s != 0))
+ utf8_decode(&d, (uint8_t)*s++);
+ return d.state == UTF8_OK;
+}
+
// --------------------------- IMPLEMENTATION ---------------------------------
#ifdef i_implement
// https://news.ycombinator.com/item?id=15423674