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;
44 /* Initializes 'b' as a buffer with an initial capacity of 'size' bytes. */
46 buffer_init(struct buffer *b, size_t size)
48 buffer_use(b, size ? xmalloc(size) : NULL, size);
51 /* Frees memory that 'b' points to. */
53 buffer_uninit(struct buffer *b)
60 /* Frees memory that 'b' points to and allocates a new buffer */
62 buffer_reinit(struct buffer *b, size_t size)
68 /* Creates and returns a new buffer with an initial capacity of 'size'
71 buffer_new(size_t size)
73 struct buffer *b = xmalloc(sizeof *b);
78 /* Frees memory that 'b' points to, as well as 'b' itself. */
80 buffer_delete(struct buffer *b)
88 /* Returns the number of bytes of headroom in 'b', that is, the number of bytes
89 * of unused space in buffer 'b' before the data that is in use. (Most
90 * commonly, the data in a buffer is at its beginning, and thus the buffer's
93 buffer_headroom(struct buffer *b)
95 return b->data - b->base;
98 /* Returns the number of bytes that may be appended to the tail end of buffer
99 * 'b' before the buffer must be reallocated. */
101 buffer_tailroom(struct buffer *b)
103 return buffer_end(b) - buffer_tail(b);
106 /* Ensures that 'b' has room for at least 'size' bytes at its tail end,
107 * reallocating and copying its data if necessary. */
109 buffer_reserve_tailroom(struct buffer *b, size_t size)
111 if (size > buffer_tailroom(b)) {
112 size_t headroom = buffer_headroom(b);
113 size_t new_allocated = b->allocated + MAX(size, 64);
114 void *new_base = xmalloc(new_allocated);
115 memcpy(new_base, b->base, b->allocated);
118 b->allocated = new_allocated;
119 b->data = new_base + headroom;
123 /* Appends 'size' bytes of data to the tail end of 'b', reallocating and
124 * copying its data if necessary. Returns a pointer to the first byte of the
125 * new data, which is left uninitialized. */
127 buffer_put_uninit(struct buffer *b, size_t size)
130 buffer_reserve_tailroom(b, size);
136 /* Appends the 'size' bytes of data in 'p' to the tail end of 'b'. Data in 'b'
137 * is reallocated and copied if necessary. */
139 buffer_put(struct buffer *b, const void *p, size_t size)
141 memcpy(buffer_put_uninit(b, size), p, size);
144 /* If 'b' contains at least 'offset + size' bytes of data, returns a pointer to
145 * byte 'offset'. Otherwise, returns a null pointers. */
147 buffer_at(const struct buffer *b, size_t offset, size_t size)
149 return offset + size <= b->size ? (char *) b->data + offset : NULL;
152 /* Returns a pointer to byte 'offset' in 'b', which must contain at least
153 * 'offset + size' bytes of data. */
155 buffer_at_assert(const struct buffer *b, size_t offset, size_t size)
157 assert(offset + size <= b->size);
158 return ((char *) b->data) + offset;
161 /* Returns the byte following the last byte of data in use in 'b'. */
163 buffer_tail(const struct buffer *b)
165 return (char *) b->data + b->size;
168 /* Returns the byte following the last byte allocated for use (but not
169 * necessarily in use) by 'b'. */
171 buffer_end(const struct buffer *b)
173 return (char *) b->base + b->allocated;
176 /* Clears any data from 'b'. */
178 buffer_clear(struct buffer *b)
184 /* Removes 'size' bytes from the head end of 'b', which must contain at least
185 * 'size' bytes of data. */
187 buffer_pull(struct buffer *b, size_t size)
189 assert(b->size >= size);