1266077Sdes/* 2266077Sdes * buffer.c -- generic memory buffer . 3266077Sdes * 4266077Sdes * Copyright (c) 2001-2008, NLnet Labs. All rights reserved. 5266077Sdes * 6266077Sdes * See LICENSE for the license. 7266077Sdes * 8266077Sdes */ 9266077Sdes/** 10266077Sdes * \file 11266077Sdes * 12266077Sdes * This file contains the definition of sldns_buffer, and functions to manipulate those. 13266077Sdes */ 14266077Sdes#include "config.h" 15287915Sdes#include "sldns/sbuffer.h" 16266077Sdes#include <stdarg.h> 17266077Sdes 18266077Sdessldns_buffer * 19266077Sdessldns_buffer_new(size_t capacity) 20266077Sdes{ 21266077Sdes sldns_buffer *buffer = (sldns_buffer*)malloc(sizeof(sldns_buffer)); 22266077Sdes 23266077Sdes if (!buffer) { 24266077Sdes return NULL; 25266077Sdes } 26266077Sdes 27266077Sdes buffer->_data = (uint8_t *) malloc(capacity); 28266077Sdes if (!buffer->_data) { 29266077Sdes free(buffer); 30266077Sdes return NULL; 31266077Sdes } 32266077Sdes 33266077Sdes buffer->_position = 0; 34266077Sdes buffer->_limit = buffer->_capacity = capacity; 35266077Sdes buffer->_fixed = 0; 36266077Sdes buffer->_status_err = 0; 37266077Sdes 38266077Sdes sldns_buffer_invariant(buffer); 39266077Sdes 40266077Sdes return buffer; 41266077Sdes} 42266077Sdes 43266077Sdesvoid 44266077Sdessldns_buffer_new_frm_data(sldns_buffer *buffer, void *data, size_t size) 45266077Sdes{ 46266077Sdes assert(data != NULL); 47266077Sdes 48266077Sdes buffer->_position = 0; 49266077Sdes buffer->_limit = buffer->_capacity = size; 50266077Sdes buffer->_fixed = 0; 51266077Sdes buffer->_data = malloc(size); 52266077Sdes if(!buffer->_data) { 53266077Sdes buffer->_status_err = 1; 54266077Sdes return; 55266077Sdes } 56266077Sdes memcpy(buffer->_data, data, size); 57266077Sdes buffer->_status_err = 0; 58266077Sdes 59266077Sdes sldns_buffer_invariant(buffer); 60266077Sdes} 61266077Sdes 62266077Sdesvoid 63266077Sdessldns_buffer_init_frm_data(sldns_buffer *buffer, void *data, size_t size) 64266077Sdes{ 65266077Sdes memset(buffer, 0, sizeof(*buffer)); 66266077Sdes buffer->_data = data; 67266077Sdes buffer->_capacity = buffer->_limit = size; 68266077Sdes buffer->_fixed = 1; 69266077Sdes} 70266077Sdes 71266077Sdesint 72266077Sdessldns_buffer_set_capacity(sldns_buffer *buffer, size_t capacity) 73266077Sdes{ 74266077Sdes void *data; 75266077Sdes 76266077Sdes sldns_buffer_invariant(buffer); 77266077Sdes assert(buffer->_position <= capacity); 78266077Sdes 79266077Sdes data = (uint8_t *) realloc(buffer->_data, capacity); 80266077Sdes if (!data) { 81266077Sdes buffer->_status_err = 1; 82266077Sdes return 0; 83266077Sdes } else { 84266077Sdes buffer->_data = data; 85266077Sdes buffer->_limit = buffer->_capacity = capacity; 86266077Sdes return 1; 87266077Sdes } 88266077Sdes} 89266077Sdes 90266077Sdesint 91266077Sdessldns_buffer_reserve(sldns_buffer *buffer, size_t amount) 92266077Sdes{ 93266077Sdes sldns_buffer_invariant(buffer); 94266077Sdes assert(!buffer->_fixed); 95266077Sdes if (buffer->_capacity < buffer->_position + amount) { 96266077Sdes size_t new_capacity = buffer->_capacity * 3 / 2; 97266077Sdes 98266077Sdes if (new_capacity < buffer->_position + amount) { 99266077Sdes new_capacity = buffer->_position + amount; 100266077Sdes } 101266077Sdes if (!sldns_buffer_set_capacity(buffer, new_capacity)) { 102266077Sdes buffer->_status_err = 1; 103266077Sdes return 0; 104266077Sdes } 105266077Sdes } 106266077Sdes buffer->_limit = buffer->_capacity; 107266077Sdes return 1; 108266077Sdes} 109266077Sdes 110266077Sdesint 111266077Sdessldns_buffer_printf(sldns_buffer *buffer, const char *format, ...) 112266077Sdes{ 113266077Sdes va_list args; 114266077Sdes int written = 0; 115266077Sdes size_t remaining; 116266077Sdes 117266077Sdes if (sldns_buffer_status_ok(buffer)) { 118266077Sdes sldns_buffer_invariant(buffer); 119266077Sdes assert(buffer->_limit == buffer->_capacity); 120266077Sdes 121266077Sdes remaining = sldns_buffer_remaining(buffer); 122266077Sdes va_start(args, format); 123266077Sdes written = vsnprintf((char *) sldns_buffer_current(buffer), remaining, 124266077Sdes format, args); 125266077Sdes va_end(args); 126266077Sdes if (written == -1) { 127266077Sdes buffer->_status_err = 1; 128266077Sdes return -1; 129266077Sdes } else if ((size_t) written >= remaining) { 130266077Sdes if (!sldns_buffer_reserve(buffer, (size_t) written + 1)) { 131266077Sdes buffer->_status_err = 1; 132266077Sdes return -1; 133266077Sdes } 134266077Sdes va_start(args, format); 135266077Sdes written = vsnprintf((char *) sldns_buffer_current(buffer), 136266077Sdes sldns_buffer_remaining(buffer), format, args); 137266077Sdes va_end(args); 138266077Sdes if (written == -1) { 139266077Sdes buffer->_status_err = 1; 140266077Sdes return -1; 141266077Sdes } 142266077Sdes } 143266077Sdes buffer->_position += written; 144266077Sdes } 145266077Sdes return written; 146266077Sdes} 147266077Sdes 148266077Sdesvoid 149266077Sdessldns_buffer_free(sldns_buffer *buffer) 150266077Sdes{ 151266077Sdes if (!buffer) { 152266077Sdes return; 153266077Sdes } 154266077Sdes 155266077Sdes if (!buffer->_fixed) 156266077Sdes free(buffer->_data); 157266077Sdes 158266077Sdes free(buffer); 159266077Sdes} 160266077Sdes 161266077Sdesvoid * 162266077Sdessldns_buffer_export(sldns_buffer *buffer) 163266077Sdes{ 164266077Sdes buffer->_fixed = 1; 165266077Sdes return buffer->_data; 166266077Sdes} 167266077Sdes 168266077Sdesvoid 169266077Sdessldns_buffer_copy(sldns_buffer* result, sldns_buffer* from) 170266077Sdes{ 171266077Sdes size_t tocopy = sldns_buffer_limit(from); 172266077Sdes 173266077Sdes if(tocopy > sldns_buffer_capacity(result)) 174266077Sdes tocopy = sldns_buffer_capacity(result); 175266077Sdes sldns_buffer_clear(result); 176266077Sdes sldns_buffer_write(result, sldns_buffer_begin(from), tocopy); 177266077Sdes sldns_buffer_flip(result); 178266077Sdes} 179