Signed-off-by: Matteo Bruni mbruni@codeweavers.com --- v2: Handle rc < 0 case, use vkd3d_array_reserve().
libs/vkd3d-shader/vkd3d_shader_main.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-)
diff --git a/libs/vkd3d-shader/vkd3d_shader_main.c b/libs/vkd3d-shader/vkd3d_shader_main.c index 16994d20..ad862181 100644 --- a/libs/vkd3d-shader/vkd3d_shader_main.c +++ b/libs/vkd3d-shader/vkd3d_shader_main.c @@ -41,20 +41,19 @@ static void vkd3d_string_buffer_clear(struct vkd3d_string_buffer *buffer)
static bool vkd3d_string_buffer_resize(struct vkd3d_string_buffer *buffer, int rc) { - unsigned int new_buffer_size = buffer->buffer_size * 2; - char *new_buffer; + unsigned int new_buffer_size = max(buffer->buffer_size * 2, 32); + + if (rc >= 0 && rc < buffer->buffer_size - buffer->content_size) + return true;
- new_buffer_size = max(new_buffer_size, 32); while (rc > 0 && (unsigned int)rc >= new_buffer_size - buffer->content_size) new_buffer_size *= 2; - if (!(new_buffer = vkd3d_realloc(buffer->buffer, new_buffer_size))) + if (!vkd3d_array_reserve((void **)&buffer->buffer, &buffer->buffer_size, new_buffer_size, 1)) { ERR("Failed to grow buffer.\n"); buffer->buffer[buffer->content_size] = '\0'; return false; } - buffer->buffer = new_buffer; - buffer->buffer_size = new_buffer_size; return true; }
Signed-off-by: Matteo Bruni mbruni@codeweavers.com --- v2: Initialize string buffers with a small local buffer.
This makes vkd3d_string_buffer_init() provide a fully usable string buffer without doing dynamic allocations and also preserving the "buffer is never NULL" invariant. Hopefully not too cumbersome.
libs/vkd3d-shader/vkd3d_shader_main.c | 22 +++++++++++----------- libs/vkd3d-shader/vkd3d_shader_private.h | 1 + 2 files changed, 12 insertions(+), 11 deletions(-)
diff --git a/libs/vkd3d-shader/vkd3d_shader_main.c b/libs/vkd3d-shader/vkd3d_shader_main.c index ad862181..f65f9b2f 100644 --- a/libs/vkd3d-shader/vkd3d_shader_main.c +++ b/libs/vkd3d-shader/vkd3d_shader_main.c @@ -25,12 +25,16 @@ VKD3D_DEBUG_ENV_NAME("VKD3D_SHADER_DEBUG");
void vkd3d_string_buffer_init(struct vkd3d_string_buffer *buffer) { - memset(buffer, 0, sizeof(*buffer)); + buffer->buffer = buffer->local_buffer; + buffer->buffer_size = sizeof(buffer->local_buffer); + buffer->content_size = 0; + memset(buffer->local_buffer, 0, sizeof(buffer->local_buffer)); }
void vkd3d_string_buffer_cleanup(struct vkd3d_string_buffer *buffer) { - vkd3d_free(buffer->buffer); + if (buffer->buffer != buffer->local_buffer) + vkd3d_free(buffer->buffer); }
static void vkd3d_string_buffer_clear(struct vkd3d_string_buffer *buffer) @@ -42,18 +46,22 @@ static void vkd3d_string_buffer_clear(struct vkd3d_string_buffer *buffer) static bool vkd3d_string_buffer_resize(struct vkd3d_string_buffer *buffer, int rc) { unsigned int new_buffer_size = max(buffer->buffer_size * 2, 32); + char *new_buffer = buffer->buffer == buffer->local_buffer ? NULL : buffer->buffer;
if (rc >= 0 && rc < buffer->buffer_size - buffer->content_size) return true;
while (rc > 0 && (unsigned int)rc >= new_buffer_size - buffer->content_size) new_buffer_size *= 2; - if (!vkd3d_array_reserve((void **)&buffer->buffer, &buffer->buffer_size, new_buffer_size, 1)) + if (!vkd3d_array_reserve((void **)&new_buffer, &buffer->buffer_size, new_buffer_size, 1)) { ERR("Failed to grow buffer.\n"); buffer->buffer[buffer->content_size] = '\0'; return false; } + if (buffer->buffer == buffer->local_buffer) + memcpy(new_buffer, buffer->local_buffer, buffer->content_size); + buffer->buffer = new_buffer; return true; }
@@ -63,9 +71,6 @@ int vkd3d_string_buffer_vprintf(struct vkd3d_string_buffer *buffer, const char * va_list a; int rc;
- if (!buffer->content_size && !vkd3d_string_buffer_resize(buffer, 32)) - return -1; - for (;;) { rem = buffer->buffer_size - buffer->content_size; @@ -144,11 +149,6 @@ struct vkd3d_string_buffer *vkd3d_string_buffer_get(struct vkd3d_string_buffer_c if (!(buffer = vkd3d_malloc(sizeof(*buffer)))) return NULL; vkd3d_string_buffer_init(buffer); - if (!vkd3d_string_buffer_resize(buffer, 1)) - { - vkd3d_free(buffer); - return NULL; - } } else { diff --git a/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d-shader/vkd3d_shader_private.h index 54ac5326..5679e940 100644 --- a/libs/vkd3d-shader/vkd3d_shader_private.h +++ b/libs/vkd3d-shader/vkd3d_shader_private.h @@ -894,6 +894,7 @@ struct vkd3d_string_buffer char *buffer; unsigned int buffer_size; unsigned int content_size; + char local_buffer[16]; };
struct vkd3d_string_buffer_cache
Signed-off-by: Matteo Bruni mbruni@codeweavers.com --- v2: Use %zu to print size_t.
include/private/vkd3d_memory.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/include/private/vkd3d_memory.h b/include/private/vkd3d_memory.h index f6846d66..8a2edb10 100644 --- a/include/private/vkd3d_memory.h +++ b/include/private/vkd3d_memory.h @@ -37,7 +37,7 @@ static inline void *vkd3d_malloc(size_t size) static inline void *vkd3d_realloc(void *ptr, size_t size) { if (!(ptr = realloc(ptr, size))) - ERR("Out of memory.\n"); + ERR("Out of memory, size %zu.\n", size); return ptr; }
Signed-off-by: Henri Verbeet hverbeet@codeweavers.com
On Thu, 26 Aug 2021 at 18:05, Matteo Bruni mbruni@codeweavers.com wrote:
static bool vkd3d_string_buffer_resize(struct vkd3d_string_buffer *buffer, int rc) {
- unsigned int new_buffer_size = buffer->buffer_size * 2;
- char *new_buffer;
- unsigned int new_buffer_size = max(buffer->buffer_size * 2, 32);
- if (rc >= 0 && rc < buffer->buffer_size - buffer->content_size)
return true;
- new_buffer_size = max(new_buffer_size, 32); while (rc > 0 && (unsigned int)rc >= new_buffer_size - buffer->content_size) new_buffer_size *= 2;
- if (!(new_buffer = vkd3d_realloc(buffer->buffer, new_buffer_size)))
- if (!vkd3d_array_reserve((void **)&buffer->buffer, &buffer->buffer_size, new_buffer_size, 1)) { ERR("Failed to grow buffer.\n"); buffer->buffer[buffer->content_size] = '\0'; return false; }
- buffer->buffer = new_buffer;
- buffer->buffer_size = new_buffer_size; return true;
}
Note that now that we're using vkd3d_array_reserve(), we no longer need the "while (rc > 0 && ...)" loop, or the size check you're introducing. In the rc >= 0 case, we can pass "buffer->content_size + rc" to vkd3d_array_reserve(), and it will take care of all that. If rc < 0, we pass "max(buffer->buffer_size * 2, 32)" instead.