src/fcptrlist.c | 18 +++++++++--------- test/meson.build | 4 +++- test/test-ptrlist.c | 33 +++++++++++++++++++++++++++++++++ 3 files changed, 45 insertions(+), 10 deletions(-) New commits: commit 4e6cdf71ea8a3e76159aab2cada4c77b5ae35b49 Merge: 005649e d72a348 Author: Akira TAGOH <akira@xxxxxxxxx> Date: Wed May 7 16:01:12 2025 +0000 Merge branch 'issues/466' into 'main' Improve performance of FcPtrListIterInitAtLast Closes #466 See merge request fontconfig/fontconfig!402 commit d72a348fe61ca055147339c29461bd9d2e73d34d Author: Akira TAGOH <akira@xxxxxxxxx> Date: Wed May 7 20:06:19 2025 +0900 Improve performance of FcPtrListIterInitAtLast It causes slow-parsing a big XML file Patch from Idriss Fekir Fixes https://gitlab.freedesktop.org/fontconfig/fontconfig/-/issues/466 Changelog: performance diff --git a/src/fcptrlist.c b/src/fcptrlist.c index 9be893e..d794b61 100644 --- a/src/fcptrlist.c +++ b/src/fcptrlist.c @@ -31,6 +31,7 @@ typedef struct _FcPtrListEntry { struct _FcPtrList { FcDestroyFunc destroy_func; FcPtrListEntry *list; + FcPtrListEntry *last; }; typedef struct _FcPtrListIterPrivate { const FcPtrList *list; @@ -46,6 +47,7 @@ FcPtrListCreate (FcDestroyFunc func) if (ret) { ret->destroy_func = func; ret->list = NULL; + ret->last = NULL; } return ret; @@ -85,16 +87,10 @@ FcPtrListIterInitAtLast (FcPtrList *list, FcPtrListIter *iter) { FcPtrListIterPrivate *priv = (FcPtrListIterPrivate *)iter; - FcPtrListEntry **e, **p; - - e = &list->list; - p = e; - for (; *e; p = e, e = &(*e)->next) - ; priv->list = list; - priv->entry = *e; - priv->prev = *p; + priv->entry = NULL; + priv->prev = list->last; } FcBool @@ -154,6 +150,7 @@ FcPtrListIterAdd (FcPtrList *list, priv->entry->next = e; } else { e->next = NULL; + list->last = e; if (priv->prev) { priv->prev->next = e; priv->entry = priv->prev; @@ -187,6 +184,8 @@ FcPtrListIterRemove (FcPtrList *list, priv->prev->next = priv->entry->next; priv->entry = priv->entry->next; free (e); + if (!priv->entry) + list->last = priv->prev; return FcTrue; } commit 3878f8e502a3be6f239fce6df917d91897178544 Author: Akira TAGOH <akira@xxxxxxxxx> Date: Wed May 7 19:58:14 2025 +0900 Add a test case for FcPtrList diff --git a/src/fcptrlist.c b/src/fcptrlist.c index cac85d4..9be893e 100644 --- a/src/fcptrlist.c +++ b/src/fcptrlist.c @@ -60,7 +60,8 @@ FcPtrListDestroy (FcPtrList *list) FcPtrListIterInit (list, &iter); do { if (FcPtrListIterGetValue (list, &iter)) - list->destroy_func (FcPtrListIterGetValue (list, &iter)); + if (list->destroy_func) + list->destroy_func (FcPtrListIterGetValue (list, &iter)); FcPtrListIterRemove (list, &iter); } while (FcPtrListIterIsValid (list, &iter)); diff --git a/test/meson.build b/test/meson.build index 769d088..36cf4fe 100644 --- a/test/meson.build +++ b/test/meson.build @@ -21,6 +21,7 @@ tests = [ ['test-bz1744377.c'], ['test-issue180.c'], ['test-family-matching.c'], + ['test-ptrlist.c', {'include_directories': include_directories('../src'), 'dependencies': libintl_dep}], ] tests_not_parallel = [] @@ -53,12 +54,13 @@ foreach test_data : tests + tests_not_parallel opts = test_data.length() > 1 ? test_data[1] : {} extra_c_args = opts.get('c_args', []) extra_deps = opts.get('dependencies', []) + extra_incdir = opts.get('include_directories', []) test_name = fname.split('.')[0].underscorify() exe = executable(test_name, fname, c_args: c_args + extra_c_args, - include_directories: incbase, + include_directories: [incbase] + extra_incdir, link_with: link_with_libs, dependencies: extra_deps, ) diff --git a/test/test-ptrlist.c b/test/test-ptrlist.c new file mode 100644 index 0000000..f859923 --- /dev/null +++ b/test/test-ptrlist.c @@ -0,0 +1,33 @@ +/* Copyright (C) 2025 fontconfig Authors */ +/* SPDX-License-Identifier: HPND */ + +/* Internal API test case */ +#include "fcint.h" +#include <stdio.h> + +int +main (void) +{ + FcPtrList *p; + FcPtrListIter iter; + int i, n; + + p = FcPtrListCreate (NULL); + FcPtrListIterInitAtLast (p, &iter); + FcPtrListIterAdd (p, &iter, (intptr_t *)0); + FcPtrListIterAdd(p, &iter, (intptr_t *)1); + FcPtrListIterAdd(p, &iter, (intptr_t *)2); + FcPtrListIterAdd (p, &iter, (intptr_t *)3); + + FcPtrListIterInit (p, &iter); + for (i = 0; FcPtrListIterIsValid (p, &iter); FcPtrListIterNext (p, &iter), i++) { + n = (intptr_t)(void *)FcPtrListIterGetValue (p, &iter); + if (i != n) { + printf("mispatch the order: %d(%d)\n", i, n); + return 1; + } + } + FcPtrListDestroy (p); + + return 0; +}