On Sun, May 21, 2017 at 11:49 PM, Thomas Helland <thomashellan...@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... _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/mesa-dev