buffer.h
Go to the documentation of this file.
/*
* buffer.h -- generic memory buffer.
*
* Copyright (c) 2005-2008, NLnet Labs. All rights reserved.
*
* See LICENSE for the license.
*
*
* The buffer module implements a generic buffer. The API is based on
* the java.nio.Buffer interface.
*/
#ifndef LDNS_BUFFER_H
#define LDNS_BUFFER_H
#include <assert.h>
#include <stdarg.h>
#include <string.h>
#include <ldns/error.h>
#include <ldns/common.h>
#include "ldns/util.h"
#ifdef __cplusplus
extern "C" {
#endif
#define LDNS_MIN_BUFLEN 512
struct ldns_struct_buffer
{
size_t _position;
size_t _limit;
size_t _capacity;
uint8_t *_data;
unsigned _fixed : 1;
ldns_status _status;
};
typedef struct ldns_struct_buffer ldns_buffer;
#ifdef NDEBUG
INLINE void
ldns_buffer_invariant(const ldns_buffer *ATTR_UNUSED(buffer))
{
}
#else
INLINE void
ldns_buffer_invariant(const ldns_buffer *buffer)
{
assert(buffer != NULL);
assert(buffer->_position <= buffer->_limit);
assert(buffer->_limit <= buffer->_capacity);
assert(buffer->_data != NULL);
}
#endif
ldns_buffer *ldns_buffer_new(size_t capacity);
void ldns_buffer_new_frm_data(ldns_buffer *buffer, const void *data, size_t size);
INLINE void ldns_buffer_clear(ldns_buffer *buffer)
{
ldns_buffer_invariant(buffer);
/* reset status here? */
buffer->_position = 0;
buffer->_limit = buffer->_capacity;
}
INLINE void ldns_buffer_flip(ldns_buffer *buffer)
{
ldns_buffer_invariant(buffer);
buffer->_limit = buffer->_position;
buffer->_position = 0;
}
INLINE void ldns_buffer_rewind(ldns_buffer *buffer)
{
ldns_buffer_invariant(buffer);
buffer->_position = 0;
}
INLINE size_t
ldns_buffer_position(const ldns_buffer *buffer)
{
return buffer->_position;
}
INLINE void
ldns_buffer_set_position(ldns_buffer *buffer, size_t mark)
{
assert(mark <= buffer->_limit);
buffer->_position = mark;
}
INLINE void
ldns_buffer_skip(ldns_buffer *buffer, ssize_t count)
{
assert(buffer->_position + count <= buffer->_limit);
buffer->_position += count;
}
INLINE size_t
ldns_buffer_limit(const ldns_buffer *buffer)
{
return buffer->_limit;
}
INLINE void
ldns_buffer_set_limit(ldns_buffer *buffer, size_t limit)
{
assert(limit <= buffer->_capacity);
buffer->_limit = limit;
if (buffer->_position > buffer->_limit)
buffer->_position = buffer->_limit;
}
INLINE size_t
ldns_buffer_capacity(const ldns_buffer *buffer)
{
return buffer->_capacity;
}
bool ldns_buffer_set_capacity(ldns_buffer *buffer, size_t capacity);
bool ldns_buffer_reserve(ldns_buffer *buffer, size_t amount);
INLINE uint8_t *
ldns_buffer_at(const ldns_buffer *buffer, size_t at)
{
assert(at <= buffer->_limit);
return buffer->_data + at;
}
INLINE uint8_t *
ldns_buffer_begin(const ldns_buffer *buffer)
{
return ldns_buffer_at(buffer, 0);
}
INLINE uint8_t *
ldns_buffer_end(const ldns_buffer *buffer)
{
return ldns_buffer_at(buffer, buffer->_limit);
}
INLINE uint8_t *
ldns_buffer_current(const ldns_buffer *buffer)
{
return ldns_buffer_at(buffer, buffer->_position);
}
INLINE size_t
ldns_buffer_remaining_at(const ldns_buffer *buffer, size_t at)
{
ldns_buffer_invariant(buffer);
assert(at <= buffer->_limit);
return buffer->_limit - at;
}
INLINE size_t
ldns_buffer_remaining(const ldns_buffer *buffer)
{
return ldns_buffer_remaining_at(buffer, buffer->_position);
}
INLINE int
ldns_buffer_available_at(const ldns_buffer *buffer, size_t at, size_t count)
{
return count <= ldns_buffer_remaining_at(buffer, at);
}
INLINE int
ldns_buffer_available(const ldns_buffer *buffer, size_t count)
{
return ldns_buffer_available_at(buffer, buffer->_position, count);
}
INLINE void
ldns_buffer_write_at(ldns_buffer *buffer, size_t at, const void *data, size_t count)
{
assert(ldns_buffer_available_at(buffer, at, count));
memcpy(buffer->_data + at, data, count);
}
INLINE void
ldns_buffer_write(ldns_buffer *buffer, const void *data, size_t count)
{
ldns_buffer_write_at(buffer, buffer->_position, data, count);
buffer->_position += count;
}
INLINE void
ldns_buffer_write_string_at(ldns_buffer *buffer, size_t at, const char *str)
{
ldns_buffer_write_at(buffer, at, str, strlen(str));
}
INLINE void
ldns_buffer_write_string(ldns_buffer *buffer, const char *str)
{
ldns_buffer_write(buffer, str, strlen(str));
}
INLINE void
ldns_buffer_write_chars(ldns_buffer *buffer, const char *str)
{
if (!ldns_buffer_reserve(buffer, strlen(str)))
buffer->_status = LDNS_STATUS_MEM_ERR;
else
ldns_buffer_write_string(buffer, str);
}
INLINE void
ldns_buffer_write_u8_at(ldns_buffer *buffer, size_t at, uint8_t data)
{
assert(ldns_buffer_available_at(buffer, at, sizeof(data)));
buffer->_data[at] = data;
}
INLINE void
ldns_buffer_write_u8(ldns_buffer *buffer, uint8_t data)
{
ldns_buffer_write_u8_at(buffer, buffer->_position, data);
buffer->_position += sizeof(data);
}
INLINE void
ldns_buffer_write_char(ldns_buffer *buffer, uint8_t data)
{
if (!ldns_buffer_reserve(buffer, sizeof(data)))
buffer->_status = LDNS_STATUS_MEM_ERR;
else
ldns_buffer_write_u8(buffer, data);
}
INLINE void
ldns_buffer_write_u16_at(ldns_buffer *buffer, size_t at, uint16_t data)
{
assert(ldns_buffer_available_at(buffer, at, sizeof(data)));
ldns_write_uint16(buffer->_data + at, data);
}
INLINE void
ldns_buffer_write_u16(ldns_buffer *buffer, uint16_t data)
{
ldns_buffer_write_u16_at(buffer, buffer->_position, data);
buffer->_position += sizeof(data);
}
INLINE void
ldns_buffer_write_u32_at(ldns_buffer *buffer, size_t at, uint32_t data)
{
assert(ldns_buffer_available_at(buffer, at, sizeof(data)));
ldns_write_uint32(buffer->_data + at, data);
}
INLINE void
ldns_buffer_write_u32(ldns_buffer *buffer, uint32_t data)
{
ldns_buffer_write_u32_at(buffer, buffer->_position, data);
buffer->_position += sizeof(data);
}
INLINE void
ldns_buffer_read_at(const ldns_buffer *buffer, size_t at, void *data, size_t count)
{
assert(ldns_buffer_available_at(buffer, at, count));
memcpy(data, buffer->_data + at, count);
}
INLINE void
ldns_buffer_read(ldns_buffer *buffer, void *data, size_t count)
{
ldns_buffer_read_at(buffer, buffer->_position, data, count);
buffer->_position += count;
}
INLINE uint8_t
ldns_buffer_read_u8_at(const ldns_buffer *buffer, size_t at)
{
assert(ldns_buffer_available_at(buffer, at, sizeof(uint8_t)));
return buffer->_data[at];
}
INLINE uint8_t
ldns_buffer_read_u8(ldns_buffer *buffer)
{
uint8_t result = ldns_buffer_read_u8_at(buffer, buffer->_position);
buffer->_position += sizeof(uint8_t);
return result;
}
INLINE uint16_t
ldns_buffer_read_u16_at(ldns_buffer *buffer, size_t at)
{
assert(ldns_buffer_available_at(buffer, at, sizeof(uint16_t)));
return ldns_read_uint16(buffer->_data + at);
}
INLINE uint16_t
ldns_buffer_read_u16(ldns_buffer *buffer)
{
uint16_t result = ldns_buffer_read_u16_at(buffer, buffer->_position);
buffer->_position += sizeof(uint16_t);
return result;
}
INLINE uint32_t
ldns_buffer_read_u32_at(ldns_buffer *buffer, size_t at)
{
assert(ldns_buffer_available_at(buffer, at, sizeof(uint32_t)));
return ldns_read_uint32(buffer->_data + at);
}
INLINE uint32_t
ldns_buffer_read_u32(ldns_buffer *buffer)
{
uint32_t result = ldns_buffer_read_u32_at(buffer, buffer->_position);
buffer->_position += sizeof(uint32_t);
return result;
}
INLINE ldns_status
ldns_buffer_status(const ldns_buffer *buffer)
{
return buffer->_status;
}
INLINE bool
ldns_buffer_status_ok(const ldns_buffer *buffer)
{
if (buffer) {
return ldns_buffer_status(buffer) == LDNS_STATUS_OK;
} else {
return false;
}
}
int ldns_buffer_printf(ldns_buffer *buffer, const char *format, ...);
/* ATTR_FORMAT(printf, 2, 3);*/
void ldns_buffer_free(ldns_buffer *buffer);
void *ldns_buffer_export(ldns_buffer *buffer);
void ldns_buffer_copy(ldns_buffer* result, const ldns_buffer* from);
#ifdef __cplusplus
}
#endif
#endif /* LDNS_BUFFER_H */
ldns_buffer_free
void ldns_buffer_free(ldns_buffer *buffer)
frees the buffer.
Definition buffer.c:137
ldns_buffer
struct ldns_struct_buffer ldns_buffer
Definition buffer.h:72
ldns_buffer_new
ldns_buffer * ldns_buffer_new(size_t capacity)
creates a new buffer with the specified capacity.
Definition buffer.c:16
ldns_buffer_export
void * ldns_buffer_export(ldns_buffer *buffer)
Makes the buffer fixed and returns a pointer to the data.
Definition buffer.c:150
ldns_buffer_copy
void ldns_buffer_copy(ldns_buffer *result, const ldns_buffer *from)
Copy contents of the from buffer to the result buffer and then flips the result buffer.
Definition buffer.c:168
ldns_buffer_set_capacity
signed char ldns_buffer_set_capacity(ldns_buffer *buffer, size_t capacity)
changes the buffer's capacity.
Definition buffer.c:60
ldns_buffer_reserve
signed char ldns_buffer_reserve(ldns_buffer *buffer, size_t amount)
ensures BUFFER can contain at least AMOUNT more bytes.
Definition buffer.c:80
ldns_buffer_printf
int ldns_buffer_printf(ldns_buffer *buffer, const char *format,...)
prints to the buffer, increasing the capacity if required using buffer_reserve().
Definition buffer.c:99
ldns_buffer_new_frm_data
void ldns_buffer_new_frm_data(ldns_buffer *buffer, const void *data, size_t size)
creates a buffer with the specified data.
Definition buffer.c:41
common.h
Common definitions for LDNS.
ATTR_UNUSED
#define ATTR_UNUSED(x)
Definition common.h:72
error.h
Defines error numbers and functions to translate those to a readable string.
LDNS_STATUS_MEM_ERR
@ LDNS_STATUS_MEM_ERR
Definition error.h:34
LDNS_STATUS_OK
@ LDNS_STATUS_OK
Definition error.h:26
ldns_status
enum ldns_enum_status ldns_status
Definition error.h:148
ldns_struct_buffer
implementation of buffers to ease operations
Definition buffer.h:51
ldns_struct_buffer::_capacity
size_t _capacity
The amount of data the buffer can contain.
Definition buffer.h:59
ldns_struct_buffer::_fixed
unsigned _fixed
If the buffer is fixed it cannot be resized.
Definition buffer.h:65
ldns_struct_buffer::_position
size_t _position
The current position used for reading/writing.
Definition buffer.h:53
ldns_struct_buffer::_status
ldns_status _status
The current state of the buffer.
Definition buffer.h:70
ldns_struct_buffer::_data
uint8_t * _data
The data contained in the buffer.
Definition buffer.h:62
ldns_struct_buffer::_limit
size_t _limit
The read/write limit.
Definition buffer.h:56
util.h
INLINE
#define INLINE
splint static inline workaround
Definition util.h:42