blob: 05ae708488f0d6ce91de64a9e0d683fb87e45576 [file] [log] [blame] [raw]
Nicholas Marriott4b62b1d2007-07-25 23:13:18 +00001/* $Id: buffer.c,v 1.2 2007-07-25 23:13:18 nicm Exp $ */
Nicholas Marriotta41ece52007-07-09 19:04:12 +00002
3/*
4 * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
5 *
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
15 * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
16 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18
19#include <sys/types.h>
20
21#include <string.h>
22
23#include "tmux.h"
24
25/* Create a buffer. */
26struct buffer *
27buffer_create(size_t size)
28{
29 struct buffer *b;
30
31 if (size == 0)
Nicholas Marriott4b62b1d2007-07-25 23:13:18 +000032 fatalx("zero size");
Nicholas Marriotta41ece52007-07-09 19:04:12 +000033
34 b = xcalloc(1, sizeof *b);
35
36 b->base = xmalloc(size);
37 b->space = size;
38
39 return (b);
40}
41
42/* Destroy a buffer. */
43void
44buffer_destroy(struct buffer *b)
45{
46 xfree(b->base);
47 xfree(b);
48}
49
50/* Empty a buffer. */
51void
52buffer_clear(struct buffer *b)
53{
54 b->size = 0;
55 b->off = 0;
56}
57
58/* Ensure free space for size in buffer. */
59void
60buffer_ensure(struct buffer *b, size_t size)
61{
62 if (size == 0)
Nicholas Marriott4b62b1d2007-07-25 23:13:18 +000063 fatalx("zero size");
Nicholas Marriotta41ece52007-07-09 19:04:12 +000064
65 if (BUFFER_FREE(b) >= size)
66 return;
67
68 if (b->off > 0) {
69 if (b->size > 0)
70 memmove(b->base, b->base + b->off, b->size);
71 b->off = 0;
72 }
73
74 ENSURE_FOR(b->base, b->space, b->size, size);
75}
76
77/* Adjust buffer after data appended. */
78void
79buffer_add(struct buffer *b, size_t size)
80{
81 if (size == 0)
Nicholas Marriott4b62b1d2007-07-25 23:13:18 +000082 fatalx("zero size");
Nicholas Marriotta41ece52007-07-09 19:04:12 +000083 if (size > b->space - b->size)
Nicholas Marriott4b62b1d2007-07-25 23:13:18 +000084 fatalx("overflow");
Nicholas Marriotta41ece52007-07-09 19:04:12 +000085
86 b->size += size;
87}
88
89/* Reverse buffer add. */
90void
91buffer_reverse_add(struct buffer *b, size_t size)
92{
93 if (size == 0)
Nicholas Marriott4b62b1d2007-07-25 23:13:18 +000094 fatalx("zero size");
Nicholas Marriotta41ece52007-07-09 19:04:12 +000095 if (size > b->size)
Nicholas Marriott4b62b1d2007-07-25 23:13:18 +000096 fatalx("underflow");
Nicholas Marriotta41ece52007-07-09 19:04:12 +000097
98 b->size -= size;
99}
100
101/* Adjust buffer after data removed. */
102void
103buffer_remove(struct buffer *b, size_t size)
104{
105 if (size == 0)
Nicholas Marriott4b62b1d2007-07-25 23:13:18 +0000106 fatalx("zero size");
Nicholas Marriotta41ece52007-07-09 19:04:12 +0000107 if (size > b->size)
Nicholas Marriott4b62b1d2007-07-25 23:13:18 +0000108 fatalx("underflow");
Nicholas Marriotta41ece52007-07-09 19:04:12 +0000109
110 b->size -= size;
111 b->off += size;
112}
113
114/* Reverse buffer remove. */
115void
116buffer_reverse_remove(struct buffer *b, size_t size)
117{
118 if (size == 0)
Nicholas Marriott4b62b1d2007-07-25 23:13:18 +0000119 fatalx("zero size");
Nicholas Marriotta41ece52007-07-09 19:04:12 +0000120 if (size > b->off)
Nicholas Marriott4b62b1d2007-07-25 23:13:18 +0000121 fatalx("overflow");
Nicholas Marriotta41ece52007-07-09 19:04:12 +0000122
123 b->size += size;
124 b->off -= size;
125}
126
127/* Insert a section into the buffer. */
128void
129buffer_insert_range(struct buffer *b, size_t base, size_t size)
130{
131 if (size == 0)
Nicholas Marriott4b62b1d2007-07-25 23:13:18 +0000132 fatalx("zero size");
Nicholas Marriotta41ece52007-07-09 19:04:12 +0000133 if (base > b->size)
Nicholas Marriott4b62b1d2007-07-25 23:13:18 +0000134 fatalx("range outside buffer");
Nicholas Marriotta41ece52007-07-09 19:04:12 +0000135
136 buffer_ensure(b, size);
137 memmove(b->base + b->off + base + size,
138 b->base + b->off + base, b->size - base);
139 b->size += size;
140}
141
142/* Delete a section from the buffer. */
143void
144buffer_delete_range(struct buffer *b, size_t base, size_t size)
145{
146 if (size == 0)
Nicholas Marriott4b62b1d2007-07-25 23:13:18 +0000147 fatalx("zero size");
Nicholas Marriotta41ece52007-07-09 19:04:12 +0000148 if (size > b->size)
Nicholas Marriott4b62b1d2007-07-25 23:13:18 +0000149 fatalx("size too big");
Nicholas Marriotta41ece52007-07-09 19:04:12 +0000150 if (base + size > b->size)
Nicholas Marriott4b62b1d2007-07-25 23:13:18 +0000151 fatalx("range outside buffer");
Nicholas Marriotta41ece52007-07-09 19:04:12 +0000152
153 memmove(b->base + b->off + base,
154 b->base + b->off + base + size, b->size - base - size);
155 b->size -= size;
156}
157
158/* Copy data into a buffer. */
159void
160buffer_write(struct buffer *b, const void *data, size_t size)
161{
162 if (size == 0)
Nicholas Marriott4b62b1d2007-07-25 23:13:18 +0000163 fatalx("zero size");
Nicholas Marriotta41ece52007-07-09 19:04:12 +0000164
165 buffer_ensure(b, size);
166 memcpy(BUFFER_IN(b), data, size);
167 buffer_add(b, size);
168}
169
170/* Copy data out of a buffer. */
171void
172buffer_read(struct buffer *b, void *data, size_t size)
173{
174 if (size == 0)
Nicholas Marriott4b62b1d2007-07-25 23:13:18 +0000175 fatalx("zero size");
Nicholas Marriotta41ece52007-07-09 19:04:12 +0000176 if (size > b->size)
Nicholas Marriott4b62b1d2007-07-25 23:13:18 +0000177 fatalx("underflow");
Nicholas Marriotta41ece52007-07-09 19:04:12 +0000178
179 memcpy(data, BUFFER_OUT(b), size);
180 buffer_remove(b, size);
181}