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