src/cx/list.h

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 647
2e6e9d9f2159
permissions
-rw-r--r--

add new pointer list wrapper - resolves #234

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

     1 /*
     2  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
     3  *
     4  * Copyright 2021 Mike Becker, Olaf Wintermann All rights reserved.
     5  *
     6  * Redistribution and use in source and binary forms, with or without
     7  * modification, are permitted provided that the following conditions are met:
     8  *
     9  *   1. Redistributions of source code must retain the above copyright
    10  *      notice, this list of conditions and the following disclaimer.
    11  *
    12  *   2. Redistributions in binary form must reproduce the above copyright
    13  *      notice, this list of conditions and the following disclaimer in the
    14  *      documentation and/or other materials provided with the distribution.
    15  *
    16  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
    17  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
    18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
    19  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
    20  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
    21  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
    22  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
    23  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
    24  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
    25  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
    26  * POSSIBILITY OF SUCH DAMAGE.
    27  */
    28 /**
    29  * \file list.h
    30  * \brief Interface for list implementations.
    31  * \author Mike Becker
    32  * \author Olaf Wintermann
    33  * \version 3.0
    34  * \copyright 2-Clause BSD License
    35  */
    37 #ifndef UCX_LIST_H
    38 #define UCX_LIST_H
    40 #include "common.h"
    41 #include "allocator.h"
    42 #include "iterator.h"
    44 #ifdef __cplusplus
    45 extern "C" {
    46 #endif
    48 /**
    49  * A comparator function comparing two list elements.
    50  */
    51 typedef int(*CxListComparator)(
    52         void const *left,
    53         void const *right
    54 );
    56 /**
    57  * List class type.
    58  */
    59 typedef struct cx_list_class_s cx_list_class;
    61 /**
    62  * Structure for holding the base data of a list.
    63  */
    64 struct cx_list_s {
    65     /**
    66      * The list class definition.
    67      */
    68     cx_list_class const *cl;
    69     /**
    70      * The actual implementation in case the list class is delegating.
    71      */
    72     cx_list_class const *climpl;
    73     /**
    74      * The allocator to use.
    75      */
    76     CxAllocator const *allocator;
    77     /**
    78      * The comparator function for the elements.
    79      */
    80     CxListComparator cmpfunc;
    81     /**
    82      * The size of each element (payload only).
    83      */
    84     size_t itemsize;
    85     /**
    86      * The size of the list (number of currently stored elements).
    87      */
    88     size_t size;
    89     /**
    90      * The capacity of the list (maximum number of elements).
    91      */
    92     size_t capacity;
    93     union {
    94         /**
    95          * An optional simple destructor for the list contents that admits the free() interface.
    96          *
    97          * @remark Set content_destructor_type to #CX_DESTRUCTOR_SIMPLE.
    98          *
    99          * @attention Read the documentation of the particular list implementation
   100          * whether this destructor shall only destroy the contents or also free the memory.
   101          */
   102         cx_destructor_func simple_destructor;
   103         /**
   104          * An optional advanced destructor for the list contents providing additional data.
   105          *
   106          * @remark Set content_destructor_type to #CX_DESTRUCTOR_ADVANCED.
   107          *
   108          * @attention Read the documentation of the particular list implementation
   109          * whether this destructor shall only destroy the contents or also free the memory.
   110          */
   111         cx_advanced_destructor advanced_destructor;
   112     };
   113     /**
   114      * The type of destructor to use.
   115      */
   116     enum cx_destructor_type content_destructor_type;
   117 };
   119 /**
   120  * The class definition for arbitrary lists.
   121  */
   122 struct cx_list_class_s {
   123     /**
   124      * Destructor function.
   125      */
   126     void (*destructor)(struct cx_list_s *list);
   128     /**
   129      * Member function for inserting a single elements.
   130      * Implementors SHOULD see to performant implementations for corner cases.
   131      */
   132     int (*insert_element)(
   133             struct cx_list_s *list,
   134             size_t index,
   135             void const *data
   136     );
   138     /**
   139      * Member function for inserting multiple elements.
   140      * Implementors SHOULD see to performant implementations for corner cases.
   141      */
   142     size_t (*insert_array)(
   143             struct cx_list_s *list,
   144             size_t index,
   145             void const *data,
   146             size_t n
   147     );
   149     /**
   150      * Member function for inserting an element relative to an iterator position.
   151      */
   152     int (*insert_iter)(
   153             struct cx_mut_iterator_s *iter,
   154             void const *elem,
   155             int prepend
   156     );
   158     /**
   159      * Member function for removing an element.
   160      */
   161     int (*remove)(
   162             struct cx_list_s *list,
   163             size_t index
   164     );
   166     /**
   167      * Member function for element lookup.
   168      */
   169     void *(*at)(
   170             struct cx_list_s const *list,
   171             size_t index
   172     );
   174     /**
   175      * Member function for finding an element.
   176      */
   177     size_t (*find)(
   178             struct cx_list_s const *list,
   179             void const *elem
   180     );
   182     /**
   183      * Member function for sorting the list in place.
   184      */
   185     void (*sort)(struct cx_list_s *list);
   187     /**
   188      * Member function for comparing this list to another list of the same type.
   189      */
   190     int (*compare)(
   191             struct cx_list_s const *list,
   192             struct cx_list_s const *other
   193     );
   195     /**
   196      * Member function for reversing the order of the items.
   197      */
   198     void (*reverse)(struct cx_list_s *list);
   200     /**
   201      * Member function for returning an iterator pointing to the specified index.
   202      */
   203     struct cx_iterator_s (*iterator)(
   204             struct cx_list_s const *list,
   205             size_t index
   206     );
   207 };
   209 /**
   210  * Common type for all list implementations.
   211  */
   212 typedef struct cx_list_s CxList;
   214 /**
   215  * Advises the list to store copies of the objects (default mode of operation).
   216  *
   217  * Retrieving objects from this list will yield pointers to the copies stored
   218  * within this list.
   219  *
   220  * @param list the list
   221  * @see cxListStorePointers()
   222  */
   223 __attribute__((__nonnull__))
   224 void cxListStoreObjects(CxList *list);
   226 /**
   227  * Advises the list to only store pointers to the objects.
   228  *
   229  * Retrieving objects from this list will yield the original pointers stored.
   230  *
   231  * @note This function forcibly sets the element size to the size of a pointer.
   232  * Invoking this function on a non-empty list that already stores copies of
   233  * objects is undefined.
   234  *
   235  * @param list the list
   236  * @see cxListStoreObjects()
   237  */
   238 __attribute__((__nonnull__))
   239 void cxListStorePointers(CxList *list);
   241 /**
   242  * Returns true, if this list is storing pointers instead of the actual data.
   243  *
   244  * @param list
   245  * @return
   246  * @see cxListStorePointers()
   247  */
   248 __attribute__((__nonnull__))
   249 bool cxListIsStoringPointers(CxList *list);
   251 /**
   252  * Adds an item to the end of the list.
   253  *
   254  * @param list the list
   255  * @param elem a pointer to the element to add
   256  * @return zero on success, non-zero on memory allocation failure
   257  * @see cxListAddArray()
   258  */
   259 __attribute__((__nonnull__))
   260 static inline int cxListAdd(
   261         CxList *list,
   262         void const *elem
   263 ) {
   264     return list->cl->insert_element(list, list->size, elem);
   265 }
   267 /**
   268  * Adds multiple items to the end of the list.
   269  *
   270  * This method is more efficient than invoking cxListAdd() multiple times.
   271  *
   272  * If there is not enough memory to add all elements, the returned value is
   273  * less than \p n.
   274  *
   275  * If this list is storing pointers instead of objects \p array is expected to
   276  * be an array of pointers.
   277  *
   278  * @param list the list
   279  * @param array a pointer to the elements to add
   280  * @param n the number of elements to add
   281  * @return the number of added elements
   282  */
   283 __attribute__((__nonnull__))
   284 static inline size_t cxListAddArray(
   285         CxList *list,
   286         void const *array,
   287         size_t n
   288 ) {
   289     return list->cl->insert_array(list, list->size, array, n);
   290 }
   292 /**
   293  * Inserts an item at the specified index.
   294  *
   295  * If \p index equals the list \c size, this is effectively cxListAdd().
   296  *
   297  * @param list the list
   298  * @param index the index the element shall have
   299  * @param elem a pointer to the element to add
   300  * @return zero on success, non-zero on memory allocation failure
   301  * or when the index is out of bounds
   302  * @see cxListInsertAfter()
   303  * @see cxListInsertBefore()
   304  */
   305 __attribute__((__nonnull__))
   306 static inline int cxListInsert(
   307         CxList *list,
   308         size_t index,
   309         void const *elem
   310 ) {
   311     return list->cl->insert_element(list, index, elem);
   312 }
   314 /**
   315  * Inserts multiple items to the list at the specified index.
   316  * If \p index equals the list size, this is effectively cxListAddArray().
   317  *
   318  * This method is usually more efficient than invoking cxListInsert()
   319  * multiple times.
   320  *
   321  * If there is not enough memory to add all elements, the returned value is
   322  * less than \p n.
   323  *
   324  * If this list is storing pointers instead of objects \p array is expected to
   325  * be an array of pointers.
   326  *
   327  * @param list the list
   328  * @param index the index where to add the elements
   329  * @param array a pointer to the elements to add
   330  * @param n the number of elements to add
   331  * @return the number of added elements
   332  */
   333 __attribute__((__nonnull__))
   334 static inline size_t cxListInsertArray(
   335         CxList *list,
   336         size_t index,
   337         void const *array,
   338         size_t n
   339 ) {
   340     return list->cl->insert_array(list, index, array, n);
   341 }
   343 /**
   344  * Inserts an element after the current location of the specified iterator.
   345  *
   346  * The used iterator remains operational, but all other active iterators should
   347  * be considered invalidated.
   348  *
   349  * If \p iter is not a list iterator, the behavior is undefined.
   350  * If \p iter is a past-the-end iterator, the new element gets appended to the list.
   351  *
   352  * @param iter an iterator
   353  * @param elem the element to insert
   354  * @return zero on success, non-zero on memory allocation failure
   355  * @see cxListInsert()
   356  * @see cxListInsertBefore()
   357  */
   358 __attribute__((__nonnull__))
   359 static inline int cxListInsertAfter(
   360         CxMutIterator *iter,
   361         void const *elem
   362 ) {
   363     return ((struct cx_list_s *) iter->src_handle)->cl->insert_iter(iter, elem, 0);
   364 }
   366 /**
   367  * Inserts an element before the current location of the specified iterator.
   368  *
   369  * The used iterator remains operational, but all other active iterators should
   370  * be considered invalidated.
   371  *
   372  * If \p iter is not a list iterator, the behavior is undefined.
   373  * If \p iter is a past-the-end iterator, the new element gets appended to the list.
   374  *
   375  * @param iter an iterator
   376  * @param elem the element to insert
   377  * @return zero on success, non-zero on memory allocation failure
   378  * @see cxListInsert()
   379  * @see cxListInsertAfter()
   380  */
   381 __attribute__((__nonnull__))
   382 static inline int cxListInsertBefore(
   383         CxMutIterator *iter,
   384         void const *elem
   385 ) {
   386     return ((struct cx_list_s *) iter->src_handle)->cl->insert_iter(iter, elem, 1);
   387 }
   389 /**
   390  * Removes the element at the specified index.
   391  * @param list the list
   392  * @param index the index of the element
   393  * @return zero on success, non-zero if the index is out of bounds
   394  */
   395 __attribute__((__nonnull__))
   396 static inline int cxListRemove(
   397         CxList *list,
   398         size_t index
   399 ) {
   400     return list->cl->remove(list, index);
   401 }
   403 /**
   404  * Returns a pointer to the element at the specified index.
   405  *
   406  * @param list the list
   407  * @param index the index of the element
   408  * @return a pointer to the element or \c NULL if the index is out of bounds
   409  */
   410 __attribute__((__nonnull__))
   411 static inline void *cxListAt(
   412         CxList *list,
   413         size_t index
   414 ) {
   415     return list->cl->at(list, index);
   416 }
   418 /**
   419  * Returns an iterator pointing to the item at the specified index.
   420  *
   421  * The returned iterator is position-aware.
   422  *
   423  * If the index is out of range, a past-the-end iterator will be returned.
   424  *
   425  * @param list the list
   426  * @param index the index where the iterator shall point at
   427  * @return a new iterator
   428  */
   429 __attribute__((__nonnull__, __warn_unused_result__))
   430 static inline CxIterator cxListIterator(
   431         CxList const *list,
   432         size_t index
   433 ) {
   434     return list->cl->iterator(list, index);
   435 }
   437 /**
   438  * Returns a mutating iterator pointing to the item at the specified index.
   439  *
   440  * The returned iterator is position-aware.
   441  *
   442  * If the index is out of range, a past-the-end iterator will be returned.
   443  *
   444  * @param list the list
   445  * @param index the index where the iterator shall point at
   446  * @return a new iterator
   447  */
   448 __attribute__((__nonnull__, __warn_unused_result__))
   449 CxMutIterator cxListMutIterator(
   450         CxList *list,
   451         size_t index
   452 );
   454 /**
   455  * Returns an iterator pointing to the first item of the list.
   456  *
   457  * The returned iterator is position-aware.
   458  *
   459  * If the list is empty, a past-the-end iterator will be returned.
   460  *
   461  * @param list the list
   462  * @return a new iterator
   463  */
   464 __attribute__((__nonnull__, __warn_unused_result__))
   465 static inline CxIterator cxListBegin(CxList const *list) {
   466     return list->cl->iterator(list, 0);
   467 }
   469 /**
   470  * Returns a mutating iterator pointing to the first item of the list.
   471  *
   472  * The returned iterator is position-aware.
   473  *
   474  * If the list is empty, a past-the-end iterator will be returned.
   475  *
   476  * @param list the list
   477  * @return a new iterator
   478  */
   479 __attribute__((__nonnull__, __warn_unused_result__))
   480 static inline CxMutIterator cxListBeginMut(CxList *list) {
   481     return cxListMutIterator(list, 0);
   482 }
   484 /**
   485  * Returns the index of the first element that equals \p elem.
   486  *
   487  * Determining equality is performed by the list's comparator function.
   488  *
   489  * @param list the list
   490  * @param elem the element to find
   491  * @return the index of the element or \c (size+1) if the element is not found
   492  */
   493 __attribute__((__nonnull__))
   494 static inline size_t cxListFind(
   495         CxList const *list,
   496         void const *elem
   497 ) {
   498     return list->cl->find(list, elem);
   499 }
   501 /**
   502  * Sorts the list in place.
   503  *
   504  * \remark The underlying sort algorithm is implementation defined.
   505  *
   506  * @param list the list
   507  */
   508 __attribute__((__nonnull__))
   509 static inline void cxListSort(CxList *list) {
   510     list->cl->sort(list);
   511 }
   513 /**
   514  * Reverses the order of the items.
   515  *
   516  * @param list the list
   517  */
   518 __attribute__((__nonnull__))
   519 static inline void cxListReverse(CxList *list) {
   520     list->cl->reverse(list);
   521 }
   523 /**
   524  * Compares a list to another list of the same type.
   525  *
   526  * First, the list sizes are compared.
   527  * If they match, the lists are compared element-wise.
   528  *
   529  * @param list the list
   530  * @param other the list to compare to
   531  * @return zero, if both lists are equal element wise,
   532  * negative if the first list is smaller, positive if the first list is larger
   533  */
   534 __attribute__((__nonnull__))
   535 int cxListCompare(
   536         CxList const *list,
   537         CxList const *other
   538 );
   540 /**
   541  * Deallocates the memory of the specified list structure.
   542  *
   543  * Also calls content a destructor function, depending on the configuration
   544  * in CxList.content_destructor_type.
   545  *
   546  * This function itself is a destructor function for the CxList.
   547  *
   548  * @param list the list which shall be destroyed
   549  */
   550 __attribute__((__nonnull__))
   551 void cxListDestroy(CxList *list);
   553 #ifdef __cplusplus
   554 } // extern "C"
   555 #endif
   557 #endif // UCX_LIST_H

mercurial