add some dependencies and test code
This commit is contained in:
224
src/array/sc_array.h
Normal file
224
src/array/sc_array.h
Normal file
@@ -0,0 +1,224 @@
|
||||
/*
|
||||
* BSD-3-Clause
|
||||
*
|
||||
* Copyright 2021 Ozan Tezcan
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holder nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
|
||||
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef SC_ARRAY_H
|
||||
#define SC_ARRAY_H
|
||||
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#define SC_ARRAY_VERSION "2.0.0"
|
||||
|
||||
#ifdef SC_HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#else
|
||||
#define sc_array_realloc realloc
|
||||
#define sc_array_free free
|
||||
#endif
|
||||
|
||||
#ifndef SC_ARRAY_MAX
|
||||
#define SC_ARRAY_MAX SIZE_MAX
|
||||
#endif
|
||||
|
||||
#define sc_array_def(T, name) \
|
||||
struct sc_array_##name { \
|
||||
bool oom; \
|
||||
size_t cap; \
|
||||
size_t size; \
|
||||
/* NOLINTNEXTLINE */ \
|
||||
T *elems; \
|
||||
}
|
||||
/**
|
||||
* Init array
|
||||
* @param a array
|
||||
*/
|
||||
#define sc_array_init(a) \
|
||||
do { \
|
||||
memset((a), 0, sizeof(*(a))); \
|
||||
} while (0)
|
||||
|
||||
/**
|
||||
* Destroy array
|
||||
* @param a array
|
||||
*/
|
||||
#define sc_array_term(a) \
|
||||
do { \
|
||||
sc_array_free((a)->elems); \
|
||||
sc_array_init(a); \
|
||||
} while (0)
|
||||
|
||||
/**
|
||||
* Add elem to array, call sc_array_oom(v) to see if 'add' failed because of out
|
||||
* of memory.
|
||||
*
|
||||
* @param a array
|
||||
* @param k elem
|
||||
*/
|
||||
#define sc_array_add(a, k) \
|
||||
do { \
|
||||
const size_t _max = SC_ARRAY_MAX / sizeof(*(a)->elems); \
|
||||
size_t _cap; \
|
||||
void *_p; \
|
||||
\
|
||||
if ((a)->cap == (a)->size) { \
|
||||
if ((a)->cap > _max / 2) { \
|
||||
(a)->oom = true; \
|
||||
break; \
|
||||
} \
|
||||
_cap = (a)->cap == 0 ? 8 : (a)->cap * 2; \
|
||||
_p = sc_array_realloc((a)->elems, \
|
||||
_cap * sizeof(*((a)->elems))); \
|
||||
if (_p == NULL) { \
|
||||
(a)->oom = true; \
|
||||
break; \
|
||||
} \
|
||||
(a)->cap = _cap; \
|
||||
(a)->elems = _p; \
|
||||
} \
|
||||
(a)->oom = false; \
|
||||
(a)->elems[(a)->size++] = k; \
|
||||
} while (0)
|
||||
|
||||
/**
|
||||
* Deletes items from the array without deallocating underlying memory
|
||||
* @param a array
|
||||
*/
|
||||
#define sc_array_clear(a) \
|
||||
do { \
|
||||
(a)->size = 0; \
|
||||
(a)->oom = false; \
|
||||
} while (0)
|
||||
|
||||
/**
|
||||
* @param a array
|
||||
* @return true if last add operation failed, false otherwise.
|
||||
*/
|
||||
#define sc_array_oom(a) ((a)->oom)
|
||||
|
||||
/**
|
||||
* Get element at index i, if 'i' is out of range, result is undefined.
|
||||
*
|
||||
* @param a array
|
||||
* @param i index
|
||||
* @return element at index 'i'
|
||||
*/
|
||||
#define sc_array_at(a, i) ((a)->elems[i])
|
||||
|
||||
/**
|
||||
* @param a array
|
||||
* @return element count
|
||||
*/
|
||||
#define sc_array_size(a) ((a)->size)
|
||||
|
||||
/**
|
||||
* @param a array
|
||||
* @param i element index, If 'i' is out of the range, result is undefined.
|
||||
*/
|
||||
#define sc_array_del(a, i) \
|
||||
do { \
|
||||
size_t idx = (i); \
|
||||
assert(idx < (a)->size); \
|
||||
\
|
||||
const size_t _cnt = (a)->size - (idx) - 1; \
|
||||
if (_cnt > 0) { \
|
||||
memmove(&((a)->elems[idx]), &((a)->elems[idx + 1]), \
|
||||
_cnt * sizeof(*((a)->elems))); \
|
||||
} \
|
||||
(a)->size--; \
|
||||
} while (0)
|
||||
|
||||
/**
|
||||
* Deletes the element at index i, replaces last element with the deleted
|
||||
* element unless deleted element is the last element. This is faster than
|
||||
* moving elements but elements will no longer be in the 'add order'
|
||||
*
|
||||
* arr[a,b,c,d,e,f] -> sc_array_del_unordered(arr, 2) - > arr[a,b,f,d,e]
|
||||
*
|
||||
* @param a array
|
||||
* @param i index. If 'i' is out of the range, result is undefined.
|
||||
*/
|
||||
#define sc_array_del_unordered(a, i) \
|
||||
do { \
|
||||
size_t idx = (i); \
|
||||
assert(idx < (a)->size); \
|
||||
(a)->elems[idx] = (a)->elems[(--(a)->size)]; \
|
||||
} while (0)
|
||||
|
||||
/**
|
||||
* Deletes the last element. If current size is zero, result is undefined.
|
||||
* @param a array
|
||||
*/
|
||||
#define sc_array_del_last(a) \
|
||||
do { \
|
||||
assert((a)->size != 0); \
|
||||
(a)->size--; \
|
||||
} while (0)
|
||||
|
||||
/**
|
||||
* Sorts the array using qsort()
|
||||
* @param a array
|
||||
* @param cmp comparator, check qsort() documentation for details
|
||||
*/
|
||||
#define sc_array_sort(a, cmp) \
|
||||
(qsort((a)->elems, (a)->size, sizeof(*(a)->elems), cmp))
|
||||
|
||||
/**
|
||||
* Returns last element. If array is empty, result is undefined.
|
||||
* @param a array
|
||||
*/
|
||||
#define sc_array_last(a) (a)->elems[(a)->size - 1]
|
||||
|
||||
/**
|
||||
* @param a array
|
||||
* @param elem elem
|
||||
*/
|
||||
#define sc_array_foreach(a, elem) \
|
||||
for (size_t _k = 1, _i = 0; _k && _i != (a)->size; _k = !_k, _i++) \
|
||||
for ((elem) = (a)->elems[_i]; _k; _k = !_k)
|
||||
|
||||
// (type, name)
|
||||
sc_array_def(int, int);
|
||||
sc_array_def(unsigned int, uint);
|
||||
sc_array_def(long, long);
|
||||
sc_array_def(long long, ll);
|
||||
sc_array_def(unsigned long, ulong);
|
||||
sc_array_def(unsigned long long, ull);
|
||||
sc_array_def(uint32_t, 32);
|
||||
sc_array_def(uint64_t, 64);
|
||||
sc_array_def(double, double);
|
||||
sc_array_def(const char *, str);
|
||||
sc_array_def(void *, ptr);
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user