Concord - C Discord API library
A Discord API wrapper library written in C
carray.h
Go to the documentation of this file.
1/* Copyright 2022 Cogmasters */
2/*
3 * C-Ware License
4 *
5 * Copyright (c) 2022, C-Ware
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions are met:
10 *
11 * 1. Redistributions of source code must retain the above copyright notice, this
12 * list of conditions and the following disclaimer.
13 *
14 * 2. Redistributions in binary form must reproduce the above copyright notice,
15 * this list of conditions and the following disclaimer in the documentation
16 * and/or other materials provided with the distribution.
17 *
18 * 3. Redistributions of modified source code must append a copyright notice in
19 * the form of 'Copyright <YEAR> <NAME>' to each modified source file's
20 * copyright notice, and the standalone license file if one exists.
21 *
22 * A 'redistribution' can be constituted as any version of the original source
23 * code material that is intended to comprise some other derivative work of
24 * this code. A fork created for the purpose of contributing to any version of
25 * the source does not constitute a truly 'derivative work' and does not require
26 * listing.
27 *
28 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
29 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
30 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
31 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
32 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
33 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
34 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
35 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
36 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
37 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
38*/
39
40/* Modified by Lucas Müller <lucas@muller.codes>, 19 Sept 2022
41 * - __carray_init() should initialize its `size` value
42 *
43 * Modified by Lucas Müller <lucas@muller.codes>, 15 Feb 2022
44 * - CARRAY_RESIZE() has a fallback value (+1)
45 *
46 * Modified by Lucas Müller <lucas@muller.codes>, 06 Feb 2022
47 * - __carray_init() accept initial length
48 *
49 * Modified by Lucas Müller <lucas@muller.codes>, 02 Feb 2022
50 * - remove free(carray) at __carrray_free()
51 *
52 * Modified by Lucas Müller <lucas@muller.codes>, 01 Feb 2022
53 * - change CARRAY_INITIAL_SIZE from 5 to 4
54 * - change CARRAY_RESIZE to doubling arrays to reduce realloc calls
55 * - remove calloc() from __carray_init(), expect user to allocate it
56 * - remove pseudo-return from __carray_init()
57 *
58 * Modified by Lucas Müller <lucas@muller.codes>, 27 Jan 2022
59 * - rename contents -> array
60 * - rename logical_size -> size
61 * - rename physical_size -> realsize
62 */
63
64#ifndef CWARE_ARRAY_H
65#define CWARE_ARRAY_H
66
67#ifndef CARRAY_INITIAL_SIZE
68#define CARRAY_INITIAL_SIZE 4
69#endif
70
71#ifndef CARRAY_RESIZE
72#define CARRAY_RESIZE(current_size) \
73 1 + current_size * 2
74#endif
75
76/* carray_init */
77#ifndef CARRAY_STACKFUL
78#define __carray_init(carray, length, _type, _compare, _free) \
79do { \
80 (carray)->realsize = length; \
81 (carray)->size = 0; \
82 (carray)->array = calloc(length, sizeof(_type)); \
83} while (0)
84
85#define carray_init(carray, settings) \
86 __carray_init(carray, CARRAY_INITIAL_SIZE, settings)
87#else
88#define carray_init(carray, length, block) \
89do { \
90 carray.realsize = length; \
91 carray.size = 0; \
92 carray.array = block; \
93} while (0)
94#endif
95
96/* carray_insert */
97#ifndef CARRAY_STACKFUL
98#define __carray_insert_handle_full(carray, index, value) \
99 (carray)->realsize = CARRAY_RESIZE((carray)->realsize); \
100 (carray)->array = realloc((carray)->array, sizeof(*(carray)->array) * (size_t) (carray)->realsize)
101#else
102#define __carray_insert_handle_full(carray, index, value) \
103 fprintf(stderr, "carray_insert: attempt to insert value '%s' into full array '%s'. (%s:%i)\n", #value, #carray, __FILE__, __LINE__); \
104 exit(EXIT_FAILURE)
105#endif
106
107#define carray_insert(carray, index, value) \
108 if((carray)->size == (carray)->realsize) { \
109 __carray_insert_handle_full(carray, index, value); \
110 } \
111 \
112 if(index < 0 || index > (carray)->size) { \
113 fprintf(stderr, "carray_insert: attempt to insert at index %i, out of bounds of array '%s'. (%s:%i)\n", index, #carray, __FILE__, __LINE__); \
114 exit(EXIT_FAILURE); \
115 } \
116 \
117 memmove((carray)->array + index + 1, (carray)->array + index, sizeof(*(carray)->array) * (size_t) ((carray)->size - index)); \
118 (carray)->array[index] = value; \
119 (carray)->size++
120
121/* carray_pop */
122#define carray_pop(carray, index, location) \
123 location; \
124 \
125 if(index < 0 || index >= (carray)->size) { \
126 fprintf(stderr, "carray_pop: attempt to pop index %i, out of bounds of array '%s'. (%s:%i)\n", index, #carray, __FILE__, __LINE__); \
127 exit(EXIT_FAILURE); \
128 } \
129 \
130 (carray)->size--; \
131 (location) = (carray)->array[(index)]; \
132 memmove((carray)->array + index, (carray)->array + index + 1, sizeof(*(carray)->array) * (size_t) ((carray)->size - index))
133
134/* carray_remove */
135#define __carray_remove(carray, value, _type, _compare, _free) \
136do { \
137 int __CARRAY_ITER_INDEX = 0; \
138 \
139 for(__CARRAY_ITER_INDEX = 0; __CARRAY_ITER_INDEX < (carray)->size; __CARRAY_ITER_INDEX++) { \
140 _type __CARRAY_OPERAND_A = (carray)->array[__CARRAY_ITER_INDEX]; \
141 _type __CARRAY_OPERAND_B = value; \
142 \
143 if((_compare) == 0) \
144 continue; \
145 \
146 _free; \
147 (carray)->size--; \
148 memmove((carray)->array + __CARRAY_ITER_INDEX, \
149 (carray)->array + __CARRAY_ITER_INDEX + 1, \
150 sizeof(*(carray)->array) * (size_t) ((carray)->size - __CARRAY_ITER_INDEX)); \
151 \
152 __CARRAY_ITER_INDEX = -1; \
153 break; \
154 } \
155 \
156 if(__CARRAY_ITER_INDEX != -1) { \
157 fprintf(stderr, "carray_remove: attempt to remove value '%s' that is not in array '%s'. (%s:%i)\n", #value, #carray, __FILE__, __LINE__); \
158 exit(EXIT_FAILURE); \
159 } \
160} while(0)
161
162#define carray_remove(carray, value, settings) \
163 __carray_remove(carray, value, settings)
164
165/* carray_find */
166#define __carray_find(carray, value, location, _type, _compare, _free) \
167 -1; \
168 \
169 do { \
170 int __CARRAY_ITER_INDEX = 0; \
171 location = -1; \
172 \
173 for(__CARRAY_ITER_INDEX = 0; __CARRAY_ITER_INDEX < (carray)->size; __CARRAY_ITER_INDEX++) { \
174 _type __CARRAY_OPERAND_A = (carray)->array[__CARRAY_ITER_INDEX]; \
175 _type __CARRAY_OPERAND_B = value; \
176 \
177 if((_compare) == 0) \
178 continue; \
179 \
180 location = __CARRAY_ITER_INDEX; \
181 \
182 break; \
183 } \
184 } while(0)
185
186#define carray_find(carray, value, location, settings) \
187 __carray_find(carray, value, location, settings)
188
189#ifndef CARRAY_STACKFUL
190#define __carray_free_array(carray) free((carray)->array);
191#else
192#define __carray_free_array(carray)
193#endif
194
195/* carray_free */
196#define __carray_free(carray, _type, _compare, _free) \
197do { \
198 int __CARRAY_ITER_INDEX = 0; \
199 \
200 for(__CARRAY_ITER_INDEX = 0; __CARRAY_ITER_INDEX < (carray)->size; __CARRAY_ITER_INDEX++) { \
201 _type __CARRAY_OPERAND_A = (carray)->array[__CARRAY_ITER_INDEX]; \
202 (void) __CARRAY_OPERAND_A; \
203 \
204 _free; \
205 } \
206 \
207 __carray_free_array(carray); \
208} while(0)
209
210#define carray_free(carray, settings) \
211 __carray_free(carray, settings)
212
213/* carray_append */
214#ifndef CARRAY_STACKFUL
215#define __carray_append_handle_full(carray, value) \
216 (carray)->realsize = CARRAY_RESIZE((carray)->realsize); \
217 (carray)->array = realloc((carray)->array, sizeof(*(carray)->array) * (size_t) (carray)->realsize)
218#else
219#define __carray_append_handle_full(carray, value) \
220 fprintf(stderr, "carray_append: attempt to append value '%s' into full array '%s'. (%s:%i)\n", #value, #carray, __FILE__, __LINE__); \
221 exit(EXIT_FAILURE)
222#endif
223
224#define carray_append(carray, value) \
225 if((carray)->size == (carray)->realsize) { \
226 __carray_append_handle_full(carray, value); \
227 } \
228 \
229 (carray)->array[(carray)->size] = value; \
230 (carray)->size++;
231
232#endif