chiark / gitweb /
Merge branch 'running' of login.chiark.greenend.org.uk:public-git/inn-innduct
[innduct.git] / lib / buffer.c
1 /*  $Id: buffer.c 5463 2002-05-06 05:40:46Z rra $
2 **
3 **  Counted, reusable memory buffer.
4 **
5 **  A buffer is an allocated bit of memory with a known size and a separate
6 **  data length.  It's intended to store strings and can be reused repeatedly
7 **  to minimize the number of memory allocations.  Buffers increase in
8 **  increments of 1K.
9 **
10 **  A buffer contains a notion of the data that's been used and the data
11 **  that's been left, used when the buffer is an I/O buffer where lots of data
12 **  is buffered and then slowly processed out of the buffer.  The total length
13 **  of the data is used + left.  If a buffer is just used to store some data,
14 **  used can be set to 0 and left stores the length of the data.
15 */
16
17 #include "config.h"
18 #include "clibrary.h"
19
20 #include "inn/buffer.h"
21 #include "libinn.h"
22
23 /*
24 **  Allocate a new struct buffer and initialize it.
25 */
26 struct buffer *
27 buffer_new(void)
28 {
29     struct buffer *buffer;
30
31     buffer = xmalloc(sizeof(struct buffer));
32     buffer->size = 0;
33     buffer->used = 0;
34     buffer->left = 0;
35     buffer->data = NULL;
36     return buffer;
37 }
38
39
40 /*
41 **  Resize a buffer to be at least as large as the provided second argument.
42 **  Resize buffers to multiples of 1KB to keep the number of reallocations to
43 **  a minimum.  Refuse to resize a buffer to make it smaller.
44 */
45 void
46 buffer_resize(struct buffer *buffer, size_t size)
47 {
48     if (size < buffer->size)
49         return;
50     buffer->size = (size + 1023) & ~1023UL;
51     buffer->data = xrealloc(buffer->data, buffer->size);
52 }
53
54
55 /*
56 **  Replace whatever data is currently in the buffer with the provided data.
57 */
58 void
59 buffer_set(struct buffer *buffer, const char *data, size_t length)
60 {
61     if (length > 0) {
62         buffer_resize(buffer, length);
63         memmove(buffer->data, data, length);
64     }
65     buffer->left = length;
66     buffer->used = 0;
67 }
68
69
70 /*
71 **  Append data to a buffer.  The new data shows up as additional unused data
72 **  at the end of the buffer.  Resize the buffer to multiples of 1KB.
73 */
74 void
75 buffer_append(struct buffer *buffer, const char *data, size_t length)
76 {
77     size_t total;
78
79     if (length == 0)
80         return;
81     total = buffer->used + buffer->left;
82     buffer_resize(buffer, total + length);
83     buffer->left += length;
84     memcpy(buffer->data + total, data, length);
85 }
86
87
88 /*
89 **  Swap the contents of two buffers.
90 */
91 void
92 buffer_swap(struct buffer *one, struct buffer *two)
93 {
94     struct buffer tmp;
95
96     tmp = *one;
97     *one = *two;
98     *two = tmp;
99 }