Add string
This commit is contained in:
		
							parent
							
								
									4c3af1db79
								
							
						
					
					
						commit
						540d71ee3c
					
				
							
								
								
									
										27
									
								
								include/extra/string.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								include/extra/string.h
									
									
									
									
									
										Normal file
									
								
							| @ -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 */ | ||||||
							
								
								
									
										114
									
								
								include/string.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										114
									
								
								include/string.h
									
									
									
									
									
										Normal file
									
								
							| @ -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 <uchar.h> | ||||||
|  | 
 | ||||||
|  | #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 */ | ||||||
							
								
								
									
										126
									
								
								src/string/base.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										126
									
								
								src/string/base.c
									
									
									
									
									
										Normal file
									
								
							| @ -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)); | ||||||
|  | } | ||||||
							
								
								
									
										89
									
								
								src/string/extra-split.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										89
									
								
								src/string/extra-split.c
									
									
									
									
									
										Normal file
									
								
							| @ -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; | ||||||
|  | } | ||||||
							
								
								
									
										177
									
								
								src/string/extra.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										177
									
								
								src/string/extra.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,177 @@ | |||||||
|  | /* This software is licensed by the MIT License, see LICENSE file */ | ||||||
|  | /*                                Copyright © 2022 Gregory Lirent */ | ||||||
|  | 
 | ||||||
|  | #include <ctype.h> | ||||||
|  | #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; | ||||||
|  | } | ||||||
							
								
								
									
										172
									
								
								src/string/get.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										172
									
								
								src/string/get.c
									
									
									
									
									
										Normal file
									
								
							| @ -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; | ||||||
|  | } | ||||||
							
								
								
									
										59
									
								
								src/string/include.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										59
									
								
								src/string/include.h
									
									
									
									
									
										Normal file
									
								
							| @ -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 */ | ||||||
							
								
								
									
										21
									
								
								src/string/internal.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								src/string/internal.c
									
									
									
									
									
										Normal file
									
								
							| @ -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); | ||||||
|  | } | ||||||
							
								
								
									
										105
									
								
								src/string/replace.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										105
									
								
								src/string/replace.c
									
									
									
									
									
										Normal file
									
								
							| @ -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; | ||||||
|  | } | ||||||
							
								
								
									
										259
									
								
								src/string/trim.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										259
									
								
								src/string/trim.c
									
									
									
									
									
										Normal file
									
								
							| @ -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); | ||||||
|  |     } | ||||||
|  | } | ||||||
		Loading…
	
		Reference in New Issue
	
	Block a user