162ac0c33Sjakob /*
262ac0c33Sjakob * buffer.c -- generic memory buffer .
362ac0c33Sjakob *
4*d3fecca9Ssthen * Copyright (c) 2001-2006, NLnet Labs. All rights reserved.
562ac0c33Sjakob *
662ac0c33Sjakob * See LICENSE for the license.
762ac0c33Sjakob *
862ac0c33Sjakob */
962ac0c33Sjakob
10aee1b7aaSsthen #include "config.h"
1162ac0c33Sjakob #include <stdlib.h>
1262ac0c33Sjakob #include <stdio.h>
1362ac0c33Sjakob
1462ac0c33Sjakob #include "buffer.h"
1562ac0c33Sjakob
1662ac0c33Sjakob static void
buffer_cleanup(void * arg)1762ac0c33Sjakob buffer_cleanup(void *arg)
1862ac0c33Sjakob {
1962ac0c33Sjakob buffer_type *buffer = (buffer_type *) arg;
2062ac0c33Sjakob assert(!buffer->_fixed);
2162ac0c33Sjakob free(buffer->_data);
2262ac0c33Sjakob }
2362ac0c33Sjakob
2462ac0c33Sjakob buffer_type *
buffer_create(region_type * region,size_t capacity)2562ac0c33Sjakob buffer_create(region_type *region, size_t capacity)
2662ac0c33Sjakob {
2762ac0c33Sjakob buffer_type *buffer
2862ac0c33Sjakob = (buffer_type *) region_alloc(region, sizeof(buffer_type));
2962ac0c33Sjakob if (!buffer)
3062ac0c33Sjakob return NULL;
3162ac0c33Sjakob
3262ac0c33Sjakob buffer->_data = (uint8_t *) xalloc(capacity);
3362ac0c33Sjakob buffer->_position = 0;
3462ac0c33Sjakob buffer->_limit = buffer->_capacity = capacity;
3562ac0c33Sjakob buffer->_fixed = 0;
3662ac0c33Sjakob buffer_invariant(buffer);
3762ac0c33Sjakob
3862ac0c33Sjakob region_add_cleanup(region, buffer_cleanup, buffer);
3962ac0c33Sjakob
4062ac0c33Sjakob return buffer;
4162ac0c33Sjakob }
4262ac0c33Sjakob
4362ac0c33Sjakob void
buffer_create_from(buffer_type * buffer,void * data,size_t size)4462ac0c33Sjakob buffer_create_from(buffer_type *buffer, void *data, size_t size)
4562ac0c33Sjakob {
4662ac0c33Sjakob assert(data);
4762ac0c33Sjakob
4862ac0c33Sjakob buffer->_position = 0;
4962ac0c33Sjakob buffer->_limit = buffer->_capacity = size;
5062ac0c33Sjakob buffer->_data = (uint8_t *) data;
5162ac0c33Sjakob buffer->_fixed = 1;
5262ac0c33Sjakob
5362ac0c33Sjakob buffer_invariant(buffer);
5462ac0c33Sjakob }
5562ac0c33Sjakob
5662ac0c33Sjakob void
buffer_clear(buffer_type * buffer)5762ac0c33Sjakob buffer_clear(buffer_type *buffer)
5862ac0c33Sjakob {
5962ac0c33Sjakob buffer_invariant(buffer);
6062ac0c33Sjakob
6162ac0c33Sjakob buffer->_position = 0;
6262ac0c33Sjakob buffer->_limit = buffer->_capacity;
6362ac0c33Sjakob }
6462ac0c33Sjakob
6562ac0c33Sjakob void
buffer_flip(buffer_type * buffer)6662ac0c33Sjakob buffer_flip(buffer_type *buffer)
6762ac0c33Sjakob {
6862ac0c33Sjakob buffer_invariant(buffer);
6962ac0c33Sjakob
7062ac0c33Sjakob buffer->_limit = buffer->_position;
7162ac0c33Sjakob buffer->_position = 0;
7262ac0c33Sjakob }
7362ac0c33Sjakob
7462ac0c33Sjakob void
buffer_rewind(buffer_type * buffer)7562ac0c33Sjakob buffer_rewind(buffer_type *buffer)
7662ac0c33Sjakob {
7762ac0c33Sjakob buffer_invariant(buffer);
7862ac0c33Sjakob
7962ac0c33Sjakob buffer->_position = 0;
8062ac0c33Sjakob }
8162ac0c33Sjakob
8262ac0c33Sjakob void
buffer_set_capacity(buffer_type * buffer,size_t capacity)8362ac0c33Sjakob buffer_set_capacity(buffer_type *buffer, size_t capacity)
8462ac0c33Sjakob {
8562ac0c33Sjakob buffer_invariant(buffer);
8662ac0c33Sjakob assert(buffer->_position <= capacity);
8762ac0c33Sjakob buffer->_data = (uint8_t *) xrealloc(buffer->_data, capacity);
8862ac0c33Sjakob buffer->_limit = buffer->_capacity = capacity;
8962ac0c33Sjakob }
9062ac0c33Sjakob
9162ac0c33Sjakob void
buffer_reserve(buffer_type * buffer,size_t amount)9262ac0c33Sjakob buffer_reserve(buffer_type *buffer, size_t amount)
9362ac0c33Sjakob {
9462ac0c33Sjakob buffer_invariant(buffer);
9562ac0c33Sjakob assert(!buffer->_fixed);
9662ac0c33Sjakob if (buffer->_capacity < buffer->_position + amount) {
9762ac0c33Sjakob size_t new_capacity = buffer->_capacity * 3 / 2;
9862ac0c33Sjakob if (new_capacity < buffer->_position + amount) {
9962ac0c33Sjakob new_capacity = buffer->_position + amount;
10062ac0c33Sjakob }
10162ac0c33Sjakob buffer_set_capacity(buffer, new_capacity);
10262ac0c33Sjakob }
10362ac0c33Sjakob buffer->_limit = buffer->_capacity;
10462ac0c33Sjakob }
10562ac0c33Sjakob
10662ac0c33Sjakob int
buffer_printf(buffer_type * buffer,const char * format,...)10762ac0c33Sjakob buffer_printf(buffer_type *buffer, const char *format, ...)
10862ac0c33Sjakob {
10962ac0c33Sjakob va_list args;
11062ac0c33Sjakob int written;
11162ac0c33Sjakob size_t remaining;
11262ac0c33Sjakob
11362ac0c33Sjakob buffer_invariant(buffer);
11462ac0c33Sjakob assert(buffer->_limit == buffer->_capacity);
11562ac0c33Sjakob
11662ac0c33Sjakob remaining = buffer_remaining(buffer);
11762ac0c33Sjakob va_start(args, format);
11862ac0c33Sjakob written = vsnprintf((char *) buffer_current(buffer), remaining,
11962ac0c33Sjakob format, args);
12062ac0c33Sjakob va_end(args);
12162ac0c33Sjakob if (written >= 0 && (size_t) written >= remaining) {
12262ac0c33Sjakob buffer_reserve(buffer, written + 1);
12362ac0c33Sjakob va_start(args, format);
12462ac0c33Sjakob written = vsnprintf((char *) buffer_current(buffer),
12562ac0c33Sjakob buffer_remaining(buffer),
12662ac0c33Sjakob format, args);
12762ac0c33Sjakob va_end(args);
12862ac0c33Sjakob }
12962ac0c33Sjakob buffer->_position += written;
13062ac0c33Sjakob return written;
13162ac0c33Sjakob }
132