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 *
sldns_buffer_new(size_t capacity)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
sldns_buffer_new_frm_data(sldns_buffer * buffer,void * data,size_t size)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
sldns_buffer_init_frm_data(sldns_buffer * buffer,void * data,size_t size)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
sldns_buffer_set_capacity(sldns_buffer * buffer,size_t capacity)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
sldns_buffer_reserve(sldns_buffer * buffer,size_t amount)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
sldns_buffer_printf(sldns_buffer * buffer,const char * format,...)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
sldns_buffer_free(sldns_buffer * buffer)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
sldns_buffer_copy(sldns_buffer * result,sldns_buffer * from)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