summaryrefslogtreecommitdiff
path: root/ccan/mem/mem.c
blob: 5b4b3508090dfb10dc7eea9236eb42ed54b92834 (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
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
/* CC0 (Public domain) - see LICENSE file for details */

#include "config.h"

#include <assert.h>
#include <string.h>
#include <ccan/mem/mem.h>

#if !HAVE_MEMMEM
void *memmem(const void *haystack, size_t haystacklen,
	     const void *needle, size_t needlelen)
{
	const char *p;

	if (needlelen > haystacklen)
		return NULL;

	p = haystack;

	for (p = haystack;
	     (p + needlelen) <= ((const char *)haystack + haystacklen);
	     p++)
		if (memcmp(p, needle, needlelen) == 0)
			return (void *)p;

	return NULL;
}
#endif

#if !HAVE_MEMRCHR
void *memrchr(const void *s, int c, size_t n)
{
	unsigned char *p = (unsigned char *)s;

	while (n) {
		if (p[n-1] == c)
			return p + n - 1;
		n--;
	}

	return NULL;
}
#endif

void *mempbrkm(const void *data_, size_t len, const void *accept_, size_t accept_len)
{
	const char *data = data_, *accept = accept_;
	size_t i, j;

	for (i = 0; i < len; i++)
		for (j = 0; j < accept_len; j++)
			if (accept[j] == data[i])
				return (void *)&data[i];
	return NULL;
}

void *memcchr(void const *data, int c, size_t data_len)
{
	char const *p = data;
	size_t i;

	for (i = 0; i < data_len; i++)
		if (p[i] != c)
			return (void *)&p[i];

	return NULL;
}

#define MEMSWAP_TMP_SIZE	256

void memswap(void *a, void *b, size_t n)
{
	char *ap = a;
	char *bp = b;
	char tmp[MEMSWAP_TMP_SIZE];

	assert(!memoverlaps(a, n, b, n));

	while (n) {
		size_t m = n > MEMSWAP_TMP_SIZE ? MEMSWAP_TMP_SIZE : n;

		memcpy(tmp, bp, m);
		memcpy(bp, ap, m);
		memcpy(ap, tmp, m);

		ap += m;
		bp += m;
		n -= m;
	}
}