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