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