Home | History | Annotate | Line # | Download | only in dist
      1 /*
      2  * buffer.c -- generic memory buffer .
      3  *
      4  * Copyright (c) 2001-2006, NLnet Labs. All rights reserved.
      5  *
      6  * See LICENSE for the license.
      7  *
      8  */
      9 
     10 #include "config.h"
     11 #include <stdlib.h>
     12 #include <stdio.h>
     13 
     14 #include "buffer.h"
     15 
     16 static void
     17 buffer_cleanup(void *arg)
     18 {
     19 	buffer_type *buffer = (buffer_type *) arg;
     20 	assert(!buffer->_fixed);
     21 	free(buffer->_data);
     22 }
     23 
     24 buffer_type *
     25 buffer_create(region_type *region, size_t capacity)
     26 {
     27 	buffer_type *buffer
     28 		= (buffer_type *) region_alloc(region, sizeof(buffer_type));
     29 	if (!buffer)
     30 		return NULL;
     31 
     32 	buffer->_data = (uint8_t *) xalloc(capacity);
     33 	buffer->_position = 0;
     34 	buffer->_limit = buffer->_capacity = capacity;
     35 	buffer->_fixed = 0;
     36 	buffer_invariant(buffer);
     37 
     38 	region_add_cleanup(region, buffer_cleanup, buffer);
     39 
     40 	return buffer;
     41 }
     42 
     43 void
     44 buffer_create_from(buffer_type *buffer, const void *data, size_t size)
     45 {
     46 	assert(data);
     47 
     48 	buffer->_position = 0;
     49 	buffer->_limit = buffer->_capacity = size;
     50 	buffer->_data = (uint8_t *) data;
     51 	buffer->_fixed = 1;
     52 
     53 	buffer_invariant(buffer);
     54 }
     55 
     56 void
     57 buffer_clear(buffer_type *buffer)
     58 {
     59 	buffer_invariant(buffer);
     60 
     61 	buffer->_position = 0;
     62 	buffer->_limit = buffer->_capacity;
     63 }
     64 
     65 void
     66 buffer_flip(buffer_type *buffer)
     67 {
     68 	buffer_invariant(buffer);
     69 
     70 	buffer->_limit = buffer->_position;
     71 	buffer->_position = 0;
     72 }
     73 
     74 void
     75 buffer_rewind(buffer_type *buffer)
     76 {
     77 	buffer_invariant(buffer);
     78 
     79 	buffer->_position = 0;
     80 }
     81 
     82 void
     83 buffer_set_capacity(buffer_type *buffer, size_t capacity)
     84 {
     85 	buffer_invariant(buffer);
     86 	assert(buffer->_position <= capacity);
     87 	buffer->_data = (uint8_t *) xrealloc(buffer->_data, capacity);
     88 	buffer->_limit = buffer->_capacity = capacity;
     89 }
     90 
     91 void
     92 buffer_reserve(buffer_type *buffer, size_t amount)
     93 {
     94 	buffer_invariant(buffer);
     95 	assert(!buffer->_fixed);
     96 	if (buffer->_capacity < buffer->_position + amount) {
     97 		size_t new_capacity = buffer->_capacity * 3 / 2;
     98 		if (new_capacity < buffer->_position + amount) {
     99 			new_capacity = buffer->_position + amount;
    100 		}
    101 		buffer_set_capacity(buffer, new_capacity);
    102 	}
    103 	buffer->_limit = buffer->_capacity;
    104 }
    105 
    106 int
    107 buffer_printf(buffer_type *buffer, const char *format, ...)
    108 {
    109 	va_list args;
    110 	int written;
    111 	size_t remaining;
    112 
    113 	buffer_invariant(buffer);
    114 	assert(buffer->_limit == buffer->_capacity);
    115 
    116 	remaining = buffer_remaining(buffer);
    117 	va_start(args, format);
    118 	written = vsnprintf((char *) buffer_current(buffer), remaining,
    119 			    format, args);
    120 	va_end(args);
    121 	if (written >= 0 && (size_t) written >= remaining) {
    122 		buffer_reserve(buffer, written + 1);
    123 		va_start(args, format);
    124 		written = vsnprintf((char *) buffer_current(buffer),
    125 				    buffer_remaining(buffer),
    126 				    format, args);
    127 		va_end(args);
    128 	}
    129 	buffer->_position += written;
    130 	return written;
    131 }
    132