選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。

1週間前
2週間前
1週間前
2週間前
1週間前
2週間前
1週間前
2週間前
1週間前
2週間前
1週間前
2週間前
1週間前
2週間前
1週間前
2週間前
1週間前
2週間前
1週間前
2週間前
1週間前
2週間前
1週間前
2週間前
1週間前
2週間前
1週間前
2週間前
1週間前
2週間前
1週間前
2週間前
1週間前
2週間前
1週間前
2週間前
1週間前
2週間前
1週間前
2週間前
1週間前
2週間前
1週間前
2週間前
1週間前
2週間前
1週間前
2週間前
1週間前
2週間前
1週間前
1週間前
2週間前
1週間前
2週間前
1週間前
1週間前
1週間前
2週間前
1週間前
2週間前
1週間前
2週間前
1週間前
2週間前
1週間前
2週間前
1週間前
2週間前
1週間前
2週間前
1週間前
2週間前
1週間前
1週間前
1週間前
1週間前
1週間前
1週間前
1週間前
2週間前
1週間前
2週間前
1週間前
2週間前
1週間前
2週間前
1週間前
2週間前
1週間前
2週間前
1週間前
2週間前
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431
  1. #include "os.cpp"
  2. #include <math.h>
  3. #include <string.h>
  4. #include "core.h"
  5. #define STB_SPRINTF_IMPLEMENTATION
  6. #include "vendor/stb_sprintf.h"
  7. void *pushSizeFill(Arena *arena, size_t bytes, byte fill) {
  8. if (arena->capacity - arena->head >= bytes) {
  9. void *ptr = (char *)arena->memory + arena->head;
  10. arena->head += bytes;
  11. memset(ptr, fill, bytes);
  12. return ptr;
  13. }
  14. return 0;
  15. }
  16. void *pushSize(Arena *arena, size_t bytes) {
  17. if (arena->capacity - arena->head >= bytes) {
  18. void *ptr = (char *)arena->memory + arena->head;
  19. arena->head += bytes;
  20. return ptr;
  21. }
  22. return 0;
  23. }
  24. Arena *arenaAlloc(size_t capacity) {
  25. Arena *result = (Arena *)os_alloc(sizeof(Arena) + capacity);
  26. result->memory = result + sizeof(Arena);
  27. result->capacity = capacity;
  28. result->head = 0;
  29. return result;
  30. }
  31. void arenaFree(Arena *arena) {
  32. os_free(arena, arena->capacity);
  33. }
  34. void arenaFreeFrom(Arena *arena, size_t position) {
  35. arena->head = position;
  36. }
  37. void arenaPopTo(Arena *arena, void *position) {
  38. arena->head = (byte *)position - (byte *)arena->memory;
  39. }
  40. Arena *scratchArenas[2];
  41. void initialiseCore() {
  42. for (EachInArray(scratchArenas, i)) {
  43. scratchArenas[i] = arenaAlloc(Megabytes(64));
  44. }
  45. }
  46. Scratch scratchStart(Arena **conflicts, size_t conflictCount) {
  47. Scratch scratch = {0};
  48. for (size_t i = 0; i < ArrayCount(scratchArenas); i += 1) {
  49. bool conflicted = false;
  50. for (Arena **conflict = conflicts; conflict < conflicts + conflictCount; conflict += 1) {
  51. if (*conflict == scratchArenas[i]) {
  52. conflicted = true;
  53. break;
  54. }
  55. }
  56. if (conflicted == false) {
  57. scratch.arena = scratchArenas[i];
  58. scratch.start = scratch.arena->head;
  59. break;
  60. }
  61. }
  62. return scratch;
  63. }
  64. #define DeferLoop(begin_stmnt, end_stmnt) for(int __defer_i = ((begin_stmnt), 0); __defer_i < 1; (++__defer_i, (end_stmnt)))
  65. #define WithScratch(scratchName) Scratch scratchName; DeferLoop(scratchName = scratchStart(0, 0), scratchEnd(scratchName))
  66. void scratchEnd(Scratch scratch) {
  67. arenaFreeFrom(scratch.arena, scratch.start);
  68. }
  69. template <typename T>
  70. T *appendList(list<T> *list, T element) {
  71. if (list->head < list->length) {
  72. list->data[list->head] = element;
  73. list->head++;
  74. return &(list->data[list->head - 1]);
  75. } else {
  76. return 0;
  77. }
  78. }
  79. template <typename T>
  80. void zeroListFull(list<T> *list) {
  81. memset(list->data, 0, list->head * sizeof(T));
  82. }
  83. template <typename T>
  84. void zeroList(list<T> *list) {
  85. list->head = 0;
  86. memset(list->data, 0, list->head * sizeof(T));
  87. }
  88. inline string operator""_s(const char *cstrLiteral, size_t length) {
  89. return {
  90. (char *)cstrLiteral,
  91. length,
  92. };
  93. }
  94. const char *cstring(Arena *arena, list<char> buf) {
  95. char *arr = PushArray(arena, char, buf.length + 1);
  96. memmove(arr, buf.data, buf.length);
  97. arr[buf.length] = '\0';
  98. return arr;
  99. }
  100. const char *cstring(Arena *arena, string str) {
  101. char *arr = PushArray(arena, char, str.length + 1);
  102. memmove(arr, str.str, str.length);
  103. arr[str.length] = '\0';
  104. return arr;
  105. }
  106. bool strStartsWith(string str, string testStr) {
  107. if (str.length < testStr.length) {
  108. return false;
  109. }
  110. for (size_t i = 0; i < testStr.length; i++) {
  111. if (str.str[i] != testStr.str[i]) {
  112. return false;
  113. }
  114. }
  115. return true;
  116. }
  117. bool strEql(string s1, string s2) {
  118. if (s1.length != s2.length) {
  119. return false;
  120. }
  121. for (size_t i = 0; i < s1.length; i++) {
  122. if (s1.str[i] != s2.str[i]) {
  123. return false;
  124. }
  125. }
  126. return true;
  127. }
  128. size_t calcStringLen(const char *str) {
  129. size_t size = 0;
  130. if (str == NULL) {
  131. return size;
  132. }
  133. while (str[size] != '\0') {
  134. size++;
  135. }
  136. return size;
  137. }
  138. string strFromCString(Arena *arena, const char *str) {
  139. string result = PushString(arena, calcStringLen(str));
  140. memcpy(result.str, str, result.length);
  141. return result;
  142. }
  143. string strReverse(Arena *arena, string str) {
  144. string reversed = PushString(arena, str.length);
  145. for (
  146. size_t mainIndex = str.length - 1, reversedIndex = 0;
  147. mainIndex < str.length;
  148. mainIndex--, reversedIndex++
  149. ) {
  150. reversed.str[reversedIndex] = str.str[mainIndex];
  151. }
  152. return reversed;
  153. }
  154. string strPrintfv(Arena *arena, const char *fmt, va_list args) {
  155. string result = {0};
  156. va_list argsCopy;
  157. va_copy(argsCopy, args);
  158. uint64 bufSize = stb_vsnprintf(0, 0, fmt, args) + 1;
  159. result.str = PushArray(arena, char, bufSize);
  160. result.length = bufSize - 1;
  161. stb_vsnprintf((char *)result.str, (int)bufSize, fmt, argsCopy);
  162. return result;
  163. }
  164. string strPrintf(Arena *arena, const char *fmt, ...) {
  165. string result = {0};
  166. va_list args;
  167. va_start(args, fmt);
  168. result = strPrintfv(arena, fmt, args);
  169. va_end(args);
  170. return result;
  171. }
  172. template <typename T>
  173. list<T> listSlice(list<T> l, size_t start, size_t stop) {
  174. if (stop == 0) {
  175. stop = l.head;
  176. }
  177. // TODO(djledda): maybe assert instead
  178. if (stop > l.head || start > stop) {
  179. return {0};
  180. }
  181. return {
  182. l.data + start,
  183. stop - start,
  184. stop - start,
  185. };
  186. }
  187. string strSlice(string str, size_t start, size_t stop) {
  188. if (stop == 0) {
  189. stop = str.length;
  190. }
  191. // TODO(djledda): maybe assert instead
  192. if (stop > str.length || start > stop) {
  193. return {0};
  194. }
  195. return {
  196. str.str + start,
  197. stop - start,
  198. };
  199. }
  200. string strSlice(char *data, size_t start, size_t stop) {
  201. return {
  202. data + start,
  203. stop - start,
  204. };
  205. }
  206. bool stringContains(string str, char c) {
  207. for (size_t i = 0; i < str.length; i++) {
  208. if (str.str[i] == c) {
  209. return true;
  210. }
  211. }
  212. return false;
  213. }
  214. string NUMERIC_CHARS = "0123456789"_s;
  215. inline bool isNumeric(char c) {
  216. return stringContains(NUMERIC_CHARS, c);
  217. }
  218. list<string> strSplit(Arena *arena, string splitStr, string inputStr) {
  219. list<string> result = {0};
  220. if (inputStr.length > 0) {
  221. size_t splitCount = 0;
  222. size_t c = 0;
  223. size_t start = 0;
  224. void *beginning = (char *)arena->memory + arena->head;
  225. while (c < inputStr.length - splitStr.length) {
  226. if (strEql(strSlice(inputStr, c, c + splitStr.length), splitStr)) {
  227. string *splitString = PushStruct(arena, string);
  228. splitString->str = inputStr.str + start;
  229. splitString->length = c - start;
  230. splitCount++;
  231. start = c + 1;
  232. }
  233. c++;
  234. }
  235. string *splitString = PushStruct(arena, string);
  236. splitString->str = inputStr.str + start;
  237. splitString->length = inputStr.length - start;
  238. splitCount++;
  239. result.data = (string *)beginning,
  240. result.head = splitCount,
  241. result.length = splitCount;
  242. }
  243. return result;
  244. }
  245. int8 parsePositiveInt(string str, size_t *lengthPointer) {
  246. size_t numEnd = 0;
  247. char currChar = str.str[numEnd];
  248. while (numEnd < str.length && isNumeric(currChar)) {
  249. currChar = str.str[++numEnd];
  250. *lengthPointer += 1;
  251. }
  252. *lengthPointer -= 1;
  253. if (numEnd > 0) {
  254. uint8 result = 0;
  255. for (size_t i = 0; i < numEnd; i++) {
  256. result *= 10;
  257. result += str.str[i] - '0';
  258. }
  259. return result;
  260. } else {
  261. return -1;
  262. }
  263. }
  264. real32 parsePositiveReal32(string str, size_t *lengthPointer) {
  265. real32 result = NAN;
  266. string wholePartStr = string{0};
  267. string fractionalPartStr = string{0};
  268. bool split = false;
  269. size_t c = 0;
  270. while (c < str.length) {
  271. if (str.str[c] == '.') {
  272. wholePartStr.str = str.str;
  273. wholePartStr.length = c;
  274. fractionalPartStr.str = str.str + c + 1;
  275. fractionalPartStr.length = str.length - c - 1;
  276. split = true;
  277. break;
  278. }
  279. c++;
  280. }
  281. if (split) {
  282. int wholePart = parsePositiveInt(wholePartStr, lengthPointer);
  283. *lengthPointer += 1;
  284. int fractionalPart = parsePositiveInt(fractionalPartStr, lengthPointer);
  285. if (wholePart >= 0 && fractionalPart >= 0) {
  286. // TODO(dledda): implement powf with intrinsics? or just custom
  287. real32 fractionalPartMultiplier = 1.0f / powf(10.0f, (real32)fractionalPartStr.length);
  288. result = (real32)wholePart + (real32)fractionalPart * (real32)fractionalPartMultiplier;
  289. }
  290. } else if (c > 0) {
  291. result = (real32)parsePositiveInt(str, lengthPointer);
  292. }
  293. return result;
  294. }
  295. list<string> getArgs(Arena *arena, int argc, char **argv) {
  296. list<string> args = PushList(arena, string, (size_t)argc - 1);
  297. for (int i = 1; i < argc; i++) {
  298. appendList(&args, strFromCString(arena, argv[i]));
  299. }
  300. return args;
  301. }
  302. UnixTimestamp getSystemUnixTime() {
  303. time_t now;
  304. time(&now);
  305. return (UnixTimestamp)now;
  306. }
  307. Timestamp timestampFromUnixTime(UnixTimestamp *unixTimestamp) {
  308. tm timestamp = {0};
  309. gmtime_r((time_t *)unixTimestamp, &timestamp);
  310. return timestamp;
  311. }
  312. string formatTimeHms(Arena *arena, UnixTimestamp time) {
  313. local_persist const string format = "HH-MM-SS"_s;
  314. string buf = PushString(arena, format.length);
  315. tm *timestamp = gmtime((time_t *)&time);
  316. strftime(buf.str, buf.length + 1, "%T", timestamp);
  317. return buf;
  318. }
  319. string formatTimeHms(Arena *arena, Timestamp *time) {
  320. local_persist const string format = "HH-MM-SS"_s;
  321. string buf = PushString(arena, format.length);
  322. strftime(buf.str, buf.length + 1, "%T", (tm *)time);
  323. return buf;
  324. }
  325. string formatTimeYmd(Arena *arena, UnixTimestamp time) {
  326. local_persist const string format = "YYYY-mm-dd"_s;
  327. string buf = PushString(arena, format.length);
  328. tm *timestamp = gmtime((time_t *)&time);
  329. strftime(buf.str, buf.length + 1, "%Y-%m-%d", timestamp);
  330. return buf;
  331. }
  332. string formatTimeYmd(Arena *arena, Timestamp *time) {
  333. local_persist const string format = "YYYY-mm-dd"_s;
  334. string buf = PushString(arena, format.length);
  335. strftime(buf.str, buf.length + 1, "%Y-%m-%d", (tm *)time);
  336. return buf;
  337. }
  338. void logErr(const char *fmt, ...) {
  339. va_list argList;
  340. va_start(argList, fmt);
  341. os_log(LogTarget_stdout, fmt, argList);
  342. va_end(argList);
  343. }
  344. function void logStdout(const char *fmt, ...) {
  345. va_list argList;
  346. va_start(argList, fmt);
  347. os_log(LogTarget_stdout, fmt, argList);
  348. va_end(argList);
  349. }
  350. void log(const char *fmt, ...) {
  351. va_list argList;
  352. va_start(argList, fmt);
  353. os_log(LogTarget_stdout, fmt, argList);
  354. va_end(argList);
  355. }
  356. void log(list<int> l, LogTarget target) {
  357. void (*logFn)(const char *fmt, ...) = target == LogTarget_stdout ? &logStdout : &logErr;
  358. logFn("{ ");
  359. for (size_t i = 0; i < l.length; i++) {
  360. if (i != 0) {
  361. logFn(", ");
  362. }
  363. logFn("%i", l.data[i]);
  364. }
  365. logFn(" } length: %zu, head: %zu\n", l.length, l.head);
  366. }
  367. void log(list<string> l, LogTarget target) {
  368. void (*logFn)(const char *fmt, ...) = target == LogTarget_stdout ? &logStdout : &logErr;
  369. logFn("{ ");
  370. for (size_t i = 0; i < l.length; i++) {
  371. if (i != 0) {
  372. logFn(", ");
  373. }
  374. logFn("\"%S\"", l.data[i]);
  375. }
  376. logFn(" } length: %zu, head: %zu\n", l.length, l.head);
  377. }
  378. int intCompare(const void *a, const void *b) {
  379. int *x = (int *)a;
  380. int *y = (int *)b;
  381. return (*x > *y) - (*x < *y);
  382. }