[Mesa-dev] [PATCH 1/9] util: Add a string buffer implementation
Grazvydas Ignotas
notasas at gmail.com
Mon May 22 00:07:01 UTC 2017
On Sun, May 21, 2017 at 11:49 PM, Thomas Helland
<thomashelland90 at gmail.com> wrote:
> Based on Vladislav Egorov's work on the preprocessor, but split
> out to a util functionality that should be universal. Setup, teardown,
> memory handling and general layout is modeled around the hash_table
> and the set, to make it familiar for everyone.
>
> A notable change is that this implementation is always null terminated.
> The rationale is that it will be less error-prone, as one might
> access the buffer directly, thereby reading a non-terminated string.
> Also, vsnprintf and friends prints the null-terminator.
> ---
> src/util/Makefile.sources | 2 +
> src/util/string_buffer.c | 180 ++++++++++++++++++++++++++++++++++++++++++++++
> src/util/string_buffer.h | 75 +++++++++++++++++++
> 3 files changed, 257 insertions(+)
> create mode 100644 src/util/string_buffer.c
> create mode 100644 src/util/string_buffer.h
>
> diff --git a/src/util/Makefile.sources b/src/util/Makefile.sources
> index e9057343dc..cb46639c87 100644
> --- a/src/util/Makefile.sources
> +++ b/src/util/Makefile.sources
> @@ -37,6 +37,8 @@ MESA_UTIL_FILES := \
> simple_list.h \
> slab.c \
> slab.h \
> + string_buffer.c \
> + string_buffer.h \
> string_to_uint_map.cpp \
> string_to_uint_map.h \
> strndup.h \
> diff --git a/src/util/string_buffer.c b/src/util/string_buffer.c
> new file mode 100644
> index 0000000000..a500ffd389
> --- /dev/null
> +++ b/src/util/string_buffer.c
> @@ -0,0 +1,180 @@
> +/*
> + * Copyright © 2017 Thomas Helland
> + *
> + * Permission is hereby granted, free of charge, to any person obtaining a
> + * copy of this software and associated documentation files (the "Software"),
> + * to deal in the Software without restriction, including without limitation
> + * the rights to use, copy, modify, merge, publish, distribute, sublicense,
> + * and/or sell copies of the Software, and to permit persons to whom the
> + * Software is furnished to do so, subject to the following conditions:
> + *
> + * The above copyright notice and this permission notice (including the next
> + * paragraph) shall be included in all copies or substantial portions of the
> + * Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
> + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
> + * IN THE SOFTWARE.
> + *
> + */
> +#include "ralloc.h"
> +#include "string_buffer.h"
> +
> +static bool
> +ensure_capacity(struct _mesa_string_buffer *str, uint32_t needed_capacity)
> +{
> + if (needed_capacity <= str->capacity)
> + return true;
> +
> + /* Too small, we have to resize our buffer.
> + * Double until we can fit the new string.
> + */
> + uint32_t new_capacity = str->capacity * 2;
> + while (needed_capacity > new_capacity)
> + new_capacity *= 2;
> +
> + str->buf = reralloc_array_size(str, str->buf, sizeof(char), new_capacity);
> + if (str->buf == NULL)
> + return false;
> +
> + str->capacity = new_capacity;
> + return true;
> +}
> +
> +struct _mesa_string_buffer *
> +_mesa_string_buffer_create(void *mem_ctx, uint32_t initial_capacity)
> +{
> + struct _mesa_string_buffer *str;
> + str = ralloc(mem_ctx, struct _mesa_string_buffer);
> +
> + if (str == NULL)
> + return NULL;
> +
> + /* If no initial capacity is set then set it to something */
> + str->capacity = initial_capacity ? initial_capacity : 8;
> + str->buf = ralloc_array(str, char, str->capacity);
> + str->length = 0;
> + str->buf[str->length] = '\0';
> + return str;
> +}
> +
> +void
> +_mesa_string_buffer_destroy(struct _mesa_string_buffer *str)
> +{
> + ralloc_free(str);
> +}
> +
> +bool
> +_mesa_string_buffer_append(struct _mesa_string_buffer *str, char *c)
const char *c
> +{
> + return _mesa_string_buffer_append_len(str, c, strlen(c));
> +}
> +
> +bool
> +_mesa_string_buffer_append_all(struct _mesa_string_buffer *str,
> + uint32_t num_args, ...)
> +{
> + int i;
> + char* s;
> + va_list args;
> + va_start(args, num_args);
> + for (i = 0; i < num_args; i++) {
> + s = va_arg(args, char*);
> + if (!_mesa_string_buffer_append_len(str, s, strlen(s)))
> + return false;
> + }
> + va_end(args);
> + return true;
> +}
> +
> +bool
> +_mesa_string_buffer_append_len(struct _mesa_string_buffer *str,
> + char *c, uint32_t len)
> +{
> + uint32_t needed_length = str->length + len + 1;
> + if (!ensure_capacity(str, needed_length))
> + return false;
> +
> + memcpy(str->buf + str->length, c, len);
> + str->length += len;
> + str->buf[str->length] = '\0';
> + return true;
> +}
> +
> +void
> +_mesa_string_buffer_clear(struct _mesa_string_buffer *str)
> +{
> + str->length = 0;
> + str->buf[str->length] = '\0';
> +}
> +
> +uint32_t
> +_mesa_string_buffer_space_left(struct _mesa_string_buffer *str)
> +{
> + return str->capacity - str->length - 1;
> +}
> +
> +bool
> +_mesa_string_buffer_vprintf(struct _mesa_string_buffer *str,
> + const char *format, va_list args)
> +{
> + uint32_t len;
> + uint32_t end = str->length;
> +
> +#if (defined(_MSC_VER) && _MSC_VER < 1900) || __MINGW32__
defined(__MINGW32__)
> + /* MSVC up to 2013 used non-standard vsnprintf() that returned -1
> + * if the buffer wasn't large enough. Another non-standard function
> + * _vscprintf() should be used to measure length of printf() output.
> + */
> + len = _vscprintf(format, args);
> +
> + /* Fail if an error happened in vscprintf() */
> + if (unlikely(len < 0))
> + return false;
but len is unsigned...
More information about the mesa-dev
mailing list