xref: /openbsd/usr.sbin/nsd/buffer.c (revision d3fecca9)
1 /*
2  * buffer.c -- generic memory buffer .
3  *
4  * Copyright (c) 2001-2006, NLnet Labs. All rights reserved.
5  *
6  * See LICENSE for the license.
7  *
8  */
9 
10 #include "config.h"
11 #include <stdlib.h>
12 #include <stdio.h>
13 
14 #include "buffer.h"
15 
16 static void
buffer_cleanup(void * arg)17 buffer_cleanup(void *arg)
18 {
19 	buffer_type *buffer = (buffer_type *) arg;
20 	assert(!buffer->_fixed);
21 	free(buffer->_data);
22 }
23 
24 buffer_type *
buffer_create(region_type * region,size_t capacity)25 buffer_create(region_type *region, size_t capacity)
26 {
27 	buffer_type *buffer
28 		= (buffer_type *) region_alloc(region, sizeof(buffer_type));
29 	if (!buffer)
30 		return NULL;
31 
32 	buffer->_data = (uint8_t *) xalloc(capacity);
33 	buffer->_position = 0;
34 	buffer->_limit = buffer->_capacity = capacity;
35 	buffer->_fixed = 0;
36 	buffer_invariant(buffer);
37 
38 	region_add_cleanup(region, buffer_cleanup, buffer);
39 
40 	return buffer;
41 }
42 
43 void
buffer_create_from(buffer_type * buffer,void * data,size_t size)44 buffer_create_from(buffer_type *buffer, void *data, size_t size)
45 {
46 	assert(data);
47 
48 	buffer->_position = 0;
49 	buffer->_limit = buffer->_capacity = size;
50 	buffer->_data = (uint8_t *) data;
51 	buffer->_fixed = 1;
52 
53 	buffer_invariant(buffer);
54 }
55 
56 void
buffer_clear(buffer_type * buffer)57 buffer_clear(buffer_type *buffer)
58 {
59 	buffer_invariant(buffer);
60 
61 	buffer->_position = 0;
62 	buffer->_limit = buffer->_capacity;
63 }
64 
65 void
buffer_flip(buffer_type * buffer)66 buffer_flip(buffer_type *buffer)
67 {
68 	buffer_invariant(buffer);
69 
70 	buffer->_limit = buffer->_position;
71 	buffer->_position = 0;
72 }
73 
74 void
buffer_rewind(buffer_type * buffer)75 buffer_rewind(buffer_type *buffer)
76 {
77 	buffer_invariant(buffer);
78 
79 	buffer->_position = 0;
80 }
81 
82 void
buffer_set_capacity(buffer_type * buffer,size_t capacity)83 buffer_set_capacity(buffer_type *buffer, size_t capacity)
84 {
85 	buffer_invariant(buffer);
86 	assert(buffer->_position <= capacity);
87 	buffer->_data = (uint8_t *) xrealloc(buffer->_data, capacity);
88 	buffer->_limit = buffer->_capacity = capacity;
89 }
90 
91 void
buffer_reserve(buffer_type * buffer,size_t amount)92 buffer_reserve(buffer_type *buffer, size_t amount)
93 {
94 	buffer_invariant(buffer);
95 	assert(!buffer->_fixed);
96 	if (buffer->_capacity < buffer->_position + amount) {
97 		size_t new_capacity = buffer->_capacity * 3 / 2;
98 		if (new_capacity < buffer->_position + amount) {
99 			new_capacity = buffer->_position + amount;
100 		}
101 		buffer_set_capacity(buffer, new_capacity);
102 	}
103 	buffer->_limit = buffer->_capacity;
104 }
105 
106 int
buffer_printf(buffer_type * buffer,const char * format,...)107 buffer_printf(buffer_type *buffer, const char *format, ...)
108 {
109 	va_list args;
110 	int written;
111 	size_t remaining;
112 
113 	buffer_invariant(buffer);
114 	assert(buffer->_limit == buffer->_capacity);
115 
116 	remaining = buffer_remaining(buffer);
117 	va_start(args, format);
118 	written = vsnprintf((char *) buffer_current(buffer), remaining,
119 			    format, args);
120 	va_end(args);
121 	if (written >= 0 && (size_t) written >= remaining) {
122 		buffer_reserve(buffer, written + 1);
123 		va_start(args, format);
124 		written = vsnprintf((char *) buffer_current(buffer),
125 				    buffer_remaining(buffer),
126 				    format, args);
127 		va_end(args);
128 	}
129 	buffer->_position += written;
130 	return written;
131 }
132