]> git.ozlabs.org Git - ccan/blob - ccan/mem/mem.h
mem: add memeqzero.
[ccan] / ccan / mem / mem.h
1 /* CC0 (Public domain) - see LICENSE file for details */
2 #ifndef CCAN_MEM_H
3 #define CCAN_MEM_H
4
5 #include "config.h"
6 #include <ccan/compiler/compiler.h>
7
8 #include <string.h>
9 #include <stdbool.h>
10
11 #if !HAVE_MEMMEM
12 PURE_FUNCTION
13 void *memmem(const void *haystack, size_t haystacklen,
14              const void *needle, size_t needlelen);
15 #endif
16
17 #if !HAVE_MEMRCHR
18 PURE_FUNCTION
19 void *memrchr(const void *s, int c, size_t n);
20 #endif
21
22 /**
23  * mempbrkm - locates the first occurrence in @data of any bytes in @accept
24  * @data: where we search
25  * @len: length of data in bytes
26  * @accept: array of bytes we search for
27  * @accept_len: # of bytes in accept
28  *
29  * Returns a pointer to the byte in @data that matches one of the bytes in
30  * @accept, or NULL if no such byte is found.
31  *
32  * Example:
33  *      char otherbytes[] = "Hello \0world";
34  *      size_t otherbytes_len = sizeof(otherbytes) - 1;
35  *      char *r = mempbrkm(otherbytes, otherbytes_len, "\0b", 2);
36  *      if (r) {
37  *              printf("Found %c\n", *r);
38  *      } else {
39  *              printf("Nada\n");
40  *      }
41  *
42  */
43 PURE_FUNCTION
44 void *mempbrkm(const void *data, size_t len, const void *accept, size_t accept_len);
45
46 /**
47  * mempbrk - locates the first occurrence in @data of any bytes in @accept
48  * @data: where we search
49  * @len: length of data in bytes
50  * @accept: NUL terminated string containing the bytes we search for
51  *
52  * Returns a pointer to the byte in @data that matches one of the bytes in
53  * @accept, or NULL if no such byte is found.
54  *
55  * Example:
56  *
57  *      r = mempbrk(otherbytes, otherbytes_len, "abcde");
58  *      if (r) {
59  *              printf("Found %c\n", *r);
60  *      } else {
61  *              printf("Nada\n");
62  *      }
63  */
64 PURE_FUNCTION
65 static inline char *mempbrk(const void *data, size_t len, const char *accept)
66 {
67         return mempbrkm(data, len, accept, strlen(accept));
68 }
69
70 /**
71  * memcchr - scan memory until a character does _not_ match @c
72  * @data: pointer to memory to scan
73  * @data_len: length of data
74  * @c: character to scan for
75  *
76  * The complement of memchr().
77  *
78  * Returns a pointer to the first character which is _not_ @c. If all memory in
79  * @data is @c, returns NULL.
80  *
81  * Example:
82  *      char somebytes[] = "HI By\0e";
83  *      size_t bytes_len = sizeof(somebytes) - 1;
84  *      r = memcchr(somebytes, ' ', bytes_len);
85  *      if (r) {
86  *              printf("Found %c after trimming spaces\n", *r);
87  *      }
88  */
89 PURE_FUNCTION
90 void *memcchr(void const *data, int c, size_t data_len);
91
92 /**
93  * memeq - Are two byte arrays equal?
94  * @a: first array
95  * @al: bytes in first array
96  * @b: second array
97  * @bl: bytes in second array
98  *
99  * Example:
100  *      if (memeq(somebytes, bytes_len, otherbytes, otherbytes_len)) {
101  *              printf("memory blocks are the same!\n");
102  *      }
103  */
104 PURE_FUNCTION
105 static inline bool memeq(const void *a, size_t al, const void *b, size_t bl)
106 {
107         return al == bl && !memcmp(a, b, bl);
108 }
109
110 /**
111  * memstarts - determine if @data starts with @prefix
112  * @data: does this begin with @prefix?
113  * @data_len: bytes in @data
114  * @prefix: does @data begin with these bytes?
115  * @prefix_len: bytes in @prefix
116  *
117  * Returns true if @data starts with @prefix, otherwise return false.
118  *
119  * Example:
120  *      if (memstarts(somebytes, bytes_len, otherbytes, otherbytes_len)) {
121  *              printf("somebytes starts with otherbytes!\n");
122  *      }
123  */
124 PURE_FUNCTION
125 static inline bool memstarts(void const *data, size_t data_len,
126                 void const *prefix, size_t prefix_len)
127 {
128         if (prefix_len > data_len)
129                 return false;
130         return memeq(data, prefix_len, prefix, prefix_len);
131 }
132
133 /**
134  * memeqstr - Is a byte array equal to a NUL terminated string?
135  * @data: byte array
136  * @length: length of @data in bytes
137  * @string: NUL terminated string
138  *
139  * The '\0' byte is ignored when checking if @bytes == @string.
140  *
141  * Example:
142  *      if (memeqstr(somebytes, bytes_len, "foo")) {
143  *              printf("somebytes == 'foo'!\n");
144  *      }
145  */
146 PURE_FUNCTION
147 bool memeqzero(const void *data, size_t length);
148
149 /**
150  * memeqzero - Is a byte array all zeroes?
151  * @data: byte array
152  * @length: length of @data in bytes
153  *
154  * Example:
155  *      if (memeqzero(somebytes, bytes_len)) {
156  *              printf("somebytes == 0!\n");
157  *      }
158  */
159 PURE_FUNCTION
160 static inline bool memeqstr(const void *data, size_t length, const char *string)
161 {
162         return memeq(data, length, string, strlen(string));
163 }
164
165 /**
166  * memstarts_str - Does this byte array start with a string prefix?
167  * @a: byte array
168  * @al: length in bytes
169  * @s: string prefix
170  *
171  * Example:
172  *      if (memstarts_str(somebytes, bytes_len, "It")) {
173  *              printf("somebytes starts with 'It'\n");
174  *      }
175  */
176 PURE_FUNCTION
177 static inline bool memstarts_str(const void *a, size_t al, const char *s)
178 {
179         return memstarts(a, al, s, strlen(s));
180 }
181
182 /**
183  * memends - Does this byte array end with a given byte-array suffix?
184  * @s: byte array
185  * @s_len: length in bytes
186  * @suffix: byte array suffix
187  * @suffix_len: length of suffix in bytes
188  *
189  * Returns true if @suffix appears as a substring at the end of @s,
190  * false otherwise.
191  */
192 PURE_FUNCTION
193 static inline bool memends(const void *s, size_t s_len, const void *suffix, size_t suffix_len)
194 {
195         return (s_len >= suffix_len) && (memcmp((const char *)s + s_len - suffix_len,
196                                                 suffix, suffix_len) == 0);
197 }
198
199 /**
200  * memends_str - Does this byte array end with a string suffix?
201  * @a: byte array
202  * @al: length in bytes
203  * @s: string suffix
204  *
205  * Example:
206  *      if (memends_str(somebytes, bytes_len, "It")) {
207  *              printf("somebytes ends with with 'It'\n");
208  *      }
209  */
210 PURE_FUNCTION
211 static inline bool memends_str(const void *a, size_t al, const char *s)
212 {
213         return memends(a, al, s, strlen(s));
214 }
215
216 /**
217  * memoverlaps - Do two memory ranges overlap?
218  * @a: pointer to first memory range
219  * @al: length of first memory range
220  * @b: pointer to second memory range
221  * @al: length of second memory range
222  */
223 CONST_FUNCTION
224 static inline bool memoverlaps(const void *a_, size_t al,
225                                const void *b_, size_t bl)
226 {
227         const char *a = a_;
228         const char *b = b_;
229
230         return (a < (b + bl)) && (b < (a + al));
231 }
232
233 /*
234  * memswap - Exchange two memory regions
235  * @a: first region
236  * @b: second region
237  * @n: length of the regions
238  *
239  * Undefined results if the two memory regions overlap.
240  */
241 void memswap(void *a, void *b, size_t n);
242
243 #if HAVE_VALGRIND_MEMCHECK_H
244 #include <valgrind/memcheck.h>
245 static inline void *memcheck_(const void *data, size_t len)
246 {
247         VALGRIND_CHECK_MEM_IS_DEFINED(data, len);
248         return (void *)data;
249 }
250 #else
251 static inline void *memcheck_(const void *data, size_t len)
252 {
253         return (void *)data;
254 }
255 #endif
256
257 #if HAVE_TYPEOF
258 /**
259  * memcheck - check that a memory region is initialized
260  * @data: start of region
261  * @len: length in bytes
262  *
263  * When running under valgrind, this causes an error to be printed
264  * if the entire region is not defined.  Otherwise valgrind only
265  * reports an error when an undefined value is used for a branch, or
266  * written out.
267  *
268  * Example:
269  *      // Search for space, but make sure it's all initialized.
270  *      if (memchr(memcheck(somebytes, bytes_len), ' ', bytes_len)) {
271  *              printf("space was found!\n");
272  *      }
273  */
274 #define memcheck(data, len) ((__typeof__((data)+0))memcheck_((data), (len)))
275 #else
276 #define memcheck(data, len) memcheck_((data), (len))
277 #endif
278 #endif /* CCAN_MEM_H */