1 /* 2 * buffer.c -- generic memory buffer . 3 * 4 * Copyright (c) 2001-2011, 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, 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