From 3a81e51ede67af5e5e02cc07fb9326e107ba7a8d Mon Sep 17 00:00:00 2001 From: Benjamin Otte Date: Fri, 3 Jul 2020 03:05:40 +0200 Subject: [PATCH] vector: Add null-termination --- gtk/gtkvectorimpl.c | 41 ++++++++++++++++++++++++++++++-------- testsuite/gtk/vector.c | 40 +++++++++++++++++++++++++++++++++++-- testsuite/gtk/vectorimpl.c | 11 +++++++++- 3 files changed, 81 insertions(+), 11 deletions(-) diff --git a/gtk/gtkvectorimpl.c b/gtk/gtkvectorimpl.c index 2a0714f38d..ee5fbc1114 100644 --- a/gtk/gtkvectorimpl.c +++ b/gtk/gtkvectorimpl.c @@ -39,6 +39,12 @@ G_BEGIN_DECLS #endif #endif +#ifdef GTK_VECTOR_NULL_TERMINATED +#define GTK_VECTOR_REAL_SIZE(_size) ((_size) + 1) +#else +#define GTK_VECTOR_REAL_SIZE(_size) (_size) +#endif + /* make this readable */ #define _T_ GTK_VECTOR_ELEMENT_TYPE #define GtkVector GTK_VECTOR_TYPE_NAME @@ -54,7 +60,7 @@ struct GtkVector _T_ *end; _T_ *end_allocation; #ifdef GTK_VECTOR_PREALLOC - _T_ preallocated[GTK_VECTOR_PREALLOC]; + _T_ preallocated[GTK_VECTOR_REAL_SIZE(GTK_VECTOR_PREALLOC)]; #endif }; @@ -66,6 +72,9 @@ gtk_vector(init) (GtkVector *self) self->start = self->preallocated; self->end = self->start; self->end_allocation = self->start + GTK_VECTOR_PREALLOC; +#ifdef GTK_VECTOR_NULL_TERMINATED + *self->start = *(_T_[1]) {}; +#endif #else self->start = NULL; self->end = NULL; @@ -130,7 +139,7 @@ gtk_vector(is_empty) (GtkVector *self) G_GNUC_UNUSED static void gtk_vector(reserve) (GtkVector *self, - gsize n) + gsize n) { gsize new_size, size; @@ -138,13 +147,21 @@ gtk_vector(reserve) (GtkVector *self, return; size = gtk_vector(get_size) (self); - new_size = 1 << g_bit_storage (MAX (n, 16) - 1); + new_size = 1 << g_bit_storage (MAX (GTK_VECTOR_REAL_SIZE (n), 16) - 1); #ifdef GTK_VECTOR_PREALLOC if (self->start == self->preallocated) { self->start = g_new (_T_, new_size); - memcpy (self->start, self->preallocated, sizeof (_T_) * size); + memcpy (self->start, self->preallocated, sizeof (_T_) * GTK_VECTOR_REAL_SIZE (size)); + } + else +#endif +#ifdef GTK_VECTOR_NULL_TERMINATED + if (self->start == NULL) + { + self->start = g_new (_T_, new_size); + *self->start = *(_T_[1]) {}; } else #endif @@ -152,6 +169,9 @@ gtk_vector(reserve) (GtkVector *self, self->end = self->start + size; self->end_allocation = self->start + new_size; +#ifdef GTK_VECTOR_NULL_TERMINATED + self->end_allocation--; +#endif } G_GNUC_UNUSED static void @@ -161,19 +181,22 @@ gtk_vector(splice) (GtkVector *self, _T_ *additions, gsize added) { - gssize size = gtk_vector(get_size) (self); + gsize size; + gsize remaining; + size = gtk_vector(get_size) (self); g_assert (pos + removed <= size); + remaining = size - pos - removed; gtk_vector(free_elements) (gtk_vector(index) (self, pos), gtk_vector(index) (self, pos + removed)); gtk_vector(reserve) (self, size - removed + added); - if (pos + removed < size && removed != added) + if (GTK_VECTOR_REAL_SIZE (remaining) && removed != added) memmove (gtk_vector(index) (self, pos + added), gtk_vector(index) (self, pos + removed), - (size - pos - removed) * sizeof (_T_)); + GTK_VECTOR_REAL_SIZE (remaining) * sizeof (_T_)); if (added) memcpy (gtk_vector(index) (self, pos), @@ -210,10 +233,12 @@ gtk_vector(get) (GtkVector *self, #undef gtk_vector_paste_more #undef gtk_vector_paste #undef gtk_vector +#undef GTK_VECTOR_REAL_SIZE -#undef GTK_VECTOR_PREALLOC #undef GTK_VECTOR_ELEMENT_TYPE #undef GTK_VECTOR_NAME #undef GTK_VECTOR_TYPE_NAME +#undef GTK_VECTOR_PREALLOC +#undef GTK_VECTOR_NULL_TERMINATED #endif diff --git a/testsuite/gtk/vector.c b/testsuite/gtk/vector.c index 5f47c9572e..6d8e55a6b5 100644 --- a/testsuite/gtk/vector.c +++ b/testsuite/gtk/vector.c @@ -50,6 +50,34 @@ int_free_func (int data) #define GTK_VECTOR_FREE_FUNC int_free_func #include "vectorimpl.c" +#define GTK_VECTOR_ELEMENT_TYPE int +#define GTK_VECTOR_NAME null_int_vector +#define GTK_VECTOR_TYPE_NAME NullIntVector +#define GTK_VECTOR_NULL_TERMINATED 1 +#include "vectorimpl.c" + +#define GTK_VECTOR_ELEMENT_TYPE int +#define GTK_VECTOR_NAME null_pre_int_vector +#define GTK_VECTOR_TYPE_NAME NullPreIntVector +#define GTK_VECTOR_PREALLOC 100 +#define GTK_VECTOR_NULL_TERMINATED 1 +#include "vectorimpl.c" + +#define GTK_VECTOR_ELEMENT_TYPE int +#define GTK_VECTOR_NAME null_free_int_vector +#define GTK_VECTOR_TYPE_NAME NullFreeIntVector +#define GTK_VECTOR_FREE_FUNC int_free_func +#define GTK_VECTOR_NULL_TERMINATED 1 +#include "vectorimpl.c" + +#define GTK_VECTOR_ELEMENT_TYPE int +#define GTK_VECTOR_NAME null_pre_free_int_vector +#define GTK_VECTOR_TYPE_NAME NullPreFreeIntVector +#define GTK_VECTOR_PREALLOC 100 +#define GTK_VECTOR_FREE_FUNC int_free_func +#define GTK_VECTOR_NULL_TERMINATED 1 +#include "vectorimpl.c" + int main (int argc, char *argv[]) { @@ -59,11 +87,19 @@ main (int argc, char *argv[]) g_test_add_func ("/intvector/simple", int_vector_test_simple); g_test_add_func ("/intvector/prealloc/simple", pre_int_vector_test_simple); g_test_add_func ("/intvector/freefunc/simple", free_int_vector_test_simple); - g_test_add_func ("/intvector/prealloc_freefunc_simple", pre_free_int_vector_test_simple); + g_test_add_func ("/intvector/prealloc/freefunc/simple", pre_free_int_vector_test_simple); + g_test_add_func ("/intvector/null/simple", null_int_vector_test_simple); + g_test_add_func ("/intvector/null/prealloc/simple", null_pre_int_vector_test_simple); + g_test_add_func ("/intvector/null/freefunc/simple", null_free_int_vector_test_simple); + g_test_add_func ("/intvector/null/prealloc/freefunc/simple", null_pre_free_int_vector_test_simple); g_test_add_func ("/intvector/splice", int_vector_test_splice); g_test_add_func ("/intvector/prealloc/splice", pre_int_vector_test_splice); g_test_add_func ("/intvector/freefunc/splice", free_int_vector_test_splice); - g_test_add_func ("/intvector/prealloc_freefunc_splice", pre_free_int_vector_test_splice); + g_test_add_func ("/intvector/prealloc/freefunc/splice", pre_free_int_vector_test_splice); + g_test_add_func ("/intvector/null/splice", null_int_vector_test_splice); + g_test_add_func ("/intvector/null/prealloc/splice", null_pre_int_vector_test_splice); + g_test_add_func ("/intvector/null/freefunc/splice", null_free_int_vector_test_splice); + g_test_add_func ("/intvector/null/prealloc/freefunc/splice", null_pre_free_int_vector_test_splice); return g_test_run (); } diff --git a/testsuite/gtk/vectorimpl.c b/testsuite/gtk/vectorimpl.c index 3b0c0f905a..10da9cfdbd 100644 --- a/testsuite/gtk/vectorimpl.c +++ b/testsuite/gtk/vectorimpl.c @@ -36,6 +36,9 @@ gtk_vector(test_simple) (void) g_assert_cmpint (gtk_vector(get_size) (&v), ==, i); g_assert_cmpint (gtk_vector(get_size) (&v), <=, gtk_vector(get_capacity) (&v)); gtk_vector(append) (&v, i); +#ifdef GTK_VECTOR_NULL_TERMINATED + g_assert_cmpint (*gtk_vector(index) (&v, gtk_vector(get_size) (&v)), ==, 0); +#endif } g_assert_cmpint (gtk_vector(get_size) (&v), ==, i); g_assert_cmpint (gtk_vector(get_size) (&v), <=, gtk_vector(get_capacity) (&v)); @@ -84,6 +87,10 @@ gtk_vector(test_splice) (void) g_assert_cmpint (gtk_vector(get_size) (&v), ==, old_size + add - remove); g_assert_cmpint (gtk_vector(get_size) (&v), <=, gtk_vector(get_capacity) (&v)); +#ifdef GTK_VECTOR_NULL_TERMINATED + if (gtk_vector(get_size) (&v)) + g_assert_cmpint (*gtk_vector(index) (&v, gtk_vector(get_size) (&v)), ==, 0); +#endif for (j = 0; j < add; j++) g_assert_cmpint (gtk_vector(get) (&v, pos + j), ==, additions[j]); } @@ -100,9 +107,11 @@ gtk_vector(test_splice) (void) #undef gtk_vector_paste_more #undef gtk_vector_paste #undef gtk_vector +#undef GTK_VECTOR_REAL_SIZE -#undef GTK_VECTOR_PREALLOC #undef GTK_VECTOR_ELEMENT_TYPE #undef GTK_VECTOR_NAME #undef GTK_VECTOR_TYPE_NAME +#undef GTK_VECTOR_PREALLOC +#undef GTK_VECTOR_NULL_TERMINATED