[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