xref: /dragonfly/contrib/ldns/buffer.c (revision bcb3e04d)
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 #include <ldns/config.h>
11 
12 #include <ldns/ldns.h>
13 #include <ldns/buffer.h>
14 
15 ldns_buffer *
16 ldns_buffer_new(size_t capacity)
17 {
18 	ldns_buffer *buffer = LDNS_MALLOC(ldns_buffer);
19 
20 	if (!buffer) {
21 		return NULL;
22 	}
23 
24 	buffer->_data = (uint8_t *) LDNS_XMALLOC(uint8_t, capacity);
25 	if (!buffer->_data) {
26 		LDNS_FREE(buffer);
27 		return NULL;
28 	}
29 
30 	buffer->_position = 0;
31 	buffer->_limit = buffer->_capacity = capacity;
32 	buffer->_fixed = 0;
33 	buffer->_status = LDNS_STATUS_OK;
34 
35 	ldns_buffer_invariant(buffer);
36 
37 	return buffer;
38 }
39 
40 void
41 ldns_buffer_new_frm_data(ldns_buffer *buffer, void *data, size_t size)
42 {
43 	assert(data != NULL);
44 
45 	buffer->_position = 0;
46 	buffer->_limit = buffer->_capacity = size;
47 	buffer->_data = LDNS_XMALLOC(uint8_t, size);
48 	memcpy(buffer->_data, data, size);
49 	buffer->_fixed = 0;
50 	buffer->_status = LDNS_STATUS_OK;
51 
52 	ldns_buffer_invariant(buffer);
53 }
54 
55 bool
56 ldns_buffer_set_capacity(ldns_buffer *buffer, size_t capacity)
57 {
58 	void *data;
59 
60 	ldns_buffer_invariant(buffer);
61 	assert(buffer->_position <= capacity);
62 
63 	data = (uint8_t *) LDNS_XREALLOC(buffer->_data, uint8_t, capacity);
64 	if (!data) {
65 		buffer->_status = LDNS_STATUS_MEM_ERR;
66 		return false;
67 	} else {
68 		buffer->_data = data;
69 		buffer->_limit = buffer->_capacity = capacity;
70 		return true;
71 	}
72 }
73 
74 bool
75 ldns_buffer_reserve(ldns_buffer *buffer, size_t amount)
76 {
77 	ldns_buffer_invariant(buffer);
78 	assert(!buffer->_fixed);
79 	if (buffer->_capacity < buffer->_position + amount) {
80 		size_t new_capacity = buffer->_capacity * 3 / 2;
81 
82 		if (new_capacity < buffer->_position + amount) {
83 			new_capacity = buffer->_position + amount;
84 		}
85 		if (!ldns_buffer_set_capacity(buffer, new_capacity)) {
86 			buffer->_status = LDNS_STATUS_MEM_ERR;
87 			return false;
88 		}
89 	}
90 	buffer->_limit = buffer->_capacity;
91 	return true;
92 }
93 
94 int
95 ldns_buffer_printf(ldns_buffer *buffer, const char *format, ...)
96 {
97 	va_list args;
98 	int written = 0;
99 	size_t remaining;
100 
101 	if (ldns_buffer_status_ok(buffer)) {
102 		ldns_buffer_invariant(buffer);
103 		assert(buffer->_limit == buffer->_capacity);
104 
105 		remaining = ldns_buffer_remaining(buffer);
106 		va_start(args, format);
107 		written = vsnprintf((char *) ldns_buffer_current(buffer), remaining,
108 				    format, args);
109 		va_end(args);
110 		if (written == -1) {
111 			buffer->_status = LDNS_STATUS_INTERNAL_ERR;
112 			return -1;
113 		} else if ((size_t) written >= remaining) {
114 			if (!ldns_buffer_reserve(buffer, (size_t) written + 1)) {
115 				buffer->_status = LDNS_STATUS_MEM_ERR;
116 				return -1;
117 			}
118 			va_start(args, format);
119 			written = vsnprintf((char *) ldns_buffer_current(buffer),
120 			    ldns_buffer_remaining(buffer), format, args);
121 			va_end(args);
122 			if (written == -1) {
123 				buffer->_status = LDNS_STATUS_INTERNAL_ERR;
124 				return -1;
125 			}
126 		}
127 		buffer->_position += written;
128 	}
129 	return written;
130 }
131 
132 void
133 ldns_buffer_free(ldns_buffer *buffer)
134 {
135 	if (!buffer) {
136 		return;
137 	}
138 
139 	LDNS_FREE(buffer->_data);
140 
141 	LDNS_FREE(buffer);
142 }
143 
144 void *
145 ldns_buffer_export(ldns_buffer *buffer)
146 {
147 	buffer->_fixed = 1;
148 	return buffer->_data;
149 }
150 
151 int
152 ldns_bgetc(ldns_buffer *buffer)
153 {
154 	if (!ldns_buffer_available_at(buffer, buffer->_position, sizeof(uint8_t))) {
155 		ldns_buffer_set_position(buffer, ldns_buffer_limit(buffer));
156 		/* ldns_buffer_rewind(buffer);*/
157 		return EOF;
158 	}
159 	return (int)ldns_buffer_read_u8(buffer);
160 }
161 
162 void
163 ldns_buffer_copy(ldns_buffer* result, ldns_buffer* from)
164 {
165 	size_t tocopy = ldns_buffer_limit(from);
166 
167 	if(tocopy > ldns_buffer_capacity(result))
168 		tocopy = ldns_buffer_capacity(result);
169 	ldns_buffer_clear(result);
170 	ldns_buffer_write(result, ldns_buffer_begin(from), tocopy);
171 	ldns_buffer_flip(result);
172 }
173