1 /* MIT (BSD) license - see LICENSE file for details */
6 #include <ccan/tcon/tcon.h>
9 * struct membuf - representation of a memory buffer.
11 * It's exposed here to allow you to embed it and so we can inline the
15 /* These are the cursors into buf elements */
19 /* Number of elements in buf */
21 /* The buffer; at this low-level, untyped. */
24 void *(*expandfn)(struct membuf *, void *elems, size_t max_elems);
28 * MEMBUF - declare a type-specific membuf
29 * @membertype: type for this buffer's values.
31 * You use this to create your own typed membuf.
34 * MEMBUF(int *) intp_membuf;
35 * printf("Address of our int * membuf = %p\n", &intp_membuf);
37 #define MEMBUF(membertype) \
38 TCON_WRAP(struct membuf, membertype canary)
41 * membuf_init - initialize a type-specfic membuf.
42 * @mb: the MEMBUF() declared membuf.
43 * @elems: the initial buffer, if any.
44 * @max_elems: the initial space @elems, in number of elements.
45 * @expandfn: the function to enlarge buf (eg. membuf_realloc).
48 * membuf_init(&intp_membuf, NULL, 0, membuf_realloc);
50 #define membuf_init(mb, elems, num, expandfn) \
51 membuf_init_(tcon_unwrap(tcon_check_ptr((mb), canary, (elems))), \
52 (elems), (num), tcon_sizeof((mb), canary), (expandfn))
54 void membuf_init_(struct membuf *mb,
55 void *elems, size_t max_elems, size_t elemsize,
56 void *(*expandfn)(struct membuf *, void *, size_t));
59 * membuf_realloc - simple membuf helper to do realloc().
61 * Assumes initial buffer was NULL, or malloc().
63 void *membuf_realloc(struct membuf *mb, void *rawelems, size_t newsize);
66 * membuf_num_elems - number of populated elements in the membuf.
67 * @mb: the MEMBUF() declared membuf.
69 #define membuf_num_elems(mb) membuf_num_elems_(tcon_unwrap(mb))
71 static inline size_t membuf_num_elems_(const struct membuf *mb)
73 return mb->end - mb->start;
77 * membuf_elems - pointer to the populated elements in the membuf.
78 * @mb: the MEMBUF() declared membuf.
80 #define membuf_elems(mb) \
81 tcon_cast_ptr(mb, canary, \
82 membuf_elems_(tcon_unwrap(mb), tcon_sizeof((mb), canary)))
84 static inline void *membuf_elems_(const struct membuf *mb, size_t elemsize)
86 return mb->elems + mb->start * elemsize;
90 * membuf_consume - we've used up this many membuf_elems.
91 * @mb: the MEMBUF() declared membuf.
92 * @num: the number of elems.
94 * Returns a pointer to the old start of membuf, so you can mark consumed
95 * and actually process in a single call.
97 #define membuf_consume(mb, num) \
98 tcon_cast_ptr(mb, canary, \
99 membuf_consume_(tcon_unwrap(mb), (num), \
100 tcon_sizeof((mb), canary)))
102 static inline void *membuf_consume_(struct membuf *mb,
103 size_t num, size_t elemsize)
105 void *old_start = membuf_elems_(mb, elemsize);
106 assert(num <= membuf_num_elems_(mb));
113 * membuf_num_space - number of unpopulated elements at end of the membuf.
114 * @mb: the MEMBUF() declared membuf.
116 #define membuf_num_space(mb) membuf_num_space_(tcon_unwrap(mb))
118 static inline size_t membuf_num_space_(const struct membuf *mb)
120 return mb->max_elems - mb->end;
124 * membuf_space - pointer to the unpopulated elements at end of membuf.
125 * @mb: the MEMBUF() declared membuf.
127 #define membuf_space(mb) \
128 tcon_cast_ptr(mb, canary, \
129 membuf_space_(tcon_unwrap(mb), tcon_sizeof((mb), canary)))
131 static inline void *membuf_space_(struct membuf *mb, size_t elemsize)
133 return mb->elems + mb->end * elemsize;
137 * membuf_prepare_space - internal routine to make sure we've got space.
138 * @mb: the MEMBUF() declared membuf.
139 * @num_extra: the minimum number of elements of space we need
141 * Usually you wouldn't call this yourself; see membuf_add() below. But
142 * you might use this if you need to know about moves within mb->elements
143 * so you can adjust your own pointers/offsets.
145 * It returns the offset *in bytes* between the old locations and the new.
146 * This is because it may not be a whole number of elements, in the case
149 * If you want to check for expandfn failure (which sets errno to
150 * ENOMEM), you can check if membuf_num_space() is < num_extra which will
151 * never otherwise happen.
153 #define membuf_prepare_space(mb, num_extra) \
154 membuf_prepare_space_(tcon_unwrap(mb), \
156 tcon_sizeof((mb), canary))
158 size_t membuf_prepare_space_(struct membuf *mb,
159 size_t num_extra, size_t elemsize);
162 * membuf_add - add to the end of the membuf.
163 * @mb: the MEMBUF() declared membuf.
164 * @num: the number of elements (must be that much space available!).
166 * Returns the pointer to the space just added, in case you want to
167 * populate it afterwards.
169 * Note that this may invalidate existing buf pointers! If you want to
170 * avoid that, call membuf_prepare_space(mb, num) first.
172 #define membuf_add(mb, num) \
173 tcon_cast_ptr(mb, canary, \
174 membuf_add_(tcon_unwrap(mb), (num), \
175 tcon_sizeof((mb), canary)))
177 static inline void *membuf_add_(struct membuf *mb, size_t num, size_t elemsize)
180 membuf_prepare_space_(mb, num, elemsize);
182 oldend = membuf_space_(mb, elemsize);
183 /* We assume expandfn succeeded. */
184 assert(num <= membuf_num_space_(mb));
191 * membuf_cleanup - reset membuf, return elems array for freeing.
192 * @mb: the MEMBUF() declared membuf.
194 * The mb will be empty after this, and crash if you try to expand it.
195 * You can membuf_init() it again, however.
198 * free(membuf_cleanup(&intp_membuf));
200 #define membuf_cleanup(mb) membuf_cleanup_(tcon_unwrap(mb))
202 static inline void *membuf_cleanup_(struct membuf *mb)
204 mb->start = mb->end = mb->max_elems = 0;
209 #endif /* CCAN_MEMBUF_H */