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