xref: /freebsd/contrib/unbound/sldns/sbuffer.c (revision 0eefd3079a04edf4cf315403beb0344724567f42)
109a3aaf3SDag-Erling Smørgrav /*
209a3aaf3SDag-Erling Smørgrav  * buffer.c -- generic memory buffer .
309a3aaf3SDag-Erling Smørgrav  *
409a3aaf3SDag-Erling Smørgrav  * Copyright (c) 2001-2008, NLnet Labs. All rights reserved.
509a3aaf3SDag-Erling Smørgrav  *
609a3aaf3SDag-Erling Smørgrav  * See LICENSE for the license.
709a3aaf3SDag-Erling Smørgrav  *
809a3aaf3SDag-Erling Smørgrav  */
909a3aaf3SDag-Erling Smørgrav /**
1009a3aaf3SDag-Erling Smørgrav  * \file
1109a3aaf3SDag-Erling Smørgrav  *
1209a3aaf3SDag-Erling Smørgrav  * This file contains the definition of sldns_buffer, and functions to manipulate those.
1309a3aaf3SDag-Erling Smørgrav  */
1409a3aaf3SDag-Erling Smørgrav #include "config.h"
1509a3aaf3SDag-Erling Smørgrav #include "sldns/sbuffer.h"
1609a3aaf3SDag-Erling Smørgrav #include <stdarg.h>
1709a3aaf3SDag-Erling Smørgrav 
1809a3aaf3SDag-Erling Smørgrav sldns_buffer *
sldns_buffer_new(size_t capacity)1909a3aaf3SDag-Erling Smørgrav sldns_buffer_new(size_t capacity)
2009a3aaf3SDag-Erling Smørgrav {
2109a3aaf3SDag-Erling Smørgrav 	sldns_buffer *buffer = (sldns_buffer*)malloc(sizeof(sldns_buffer));
2209a3aaf3SDag-Erling Smørgrav 
2309a3aaf3SDag-Erling Smørgrav 	if (!buffer) {
2409a3aaf3SDag-Erling Smørgrav 		return NULL;
2509a3aaf3SDag-Erling Smørgrav 	}
2609a3aaf3SDag-Erling Smørgrav 
2709a3aaf3SDag-Erling Smørgrav 	buffer->_data = (uint8_t *) malloc(capacity);
2809a3aaf3SDag-Erling Smørgrav 	if (!buffer->_data) {
2909a3aaf3SDag-Erling Smørgrav 		free(buffer);
3009a3aaf3SDag-Erling Smørgrav 		return NULL;
3109a3aaf3SDag-Erling Smørgrav 	}
3209a3aaf3SDag-Erling Smørgrav 
3309a3aaf3SDag-Erling Smørgrav 	buffer->_position = 0;
3409a3aaf3SDag-Erling Smørgrav 	buffer->_limit = buffer->_capacity = capacity;
3509a3aaf3SDag-Erling Smørgrav 	buffer->_fixed = 0;
3609a3aaf3SDag-Erling Smørgrav 	buffer->_status_err = 0;
3709a3aaf3SDag-Erling Smørgrav 
3809a3aaf3SDag-Erling Smørgrav 	sldns_buffer_invariant(buffer);
3909a3aaf3SDag-Erling Smørgrav 
4009a3aaf3SDag-Erling Smørgrav 	return buffer;
4109a3aaf3SDag-Erling Smørgrav }
4209a3aaf3SDag-Erling Smørgrav 
4309a3aaf3SDag-Erling Smørgrav void
sldns_buffer_new_frm_data(sldns_buffer * buffer,void * data,size_t size)4409a3aaf3SDag-Erling Smørgrav sldns_buffer_new_frm_data(sldns_buffer *buffer, void *data, size_t size)
4509a3aaf3SDag-Erling Smørgrav {
4609a3aaf3SDag-Erling Smørgrav 	assert(data != NULL);
4709a3aaf3SDag-Erling Smørgrav 
4809a3aaf3SDag-Erling Smørgrav 	buffer->_position = 0;
4909a3aaf3SDag-Erling Smørgrav 	buffer->_limit = buffer->_capacity = size;
5009a3aaf3SDag-Erling Smørgrav 	buffer->_fixed = 0;
51*c7f4d7adSDag-Erling Smørgrav 	if (!buffer->_fixed && buffer->_data)
52*c7f4d7adSDag-Erling Smørgrav 		free(buffer->_data);
5309a3aaf3SDag-Erling Smørgrav 	buffer->_data = malloc(size);
5409a3aaf3SDag-Erling Smørgrav 	if(!buffer->_data) {
5509a3aaf3SDag-Erling Smørgrav 		buffer->_status_err = 1;
5609a3aaf3SDag-Erling Smørgrav 		return;
5709a3aaf3SDag-Erling Smørgrav 	}
5809a3aaf3SDag-Erling Smørgrav 	memcpy(buffer->_data, data, size);
5909a3aaf3SDag-Erling Smørgrav 	buffer->_status_err = 0;
6009a3aaf3SDag-Erling Smørgrav 
6109a3aaf3SDag-Erling Smørgrav 	sldns_buffer_invariant(buffer);
6209a3aaf3SDag-Erling Smørgrav }
6309a3aaf3SDag-Erling Smørgrav 
6409a3aaf3SDag-Erling Smørgrav void
sldns_buffer_init_frm_data(sldns_buffer * buffer,void * data,size_t size)6509a3aaf3SDag-Erling Smørgrav sldns_buffer_init_frm_data(sldns_buffer *buffer, void *data, size_t size)
6609a3aaf3SDag-Erling Smørgrav {
6709a3aaf3SDag-Erling Smørgrav 	memset(buffer, 0, sizeof(*buffer));
6809a3aaf3SDag-Erling Smørgrav 	buffer->_data = data;
6909a3aaf3SDag-Erling Smørgrav 	buffer->_capacity = buffer->_limit = size;
7009a3aaf3SDag-Erling Smørgrav 	buffer->_fixed = 1;
7109a3aaf3SDag-Erling Smørgrav }
7209a3aaf3SDag-Erling Smørgrav 
7309a3aaf3SDag-Erling Smørgrav int
sldns_buffer_set_capacity(sldns_buffer * buffer,size_t capacity)7409a3aaf3SDag-Erling Smørgrav sldns_buffer_set_capacity(sldns_buffer *buffer, size_t capacity)
7509a3aaf3SDag-Erling Smørgrav {
7609a3aaf3SDag-Erling Smørgrav 	void *data;
7709a3aaf3SDag-Erling Smørgrav 
7809a3aaf3SDag-Erling Smørgrav 	sldns_buffer_invariant(buffer);
7965b390aaSDag-Erling Smørgrav 	assert(buffer->_position <= capacity && !buffer->_fixed);
8009a3aaf3SDag-Erling Smørgrav 
8109a3aaf3SDag-Erling Smørgrav 	data = (uint8_t *) realloc(buffer->_data, capacity);
8209a3aaf3SDag-Erling Smørgrav 	if (!data) {
8309a3aaf3SDag-Erling Smørgrav 		buffer->_status_err = 1;
8409a3aaf3SDag-Erling Smørgrav 		return 0;
8509a3aaf3SDag-Erling Smørgrav 	} else {
8609a3aaf3SDag-Erling Smørgrav 		buffer->_data = data;
8709a3aaf3SDag-Erling Smørgrav 		buffer->_limit = buffer->_capacity = capacity;
8809a3aaf3SDag-Erling Smørgrav 		return 1;
8909a3aaf3SDag-Erling Smørgrav 	}
9009a3aaf3SDag-Erling Smørgrav }
9109a3aaf3SDag-Erling Smørgrav 
9209a3aaf3SDag-Erling Smørgrav int
sldns_buffer_reserve(sldns_buffer * buffer,size_t amount)9309a3aaf3SDag-Erling Smørgrav sldns_buffer_reserve(sldns_buffer *buffer, size_t amount)
9409a3aaf3SDag-Erling Smørgrav {
9509a3aaf3SDag-Erling Smørgrav 	sldns_buffer_invariant(buffer);
9609a3aaf3SDag-Erling Smørgrav 	assert(!buffer->_fixed);
9709a3aaf3SDag-Erling Smørgrav 	if (buffer->_capacity < buffer->_position + amount) {
9809a3aaf3SDag-Erling Smørgrav 		size_t new_capacity = buffer->_capacity * 3 / 2;
9909a3aaf3SDag-Erling Smørgrav 
10009a3aaf3SDag-Erling Smørgrav 		if (new_capacity < buffer->_position + amount) {
10109a3aaf3SDag-Erling Smørgrav 			new_capacity = buffer->_position + amount;
10209a3aaf3SDag-Erling Smørgrav 		}
10309a3aaf3SDag-Erling Smørgrav 		if (!sldns_buffer_set_capacity(buffer, new_capacity)) {
10409a3aaf3SDag-Erling Smørgrav 			buffer->_status_err = 1;
10509a3aaf3SDag-Erling Smørgrav 			return 0;
10609a3aaf3SDag-Erling Smørgrav 		}
10709a3aaf3SDag-Erling Smørgrav 	}
10809a3aaf3SDag-Erling Smørgrav 	buffer->_limit = buffer->_capacity;
10909a3aaf3SDag-Erling Smørgrav 	return 1;
11009a3aaf3SDag-Erling Smørgrav }
11109a3aaf3SDag-Erling Smørgrav 
11209a3aaf3SDag-Erling Smørgrav int
sldns_buffer_printf(sldns_buffer * buffer,const char * format,...)11309a3aaf3SDag-Erling Smørgrav sldns_buffer_printf(sldns_buffer *buffer, const char *format, ...)
11409a3aaf3SDag-Erling Smørgrav {
11509a3aaf3SDag-Erling Smørgrav 	va_list args;
11609a3aaf3SDag-Erling Smørgrav 	int written = 0;
11709a3aaf3SDag-Erling Smørgrav 	size_t remaining;
11809a3aaf3SDag-Erling Smørgrav 
11909a3aaf3SDag-Erling Smørgrav 	if (sldns_buffer_status_ok(buffer)) {
12009a3aaf3SDag-Erling Smørgrav 		sldns_buffer_invariant(buffer);
12109a3aaf3SDag-Erling Smørgrav 		assert(buffer->_limit == buffer->_capacity);
12209a3aaf3SDag-Erling Smørgrav 
12309a3aaf3SDag-Erling Smørgrav 		remaining = sldns_buffer_remaining(buffer);
12409a3aaf3SDag-Erling Smørgrav 		va_start(args, format);
12509a3aaf3SDag-Erling Smørgrav 		written = vsnprintf((char *) sldns_buffer_current(buffer), remaining,
12609a3aaf3SDag-Erling Smørgrav 				    format, args);
12709a3aaf3SDag-Erling Smørgrav 		va_end(args);
12809a3aaf3SDag-Erling Smørgrav 		if (written == -1) {
12909a3aaf3SDag-Erling Smørgrav 			buffer->_status_err = 1;
13009a3aaf3SDag-Erling Smørgrav 			return -1;
13109a3aaf3SDag-Erling Smørgrav 		}
13209a3aaf3SDag-Erling Smørgrav 		buffer->_position += written;
13309a3aaf3SDag-Erling Smørgrav 	}
13409a3aaf3SDag-Erling Smørgrav 	return written;
13509a3aaf3SDag-Erling Smørgrav }
13609a3aaf3SDag-Erling Smørgrav 
13709a3aaf3SDag-Erling Smørgrav void
sldns_buffer_free(sldns_buffer * buffer)13809a3aaf3SDag-Erling Smørgrav sldns_buffer_free(sldns_buffer *buffer)
13909a3aaf3SDag-Erling Smørgrav {
14009a3aaf3SDag-Erling Smørgrav 	if (!buffer) {
14109a3aaf3SDag-Erling Smørgrav 		return;
14209a3aaf3SDag-Erling Smørgrav 	}
14309a3aaf3SDag-Erling Smørgrav 
14409a3aaf3SDag-Erling Smørgrav 	if (!buffer->_fixed)
14509a3aaf3SDag-Erling Smørgrav 		free(buffer->_data);
14609a3aaf3SDag-Erling Smørgrav 
14709a3aaf3SDag-Erling Smørgrav 	free(buffer);
14809a3aaf3SDag-Erling Smørgrav }
14909a3aaf3SDag-Erling Smørgrav 
15009a3aaf3SDag-Erling Smørgrav void
sldns_buffer_copy(sldns_buffer * result,sldns_buffer * from)15109a3aaf3SDag-Erling Smørgrav sldns_buffer_copy(sldns_buffer* result, sldns_buffer* from)
15209a3aaf3SDag-Erling Smørgrav {
15309a3aaf3SDag-Erling Smørgrav 	size_t tocopy = sldns_buffer_limit(from);
15409a3aaf3SDag-Erling Smørgrav 
15509a3aaf3SDag-Erling Smørgrav 	if(tocopy > sldns_buffer_capacity(result))
15609a3aaf3SDag-Erling Smørgrav 		tocopy = sldns_buffer_capacity(result);
15709a3aaf3SDag-Erling Smørgrav 	sldns_buffer_clear(result);
15809a3aaf3SDag-Erling Smørgrav 	sldns_buffer_write(result, sldns_buffer_begin(from), tocopy);
15909a3aaf3SDag-Erling Smørgrav 	sldns_buffer_flip(result);
16009a3aaf3SDag-Erling Smørgrav }
161