Home | History | Annotate | Line # | Download | only in sldns
      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 *
     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
     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
     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
     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
     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
    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
    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
    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