260 lines
5.6 KiB
C
260 lines
5.6 KiB
C
|
/* 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);
|
||
|
}
|
||
|
}
|