diff options
Diffstat (limited to 'memelemmove.c')
-rw-r--r-- | memelemmove.c | 124 |
1 files changed, 124 insertions, 0 deletions
diff --git a/memelemmove.c b/memelemmove.c new file mode 100644 index 0000000..2a90e26 --- /dev/null +++ b/memelemmove.c @@ -0,0 +1,124 @@ +/* See LICENSE file for copyright and license details. */ +#include "libsimple.h" +#ifndef TEST + + +#define MEMELEMMOVE(TYPE)\ + do {\ + TYPE *p;\ + if (d <= s) {\ + for (; n; n--, s++)\ + if ((*d++ = *s) == elem)\ + return d;\ + } else {\ + for (p = *(TYPE **)(void *)&s; n; n--, p++) {\ + if (*p == elem) {\ + n = (size_t)(p - s);\ + p = &d[n + 1];\ + do { d[n] = s[n]; } while (n--);\ + return p;\ + }\ + }\ + for (n = (size_t)(p - s); n;) {\ + n--;\ + d[n] = s[n];\ + }\ + }\ + return NULL;\ + } while (0) + + +static uint16_t * +memelemmove16(uint16_t *restrict d, const uint16_t *restrict s, uint16_t elem, size_t n) +{ + MEMELEMMOVE(uint16_t); +} + + +static uint32_t * +memelemmove32(uint32_t *restrict d, const uint32_t *restrict s, uint32_t elem, size_t n) +{ + MEMELEMMOVE(uint32_t); +} + + +static uint64_t * +memelemmove64(uint64_t *restrict d, const uint64_t *restrict s, uint64_t elem, size_t n) +{ + MEMELEMMOVE(uint64_t); +} + + +static char * +memelemmovex(char *restrict d, const char *restrict s, const char *restrict elem, size_t size, size_t n) +{ + char *p; + size_t i; + if (d <= s) { + for (; n; s += size, n--) { + for (i = 0; i < size; i++) + d[i] = s[i]; + for (i = 0; i < size; i++) + if (d[i] != elem[i]) + goto next_forwards; + d += size; + return d; + next_forwards: + d += size; + } + return NULL; + } else { + for (p = *(char **)(void *)&s; n; n--) { + for (i = 0; i < size; i++) + if (p[i] != elem[i]) + goto next_backwards; + + p += size; + n = (size_t)(p - s); + p = &d[n]; + goto out_backwards; + next_backwards: + p += size; + } + n = (size_t)(p - s); + p = NULL; + out_backwards: + while (n) { + n--; + d[n] = s[n]; + } + return p; + } +} + + +void * +libsimple_memelemmove(void *d, const void *s, const void *restrict elem, size_t size, size_t n) /* TODO test, man */ +{ + switch (size) { + case 0: + return d; + case 1: + return memcmove(d, s, *(const char *)elem, n); + case 2: + return memelemmove16(d, s, *(const uint16_t *)elem, n); + case 4: + return memelemmove32(d, s, *(const uint32_t *)elem, n); + case 8: + return memelemmove64(d, s, *(const uint64_t *)elem, n); + default: + return memelemmovex(d, s, elem, size, n); + } +} + + +#else +#include "test.h" + +int +main(void) +{ + return 0; +} + +#endif |