From 540d71ee3cfe9e4a01297655f84062d8b8a6b3da Mon Sep 17 00:00:00 2001 From: Gregory Lirent Date: Thu, 2 Jun 2022 15:53:09 +0300 Subject: [PATCH] Add string --- include/extra/string.h | 27 ++++ include/string.h | 114 +++++++++++++++++ src/string/base.c | 126 +++++++++++++++++++ src/string/extra-split.c | 89 ++++++++++++++ src/string/extra.c | 177 ++++++++++++++++++++++++++ src/string/get.c | 172 ++++++++++++++++++++++++++ src/string/include.h | 59 +++++++++ src/string/internal.c | 21 ++++ src/string/replace.c | 105 ++++++++++++++++ src/string/trim.c | 259 +++++++++++++++++++++++++++++++++++++++ 10 files changed, 1149 insertions(+) create mode 100644 include/extra/string.h create mode 100644 include/string.h create mode 100644 src/string/base.c create mode 100644 src/string/extra-split.c create mode 100644 src/string/extra.c create mode 100644 src/string/get.c create mode 100644 src/string/include.h create mode 100644 src/string/internal.c create mode 100644 src/string/replace.c create mode 100644 src/string/trim.c diff --git a/include/extra/string.h b/include/extra/string.h new file mode 100644 index 0000000..bae4168 --- /dev/null +++ b/include/extra/string.h @@ -0,0 +1,27 @@ +/* This software is licensed by the MIT License, see LICENSE file */ +/* Copyright © 2022 Gregory Lirent */ + +#include "../string.h" + +#ifndef LIBCDSB_EXTRA_STRING_H +#define LIBCDSB_EXTRA_STRING_H + +#define string_split(x, sep, maxn) _LIBCDSB_GenericS(libcdsb_string, split, sep)(x, sep, maxn) +#define string_case_compare string_compare_case_insensitive + +extern size_t string_to_lower (vtype_string* x) LIBCDSB_nt__ LIBCDSB_nn1__; +extern size_t string_to_upper (vtype_string* x) LIBCDSB_nt__ LIBCDSB_nn1__; +extern size_t string_capitalize(vtype_string* x) LIBCDSB_nt__ LIBCDSB_nn1__; + + +extern int string_compare_case_insensitive(const vtype_string* s0, const vtype_string* s1) LIBCDSB_cmpattr__; + +inline vtype_array libcdsb_string_split_string (const vtype_string* x, const vtype_string* sep, size_t maxn) __attribute__((always_inline)); +extern vtype_array libcdsb_string_split_cstring(const vtype_string* string, const char* sep, size_t maxn) LIBCDSB_nt__ LIBCDSB_nn1__; +extern vtype_array libcdsb_string_split_char (const vtype_string* string, int chr, size_t maxn) LIBCDSB_nt__ LIBCDSB_nn1__; + +inline vtype_array libcdsb_string_split_string(const vtype_string* x, const vtype_string* sep, size_t maxn) { + return string_split(x, sep->buffer, maxn); +} + +#endif /* LIBCDSB_EXTRA_STRING_H */ diff --git a/include/string.h b/include/string.h new file mode 100644 index 0000000..3229279 --- /dev/null +++ b/include/string.h @@ -0,0 +1,114 @@ +/* This software is licensed by the MIT License, see LICENSE file */ +/* Copyright © 2022 Gregory Lirent */ + +#include "__generics.h" +#include "vtype.h" +#include + +#ifndef LIBCDSB_STRING_H +#define LIBCDSB_STRING_H + +extern void string_init(vtype_string* x, const char* value) LIBCDSB_nt__ LIBCDSB_nn1__; + +extern char* string_at(const vtype_string* s, ssize_t index) LIBCDSB_nt__ LIBCDSB_nn1__; +extern _Bool string_slice(vtype_string* x, vtype_string* s, ssize_t index, size_t nchars, _Bool cut) LIBCDSB_nt__ LIBCDSB_nn12__; + + +#define string_indexof(s, arg) _LIBCDSB_GenericS(libcdsb_string, indexof, arg)(s, arg) +#define string_count(s, arg) _LIBCDSB_GenericS(libcdsb_string, count, arg)(s, arg) +#define string_concat(s, value) _LIBCDSB_GenericS(libcdsb_string, concat, value)(s, value) + + +#define string_trim(x, arg) _LIBCDSB_GenericS(libcdsb_string, trim, arg)(x, arg) +#define string_ltrim(x, arg) _LIBCDSB_GenericS(libcdsb_string, ltrim, arg)(x, arg) +#define string_rtrim(x, arg) _LIBCDSB_GenericS(libcdsb_string, rtrim, arg)(x, arg) + +#define string_replace(x, src, dest, maxn) _LIBCDSB_GenericS2(libcdsb_string, replace, src, dest)(x, src, dest, maxn) + + + + + + + +inline ssize_t libcdsb_string_indexof_string (const vtype_string* s, const vtype_string* arg) __attribute__((always_inline)); +extern ssize_t libcdsb_string_indexof_cstring(const vtype_string* s, const char* arg) LIBCDSB_pure__ LIBCDSB_nn1__; +extern ssize_t libcdsb_string_indexof_char (const vtype_string* s, int arg) LIBCDSB_pure__ LIBCDSB_nn1__; + +inline size_t libcdsb_string_count_string (const vtype_string* s, const vtype_string* arg) __attribute__((always_inline)); +extern size_t libcdsb_string_count_cstring(const vtype_string* s, const char* arg) LIBCDSB_pure__ LIBCDSB_nn1__; +extern size_t libcdsb_string_count_char (const vtype_string* s, int arg) LIBCDSB_pure__ LIBCDSB_nn1__; + +inline _Bool libcdsb_string_concat_string (vtype_string* x, const vtype_string* value) __attribute__((always_inline)); +extern _Bool libcdsb_string_concat_cstring(vtype_string* x, const char* value) LIBCDSB_nt__ LIBCDSB_nn1__; +extern _Bool libcdsb_string_concat_char (vtype_string* x, int value) LIBCDSB_nt__ LIBCDSB_nn1__; + +inline void libcdsb_string_trim_string (vtype_string* x, const vtype_string* arg) __attribute__((always_inline)); +extern void libcdsb_string_trim_cstring (vtype_string* x, const char* arg) LIBCDSB_nt__ LIBCDSB_nn1__; +extern void libcdsb_string_trim_char (vtype_string* x, int arg) LIBCDSB_nt__ LIBCDSB_nn1__; + +inline void libcdsb_string_ltrim_string (vtype_string* x, const vtype_string* arg) __attribute__((always_inline)); +extern void libcdsb_string_ltrim_cstring(vtype_string* x, const char* arg) LIBCDSB_nt__ LIBCDSB_nn1__; +extern void libcdsb_string_ltrim_char (vtype_string* x, int arg) LIBCDSB_nt__ LIBCDSB_nn1__; + +inline void libcdsb_string_rtrim_string (vtype_string* x, const vtype_string* arg) __attribute__((always_inline)); +extern void libcdsb_string_rtrim_cstring(vtype_string* x, const char* arg) LIBCDSB_nt__ LIBCDSB_nn1__; +extern void libcdsb_string_rtrim_char (vtype_string* x, int arg) LIBCDSB_nt__ LIBCDSB_nn1__; + + +inline size_t libcdsb_string_replace_string_string (vtype_string* x, const vtype_string* src, const vtype_string* dest, size_t maxn) __attribute__((always_inline)); +inline size_t libcdsb_string_replace_string_cstring (vtype_string* x, const vtype_string* src, const char* dest, size_t maxn) __attribute__((always_inline)); +inline size_t libcdsb_string_replace_string_char (vtype_string* x, const vtype_string* src, int dest, size_t maxn) __attribute__((always_inline)); +inline size_t libcdsb_string_replace_cstring_string (vtype_string* x, const char* src, const vtype_string* dest, size_t maxn) __attribute__((always_inline)); +extern size_t libcdsb_string_replace_cstring_cstring(vtype_string* string, const char* src, const char* dest, size_t maxn) LIBCDSB_nt__ LIBCDSB_nn1__; +extern size_t libcdsb_string_replace_cstring_char (vtype_string* string, const char* src, int dest, size_t maxn) LIBCDSB_nt__ LIBCDSB_nn1__; +inline size_t libcdsb_string_replace_char_string (vtype_string* x, int src, const vtype_string* dest, size_t maxn) __attribute__((always_inline)); +extern size_t libcdsb_string_replace_char_cstring (vtype_string* string, int src, const char* dest, size_t maxn) LIBCDSB_nt__ LIBCDSB_nn1__; +extern size_t libcdsb_string_replace_char_char (vtype_string* string, int src, int dest, size_t maxn) LIBCDSB_nt__ LIBCDSB_nn1__; + + +inline ssize_t libcdsb_string_indexof_string(const vtype_string* s, const vtype_string* arg) { + return string_indexof(s, arg->buffer); +} + +inline size_t libcdsb_string_count_string(const vtype_string* s, const vtype_string* arg) { + return string_count(s, arg->buffer); +} + +inline _Bool libcdsb_string_concat_string(vtype_string* x, const vtype_string* s) { + return string_concat(x, s->buffer); +} + +inline void libcdsb_string_trim_string (vtype_string* x, const vtype_string* s) { + return string_trim (x, s->buffer); +} + +inline void libcdsb_string_ltrim_string (vtype_string* x, const vtype_string* s) { + return string_ltrim(x, s->buffer); +} + +inline void libcdsb_string_rtrim_string (vtype_string* x, const vtype_string* s) { + return string_rtrim(x, s->buffer); +} + +inline size_t libcdsb_string_replace_string_string (vtype_string* x, const vtype_string* src, const vtype_string* dest, size_t maxn) { + return string_replace(x, src->buffer, dest->buffer, maxn); +} + +inline size_t libcdsb_string_replace_string_cstring(vtype_string* x, const vtype_string* src, const char* dest, size_t maxn) { + return string_replace(x, src->buffer, dest, maxn); +} + +inline size_t libcdsb_string_replace_cstring_string(vtype_string* x, const char* src, const vtype_string* dest, size_t maxn) { + return string_replace(x, src, dest->buffer, maxn); +} + +inline size_t libcdsb_string_replace_string_char (vtype_string* x, const vtype_string* src, int dest, size_t maxn) { + return string_replace(x, src->buffer, dest, maxn); +} + +inline size_t libcdsb_string_replace_char_string (vtype_string* x, int src, const vtype_string* dest, size_t maxn) { + return string_replace(x, src, dest->buffer, maxn); +} + +#endif /* LIBCDSB_BASE_STRING_H */ diff --git a/src/string/base.c b/src/string/base.c new file mode 100644 index 0000000..55f5ee5 --- /dev/null +++ b/src/string/base.c @@ -0,0 +1,126 @@ +/* This software is licensed by the MIT License, see LICENSE file */ +/* Copyright © 2022 Gregory Lirent */ + +#include "include.h" + +size_t string_nmemb(const str_t* s) { + return (!is_null(s->buffer)) ? strlen(s->buffer) : 0; +} + + +size_t string_size(const str_t* s) { + size_t n; + char* p; + + if (is_null(s->buffer) || !*s->buffer) + return 0; + + n = strasciilen(s->buffer); + p = s->buffer + n; + + while (*p) { + p = next_char(p); + ++n; + } + + return n; +} + + +void string_init(str_t* x, const char* s) { + size_t n = (!is_null(s)) ? strlen(s) : 0; + + if (n) x->buffer = strndup(s, n); + else memset(x, 0, sizeof(*x)); +} + + +void string_free(str_t* x) { + free(x->buffer); + memset(x, 0, sizeof(*x)); +} + + +int string_compare(const str_t* s0, const str_t* s1) { + ssize_t n0, n1; + + if (s0 == s1) return 0; + + n0 = (!is_null(s0->buffer)) ? strlen(s0->buffer) : 0; + n1 = (!is_null(s1->buffer)) ? strlen(s1->buffer) : 0; + + n0 -= n1; + + if (n0 || !n1) return n0; + + return memcmp(s0->buffer, s1->buffer, n1); +} + + +/*#####################################################################################################################*/ + + +_Bool string_concat_cstring(str_t* x, const char* s) { + size_t n; + size_t xn; + + if ((n = (!is_null(s)) ? strlen(s) : 0)) { + xn = (!is_null(x->buffer)) ? strlen(x->buffer) : 0; + + x->buffer = realloc(x->buffer, xn + ++n); + memcpy(x->buffer + xn, s, n); + + return true; + } + + return false; +} + + +_Bool string_concat_char(str_t* x, int chr) { + size_t xn; + size_t n; + char *e; + char s[5] = {0}; + + if (!is_null(e = tochar_unicode(s, chr))) { + xn = (!is_null(x->buffer)) ? strlen(x->buffer) : 0; + n = e - s; + + x->buffer = realloc(x->buffer, xn + ++n); + memcpy(x->buffer + xn, s, n); + + return true; + } + + return false; +} + + +/*#####################################################################################################################*/ + + +str_t string_copy(const str_t* s) { + str_t x = { .buffer = 0 }; + size_t n = (!is_null(s->buffer)) ? strlen(s->buffer) : 0; + + if (n) x.buffer = strndup(s->buffer, n); + return x; +} + + +str_t* string_duplicate(const str_t* s) { + str_t* x = calloc(sizeof(*x), 1); + size_t n = (!is_null(s->buffer)) ? strlen(s->buffer) : 0; + + if (n) x->buffer = strndup(s->buffer, n); + return x; +} + + +void string_copy_init(str_t* x, const str_t* s) { + size_t n = (!is_null(s->buffer)) ? strlen(s->buffer) : 0; + + if (n) x->buffer = strndup(s->buffer, n); + else memset(x, 0, sizeof(*x)); +} diff --git a/src/string/extra-split.c b/src/string/extra-split.c new file mode 100644 index 0000000..655e067 --- /dev/null +++ b/src/string/extra-split.c @@ -0,0 +1,89 @@ +/* This software is licensed by the MIT License, see LICENSE file */ +/* Copyright © 2022 Gregory Lirent */ + +#include "include.h" + +arr_t string_split_cstring(const str_t* s, const char* a, size_t maxn) { + arr_t x = { .mem = 0, .size = 0, .type = VTYPE_STRING }; + + size_t n; + char* p; + char* e; + str_t* v; + + if (is_null(s->buffer)) { + return x; + } + + if (is_null(a) || !*a) { + v = x.mem = malloc(sizeof(str_t)); + v->buffer = strdup(s->buffer); + return x; + } + + n = strlen(a); + p = s->buffer; + e = p; + + while (maxn-- && !is_null(p = strstr(p, a))) { + p += n; + v = x.mem = realloc(x.mem, ++x.size*sizeof(str_t)); + + v[x.size-1].buffer = strndup(e, p - e); + + p += n; + e = p; + } + + if (*e) { + n = strlen(e); + v = x.mem = realloc(x.mem, ++x.size*sizeof(str_t)); + + v[x.size-1].buffer = strndup(e, n); + } + + return x; +} + + +arr_t string_split_char(const str_t* s, int ac, size_t maxn) { + arr_t x = { .mem = 0, .size = 0, .type = VTYPE_STRING }; + char a[5] = { 0 }; + + size_t n; + char* p; + char* e; + str_t* v; + + if (is_null(s->buffer)) { + return x; + } + + if (is_null(p = tochar_unicode(a, ac)) || !(n = p - a)) { + v = x.mem = malloc(sizeof(str_t)); + v->buffer = strdup(s->buffer); + return x; + } + + p = s->buffer; + e = p; + + while (maxn-- && !is_null(p = strstr(p, a))) { + p += n; + v = x.mem = realloc(x.mem, ++x.size*sizeof(str_t)); + + v[x.size-1].buffer = strndup(e, p - e); + + p += n; + e = p; + } + + if (*e) { + n = strlen(e); + v = x.mem = realloc(x.mem, ++x.size*sizeof(str_t)); + + v[x.size-1].buffer = strndup(e, n); + } + + return x; +} diff --git a/src/string/extra.c b/src/string/extra.c new file mode 100644 index 0000000..fa301de --- /dev/null +++ b/src/string/extra.c @@ -0,0 +1,177 @@ +/* This software is licensed by the MIT License, see LICENSE file */ +/* Copyright © 2022 Gregory Lirent */ + +#include +#include "include.h" + +int string_case_compare(const str_t* s0, const str_t* s1) { + const char *p0, *p1, *t0, *t1; + ssize_t n0, n1; + u32_t uc0, uc1; + + if (s0 == s1) return 0; + + p0 = s0->buffer; + p1 = s1->buffer; + n0 = (!is_null(p0)) ? strasciilen(p0) : 0; + n1 = (!is_null(p1)) ? strasciilen(p1) : 0; + + n0 -= n1; + + if (!n0 && n1) { + do { + n0 = toupper(*(p0++)); + n0 -= toupper(*(p1++)); + if (n0) return n0; + } while(--n1); + + } else return memcmp(s0->buffer, s1->buffer, n1); + + while (*p0 && *p1) { + t0 = fromchar_unicode(&uc0, p0); + t1 = fromchar_unicode(&uc1, p1); + + if (is_null(t0) || is_null(t1)) { + n0 = (ssize_t)*(unsigned char*)(p0++) - *(unsigned char*)(p1++); + if (n0) return n0; + } else { + n0 = toupper_unicode(uc0); + if ((n0 -= toupper_unicode(uc1))) + return n0; + + p0 = t0; + p1 = t1; + } + } + + n0 = *(unsigned char*)p0 - *(unsigned char*)p1; + + return n0; +} + + +/*#####################################################################################################################*/ + + +size_t string_to_lower(str_t* x) { + + char ps[4]; + char *es, *p, *e; + u32_t uc0, uc1; + size_t n; + + if (is_null(x->buffer) || !*x->buffer) + return 0; + + n = 0; + p = x->buffer; + + for (;;) { + e = (char*)fromchar_unicode(&uc0, p); + + if (!is_null(e)) { + if (!uc0) break; + + if (uc0 != (uc1 = tolower_unicode(uc0))) { + es = tochar_unicode(ps, uc1); + + if (!is_null(es)) { + string_replace(x, p, e-p, ps, es-ps); + ++n; + } + } + + p = e; + } else ++p; + } + + return n; +} + + +size_t string_to_upper(str_t* x) { + + char ps[4]; + char *es, *p, *e; + u32_t uc0, uc1; + size_t n; + + if (is_null(x->buffer) || !*x->buffer) + return 0; + + n = 0; + p = x->buffer; + + for (;;) { + e = (char*)fromchar_unicode(&uc0, p); + + if (!is_null(e)) { + if (!uc0) break; + + if (uc0 != (uc1 = toupper_unicode(uc0))) { + es = tochar_unicode(ps, uc1); + + if (!is_null(es)) { + string_replace(x, p, e-p, ps, es-ps); + ++n; + } + } + + p = e; + } else ++p; + } + + return n; +} + + +size_t string_capitalize(str_t* x) { + + char ps[4]; + char *es, *p, *e; + u32_t uc0, uc1; + size_t n; + + if (is_null(x->buffer) || !*x->buffer) + return 0; + + n = 0; + p = x->buffer; + e = (char*)fromchar_unicode(&uc0, p); + + if (!is_null(e)) { + if (!uc0) return 0; + + if (uc0 != (uc1 = toupper_unicode(uc0))) { + es = tochar_unicode(ps, uc1); + + if (!is_null(es)) { + string_replace(x, p, e-p, ps, es-ps); + ++n; + } + } + + p = e; + } else ++p; + + for (;;) { + e = (char*)fromchar_unicode(&uc0, p); + + if (!is_null(e)) { + if (!uc0) break; + + if (uc0 != (uc1 = tolower_unicode(uc0))) { + es = tochar_unicode(ps, uc1); + + if (!is_null(es)) { + string_replace(x, p, e-p, ps, es-ps); + ++n; + } + } + + p = e; + } else ++p; + } + + return n; +} diff --git a/src/string/get.c b/src/string/get.c new file mode 100644 index 0000000..7a44f29 --- /dev/null +++ b/src/string/get.c @@ -0,0 +1,172 @@ +/* This software is licensed by the MIT License, see LICENSE file */ +/* Copyright © 2022 Gregory Lirent */ + +#include "include.h" + +char* string_at(const str_t* s, ssize_t i) { + char *e, *p; + size_t n, l; + + if (is_null(s->buffer) || !*s->buffer) + return nullptr; + + n = strasciilen(s->buffer); + e = s->buffer + n; + + if (i > n) { + p = s->buffer + n; + e = p + strlen(p); + + do { p = next_char(p); } while (--i && p < e); + return (!i) ? p : nullptr; + + } else if (i < 0 && n < (l = strlen(s->buffer))) { + p = s->buffer + l; + + do { p = prev_char(p); } while (++i && p >= s->buffer); + return (!i) ? p : nullptr; + + } else if (i < 0 && (i += l) < 0) i = 0; + + return s->buffer + i; +} + + +_Bool string_slice(str_t* x, str_t* s, ssize_t i, size_t c, _Bool cut) { + char *e, *p, *v; + size_t n; + + memset(x, 0, sizeof(*x)); + + if (!c) return true; + + p = string_at(s, i); + + if (is_null(p) || (e = p + strlen(p)) > p + c) + return false; + + v = p; + + do { v = next_char(v); } while (--c && v < e); + + if (!c) { + x->buffer = strndup(p, v - p); + + if (cut) { + memmove(p, v, strlen(v) + 1); + } + + return true; + } else return false; +} + + +/*#####################################################################################################################*/ + + +ssize_t string_indexof_cstring(const str_t* s, const char* a) { + char *e, *p; + size_t n; + + if (is_null(s->buffer) || is_null(a) || !*s->buffer || !*a) { + return 0; + } + + if (!is_null(p = strstr(s->buffer, a))) { + n = strasciilen(s->buffer); + e = s->buffer + n; + + if (e >= p) return p - s->buffer; + + do { + e = next_char(e); + ++n; + } while (e < p); + + if (e != p) { + /* Trying to find index of inconsistent string part + * It is not make a sense on that abstract level */ + } else return n; + } + + return -1; +} + + +ssize_t string_indexof_char(const str_t* s, int ac) { + size_t n; + char* e; + + char a[5] = { 0 }; + char* p = tochar_unicode(a, ac); + + if (is_null(s->buffer) || !*s->buffer || is_null(p)) { + return 0; + } + + if (!is_null(p = strstr(s->buffer, a))) { + n = strasciilen(s->buffer); + e = s->buffer + n; + + if (e >= p) return p - s->buffer; + + do { + e = next_char(e); + ++n; + } while (e < p); + + if (e != p) { + /* Trying to find index of inconsistent string part + * It is not make a sense on that abstract level */ + } else return n; + } + + return -1; +} + + +/*#####################################################################################################################*/ + + +size_t string_count_cstring(const str_t* s, const char* a) { + char* p; + size_t n, c; + + if (is_null(s->buffer) || is_null(a) || !*s->buffer || !*a) { + return 0; + } + + n = strlen(a); + p = s->buffer; + c = 0; + + while (!is_null(p = strstr(p, a))) { + p += n; + ++c; + } + + return c; +} + + +size_t string_count_char(const str_t* s, int ac) { + size_t n, c; + + char a[5] = {0}; + char* p = tochar_unicode(a, ac); + + if (is_null(s->buffer) || !*s->buffer || is_null(p)) { + return 0; + } + + n = p - a; + p = s->buffer; + c = 0; + + while (!is_null(p = strstr(p, a))) { + p += n; + ++c; + } + + return c; +} diff --git a/src/string/include.h b/src/string/include.h new file mode 100644 index 0000000..2fddeef --- /dev/null +++ b/src/string/include.h @@ -0,0 +1,59 @@ +/* This software is licensed by the MIT License, see LICENSE file */ +/* Copyright © 2022 Gregory Lirent */ + +#include "../../modules/libunic/include.h" +#include "../../include/extra/string.h" +#include "../__internal/include.h" + +#ifndef LIBCDSB_SRC_STRING_INCLUDE_H +#define LIBCDSB_SRC_STRING_INCLUDE_H + +ainline(char* next_char(char* s)) { + int cs = charsize(s); + + if (cs) return s + cs; + return ++s; +} + +ainline(char* prev_char(char* s)) { + + if (*(--s)&0x80) { + char* p = s; + + while ((*(--p)&0xc0) == 0x80) {} + + if (charsize(p) == s - p) + return p; + } + + return s; +} + +extern void libcdsb_string_replace(str_t* x, char* p, size_t n, const char* v, size_t vn); + +#ifdef string_replace +#undef string_replace +#endif + +#define string_replace libcdsb_string_replace +#define string_indexof_cstring libcdsb_string_indexof_cstring +#define string_indexof_char libcdsb_string_indexof_char +#define string_count_cstring libcdsb_string_count_cstring +#define string_count_char libcdsb_string_count_char +#define string_concat_cstring libcdsb_string_concat_cstring +#define string_concat_char libcdsb_string_concat_char +#define string_trim_cstring libcdsb_string_trim_cstring +#define string_trim_char libcdsb_string_trim_char +#define string_ltrim_cstring libcdsb_string_ltrim_cstring +#define string_ltrim_char libcdsb_string_ltrim_char +#define string_rtrim_cstring libcdsb_string_rtrim_cstring +#define string_rtrim_char libcdsb_string_rtrim_char +#define string_replace_cstring_cstring libcdsb_string_replace_cstring_cstring +#define string_replace_cstring_char libcdsb_string_replace_cstring_char +#define string_replace_char_cstring libcdsb_string_replace_char_cstring +#define string_replace_char_char libcdsb_string_replace_char_char +#define string_split_string libcdsb_string_split_string +#define string_split_cstring libcdsb_string_split_cstring +#define string_split_char libcdsb_string_split_char + +#endif /* LIBCDSB_SRC_STRING_INCLUDE_H */ diff --git a/src/string/internal.c b/src/string/internal.c new file mode 100644 index 0000000..bc50e01 --- /dev/null +++ b/src/string/internal.c @@ -0,0 +1,21 @@ +/* This software is licensed by the MIT License, see LICENSE file */ +/* Copyright © 2022 Gregory Lirent */ + +#include "include.h" + +void string_replace(str_t* x, char* p, size_t n, const char* v, size_t vn) { + if (n != vn) { + size_t l = strlen(x->buffer); + + if (n < vn) { + char* t = x->buffer; + + x->buffer = realloc(x->buffer, l + (vn - n) + 1); + p = x->buffer + (p - t); + } + + memmove(p+vn, p+n, l - (p+n - x->buffer) + 1); + } + + memcpy(p, v, vn); +} diff --git a/src/string/replace.c b/src/string/replace.c new file mode 100644 index 0000000..b9d0462 --- /dev/null +++ b/src/string/replace.c @@ -0,0 +1,105 @@ +/* This software is licensed by the MIT License, see LICENSE file */ +/* Copyright © 2022 Gregory Lirent */ + +#include "include.h" + +size_t string_replace_cstring_cstring(str_t* x, const char* a, const char* d, size_t maxn) { + char* p; + size_t c, an, dn; + + if (is_null(x->buffer) || is_null(a) || !*x->buffer || !*a) { + return 0; + } + + an = strlen(a); + dn = (!is_null(d)) ? strlen(d) : 0; + p = x->buffer; + c = 0; + + while (maxn-- && !is_null(p = strstr(p, a))) { + string_replace(x, p, an, d, dn); + p += an; + ++c; + } + + return c; +} + + +size_t string_replace_cstring_char(str_t* x, const char* a, int dc, size_t maxn) { + char* p; + char d[4]; + size_t c, an, dn; + + if (is_null(x->buffer) || is_null(a) || !*x->buffer || !*a) { + return 0; + } + + an = strlen(a); + p = tochar_unicode(d, dc); + dn = (!is_null(p)) ? p - d : 0; + p = x->buffer; + c = 0; + + while (maxn-- && !is_null(p = strstr(p, a))) { + string_replace(x, p, an, d, dn); + p += an; + ++c; + } + + return c; +} + + +size_t string_replace_char_cstring(str_t* x, int ac, const char* d, size_t maxn) { + char* p; + char a[4]; + size_t c, an, dn; + + p = tochar_unicode(a, ac); + + if (is_null(x->buffer) || is_null(p) || !*x->buffer || !*p) { + return 0; + } + + an = p - a; + dn = (!is_null(d)) ? strlen(d) : 0; + p = x->buffer; + c = 0; + + while (maxn-- && !is_null(p = strstr(p, a))) { + string_replace(x, p, an, d, dn); + p += an; + ++c; + } + + return c; +} + + +size_t string_replace_char_char(str_t* x, int ac, int dc, size_t maxn) { + char* p; + char a[4]; + char d[4]; + size_t c, an, dn; + + p = tochar_unicode(a, ac); + + if (is_null(x->buffer) || is_null(p) || !*x->buffer || !*p) { + return 0; + } + + an = p - a; + p = tochar_unicode(d, dc); + dn = (!is_null(p)) ? p - d : 0; + p = x->buffer; + c = 0; + + while (maxn-- && !is_null(p = strstr(p, a))) { + string_replace(x, p, an, d, dn); + p += an; + ++c; + } + + return c; +} diff --git a/src/string/trim.c b/src/string/trim.c new file mode 100644 index 0000000..22f198e --- /dev/null +++ b/src/string/trim.c @@ -0,0 +1,259 @@ +/* This software is licensed by the MIT License, see LICENSE file */ +/* Copyright © 2022 Gregory Lirent */ + +#include "include.h" + +/*#####################################################################################################################*/ + +typedef struct trim_handler { + union { + struct { + size_t pad; + + struct { + const char* ptr; + size_t len; + } *values; + + size_t size; + }; + #ifndef STRING_TRIM_MEMOPT + u8_t x[128]; + #else + size_t x[(16/sizeof(size_t))]; + #endif + }; +} th_t; + +/*#####################################################################################################################*/ + +static void th_init(th_t* x, const char* s) { + size_t n = (!is_null(s)) ? strlen(s) : 0; + + memset(x, 0, sizeof(*x)); + + if (n && n == strasciilen(s)) { + for (int i = 0; i < n; ++i) { + #ifndef STRING_TRIM_MEMOPT + x->x[s[i]] = 1; + #else + x->x[s[i]/(8*sizeof(size_t))] |= (size_t)1<<(s[i]%(8*sizeof(size_t))); + #endif + } + } else if (n) { + x->pad = (size_t)-1; + do { + if ((n = charsize(s))) { + + x->values = realloc(x->values, sizeof(*x->values)*x->size + 1); + x->values[x->size].len = n; + x->values[x->size].ptr = s; + + ++x->size; + s += n; + s += n; + } else ++s; + } while (*s); + } else { + #ifndef STRING_TRIM_MEMOPT + x->x[ ' '] = 1; + x->x['\r'] = 1; + x->x['\n'] = 1; + x->x['\t'] = 1; + x->x['\v'] = 1; + #else + x->x[ ' '/(8*sizeof(size_t))] |= (size_t)1<<( ' '%(8*sizeof(size_t))); + x->x['\r'/(8*sizeof(size_t))] |= (size_t)1<<('\r'%(8*sizeof(size_t))); + x->x['\n'/(8*sizeof(size_t))] |= (size_t)1<<('\n'%(8*sizeof(size_t))); + x->x['\t'/(8*sizeof(size_t))] |= (size_t)1<<('\t'%(8*sizeof(size_t))); + x->x['\v'/(8*sizeof(size_t))] |= (size_t)1<<('\v'%(8*sizeof(size_t))); + #endif + } +} + + + +static void th_free(th_t* x) { + if (x->pad == (size_t)-1) { + free(x->values); + } +} + + + +static char* th_next(const th_t* x, char* s) { + + if (!(x->pad != (size_t)-1) && *(u8_t*)s <= 0x7f) { + #ifndef STRING_TRIM_MEMOPT + if (x->x[*(u8_t*)s]) { + #else + if (x->x[(*(u8_t*)s)/(8*sizeof(size_t))] & ((size_t)1<<((*(u8_t*)s)%(8*sizeof(size_t))))) { + #endif + return ++s; + } + } else for (int i = 0; i < x->size; ++i) { + if (memcmp(x->values[i].ptr, s, x->values[i].len) == 0) { + return s + x->values[i].len; + } + } + + return nullptr; +} + + + +static char* th_prev(const th_t* x, char* s) { + + if (!(x->pad != (size_t)-1) && *(u8_t*)(--s) <= 0x7f) { + #ifndef STRING_TRIM_MEMOPT + if (x->x[*(u8_t*)s]) { + #else + if (x->x[(*(u8_t*)s)/(8*sizeof(size_t))] & ((size_t)1<<((*(u8_t*)s)%(8*sizeof(size_t))))) { + #endif + return s; + } + } else for (int i = 0; i < x->size; ++i) { + char* p = s - x->values[i].len; + if (memcmp(x->values[i].ptr, p, x->values[i].len) == 0) { + return p; + } + } + + return nullptr; +} + + +/*#####################################################################################################################*/ + + +void string_trim_cstring(str_t* x, const char* s) { + size_t n; + + if (!is_null(x->buffer) && (n = strlen(x->buffer))) { + th_t t; + char *p0, *p1; + + th_init(&t, s); + + p0 = x->buffer; + + while ((p1 = th_next(&t, p0))) { p0 = p1; } + + n -= p0 - x->buffer; + p0 = memmove(x->buffer, p0, n + 1) + n; + + while ((p1 = th_prev(&t, p0))) { p0 = p1; } + *p0 = 0; + + th_free(&t); + } +} + + +void string_trim_char(str_t* x, int sc) { + size_t n; + char s[5] = {0}; + + if (!is_null(x->buffer) && tochar_unicode(s, sc) && (n = strlen(x->buffer))) { + th_t t; + char *p0, *p1; + + th_init(&t, s); + + p0 = x->buffer; + + while ((p1 = th_next(&t, p0))) { p0 = p1; } + + n -= p0 - x->buffer; + p0 = memmove(x->buffer, p0, n + 1) + n; + + while ((p1 = th_prev(&t, p0))) { p0 = p1; } + *p0 = 0; + + th_free(&t); + } +} + + +void string_ltrim_cstring(str_t* x, const char* s) { + size_t n; + + if (!is_null(x->buffer) && (n = strlen(x->buffer))) { + th_t t; + char *p0, *p1; + + th_init(&t, s); + + p0 = x->buffer; + + while ((p1 = th_next(&t, p0))) { p0 = p1; } + + n -= p0 - x->buffer; + + memmove(x->buffer, p0, ++n); + + th_free(&t); + } +} + + +void string_ltrim_char(str_t* x, int sc) { + size_t n; + char s[5] = {0}; + + if (!is_null(x->buffer) && tochar_unicode(s, sc) && (n = strlen(x->buffer))) { + th_t t; + char *p0, *p1; + + th_init(&t, s); + + p0 = x->buffer; + + while ((p1 = th_next(&t, p0))) { p0 = p1; } + + n -= p0 - x->buffer; + + memmove(x->buffer, p0, ++n); + + th_free(&t); + } +} + + +void string_rtrim_cstring(str_t* x, const char* s) { + size_t n; + + if (!is_null(x->buffer) && (n = strlen(x->buffer))) { + th_t t; + char *p0, *p1; + + th_init(&t, s); + + p0 = x->buffer + n; + + while ((p1 = th_prev(&t, p0))) { p0 = p1; } + *p0 = 0; + + th_free(&t); + } +} + + +void string_rtrim_char(str_t* x, int sc) { + size_t n; + char s[5] = {0}; + + if (!is_null(x->buffer) && tochar_unicode(s, sc) && (n = strlen(x->buffer))) { + th_t t; + char *p0, *p1; + + th_init(&t, s); + + p0 = x->buffer + n; + + while ((p1 = th_prev(&t, p0))) { p0 = p1; } + *p0 = 0; + + th_free(&t); + } +}