summaryrefslogtreecommitdiffstats
path: root/fluent-bit/lib/avro/src/string.c
diff options
context:
space:
mode:
Diffstat (limited to 'fluent-bit/lib/avro/src/string.c')
-rw-r--r--fluent-bit/lib/avro/src/string.c304
1 files changed, 304 insertions, 0 deletions
diff --git a/fluent-bit/lib/avro/src/string.c b/fluent-bit/lib/avro/src/string.c
new file mode 100644
index 00000000..f5cde949
--- /dev/null
+++ b/fluent-bit/lib/avro/src/string.c
@@ -0,0 +1,304 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to you under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "avro_private.h"
+#include "avro/data.h"
+#include "avro/allocation.h"
+#include "avro/errors.h"
+
+#ifndef AVRO_STRING_DEBUG
+#define AVRO_STRING_DEBUG 0
+#endif
+
+#if AVRO_STRING_DEBUG
+#include <stdio.h>
+#define DEBUG(...) \
+ do { \
+ fprintf(stderr, __VA_ARGS__); \
+ fprintf(stderr, "\n"); \
+ } while (0)
+#else
+#define DEBUG(...) /* don't print messages */
+#endif
+
+
+/*
+ * A resizable wrapped buffer implementation. This implementation makes
+ * actual copies in its copy method; if we wanted a zero-copy solution
+ * here, then we'd have to keep track of all copies of the buffer, so
+ * that we can update pointers whenever the buffer is resized (since
+ * this might change the location of the memory region).
+ */
+
+struct avro_wrapped_resizable {
+ size_t buf_size;
+};
+
+#define avro_wrapped_resizable_size(sz) \
+ (sizeof(struct avro_wrapped_resizable) + (sz))
+
+static void
+avro_wrapped_resizable_free(avro_wrapped_buffer_t *self)
+{
+ DEBUG("--- Freeing resizable <%p:%" PRIsz "> (%p)", self->buf, self->size, self->user_data);
+ struct avro_wrapped_resizable *resizable = (struct avro_wrapped_resizable *) self->user_data;
+ avro_free(resizable, avro_wrapped_resizable_size(resizable->buf_size));
+}
+
+static int
+avro_wrapped_resizable_resize(avro_wrapped_buffer_t *self, size_t desired)
+{
+ struct avro_wrapped_resizable *resizable = (struct avro_wrapped_resizable *) self->user_data;
+
+ /*
+ * If we've already allocated enough memory for the desired
+ * size, there's nothing to do.
+ */
+
+ if (resizable->buf_size >= desired) {
+ return 0;
+ }
+
+ size_t new_buf_size = resizable->buf_size * 2;
+ if (desired > new_buf_size) {
+ new_buf_size = desired;
+ }
+
+ DEBUG("--- Resizing <%p:%" PRIsz "> (%p) -> %" PRIsz,
+ self->buf, self->buf_size, self->user_data, new_buf_size);
+
+ struct avro_wrapped_resizable *new_resizable =
+ (struct avro_wrapped_resizable *) avro_realloc(resizable,
+ avro_wrapped_resizable_size(resizable->buf_size),
+ avro_wrapped_resizable_size(new_buf_size));
+ if (new_resizable == NULL) {
+ return ENOMEM;
+ }
+ DEBUG("--- New buffer <%p:%" PRIsz ">", new_buf, new_buf_size);
+
+ new_resizable->buf_size = new_buf_size;
+
+ char *old_buf = (char *) resizable;
+ char *new_buf = (char *) new_resizable;
+
+ ptrdiff_t offset = (char *) self->buf - old_buf;
+ DEBUG("--- Old data pointer is %p", self->buf);
+ self->buf = new_buf + offset;
+ self->user_data = new_resizable;
+ DEBUG("--- New data pointer is %p", self->buf);
+ return 0;
+}
+
+static int
+avro_wrapped_resizable_new(avro_wrapped_buffer_t *dest, size_t buf_size)
+{
+ size_t allocated_size = avro_wrapped_resizable_size(buf_size);
+ struct avro_wrapped_resizable *resizable =
+ (struct avro_wrapped_resizable *) avro_malloc(allocated_size);
+ if (resizable == NULL) {
+ return ENOMEM;
+ }
+
+ resizable->buf_size = buf_size;
+
+ dest->buf = ((char *) resizable) + sizeof(struct avro_wrapped_resizable);
+ DEBUG("--- Creating resizable <%p:%" PRIsz "> (%p)", dest->buf, buf_size, resizable);
+ dest->size = buf_size;
+ dest->user_data = resizable;
+ dest->free = avro_wrapped_resizable_free;
+ dest->copy = NULL;
+ dest->slice = NULL;
+ return 0;
+}
+
+#define is_resizable(buf) \
+ ((buf).free == avro_wrapped_resizable_free)
+
+
+
+void
+avro_raw_string_init(avro_raw_string_t *str)
+{
+ memset(str, 0, sizeof(avro_raw_string_t));
+}
+
+
+void
+avro_raw_string_clear(avro_raw_string_t *str)
+{
+ /*
+ * If the string's buffer is one that we control, then we don't
+ * free it; that lets us reuse the storage on the next call to
+ * avro_raw_string_set[_length].
+ */
+
+ if (is_resizable(str->wrapped)) {
+ DEBUG("--- Clearing resizable buffer");
+ str->wrapped.size = 0;
+ } else {
+ DEBUG("--- Freeing wrapped buffer");
+ avro_wrapped_buffer_free(&str->wrapped);
+ avro_raw_string_init(str);
+ }
+}
+
+
+void
+avro_raw_string_done(avro_raw_string_t *str)
+{
+ avro_wrapped_buffer_free(&str->wrapped);
+ avro_raw_string_init(str);
+}
+
+
+/**
+ * Makes sure that the string's buffer is one that we allocated
+ * ourselves, and that the buffer is big enough to hold a string of the
+ * given length.
+ */
+
+static int
+avro_raw_string_ensure_buf(avro_raw_string_t *str, size_t length)
+{
+ int rval;
+
+ DEBUG("--- Ensuring resizable buffer of size %" PRIsz, length);
+ if (is_resizable(str->wrapped)) {
+ /*
+ * If we've already got a resizable buffer, just have it
+ * resize itself.
+ */
+
+ return avro_wrapped_resizable_resize(&str->wrapped, length);
+ } else {
+ /*
+ * Stash a copy of the old wrapped buffer, and then
+ * create a new resizable buffer to store our content
+ * in.
+ */
+
+ avro_wrapped_buffer_t orig = str->wrapped;
+ check(rval, avro_wrapped_resizable_new(&str->wrapped, length));
+
+ /*
+ * If there was any content in the old wrapped buffer,
+ * copy it into the new resizable one.
+ */
+
+ if (orig.size > 0) {
+ size_t to_copy =
+ (orig.size < length)? orig.size: length;
+ memcpy((void *) str->wrapped.buf, orig.buf, to_copy);
+ }
+ avro_wrapped_buffer_free(&orig);
+
+ return 0;
+ }
+}
+
+
+void
+avro_raw_string_set_length(avro_raw_string_t *str,
+ const void *src, size_t length)
+{
+ avro_raw_string_ensure_buf(str, length+1);
+ memcpy((void *) str->wrapped.buf, src, length);
+ ((char *) str->wrapped.buf)[length] = '\0';
+ str->wrapped.size = length;
+}
+
+
+void avro_raw_string_append_length(avro_raw_string_t *str,
+ const void *src,
+ size_t length)
+{
+ if (avro_raw_string_length(str) == 0) {
+ return avro_raw_string_set_length(str, src, length);
+ }
+
+ avro_raw_string_ensure_buf(str, str->wrapped.size + length);
+ memcpy((char *) str->wrapped.buf + str->wrapped.size, src, length);
+ str->wrapped.size += length;
+}
+
+
+void
+avro_raw_string_set(avro_raw_string_t *str, const char *src)
+{
+ size_t length = strlen(src);
+ avro_raw_string_ensure_buf(str, length+1);
+ memcpy((void *) str->wrapped.buf, src, length+1);
+ str->wrapped.size = length+1;
+}
+
+
+void
+avro_raw_string_append(avro_raw_string_t *str, const char *src)
+{
+ if (avro_raw_string_length(str) == 0) {
+ return avro_raw_string_set(str, src);
+ }
+
+ /* Assume that str->wrapped.size includes a NUL terminator */
+ size_t length = strlen(src);
+ avro_raw_string_ensure_buf(str, str->wrapped.size + length);
+ memcpy((char *) str->wrapped.buf + str->wrapped.size - 1, src, length+1);
+ str->wrapped.size += length;
+}
+
+
+void
+avro_raw_string_give(avro_raw_string_t *str,
+ avro_wrapped_buffer_t *src)
+{
+ DEBUG("--- Giving control of <%p:%" PRIsz "> (%p) to string",
+ src->buf, src->size, src);
+ avro_wrapped_buffer_free(&str->wrapped);
+ avro_wrapped_buffer_move(&str->wrapped, src);
+}
+
+int
+avro_raw_string_grab(const avro_raw_string_t *str,
+ avro_wrapped_buffer_t *dest)
+{
+ return avro_wrapped_buffer_copy(dest, &str->wrapped, 0, str->wrapped.size);
+}
+
+
+int
+avro_raw_string_equals(const avro_raw_string_t *str1,
+ const avro_raw_string_t *str2)
+{
+ if (str1 == str2) {
+ return 1;
+ }
+
+ if (!str1 || !str2) {
+ return 0;
+ }
+
+ if (str1->wrapped.size != str2->wrapped.size) {
+ return 0;
+ }
+
+ return (memcmp(str1->wrapped.buf, str2->wrapped.buf,
+ str1->wrapped.size) == 0);
+}