xref: /freebsd/contrib/unbound/sldns/sbuffer.c (revision 5ca8e32633c4ffbbcd6762e5888b6a4ba0708c6c)
1 /*
2  * buffer.c -- generic memory buffer .
3  *
4  * Copyright (c) 2001-2008, NLnet Labs. All rights reserved.
5  *
6  * See LICENSE for the license.
7  *
8  */
9 /**
10  * \file
11  *
12  * This file contains the definition of sldns_buffer, and functions to manipulate those.
13  */
14 #include "config.h"
15 #include "sldns/sbuffer.h"
16 #include <stdarg.h>
17 
18 sldns_buffer *
19 sldns_buffer_new(size_t capacity)
20 {
21 	sldns_buffer *buffer = (sldns_buffer*)malloc(sizeof(sldns_buffer));
22 
23 	if (!buffer) {
24 		return NULL;
25 	}
26 
27 	buffer->_data = (uint8_t *) malloc(capacity);
28 	if (!buffer->_data) {
29 		free(buffer);
30 		return NULL;
31 	}
32 
33 	buffer->_position = 0;
34 	buffer->_limit = buffer->_capacity = capacity;
35 	buffer->_fixed = 0;
36 	buffer->_status_err = 0;
37 
38 	sldns_buffer_invariant(buffer);
39 
40 	return buffer;
41 }
42 
43 void
44 sldns_buffer_new_frm_data(sldns_buffer *buffer, void *data, size_t size)
45 {
46 	assert(data != NULL);
47 
48 	buffer->_position = 0;
49 	buffer->_limit = buffer->_capacity = size;
50 	buffer->_fixed = 0;
51 	if (!buffer->_fixed && buffer->_data)
52 		free(buffer->_data);
53 	buffer->_data = malloc(size);
54 	if(!buffer->_data) {
55 		buffer->_status_err = 1;
56 		return;
57 	}
58 	memcpy(buffer->_data, data, size);
59 	buffer->_status_err = 0;
60 
61 	sldns_buffer_invariant(buffer);
62 }
63 
64 void
65 sldns_buffer_init_frm_data(sldns_buffer *buffer, void *data, size_t size)
66 {
67 	memset(buffer, 0, sizeof(*buffer));
68 	buffer->_data = data;
69 	buffer->_capacity = buffer->_limit = size;
70 	buffer->_fixed = 1;
71 }
72 
73 int
74 sldns_buffer_set_capacity(sldns_buffer *buffer, size_t capacity)
75 {
76 	void *data;
77 
78 	sldns_buffer_invariant(buffer);
79 	assert(buffer->_position <= capacity && !buffer->_fixed);
80 
81 	data = (uint8_t *) realloc(buffer->_data, capacity);
82 	if (!data) {
83 		buffer->_status_err = 1;
84 		return 0;
85 	} else {
86 		buffer->_data = data;
87 		buffer->_limit = buffer->_capacity = capacity;
88 		return 1;
89 	}
90 }
91 
92 int
93 sldns_buffer_reserve(sldns_buffer *buffer, size_t amount)
94 {
95 	sldns_buffer_invariant(buffer);
96 	assert(!buffer->_fixed);
97 	if (buffer->_capacity < buffer->_position + amount) {
98 		size_t new_capacity = buffer->_capacity * 3 / 2;
99 
100 		if (new_capacity < buffer->_position + amount) {
101 			new_capacity = buffer->_position + amount;
102 		}
103 		if (!sldns_buffer_set_capacity(buffer, new_capacity)) {
104 			buffer->_status_err = 1;
105 			return 0;
106 		}
107 	}
108 	buffer->_limit = buffer->_capacity;
109 	return 1;
110 }
111 
112 int
113 sldns_buffer_printf(sldns_buffer *buffer, const char *format, ...)
114 {
115 	va_list args;
116 	int written = 0;
117 	size_t remaining;
118 
119 	if (sldns_buffer_status_ok(buffer)) {
120 		sldns_buffer_invariant(buffer);
121 		assert(buffer->_limit == buffer->_capacity);
122 
123 		remaining = sldns_buffer_remaining(buffer);
124 		va_start(args, format);
125 		written = vsnprintf((char *) sldns_buffer_current(buffer), remaining,
126 				    format, args);
127 		va_end(args);
128 		if (written == -1) {
129 			buffer->_status_err = 1;
130 			return -1;
131 		}
132 		buffer->_position += written;
133 	}
134 	return written;
135 }
136 
137 void
138 sldns_buffer_free(sldns_buffer *buffer)
139 {
140 	if (!buffer) {
141 		return;
142 	}
143 
144 	if (!buffer->_fixed)
145 		free(buffer->_data);
146 
147 	free(buffer);
148 }
149 
150 void
151 sldns_buffer_copy(sldns_buffer* result, sldns_buffer* from)
152 {
153 	size_t tocopy = sldns_buffer_limit(from);
154 
155 	if(tocopy > sldns_buffer_capacity(result))
156 		tocopy = sldns_buffer_capacity(result);
157 	sldns_buffer_clear(result);
158 	sldns_buffer_write(result, sldns_buffer_begin(from), tocopy);
159 	sldns_buffer_flip(result);
160 }
161