refactoring of collections to make use of destructors in map implementations

Sun, 09 Apr 2023 19:03:58 +0200

author
Mike Becker <universe@uap-core.de>
date
Sun, 09 Apr 2023 19:03:58 +0200
changeset 677
b09aae58bba4
parent 676
d0680a23d850
child 678
78f943d76f50

refactoring of collections to make use of destructors in map implementations

src/CMakeLists.txt file | annotate | diff | comparison | revisions
src/array_list.c file | annotate | diff | comparison | revisions
src/cx/allocator.h file | annotate | diff | comparison | revisions
src/cx/array_list.h file | annotate | diff | comparison | revisions
src/cx/collection.h file | annotate | diff | comparison | revisions
src/cx/hash_map.h file | annotate | diff | comparison | revisions
src/cx/linked_list.h file | annotate | diff | comparison | revisions
src/cx/list.h file | annotate | diff | comparison | revisions
src/cx/map.h file | annotate | diff | comparison | revisions
src/cx/string.h file | annotate | diff | comparison | revisions
src/hash_map.c file | annotate | diff | comparison | revisions
src/linked_list.c file | annotate | diff | comparison | revisions
src/list.c file | annotate | diff | comparison | revisions
tests/test_list.cpp file | annotate | diff | comparison | revisions
tests/test_map.cpp file | annotate | diff | comparison | revisions
     1.1 --- a/src/CMakeLists.txt	Fri Apr 07 11:30:28 2023 +0200
     1.2 +++ b/src/CMakeLists.txt	Sun Apr 09 19:03:58 2023 +0200
     1.3 @@ -19,6 +19,7 @@
     1.4          cx/string.h
     1.5          cx/allocator.h
     1.6          cx/iterator.h
     1.7 +        cx/collection.h
     1.8          cx/list.h
     1.9          cx/array_list.h
    1.10          cx/linked_list.h
     2.1 --- a/src/array_list.c	Fri Apr 07 11:30:28 2023 +0200
     2.2 +++ b/src/array_list.c	Sun Apr 09 19:03:58 2023 +0200
     2.3 @@ -150,6 +150,7 @@
     2.4  typedef struct {
     2.5      struct cx_list_s base;
     2.6      void *data;
     2.7 +    size_t capacity;
     2.8      struct cx_array_reallocator_s reallocator;
     2.9  } cx_array_list;
    2.10  
    2.11 @@ -186,17 +187,17 @@
    2.12      // do we need to move some elements?
    2.13      if (index < list->size) {
    2.14          char const *first_to_move = (char const *) arl->data;
    2.15 -        first_to_move += index * list->itemsize;
    2.16 +        first_to_move += index * list->item_size;
    2.17          size_t elems_to_move = list->size - index;
    2.18          size_t start_of_moved = index + n;
    2.19  
    2.20          if (CX_ARRAY_COPY_SUCCESS != cx_array_copy(
    2.21                  &arl->data,
    2.22                  &list->size,
    2.23 -                &list->capacity,
    2.24 +                &arl->capacity,
    2.25                  start_of_moved,
    2.26                  first_to_move,
    2.27 -                list->itemsize,
    2.28 +                list->item_size,
    2.29                  elems_to_move,
    2.30                  &arl->reallocator
    2.31          )) {
    2.32 @@ -213,10 +214,10 @@
    2.33      if (CX_ARRAY_COPY_SUCCESS == cx_array_copy(
    2.34              &arl->data,
    2.35              &list->size,
    2.36 -            &list->capacity,
    2.37 +            &arl->capacity,
    2.38              index,
    2.39              array,
    2.40 -            list->itemsize,
    2.41 +            list->item_size,
    2.42              n,
    2.43              &arl->reallocator
    2.44      )) {
    2.45 @@ -249,7 +250,7 @@
    2.46          );
    2.47          if (result == 0 && prepend != 0) {
    2.48              iter->index++;
    2.49 -            iter->elem_handle = ((char *) iter->elem_handle) + list->itemsize;
    2.50 +            iter->elem_handle = ((char *) iter->elem_handle) + list->item_size;
    2.51          }
    2.52          return result;
    2.53      } else {
    2.54 @@ -271,11 +272,7 @@
    2.55      }
    2.56  
    2.57      // content destruction
    2.58 -    if (list->content_destructor_type != CX_DESTRUCTOR_NONE) {
    2.59 -        char *ptr = arl->data;
    2.60 -        ptr += index * list->itemsize;
    2.61 -        cx_list_invoke_destructor(list, ptr);
    2.62 -    }
    2.63 +    cx_invoke_destructor(list, ((char*)arl->data) + index * list->item_size);
    2.64  
    2.65      // short-circuit removal of last element
    2.66      if (index == list->size - 1) {
    2.67 @@ -287,10 +284,10 @@
    2.68      int result = cx_array_copy(
    2.69              &arl->data,
    2.70              &list->size,
    2.71 -            &list->capacity,
    2.72 +            &arl->capacity,
    2.73              index,
    2.74 -            ((char *) arl->data) + (index + 1) * list->itemsize,
    2.75 -            list->itemsize,
    2.76 +            ((char *) arl->data) + (index + 1) * list->item_size,
    2.77 +            list->item_size,
    2.78              list->size - index - 1,
    2.79              &arl->reallocator
    2.80      );
    2.81 @@ -307,26 +304,20 @@
    2.82      cx_array_list *arl = (cx_array_list *) list;
    2.83      char *ptr = arl->data;
    2.84  
    2.85 -    switch (list->content_destructor_type) {
    2.86 -        case CX_DESTRUCTOR_SIMPLE: {
    2.87 -            for (size_t i = 0; i < list->size; i++) {
    2.88 -                cx_list_invoke_simple_destructor(list, ptr);
    2.89 -                ptr += list->itemsize;
    2.90 -            }
    2.91 -            break;
    2.92 +    if (list->simple_destructor) {
    2.93 +        for (size_t i = 0; i < list->size; i++) {
    2.94 +            cx_invoke_simple_destructor(list, ptr);
    2.95 +            ptr += list->item_size;
    2.96          }
    2.97 -        case CX_DESTRUCTOR_ADVANCED: {
    2.98 -            for (size_t i = 0; i < list->size; i++) {
    2.99 -                cx_list_invoke_advanced_destructor(list, ptr);
   2.100 -                ptr += list->itemsize;
   2.101 -            }
   2.102 -            break;
   2.103 +    }
   2.104 +    if (list->advanced_destructor) {
   2.105 +        for (size_t i = 0; i < list->size; i++) {
   2.106 +            cx_invoke_advanced_destructor(list, ptr);
   2.107 +            ptr += list->item_size;
   2.108          }
   2.109 -        case CX_DESTRUCTOR_NONE:
   2.110 -            break; // nothing
   2.111      }
   2.112  
   2.113 -    memset(arl->data, 0, list->size * list->itemsize);
   2.114 +    memset(arl->data, 0, list->size * list->item_size);
   2.115      list->size = 0;
   2.116  }
   2.117  
   2.118 @@ -337,7 +328,7 @@
   2.119  ) {
   2.120      if (i >= list->size || j >= list->size) return 1;
   2.121      cx_array_list *arl = (cx_array_list *) list;
   2.122 -    cx_array_swap(arl->data, list->itemsize, i, j);
   2.123 +    cx_array_swap(arl->data, list->item_size, i, j);
   2.124      return 0;
   2.125  }
   2.126  
   2.127 @@ -348,7 +339,7 @@
   2.128      if (index < list->size) {
   2.129          cx_array_list const *arl = (cx_array_list const *) list;
   2.130          char *space = arl->data;
   2.131 -        return space + index * list->itemsize;
   2.132 +        return space + index * list->item_size;
   2.133      } else {
   2.134          return NULL;
   2.135      }
   2.136 @@ -365,7 +356,7 @@
   2.137          if (0 == list->cmpfunc(elem, cur)) {
   2.138              return i;
   2.139          }
   2.140 -        cur += list->itemsize;
   2.141 +        cur += list->item_size;
   2.142      }
   2.143  
   2.144      return list->size;
   2.145 @@ -375,7 +366,7 @@
   2.146      assert(list->cmpfunc != NULL);
   2.147      qsort(((cx_array_list *) list)->data,
   2.148            list->size,
   2.149 -          list->itemsize,
   2.150 +          list->item_size,
   2.151            list->cmpfunc
   2.152      );
   2.153  }
   2.154 @@ -393,8 +384,8 @@
   2.155              if (d != 0) {
   2.156                  return d;
   2.157              }
   2.158 -            left += list->itemsize;
   2.159 -            right += other->itemsize;
   2.160 +            left += list->item_size;
   2.161 +            right += other->item_size;
   2.162          }
   2.163          return 0;
   2.164      } else {
   2.165 @@ -407,7 +398,7 @@
   2.166      void *data = ((cx_array_list const *) list)->data;
   2.167      size_t half = list->size / 2;
   2.168      for (size_t i = 0; i < half; i++) {
   2.169 -        cx_array_swap(data, list->itemsize, i, list->size - 1 - i);
   2.170 +        cx_array_swap(data, list->item_size, i, list->size - 1 - i);
   2.171      }
   2.172  }
   2.173  
   2.174 @@ -433,7 +424,7 @@
   2.175          iter->index++;
   2.176          iter->elem_handle =
   2.177                  ((char *) iter->elem_handle)
   2.178 -                + ((struct cx_list_s const *) iter->src_handle)->itemsize;
   2.179 +                + ((struct cx_list_s const *) iter->src_handle)->item_size;
   2.180      }
   2.181  }
   2.182  
   2.183 @@ -448,7 +439,7 @@
   2.184      iter->index--;
   2.185      if (iter->index < list->base.size) {
   2.186          iter->elem_handle = ((char *) list->data)
   2.187 -                            + iter->index * list->base.itemsize;
   2.188 +                            + iter->index * list->base.item_size;
   2.189      }
   2.190  }
   2.191  
   2.192 @@ -500,7 +491,7 @@
   2.193  
   2.194  CxList *cxArrayListCreate(
   2.195          CxAllocator const *allocator,
   2.196 -        CxListComparator comparator,
   2.197 +        cx_compare_func comparator,
   2.198          size_t item_size,
   2.199          size_t initial_capacity
   2.200  ) {
   2.201 @@ -514,10 +505,10 @@
   2.202      list->base.cl = &cx_array_list_class;
   2.203      list->base.allocator = allocator;
   2.204      list->base.cmpfunc = comparator;
   2.205 -    list->base.capacity = initial_capacity;
   2.206 +    list->capacity = initial_capacity;
   2.207  
   2.208      if (item_size > 0) {
   2.209 -        list->base.itemsize = item_size;
   2.210 +        list->base.item_size = item_size;
   2.211      } else {
   2.212          item_size = sizeof(void*);
   2.213          cxListStorePointers((CxList *) list);
     3.1 --- a/src/cx/allocator.h	Fri Apr 07 11:30:28 2023 +0200
     3.2 +++ b/src/cx/allocator.h	Sun Apr 09 19:03:58 2023 +0200
     3.3 @@ -133,41 +133,6 @@
     3.4  ) __attribute__((__nonnull__(2)));
     3.5  
     3.6  /**
     3.7 - * Structure holding an advanced destructor function and the desired payload.
     3.8 - * Invocations of func should use data as first argument.
     3.9 - */
    3.10 -typedef struct {
    3.11 -    /**
    3.12 -     * A pointer to the data that SHALL be used to invoke func.
    3.13 -     */
    3.14 -    void *data;
    3.15 -    /**
    3.16 -     * A pointer to the function to invoke.
    3.17 -     */
    3.18 -    cx_destructor_func2 func;
    3.19 -} cx_advanced_destructor;
    3.20 -
    3.21 -/**
    3.22 - * Specifies the type of destructor to use.
    3.23 - */
    3.24 -enum cx_destructor_type {
    3.25 -    /**
    3.26 -     * Do not use a destructor function.
    3.27 -     */
    3.28 -    CX_DESTRUCTOR_NONE,
    3.29 -    /**
    3.30 -     * Use a simple destructor.
    3.31 -     * @see cx_destructor_func
    3.32 -     */
    3.33 -    CX_DESTRUCTOR_SIMPLE,
    3.34 -    /**
    3.35 -     * Use an advanced destructor.
    3.36 -     * @see cx_advanced_destructor
    3.37 -     */
    3.38 -    CX_DESTRUCTOR_ADVANCED
    3.39 -};
    3.40 -
    3.41 -/**
    3.42   * Allocate \p n bytes of memory.
    3.43   *
    3.44   * @param allocator the allocator
     4.1 --- a/src/cx/array_list.h	Fri Apr 07 11:30:28 2023 +0200
     4.2 +++ b/src/cx/array_list.h	Sun Apr 09 19:03:58 2023 +0200
     4.3 @@ -165,7 +165,7 @@
     4.4   */
     4.5  CxList *cxArrayListCreate(
     4.6          CxAllocator const *allocator,
     4.7 -        CxListComparator comparator,
     4.8 +        cx_compare_func comparator,
     4.9          size_t item_size,
    4.10          size_t initial_capacity
    4.11  );
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/src/cx/collection.h	Sun Apr 09 19:03:58 2023 +0200
     5.3 @@ -0,0 +1,139 @@
     5.4 +/*
     5.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
     5.6 + *
     5.7 + * Copyright 2023 Mike Becker, Olaf Wintermann All rights reserved.
     5.8 + *
     5.9 + * Redistribution and use in source and binary forms, with or without
    5.10 + * modification, are permitted provided that the following conditions are met:
    5.11 + *
    5.12 + *   1. Redistributions of source code must retain the above copyright
    5.13 + *      notice, this list of conditions and the following disclaimer.
    5.14 + *
    5.15 + *   2. Redistributions in binary form must reproduce the above copyright
    5.16 + *      notice, this list of conditions and the following disclaimer in the
    5.17 + *      documentation and/or other materials provided with the distribution.
    5.18 + *
    5.19 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
    5.20 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
    5.21 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
    5.22 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
    5.23 + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
    5.24 + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
    5.25 + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
    5.26 + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
    5.27 + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
    5.28 + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
    5.29 + * POSSIBILITY OF SUCH DAMAGE.
    5.30 + */
    5.31 +/**
    5.32 + * \file collection.h
    5.33 + * \brief Common definitions for various collection implementations.
    5.34 + * \author Mike Becker
    5.35 + * \author Olaf Wintermann
    5.36 + * \version 3.0
    5.37 + * \copyright 2-Clause BSD License
    5.38 + */
    5.39 +
    5.40 +#ifndef UCX_COLLECTION_H
    5.41 +#define UCX_COLLECTION_H
    5.42 +
    5.43 +#include "common.h"
    5.44 +#include "allocator.h"
    5.45 +#include "iterator.h"
    5.46 +
    5.47 +#ifdef __cplusplus
    5.48 +extern "C" {
    5.49 +#endif
    5.50 +
    5.51 +/**
    5.52 + * Special constant used for creating collections that are storing pointers.
    5.53 + */
    5.54 +#define CX_STORE_POINTERS 0
    5.55 +
    5.56 +/**
    5.57 + * A comparator function comparing two collection elements.
    5.58 + */
    5.59 +typedef int(*cx_compare_func)(
    5.60 +        void const *left,
    5.61 +        void const *right
    5.62 +);
    5.63 +
    5.64 +/**
    5.65 + * Use this macro to declare common members for a collection structure.
    5.66 + */
    5.67 +#define CX_COLLECTION_MEMBERS \
    5.68 +    /** \
    5.69 +     * The allocator to use. \
    5.70 +     */ \
    5.71 +    CxAllocator const *allocator; \
    5.72 +    /** \
    5.73 +     * The comparator function for the elements. \
    5.74 +     */ \
    5.75 +    cx_compare_func cmpfunc; \
    5.76 +    /** \
    5.77 +     * The size of each element. \
    5.78 +     */ \
    5.79 +    size_t item_size; \
    5.80 +    /** \
    5.81 +     * The number of currently stored elements. \
    5.82 +     */ \
    5.83 +    size_t size; \
    5.84 +    /** \
    5.85 +     * An optional simple destructor for the collection's elements. \
    5.86 +     * \
    5.87 +     * @attention Read the documentation of the particular collection implementation \
    5.88 +     * whether this destructor shall only destroy the contents or also free the memory. \
    5.89 +     */ \
    5.90 +    cx_destructor_func simple_destructor; \
    5.91 +    /** \
    5.92 +     * An optional advanced destructor for the collection's elements. \
    5.93 +     * \
    5.94 +     * @attention Read the documentation of the particular collection implementation \
    5.95 +     * whether this destructor shall only destroy the contents or also free the memory. \
    5.96 +     */ \
    5.97 +    cx_destructor_func2 advanced_destructor; \
    5.98 +    /** \
    5.99 +     * The pointer to additional data that is passed to the advanced destructor. \
   5.100 +     */ \
   5.101 +    void *destructor_data; \
   5.102 +    /** \
   5.103 +     * Indicates if this instance of a collection is supposed to store pointers \
   5.104 +     * instead of copies of the actual objects. \
   5.105 +     */ \
   5.106 +    bool store_pointer;
   5.107 +
   5.108 +/**
   5.109 + * Invokes the simple destructor function for a specific element.
   5.110 + *
   5.111 + * Usually only used by collection implementations. There should be no need
   5.112 + * to invoke this macro manually.
   5.113 + *
   5.114 + * @param c the collection
   5.115 + * @param e the element
   5.116 + */
   5.117 +#define cx_invoke_simple_destructor(c, e) \
   5.118 +    (c)->simple_destructor((c)->store_pointer ? (*((void **) e)) : e)
   5.119 +
   5.120 +/**
   5.121 + * Invokes the advanced destructor function for a specific element.
   5.122 + *
   5.123 + * Usually only used by collection implementations. There should be no need
   5.124 + * to invoke this macro manually.
   5.125 + *
   5.126 + * @param c the collection
   5.127 + * @param e the element
   5.128 + */
   5.129 +#define cx_invoke_advanced_destructor(c, e) \
   5.130 +    (c)->advanced_destructor((c)->destructor_data, \
   5.131 +    (c)->store_pointer ? (*((void **) e)) : e)
   5.132 +
   5.133 +
   5.134 +#define cx_invoke_destructor(c, e) \
   5.135 +    if ((c)->simple_destructor) cx_invoke_simple_destructor(c,e); \
   5.136 +    if ((c)->advanced_destructor) cx_invoke_advanced_destructor(c,e)
   5.137 +
   5.138 +#ifdef __cplusplus
   5.139 +} // extern "C"
   5.140 +#endif
   5.141 +
   5.142 +#endif // UCX_COLLECTION_H
     6.1 --- a/src/cx/hash_map.h	Fri Apr 07 11:30:28 2023 +0200
     6.2 +++ b/src/cx/hash_map.h	Sun Apr 09 19:03:58 2023 +0200
     6.3 @@ -70,7 +70,7 @@
     6.4   *
     6.5   * If \p buckets is zero, an implementation defined default will be used.
     6.6   *
     6.7 - * If \p itemsize is CX_STORE_POINTERS, the created map will be created as if
     6.8 + * If \p item_size is CX_STORE_POINTERS, the created map will be created as if
     6.9   * cxMapStorePointers() was called immediately after creation.
    6.10   *
    6.11   * @note Iterators provided by this hash map implementation provide the remove operation.
     7.1 --- a/src/cx/linked_list.h	Fri Apr 07 11:30:28 2023 +0200
     7.2 +++ b/src/cx/linked_list.h	Sun Apr 09 19:03:58 2023 +0200
     7.3 @@ -66,7 +66,7 @@
     7.4   */
     7.5  CxList *cxLinkedListCreate(
     7.6          CxAllocator const *allocator,
     7.7 -        CxListComparator comparator,
     7.8 +        cx_compare_func comparator,
     7.9          size_t item_size
    7.10  );
    7.11  
    7.12 @@ -124,7 +124,7 @@
    7.13          void const *start,
    7.14          ptrdiff_t loc_advance,
    7.15          ptrdiff_t loc_data,
    7.16 -        CxListComparator cmp_func,
    7.17 +        cx_compare_func cmp_func,
    7.18          void const *elem
    7.19  ) __attribute__((__nonnull__));
    7.20  
    7.21 @@ -368,7 +368,7 @@
    7.22          ptrdiff_t loc_prev,
    7.23          ptrdiff_t loc_next,
    7.24          ptrdiff_t loc_data,
    7.25 -        CxListComparator cmp_func
    7.26 +        cx_compare_func cmp_func
    7.27  ) __attribute__((__nonnull__(1, 6)));
    7.28  
    7.29  
    7.30 @@ -390,7 +390,7 @@
    7.31          void const *begin_right,
    7.32          ptrdiff_t loc_advance,
    7.33          ptrdiff_t loc_data,
    7.34 -        CxListComparator cmp_func
    7.35 +        cx_compare_func cmp_func
    7.36  ) __attribute__((__nonnull__(5)));
    7.37  
    7.38  /**
     8.1 --- a/src/cx/list.h	Fri Apr 07 11:30:28 2023 +0200
     8.2 +++ b/src/cx/list.h	Sun Apr 09 19:03:58 2023 +0200
     8.3 @@ -37,29 +37,12 @@
     8.4  #ifndef UCX_LIST_H
     8.5  #define UCX_LIST_H
     8.6  
     8.7 -#include "common.h"
     8.8 -#include "allocator.h"
     8.9 -#include "iterator.h"
    8.10 +#include "collection.h"
    8.11  
    8.12  #ifdef __cplusplus
    8.13  extern "C" {
    8.14  #endif
    8.15  
    8.16 -#ifndef CX_STORE_POINTERS
    8.17 -/**
    8.18 - * Special constant used for creating collections that are storing pointers.
    8.19 - */
    8.20 -#define CX_STORE_POINTERS 0
    8.21 -#endif
    8.22 -
    8.23 -/**
    8.24 - * A comparator function comparing two list elements.
    8.25 - */
    8.26 -typedef int(*CxListComparator)(
    8.27 -        void const *left,
    8.28 -        void const *right
    8.29 -);
    8.30 -
    8.31  /**
    8.32   * List class type.
    8.33   */
    8.34 @@ -69,6 +52,7 @@
    8.35   * Structure for holding the base data of a list.
    8.36   */
    8.37  struct cx_list_s {
    8.38 +    CX_COLLECTION_MEMBERS
    8.39      /**
    8.40       * The list class definition.
    8.41       */
    8.42 @@ -77,50 +61,6 @@
    8.43       * The actual implementation in case the list class is delegating.
    8.44       */
    8.45      cx_list_class const *climpl;
    8.46 -    /**
    8.47 -     * The allocator to use.
    8.48 -     */
    8.49 -    CxAllocator const *allocator;
    8.50 -    /**
    8.51 -     * The comparator function for the elements.
    8.52 -     */
    8.53 -    CxListComparator cmpfunc;
    8.54 -    /**
    8.55 -     * The size of each element (payload only).
    8.56 -     */
    8.57 -    size_t itemsize;
    8.58 -    /**
    8.59 -     * The size of the list (number of currently stored elements).
    8.60 -     */
    8.61 -    size_t size;
    8.62 -    /**
    8.63 -     * The capacity of the list (maximum number of elements).
    8.64 -     */
    8.65 -    size_t capacity;
    8.66 -    union {
    8.67 -        /**
    8.68 -         * An optional simple destructor for the list contents that admits the free() interface.
    8.69 -         *
    8.70 -         * @remark Set content_destructor_type to #CX_DESTRUCTOR_SIMPLE.
    8.71 -         *
    8.72 -         * @attention Read the documentation of the particular list implementation
    8.73 -         * whether this destructor shall only destroy the contents or also free the memory.
    8.74 -         */
    8.75 -        cx_destructor_func simple_destructor;
    8.76 -        /**
    8.77 -         * An optional advanced destructor for the list contents providing additional data.
    8.78 -         *
    8.79 -         * @remark Set content_destructor_type to #CX_DESTRUCTOR_ADVANCED.
    8.80 -         *
    8.81 -         * @attention Read the documentation of the particular list implementation
    8.82 -         * whether this destructor shall only destroy the contents or also free the memory.
    8.83 -         */
    8.84 -        cx_advanced_destructor advanced_destructor;
    8.85 -    };
    8.86 -    /**
    8.87 -     * The type of destructor to use.
    8.88 -     */
    8.89 -    enum cx_destructor_type content_destructor_type;
    8.90  };
    8.91  
    8.92  /**
    8.93 @@ -234,51 +174,6 @@
    8.94  typedef struct cx_list_s CxList;
    8.95  
    8.96  /**
    8.97 - * Invokes the configured destructor function for a specific element.
    8.98 - *
    8.99 - * Usually only used by list implementations. There should be no need
   8.100 - * to invoke this function manually.
   8.101 - *
   8.102 - * @param list the list
   8.103 - * @param elem the element
   8.104 - */
   8.105 -__attribute__((__nonnull__))
   8.106 -void cx_list_invoke_destructor(
   8.107 -        struct cx_list_s const *list,
   8.108 -        void *elem
   8.109 -);
   8.110 -
   8.111 -/**
   8.112 - * Invokes the simple destructor function for a specific element.
   8.113 - *
   8.114 - * Usually only used by list implementations. There should be no need
   8.115 - * to invoke this function manually.
   8.116 - *
   8.117 - * @param list the list
   8.118 - * @param elem the element
   8.119 - */
   8.120 -__attribute__((__nonnull__))
   8.121 -void cx_list_invoke_simple_destructor(
   8.122 -        struct cx_list_s const *list,
   8.123 -        void *elem
   8.124 -);
   8.125 -
   8.126 -/**
   8.127 - * Invokes the advanced destructor function for a specific element.
   8.128 - *
   8.129 - * Usually only used by list implementations. There should be no need
   8.130 - * to invoke this function manually.
   8.131 - *
   8.132 - * @param list the list
   8.133 - * @param elem the element
   8.134 - */
   8.135 -__attribute__((__nonnull__))
   8.136 -void cx_list_invoke_advanced_destructor(
   8.137 -        struct cx_list_s const *list,
   8.138 -        void *elem
   8.139 -);
   8.140 -
   8.141 -/**
   8.142   * Advises the list to store copies of the objects (default mode of operation).
   8.143   *
   8.144   * Retrieving objects from this list will yield pointers to the copies stored
   8.145 @@ -309,11 +204,24 @@
   8.146   * Returns true, if this list is storing pointers instead of the actual data.
   8.147   *
   8.148   * @param list
   8.149 - * @return
   8.150 + * @return true, if this list is storing pointers
   8.151   * @see cxListStorePointers()
   8.152   */
   8.153  __attribute__((__nonnull__))
   8.154 -bool cxListIsStoringPointers(CxList const *list);
   8.155 +static inline bool cxListIsStoringPointers(CxList const *list) {
   8.156 +    return list->store_pointer;
   8.157 +}
   8.158 +
   8.159 +/**
   8.160 + * Returns the number of elements currently stored in the list.
   8.161 + *
   8.162 + * @param list the list
   8.163 + * @return the number of currently stored elements
   8.164 + */
   8.165 +__attribute__((__nonnull__))
   8.166 +static inline size_t cxListSize(CxList const *list) {
   8.167 +    return list->size;
   8.168 +}
   8.169  
   8.170  /**
   8.171   * Adds an item to the end of the list.
     9.1 --- a/src/cx/map.h	Fri Apr 07 11:30:28 2023 +0200
     9.2 +++ b/src/cx/map.h	Sun Apr 09 19:03:58 2023 +0200
     9.3 @@ -37,22 +37,13 @@
     9.4  #ifndef UCX_MAP_H
     9.5  #define UCX_MAP_H
     9.6  
     9.7 -#include "common.h"
     9.8 -#include "allocator.h"
     9.9 -#include "iterator.h"
    9.10 +#include "collection.h"
    9.11  #include "hash_key.h"
    9.12  
    9.13  #ifdef    __cplusplus
    9.14  extern "C" {
    9.15  #endif
    9.16  
    9.17 -#ifndef CX_STORE_POINTERS
    9.18 -/**
    9.19 - * Special constant used for creating collections that are storing pointers.
    9.20 - */
    9.21 -#define CX_STORE_POINTERS 0
    9.22 -#endif
    9.23 -
    9.24  /** Type for the UCX map. */
    9.25  typedef struct cx_map_s CxMap;
    9.26  
    9.27 @@ -73,7 +64,7 @@
    9.28      /**
    9.29       * The size of an element.
    9.30       */
    9.31 -    size_t itemsize;
    9.32 +    size_t item_size;
    9.33      /**
    9.34       * True, if this map shall store pointers instead
    9.35       * of copies of objects.
    9.36 @@ -205,7 +196,7 @@
    9.37  __attribute__((__nonnull__))
    9.38  static inline void cxMapStorePointers(CxMap *map) {
    9.39      map->store_pointers = true;
    9.40 -    map->itemsize = sizeof(void *);
    9.41 +    map->item_size = sizeof(void *);
    9.42  }
    9.43  
    9.44  
    10.1 --- a/src/cx/string.h	Fri Apr 07 11:30:28 2023 +0200
    10.2 +++ b/src/cx/string.h	Sun Apr 09 19:03:58 2023 +0200
    10.3 @@ -660,7 +660,7 @@
    10.4  /**
    10.5   * Compares two strings.
    10.6   *
    10.7 - * This function has a compatible signature for the use as a CxListComparator.
    10.8 + * This function has a compatible signature for the use as a cx_compare_func.
    10.9   *
   10.10   * @param s1 the first string
   10.11   * @param s2 the second string
   10.12 @@ -676,7 +676,7 @@
   10.13  /**
   10.14   * Compares two strings ignoring case.
   10.15   *
   10.16 - * This function has a compatible signature for the use as a CxListComparator.
   10.17 + * This function has a compatible signature for the use as a cx_compare_func.
   10.18   *
   10.19   * @param s1 the first string
   10.20   * @param s2 the second string
    11.1 --- a/src/hash_map.c	Fri Apr 07 11:30:28 2023 +0200
    11.2 +++ b/src/hash_map.c	Sun Apr 09 19:03:58 2023 +0200
    11.3 @@ -103,13 +103,13 @@
    11.4          if (map->store_pointers) {
    11.5              memcpy(elm->data, &value, sizeof(void *));
    11.6          } else {
    11.7 -            memcpy(elm->data, value, map->itemsize);
    11.8 +            memcpy(elm->data, value, map->item_size);
    11.9          }
   11.10      } else {
   11.11          // allocate new element
   11.12          struct cx_hash_map_element_s *e = cxMalloc(
   11.13                  allocator,
   11.14 -                sizeof(struct cx_hash_map_element_s) + map->itemsize
   11.15 +                sizeof(struct cx_hash_map_element_s) + map->item_size
   11.16          );
   11.17          if (e == NULL) {
   11.18              return -1;
   11.19 @@ -119,7 +119,7 @@
   11.20          if (map->store_pointers) {
   11.21              memcpy(e->data, &value, sizeof(void *));
   11.22          } else {
   11.23 -            memcpy(e->data, value, map->itemsize);
   11.24 +            memcpy(e->data, value, map->item_size);
   11.25          }
   11.26  
   11.27          // copy the key
   11.28 @@ -434,10 +434,10 @@
   11.29  
   11.30      if (itemsize > 0) {
   11.31          map->base.store_pointers = false;
   11.32 -        map->base.itemsize = itemsize;
   11.33 +        map->base.item_size = itemsize;
   11.34      } else {
   11.35          map->base.store_pointers = true;
   11.36 -        map->base.itemsize = sizeof(void *);
   11.37 +        map->base.item_size = sizeof(void *);
   11.38      }
   11.39  
   11.40      return (CxMap *) map;
    12.1 --- a/src/linked_list.c	Fri Apr 07 11:30:28 2023 +0200
    12.2 +++ b/src/linked_list.c	Sun Apr 09 19:03:58 2023 +0200
    12.3 @@ -60,7 +60,7 @@
    12.4          void const *start,
    12.5          ptrdiff_t loc_advance,
    12.6          ptrdiff_t loc_data,
    12.7 -        CxListComparator cmp_func,
    12.8 +        cx_compare_func cmp_func,
    12.9          void const *elem
   12.10  ) {
   12.11      assert(start != NULL);
   12.12 @@ -291,7 +291,7 @@
   12.13          void *ls,
   12.14          void *le,
   12.15          void *re,
   12.16 -        CxListComparator cmp_func
   12.17 +        cx_compare_func cmp_func
   12.18  ) {
   12.19      void *sbo[CX_LINKED_LIST_SORT_SBO_SIZE];
   12.20      void **sorted = length >= CX_LINKED_LIST_SORT_SBO_SIZE ?
   12.21 @@ -343,7 +343,7 @@
   12.22          ptrdiff_t loc_prev,
   12.23          ptrdiff_t loc_next,
   12.24          ptrdiff_t loc_data,
   12.25 -        CxListComparator cmp_func
   12.26 +        cx_compare_func cmp_func
   12.27  ) {
   12.28      assert(begin != NULL);
   12.29      assert(loc_next >= 0);
   12.30 @@ -403,7 +403,7 @@
   12.31          void const *begin_right,
   12.32          ptrdiff_t loc_advance,
   12.33          ptrdiff_t loc_data,
   12.34 -        CxListComparator cmp_func
   12.35 +        cx_compare_func cmp_func
   12.36  ) {
   12.37      void const *left = begin_left, *right = begin_right;
   12.38  
   12.39 @@ -494,14 +494,14 @@
   12.40  
   12.41      // create the new new_node
   12.42      cx_linked_list_node *new_node = cxMalloc(list->allocator,
   12.43 -                                             sizeof(cx_linked_list_node) + list->itemsize);
   12.44 +                                             sizeof(cx_linked_list_node) + list->item_size);
   12.45  
   12.46      // sortir if failed
   12.47      if (new_node == NULL) return 1;
   12.48  
   12.49      // initialize new new_node
   12.50      new_node->prev = new_node->next = NULL;
   12.51 -    memcpy(new_node->payload, elem, list->itemsize);
   12.52 +    memcpy(new_node->payload, elem, list->item_size);
   12.53  
   12.54      // insert
   12.55      cx_linked_list *ll = (cx_linked_list *) list;
   12.56 @@ -542,7 +542,7 @@
   12.57      // we can add the remaining nodes and immedately advance to the inserted node
   12.58      char const *source = array;
   12.59      for (size_t i = 1; i < n; i++) {
   12.60 -        source += list->itemsize;
   12.61 +        source += list->item_size;
   12.62          if (0 != cx_ll_insert_at(list, node, source)) {
   12.63              return i;
   12.64          }
   12.65 @@ -570,9 +570,7 @@
   12.66      if (node == NULL) return 1;
   12.67  
   12.68      // element destruction
   12.69 -    if (list->content_destructor_type != CX_DESTRUCTOR_NONE) {
   12.70 -        cx_list_invoke_destructor(list, node->payload);
   12.71 -    }
   12.72 +    cx_invoke_destructor(list, node->payload);
   12.73  
   12.74      // remove
   12.75      cx_linked_list_remove((void **) &ll->begin, (void **) &ll->end,
   12.76 @@ -592,38 +590,12 @@
   12.77  
   12.78      cx_linked_list *ll = (cx_linked_list *) list;
   12.79      cx_linked_list_node *node = ll->begin;
   12.80 -
   12.81 -    // looks super redundant, but avoids repeatedly checking
   12.82 -    // the destructor type for each element
   12.83 -    switch (list->content_destructor_type) {
   12.84 -        case CX_DESTRUCTOR_SIMPLE: {
   12.85 -            while (node != NULL) {
   12.86 -                cx_list_invoke_simple_destructor(list, node->payload);
   12.87 -                cx_linked_list_node *next = node->next;
   12.88 -                cxFree(list->allocator, node);
   12.89 -                node = next;
   12.90 -            }
   12.91 -            break;
   12.92 -        }
   12.93 -        case CX_DESTRUCTOR_ADVANCED: {
   12.94 -            while (node != NULL) {
   12.95 -                cx_list_invoke_advanced_destructor(list, node->payload);
   12.96 -                cx_linked_list_node *next = node->next;
   12.97 -                cxFree(list->allocator, node);
   12.98 -                node = next;
   12.99 -            }
  12.100 -            break;
  12.101 -        }
  12.102 -        case CX_DESTRUCTOR_NONE: {
  12.103 -            while (node != NULL) {
  12.104 -                cx_linked_list_node *next = node->next;
  12.105 -                cxFree(list->allocator, node);
  12.106 -                node = next;
  12.107 -            }
  12.108 -            break;
  12.109 -        }
  12.110 +    while (node != NULL) {
  12.111 +        cx_invoke_destructor(list, node->payload);
  12.112 +        cx_linked_list_node *next = node->next;
  12.113 +        cxFree(list->allocator, node);
  12.114 +        node = next;
  12.115      }
  12.116 -
  12.117      ll->begin = ll->end = NULL;
  12.118      list->size = 0;
  12.119  }
  12.120 @@ -708,7 +680,7 @@
  12.121          }
  12.122      }
  12.123  
  12.124 -    if (list->itemsize > CX_LINKED_LIST_SWAP_SBO_SIZE || CX_DISABLE_LINKED_LIST_SWAP_SBO) {
  12.125 +    if (list->item_size > CX_LINKED_LIST_SWAP_SBO_SIZE || CX_DISABLE_LINKED_LIST_SWAP_SBO) {
  12.126          cx_linked_list_node *prev = nleft->prev;
  12.127          cx_linked_list_node *next = nright->next;
  12.128          cx_linked_list_node *midstart = nleft->next;
  12.129 @@ -740,9 +712,9 @@
  12.130      } else {
  12.131          // swap payloads to avoid relinking
  12.132          char buf[CX_LINKED_LIST_SWAP_SBO_SIZE];
  12.133 -        memcpy(buf, nleft->payload, list->itemsize);
  12.134 -        memcpy(nleft->payload, nright->payload, list->itemsize);
  12.135 -        memcpy(nright->payload, buf, list->itemsize);
  12.136 +        memcpy(buf, nleft->payload, list->item_size);
  12.137 +        memcpy(nleft->payload, nright->payload, list->item_size);
  12.138 +        memcpy(nright->payload, buf, list->item_size);
  12.139      }
  12.140  
  12.141      return 0;
  12.142 @@ -803,9 +775,7 @@
  12.143          cx_linked_list *ll = iter->src_handle;
  12.144          cx_linked_list_node *node = iter->elem_handle;
  12.145          iter->elem_handle = node->next;
  12.146 -        if (list->content_destructor_type != CX_DESTRUCTOR_NONE) {
  12.147 -            cx_list_invoke_destructor(list, node->payload);
  12.148 -        }
  12.149 +        cx_invoke_destructor(list, node->payload);
  12.150          cx_linked_list_remove((void **) &ll->begin, (void **) &ll->end,
  12.151                                CX_LL_LOC_PREV, CX_LL_LOC_NEXT, node);
  12.152          list->size--;
  12.153 @@ -828,9 +798,7 @@
  12.154          cx_linked_list_node *node = iter->elem_handle;
  12.155          iter->elem_handle = node->prev;
  12.156          iter->index--;
  12.157 -        if (list->content_destructor_type != CX_DESTRUCTOR_NONE) {
  12.158 -            cx_list_invoke_destructor(list, node->payload);
  12.159 -        }
  12.160 +        cx_invoke_destructor(list, node->payload);
  12.161          cx_linked_list_remove((void **) &ll->begin, (void **) &ll->end,
  12.162                                CX_LL_LOC_PREV, CX_LL_LOC_NEXT, node);
  12.163          list->size--;
  12.164 @@ -927,7 +895,7 @@
  12.165  
  12.166  CxList *cxLinkedListCreate(
  12.167          CxAllocator const *allocator,
  12.168 -        CxListComparator comparator,
  12.169 +        cx_compare_func comparator,
  12.170          size_t item_size
  12.171  ) {
  12.172      if (allocator == NULL) {
  12.173 @@ -940,10 +908,9 @@
  12.174      list->base.cl = &cx_linked_list_class;
  12.175      list->base.allocator = allocator;
  12.176      list->base.cmpfunc = comparator;
  12.177 -    list->base.capacity = SIZE_MAX;
  12.178  
  12.179      if (item_size > 0) {
  12.180 -        list->base.itemsize = item_size;
  12.181 +        list->base.item_size = item_size;
  12.182      } else {
  12.183          cxListStorePointers((CxList *) list);
  12.184      }
    13.1 --- a/src/list.c	Fri Apr 07 11:30:28 2023 +0200
    13.2 +++ b/src/list.c	Sun Apr 09 19:03:58 2023 +0200
    13.3 @@ -32,7 +32,7 @@
    13.4  
    13.5  // <editor-fold desc="Store Pointers Functionality">
    13.6  
    13.7 -static _Thread_local CxListComparator cx_pl_cmpfunc_impl;
    13.8 +static _Thread_local cx_compare_func cx_pl_cmpfunc_impl;
    13.9  
   13.10  static int cx_pl_cmpfunc(
   13.11          void const *l,
   13.12 @@ -179,6 +179,7 @@
   13.13  };
   13.14  
   13.15  void cxListStoreObjects(CxList *list) {
   13.16 +    list->store_pointer = false;
   13.17      if (list->climpl != NULL) {
   13.18          list->cl = list->climpl;
   13.19          list->climpl = NULL;
   13.20 @@ -186,75 +187,28 @@
   13.21  }
   13.22  
   13.23  void cxListStorePointers(CxList *list) {
   13.24 -    list->itemsize = sizeof(void *);
   13.25 +    list->item_size = sizeof(void *);
   13.26 +    list->store_pointer = true;
   13.27      list->climpl = list->cl;
   13.28      list->cl = &cx_pointer_list_class;
   13.29  }
   13.30  
   13.31 -bool cxListIsStoringPointers(CxList const *list) {
   13.32 -    return list->climpl != NULL;
   13.33 -}
   13.34 -
   13.35  // </editor-fold>
   13.36  
   13.37 -void cx_list_invoke_destructor(
   13.38 -        CxList const *list,
   13.39 -        void *elem
   13.40 -) {
   13.41 -    switch (list->content_destructor_type) {
   13.42 -        case CX_DESTRUCTOR_SIMPLE: {
   13.43 -            cx_list_invoke_simple_destructor(list, elem);
   13.44 -            break;
   13.45 +void cxListDestroy(CxList *list) {
   13.46 +    if (list->simple_destructor) {
   13.47 +        CxIterator iter = cxListIterator(list);
   13.48 +        cx_foreach(void*, elem, iter) {
   13.49 +            // already correctly resolved pointer - immediately invoke dtor
   13.50 +            list->simple_destructor(elem);
   13.51          }
   13.52 -        case CX_DESTRUCTOR_ADVANCED: {
   13.53 -            cx_list_invoke_advanced_destructor(list, elem);
   13.54 -            break;
   13.55 +    }
   13.56 +    if (list->advanced_destructor) {
   13.57 +        CxIterator iter = cxListIterator(list);
   13.58 +        cx_foreach(void*, elem, iter) {
   13.59 +            // already correctly resolved pointer - immediately invoke dtor
   13.60 +            list->advanced_destructor(list->destructor_data, elem);
   13.61          }
   13.62 -        case CX_DESTRUCTOR_NONE:
   13.63 -            break; // nothing
   13.64 -    }
   13.65 -}
   13.66 -
   13.67 -void cx_list_invoke_simple_destructor(
   13.68 -        CxList const *list,
   13.69 -        void *elem
   13.70 -) {
   13.71 -    if (cxListIsStoringPointers(list)) {
   13.72 -        elem = *((void **) elem);
   13.73 -    }
   13.74 -    list->simple_destructor(elem);
   13.75 -}
   13.76 -
   13.77 -void cx_list_invoke_advanced_destructor(
   13.78 -        CxList const *list,
   13.79 -        void *elem
   13.80 -) {
   13.81 -    if (cxListIsStoringPointers(list)) {
   13.82 -        elem = *((void **) elem);
   13.83 -    }
   13.84 -    list->advanced_destructor.func(list->advanced_destructor.data, elem);
   13.85 -}
   13.86 -
   13.87 -void cxListDestroy(CxList *list) {
   13.88 -    switch (list->content_destructor_type) {
   13.89 -        case CX_DESTRUCTOR_SIMPLE: {
   13.90 -            CxIterator iter = cxListIterator(list);
   13.91 -            cx_foreach(void*, elem, iter) {
   13.92 -                // already correctly resolved pointer - immediately invoke dtor
   13.93 -                list->simple_destructor(elem);
   13.94 -            }
   13.95 -            break;
   13.96 -        }
   13.97 -        case CX_DESTRUCTOR_ADVANCED: {
   13.98 -            CxIterator iter = cxListIterator(list);
   13.99 -            cx_foreach(void*, elem, iter) {
  13.100 -                // already correctly resolved pointer - immediately invoke dtor
  13.101 -                list->advanced_destructor.func(list->advanced_destructor.data, elem);
  13.102 -            }
  13.103 -            break;
  13.104 -        }
  13.105 -        case CX_DESTRUCTOR_NONE:
  13.106 -            break; // nothing
  13.107      }
  13.108  
  13.109      list->cl->destructor(list);
    14.1 --- a/tests/test_list.cpp	Fri Apr 07 11:30:28 2023 +0200
    14.2 +++ b/tests/test_list.cpp	Sun Apr 09 19:03:58 2023 +0200
    14.3 @@ -592,8 +592,7 @@
    14.4      ) {
    14.5          auto len = testdata_len;
    14.6          cx_for_n (i, len) EXPECT_EQ(cxListAdd(list, &testdata.data[i]), 0);
    14.7 -        EXPECT_EQ(list->size, len);
    14.8 -        EXPECT_GE(list->capacity, list->size);
    14.9 +        EXPECT_EQ(cxListSize(list), len);
   14.10          cx_for_n (i, len) EXPECT_EQ(*(int *) cxListAt(list, i), testdata.data[i]);
   14.11          cx_for_n (i, len) ++testdata.data[i];
   14.12          if (as_pointer) {
   14.13 @@ -607,17 +606,16 @@
   14.14          int a = 5, b = 47, c = 13, d = 42;
   14.15  
   14.16          EXPECT_NE(cxListInsert(list, 1, &a), 0);
   14.17 -        EXPECT_EQ(list->size, 0);
   14.18 +        EXPECT_EQ(cxListSize(list), 0);
   14.19          EXPECT_EQ(cxListInsert(list, 0, &a), 0);
   14.20 -        EXPECT_EQ(list->size, 1);
   14.21 +        EXPECT_EQ(cxListSize(list), 1);
   14.22          EXPECT_EQ(cxListInsert(list, 0, &b), 0);
   14.23 -        EXPECT_EQ(list->size, 2);
   14.24 +        EXPECT_EQ(cxListSize(list), 2);
   14.25          EXPECT_EQ(cxListInsert(list, 1, &c), 0);
   14.26 -        EXPECT_EQ(list->size, 3);
   14.27 +        EXPECT_EQ(cxListSize(list), 3);
   14.28          EXPECT_EQ(cxListInsert(list, 3, &d), 0);
   14.29  
   14.30 -        ASSERT_EQ(list->size, 4);
   14.31 -        EXPECT_GE(list->capacity, list->size);
   14.32 +        ASSERT_EQ(cxListSize(list), 4);
   14.33  
   14.34          EXPECT_EQ(*(int *) cxListAt(list, 0), 47);
   14.35          EXPECT_EQ(*(int *) cxListAt(list, 1), 13);
   14.36 @@ -672,8 +670,7 @@
   14.37      void verifyRemove(CxList *list) const {
   14.38          EXPECT_EQ(cxListRemove(list, 2), 0);
   14.39          EXPECT_EQ(cxListRemove(list, 4), 0);
   14.40 -        EXPECT_EQ(list->size, testdata_len - 2);
   14.41 -        EXPECT_GE(list->capacity, list->size);
   14.42 +        EXPECT_EQ(cxListSize(list), testdata_len - 2);
   14.43          EXPECT_EQ(*(int *) cxListAt(list, 0), testdata.data[0]);
   14.44          EXPECT_EQ(*(int *) cxListAt(list, 1), testdata.data[1]);
   14.45          EXPECT_EQ(*(int *) cxListAt(list, 2), testdata.data[3]);
   14.46 @@ -681,8 +678,7 @@
   14.47          EXPECT_EQ(*(int *) cxListAt(list, 4), testdata.data[6]);
   14.48  
   14.49          EXPECT_EQ(cxListRemove(list, 0), 0);
   14.50 -        EXPECT_EQ(list->size, testdata_len - 3);
   14.51 -        EXPECT_GE(list->capacity, list->size);
   14.52 +        EXPECT_EQ(cxListSize(list), testdata_len - 3);
   14.53          EXPECT_EQ(*(int *) cxListAt(list, 0), testdata.data[1]);
   14.54          EXPECT_EQ(*(int *) cxListAt(list, 1), testdata.data[3]);
   14.55  
   14.56 @@ -691,7 +687,7 @@
   14.57  
   14.58      static void verifyClear(CxList *list) {
   14.59          cxListClear(list);
   14.60 -        EXPECT_EQ(0, list->size);
   14.61 +        EXPECT_EQ(0, cxListSize(list));
   14.62      }
   14.63  
   14.64      static unsigned destr_test_ctr;
   14.65 @@ -717,33 +713,33 @@
   14.66          cxListRemove(list, 15);
   14.67          EXPECT_EQ(1, destr_test_ctr);
   14.68          EXPECT_EQ(testdata.data[15], destr_last_value + off);
   14.69 -        EXPECT_EQ(testdata_len - destr_test_ctr, list->size);
   14.70 +        EXPECT_EQ(testdata_len - destr_test_ctr, cxListSize(list));
   14.71          cxListRemove(list, 47);
   14.72          EXPECT_EQ(2, destr_test_ctr);
   14.73          EXPECT_EQ(testdata.data[48], destr_last_value + off);
   14.74 -        EXPECT_EQ(testdata_len - destr_test_ctr, list->size);
   14.75 +        EXPECT_EQ(testdata_len - destr_test_ctr, cxListSize(list));
   14.76  
   14.77          auto iter = cxListMutIteratorAt(list, 7);
   14.78          cxIteratorNext(iter);
   14.79          EXPECT_EQ(2, destr_test_ctr);
   14.80          EXPECT_EQ(testdata.data[48], destr_last_value + off);
   14.81 -        EXPECT_EQ(testdata_len - destr_test_ctr, list->size);
   14.82 +        EXPECT_EQ(testdata_len - destr_test_ctr, cxListSize(list));
   14.83          cxIteratorFlagRemoval(iter);
   14.84          cxIteratorNext(iter);
   14.85          EXPECT_EQ(3, destr_test_ctr);
   14.86          EXPECT_EQ(testdata.data[8], destr_last_value + off);
   14.87 -        EXPECT_EQ(testdata_len - destr_test_ctr, list->size);
   14.88 +        EXPECT_EQ(testdata_len - destr_test_ctr, cxListSize(list));
   14.89  
   14.90          iter = cxListMutBackwardsIteratorAt(list, 5);
   14.91          cxIteratorNext(iter);
   14.92          EXPECT_EQ(3, destr_test_ctr);
   14.93          EXPECT_EQ(testdata.data[8], destr_last_value + off);
   14.94 -        EXPECT_EQ(testdata_len - destr_test_ctr, list->size);
   14.95 +        EXPECT_EQ(testdata_len - destr_test_ctr, cxListSize(list));
   14.96          cxIteratorFlagRemoval(iter);
   14.97          cxIteratorNext(iter);
   14.98          EXPECT_EQ(4, destr_test_ctr);
   14.99          EXPECT_EQ(testdata.data[4], destr_last_value + off);
  14.100 -        EXPECT_EQ(testdata_len - destr_test_ctr, list->size);
  14.101 +        EXPECT_EQ(testdata_len - destr_test_ctr, cxListSize(list));
  14.102  
  14.103          cxListClear(list);
  14.104          EXPECT_EQ(testdata_len, destr_test_ctr);
  14.105 @@ -754,20 +750,18 @@
  14.106  
  14.107      void verifySimpleDestructor(CxList *list) {
  14.108          destr_test_ctr = 0;
  14.109 -        list->content_destructor_type = CX_DESTRUCTOR_SIMPLE;
  14.110          list->simple_destructor = simple_destr_test_fun;
  14.111          verifyAnyDestructor(list);
  14.112      }
  14.113  
  14.114      void verifyAdvancedDestructor(CxList *list) {
  14.115          destr_test_ctr = 0;
  14.116 -        list->content_destructor_type = CX_DESTRUCTOR_ADVANCED;
  14.117 -        list->advanced_destructor.func = advanced_destr_test_fun;
  14.118 +        list->advanced_destructor = advanced_destr_test_fun;
  14.119          verifyAnyDestructor(list);
  14.120      }
  14.121  
  14.122      static void verifySwap(CxList *list) {
  14.123 -        ASSERT_EQ(list->size, 0);
  14.124 +        ASSERT_EQ(cxListSize(list), 0);
  14.125  
  14.126          int original[16] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
  14.127          int swapped[16] = {8, 4, 14, 3, 1, 5, 9, 12, 0, 6, 11, 10, 7, 15, 2, 13};
  14.128 @@ -816,11 +810,11 @@
  14.129  
  14.130      void verifyAt(CxList *list) const {
  14.131          auto len = testdata_len;
  14.132 -        EXPECT_EQ(list->size, len);
  14.133 +        EXPECT_EQ(cxListSize(list), len);
  14.134          cx_for_n (i, len) {
  14.135              EXPECT_EQ(*(int *) cxListAt(list, i), testdata.data[i]);
  14.136          }
  14.137 -        EXPECT_EQ(cxListAt(list, list->size), nullptr);
  14.138 +        EXPECT_EQ(cxListAt(list, cxListSize(list)), nullptr);
  14.139      }
  14.140  
  14.141      void verifyFind(CxList *list) const {
  14.142 @@ -838,7 +832,7 @@
  14.143          }
  14.144  
  14.145          int notinlist = -1;
  14.146 -        EXPECT_EQ(list->size, cxListFind(list, &notinlist));
  14.147 +        EXPECT_EQ(cxListSize(list), cxListFind(list, &notinlist));
  14.148      }
  14.149  
  14.150      void verifySort(CxList *list) const {
  14.151 @@ -856,7 +850,7 @@
  14.152              EXPECT_EQ(*x, testdata.data[iter.index]);
  14.153              i++;
  14.154          }
  14.155 -        ASSERT_EQ(i, list->size);
  14.156 +        ASSERT_EQ(i, cxListSize(list));
  14.157          iter = cxListBackwardsIterator(list);
  14.158          cx_foreach(int*, x, iter) {
  14.159              ASSERT_EQ(i - 1, iter.index);
  14.160 @@ -887,7 +881,7 @@
  14.161              j++;
  14.162          }
  14.163          ASSERT_EQ(i, 0);
  14.164 -        ASSERT_EQ(list->size, len / 2);
  14.165 +        ASSERT_EQ(cxListSize(list), len / 2);
  14.166          cx_for_n(j, len / 2) ASSERT_EQ(*(int *) cxListAt(list, j), testdata.data[j * 2]);
  14.167      }
  14.168  
  14.169 @@ -912,11 +906,11 @@
  14.170          EXPECT_TRUE(cxIteratorValid(iter));
  14.171          EXPECT_EQ(iter.index, 1);
  14.172          EXPECT_EQ(*(int *) cxIteratorCurrent(iter), 0);
  14.173 -        iter = cxListMutIteratorAt(list, list->size);
  14.174 +        iter = cxListMutIteratorAt(list, cxListSize(list));
  14.175          cxListInsertBefore(&iter, &newdata[3]);
  14.176          EXPECT_FALSE(cxIteratorValid(iter));
  14.177          EXPECT_EQ(iter.index, 9);
  14.178 -        iter = cxListMutIteratorAt(list, list->size);
  14.179 +        iter = cxListMutIteratorAt(list, cxListSize(list));
  14.180          cxListInsertAfter(&iter, &newdata[4]);
  14.181          EXPECT_FALSE(cxIteratorValid(iter));
  14.182          EXPECT_EQ(iter.index, 10);
  14.183 @@ -939,16 +933,16 @@
  14.184          EXPECT_EQ(cxListCompare(left, right), 0);
  14.185          int x = 42;
  14.186          cxListAdd(left, &x);
  14.187 -        ASSERT_GT(left->size, right->size);
  14.188 +        ASSERT_GT(cxListSize(left), cxListSize(right));
  14.189          EXPECT_GT(cxListCompare(left, right), 0);
  14.190          EXPECT_LT(cxListCompare(right, left), 0);
  14.191          cxListAdd(right, &x);
  14.192 -        ASSERT_EQ(left->size, right->size);
  14.193 +        ASSERT_EQ(cxListSize(left), cxListSize(right));
  14.194          EXPECT_EQ(cxListCompare(left, right), 0);
  14.195          int a = 5, b = 10;
  14.196          cxListInsert(left, 15, &a);
  14.197          cxListInsert(right, 15, &b);
  14.198 -        ASSERT_EQ(left->size, right->size);
  14.199 +        ASSERT_EQ(cxListSize(left), cxListSize(right));
  14.200          EXPECT_LT(cxListCompare(left, right), 0);
  14.201          EXPECT_GT(cxListCompare(right, left), 0);
  14.202          *(int *) cxListAt(left, 15) = 10;
  14.203 @@ -972,7 +966,7 @@
  14.204      auto list = autofree(cxLinkedListCreate(&testingAllocator, cx_cmp_int, 47));
  14.205      EXPECT_FALSE(cxListIsStoringPointers(list));
  14.206      cxListStorePointers(list);
  14.207 -    EXPECT_EQ(list->itemsize, sizeof(void *));
  14.208 +    EXPECT_EQ(list->item_size, sizeof(void *));
  14.209      EXPECT_NE(list->cl, nullptr);
  14.210      EXPECT_NE(list->climpl, nullptr);
  14.211      EXPECT_TRUE(cxListIsStoringPointers(list));
  14.212 @@ -985,10 +979,11 @@
  14.213  TEST_F(LinkedList, cxLinkedListCreate) {
  14.214      CxList *list = autofree(cxLinkedListCreate(&testingAllocator, cx_cmp_int, sizeof(int)));
  14.215      ASSERT_NE(list, nullptr);
  14.216 -    EXPECT_EQ(list->itemsize, sizeof(int));
  14.217 -    EXPECT_EQ(list->capacity, (size_t) -1);
  14.218 -    EXPECT_EQ(list->content_destructor_type, CX_DESTRUCTOR_NONE);
  14.219 -    EXPECT_EQ(list->size, 0);
  14.220 +    EXPECT_EQ(list->item_size, sizeof(int));
  14.221 +    EXPECT_EQ(list->simple_destructor, nullptr);
  14.222 +    EXPECT_EQ(list->advanced_destructor, nullptr);
  14.223 +    EXPECT_EQ(list->destructor_data, nullptr);
  14.224 +    EXPECT_EQ(cxListSize(list), 0);
  14.225      EXPECT_EQ(list->allocator, &testingAllocator);
  14.226      EXPECT_EQ(list->cmpfunc, cx_cmp_int);
  14.227      EXPECT_FALSE(cxListIsStoringPointers(list));
  14.228 @@ -997,30 +992,37 @@
  14.229  TEST_F(LinkedList, cxLinkedListCreateSimple) {
  14.230      CxList *list = autofree(cxLinkedListCreateSimple(sizeof(int)));
  14.231      ASSERT_NE(list, nullptr);
  14.232 -    EXPECT_EQ(list->itemsize, sizeof(int));
  14.233 -    EXPECT_EQ(list->capacity, (size_t) -1);
  14.234 +    EXPECT_EQ(list->item_size, sizeof(int));
  14.235      EXPECT_EQ(list->cmpfunc, nullptr);
  14.236      EXPECT_EQ(list->allocator, cxDefaultAllocator);
  14.237 +    EXPECT_EQ(list->simple_destructor, nullptr);
  14.238 +    EXPECT_EQ(list->advanced_destructor, nullptr);
  14.239 +    EXPECT_EQ(list->destructor_data, nullptr);
  14.240 +    EXPECT_EQ(cxListSize(list), 0);
  14.241      EXPECT_FALSE(cxListIsStoringPointers(list));
  14.242  }
  14.243  
  14.244  TEST_F(LinkedList, cxLinkedListCreateSimpleForPointers) {
  14.245      CxList *list = autofree(cxLinkedListCreateSimple(CX_STORE_POINTERS));
  14.246      ASSERT_NE(list, nullptr);
  14.247 -    EXPECT_EQ(list->itemsize, sizeof(void *));
  14.248 -    EXPECT_EQ(list->capacity, (size_t) -1);
  14.249 +    EXPECT_EQ(list->item_size, sizeof(void *));
  14.250      EXPECT_EQ(list->cmpfunc, nullptr);
  14.251      EXPECT_EQ(list->allocator, cxDefaultAllocator);
  14.252 +    EXPECT_EQ(list->simple_destructor, nullptr);
  14.253 +    EXPECT_EQ(list->advanced_destructor, nullptr);
  14.254 +    EXPECT_EQ(list->destructor_data, nullptr);
  14.255 +    EXPECT_EQ(cxListSize(list), 0);
  14.256      EXPECT_TRUE(cxListIsStoringPointers(list));
  14.257  }
  14.258  
  14.259  TEST_F(ArrayList, cxArrayListCreate) {
  14.260      CxList *list = autofree(cxArrayListCreate(&testingAllocator, cx_cmp_int, sizeof(int), 8));
  14.261      ASSERT_NE(list, nullptr);
  14.262 -    EXPECT_EQ(list->itemsize, sizeof(int));
  14.263 -    EXPECT_EQ(list->capacity, 8);
  14.264 -    EXPECT_EQ(list->content_destructor_type, CX_DESTRUCTOR_NONE);
  14.265 -    EXPECT_EQ(list->size, 0);
  14.266 +    EXPECT_EQ(list->item_size, sizeof(int));
  14.267 +    EXPECT_EQ(list->simple_destructor, nullptr);
  14.268 +    EXPECT_EQ(list->advanced_destructor, nullptr);
  14.269 +    EXPECT_EQ(list->destructor_data, nullptr);
  14.270 +    EXPECT_EQ(cxListSize(list), 0);
  14.271      EXPECT_EQ(list->allocator, &testingAllocator);
  14.272      EXPECT_EQ(list->cmpfunc, cx_cmp_int);
  14.273      EXPECT_FALSE(cxListIsStoringPointers(list));
  14.274 @@ -1031,8 +1033,11 @@
  14.275      ASSERT_NE(list, nullptr);
  14.276      EXPECT_EQ(list->cmpfunc, nullptr);
  14.277      EXPECT_EQ(list->allocator, cxDefaultAllocator);
  14.278 -    EXPECT_EQ(list->itemsize, sizeof(int));
  14.279 -    EXPECT_EQ(list->capacity, 8);
  14.280 +    EXPECT_EQ(list->item_size, sizeof(int));
  14.281 +    EXPECT_EQ(list->simple_destructor, nullptr);
  14.282 +    EXPECT_EQ(list->advanced_destructor, nullptr);
  14.283 +    EXPECT_EQ(list->destructor_data, nullptr);
  14.284 +    EXPECT_EQ(cxListSize(list), 0);
  14.285      EXPECT_FALSE(cxListIsStoringPointers(list));
  14.286  }
  14.287  
  14.288 @@ -1041,8 +1046,7 @@
  14.289      ASSERT_NE(list, nullptr);
  14.290      EXPECT_EQ(list->cmpfunc, nullptr);
  14.291      EXPECT_EQ(list->allocator, cxDefaultAllocator);
  14.292 -    EXPECT_EQ(list->itemsize, sizeof(void *));
  14.293 -    EXPECT_EQ(list->capacity, 8);
  14.294 +    EXPECT_EQ(list->item_size, sizeof(void *));
  14.295      EXPECT_TRUE(cxListIsStoringPointers(list));
  14.296  }
  14.297  
  14.298 @@ -1313,7 +1317,6 @@
  14.299  TEST_F(PointerLinkedList, DestroySimpleDestructor) {
  14.300      int item = 0;
  14.301      auto list = cxLinkedListCreate(cxDefaultAllocator, cx_cmp_int, CX_STORE_POINTERS);
  14.302 -    list->content_destructor_type = CX_DESTRUCTOR_SIMPLE;
  14.303      list->simple_destructor = [](void *elem) { *(int *) elem = 42; };
  14.304      cxListAdd(list, &item);
  14.305      cxListDestroy(list);
  14.306 @@ -1323,9 +1326,8 @@
  14.307  TEST_F(PointerLinkedList, DestroyAdvancedDestructor) {
  14.308      void *item = cxMalloc(&testingAllocator, sizeof(int));
  14.309      auto list = cxLinkedListCreate(cxDefaultAllocator, cx_cmp_int, CX_STORE_POINTERS);
  14.310 -    list->content_destructor_type = CX_DESTRUCTOR_ADVANCED;
  14.311 -    list->advanced_destructor.data = &testingAllocator;
  14.312 -    list->advanced_destructor.func = (cx_destructor_func2) cxFree;
  14.313 +    list->destructor_data = &testingAllocator;
  14.314 +    list->advanced_destructor = (cx_destructor_func2) cxFree;
  14.315      cxListAdd(list, item);
  14.316      ASSERT_FALSE(testingAllocator.verify());
  14.317      cxListDestroy(list);
    15.1 --- a/tests/test_map.cpp	Fri Apr 07 11:30:28 2023 +0200
    15.2 +++ b/tests/test_map.cpp	Sun Apr 09 19:03:58 2023 +0200
    15.3 @@ -121,13 +121,13 @@
    15.4      cx_for_n(i, hmap->bucket_count) {
    15.5          EXPECT_EQ(hmap->buckets[i], nullptr);
    15.6      }
    15.7 -    EXPECT_EQ(map->itemsize, 1);
    15.8 +    EXPECT_EQ(map->item_size, 1);
    15.9      EXPECT_EQ(map->size, 0);
   15.10      EXPECT_EQ(map->allocator, &allocator);
   15.11      EXPECT_FALSE(map->store_pointers);
   15.12      cxMapStorePointers(map);
   15.13      EXPECT_TRUE(map->store_pointers);
   15.14 -    EXPECT_EQ(map->itemsize, sizeof(void *));
   15.15 +    EXPECT_EQ(map->item_size, sizeof(void *));
   15.16      cxMapStoreObjects(map);
   15.17      EXPECT_FALSE(map->store_pointers);
   15.18  
   15.19 @@ -146,7 +146,7 @@
   15.20      EXPECT_EQ(map->size, 0);
   15.21      EXPECT_EQ(map->allocator, &allocator);
   15.22      EXPECT_TRUE(map->store_pointers);
   15.23 -    EXPECT_EQ(map->itemsize, sizeof(void *));
   15.24 +    EXPECT_EQ(map->item_size, sizeof(void *));
   15.25  
   15.26      cxMapDestroy(map);
   15.27      EXPECT_TRUE(allocator.verify());

mercurial