1 #pragma once
2
3 /** @file the_Foundation/defs.h General definitions.
4
5 @authors Copyright (c) 2017 Jaakko Keränen <jaakko.keranen@iki.fi>
6
7 @par License
8
9 Redistribution and use in source and binary forms, with or without
10 modification, are permitted provided that the following conditions are met:
11
12 1. Redistributions of source code must retain the above copyright notice, this
13 list of conditions and the following disclaimer.
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 <small>THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
22 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
25 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.</small>
28 */
29
30 #include <stddef.h>
31 #include <stdint.h> // prefer to use int{n}_t/uint{n}_t
32 #include <stdbool.h>
33 #include <stdio.h>
34 #include <string.h>
35
36 #include "config.h"
37
38 #if defined (__cplusplus)
39 # define iPublic extern "C"
40 # define iBeginPublic extern "C" {
41 # define iEndPublic }
42 #else
43 # define iPublic
44 # define iBeginPublic
45 # define iEndPublic
46 #endif
47
48 #define iLocalDef static inline
49
50 #define iFalse false
51 #define iTrue true
52
53 #define iInvalidPos ((size_t) -1)
54 #define iInvalidSize ((size_t) -1)
55
56 #define iBit(n1_to_32) (1U << (n1_to_32 - 1))
57 #define iBit64(n1_to_64) (1ULL << (n1_to_64 - 1))
58 #define iMin(a, b) ((a) < (b) ? (a) : (b))
59 #define iMax(a, b) ((a) > (b) ? (a) : (b))
60 #define iAbs(a) ((a) > 0 ? (a) : -(a))
61 #define iClamp(i, low, high) ((i) < (low) ? (low) : (i) > (high) ? (high) : (i))
62 #define iCmp(a, b) ((a) > (b) ? 1 : (a) < (b) ? -1 : 0)
63 #define iElemCount(ar) (sizeof(ar) / sizeof((ar)[0]))
64 #define iSwap(typeName, a, b) { typeName tmp_Swap_ = (a); (a) = (b); (b) = tmp_Swap_; }
65
iAbsi(const int a)66 iLocalDef int iAbsi(const int a) { return a < 0 ? -a : a; }
iMaxi(const int a,const int b)67 iLocalDef int iMaxi(const int a, const int b) { return a > b ? a : b; }
iMini(const int a,const int b)68 iLocalDef int iMini(const int a, const int b) { return a < b ? a : b; }
iSign(const int a)69 iLocalDef int iSign(const int a) { return a < 0 ? -1 : a > 0 ? +1 : 0; }
70
71 #define iChangeFlags(var, flags, doSet) {if (doSet) { (var) |= (flags); } else { (var) &= ~(flags); }}
72
73 /* Types. */
74 typedef bool iBool;
75 typedef void iAny;
76 typedef void iAnyObject;
77 typedef void (*iDeinitFunc)(iAny *);
78 typedef void (*iDeleteFunc)(iAny *);
79
80 typedef struct { uint8_t bits; } iBoolv;
81
init2_Boolv(const iBool a,const iBool b)82 iLocalDef iBoolv init2_Boolv (const iBool a, const iBool b) {
83 return (iBoolv){ .bits = (a ? 1 : 0) | (b ? 2 : 0) };
84 }
init3_Boolv(const iBool a,const iBool b,const iBool c)85 iLocalDef iBoolv init3_Boolv (const iBool a, const iBool b, const iBool c) {
86 return (iBoolv){ .bits = (a ? 1 : 0) | (b ? 2 : 0) | (c ? 4 : 0) };
87 }
any_Boolv(const iBoolv a)88 iLocalDef iBool any_Boolv (const iBoolv a) { return a.bits != 0; }
all_Boolv2(const iBoolv a)89 iLocalDef iBool all_Boolv2 (const iBoolv a) { return a.bits == 3; }
all_Boolv3(const iBoolv a)90 iLocalDef iBool all_Boolv3 (const iBoolv a) { return a.bits == 7; }
91
92 #include "garbage.h"
93
94 iPublic void init_Foundation (void);
95 iPublic void deinit_Foundation (void);
96 iPublic iBool isInitialized_Foundation (void);
97 iPublic void setLocale_Foundation (void);
98 iPublic void printMessage_Foundation (FILE *, const char *format, ...);
99
100 iPublic uint32_t iCrc32 (const char *data, size_t size);
101 iPublic void iMd5Hash (const void *data, size_t size, uint8_t md5_out[16]);
102
103 #define iUnusedMany_(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, ...) \
104 ((void)(_0), (void)(_1), (void)(_2), (void)(_3), (void)(_4), \
105 (void)(_5), (void)(_6), (void)(_7), (void)(_8), (void)(_9))
106 #define iUnused(...) iUnusedMany_(__VA_ARGS__, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
107 #define iZap(var) memset(&(var), 0, sizeof(var));
108 #define iMalloc(typeName) ((i##typeName *) malloc(sizeof(i##typeName)))
109 #define iZapMalloc(typeName) ((i##typeName *) calloc(sizeof(i##typeName), 1))
110
111 #include "argcount.h"
112
113 #if !defined (__cplusplus)
114 # define iConstCast(type, ptr) ((type) (intptr_t) (ptr))
115 # define iFunctionCast(type, ptr) ((type) (ptr))
116 #else
117 # define iConstCast(type, ptr) const_cast<type>(ptr)
118 # define iFunctionCast(type, ptr) reinterpret_cast<type>(ptr)
119 #endif
120
121 #define iDeclareType(typeName) typedef struct Impl_##typeName i##typeName;
122
123 #define iDeclareTypeConstruction(typeName) \
124 i##typeName *new_##typeName(void); \
125 void delete_##typeName(i##typeName *); \
126 iLocalDef i##typeName *collect_##typeName(i##typeName *d) { \
127 return iCollectDel(d, delete_##typeName); \
128 } \
129 iLocalDef i##typeName *collectNew_##typeName(void) { \
130 return collect_##typeName(new_##typeName()); \
131 } \
132 void init_##typeName(i##typeName *); \
133 void deinit_##typeName(i##typeName *);
134
135 #define iDeclareTypeConstructionArgs(typeName, ...) \
136 i##typeName *new_##typeName(__VA_ARGS__); \
137 void delete_##typeName(i##typeName *); \
138 iLocalDef i##typeName *collect_##typeName(i##typeName *d) { \
139 return iCollectDel(d, delete_##typeName); \
140 } \
141 void init_##typeName(i##typeName *, __VA_ARGS__); \
142 void deinit_##typeName(i##typeName *);
143
144 #define iDefineTypeConstruction(typeName) \
145 i##typeName *new_##typeName(void) { \
146 i##typeName *d = iMalloc(typeName); \
147 init_##typeName(d); \
148 return d; \
149 } \
150 void delete_##typeName(i##typeName *d) { \
151 if (d) { \
152 deinit_##typeName(d); \
153 free(d); \
154 } \
155 }
156
157 #define iDefineStaticTypeConstruction(typeName) \
158 static i##typeName *new_##typeName##_(void) { \
159 i##typeName *d = iMalloc(typeName); \
160 init_##typeName##_(d); \
161 return d; \
162 } \
163 static void delete_##typeName##_(i##typeName *d) { \
164 deinit_##typeName##_(d); \
165 free(d); \
166 }
167
168 #define iDefineTypeConstructionArgs(typeName, newArgs, ...) \
169 i##typeName *new_##typeName newArgs { \
170 i##typeName *d = iMalloc(typeName); \
171 init_##typeName(d, __VA_ARGS__); \
172 return d; \
173 } \
174 void delete_##typeName(i##typeName *d) { \
175 if (d) { \
176 deinit_##typeName(d); \
177 free(d); \
178 } \
179 }
180
181 #define iDeclareTypeSerialization(typeName) \
182 void serialize_##typeName(const i##typeName *, iStream *); \
183 void deserialize_##typeName(i##typeName *, iStream *);
184
185 #define iDeclareIterator_(iterType, typeName, container) \
186 typedef struct iterType##Impl_##typeName i##typeName##iterType; \
187 typedef struct iterType##Impl_##typeName i##typeName##Reverse##iterType; \
188 void init_##typeName##iterType(i##typeName##iterType *, container); \
189 void next_##typeName##iterType(i##typeName##iterType *); \
190 void init_##typeName##Reverse##iterType(i##typeName##Reverse##iterType *, container); \
191 void next_##typeName##Reverse##iterType(i##typeName##Reverse##iterType *);
192
193 #define iDeclareIterator(typeName, container) \
194 iDeclareIterator_(Iterator, typeName, container)
195
196 #define iDeclareConstIterator(typeName, container) \
197 iDeclareIterator_(ConstIterator, typeName, container)
198
199 #define iIterate(typeName, iterType, iterName, container) \
200 i##typeName##iterType iterName; \
201 for (init_##typeName##iterType(&iterName, container); \
202 iterName.value; \
203 next_##typeName##iterType(&iterName))
204
205 #define iForIndices(iterName, container) \
206 for (size_t iterName = 0; iterName < iElemCount(container); ++iterName)
207
208 #define iForEach(typeName, iterName, container) \
209 iIterate(typeName, Iterator, iterName, container)
210
211 #define iReverseForEach(typeName, iterName, container) \
212 iIterate(typeName, ReverseIterator, iterName, container)
213
214 #define iConstForEach(typeName, iterName, container) \
215 iIterate(typeName, ConstIterator, iterName, container)
216
217 #define iReverseConstForEach(typeName, iterName, container) \
218 iIterate(typeName, ReverseConstIterator, iterName, container)
219
220 #define iForVarArgs(type, var, body) { \
221 { body; } \
222 va_list iVarArgs_; \
223 for (va_start(iVarArgs_, var);;) { \
224 var = va_arg(iVarArgs_, type); \
225 if (!var) break; \
226 { body; } \
227 } \
228 va_end(iVarArgs_); }
229
230 #if defined (NDEBUG)
231 # define iAssert(cond)
232 # define iDebugOnly(...) iUnused(__VA_ARGS__)
233 #else
234 # include <assert.h>
235 # define iAssert(cond) assert(cond)
236 # define iDebugOnly(...)
237 #endif
238
239 #if defined (iHaveDebugOutput)
240 # define iDebug(...) printMessage_Foundation(stdout, __VA_ARGS__)
241 # define iWarning(...) printMessage_Foundation(stderr, __VA_ARGS__)
242 #else
243 # define iDebug(...)
244 # define iWarning(...)
245 #endif
246