jrk.h (19999B)
1 /* 2 * NOTES: 3 * - i think i've finally landed on dynamic array api 4 * that i like. 5 * 6 * TODO: 7 * - look at at the jrk_sv_chop_delim_loop stuff. there must 8 * must be a better way of handling things. 9 * 10 */ 11 12 #include <stdbool.h> 13 #include <stdint.h> 14 15 typedef int8_t i8; 16 typedef int16_t i16; 17 typedef int32_t i32; 18 typedef int64_t i64; 19 20 typedef uint8_t u8; 21 typedef uint16_t u16; 22 typedef uint32_t u32; 23 typedef uint64_t u64; 24 25 typedef float f32; 26 typedef double f64; 27 28 #define JRK_UNUSED(x) (void)x 29 #define JRK_ARRLENGTH(arr) (sizeof(arr) / sizeof(arr[0])) 30 31 #define jrk_return_defer(value) \ 32 do { result = value; goto defer; } while(0) 33 34 #define JRK_KILOBYTES(x) ((u64)x*1024) 35 #define JRK_MEGABYTES(x) ((u64)JRK_KILOBYTES((u64)x*1024)) 36 #define JRK_GIGABYTES(x) ((u64)JRK_MEGABYTES((u64)x*1024)) 37 #define JRK_TERABYTES(x) ((u64)JRK_GIGABYTES((u64)x*1024)) 38 39 #define JRK_TMPSTRINGS_ARR_CAPACITY 4 40 #define JRK_TMPSTRINGS_STR_CAPACITY JRK_KILOBYTES(1) 41 42 typedef struct { 43 u8 *data; 44 u64 offset; 45 u64 prev_offset; 46 u64 capacity; 47 } jrk_Arena; 48 49 typedef struct { 50 char *data; 51 u64 size; 52 } jrk_StringView; 53 54 void *jrk_ecalloc(u64, u64); 55 void *jrk_erealloc(void*, u64); 56 57 void *jrk_array_alloc_function_arena(u64, u64, void*); 58 void *jrk_array_realloc_function_arena(void*, u64, u64, void*); 59 60 jrk_Arena jrk_arena_create(u8*, u64); 61 void *jrk_arena_push(jrk_Arena*, u64); 62 char *jrk_arena_push_strf(jrk_Arena*, char*, ...); 63 void jrk_arena_reset(jrk_Arena*); 64 void *jrk_arena_resize(jrk_Arena*, void*, u64, u64); 65 66 i32 jrk_rand_num(i32); 67 i32 jrk_rand_num_range(i32, i32); 68 69 i32 jrk_fd_open_read(char*); 70 i32 jrk_fd_open_write(char*); 71 i32 jrk_fd_open_write_append(char*); 72 bool jrk_fd_size(i32, u64*); 73 void jrk_fd_close(i32); 74 75 jrk_StringView jrk_sv_from_parts(char*, u64); 76 jrk_StringView jrk_sv_trim_right(jrk_StringView); 77 jrk_StringView jrk_sv_trim_left(jrk_StringView); 78 jrk_StringView jrk_sv_trim(jrk_StringView); 79 jrk_StringView jrk_sv_from_cstr(char*); 80 jrk_StringView jrk_sv_chop_delim(jrk_StringView*, char delim); 81 82 char *jrk_tmpstrings_push(char*); 83 char *jrk_tmpstrings_pushf(char*, ...); 84 85 /* XXX: im not thrilled with this api, the memory can get messy real fast */ 86 #define jrk_sv_chop_delim_loop(sv, it, delim) \ 87 for (jrk_StringView it = jrk_sv_chop_delim(sv, delim); it.size != 0; it = jrk_sv_chop_delim(sv, delim)) 88 89 #ifndef jrk_die 90 #define jrk_die(x) \ 91 do { \ 92 fprintf(stderr, "%s:%d: error: "x" \n", __FILE__, __LINE__); \ 93 exit(69); \ 94 } while (0) 95 #endif 96 97 #ifndef jrk_diev 98 #define jrk_diev(x, ...) \ 99 do { \ 100 fprintf(stderr, "%s:%d: error: "x"\n", __FILE__, __LINE__, __VA_ARGS__); \ 101 exit(69); \ 102 } while (0) 103 #endif 104 105 #define jrk_edie(x) jrk_diev(x": %s", strerror(errno)) 106 #define jrk_ediev(x, ...) jrk_diev(x": %s", __VA_ARGS__, strerror(errno)) 107 108 #ifndef jrk_log 109 #define jrk_log(x) \ 110 do { \ 111 fprintf(stderr, "info: "x"\n"); \ 112 } while (0) 113 #endif 114 115 #ifndef jrk_logv 116 #define jrk_logv(x, ...) \ 117 do { \ 118 fprintf(stderr, "info: "x"\n", __VA_ARGS__); \ 119 } while (0) 120 #endif 121 122 #ifndef jrk_elog 123 #define jrk_elog(x) jrk_log(x": %s", strerror(errno)) 124 #endif 125 126 #ifndef jrk_elogv 127 #define jrk_elogv(x, ...) jrk_logv(x": %s", __VA_ARGS__, strerror(errno)) 128 #endif 129 130 #ifndef jrk_error 131 #define jrk_error(x) \ 132 do { \ 133 fprintf(stderr, "error: "x"\n"); \ 134 } while (0) 135 #endif 136 137 #ifndef jrk_errorv 138 #define jrk_errorv(x, ...) \ 139 do { \ 140 fprintf(stderr, "error: "x"\n", __VA_ARGS__); \ 141 } while (0) 142 #endif 143 144 #ifndef jrk_eerror 145 #define jrk_eerror(x) jrk_errorv(x": %s", strerror(errno)) 146 #endif 147 148 #ifndef jrk_eerrorv 149 #define jrk_eerrorv(x, ...) jrk_errorv(x": %s", __VA_ARGS__, strerror(errno)) 150 #endif 151 152 #define jrk_assert(c, msg) do { if (!(c)) jrk_die("jrk_assert: "msg); } while(0) 153 #define jrk_assertv(c, msg, ...) do { if (!(c)) jrk_diev("jrk_assert: "msg, __VA_ARGS__); } while(0) 154 155 #define jrk_shift(x, n) ((n)--, *(x)++) 156 #define jrk_shift_loop(x, n, it) for (char *it = jrk_shift(x, n); n >= 0; it = jrk_shift(x, n)) 157 158 #define jrk_emalloc(n) jrk_ecalloc(1, n) 159 160 #define JRK_ARRAY_DEFAULT_INIT_CAPACITY 16 161 162 #ifndef JRK_ARRAY_DEFAULT_ALLOC_FN 163 #define JRK_ARRAY_DEFAULT_ALLOC_FN jrk_ecalloc 164 #endif 165 166 #ifndef JRK_ARRAY_DEFAULT_REALLOC_FN 167 #define JRK_ARRAY_DEFAULT_REALLOC_FN jrk_erealloc 168 #endif 169 170 #ifndef JRK_ARRAY_DEFAULT_FREE_FN 171 #define JRK_ARRAY_DEFAULT_FREE_FN free 172 #endif 173 174 typedef void *(*jrk_array_alloc_function_t) (u64, u64, void*); 175 typedef void *(*jrk_array_realloc_function_t) (void*, u64, u64, void*); 176 177 #define __jrk_array_alloc(arr, count, size) (arr)->allocfn ? (arr)->allocfn((count), (size), (arr)->allocfn_user) : JRK_ARRAY_DEFAULT_ALLOC_FN((count), (size)) 178 #define __jrk_array_realloc(arr, _size) (arr)->reallocfn ? (arr)->reallocfn((arr)->items, (arr)->size * sizeof((arr)->items[0]), (_size), (arr)->allocfn_user) : JRK_ARRAY_DEFAULT_REALLOC_FN((arr)->items, (_size)) 179 180 #define jrk_array_prototype(type) \ 181 typedef struct { \ 182 type *items; \ 183 u64 size; \ 184 u64 capacity; \ 185 jrk_array_alloc_function_t allocfn; \ 186 jrk_array_realloc_function_t reallocfn; \ 187 void *allocfn_user; \ 188 } jrk_Array_##type; \ 189 \ 190 bool jrk_array_##type##_init_ex(jrk_Array_##type*, u64, jrk_array_alloc_function_t, jrk_array_realloc_function_t, void*); \ 191 bool jrk_array_##type##_init(jrk_Array_##type*, u64); \ 192 void jrk_array_##type##_deinit(jrk_Array_##type*); \ 193 bool jrk_array_##type##_setcap(jrk_Array_##type*, u64); \ 194 bool jrk_array_##type##_push(jrk_Array_##type*, type); \ 195 bool jrk_array_##type##_pushn(jrk_Array_##type*, type*, u64) 196 197 #define jrk_array_impl(type) \ 198 bool jrk_array_##type##_init_ex(jrk_Array_##type *arr, u64 capacity, jrk_array_alloc_function_t allocfn, jrk_array_realloc_function_t reallocfn, void *allocfn_user) \ 199 { \ 200 (arr)->allocfn = (allocfn) ? (allocfn) : NULL; \ 201 (arr)->reallocfn = (reallocfn) ? (reallocfn) : NULL; \ 202 (arr)->allocfn_user = (allocfn_user) ? (allocfn_user) : NULL; \ 203 (arr)->size = 0; \ 204 (arr)->capacity = (capacity); \ 205 (arr)->items = __jrk_array_alloc((arr), (arr)->capacity, sizeof(type)); \ 206 if (!(arr)->items) return false; \ 207 memset((arr)->items, 0, (arr)->capacity * sizeof(type)); \ 208 return true; \ 209 } \ 210 \ 211 bool jrk_array_##type##_init(jrk_Array_##type *arr, u64 capacity) \ 212 { \ 213 return jrk_array_##type##_init_ex(arr, capacity, NULL, NULL, NULL); \ 214 }\ 215 \ 216 void jrk_array_##type##_deinit(jrk_Array_##type *arr) \ 217 { \ 218 if ((arr)->items && !(arr)->allocfn) \ 219 JRK_ARRAY_DEFAULT_FREE_FN((arr)->items); \ 220 } \ 221 \ 222 bool jrk_array_##type##_setcap(jrk_Array_##type *arr, u64 new_capacity) \ 223 { \ 224 if (new_capacity < (arr)->capacity) return false; \ 225 (arr)->items = __jrk_array_realloc((arr), new_capacity * sizeof(type)); \ 226 if (!(arr)->items) return false; \ 227 memset((arr)->items + (arr)->size, 0, (new_capacity * sizeof(type)) - ((arr)->capacity * sizeof(type))); \ 228 (arr)->capacity = new_capacity; \ 229 return true; \ 230 } \ 231 \ 232 bool jrk_array_##type##_push(jrk_Array_##type *arr, type val) \ 233 { \ 234 if ((arr)->size + 1 > (arr)->capacity) { \ 235 while ((arr)->size + 1 > ((arr)->capacity)) \ 236 (arr)->capacity = (arr->capacity) ? (arr)->capacity * 2 : JRK_ARRAY_DEFAULT_INIT_CAPACITY; \ 237 (arr)->items = __jrk_array_realloc((arr), (arr)->capacity * sizeof(type)); \ 238 if (!(arr)->items) return false; \ 239 } \ 240 (arr)->items[(arr)->size++] = (val); \ 241 return true; \ 242 } \ 243 \ 244 bool jrk_array_##type##_pushn(jrk_Array_##type *arr, type *vals, u64 count) \ 245 { \ 246 if ((arr)->size + count > (arr)->capacity) { \ 247 while ((arr)->size + count > ((arr)->capacity)) \ 248 (arr)->capacity = (arr->capacity) ? (arr)->capacity * 2 : JRK_ARRAY_DEFAULT_INIT_CAPACITY; \ 249 (arr)->items = __jrk_array_realloc((arr), (arr)->capacity * sizeof(type)); \ 250 if (!(arr)->items) return false; \ 251 memset((arr)->items + (arr)->size, 0, count * sizeof(type)); \ 252 }\ 253 memcpy(&(arr)->items[(arr)->size], (vals), sizeof(type) * (count)); \ 254 (arr)->size += count; \ 255 return true; \ 256 } 257 258 #define jrk_array_foreach(type, it, arr) for (type *it = (arr)->items; it < (arr)->items + (arr)->size; ++it) 259 260 jrk_array_prototype(char); 261 #define jrk_StringBuilder jrk_Array_char 262 263 #define jrk_sb_append_null(sb) jrk_array_char_push((sb), 0) 264 #define jrk_sb_append_cstr(sb, str) jrk_sb_appendf((sb), (str)) 265 #define jrk_sb_append_buf(sb, buf, bufsz) jrk_array_char_pushn((sb), (buf), (bufsz)) 266 #define jrk_sb_init_ex(sb, size, allocfn, reallocfn, userarg) jrk_array_char_init_ex((sb), (size), (allocfn), (reallocfn), (userarg)) 267 #define jrk_sb_init_arena(sb, size, arena) jrk_sb_init_ex((sb), (size), jrk_array_alloc_function_arena, jrk_array_realloc_function_arena, (void *)(arena)) 268 #define jrk_sb_deinit(sb) jrk_array_char_deinit((sb)) 269 #define jrk_sb_to_sv(sb) jrk_sv_from_parts((sb).items, (sb).size) 270 271 bool jrk_sb_appendf(jrk_StringBuilder*, char*, ...); 272 bool jrk_sb_append_buf_at(jrk_StringBuilder*, char*, u64, u64); 273 bool jrk_sb_fd_write(jrk_StringBuilder*, i32); 274 bool jrk_sb_write_entire_file(jrk_StringBuilder *, char *); 275 bool jrk_sb_fd_read_all(jrk_StringBuilder*, i32); 276 bool jrk_sb_read_entire_file(jrk_StringBuilder*, char*); 277 278 #ifdef JRK_IMPLEMENTATION 279 #include <ctype.h> 280 #include <errno.h> 281 #include <fcntl.h> 282 #include <stdarg.h> 283 #include <stdio.h> 284 #include <stdlib.h> 285 #include <string.h> 286 #include <sys/stat.h> 287 #include <unistd.h> 288 289 jrk_array_impl(char) 290 291 void * 292 jrk_array_alloc_function_arena(u64 size, u64 count, void *user) 293 { 294 void *result = NULL; 295 jrk_Arena *arena = (jrk_Arena *) user; 296 result = jrk_arena_push(arena, size * count); 297 return result; 298 } 299 300 void * 301 jrk_array_realloc_function_arena(void *ptr, u64 old_size, u64 new_size, void *user) 302 { 303 void *result = NULL; 304 jrk_Arena *arena = (jrk_Arena *) user; 305 result = jrk_arena_resize(arena, ptr, old_size, new_size); 306 return result; 307 } 308 309 bool 310 jrk_sb_appendf(jrk_StringBuilder *sb, char *fmt, ...) 311 { 312 char buf[JRK_KILOBYTES(1)]; 313 va_list args; 314 va_start(args, fmt); 315 316 i32 buf_sz = vsnprintf(buf, sizeof(buf), fmt, args); 317 if (buf_sz < 0) { 318 jrk_eerrorv("jrk_sb_appendf(%p, %s): failed to create full string from '%s'", (void *) sb, fmt, fmt); 319 return false; 320 } 321 va_end(args); 322 323 i32 actual_sz = 0; 324 if ((u32) buf_sz > JRK_ARRLENGTH(buf)) { 325 actual_sz = JRK_ARRLENGTH(buf); 326 jrk_errorv("jrk_sb_appendf(%p, %s): pushing '%s' into sb caused truncation of %ld bytes", 327 (void *) sb, fmt, fmt, buf_sz - JRK_ARRLENGTH(buf)); 328 return false; 329 } else { 330 actual_sz = buf_sz; 331 } 332 333 if (!jrk_array_char_pushn(sb, buf, actual_sz)) { 334 jrk_errorv("jrk_sb_appendf(%p, %s): failed to push '%s' into sb", (void *) sb, fmt, fmt); 335 return false; 336 } 337 338 return true; 339 } 340 341 bool 342 jrk_sb_append_buf_at(jrk_StringBuilder *sb, char *buf, u64 buf_sz, u64 idx) 343 { 344 if (idx > sb->size) { 345 jrk_errorv("jrk_sb_append_buf_at(%p, %s, %ld, %ld): idx is greater than sb.size", 346 (void *)sb, buf, buf_sz, idx); 347 return false; 348 } 349 350 if (sb->size + (buf_sz) > sb->capacity) { 351 while (sb->size + (buf_sz) > sb->capacity) { 352 sb->capacity *= 2; 353 } 354 sb->items = __jrk_array_realloc(sb, sb->capacity); 355 if (!sb->items) return false; 356 memset(sb->items + sb->size, 0, sb->capacity - sb->size); 357 } 358 359 memmove(sb->items + idx + buf_sz, sb->items + idx, sb->size - idx); 360 memcpy(sb->items + idx, buf, buf_sz); 361 362 sb->size += buf_sz; 363 return true; 364 } 365 366 bool 367 jrk_sb_fd_read_all(jrk_StringBuilder *sb, i32 fd) 368 { 369 bool result = true; 370 u64 filesize = 0; 371 if (!jrk_fd_size(fd, &filesize)) jrk_return_defer(false); 372 char *buf = jrk_emalloc(filesize); 373 if (read(fd, buf, filesize) < 0) { 374 jrk_eerrorv("jrk_sb_fd_read_all(%p, %d)", (void *)sb, fd); 375 jrk_return_defer(false); 376 } 377 378 if (!jrk_sb_append_buf(sb, buf, filesize)) jrk_return_defer(false); 379 defer: 380 free(buf); 381 return result; 382 } 383 384 bool 385 jrk_sb_fd_write(jrk_StringBuilder *sb, i32 fd) 386 { 387 i64 result; 388 result = write(fd, (void *) sb->items, sb->size); 389 if (result < 0) { 390 jrk_eerrorv("jrk_sb_fd_write_all(%p, %d)", (void *)sb, fd); 391 return -1; 392 } 393 394 return result; 395 } 396 397 bool 398 jrk_sb_read_entire_file(jrk_StringBuilder *sb, char *filename) 399 { 400 bool result = true; 401 i32 fd = jrk_fd_open_read(filename); 402 if (fd < 0) return false; 403 if (!jrk_sb_fd_read_all(sb, fd)) jrk_return_defer(false); 404 405 defer: 406 jrk_fd_close(fd); 407 return result; 408 } 409 410 bool 411 jrk_sb_write_entire_file(jrk_StringBuilder *sb, char *filename) 412 { 413 bool result = true; 414 i32 fd = jrk_fd_open_write(filename); 415 if (fd < 0) return false; 416 if(!jrk_sb_fd_write(sb, fd)) jrk_return_defer(false); 417 418 defer: 419 jrk_fd_close(fd); 420 return result; 421 } 422 423 void * 424 jrk_ecalloc(u64 nmemb, u64 size) 425 { 426 void *p; 427 428 if (!(p = calloc(nmemb, size))) 429 jrk_ediev("jrk_ecalloc(%ld, %ld): buy more ram lol", nmemb, size); 430 return p; 431 } 432 433 void * 434 jrk_erealloc(void *ptr, u64 size) 435 { 436 void *p; 437 438 if (!(p = realloc(ptr, size))) 439 jrk_ediev("jrk_erealloc(%p, %ld): buy more ram lol", ptr, size); 440 return p; 441 } 442 443 // NOTE: only allocate space for translation units with JRK_IMPLEMENTATION 444 static char jrk__tmpstrings[JRK_TMPSTRINGS_ARR_CAPACITY][JRK_TMPSTRINGS_STR_CAPACITY]; 445 static u32 jrk__tmpstrings_idx = 0; 446 447 char * 448 jrk_tmpstrings_push(char *str) 449 { 450 char *result; 451 result = jrk_tmpstrings_pushf(str); 452 return result; 453 } 454 455 char * 456 jrk_tmpstrings_pushf(char *fmt, ...) 457 { 458 char *result = jrk__tmpstrings[jrk__tmpstrings_idx]; 459 460 va_list args; 461 va_start(args, fmt); 462 vsnprintf(result, JRK_TMPSTRINGS_STR_CAPACITY, fmt, args); 463 va_end(args); 464 465 if (++jrk__tmpstrings_idx >= JRK_TMPSTRINGS_ARR_CAPACITY) 466 jrk__tmpstrings_idx = 0; 467 468 return result; 469 } 470 471 jrk_Arena 472 jrk_arena_create(u8 *buffer, u64 buffer_count) 473 { 474 jrk_Arena result = {0}; 475 result.data = buffer; 476 result.capacity = buffer_count; 477 result.offset = 0; 478 result.prev_offset = 0; 479 return result; 480 } 481 482 void * 483 jrk_arena_push(jrk_Arena *arena, u64 n) 484 { 485 if (arena->offset + n > arena->capacity) { 486 jrk_errorv("jrk_arena_push(%p, %ld): arena push requires %ld bytes but has a capacity of %ld bytes", 487 (void *) arena, n, arena->offset + n, arena->capacity); 488 return NULL; 489 } 490 491 void *result = &arena->data[arena->offset]; 492 arena->prev_offset = arena->offset; 493 arena->offset += n; 494 memset(result, 0, n); 495 496 return result; 497 } 498 499 char * 500 jrk_arena_push_strf(jrk_Arena *arena, char *fmt, ...) 501 { 502 char *result = NULL; 503 504 va_list args; 505 va_start(args, fmt); 506 i32 n = vsnprintf(NULL, 0, fmt, args); 507 va_end(args); 508 509 result = jrk_arena_push(arena, (u64) n + 1); 510 if (!result) return NULL; 511 512 va_start(args, fmt); 513 vsnprintf(result, n + 1, fmt, args); 514 va_end(args); 515 516 return result; 517 } 518 519 void * 520 jrk_arena_resize(jrk_Arena *arena, void *old, u64 old_size, u64 new_size) 521 { 522 u8 *result = NULL; 523 524 if (new_size < old_size) { 525 jrk_errorv("jrk_arena_resize(%p, %p, %ld, %ld): new_size is smaller than the old_size", 526 (void *) arena, old, old_size, new_size); 527 return result; 528 } 529 530 if (arena->offset + (new_size - old_size) > arena->capacity) { 531 jrk_errorv("jrk_arena_resize(%p, %p, %ld, %ld): arena resize requires %ld bytes but has a capacity of %ld bytes", 532 (void *) arena, old, old_size, new_size, arena->offset + (new_size - old_size), arena->capacity); 533 return result; 534 } 535 536 if (old == &arena->data[arena->prev_offset]) { 537 result = old; 538 arena->prev_offset = arena->offset; 539 arena->offset += new_size; 540 memset(&arena->data[arena->prev_offset], 0, new_size - old_size); 541 } else { 542 result = &arena->data[arena->offset]; 543 arena->prev_offset = arena->offset; 544 arena->offset += new_size; 545 if (arena->offset > arena->capacity) { 546 jrk_errorv("jrk_arena_resize(%p, %p, %ld, %ld): arena resize requires %ld bytes but has a capacity of %ld bytes", 547 (void *) arena, old, old_size, new_size, arena->offset, arena->capacity); 548 return NULL; 549 } 550 memmove(result, old, old_size); 551 memset(result + old_size, 0, new_size - old_size); 552 } 553 554 return (void *) result; 555 } 556 557 void 558 jrk_arena_reset(jrk_Arena *arena) 559 { 560 arena->offset = 0; 561 arena->prev_offset = 0; 562 memset(arena->data, 0, arena->capacity); 563 } 564 565 bool 566 jrk_fd_size(i32 fd, u64 *size) 567 { 568 if (!size) { 569 jrk_errorv("jrk_fd_size(%d, %p): size ptr is NULL", fd, (void *) size); 570 return false; 571 } 572 573 struct stat statbuf = {0}; 574 if (fstat(fd, &statbuf) < 0) { 575 jrk_eerrorv("jrk_fd_size(%d, %p)", fd, (void *) size); 576 return false; 577 } 578 579 *size = statbuf.st_size; 580 return true; 581 } 582 583 void 584 jrk_fd_close(i32 fd) 585 { 586 close(fd); 587 } 588 589 i32 590 jrk_fd_open_read(char *path) 591 { 592 i32 result = open(path, O_RDONLY); 593 594 if (result < 0) { 595 jrk_eerrorv("jrk_fd_open_read(%s)", path); 596 return -1; 597 } 598 599 return result; 600 } 601 602 i32 603 jrk_fd_open_write(char *path) 604 { 605 i32 result = open(path, 606 O_WRONLY | O_CREAT | O_TRUNC, 607 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); 608 609 if (result < 0) { 610 jrk_eerrorv("jrk_fd_open_write(%s)", path); 611 return -1; 612 } 613 614 return result; 615 } 616 617 i32 618 jrk_fd_open_write_append(char *path) 619 { 620 i32 result = open(path, 621 O_WRONLY | O_CREAT | O_APPEND, 622 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); 623 624 if (result < 0) { 625 jrk_eerrorv("jrk_fd_open_write_append(%s)", path); 626 return -1; 627 } 628 629 return result; 630 } 631 632 jrk_StringView 633 jrk_sv_from_parts(char *data, u64 size) 634 { 635 jrk_StringView result = {0}; 636 result.data = data; 637 result.size = size; 638 return result; 639 } 640 641 jrk_StringView 642 jrk_sv_from_cstr(char *data) 643 { 644 jrk_StringView result = {0}; 645 result.data = data; 646 result.size = strlen(data); 647 return result; 648 } 649 650 jrk_StringView 651 jrk_sv_trim_right(jrk_StringView sv) 652 { 653 u64 i = 0; 654 for (; i < sv.size && isspace(sv.data[sv.size - 1 - i]); ++i); 655 return jrk_sv_from_parts(sv.data, sv.size - i); 656 } 657 658 jrk_StringView 659 jrk_sv_trim_left(jrk_StringView sv) 660 { 661 u64 i = 0; 662 for (; i < sv.size && isspace(sv.data[i]); ++i); 663 return jrk_sv_from_parts(sv.data + i, sv.size - i); 664 } 665 666 jrk_StringView 667 jrk_sv_trim(jrk_StringView sv) 668 { 669 return jrk_sv_trim_right(jrk_sv_trim_left(sv)); 670 } 671 672 jrk_StringView 673 jrk_sv_chop_delim(jrk_StringView *sv, char delim) 674 { 675 u64 i = 0; 676 while (i < sv->size && sv->data[i] != delim) 677 ++i; 678 679 jrk_StringView result = jrk_sv_from_parts(sv->data, i); 680 681 if (i < sv->size) { 682 sv->data += i + 1; 683 sv->size -= i + 1; 684 } else { 685 sv->data += i; 686 sv->size -= i; 687 } 688 689 return result; 690 } 691 692 i32 693 jrk_rand_num(i32 upbound) 694 { 695 return rand() % upbound + 1; 696 } 697 698 i32 699 jrk_rand_num_range(i32 min, i32 max) 700 { 701 return rand() % (max - min + 1) + min; 702 } 703 704 #endif // JRK_IMPLEMENTATION
