aboutsummaryrefslogtreecommitdiff
path: root/ldns/sbuffer.c
diff options
context:
space:
mode:
Diffstat (limited to 'ldns/sbuffer.c')
-rw-r--r--ldns/sbuffer.c189
1 files changed, 189 insertions, 0 deletions
diff --git a/ldns/sbuffer.c b/ldns/sbuffer.c
new file mode 100644
index 000000000000..b0b2efdcf4fa
--- /dev/null
+++ b/ldns/sbuffer.c
@@ -0,0 +1,189 @@
+/*
+ * buffer.c -- generic memory buffer .
+ *
+ * Copyright (c) 2001-2008, NLnet Labs. All rights reserved.
+ *
+ * See LICENSE for the license.
+ *
+ */
+/**
+ * \file
+ *
+ * This file contains the definition of sldns_buffer, and functions to manipulate those.
+ */
+#include "config.h"
+#include "ldns/sbuffer.h"
+#include <stdarg.h>
+
+sldns_buffer *
+sldns_buffer_new(size_t capacity)
+{
+ sldns_buffer *buffer = (sldns_buffer*)malloc(sizeof(sldns_buffer));
+
+ if (!buffer) {
+ return NULL;
+ }
+
+ buffer->_data = (uint8_t *) malloc(capacity);
+ if (!buffer->_data) {
+ free(buffer);
+ return NULL;
+ }
+
+ buffer->_position = 0;
+ buffer->_limit = buffer->_capacity = capacity;
+ buffer->_fixed = 0;
+ buffer->_status_err = 0;
+
+ sldns_buffer_invariant(buffer);
+
+ return buffer;
+}
+
+void
+sldns_buffer_new_frm_data(sldns_buffer *buffer, void *data, size_t size)
+{
+ assert(data != NULL);
+
+ buffer->_position = 0;
+ buffer->_limit = buffer->_capacity = size;
+ buffer->_fixed = 0;
+ buffer->_data = malloc(size);
+ if(!buffer->_data) {
+ buffer->_status_err = 1;
+ return;
+ }
+ memcpy(buffer->_data, data, size);
+ buffer->_status_err = 0;
+
+ sldns_buffer_invariant(buffer);
+}
+
+void
+sldns_buffer_init_frm_data(sldns_buffer *buffer, void *data, size_t size)
+{
+ memset(buffer, 0, sizeof(*buffer));
+ buffer->_data = data;
+ buffer->_capacity = buffer->_limit = size;
+ buffer->_fixed = 1;
+}
+
+int
+sldns_buffer_set_capacity(sldns_buffer *buffer, size_t capacity)
+{
+ void *data;
+
+ sldns_buffer_invariant(buffer);
+ assert(buffer->_position <= capacity);
+
+ data = (uint8_t *) realloc(buffer->_data, capacity);
+ if (!data) {
+ buffer->_status_err = 1;
+ return 0;
+ } else {
+ buffer->_data = data;
+ buffer->_limit = buffer->_capacity = capacity;
+ return 1;
+ }
+}
+
+int
+sldns_buffer_reserve(sldns_buffer *buffer, size_t amount)
+{
+ sldns_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;
+ }
+ if (!sldns_buffer_set_capacity(buffer, new_capacity)) {
+ buffer->_status_err = 1;
+ return 0;
+ }
+ }
+ buffer->_limit = buffer->_capacity;
+ return 1;
+}
+
+int
+sldns_buffer_printf(sldns_buffer *buffer, const char *format, ...)
+{
+ va_list args;
+ int written = 0;
+ size_t remaining;
+
+ if (sldns_buffer_status_ok(buffer)) {
+ sldns_buffer_invariant(buffer);
+ assert(buffer->_limit == buffer->_capacity);
+
+ remaining = sldns_buffer_remaining(buffer);
+ va_start(args, format);
+ written = vsnprintf((char *) sldns_buffer_current(buffer), remaining,
+ format, args);
+ va_end(args);
+ if (written == -1) {
+ buffer->_status_err = 1;
+ return -1;
+ } else if ((size_t) written >= remaining) {
+ if (!sldns_buffer_reserve(buffer, (size_t) written + 1)) {
+ buffer->_status_err = 1;
+ return -1;
+ }
+ va_start(args, format);
+ written = vsnprintf((char *) sldns_buffer_current(buffer),
+ sldns_buffer_remaining(buffer), format, args);
+ va_end(args);
+ if (written == -1) {
+ buffer->_status_err = 1;
+ return -1;
+ }
+ }
+ buffer->_position += written;
+ }
+ return written;
+}
+
+void
+sldns_buffer_free(sldns_buffer *buffer)
+{
+ if (!buffer) {
+ return;
+ }
+
+ if (!buffer->_fixed)
+ free(buffer->_data);
+
+ free(buffer);
+}
+
+void *
+sldns_buffer_export(sldns_buffer *buffer)
+{
+ buffer->_fixed = 1;
+ return buffer->_data;
+}
+
+int
+sldns_bgetc(sldns_buffer *buffer)
+{
+ if (!sldns_buffer_available_at(buffer, buffer->_position, sizeof(uint8_t))) {
+ sldns_buffer_set_position(buffer, sldns_buffer_limit(buffer));
+ /* sldns_buffer_rewind(buffer);*/
+ return EOF;
+ }
+ return (int)sldns_buffer_read_u8(buffer);
+}
+
+void
+sldns_buffer_copy(sldns_buffer* result, sldns_buffer* from)
+{
+ size_t tocopy = sldns_buffer_limit(from);
+
+ if(tocopy > sldns_buffer_capacity(result))
+ tocopy = sldns_buffer_capacity(result);
+ sldns_buffer_clear(result);
+ sldns_buffer_write(result, sldns_buffer_begin(from), tocopy);
+ sldns_buffer_flip(result);
+}