-
Notifications
You must be signed in to change notification settings - Fork 0
/
aocCommon.h
212 lines (179 loc) · 6.38 KB
/
aocCommon.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
#ifndef AOC_COMMON_H
#define AOC_COMMON_H
#if defined(__GNUC__)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-function"
#endif
#if defined(__clang__)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunused-function"
#endif
#include <stdio.h> /* for getFileLength */
#include <stdlib.h>
#ifndef AOC_MEMMOVE
#include <string.h>
#define AOC_MEMMOVE memmove
#endif
#ifndef AOC_ASSERT
#include <assert.h>
#define AOC_ASSERT assert
#endif /* AOC_ASSERT */
#define AOC_NEW_DYN_ARR(type, arr_ptr, max) \
do \
{ \
(arr_ptr) = malloc(sizeof(type) * (max)); \
AOC_ASSERT((arr_ptr) != NULL); \
} while (0)
/* Modifies both arr and len */
#define AOC_GROW_DYN_ARR(type, arr, len) \
do \
{ \
type *AOC_EXPAND_ARR; \
size_t AOC_EXPAND_LEN = ((len) == 0) ? (2) : (((len) * 3) / 2); \
\
AOC_EXPAND_ARR = realloc((arr), sizeof(type) * AOC_EXPAND_LEN); \
AOC_ASSERT(AOC_EXPAND_ARR != NULL); \
(arr) = AOC_EXPAND_ARR; \
(len) = AOC_EXPAND_LEN; \
} while (0)
#define AOC_CAT_DYN_ARR(type, arr, len, max, val) \
do \
{ \
if ((len) == (max)) \
{ \
AOC_GROW_DYN_ARR(type, (arr), (max)); \
} \
\
(arr)[(len)++] = (val); \
} while (0)
/* Insertion sort concatination. Entirely possible there is a way to do this
* in a regular function should one prefer */
#define AOC_INSERT_CAT(type, arr, len, max, val, CompFunc) \
do \
{ \
if ((len) == (max)) \
{ \
AOC_GROW_DYN_ARR(type, (arr), (max)); \
} \
\
if ((len) == 0) \
{ \
(arr)[(len)++] = (val); \
} \
else \
{ \
const size_t AOC_INSERT_INDEX = leftBinSearch((arr), \
(len), &(val), sizeof(type), (CompFunc)); \
\
AOC_MEMMOVE(&((arr)[AOC_INSERT_INDEX + 1]), \
&((arr)[AOC_INSERT_INDEX]), \
sizeof(type) * ((len) - AOC_INSERT_INDEX)); \
(arr)[AOC_INSERT_INDEX] = (val); \
(len)++; \
} \
} while (0)
#define AOC_FREE(ptr) \
do \
{ \
if ((ptr) != NULL) \
{ \
free((ptr)); \
(ptr) = NULL; \
} \
} while (0) \
#define AOC_SWAP(type, left, right) \
do \
{ \
type AOC_SWAP_TMP = (left); \
(left) = (right); \
(right) = AOC_SWAP_TMP; \
} while (0)
#define AOC_BOOL unsigned char
#define AOC_STAT signed char
#define AOC_TRUE (1)
#define AOC_FALSE (0)
#define AOC_SUCCESS (0)
#define AOC_FAILURE (1)
#define AOC_ERROR (-1)
#define AOC_ABS(x) (((x) < 0) ? ((x) * -1) : (x))
#define AOC_MIN(x, y) (((x) < (y)) ? (x) : (y))
#define AOC_MAX(x, y) (((x) > (y)) ? (x) : (y))
#define AOC_CLAMP(l, x, u) (AOC_MAX((l), (AOC_MIN((x), (u)))))
/* These binary search variant functions are here just because while the
* standard library does include bsearch its behavior is undefined for what
* element it returns if the target element appears more than once. These
* return the leftmost and rightmost occurance of that element instead */
/* This is just a helper function because performing pointer arithmatic on
* a void pointer is disallowed but casting it to a character pointer is valid
* and also the only cast that doesn't violate strict aliasing */
#define AOC_ACCESS_VARR(arr, index, size) ((char *) (arr) + ((index) * (size)))
static size_t leftBinSearch(void *arr, const size_t len, const void *target,
const size_t size, int (*CompFunc)(const void *, const void *))
{
size_t left = 0;
size_t right = len;
AOC_ASSERT((arr != NULL) && (len != 0) && (target != NULL)
&& (CompFunc != NULL));
while (left < right)
{
size_t mid = ((left + right) >> 1);
if (CompFunc(AOC_ACCESS_VARR(arr, mid, size), target) < 0)
{
left = mid + 1;
}
else
{
right = mid;
}
}
return left;
}
static size_t rightBinSearch(void *arr, const size_t len, const void *target,
const size_t size, int (*CompFunc)(const void *, const void *))
{
size_t left = 0;
size_t right = len;
AOC_ASSERT((arr != NULL) && (len != 0) && (target != NULL)
&& (CompFunc != NULL));
while (left < right)
{
size_t mid = ((left + right) >> 1);
if (CompFunc(AOC_ACCESS_VARR(arr, mid, size), target) > 0)
{
right = mid;
}
else
{
left = mid + 1;
}
}
return right - 1;
}
static long int getFileLength(FILE *f_handle)
{
long int length = -1;
if (f_handle != NULL)
{
const long int initial = ftell(f_handle);
if (fseek(f_handle, 0, SEEK_END) == -1)
{
return -1;
}
length = ftell(f_handle);
if (fseek(f_handle, initial, SEEK_SET) == -1)
{
return -1;
}
}
return length;
}
#if defined(__GNUC__)
#pragma GCC diagnostic pop
#endif
#if defined(__clang__)
#pragma clang diagnostic pop
#endif
#endif /* AOC_COMMON_H */
/*
Copyright (c) 2024, grauho <grauho@proton.me> All rights reserved.
*/