array: Add null-termination

This commit is contained in:
Benjamin Otte 2020-07-02 23:32:04 +02:00
parent 65359dcc59
commit a4cd974912
3 changed files with 80 additions and 10 deletions

View File

@ -39,6 +39,12 @@ G_BEGIN_DECLS
#endif
#endif
#ifdef GDK_ARRAY_NULL_TERMINATED
#define GDK_ARRAY_REAL_SIZE(_size) ((_size) + 1)
#else
#define GDK_ARRAY_REAL_SIZE(_size) (_size)
#endif
/* make this readable */
#define _T_ GDK_ARRAY_ELEMENT_TYPE
#define GdkArray GDK_ARRAY_TYPE_NAME
@ -54,7 +60,7 @@ struct GdkArray
_T_ *end;
_T_ *end_allocation;
#ifdef GDK_ARRAY_PREALLOC
_T_ preallocated[GDK_ARRAY_PREALLOC];
_T_ preallocated[GDK_ARRAY_REAL_SIZE(GDK_ARRAY_PREALLOC)];
#endif
};
@ -66,6 +72,9 @@ gdk_array(init) (GdkArray *self)
self->start = self->preallocated;
self->end = self->start;
self->end_allocation = self->start + GDK_ARRAY_PREALLOC;
#ifdef GDK_ARRAY_NULL_TERMINATED
*self->start = *(_T_[1]) {};
#endif
#else
self->start = NULL;
self->end = NULL;
@ -138,13 +147,21 @@ gdk_array(reserve) (GdkArray *self,
return;
size = gdk_array(get_size) (self);
new_size = 1 << g_bit_storage (MAX (n, 16) - 1);
new_size = 1 << g_bit_storage (MAX (GDK_ARRAY_REAL_SIZE (n), 16) - 1);
#ifdef GDK_ARRAY_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_) * GDK_ARRAY_REAL_SIZE (size));
}
else
#endif
#ifdef GDK_ARRAY_NULL_TERMINATED
if (self->start == NULL)
{
self->start = g_new (_T_, new_size);
*self->start = *(_T_[1]) {};
}
else
#endif
@ -152,6 +169,9 @@ gdk_array(reserve) (GdkArray *self,
self->end = self->start + size;
self->end_allocation = self->start + new_size;
#ifdef GDK_ARRAY_NULL_TERMINATED
self->end_allocation--;
#endif
}
G_GNUC_UNUSED static void
@ -161,19 +181,22 @@ gdk_array(splice) (GdkArray *self,
_T_ *additions,
gsize added)
{
gssize size = gdk_array(get_size) (self);
gsize size;
gsize remaining;
size = gdk_array(get_size) (self);
g_assert (pos + removed <= size);
remaining = size - pos - removed;
gdk_array(free_elements) (gdk_array(index) (self, pos),
gdk_array(index) (self, pos + removed));
gdk_array(reserve) (self, size - removed + added);
if (pos + removed < size && removed != added)
if (GDK_ARRAY_REAL_SIZE (remaining) && removed != added)
memmove (gdk_array(index) (self, pos + added),
gdk_array(index) (self, pos + removed),
(size - pos - removed) * sizeof (_T_));
GDK_ARRAY_REAL_SIZE (remaining) * sizeof (_T_));
if (added)
memcpy (gdk_array(index) (self, pos),
@ -210,10 +233,12 @@ gdk_array(get) (GdkArray *self,
#undef gdk_array_paste_more
#undef gdk_array_paste
#undef gdk_array
#undef GDK_ARRAY_REAL_SIZE
#undef GDK_ARRAY_PREALLOC
#undef GDK_ARRAY_ELEMENT_TYPE
#undef GDK_ARRAY_NAME
#undef GDK_ARRAY_TYPE_NAME
#undef GDK_ARRAY_PREALLOC
#undef GDK_ARRAY_NULL_TERMINATED
#endif

View File

@ -50,6 +50,34 @@ int_free_func (int data)
#define GDK_ARRAY_FREE_FUNC int_free_func
#include "arrayimpl.c"
#define GDK_ARRAY_ELEMENT_TYPE int
#define GDK_ARRAY_NAME null_int_array
#define GDK_ARRAY_TYPE_NAME NullIntVector
#define GDK_ARRAY_NULL_TERMINATED 1
#include "arrayimpl.c"
#define GDK_ARRAY_ELEMENT_TYPE int
#define GDK_ARRAY_NAME null_pre_int_array
#define GDK_ARRAY_TYPE_NAME NullPreIntVector
#define GDK_ARRAY_PREALLOC 100
#define GDK_ARRAY_NULL_TERMINATED 1
#include "arrayimpl.c"
#define GDK_ARRAY_ELEMENT_TYPE int
#define GDK_ARRAY_NAME null_free_int_array
#define GDK_ARRAY_TYPE_NAME NullFreeIntVector
#define GDK_ARRAY_FREE_FUNC int_free_func
#define GDK_ARRAY_NULL_TERMINATED 1
#include "arrayimpl.c"
#define GDK_ARRAY_ELEMENT_TYPE int
#define GDK_ARRAY_NAME null_pre_free_int_array
#define GDK_ARRAY_TYPE_NAME NullPreFreeIntVector
#define GDK_ARRAY_PREALLOC 100
#define GDK_ARRAY_FREE_FUNC int_free_func
#define GDK_ARRAY_NULL_TERMINATED 1
#include "arrayimpl.c"
int
main (int argc, char *argv[])
{
@ -59,11 +87,19 @@ main (int argc, char *argv[])
g_test_add_func ("/intarray/simple", int_array_test_simple);
g_test_add_func ("/intarray/prealloc/simple", pre_int_array_test_simple);
g_test_add_func ("/intarray/freefunc/simple", free_int_array_test_simple);
g_test_add_func ("/intarray/prealloc_freefunc_simple", pre_free_int_array_test_simple);
g_test_add_func ("/intarray/prealloc/freefunc/simple", pre_free_int_array_test_simple);
g_test_add_func ("/intarray/null/simple", null_int_array_test_simple);
g_test_add_func ("/intarray/null/prealloc/simple", null_pre_int_array_test_simple);
g_test_add_func ("/intarray/null/freefunc/simple", null_free_int_array_test_simple);
g_test_add_func ("/intarray/null/prealloc/freefunc/simple", null_pre_free_int_array_test_simple);
g_test_add_func ("/intarray/splice", int_array_test_splice);
g_test_add_func ("/intarray/prealloc/splice", pre_int_array_test_splice);
g_test_add_func ("/intarray/freefunc/splice", free_int_array_test_splice);
g_test_add_func ("/intarray/prealloc_freefunc_splice", pre_free_int_array_test_splice);
g_test_add_func ("/intarray/prealloc/freefunc/splice", pre_free_int_array_test_splice);
g_test_add_func ("/intarray/null/splice", null_int_array_test_splice);
g_test_add_func ("/intarray/null/prealloc/splice", null_pre_int_array_test_splice);
g_test_add_func ("/intarray/null/freefunc/splice", null_free_int_array_test_splice);
g_test_add_func ("/intarray/null/prealloc/freefunc/splice", null_pre_free_int_array_test_splice);
return g_test_run ();
}

View File

@ -36,6 +36,9 @@ gdk_array(test_simple) (void)
g_assert_cmpint (gdk_array(get_size) (&v), ==, i);
g_assert_cmpint (gdk_array(get_size) (&v), <=, gdk_array(get_capacity) (&v));
gdk_array(append) (&v, i);
#ifdef GDK_ARRAY_NULL_TERMINATED
g_assert_cmpint (*gdk_array(index) (&v, gdk_array(get_size) (&v)), ==, 0);
#endif
}
g_assert_cmpint (gdk_array(get_size) (&v), ==, i);
g_assert_cmpint (gdk_array(get_size) (&v), <=, gdk_array(get_capacity) (&v));
@ -84,6 +87,10 @@ gdk_array(test_splice) (void)
g_assert_cmpint (gdk_array(get_size) (&v), ==, old_size + add - remove);
g_assert_cmpint (gdk_array(get_size) (&v), <=, gdk_array(get_capacity) (&v));
#ifdef GDK_ARRAY_NULL_TERMINATED
if (gdk_array(get_size) (&v))
g_assert_cmpint (*gdk_array(index) (&v, gdk_array(get_size) (&v)), ==, 0);
#endif
for (j = 0; j < add; j++)
g_assert_cmpint (gdk_array(get) (&v, pos + j), ==, additions[j]);
}
@ -100,9 +107,11 @@ gdk_array(test_splice) (void)
#undef gdk_array_paste_more
#undef gdk_array_paste
#undef gdk_array
#undef GDK_ARRAY_REAL_SIZE
#undef GDK_ARRAY_PREALLOC
#undef GDK_ARRAY_ELEMENT_TYPE
#undef GDK_ARRAY_NAME
#undef GDK_ARRAY_TYPE_NAME
#undef GDK_ARRAY_PREALLOC
#undef GDK_ARRAY_NULL_TERMINATED