rsys

Basic data structures and low-level features
git clone git://git.meso-star.fr/rsys.git
Log | Files | Refs | README | LICENSE

stretchy_array.h (4171B)


      1 /* Copyright (C) 2013-2023, 2025 Vincent Forest (vaplv@free.fr)
      2  *
      3  * The RSys library is free software: you can redistribute it and/or modify
      4  * it under the terms of the GNU General Public License as published
      5  * by the Free Software Foundation, either version 3 of the License, or
      6  * (at your option) any later version.
      7  *
      8  * The RSys library is distributed in the hope that it will be useful,
      9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
     11  * GNU General Public License for more details.
     12  *
     13  * You should have received a copy of the GNU General Public License
     14  * along with the RSys library. If not, see <http://www.gnu.org/licenses/>. */
     15 
     16 #ifndef STRETCHY_ARRAY_H
     17 #define STRETCHY_ARRAY_H
     18 
     19 #include "math.h"
     20 #include "mem_allocator.h"
     21 
     22 /*
     23  * Port of the suckless Sean T. Barret's stretchy buffer. Stretchy arrays can
     24  * be use on data types that does not rely on an init or release process and
     25  * can be bitwise copied. Refer to dynamic_array for more advanced data types
     26  */
     27 
     28 /*******************************************************************************
     29  * Internal macros
     30  ******************************************************************************/
     31 #define sa_raw__(A) ((size_t*)(A)-2)
     32 #define sa_capacity__(A) sa_raw__(A)[0]
     33 #define sa_size__(A) sa_raw__(A)[1]
     34 #define sa_need_grow__(A, N) ((A)==NULL || sa_size__(A) + (N) >= sa_capacity__(A))
     35 #define sa_may_be_grow__(A, N) (sa_need_grow__(A, (N)) ? sa_grow__(A, N) : 0)
     36 #define sa_grow__(A, N) \
     37   (*(void**)(&A) = sa_grow_func__((void*)(A), (N), sizeof(*(A))))
     38 
     39 /*******************************************************************************
     40  * Stretchy buffer API
     41  ******************************************************************************/
     42 /* Free `Array' memory */
     43 #define sa_release(Array) {                                                    \
     44     if(Array)                                                                  \
     45       mem_rm(sa_raw__(Array));                                                 \
     46   } (void)0
     47 
     48 /* Push back `Val' in `Array' */
     49 #define sa_push(Array, Val) {                                                  \
     50     sa_may_be_grow__(Array, 1);                                                \
     51     (Array)[sa_size__(Array)++] = (Val);                                       \
     52   } (void)0
     53 
     54 /* Clean up `Array' but does not release its memory */
     55 #define sa_clear(Array) {                                                      \
     56     if(Array)                                                                  \
     57       sa_size__(Array) = 0;                                                    \
     58   } (void)0
     59 
     60 /* Add `N' uninitialized items to `Array'. Return a pointer to the 1st added */
     61 #define sa_add(Array, N)                                                       \
     62   (sa_may_be_grow__(Array, N),                                                 \
     63    sa_size__(Array) += (N),                                                    \
     64    &(Array)[sa_size__(Array) - (N)])
     65 
     66 /* Return a lvalue of the last item in `Array' */
     67 #define sa_last(Array) ((Array)[sa_size__(Array)-1])
     68 
     69 /* Return the number of items in `Array' */
     70 #define sa_size(Array) ((Array) ? sa_size__(Array) : 0)
     71 
     72 /*******************************************************************************
     73  * Helper internal function
     74  ******************************************************************************/
     75 static INLINE void*
     76 sa_grow_func__(void* array, const size_t increment, const size_t itemsize)
     77 {
     78   size_t dbl_capacity = array ? 2 * sa_capacity__(array) : 0;
     79   size_t min_needed_capacity = MMAX(sa_size(array) + increment, 32);
     80   size_t new_capacity = MMAX(dbl_capacity, min_needed_capacity);
     81   size_t sizeof_array = itemsize * new_capacity + sizeof(size_t)*2;
     82   size_t* new_array;
     83   ASSERT(itemsize);
     84 
     85   if(array) {
     86     new_array = (size_t*)mem_realloc(sa_raw__(array), sizeof_array);
     87   } else {
     88     new_array = (size_t*)mem_alloc_aligned(sizeof_array, 16);
     89   }
     90 
     91   if(!new_array)
     92     FATAL("Unsufficient memory\n");
     93 
     94   if(!array) new_array[1] = 0;
     95   new_array[0] = new_capacity;
     96   return new_array+2;
     97 }
     98 
     99 #endif /* STRETCHY_ARRAY_H */