Standard setup for writing C inspired by Casey Muratori, Ryan Fleury, Mr. 4th Programmer, and others in the handmade community.
Du kan inte välja fler än 25 ämnen Ämnen måste starta med en bokstav eller siffra, kan innehålla bindestreck ('-') och vara max 35 tecken långa.
 
 
 
 

271 rader
7.8 KiB

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