Standard setup for writing C inspired by Casey Muratori, Ryan Fleury, Mr. 4th Programmer, and others in the handmade community.
Nevar pievienot vairāk kā 25 tēmas Tēmai ir jāsākas ar burtu vai ciparu, tā var saturēt domu zīmes ('-') un var būt līdz 35 simboliem gara.
 
 
 

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