add new pointer list wrapper - resolves #234

Thu, 26 Jan 2023 20:59:36 +0100

author
Mike Becker <universe@uap-core.de>
date
Thu, 26 Jan 2023 20:59:36 +0100
changeset 641
d402fead3386
parent 640
55cc3b373c5e
child 642
98c90759f69e

add new pointer list wrapper - resolves #234

since we need a thread local variable, this drops C99 support

CMakeLists.txt file | annotate | diff | comparison | revisions
src/array_list.c file | annotate | diff | comparison | revisions
src/cx/iterator.h file | annotate | diff | comparison | revisions
src/cx/list.h file | annotate | diff | comparison | revisions
src/linked_list.c file | annotate | diff | comparison | revisions
src/list.c file | annotate | diff | comparison | revisions
test/test_list.cpp file | annotate | diff | comparison | revisions
     1.1 --- a/CMakeLists.txt	Wed Jan 25 19:19:29 2023 +0100
     1.2 +++ b/CMakeLists.txt	Thu Jan 26 20:59:36 2023 +0100
     1.3 @@ -3,7 +3,7 @@
     1.4  
     1.5  # Configuration
     1.6  set(CMAKE_C_STANDARD 11)
     1.7 -set(CMAKE_C_STANDARD_REQUIRED  99)
     1.8 +set(CMAKE_C_STANDARD_REQUIRED 11)
     1.9  
    1.10  option(GCC_MORE_WARNINGS "Enable -Wall -Wextra -pedantic when using gcc." OFF)
    1.11  if (GCC_MORE_WARNINGS AND CMAKE_COMPILER_IS_GNUCC)
     2.1 --- a/src/array_list.c	Wed Jan 25 19:19:29 2023 +0100
     2.2 +++ b/src/array_list.c	Thu Jan 26 20:59:36 2023 +0100
     2.3 @@ -224,6 +224,14 @@
     2.4      }
     2.5  }
     2.6  
     2.7 +static int cx_arl_insert_element(
     2.8 +        struct cx_list_s *list,
     2.9 +        size_t index,
    2.10 +        void const *element
    2.11 +) {
    2.12 +    return 1 != cx_arl_insert_array(list, index, element, 1);
    2.13 +}
    2.14 +
    2.15  static int cx_arl_insert_iter(
    2.16          struct cx_mut_iterator_s *iter,
    2.17          void const *elem,
    2.18 @@ -231,11 +239,10 @@
    2.19  ) {
    2.20      struct cx_list_s *list = iter->src_handle;
    2.21      if (iter->index < list->size) {
    2.22 -        int result = 1 != cx_arl_insert_array(
    2.23 +        int result = cx_arl_insert_element(
    2.24                  list,
    2.25                  iter->index + 1 - prepend,
    2.26 -                elem,
    2.27 -                1
    2.28 +                elem
    2.29          );
    2.30          if (result == 0 && prepend != 0) {
    2.31              iter->index++;
    2.32 @@ -243,7 +250,7 @@
    2.33          }
    2.34          return result;
    2.35      } else {
    2.36 -        int result = 1 != cx_arl_insert_array(list, list->size, elem, 1);
    2.37 +        int result = cx_arl_insert_element(list, list->size, elem);
    2.38          iter->index = list->size;
    2.39          return result;
    2.40      }
    2.41 @@ -407,6 +414,7 @@
    2.42  
    2.43  static cx_list_class cx_array_list_class = {
    2.44          cx_arl_destructor,
    2.45 +        cx_arl_insert_element,
    2.46          cx_arl_insert_array,
    2.47          cx_arl_insert_iter,
    2.48          cx_arl_remove,
     3.1 --- a/src/cx/iterator.h	Wed Jan 25 19:19:29 2023 +0100
     3.2 +++ b/src/cx/iterator.h	Thu Jan 26 20:59:36 2023 +0100
     3.3 @@ -56,6 +56,12 @@
     3.4      void *(*current)(void const *);
     3.5  
     3.6      /**
     3.7 +     * Original implementation in case the function needs to be wrapped.
     3.8 +     */
     3.9 +    __attribute__ ((__nonnull__))
    3.10 +    void *(*current_impl)(void const *);
    3.11 +
    3.12 +    /**
    3.13       * Advances the iterator.
    3.14       */
    3.15      __attribute__ ((__nonnull__))
     4.1 --- a/src/cx/list.h	Wed Jan 25 19:19:29 2023 +0100
     4.2 +++ b/src/cx/list.h	Thu Jan 26 20:59:36 2023 +0100
     4.3 @@ -65,7 +65,11 @@
     4.4      /**
     4.5       * The list class definition.
     4.6       */
     4.7 -    cx_list_class *cl;
     4.8 +    cx_list_class const *cl;
     4.9 +    /**
    4.10 +     * The actual implementation in case the list class is delegating.
    4.11 +     */
    4.12 +    cx_list_class const *climpl;
    4.13      /**
    4.14       * The allocator to use.
    4.15       */
    4.16 @@ -122,6 +126,16 @@
    4.17      void (*destructor)(struct cx_list_s *list);
    4.18  
    4.19      /**
    4.20 +     * Member function for inserting a single elements.
    4.21 +     * Implementors SHOULD see to performant implementations for corner cases.
    4.22 +     */
    4.23 +    int (*insert_element)(
    4.24 +            struct cx_list_s *list,
    4.25 +            size_t index,
    4.26 +            void const *data
    4.27 +    );
    4.28 +
    4.29 +    /**
    4.30       * Member function for inserting multiple elements.
    4.31       * Implementors SHOULD see to performant implementations for corner cases.
    4.32       */
    4.33 @@ -198,6 +212,43 @@
    4.34  typedef struct cx_list_s CxList;
    4.35  
    4.36  /**
    4.37 + * Advises the list to store copies of the objects (default mode of operation).
    4.38 + *
    4.39 + * Retrieving objects from this list will yield pointers to the copies stored
    4.40 + * within this list.
    4.41 + *
    4.42 + * @param list the list
    4.43 + * @see cxListStorePointers()
    4.44 + */
    4.45 +__attribute__((__nonnull__))
    4.46 +void cxListStoreObjects(CxList *list);
    4.47 +
    4.48 +/**
    4.49 + * Advises the list to only store pointers to the objects.
    4.50 + *
    4.51 + * Retrieving objects from this list will yield the original pointers stored.
    4.52 + *
    4.53 + * @note This function forcibly sets the element size to the size of a pointer.
    4.54 + * Invoking this function on a non-empty list that already stores copies of
    4.55 + * objects is undefined.
    4.56 + *
    4.57 + * @param list the list
    4.58 + * @see cxListStoreObjects()
    4.59 + */
    4.60 +__attribute__((__nonnull__))
    4.61 +void cxListStorePointers(CxList *list);
    4.62 +
    4.63 +/**
    4.64 + * Returns true, if this list is storing pointers instead of the actual data.
    4.65 + *
    4.66 + * @param list
    4.67 + * @return
    4.68 + * @see cxListStorePointers()
    4.69 + */
    4.70 +__attribute__((__nonnull__))
    4.71 +bool cxListIsStoringPointers(CxList *list);
    4.72 +
    4.73 +/**
    4.74   * Adds an item to the end of the list.
    4.75   *
    4.76   * @param list the list
    4.77 @@ -210,7 +261,7 @@
    4.78          CxList *list,
    4.79          void const *elem
    4.80  ) {
    4.81 -    return list->cl->insert_array(list, list->size, elem, 1) != 1;
    4.82 +    return list->cl->insert_element(list, list->size, elem);
    4.83  }
    4.84  
    4.85  /**
    4.86 @@ -221,6 +272,9 @@
    4.87   * If there is not enough memory to add all elements, the returned value is
    4.88   * less than \p n.
    4.89   *
    4.90 + * If this list is storing pointers instead of objects \p array is expected to
    4.91 + * be an array of pointers.
    4.92 + *
    4.93   * @param list the list
    4.94   * @param array a pointer to the elements to add
    4.95   * @param n the number of elements to add
    4.96 @@ -254,7 +308,7 @@
    4.97          size_t index,
    4.98          void const *elem
    4.99  ) {
   4.100 -    return list->cl->insert_array(list, index, elem, 1) != 1;
   4.101 +    return list->cl->insert_element(list, index, elem);
   4.102  }
   4.103  
   4.104  /**
   4.105 @@ -267,6 +321,9 @@
   4.106   * If there is not enough memory to add all elements, the returned value is
   4.107   * less than \p n.
   4.108   *
   4.109 + * If this list is storing pointers instead of objects \p array is expected to
   4.110 + * be an array of pointers.
   4.111 + *
   4.112   * @param list the list
   4.113   * @param index the index where to add the elements
   4.114   * @param array a pointer to the elements to add
     5.1 --- a/src/linked_list.c	Wed Jan 25 19:19:29 2023 +0100
     5.2 +++ b/src/linked_list.c	Thu Jan 26 20:59:36 2023 +0100
     5.3 @@ -546,6 +546,14 @@
     5.4      return n;
     5.5  }
     5.6  
     5.7 +static int cx_ll_insert_element(
     5.8 +        struct cx_list_s *list,
     5.9 +        size_t index,
    5.10 +        void const *element
    5.11 +) {
    5.12 +    return 1 != cx_ll_insert_array(list, index, element, 1);
    5.13 +}
    5.14 +
    5.15  static int cx_ll_remove(
    5.16          struct cx_list_s *list,
    5.17          size_t index
    5.18 @@ -682,7 +690,7 @@
    5.19          iter->index += prepend * (0 == result);
    5.20          return result;
    5.21      } else {
    5.22 -        int result = cx_ll_insert_array(list, list->size, elem, 1) != 1;
    5.23 +        int result = cx_ll_insert_element(list, list->size, elem);
    5.24          iter->index = list->size;
    5.25          return result;
    5.26      }
    5.27 @@ -702,6 +710,7 @@
    5.28  
    5.29  static cx_list_class cx_linked_list_class = {
    5.30          cx_ll_destructor,
    5.31 +        cx_ll_insert_element,
    5.32          cx_ll_insert_array,
    5.33          cx_ll_insert_iter,
    5.34          cx_ll_remove,
     6.1 --- a/src/list.c	Wed Jan 25 19:19:29 2023 +0100
     6.2 +++ b/src/list.c	Thu Jan 26 20:59:36 2023 +0100
     6.3 @@ -30,6 +30,158 @@
     6.4  
     6.5  #include <string.h>
     6.6  
     6.7 +// <editor-fold desc="Store Pointers Functionality">
     6.8 +
     6.9 +static _Thread_local CxListComparator cx_pl_cmpfunc_impl;
    6.10 +
    6.11 +static int cx_pl_cmpfunc(
    6.12 +        void const *l,
    6.13 +        void const *r
    6.14 +) {
    6.15 +    void *const *lptr = l;
    6.16 +    void *const *rptr = r;
    6.17 +    void const *left = lptr == NULL ? NULL : *lptr;
    6.18 +    void const *right = rptr == NULL ? NULL : *rptr;
    6.19 +    return cx_pl_cmpfunc_impl(left, right);
    6.20 +}
    6.21 +
    6.22 +static void cx_pl_hack_cmpfunc(struct cx_list_s const *list) {
    6.23 +    // cast away const - this is the hacky thing
    6.24 +    struct cx_list_s *l = (struct cx_list_s *) list;
    6.25 +    cx_pl_cmpfunc_impl = l->cmpfunc;
    6.26 +    l->cmpfunc = cx_pl_cmpfunc;
    6.27 +}
    6.28 +
    6.29 +static void cx_pl_unhack_cmpfunc(struct cx_list_s const *list) {
    6.30 +    // cast away const - this is the hacky thing
    6.31 +    struct cx_list_s *l = (struct cx_list_s *) list;
    6.32 +    l->cmpfunc = cx_pl_cmpfunc_impl;
    6.33 +}
    6.34 +
    6.35 +static void cx_pl_destructor(struct cx_list_s *list) {
    6.36 +    list->climpl->destructor(list);
    6.37 +}
    6.38 +
    6.39 +static int cx_pl_insert_element(
    6.40 +        struct cx_list_s *list,
    6.41 +        size_t index,
    6.42 +        void const *element
    6.43 +) {
    6.44 +    return list->climpl->insert_element(list, index, &element);
    6.45 +}
    6.46 +
    6.47 +static size_t cx_pl_insert_array(
    6.48 +        struct cx_list_s *list,
    6.49 +        size_t index,
    6.50 +        void const *array,
    6.51 +        size_t n
    6.52 +) {
    6.53 +    return list->climpl->insert_array(list, index, array, n);
    6.54 +}
    6.55 +
    6.56 +static int cx_pl_insert_iter(
    6.57 +        struct cx_mut_iterator_s *iter,
    6.58 +        void const *elem,
    6.59 +        int prepend
    6.60 +) {
    6.61 +    struct cx_list_s *list = iter->src_handle;
    6.62 +    return list->climpl->insert_iter(iter, &elem, prepend);
    6.63 +}
    6.64 +
    6.65 +static int cx_pl_remove(
    6.66 +        struct cx_list_s *list,
    6.67 +        size_t index
    6.68 +) {
    6.69 +    return list->climpl->remove(list, index);
    6.70 +}
    6.71 +
    6.72 +static void *cx_pl_at(
    6.73 +        struct cx_list_s const *list,
    6.74 +        size_t index
    6.75 +) {
    6.76 +    void **ptr = list->climpl->at(list, index);
    6.77 +    return ptr == NULL ? NULL : *ptr;
    6.78 +}
    6.79 +
    6.80 +static size_t cx_pl_find(
    6.81 +        struct cx_list_s const *list,
    6.82 +        void const *elem
    6.83 +) {
    6.84 +    cx_pl_hack_cmpfunc(list);
    6.85 +    size_t ret = list->climpl->find(list, &elem);
    6.86 +    cx_pl_unhack_cmpfunc(list);
    6.87 +    return ret;
    6.88 +}
    6.89 +
    6.90 +static void cx_pl_sort(struct cx_list_s *list) {
    6.91 +    cx_pl_hack_cmpfunc(list);
    6.92 +    list->climpl->sort(list);
    6.93 +    cx_pl_unhack_cmpfunc(list);
    6.94 +}
    6.95 +
    6.96 +static int cx_pl_compare(
    6.97 +        struct cx_list_s const *list,
    6.98 +        struct cx_list_s const *other
    6.99 +) {
   6.100 +    cx_pl_hack_cmpfunc(list);
   6.101 +    int ret = list->climpl->compare(list, other);
   6.102 +    cx_pl_unhack_cmpfunc(list);
   6.103 +    return ret;
   6.104 +}
   6.105 +
   6.106 +static void cx_pl_reverse(struct cx_list_s *list) {
   6.107 +    list->climpl->reverse(list);
   6.108 +}
   6.109 +
   6.110 +static void *cx_pl_iter_current(void const *it) {
   6.111 +    struct cx_iterator_s const *iter = it;
   6.112 +    void **ptr = iter->base.current_impl(it);
   6.113 +    return ptr == NULL ? NULL : *ptr;
   6.114 +}
   6.115 +
   6.116 +static struct cx_iterator_s cx_pl_iterator(
   6.117 +        struct cx_list_s const *list,
   6.118 +        size_t index
   6.119 +) {
   6.120 +    struct cx_iterator_s iter = list->climpl->iterator(list, index);
   6.121 +    iter.base.current_impl = iter.base.current;
   6.122 +    iter.base.current = cx_pl_iter_current;
   6.123 +    return iter;
   6.124 +}
   6.125 +
   6.126 +static cx_list_class cx_pointer_list_class = {
   6.127 +        cx_pl_destructor,
   6.128 +        cx_pl_insert_element,
   6.129 +        cx_pl_insert_array,
   6.130 +        cx_pl_insert_iter,
   6.131 +        cx_pl_remove,
   6.132 +        cx_pl_at,
   6.133 +        cx_pl_find,
   6.134 +        cx_pl_sort,
   6.135 +        cx_pl_compare,
   6.136 +        cx_pl_reverse,
   6.137 +        cx_pl_iterator,
   6.138 +};
   6.139 +
   6.140 +void cxListStoreObjects(CxList *list) {
   6.141 +    if (list->climpl != NULL) {
   6.142 +        list->cl = list->climpl;
   6.143 +        list->climpl = NULL;
   6.144 +    }
   6.145 +}
   6.146 +
   6.147 +void cxListStorePointers(CxList *list) {
   6.148 +    list->itemsize = sizeof(void *);
   6.149 +    list->climpl = list->cl;
   6.150 +    list->cl = &cx_pointer_list_class;
   6.151 +}
   6.152 +
   6.153 +bool cxListIsStoringPointers(CxList *list) {
   6.154 +    return list->climpl != NULL;
   6.155 +}
   6.156 +
   6.157 +// </editor-fold>
   6.158 +
   6.159  void cxListDestroy(CxList *list) {
   6.160      switch (list->content_destructor_type) {
   6.161          case CX_DESTRUCTOR_SIMPLE: {
     7.1 --- a/test/test_list.cpp	Wed Jan 25 19:19:29 2023 +0100
     7.2 +++ b/test/test_list.cpp	Thu Jan 26 20:59:36 2023 +0100
     7.3 @@ -573,6 +573,14 @@
     7.4          return list;
     7.5      }
     7.6  
     7.7 +    auto pointerLinkedListFromTestData() const -> CxList * {
     7.8 +        auto list = autofree(cxLinkedListCreate(&testingAllocator, cx_cmp_int, sizeof(int *)));
     7.9 +        cxListStorePointers(list);
    7.10 +        // note: cannot use cxListAddArray() because we don't have a list of pointers
    7.11 +        cx_for_n(i, testdata_len) cxListAdd(list, &testdata.data[i]);
    7.12 +        return list;
    7.13 +    }
    7.14 +
    7.15      auto arrayListFromTestData() const -> CxList * {
    7.16          auto list = autofree(cxArrayListCreate(&testingAllocator, cx_cmp_int, sizeof(int), testdata_len));
    7.17          cxListAddArray(list, testdata.data.data(), testdata_len);
    7.18 @@ -625,21 +633,37 @@
    7.19          EXPECT_EQ(*(int *) cxListAt(list, 3), 42);
    7.20      }
    7.21  
    7.22 -    static void verifyInsertArray(CxList *list) {
    7.23 +    static void verifyInsertArray(
    7.24 +            CxList *list,
    7.25 +            bool pointers = false
    7.26 +    ) {
    7.27          int a[5] = {5, 47, 11, 13, 42};
    7.28          int b[5] = {9, 18, 72, 50, 7};
    7.29 +        int *aptr[5];
    7.30 +        int *bptr[5];
    7.31 +        cx_for_n(i, 5) {
    7.32 +            aptr[i] = &a[i];
    7.33 +            bptr[i] = &b[i];
    7.34 +        }
    7.35  
    7.36          size_t inserted;
    7.37  
    7.38 -        inserted = cxListInsertArray(list, 0, a, 5);
    7.39 +        if (pointers) {
    7.40 +            inserted = cxListInsertArray(list, 0, aptr, 5);
    7.41 +        } else {
    7.42 +            inserted = cxListInsertArray(list, 0, a, 5);
    7.43 +        }
    7.44          EXPECT_EQ(inserted, 5);
    7.45          EXPECT_EQ(*(int *) cxListAt(list, 0), 5);
    7.46          EXPECT_EQ(*(int *) cxListAt(list, 1), 47);
    7.47          EXPECT_EQ(*(int *) cxListAt(list, 2), 11);
    7.48          EXPECT_EQ(*(int *) cxListAt(list, 3), 13);
    7.49          EXPECT_EQ(*(int *) cxListAt(list, 4), 42);
    7.50 -
    7.51 -        inserted = cxListInsertArray(list, 3, b, 5);
    7.52 +        if (pointers) {
    7.53 +            inserted = cxListInsertArray(list, 3, bptr, 5);
    7.54 +        } else {
    7.55 +            inserted = cxListInsertArray(list, 3, b, 5);
    7.56 +        }
    7.57          EXPECT_EQ(inserted, 5);
    7.58          EXPECT_EQ(*(int *) cxListAt(list, 0), 5);
    7.59          EXPECT_EQ(*(int *) cxListAt(list, 1), 47);
    7.60 @@ -787,9 +811,26 @@
    7.61  class LinkedList : public HighLevelTest {
    7.62  };
    7.63  
    7.64 +class PointerLinkedList : public HighLevelTest {
    7.65 +};
    7.66 +
    7.67  class ArrayList : public HighLevelTest {
    7.68  };
    7.69  
    7.70 +TEST_F(PointerLinkedList, cxListStorePointers) {
    7.71 +    auto list = autofree(cxLinkedListCreate(&testingAllocator, cx_cmp_int, 47));
    7.72 +    EXPECT_FALSE(cxListIsStoringPointers(list));
    7.73 +    cxListStorePointers(list);
    7.74 +    EXPECT_EQ(list->itemsize, sizeof(void *));
    7.75 +    EXPECT_NE(list->cl, nullptr);
    7.76 +    EXPECT_NE(list->climpl, nullptr);
    7.77 +    EXPECT_TRUE(cxListIsStoringPointers(list));
    7.78 +    cxListStoreObjects(list);
    7.79 +    EXPECT_NE(list->cl, nullptr);
    7.80 +    EXPECT_EQ(list->climpl, nullptr);
    7.81 +    EXPECT_FALSE(cxListIsStoringPointers(list));
    7.82 +}
    7.83 +
    7.84  TEST_F(LinkedList, cxLinkedListCreate) {
    7.85      CxList *list = autofree(cxLinkedListCreate(&testingAllocator, cx_cmp_int, sizeof(int)));
    7.86      ASSERT_NE(list, nullptr);
    7.87 @@ -807,12 +848,18 @@
    7.88  }
    7.89  
    7.90  TEST_F(LinkedList, cxListAdd) {
    7.91 -    CxList *list = autofree(cxLinkedListCreate(&testingAllocator, cx_cmp_int, sizeof(int)));
    7.92 +    auto list = autofree(cxLinkedListCreate(&testingAllocator, cx_cmp_int, sizeof(int)));
    7.93      verifyAdd(list, false);
    7.94  }
    7.95  
    7.96 +TEST_F(PointerLinkedList, cxListAdd) {
    7.97 +    auto list = autofree(cxLinkedListCreate(&testingAllocator, cx_cmp_int, sizeof(int *)));
    7.98 +    cxListStorePointers(list);
    7.99 +    verifyAdd(list, true);
   7.100 +}
   7.101 +
   7.102  TEST_F(ArrayList, cxListAdd) {
   7.103 -    CxList *list = autofree(cxArrayListCreate(&testingAllocator, cx_cmp_int, sizeof(int), 8));
   7.104 +    auto list = autofree(cxArrayListCreate(&testingAllocator, cx_cmp_int, sizeof(int), 8));
   7.105      verifyAdd(list, false);
   7.106  }
   7.107  
   7.108 @@ -820,6 +867,12 @@
   7.109      verifyInsert(autofree(cxLinkedListCreate(&testingAllocator, cx_cmp_int, sizeof(int))));
   7.110  }
   7.111  
   7.112 +TEST_F(PointerLinkedList, cxListInsert) {
   7.113 +    auto list = autofree(cxLinkedListCreate(&testingAllocator, cx_cmp_int, sizeof(int *)));
   7.114 +    cxListStorePointers(list);
   7.115 +    verifyInsert(list);
   7.116 +}
   7.117 +
   7.118  TEST_F(ArrayList, cxListInsert) {
   7.119      verifyInsert(autofree(cxArrayListCreate(&testingAllocator, cx_cmp_int, sizeof(int), 2)));
   7.120  }
   7.121 @@ -828,6 +881,12 @@
   7.122      verifyInsertArray(autofree(cxLinkedListCreate(&testingAllocator, cx_cmp_int, sizeof(int))));
   7.123  }
   7.124  
   7.125 +TEST_F(PointerLinkedList, cxListInsertArray) {
   7.126 +    auto list = autofree(cxLinkedListCreate(&testingAllocator, cx_cmp_int, sizeof(int *)));
   7.127 +    cxListStorePointers(list);
   7.128 +    verifyInsertArray(list, true);
   7.129 +}
   7.130 +
   7.131  TEST_F(ArrayList, cxListInsertArray) {
   7.132      verifyInsertArray(autofree(cxArrayListCreate(&testingAllocator, cx_cmp_int, sizeof(int), 4)));
   7.133  }
   7.134 @@ -836,6 +895,10 @@
   7.135      verifyRemove(linkedListFromTestData());
   7.136  }
   7.137  
   7.138 +TEST_F(PointerLinkedList, cxListRemove) {
   7.139 +    verifyRemove(pointerLinkedListFromTestData());
   7.140 +}
   7.141 +
   7.142  TEST_F(ArrayList, cxListRemove) {
   7.143      verifyRemove(arrayListFromTestData());
   7.144  }
   7.145 @@ -844,6 +907,10 @@
   7.146      verifyAt(linkedListFromTestData());
   7.147  }
   7.148  
   7.149 +TEST_F(PointerLinkedList, cxListAt) {
   7.150 +    verifyAt(pointerLinkedListFromTestData());
   7.151 +}
   7.152 +
   7.153  TEST_F(ArrayList, cxListAt) {
   7.154      verifyAt(arrayListFromTestData());
   7.155  }
   7.156 @@ -852,6 +919,10 @@
   7.157      verifyFind(linkedListFromTestData());
   7.158  }
   7.159  
   7.160 +TEST_F(PointerLinkedList, cxListFind) {
   7.161 +    verifyFind(pointerLinkedListFromTestData());
   7.162 +}
   7.163 +
   7.164  TEST_F(ArrayList, cxListFind) {
   7.165      verifyFind(arrayListFromTestData());
   7.166  }
   7.167 @@ -860,6 +931,10 @@
   7.168      verifySort(linkedListFromTestData());
   7.169  }
   7.170  
   7.171 +TEST_F(PointerLinkedList, cxListSort) {
   7.172 +    verifySort(pointerLinkedListFromTestData());
   7.173 +}
   7.174 +
   7.175  TEST_F(ArrayList, cxListSort) {
   7.176      verifySort(arrayListFromTestData());
   7.177  }
   7.178 @@ -868,6 +943,10 @@
   7.179      verifyIterator(linkedListFromTestData());
   7.180  }
   7.181  
   7.182 +TEST_F(PointerLinkedList, Iterator) {
   7.183 +    verifyIterator(pointerLinkedListFromTestData());
   7.184 +}
   7.185 +
   7.186  TEST_F(ArrayList, Iterator) {
   7.187      verifyIterator(arrayListFromTestData());
   7.188  }
   7.189 @@ -879,6 +958,15 @@
   7.190      verifyInsertViaIterator(list);
   7.191  }
   7.192  
   7.193 +TEST_F(PointerLinkedList, InsertViaIterator) {
   7.194 +    int fivenums[] = {0, 1, 2, 3, 4, 5};
   7.195 +    auto list = autofree(cxLinkedListCreate(&testingAllocator, cx_cmp_int, sizeof(int *)));
   7.196 +    cxListStorePointers(list);
   7.197 +    // note: cannot use cxListAddArray() because we don't have a list of pointers
   7.198 +    cx_for_n(i, 5) cxListAdd(list, &fivenums[i]);
   7.199 +    verifyInsertViaIterator(list);
   7.200 +}
   7.201 +
   7.202  TEST_F(ArrayList, InsertViaIterator) {
   7.203      int fivenums[] = {0, 1, 2, 3, 4, 5};
   7.204      CxList *list = autofree(cxArrayListCreate(&testingAllocator, cx_cmp_int, sizeof(int), 4));
   7.205 @@ -890,6 +978,10 @@
   7.206      verifyReverse(linkedListFromTestData());
   7.207  }
   7.208  
   7.209 +TEST_F(PointerLinkedList, cxListReverse) {
   7.210 +    verifyReverse(pointerLinkedListFromTestData());
   7.211 +}
   7.212 +
   7.213  TEST_F(ArrayList, cxListReverse) {
   7.214      verifyReverse(arrayListFromTestData());
   7.215  }
   7.216 @@ -900,20 +992,86 @@
   7.217      verifyCompare(left, right);
   7.218  }
   7.219  
   7.220 +TEST_F(LinkedList, cxListCompareWithPtrList) {
   7.221 +    auto left = linkedListFromTestData();
   7.222 +    auto right = pointerLinkedListFromTestData();
   7.223 +    verifyCompare(left, right);
   7.224 +}
   7.225 +
   7.226  TEST_F(LinkedList, cxListCompareWithArrayList) {
   7.227      auto left = linkedListFromTestData();
   7.228      auto right = arrayListFromTestData();
   7.229      verifyCompare(left, right);
   7.230  }
   7.231  
   7.232 +TEST_F(PointerLinkedList, cxListCompare) {
   7.233 +    auto left = pointerLinkedListFromTestData();
   7.234 +    auto right = pointerLinkedListFromTestData();
   7.235 +    verifyCompare(left, right);
   7.236 +}
   7.237 +
   7.238 +TEST_F(PointerLinkedList, cxListCompareWithNormalList) {
   7.239 +    auto left = pointerLinkedListFromTestData();
   7.240 +    auto right = linkedListFromTestData();
   7.241 +    verifyCompare(left, right);
   7.242 +}
   7.243 +
   7.244 +TEST_F(PointerLinkedList, cxListCompareWithArrayList) {
   7.245 +    auto left = pointerLinkedListFromTestData();
   7.246 +    auto right = arrayListFromTestData();
   7.247 +    verifyCompare(left, right);
   7.248 +}
   7.249 +
   7.250  TEST_F(ArrayList, cxListCompare) {
   7.251      auto left = arrayListFromTestData();
   7.252      auto right = arrayListFromTestData();
   7.253      verifyCompare(left, right);
   7.254  }
   7.255  
   7.256 -TEST_F(ArrayList, cxListCompareWithLinkedList) {
   7.257 +TEST_F(ArrayList, cxListCompareWithPtrList) {
   7.258 +    auto left = arrayListFromTestData();
   7.259 +    auto right = pointerLinkedListFromTestData();
   7.260 +    verifyCompare(left, right);
   7.261 +}
   7.262 +
   7.263 +TEST_F(ArrayList, cxListCompareWithNormalList) {
   7.264      auto left = arrayListFromTestData();
   7.265      auto right = linkedListFromTestData();
   7.266      verifyCompare(left, right);
   7.267  }
   7.268 +
   7.269 +TEST_F(PointerLinkedList, NoDestructor) {
   7.270 +    void *item = cxMalloc(&testingAllocator, sizeof(int));
   7.271 +    auto list = cxLinkedListCreate(cxDefaultAllocator, cx_cmp_int, sizeof(int *));
   7.272 +    cxListStorePointers(list);
   7.273 +    cxListAdd(list, item);
   7.274 +    ASSERT_FALSE(testingAllocator.verify());
   7.275 +    cxListDestroy(list);
   7.276 +    EXPECT_FALSE(testingAllocator.verify());
   7.277 +    cxFree(&testingAllocator, item);
   7.278 +    EXPECT_TRUE(testingAllocator.verify());
   7.279 +}
   7.280 +
   7.281 +TEST_F(PointerLinkedList, SimpleDestructor) {
   7.282 +    int item = 0;
   7.283 +    auto list = cxLinkedListCreate(cxDefaultAllocator, cx_cmp_int, sizeof(int *));
   7.284 +    cxListStorePointers(list);
   7.285 +    list->content_destructor_type = CX_DESTRUCTOR_SIMPLE;
   7.286 +    list->simple_destructor = [](void *elem) { *(int *) elem = 42; };
   7.287 +    cxListAdd(list, &item);
   7.288 +    cxListDestroy(list);
   7.289 +    EXPECT_EQ(item, 42);
   7.290 +}
   7.291 +
   7.292 +TEST_F(PointerLinkedList, AdvancedDestructor) {
   7.293 +    void *item = cxMalloc(&testingAllocator, sizeof(int));
   7.294 +    auto list = cxLinkedListCreate(cxDefaultAllocator, cx_cmp_int, sizeof(int *));
   7.295 +    cxListStorePointers(list);
   7.296 +    list->content_destructor_type = CX_DESTRUCTOR_ADVANCED;
   7.297 +    list->advanced_destructor.data = &testingAllocator;
   7.298 +    list->advanced_destructor.func = (cx_destructor_func2) cxFree;
   7.299 +    cxListAdd(list, item);
   7.300 +    ASSERT_FALSE(testingAllocator.verify());
   7.301 +    cxListDestroy(list);
   7.302 +    EXPECT_TRUE(testingAllocator.verify());
   7.303 +}

mercurial