2023-04-30 03:15:27 +02:00
|
|
|
/*
|
|
|
|
* buffer.c -- generic memory buffer .
|
|
|
|
*
|
|
|
|
* Copyright (c) 2001-2006, NLnet Labs. All rights reserved.
|
|
|
|
*
|
|
|
|
* See LICENSE for the license.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "config.h"
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
|
|
|
|
#include "buffer.h"
|
|
|
|
|
|
|
|
static void
|
|
|
|
buffer_cleanup(void *arg)
|
|
|
|
{
|
|
|
|
buffer_type *buffer = (buffer_type *) arg;
|
|
|
|
assert(!buffer->_fixed);
|
|
|
|
free(buffer->_data);
|
|
|
|
}
|
|
|
|
|
|
|
|
buffer_type *
|
|
|
|
buffer_create(region_type *region, size_t capacity)
|
|
|
|
{
|
|
|
|
buffer_type *buffer
|
|
|
|
= (buffer_type *) region_alloc(region, sizeof(buffer_type));
|
|
|
|
if (!buffer)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
buffer->_data = (uint8_t *) xalloc(capacity);
|
|
|
|
buffer->_position = 0;
|
|
|
|
buffer->_limit = buffer->_capacity = capacity;
|
|
|
|
buffer->_fixed = 0;
|
|
|
|
buffer_invariant(buffer);
|
2023-09-26 21:52:17 +02:00
|
|
|
|
2023-04-30 03:15:27 +02:00
|
|
|
region_add_cleanup(region, buffer_cleanup, buffer);
|
|
|
|
|
|
|
|
return buffer;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
buffer_create_from(buffer_type *buffer, void *data, size_t size)
|
|
|
|
{
|
|
|
|
assert(data);
|
|
|
|
|
|
|
|
buffer->_position = 0;
|
|
|
|
buffer->_limit = buffer->_capacity = size;
|
|
|
|
buffer->_data = (uint8_t *) data;
|
|
|
|
buffer->_fixed = 1;
|
2023-09-26 21:52:17 +02:00
|
|
|
|
2023-04-30 03:15:27 +02:00
|
|
|
buffer_invariant(buffer);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
buffer_clear(buffer_type *buffer)
|
|
|
|
{
|
|
|
|
buffer_invariant(buffer);
|
2023-09-26 21:52:17 +02:00
|
|
|
|
2023-04-30 03:15:27 +02:00
|
|
|
buffer->_position = 0;
|
|
|
|
buffer->_limit = buffer->_capacity;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
buffer_flip(buffer_type *buffer)
|
|
|
|
{
|
|
|
|
buffer_invariant(buffer);
|
2023-09-26 21:52:17 +02:00
|
|
|
|
2023-04-30 03:15:27 +02:00
|
|
|
buffer->_limit = buffer->_position;
|
|
|
|
buffer->_position = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
buffer_rewind(buffer_type *buffer)
|
|
|
|
{
|
|
|
|
buffer_invariant(buffer);
|
2023-09-26 21:52:17 +02:00
|
|
|
|
2023-04-30 03:15:27 +02:00
|
|
|
buffer->_position = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
buffer_set_capacity(buffer_type *buffer, size_t capacity)
|
|
|
|
{
|
|
|
|
buffer_invariant(buffer);
|
|
|
|
assert(buffer->_position <= capacity);
|
|
|
|
buffer->_data = (uint8_t *) xrealloc(buffer->_data, capacity);
|
|
|
|
buffer->_limit = buffer->_capacity = capacity;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
buffer_reserve(buffer_type *buffer, size_t amount)
|
|
|
|
{
|
|
|
|
buffer_invariant(buffer);
|
|
|
|
assert(!buffer->_fixed);
|
|
|
|
if (buffer->_capacity < buffer->_position + amount) {
|
|
|
|
size_t new_capacity = buffer->_capacity * 3 / 2;
|
|
|
|
if (new_capacity < buffer->_position + amount) {
|
|
|
|
new_capacity = buffer->_position + amount;
|
|
|
|
}
|
|
|
|
buffer_set_capacity(buffer, new_capacity);
|
|
|
|
}
|
|
|
|
buffer->_limit = buffer->_capacity;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
buffer_printf(buffer_type *buffer, const char *format, ...)
|
|
|
|
{
|
|
|
|
va_list args;
|
|
|
|
int written;
|
|
|
|
size_t remaining;
|
2023-09-26 21:52:17 +02:00
|
|
|
|
2023-04-30 03:15:27 +02:00
|
|
|
buffer_invariant(buffer);
|
|
|
|
assert(buffer->_limit == buffer->_capacity);
|
|
|
|
|
|
|
|
remaining = buffer_remaining(buffer);
|
|
|
|
va_start(args, format);
|
|
|
|
written = vsnprintf((char *) buffer_current(buffer), remaining,
|
|
|
|
format, args);
|
|
|
|
va_end(args);
|
|
|
|
if (written >= 0 && (size_t) written >= remaining) {
|
|
|
|
buffer_reserve(buffer, written + 1);
|
|
|
|
va_start(args, format);
|
|
|
|
written = vsnprintf((char *) buffer_current(buffer),
|
|
|
|
buffer_remaining(buffer),
|
|
|
|
format, args);
|
|
|
|
va_end(args);
|
|
|
|
}
|
|
|
|
buffer->_position += written;
|
|
|
|
return written;
|
|
|
|
}
|