/* 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[((unsigned char*)s)[i]] = 1; #else x->x[((unsigned char*)s)[i]/(8*sizeof(size_t))] |= (size_t)1<<(((unsigned char*)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); } }