]> git.ozlabs.org Git - ccan/blob - ccan/mem/mem.h
mem: add mem helper functions
[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
7 #include <string.h>
8 #include <stdbool.h>
9
10 #if !HAVE_MEMMEM
11 void *memmem(const void *haystack, size_t haystacklen,
12              const void *needle, size_t needlelen);
13 #endif
14
15 #if !HAVE_MEMRCHR
16 void *memrchr(const void *s, int c, size_t n);
17 #endif
18
19 /**
20  * mempbrkm - locates the first occurrence in @data of any bytes in @accept
21  * @data: where we search
22  * @len: length of data in bytes
23  * @accept: array of bytes we search for
24  * @accept_len: # of bytes in accept
25  *
26  * Returns a pointer to the byte in @data that matches one of the bytes in
27  * @accept, or NULL if no such byte is found.
28  *
29  * Example:
30  *      char otherbytes[] = "Hello \0world";
31  *      size_t otherbytes_len = sizeof(otherbytes) - 1;
32  *      char *r = mempbrkm(otherbytes, otherbytes_len, "\0b", 2);
33  *      if (r) {
34  *              printf("Found %c\n", *r);
35  *      } else {
36  *              printf("Nada\n");
37  *      }
38  *
39  */
40 void *mempbrkm(const void *data, size_t len, const void *accept, size_t accept_len);
41
42 /**
43  * mempbrk - locates the first occurrence in @data of any bytes in @accept
44  * @data: where we search
45  * @len: length of data in bytes
46  * @accept: NUL terminated string containing the bytes we search for
47  *
48  * Returns a pointer to the byte in @data that matches one of the bytes in
49  * @accept, or NULL if no such byte is found.
50  *
51  * Example:
52  *
53  *      r = mempbrk(otherbytes, otherbytes_len, "abcde");
54  *      if (r) {
55  *              printf("Found %c\n", *r);
56  *      } else {
57  *              printf("Nada\n");
58  *      }
59  */
60 static inline char *mempbrk(const void *data, size_t len, const char *accept)
61 {
62         return mempbrkm(data, len, accept, strlen(accept));
63 }
64
65 /**
66  * memcchr - scan memory until a character does _not_ match @c
67  * @data: pointer to memory to scan
68  * @data_len: length of data
69  * @c: character to scan for
70  *
71  * The complement of memchr().
72  *
73  * Returns a pointer to the first character which is _not_ @c. If all memory in
74  * @data is @c, returns NULL.
75  *
76  * Example:
77  *      char somebytes[] = "HI By\0e";
78  *      size_t bytes_len = sizeof(somebytes) - 1;
79  *      r = memcchr(somebytes, ' ', bytes_len);
80  *      if (r) {
81  *              printf("Found %c after trimming spaces\n", *r);
82  *      }
83  */
84 void *memcchr(void const *data, int c, size_t data_len);
85
86 /**
87  * memeq - Are two byte arrays equal?
88  * @a: first array
89  * @al: bytes in first array
90  * @b: second array
91  * @bl: bytes in second array
92  *
93  * Example:
94  *      if (memeq(somebytes, bytes_len, otherbytes, otherbytes_len)) {
95  *              printf("memory blocks are the same!\n");
96  *      }
97  */
98 static inline bool memeq(const void *a, size_t al, const void *b, size_t bl)
99 {
100         return al == bl && !memcmp(a, b, bl);
101 }
102
103 /**
104  * memstarts - determine if @data starts with @prefix
105  * @data: does this begin with @prefix?
106  * @data_len: bytes in @data
107  * @prefix: does @data begin with these bytes?
108  * @prefix_len: bytes in @prefix
109  *
110  * Returns true if @data starts with @prefix, otherwise return false.
111  *
112  * Example:
113  *      if (memstarts(somebytes, bytes_len, otherbytes, otherbytes_len)) {
114  *              printf("somebytes starts with otherbytes!\n");
115  *      }
116  */
117 static inline bool memstarts(void const *data, size_t data_len,
118                 void const *prefix, size_t prefix_len)
119 {
120         if (prefix_len > data_len)
121                 return false;
122         return memeq(data, prefix_len, prefix, prefix_len);
123 }
124
125 /**
126  * memeqstr - Is a byte array equal to a NUL terminated string?
127  * @data: byte array
128  * @length: length of @data in bytes
129  * @string: NUL terminated string
130  *
131  * The '\0' byte is ignored when checking if @bytes == @string.
132  *
133  * Example:
134  *      if (memeqstr(somebytes, bytes_len, "foo")) {
135  *              printf("somebytes == 'foo'!\n");
136  *      }
137  */
138 static inline bool memeqstr(const void *data, size_t length, const char *string)
139 {
140         return memeq(data, length, string, strlen(string));
141 }
142
143 /**
144  * memstarts_str - Does this byte array start with a string prefix?
145  * @a: byte array
146  * @al: length in bytes
147  * @s: string prefix
148  *
149  * Example:
150  *      if (memstarts_str(somebytes, bytes_len, "It")) {
151  *              printf("somebytes starts with 'It'\n");
152  *      }
153  */
154 static inline bool memstarts_str(const void *a, size_t al, const char *s)
155 {
156         return memstarts(a, al, s, strlen(s));
157 }
158
159 /**
160  * memends - Does this byte array end with a given byte-array suffix?
161  * @s: byte array
162  * @s_len: length in bytes
163  * @suffix: byte array suffix
164  * @suffix_len: length of suffix in bytes
165  *
166  * Returns true if @suffix appears as a substring at the end of @s,
167  * false otherwise.
168  */
169 static inline bool memends(const void *s, size_t s_len, const void *suffix, size_t suffix_len)
170 {
171         return (s_len >= suffix_len) && (memcmp((const char *)s + s_len - suffix_len,
172                                                 suffix, suffix_len) == 0);
173 }
174
175 #endif /* CCAN_MEM_H */