aboutsummaryrefslogtreecommitdiff
path: root/src/mem/ft_memchr.c
diff options
context:
space:
mode:
authorCharles <sircharlesaze@gmail.com>2020-03-11 21:07:32 +0100
committerCharles <sircharlesaze@gmail.com>2020-03-11 21:23:49 +0100
commitc128213daa677d548bfc2905496257fe4a4faf79 (patch)
treed087ceaeff3124ff539bc05d834d79f8187d5628 /src/mem/ft_memchr.c
parent3c3f1115f6e9a9b914e2dcbd796501ca7ce85342 (diff)
downloadlibft-c128213daa677d548bfc2905496257fe4a4faf79.tar.gz
libft-c128213daa677d548bfc2905496257fe4a4faf79.tar.bz2
libft-c128213daa677d548bfc2905496257fe4a4faf79.zip
ft_mem* and ft_strlen optimization
Diffstat (limited to 'src/mem/ft_memchr.c')
-rw-r--r--src/mem/ft_memchr.c44
1 files changed, 37 insertions, 7 deletions
diff --git a/src/mem/ft_memchr.c b/src/mem/ft_memchr.c
index 4fd8689..54780fe 100644
--- a/src/mem/ft_memchr.c
+++ b/src/mem/ft_memchr.c
@@ -12,15 +12,45 @@
#include "libft.h"
+/*
+** Determining if a long word contain byte n
+**
+** xor all bytes with n, then check for zero byte like in ft_strlen.
+*/
+
+#define HIMAGIC 0x8080808080808080L
+#define LOMAGIC 0x0101010101010101L
+
void *ft_memchr(const void *s, int c, size_t n)
{
- size_t i;
- t_ftbyte *cast_s;
+ uint64_t buf;
+ uint64_t lw;
- cast_s = (t_ftbyte*)s;
- i = -1;
- while (++i < n)
- if (cast_s[i] == (unsigned char)c)
- return (cast_s + i);
+ c = (uint8_t)c;
+ while (((uint64_t)s & 0b111) != 0)
+ {
+ n--;
+ if (*(uint8_t*)s == (uint8_t)c)
+ return ((uint8_t*)s);
+ s++;
+ }
+ buf = (uint64_t)c | (uint64_t)c << 8 | (uint64_t)c << 16
+ | (uint64_t)c << 24 | (uint64_t)c << 32 | (uint64_t)c << 40
+ | (uint64_t)c << 48 | (uint64_t)c << 56;
+ while (n >= 8)
+ {
+ lw = *(uint64_t*)s ^ buf;
+ if ((lw - LOMAGIC) & ~lw & HIMAGIC)
+ break;
+ n -= 8;
+ s += 8;
+ }
+ while (n > 0)
+ {
+ if (*(uint8_t*)s == (uint8_t)c)
+ return ((uint8_t*)s);
+ n--;
+ s++;
+ }
return (NULL);
}