summaryrefslogtreecommitdiff
path: root/ccan/bytestring/bytestring.c
blob: 09ab006ad510c3d9a4d4cf795cd64279756d2957 (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
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
/* Licensed under LGPLv2+ - see LICENSE file for details */
#include "config.h"

#include <ccan/bytestring/bytestring.h>

size_t bytestring_spn(struct bytestring s, struct bytestring accept)
{
	size_t i;

	for (i = 0; i < s.len; i++)
		if (bytestring_index(accept, s.ptr[i]) == NULL)
			return i;

	return s.len;
}

size_t bytestring_cspn(struct bytestring s, struct bytestring reject)
{
	size_t i;

	for (i = 0; i < s.len; i++)
		if (bytestring_index(reject, s.ptr[i]) != NULL)
			return i;

	return s.len;
}

static struct bytestring _splitchr(struct bytestring whole, char delim,
				   size_t start)
{
	const char *p;

	assert(start <= whole.len);

	/* Check this first, in case memchr() is not safe with zero length */
	if (start == whole.len)
		return bytestring(whole.ptr + start, 0);

	p = memchr(whole.ptr + start, delim, whole.len - start);
	if (p)
		return bytestring_slice(whole, start, p - whole.ptr);
	else
		return bytestring_slice(whole, start, whole.len);
}

struct bytestring bytestring_splitchr_first(struct bytestring whole,
					    char delim)
{
	if (whole.len == 0)
		return bytestring_NULL;

	return _splitchr(whole, delim, 0);
}

struct bytestring bytestring_splitchr_next(struct bytestring whole,
					   char delim, struct bytestring prev)
{
	if (!prev.ptr)
		return bytestring_NULL;

	/* prev has to be a substring of whole */
	assert(prev.ptr >= whole.ptr);

	if ((prev.ptr + prev.len) == (whole.ptr + whole.len))
		return bytestring_NULL;

	return _splitchr(whole, delim, (prev.ptr - whole.ptr) + prev.len + 1);
}

static struct bytestring _splitchrs(struct bytestring whole,
				    struct bytestring delim, size_t start)
{
	struct bytestring remainder;
	size_t n;

	assert(start <= whole.len);

	remainder = bytestring_slice(whole, start, whole.len);
	n = bytestring_cspn(remainder, delim);
	return bytestring_slice(whole, start, start + n);
}

struct bytestring bytestring_splitchrs_first(struct bytestring whole,
					     struct bytestring delim)
{
	if (whole.len == 0)
		return bytestring_NULL;

	return _splitchrs(whole, delim, 0);
}

struct bytestring bytestring_splitchrs_next(struct bytestring whole,
					    struct bytestring delim,
					    struct bytestring prev)
{
	if (!prev.ptr)
		return bytestring_NULL;

	/* prev has to be a substring of whole */
	assert(prev.ptr >= whole.ptr);

	if ((prev.ptr + prev.len) == (whole.ptr + whole.len))
		return bytestring_NULL;

	return _splitchrs(whole, delim, (prev.ptr - whole.ptr) + prev.len + 1);
}

static struct bytestring _splitstr(struct bytestring whole,
				   struct bytestring delim, size_t start)
{
	struct bytestring remainder, nextdelim;

	assert(start <= whole.len);

	remainder = bytestring_slice(whole, start, whole.len);
	nextdelim = bytestring_bytestring(remainder, delim);
	if (nextdelim.ptr)
		return bytestring_slice(whole, start,
					nextdelim.ptr - whole.ptr);
	else
		return remainder;
}

struct bytestring bytestring_splitstr_first(struct bytestring whole,
					     struct bytestring delim)
{
	if (whole.len == 0)
		return bytestring_NULL;

	return _splitstr(whole, delim, 0);
}

struct bytestring bytestring_splitstr_next(struct bytestring whole,
					   struct bytestring delim,
					   struct bytestring prev)
{
	if (!prev.ptr)
		return bytestring_NULL;

	/* prev has to be a substring of whole */
	assert(prev.ptr >= whole.ptr);

	if ((prev.ptr + prev.len) == (whole.ptr + whole.len))
		return bytestring_NULL;

	return _splitstr(whole, delim,
			 (prev.ptr - whole.ptr) + prev.len + delim.len);
}