xref: /dragonfly/contrib/ldns/buffer.c (revision ee791feb)
1825eb42bSJan Lentfer /*
2825eb42bSJan Lentfer  * buffer.c -- generic memory buffer .
3825eb42bSJan Lentfer  *
4825eb42bSJan Lentfer  * Copyright (c) 2001-2008, NLnet Labs. All rights reserved.
5825eb42bSJan Lentfer  *
6825eb42bSJan Lentfer  * See LICENSE for the license.
7825eb42bSJan Lentfer  *
8825eb42bSJan Lentfer  */
9825eb42bSJan Lentfer 
10825eb42bSJan Lentfer #include <ldns/config.h>
11825eb42bSJan Lentfer 
12825eb42bSJan Lentfer #include <ldns/ldns.h>
13825eb42bSJan Lentfer #include <ldns/buffer.h>
14825eb42bSJan Lentfer 
15825eb42bSJan Lentfer ldns_buffer *
ldns_buffer_new(size_t capacity)16825eb42bSJan Lentfer ldns_buffer_new(size_t capacity)
17825eb42bSJan Lentfer {
18825eb42bSJan Lentfer 	ldns_buffer *buffer = LDNS_MALLOC(ldns_buffer);
19825eb42bSJan Lentfer 
20825eb42bSJan Lentfer 	if (!buffer) {
21825eb42bSJan Lentfer 		return NULL;
22825eb42bSJan Lentfer 	}
23825eb42bSJan Lentfer 
24825eb42bSJan Lentfer 	buffer->_data = (uint8_t *) LDNS_XMALLOC(uint8_t, capacity);
25825eb42bSJan Lentfer 	if (!buffer->_data) {
26825eb42bSJan Lentfer 		LDNS_FREE(buffer);
27825eb42bSJan Lentfer 		return NULL;
28825eb42bSJan Lentfer 	}
29825eb42bSJan Lentfer 
30825eb42bSJan Lentfer 	buffer->_position = 0;
31825eb42bSJan Lentfer 	buffer->_limit = buffer->_capacity = capacity;
32825eb42bSJan Lentfer 	buffer->_fixed = 0;
33825eb42bSJan Lentfer 	buffer->_status = LDNS_STATUS_OK;
34825eb42bSJan Lentfer 
35825eb42bSJan Lentfer 	ldns_buffer_invariant(buffer);
36825eb42bSJan Lentfer 
37825eb42bSJan Lentfer 	return buffer;
38825eb42bSJan Lentfer }
39825eb42bSJan Lentfer 
40825eb42bSJan Lentfer void
ldns_buffer_new_frm_data(ldns_buffer * buffer,const void * data,size_t size)415340022aSzrj ldns_buffer_new_frm_data(ldns_buffer *buffer, const void *data, size_t size)
42825eb42bSJan Lentfer {
43825eb42bSJan Lentfer 	assert(data != NULL);
44825eb42bSJan Lentfer 
45825eb42bSJan Lentfer 	buffer->_position = 0;
46825eb42bSJan Lentfer 	buffer->_limit = buffer->_capacity = size;
47825eb42bSJan Lentfer 	buffer->_fixed = 0;
48ac996e71SJan Lentfer 	buffer->_data = LDNS_XMALLOC(uint8_t, size);
49ac996e71SJan Lentfer 	if(!buffer->_data) {
50ac996e71SJan Lentfer 		buffer->_status = LDNS_STATUS_MEM_ERR;
51ac996e71SJan Lentfer 		return;
52ac996e71SJan Lentfer 	}
53ac996e71SJan Lentfer 	memcpy(buffer->_data, data, size);
54825eb42bSJan Lentfer 	buffer->_status = LDNS_STATUS_OK;
55825eb42bSJan Lentfer 
56825eb42bSJan Lentfer 	ldns_buffer_invariant(buffer);
57825eb42bSJan Lentfer }
58825eb42bSJan Lentfer 
59825eb42bSJan Lentfer bool
ldns_buffer_set_capacity(ldns_buffer * buffer,size_t capacity)60825eb42bSJan Lentfer ldns_buffer_set_capacity(ldns_buffer *buffer, size_t capacity)
61825eb42bSJan Lentfer {
62825eb42bSJan Lentfer 	void *data;
63825eb42bSJan Lentfer 
64825eb42bSJan Lentfer 	ldns_buffer_invariant(buffer);
65825eb42bSJan Lentfer 	assert(buffer->_position <= capacity);
66*ee791febSAntonio Huete Jimenez 	assert(!buffer->_fixed);
67825eb42bSJan Lentfer 
68825eb42bSJan Lentfer 	data = (uint8_t *) LDNS_XREALLOC(buffer->_data, uint8_t, capacity);
69825eb42bSJan Lentfer 	if (!data) {
70825eb42bSJan Lentfer 		buffer->_status = LDNS_STATUS_MEM_ERR;
71825eb42bSJan Lentfer 		return false;
72825eb42bSJan Lentfer 	} else {
73825eb42bSJan Lentfer 		buffer->_data = data;
74825eb42bSJan Lentfer 		buffer->_limit = buffer->_capacity = capacity;
75825eb42bSJan Lentfer 		return true;
76825eb42bSJan Lentfer 	}
77825eb42bSJan Lentfer }
78825eb42bSJan Lentfer 
79825eb42bSJan Lentfer bool
ldns_buffer_reserve(ldns_buffer * buffer,size_t amount)80825eb42bSJan Lentfer ldns_buffer_reserve(ldns_buffer *buffer, size_t amount)
81825eb42bSJan Lentfer {
82825eb42bSJan Lentfer 	ldns_buffer_invariant(buffer);
83825eb42bSJan Lentfer 	if (buffer->_capacity < buffer->_position + amount) {
84825eb42bSJan Lentfer 		size_t new_capacity = buffer->_capacity * 3 / 2;
85825eb42bSJan Lentfer 
86825eb42bSJan Lentfer 		if (new_capacity < buffer->_position + amount) {
87825eb42bSJan Lentfer 			new_capacity = buffer->_position + amount;
88825eb42bSJan Lentfer 		}
89825eb42bSJan Lentfer 		if (!ldns_buffer_set_capacity(buffer, new_capacity)) {
90825eb42bSJan Lentfer 			buffer->_status = LDNS_STATUS_MEM_ERR;
91825eb42bSJan Lentfer 			return false;
92825eb42bSJan Lentfer 		}
93825eb42bSJan Lentfer 	}
94825eb42bSJan Lentfer 	buffer->_limit = buffer->_capacity;
95825eb42bSJan Lentfer 	return true;
96825eb42bSJan Lentfer }
97825eb42bSJan Lentfer 
98825eb42bSJan Lentfer int
ldns_buffer_printf(ldns_buffer * buffer,const char * format,...)99825eb42bSJan Lentfer ldns_buffer_printf(ldns_buffer *buffer, const char *format, ...)
100825eb42bSJan Lentfer {
101825eb42bSJan Lentfer 	va_list args;
102825eb42bSJan Lentfer 	int written = 0;
103825eb42bSJan Lentfer 	size_t remaining;
104825eb42bSJan Lentfer 
105825eb42bSJan Lentfer 	if (ldns_buffer_status_ok(buffer)) {
106825eb42bSJan Lentfer 		ldns_buffer_invariant(buffer);
107825eb42bSJan Lentfer 		assert(buffer->_limit == buffer->_capacity);
108825eb42bSJan Lentfer 
109825eb42bSJan Lentfer 		remaining = ldns_buffer_remaining(buffer);
110825eb42bSJan Lentfer 		va_start(args, format);
111825eb42bSJan Lentfer 		written = vsnprintf((char *) ldns_buffer_current(buffer), remaining,
112825eb42bSJan Lentfer 				    format, args);
113825eb42bSJan Lentfer 		va_end(args);
114825eb42bSJan Lentfer 		if (written == -1) {
115825eb42bSJan Lentfer 			buffer->_status = LDNS_STATUS_INTERNAL_ERR;
116825eb42bSJan Lentfer 			return -1;
117825eb42bSJan Lentfer 		} else if ((size_t) written >= remaining) {
118825eb42bSJan Lentfer 			if (!ldns_buffer_reserve(buffer, (size_t) written + 1)) {
119825eb42bSJan Lentfer 				buffer->_status = LDNS_STATUS_MEM_ERR;
120825eb42bSJan Lentfer 				return -1;
121825eb42bSJan Lentfer 			}
122825eb42bSJan Lentfer 			va_start(args, format);
123825eb42bSJan Lentfer 			written = vsnprintf((char *) ldns_buffer_current(buffer),
124825eb42bSJan Lentfer 			    ldns_buffer_remaining(buffer), format, args);
125825eb42bSJan Lentfer 			va_end(args);
126825eb42bSJan Lentfer 			if (written == -1) {
127825eb42bSJan Lentfer 				buffer->_status = LDNS_STATUS_INTERNAL_ERR;
128825eb42bSJan Lentfer 				return -1;
129825eb42bSJan Lentfer 			}
130825eb42bSJan Lentfer 		}
131825eb42bSJan Lentfer 		buffer->_position += written;
132825eb42bSJan Lentfer 	}
133825eb42bSJan Lentfer 	return written;
134825eb42bSJan Lentfer }
135825eb42bSJan Lentfer 
136825eb42bSJan Lentfer void
ldns_buffer_free(ldns_buffer * buffer)137825eb42bSJan Lentfer ldns_buffer_free(ldns_buffer *buffer)
138825eb42bSJan Lentfer {
139825eb42bSJan Lentfer 	if (!buffer) {
140825eb42bSJan Lentfer 		return;
141825eb42bSJan Lentfer 	}
142825eb42bSJan Lentfer 
143d1b2b5caSJohn Marino 	if (!buffer->_fixed)
144825eb42bSJan Lentfer 		LDNS_FREE(buffer->_data);
145825eb42bSJan Lentfer 
146825eb42bSJan Lentfer 	LDNS_FREE(buffer);
147825eb42bSJan Lentfer }
148825eb42bSJan Lentfer 
149825eb42bSJan Lentfer void *
ldns_buffer_export(ldns_buffer * buffer)150825eb42bSJan Lentfer ldns_buffer_export(ldns_buffer *buffer)
151825eb42bSJan Lentfer {
152825eb42bSJan Lentfer 	buffer->_fixed = 1;
153825eb42bSJan Lentfer 	return buffer->_data;
154825eb42bSJan Lentfer }
155825eb42bSJan Lentfer 
156825eb42bSJan Lentfer int
ldns_bgetc(ldns_buffer * buffer)157825eb42bSJan Lentfer ldns_bgetc(ldns_buffer *buffer)
158825eb42bSJan Lentfer {
159825eb42bSJan Lentfer 	if (!ldns_buffer_available_at(buffer, buffer->_position, sizeof(uint8_t))) {
160825eb42bSJan Lentfer 		ldns_buffer_set_position(buffer, ldns_buffer_limit(buffer));
161825eb42bSJan Lentfer 		/* ldns_buffer_rewind(buffer);*/
162825eb42bSJan Lentfer 		return EOF;
163825eb42bSJan Lentfer 	}
164825eb42bSJan Lentfer 	return (int)ldns_buffer_read_u8(buffer);
165825eb42bSJan Lentfer }
166825eb42bSJan Lentfer 
167825eb42bSJan Lentfer void
ldns_buffer_copy(ldns_buffer * result,const ldns_buffer * from)1685340022aSzrj ldns_buffer_copy(ldns_buffer* result, const ldns_buffer* from)
169825eb42bSJan Lentfer {
170825eb42bSJan Lentfer 	size_t tocopy = ldns_buffer_limit(from);
171825eb42bSJan Lentfer 
172825eb42bSJan Lentfer 	if(tocopy > ldns_buffer_capacity(result))
173825eb42bSJan Lentfer 		tocopy = ldns_buffer_capacity(result);
174825eb42bSJan Lentfer 	ldns_buffer_clear(result);
175825eb42bSJan Lentfer 	ldns_buffer_write(result, ldns_buffer_begin(from), tocopy);
176825eb42bSJan Lentfer 	ldns_buffer_flip(result);
177825eb42bSJan Lentfer }
178