aboutsummaryrefslogtreecommitdiff
path: root/src/mem/ft_memccpy.c
blob: 0f5224212c63b592585836149c37468de59bafd4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
/* ************************************************************************** */
/*                                                                            */
/*                                                        :::      ::::::::   */
/*   ft_memccpy.c                                       :+:      :+:    :+:   */
/*                                                    +:+ +:+         +:+     */
/*   By: cacharle <marvin@42.fr>                    +#+  +:+       +#+        */
/*                                                +#+#+#+#+#+   +#+           */
/*   Created: 2019/10/07 10:01:53 by cacharle          #+#    #+#             */
/*   Updated: 2020/01/17 10:54:03 by cacharle         ###   ########.fr       */
/*                                                                            */
/* ************************************************************************** */

#include "libft.h"

#define HIMAGIC 0x8080808080808080L
#define LOMAGIC 0x0101010101010101L

void	*ft_memccpy(void *dest, const void *src, int c, size_t n)
{
	uint64_t	buf;
	uint64_t	lw;

	if (dest == src)
		return (dest);
	c = (uint8_t)c;
	while ((n & 0b111) != 0)
	{
		*(uint8_t*)dest = *(uint8_t*)src;
		if (*(uint8_t*)dest == c)
			return ((uint8_t*)dest + 1);
		src++;
		dest++;
		n--;
	}
	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 > 0)
	{
		lw = *(uint64_t*)src ^ buf;
		if ((lw - LOMAGIC) & ~lw & HIMAGIC)
		{
			if ( (((uint8_t*)dest)[0] = ((uint8_t*)src)[0]) == (uint8_t)c)
				return ((uint8_t*)dest + 1);
			if ( (((uint8_t*)dest)[1] = ((uint8_t*)src)[1]) == (uint8_t)c)
				return ((uint8_t*)dest + 2);
			if ( (((uint8_t*)dest)[2] = ((uint8_t*)src)[2]) == (uint8_t)c)
				return ((uint8_t*)dest + 3);
			if ( (((uint8_t*)dest)[3] = ((uint8_t*)src)[3]) == (uint8_t)c)
				return ((uint8_t*)dest + 4);
			if ( (((uint8_t*)dest)[4] = ((uint8_t*)src)[4]) == (uint8_t)c)
				return ((uint8_t*)dest + 5);
			if ( (((uint8_t*)dest)[5] = ((uint8_t*)src)[5]) == (uint8_t)c)
				return ((uint8_t*)dest + 6);
			if ( (((uint8_t*)dest)[6] = ((uint8_t*)src)[6]) == (uint8_t)c)
				return ((uint8_t*)dest + 7);
			if ( (((uint8_t*)dest)[7] = ((uint8_t*)src)[7]) == (uint8_t)c)
				return ((uint8_t*)dest + 8);
		}
		else
			*(uint64_t*)dest = *(uint64_t*)src;
		n -= 8;
		dest += 8;
		src += 8;
	}
	return (NULL);
}