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