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 #include <ldns/config.h> 11 12 #include <ldns/ldns.h> 13 #include <ldns/buffer.h> 14 15 ldns_buffer * 16 ldns_buffer_new(size_t capacity) 17 { 18 ldns_buffer *buffer = LDNS_MALLOC(ldns_buffer); 19 20 if (!buffer) { 21 return NULL; 22 } 23 24 buffer->_data = (uint8_t *) LDNS_XMALLOC(uint8_t, capacity); 25 if (!buffer->_data) { 26 LDNS_FREE(buffer); 27 return NULL; 28 } 29 30 buffer->_position = 0; 31 buffer->_limit = buffer->_capacity = capacity; 32 buffer->_fixed = 0; 33 buffer->_status = LDNS_STATUS_OK; 34 35 ldns_buffer_invariant(buffer); 36 37 return buffer; 38 } 39 40 void 41 ldns_buffer_new_frm_data(ldns_buffer *buffer, void *data, size_t size) 42 { 43 assert(data != NULL); 44 45 buffer->_position = 0; 46 buffer->_limit = buffer->_capacity = size; 47 buffer->_data = LDNS_XMALLOC(uint8_t, size); 48 memcpy(buffer->_data, data, size); 49 buffer->_fixed = 0; 50 buffer->_status = LDNS_STATUS_OK; 51 52 ldns_buffer_invariant(buffer); 53 } 54 55 bool 56 ldns_buffer_set_capacity(ldns_buffer *buffer, size_t capacity) 57 { 58 void *data; 59 60 ldns_buffer_invariant(buffer); 61 assert(buffer->_position <= capacity); 62 63 data = (uint8_t *) LDNS_XREALLOC(buffer->_data, uint8_t, capacity); 64 if (!data) { 65 buffer->_status = LDNS_STATUS_MEM_ERR; 66 return false; 67 } else { 68 buffer->_data = data; 69 buffer->_limit = buffer->_capacity = capacity; 70 return true; 71 } 72 } 73 74 bool 75 ldns_buffer_reserve(ldns_buffer *buffer, size_t amount) 76 { 77 ldns_buffer_invariant(buffer); 78 assert(!buffer->_fixed); 79 if (buffer->_capacity < buffer->_position + amount) { 80 size_t new_capacity = buffer->_capacity * 3 / 2; 81 82 if (new_capacity < buffer->_position + amount) { 83 new_capacity = buffer->_position + amount; 84 } 85 if (!ldns_buffer_set_capacity(buffer, new_capacity)) { 86 buffer->_status = LDNS_STATUS_MEM_ERR; 87 return false; 88 } 89 } 90 buffer->_limit = buffer->_capacity; 91 return true; 92 } 93 94 int 95 ldns_buffer_printf(ldns_buffer *buffer, const char *format, ...) 96 { 97 va_list args; 98 int written = 0; 99 size_t remaining; 100 101 if (ldns_buffer_status_ok(buffer)) { 102 ldns_buffer_invariant(buffer); 103 assert(buffer->_limit == buffer->_capacity); 104 105 remaining = ldns_buffer_remaining(buffer); 106 va_start(args, format); 107 written = vsnprintf((char *) ldns_buffer_current(buffer), remaining, 108 format, args); 109 va_end(args); 110 if (written == -1) { 111 buffer->_status = LDNS_STATUS_INTERNAL_ERR; 112 return -1; 113 } else if ((size_t) written >= remaining) { 114 if (!ldns_buffer_reserve(buffer, (size_t) written + 1)) { 115 buffer->_status = LDNS_STATUS_MEM_ERR; 116 return -1; 117 } 118 va_start(args, format); 119 written = vsnprintf((char *) ldns_buffer_current(buffer), 120 ldns_buffer_remaining(buffer), format, args); 121 va_end(args); 122 if (written == -1) { 123 buffer->_status = LDNS_STATUS_INTERNAL_ERR; 124 return -1; 125 } 126 } 127 buffer->_position += written; 128 } 129 return written; 130 } 131 132 void 133 ldns_buffer_free(ldns_buffer *buffer) 134 { 135 if (!buffer) { 136 return; 137 } 138 139 LDNS_FREE(buffer->_data); 140 141 LDNS_FREE(buffer); 142 } 143 144 void * 145 ldns_buffer_export(ldns_buffer *buffer) 146 { 147 buffer->_fixed = 1; 148 return buffer->_data; 149 } 150 151 int 152 ldns_bgetc(ldns_buffer *buffer) 153 { 154 if (!ldns_buffer_available_at(buffer, buffer->_position, sizeof(uint8_t))) { 155 ldns_buffer_set_position(buffer, ldns_buffer_limit(buffer)); 156 /* ldns_buffer_rewind(buffer);*/ 157 return EOF; 158 } 159 return (int)ldns_buffer_read_u8(buffer); 160 } 161 162 void 163 ldns_buffer_copy(ldns_buffer* result, ldns_buffer* from) 164 { 165 size_t tocopy = ldns_buffer_limit(from); 166 167 if(tocopy > ldns_buffer_capacity(result)) 168 tocopy = ldns_buffer_capacity(result); 169 ldns_buffer_clear(result); 170 ldns_buffer_write(result, ldns_buffer_begin(from), tocopy); 171 ldns_buffer_flip(result); 172 } 173