From d207a956563d1f010d00dded31b3db1263c28b7b Mon Sep 17 00:00:00 2001 From: Georges Basile Stavracas Neto Date: Sun, 3 May 2026 13:03:29 -0300 Subject: [PATCH] contrib: Import gdkarrayimpl.c from GDK We'll use this in the next patch to reimplement GcalEventList. Part-of: --- src/contrib/gdkarrayimpl.c | 334 +++++++++++++++++++++++++++++++++++++ src/contrib/meson.build | 1 + src/meson.build | 1 + 3 files changed, 336 insertions(+) create mode 100644 src/contrib/gdkarrayimpl.c create mode 100644 src/contrib/meson.build diff --git a/src/contrib/gdkarrayimpl.c b/src/contrib/gdkarrayimpl.c new file mode 100644 index 00000000..5aeaf9d1 --- /dev/null +++ b/src/contrib/gdkarrayimpl.c @@ -0,0 +1,334 @@ +/* + * Copyright © 2020 Benjamin Otte + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + * Authors: Benjamin Otte + */ + +#include + +G_BEGIN_DECLS + +#ifndef GDK_ARRAY_TYPE_NAME +#define GDK_ARRAY_TYPE_NAME GdkArray +#endif + +#ifndef GDK_ARRAY_NAME +#define GDK_ARRAY_NAME gdk_array +#endif + +#ifndef GDK_ARRAY_ELEMENT_TYPE +#define GDK_ARRAY_ELEMENT_TYPE gpointer +#endif + +#ifdef GDK_ARRAY_PREALLOC +#if GDK_ARRAY_PREALLOC == 0 +#undef GDK_ARRAY_PREALLOC +#endif +#endif + +#ifdef GDK_ARRAY_NULL_TERMINATED +#define GDK_ARRAY_REAL_SIZE(_size) ((_size) + 1) +#define GDK_ARRAY_MAX_SIZE (G_MAXSIZE / sizeof (_T_) - 1) +#else +#define GDK_ARRAY_REAL_SIZE(_size) (_size) +#define GDK_ARRAY_MAX_SIZE (G_MAXSIZE / sizeof (_T_)) +#endif + +/* make this readable */ +#define _T_ GDK_ARRAY_ELEMENT_TYPE +#define GdkArray GDK_ARRAY_TYPE_NAME +#define gdk_array_paste_more(GDK_ARRAY_NAME, func_name) GDK_ARRAY_NAME ## _ ## func_name +#define gdk_array_paste(GDK_ARRAY_NAME, func_name) gdk_array_paste_more (GDK_ARRAY_NAME, func_name) +#define gdk_array(func_name) gdk_array_paste (GDK_ARRAY_NAME, func_name) + +typedef struct GdkArray GdkArray; + +struct GdkArray +{ + _T_ *start; + _T_ *end; + _T_ *end_allocation; +#ifdef GDK_ARRAY_PREALLOC + _T_ preallocated[GDK_ARRAY_REAL_SIZE(GDK_ARRAY_PREALLOC)]; +#endif +}; + +/* no G_GNUC_UNUSED here, if you don't use an array type, remove it. */ +static inline void +gdk_array(init) (GdkArray *self) +{ +#ifdef GDK_ARRAY_PREALLOC + 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]) { 0 }; +#endif +#else + self->start = NULL; + self->end = NULL; + self->end_allocation = NULL; +#endif +} + +G_GNUC_UNUSED static inline gsize +gdk_array(get_capacity) (const GdkArray *self) +{ + return self->end_allocation - self->start; +} + +G_GNUC_UNUSED static inline gsize +gdk_array(get_size) (const GdkArray *self) +{ + return self->end - self->start; +} + +static inline void +gdk_array(free_elements) (_T_ *start, + _T_ *end) +{ +#ifdef GDK_ARRAY_FREE_FUNC + _T_ *e; + for (e = start; e < end; e++) +#ifdef GDK_ARRAY_BY_VALUE + GDK_ARRAY_FREE_FUNC (e); +#else + GDK_ARRAY_FREE_FUNC (*e); +#endif +#endif +} + +/* no G_GNUC_UNUSED here */ +static inline void +gdk_array(clear) (GdkArray *self) +{ + gdk_array(free_elements) (self->start, self->end); + +#ifdef GDK_ARRAY_PREALLOC + if (self->start != self->preallocated) +#endif + g_free_sized (self->start, gdk_array(get_capacity) (self) * sizeof (_T_)); + gdk_array(init) (self); +} + +/* + * gdk_array_steal: + * @self: the array + * + * Steals all data in the array and clears the array. + * + * If you need to know the size of the data, you should query it + * beforehand. + * + * Returns: The array's data + **/ +G_GNUC_UNUSED static inline _T_ * +gdk_array(steal) (GdkArray *self) +{ + _T_ *result; + +#ifdef GDK_ARRAY_PREALLOC + if (self->start == self->preallocated) + { + gsize size = GDK_ARRAY_REAL_SIZE (gdk_array(get_size) (self)); + result = g_new (_T_, size); + memcpy (result, self->preallocated, sizeof (_T_) * size); + } + else +#endif + result = self->start; + + gdk_array(init) (self); + + return result; +} + +G_GNUC_UNUSED static inline _T_ * +gdk_array(get_data) (const GdkArray *self) +{ + return self->start; +} + +G_GNUC_UNUSED static inline _T_ * +gdk_array(index) (const GdkArray *self, + gsize pos) +{ + return self->start + pos; +} + +G_GNUC_UNUSED static inline gboolean +gdk_array(is_empty) (const GdkArray *self) +{ + return self->end == self->start; +} + +G_GNUC_UNUSED static inline void +gdk_array(reserve) (GdkArray *self, + gsize n) +{ + gsize new_capacity, size, capacity; + + if (G_UNLIKELY (n > GDK_ARRAY_MAX_SIZE)) + g_error ("requesting array size of %zu, but maximum size is %zu", n, GDK_ARRAY_MAX_SIZE); + + capacity = gdk_array(get_capacity) (self); + if (n <= capacity) + return; + + size = gdk_array(get_size) (self); + /* capacity * 2 can overflow, that's why we MAX() */ + new_capacity = MAX (GDK_ARRAY_REAL_SIZE (n), capacity * 2); + +#ifdef GDK_ARRAY_PREALLOC + if (self->start == self->preallocated) + { + self->start = g_new (_T_, new_capacity); + 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_capacity); + *self->start = *(_T_[1]) { 0 }; + } + else +#endif + self->start = g_renew (_T_, self->start, new_capacity); + + self->end = self->start + size; + self->end_allocation = self->start + new_capacity; +#ifdef GDK_ARRAY_NULL_TERMINATED + self->end_allocation--; +#endif +} + +G_GNUC_UNUSED static inline void +gdk_array(splice) (GdkArray *self, + gsize pos, + gsize removed, + gboolean stolen, +#ifdef GDK_ARRAY_BY_VALUE + const _T_ *additions, +#else + _T_ *additions, +#endif + gsize added) +{ + gsize size; + gsize remaining; + + size = gdk_array(get_size) (self); + g_assert (pos + removed <= size); + remaining = size - pos - removed; + + if (!stolen) + gdk_array(free_elements) (gdk_array(index) (self, pos), + gdk_array(index) (self, pos + removed)); + + gdk_array(reserve) (self, size - removed + added); + + if (GDK_ARRAY_REAL_SIZE (remaining) && removed != added) + memmove (gdk_array(index) (self, pos + added), + gdk_array(index) (self, pos + removed), + GDK_ARRAY_REAL_SIZE (remaining) * sizeof (_T_)); + + if (added) + { + if (additions) + memcpy (gdk_array(index) (self, pos), + additions, + added * sizeof (_T_)); +#ifndef GDK_ARRAY_NO_MEMSET + else + memset (gdk_array(index) (self, pos), 0, added * sizeof (_T_)); +#endif + } + + + /* might overflow, but does the right thing */ + self->end += added - removed; +} + +G_GNUC_UNUSED static void +gdk_array(set_size) (GdkArray *self, + gsize new_size) +{ + gsize old_size = gdk_array(get_size) (self); + if (new_size > old_size) + gdk_array(splice) (self, old_size, 0, FALSE, NULL, new_size - old_size); + else + gdk_array(splice) (self, new_size, old_size - new_size, FALSE, NULL, 0); +} + +G_GNUC_UNUSED static void +gdk_array(append) (GdkArray *self, +#ifdef GDK_ARRAY_BY_VALUE + _T_ *value) +#else + _T_ value) +#endif +{ + gdk_array(splice) (self, + gdk_array(get_size) (self), + 0, + FALSE, +#ifdef GDK_ARRAY_BY_VALUE + value, +#else + &value, +#endif + 1); +} + +#ifdef GDK_ARRAY_BY_VALUE +G_GNUC_UNUSED static _T_ * +gdk_array(get) (const GdkArray *self, + gsize pos) +{ + return gdk_array(index) (self, pos); +} +#else +G_GNUC_UNUSED static _T_ +gdk_array(get) (const GdkArray *self, + gsize pos) + { + return *gdk_array(index) (self, pos); + } +#endif + +#ifndef GDK_ARRAY_NO_UNDEF + +#undef _T_ +#undef GdkArray +#undef gdk_array_paste_more +#undef gdk_array_paste +#undef gdk_array +#undef GDK_ARRAY_REAL_SIZE +#undef GDK_ARRAY_MAX_SIZE + +#undef GDK_ARRAY_BY_VALUE +#undef GDK_ARRAY_ELEMENT_TYPE +#undef GDK_ARRAY_FREE_FUNC +#undef GDK_ARRAY_NAME +#undef GDK_ARRAY_NULL_TERMINATED +#undef GDK_ARRAY_PREALLOC +#undef GDK_ARRAY_TYPE_NAME +#undef GDK_ARRAY_NO_MEMSET +#endif + +G_END_DECLS diff --git a/src/contrib/meson.build b/src/contrib/meson.build new file mode 100644 index 00000000..7c068dc5 --- /dev/null +++ b/src/contrib/meson.build @@ -0,0 +1 @@ +calendar_incs += include_directories('.') diff --git a/src/meson.build b/src/meson.build index 7b86f803..d22917af 100644 --- a/src/meson.build +++ b/src/meson.build @@ -59,6 +59,7 @@ calendar_incs = [ sources = files() subdir('appdata') +subdir('contrib') subdir('core') subdir('gui') subdir('search')