1 /* Copyright (C) 2007 Board of Trustees, Leland Stanford Jr. University.
3 * Permission is hereby granted, free of charge, to any person obtaining a copy
4 * of this software and associated documentation files (the "Software"), to
5 * deal in the Software without restriction, including without limitation the
6 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
7 * sell copies of the Software, and to permit persons to whom the Software is
8 * furnished to do so, subject to the following conditions:
10 * The above copyright notice and this permission notice shall be included in
11 * all copies or substantial portions of the Software.
13 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
18 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
28 /* Initializes 'b' as an empty buffer that contains the 'allocated' bytes of
29 * memory starting at 'base'.
31 * 'base' should ordinarily be the first byte of a region obtained from
32 * malloc(), but in circumstances where it can be guaranteed that 'b' will
33 * never need to be expanded or freed, it can be a pointer into arbitrary
36 buffer_use(struct buffer *b, void *base, size_t allocated)
38 b->base = b->data = base;
39 b->allocated = allocated;
41 b->l2 = b->l3 = b->l4 = NULL;
45 /* Initializes 'b' as a buffer with an initial capacity of 'size' bytes. */
47 buffer_init(struct buffer *b, size_t size)
49 buffer_use(b, size ? xmalloc(size) : NULL, size);
52 /* Frees memory that 'b' points to. */
54 buffer_uninit(struct buffer *b)
61 /* Frees memory that 'b' points to and allocates a new buffer */
63 buffer_reinit(struct buffer *b, size_t size)
69 /* Creates and returns a new buffer with an initial capacity of 'size'
72 buffer_new(size_t size)
74 struct buffer *b = xmalloc(sizeof *b);
80 buffer_clone(const struct buffer *buffer)
82 /* FIXME: reference counting. */
83 struct buffer *b = buffer_new(buffer->size);
84 buffer_put(b, buffer->data, buffer->size);
88 /* Frees memory that 'b' points to, as well as 'b' itself. */
90 buffer_delete(struct buffer *b)
98 /* Returns the number of bytes of headroom in 'b', that is, the number of bytes
99 * of unused space in buffer 'b' before the data that is in use. (Most
100 * commonly, the data in a buffer is at its beginning, and thus the buffer's
103 buffer_headroom(struct buffer *b)
105 return b->data - b->base;
108 /* Returns the number of bytes that may be appended to the tail end of buffer
109 * 'b' before the buffer must be reallocated. */
111 buffer_tailroom(struct buffer *b)
113 return buffer_end(b) - buffer_tail(b);
116 /* Ensures that 'b' has room for at least 'size' bytes at its tail end,
117 * reallocating and copying its data if necessary. */
119 buffer_reserve_tailroom(struct buffer *b, size_t size)
121 if (size > buffer_tailroom(b)) {
122 size_t new_allocated = b->allocated + MAX(size, 64);
123 void *new_base = xmalloc(new_allocated);
124 uintptr_t base_delta = new_base - b->base;
125 memcpy(new_base, b->base, b->allocated);
128 b->allocated = new_allocated;
129 b->data += base_delta;
143 buffer_reserve_headroom(struct buffer *b, size_t size)
145 assert(size <= buffer_headroom(b));
148 /* Appends 'size' bytes of data to the tail end of 'b', reallocating and
149 * copying its data if necessary. Returns a pointer to the first byte of the
150 * new data, which is left uninitialized. */
152 buffer_put_uninit(struct buffer *b, size_t size)
155 buffer_reserve_tailroom(b, size);
161 /* Appends the 'size' bytes of data in 'p' to the tail end of 'b'. Data in 'b'
162 * is reallocated and copied if necessary. */
164 buffer_put(struct buffer *b, const void *p, size_t size)
166 memcpy(buffer_put_uninit(b, size), p, size);
170 buffer_push_uninit(struct buffer *b, size_t size)
172 buffer_reserve_headroom(b, size);
178 /* If 'b' contains at least 'offset + size' bytes of data, returns a pointer to
179 * byte 'offset'. Otherwise, returns a null pointers. */
181 buffer_at(const struct buffer *b, size_t offset, size_t size)
183 return offset + size <= b->size ? (char *) b->data + offset : NULL;
186 /* Returns a pointer to byte 'offset' in 'b', which must contain at least
187 * 'offset + size' bytes of data. */
189 buffer_at_assert(const struct buffer *b, size_t offset, size_t size)
191 assert(offset + size <= b->size);
192 return ((char *) b->data) + offset;
195 /* Returns the byte following the last byte of data in use in 'b'. */
197 buffer_tail(const struct buffer *b)
199 return (char *) b->data + b->size;
202 /* Returns the byte following the last byte allocated for use (but not
203 * necessarily in use) by 'b'. */
205 buffer_end(const struct buffer *b)
207 return (char *) b->base + b->allocated;
210 /* Clears any data from 'b'. */
212 buffer_clear(struct buffer *b)
218 /* Removes 'size' bytes from the head end of 'b', which must contain at least
219 * 'size' bytes of data. */
221 buffer_pull(struct buffer *b, size_t size)
223 assert(b->size >= size);