]> git.ozlabs.org Git - ccan/blob - ccan/mem/mem.h
mem: add memcheck() for valgrind.
[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 static inline bool memeqstr(const void *data, size_t length, const char *string)
148 {
149         return memeq(data, length, string, strlen(string));
150 }
151
152 /**
153  * memstarts_str - Does this byte array start with a string prefix?
154  * @a: byte array
155  * @al: length in bytes
156  * @s: string prefix
157  *
158  * Example:
159  *      if (memstarts_str(somebytes, bytes_len, "It")) {
160  *              printf("somebytes starts with 'It'\n");
161  *      }
162  */
163 PURE_FUNCTION
164 static inline bool memstarts_str(const void *a, size_t al, const char *s)
165 {
166         return memstarts(a, al, s, strlen(s));
167 }
168
169 /**
170  * memends - Does this byte array end with a given byte-array suffix?
171  * @s: byte array
172  * @s_len: length in bytes
173  * @suffix: byte array suffix
174  * @suffix_len: length of suffix in bytes
175  *
176  * Returns true if @suffix appears as a substring at the end of @s,
177  * false otherwise.
178  */
179 PURE_FUNCTION
180 static inline bool memends(const void *s, size_t s_len, const void *suffix, size_t suffix_len)
181 {
182         return (s_len >= suffix_len) && (memcmp((const char *)s + s_len - suffix_len,
183                                                 suffix, suffix_len) == 0);
184 }
185
186 /**
187  * memends_str - Does this byte array end with a string suffix?
188  * @a: byte array
189  * @al: length in bytes
190  * @s: string suffix
191  *
192  * Example:
193  *      if (memends_str(somebytes, bytes_len, "It")) {
194  *              printf("somebytes ends with with 'It'\n");
195  *      }
196  */
197 PURE_FUNCTION
198 static inline bool memends_str(const void *a, size_t al, const char *s)
199 {
200         return memends(a, al, s, strlen(s));
201 }
202
203 /**
204  * memoverlaps - Do two memory ranges overlap?
205  * @a: pointer to first memory range
206  * @al: length of first memory range
207  * @b: pointer to second memory range
208  * @al: length of second memory range
209  */
210 CONST_FUNCTION
211 static inline bool memoverlaps(const void *a_, size_t al,
212                                const void *b_, size_t bl)
213 {
214         const char *a = a_;
215         const char *b = b_;
216
217         return (a < (b + bl)) && (b < (a + al));
218 }
219
220 /*
221  * memswap - Exchange two memory regions
222  * @a: first region
223  * @b: second region
224  * @n: length of the regions
225  *
226  * Undefined results if the two memory regions overlap.
227  */
228 void memswap(void *a, void *b, size_t n);
229
230 #if HAVE_VALGRIND_MEMCHECK_H
231 #include <valgrind/memcheck.h>
232 static inline void *memcheck_(const void *data, size_t len)
233 {
234         VALGRIND_CHECK_MEM_IS_DEFINED(data, len);
235         return (void *)data;
236 }
237 #else
238 static inline void *memcheck_(const void *data, size_t len)
239 {
240         return (void *)data;
241 }
242 #endif
243
244 #if HAVE_TYPEOF
245 /**
246  * memcheck - check that a memory region is initialized
247  * @data: start of region
248  * @len: length in bytes
249  *
250  * When running under valgrind, this causes an error to be printed
251  * if the entire region is not defined.  Otherwise valgrind only
252  * reports an error when an undefined value is used for a branch, or
253  * written out.
254  *
255  * Example:
256  *      // Search for space, but make sure it's all initialized.
257  *      if (memchr(memcheck(somebytes, bytes_len), ' ', bytes_len)) {
258  *              printf("space was found!\n");
259  *      }
260  */
261 #define memcheck(data, len) ((__typeof__((data)+0))memcheck_((data), (len)))
262 #else
263 #define memcheck(data, len) memcheck_((data), (len))
264 #endif
265 #endif /* CCAN_MEM_H */