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