sbuffer.c revision 356345
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
18sldns_buffer *
19sldns_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
43void
44sldns_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
64void
65sldns_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
73int
74sldns_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
92int
93sldns_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
112int
113sldns_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
137void
138sldns_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
150void
151sldns_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