Standard setup for writing C inspired by Casey Muratori, Ryan Fleury, Mr. 4th Programmer, and others in the handmade community.
Nelze vybrat více než 25 témat Téma musí začínat písmenem nebo číslem, může obsahovat pomlčky („-“) a může být dlouhé až 35 znaků.
 
 
 

290 řádky
8.7 KiB

  1. #ifndef CORE_H
  2. #define CORE_H
  3. // cstdlib includes
  4. #include "stdbool.h"
  5. #include "stdint.h" // necessary for int type sizes
  6. #include "time.h" // TODO(djledda): try not to depend on this one
  7. // ### Misc macros ###
  8. #if ENABLE_ASSERT
  9. #define Assert(expression) if (!(expression)) {*(volatile int *)0 = 0;}
  10. #else
  11. #define Assert(expression)
  12. #endif
  13. #define function static
  14. #define global static
  15. #define local_persist static
  16. // ### Types ###
  17. typedef int8_t int8;
  18. typedef int16_t int16;
  19. typedef int32_t int32;
  20. typedef int64_t int64;
  21. typedef uint8_t uint8;
  22. typedef uint16_t uint16;
  23. typedef uint32_t uint32;
  24. typedef uint64_t uint64;
  25. typedef uint8_t byte;
  26. typedef float real32;
  27. typedef double real64;
  28. typedef struct string string;
  29. // ### Sizes and Numbers ###
  30. #define Bytes(n) (n)
  31. #define Kilobytes(n) (n << 10)
  32. #define Megabytes(n) (n << 20)
  33. #define Gigabytes(n) (((uint64)n) << 30)
  34. #define Terabytes(n) (((uint64)n) << 40)
  35. #define Thousand(n) ((n)*1000)
  36. #define Million(n) ((n)*1000000)
  37. #define Billion(n) ((n)*1000000000LL)
  38. #define ArrayCount(arr) (sizeof(arr) / sizeof((arr)[0]))
  39. #define MemberSize(type, memberName) sizeof(((type *)0)->memberName)
  40. #define MemberType(type, memberName) typeof(((type *)0)->memberName)
  41. #define MemberSizeUnderlying(type, memberName) sizeof(*((type *)0)->memberName)
  42. #define MemberTypeUnderlying(type, memberName) typeof(*((type *)0)->memberName)
  43. // ### Arenas ###
  44. typedef struct {
  45. void *memory;
  46. size_t capacity;
  47. size_t head;
  48. } Arena;
  49. typedef struct {
  50. Arena *arena;
  51. size_t start;
  52. } Scratch;
  53. void *pushSize(Arena *arena, size_t bytes);
  54. void *pushSizeFill(Arena *arena, size_t bytes, byte fill);
  55. Arena *arenaAlloc(size_t capacity);
  56. void arenaFree(Arena *arena);
  57. void arenaFreeFrom(Arena *arena, size_t pos);
  58. void arenaPopTo(Arena *arena, void *pos);
  59. void initialiseDjStdCore();
  60. Scratch scratchStart(Arena **conflicts, size_t conflictCount);
  61. void scratchEnd(Scratch scratch);
  62. #define PushArray(arena, type, size) (type *)pushSize(arena, sizeof(type) * (size))
  63. #define PushArrayZero(arena, type, size) (type *)pushSizeFill(arena, sizeof(type) * (size), 0)
  64. #define PushStruct(arena, type) (type *)pushSize(arena, sizeof(type))
  65. #define PushStructZero(arena, type) (type *)pushSizeFill(arena, sizeof(type), 0)
  66. // ### Vectors ###
  67. typedef union {
  68. struct {
  69. real32 x;
  70. real32 y;
  71. };
  72. real32 vec[2];
  73. } Vec2;
  74. inline function Vec2 vec2(real32 x, real32 y) {
  75. Vec2 result = {0};
  76. result.x = x;
  77. result.y = y;
  78. return result;
  79. }
  80. typedef union {
  81. struct {
  82. real32 x;
  83. real32 y;
  84. real32 z;
  85. };
  86. real32 vec[3];
  87. } Vec3;
  88. inline function Vec3 vec3(real32 x, real32 y, real32 z) {
  89. Vec3 result = {0};
  90. result.x = x;
  91. result.y = y;
  92. result.z = z;
  93. return result;
  94. }
  95. typedef union {
  96. struct {
  97. real32 r;
  98. real32 g;
  99. real32 b;
  100. real32 a;
  101. };
  102. struct {
  103. real32 x;
  104. real32 y;
  105. real32 z;
  106. real32 w;
  107. };
  108. real32 vec[4];
  109. } Vec4;
  110. inline function Vec4 vec4(real32 x, real32 y, real32 z, real32 w) {
  111. Vec4 result = {0};
  112. result.x = x;
  113. result.y = y;
  114. result.z = z;
  115. result.w = w;
  116. return result;
  117. }
  118. // ### Lists ###
  119. #define DefineList(type, prefix) \
  120. typedef struct {\
  121. type* data;\
  122. size_t length;\
  123. size_t capacity;\
  124. } prefix ## List
  125. DefineList(string, String);
  126. #define PushList(arena, type, size) (type){ (MemberTypeUnderlying(type, data) *)pushSize(arena, MemberSizeUnderlying(type, data)*size), size, 0 }
  127. #define EmptyList(type) (type){ NULL, 0, 0 }
  128. #define PushListZero(arena, type, size) (type){ (MemberTypeUnderlying(type, data) *)pushSizeFill(arena, MemberSizeUnderlying(type, data)*size, 0), size, 0 }
  129. #define PushFullList(arena, type, size) (type){ (MemberTypeUnderlying(type, data) *)pushSize(arena, MemberSizeUnderlying(type, data))*size, size, size }
  130. #define PushFullListZero(arena, type, size) (type){ (MemberTypeUnderlying(type, data) *)pushSizeFill(arena, MemberSizeUnderlying(type, data)*size, 0), size, size }
  131. #define ArrayAsList(type, array) (type){ array, ArrayCount(array), ArrayCount(array) }
  132. #define AppendList(list, element) \
  133. if ((list)->length < (list)->capacity) { \
  134. (list)->data[(list)->length++] = (element); \
  135. }
  136. #define ZeroListFull(list) memset((list)->data, 0, (list)->length * sizeof(T))
  137. #define ZeroList(list) (list)->length = 0; \
  138. memset((list)->data, 0, (list)->length * sizeof(T));
  139. #define ListSlice(list, start, stop) (stop > list.length || start > stop ? {0} : { list.data + start, stop - start, stop - start, })
  140. #define ListTail(list, start) ListSlice(list, list.length)
  141. // ### Strings ###
  142. struct string {
  143. char *str;
  144. size_t length;
  145. };
  146. #define STB_SPRINTF_DECORATE(name) stb_##name // define this before including if you want to change the names
  147. #include "vendor/stb_sprintf.h"
  148. #define s(lit) ((string){(char *)(lit), sizeof(lit) - 1})
  149. #define PushString(arena, length) ((string){ (char *)pushSize(arena, length), (length) })
  150. #define PushStringFill(arena, length, characterByte) ((string){ (char *)pushSizeFill(arena, length, characterByte), (length) })
  151. // C Strings
  152. DefineList(char, Char);
  153. const char *cstringFromCharList(Arena *arena, CharList buf);
  154. const char *cstring(Arena *arena, string str);
  155. size_t calcStringLen(const char *str);
  156. string strFromCString(Arena *arena, const char *str);
  157. bool strEql(string s1, string s2);
  158. bool strStartsWith(string str, string testStr);
  159. bool stringContains(string str, char c);
  160. string strReverse(Arena *arena, string str);
  161. string strSlice(string str, size_t start, size_t stop);
  162. string strSliceCStr(char *data, size_t start, size_t stop);
  163. StringList strSplit(Arena *arena, string splitStr, string inputStr);
  164. string strPrintfv(Arena *arena, const char *fmt, va_list args);
  165. string strPrintf(Arena *arena, const char *fmt, ...);
  166. typedef struct {
  167. uint8 result;
  168. bool valid;
  169. } ParsePositiveIntResult;
  170. ParsePositiveIntResult parsePositiveInt(string str, size_t *lengthPointer);
  171. typedef struct {
  172. real32 result;
  173. bool valid;
  174. } ParsePositiveReal32Result;
  175. ParsePositiveReal32Result parsePositiveReal32(string str, size_t *lengthPointer);
  176. inline function bool isNumeric(char c);
  177. // ### Cmdline ###
  178. StringList getArgs(Arena *arena, int argc, char **argv);
  179. // ### Time ###
  180. typedef uint64 UnixTimestamp;
  181. typedef struct tm Timestamp;
  182. UnixTimestamp getSystemUnixTime();
  183. Timestamp timestampFromUnixTime(UnixTimestamp *unixTimestamp);
  184. string formatTimeHmsUnix(Arena *arena, UnixTimestamp time);
  185. string formatTimeHms(Arena *arena, Timestamp *time);
  186. string formatTimeYmdUnix(Arena *arena, UnixTimestamp time);
  187. string formatTimeYmd(Arena *arena, Timestamp *time);
  188. // ### Linked Lists ###
  189. // TODO(djledda): implement basic linked lists (based on arenas?)
  190. // ### Logging ###
  191. typedef enum {
  192. StdStream_stdout,
  193. StdStream_stdin,
  194. StdStream_stderr,
  195. } StdStream;
  196. #define ANSI_INSTRUCTION_FROM_ENUM(ansiCodeEnum) ANSI_INSTRUCTION(ansiCodeEnum)
  197. #define ANSI_INSTRUCTION(ansiCode) "\u001b[" #ansiCode "m"
  198. #define ANSI_INSTRUCTION_STR(ansiCodeStr) "\u001b[" ansiCodeStr "m"
  199. #define ANSI_RESET ANSI_INSTRUCTION(0)
  200. #define ANSI_fg_black 30
  201. #define ANSI_fg_red 31
  202. #define ANSI_fg_green 32
  203. #define ANSI_fg_yellow 33
  204. #define ANSI_fg_blue 34
  205. #define ANSI_fg_magenta 35
  206. #define ANSI_fg_cyan 36
  207. #define ANSI_fg_white 37
  208. #define ANSI_fg_bblack 90
  209. #define ANSI_fg_bred 91
  210. #define ANSI_fg_bgreen 92
  211. #define ANSI_fg_byellow 93
  212. #define ANSI_fg_bblue 94
  213. #define ANSI_fg_bmagenta 95
  214. #define ANSI_fg_bcyan 96
  215. #define ANSI_fg_bwhite 97
  216. #define ANSI_bg_black 40
  217. #define ANSI_bg_red 41
  218. #define ANSI_bg_green 42
  219. #define ANSI_bg_yellow 43
  220. #define ANSI_bg_blue 44
  221. #define ANSI_bg_magenta 45
  222. #define ANSI_bg_cyan 46
  223. #define ANSI_bg_white 47
  224. #define ANSI_bg_bblack 100
  225. #define ANSI_bg_bred 101
  226. #define ANSI_bg_bgreen 102
  227. #define ANSI_bg_byellow 103
  228. #define ANSI_bg_bblue 104
  229. #define ANSI_bg_bmagenta 105
  230. #define ANSI_bg_bcyan 106
  231. #define ANSI_bg_bwhite 107
  232. #define COLOR_TEXT(text, foregroundcolor) ANSI_INSTRUCTION_FROM_ENUM(foregroundcolor) text ANSI_RESET
  233. #define COLOR_TEXT_BG(text, backgroundcolor) ANSI_INSTRUCTION_FROM_ENUM(backgroundcolor) text ANSI_RESET
  234. #define COLOR_TEXT_FG_BG(text, foregroundcolor, backgroundcolor) ANSI_INSTRUCTION_FROM_ENUM(foregroundcolor) ANSI_INSTRUCTION_FROM_ENUM(backgroundcolor) text ANSI_RESET
  235. #define COLOR_TEXT_RGB(text, red, green, blue) ANSI_INSTRUCTION_STR("38;2;" #red ";" #green ";" #blue) text ANSI_RESET
  236. DefineList(int, Int);
  237. void printIntList(IntList l);
  238. void printStrList(StringList l);
  239. extern void (*print)(const char *fmt, ...);
  240. // ### Loops ###
  241. #define EachIn(list, it) size_t it = 0; it < (list).length; it++
  242. #define EachInReversed(list, it) size_t it = (list).length - 1; it >= 0 && it < (list).length; it--
  243. #define EachInArray(arr, it) size_t it = 0; it < ArrayCount(arr); ++it
  244. // ### Misc ###
  245. int intCompare(const void *a, const void *b);
  246. #endif