203 Commits

Author SHA1 Message Date
9f32891bbc Add test for str8 array 2025-09-28 00:05:17 +01:00
b3ebff3635 Remove ABS_INSTALL_PREFIX 2025-09-20 15:43:36 +01:00
14bd6ce5fd File utilities and datatype implementation for a C-based code generator (#5)
Co-authored-by: Abdelrahman Said <said.abdelrahman@flawlessai.com>
Reviewed-on: #5
Co-authored-by: Abdelrahman <said.abdelrahman89@gmail.com>
Co-committed-by: Abdelrahman <said.abdelrahman89@gmail.com>
2025-09-20 13:48:08 +00:00
09e96f8112 Update Makefile 2025-09-06 21:27:17 +01:00
Abdelrahman Said
9cbd0b29ef Fix build on macOS 2025-09-01 22:10:41 +01:00
26fd329caa Update codegen to support accepting JSON file as input 2025-08-31 20:56:49 +01:00
1e224702a3 Add default target as one of the available targets when make help is run 2025-08-31 14:21:55 +01:00
74cca183e0 Make all the default target 2025-08-31 14:20:44 +01:00
e26bf613a5 Add support for release builds with debug info and using lib externally 2025-08-31 14:17:04 +01:00
Abdelrahman Said
81e3ab2c67 Switch to using intercept build since OSX [SIP](https://en.wikipedia.org/wiki/System_Integrity_Protection) stop bear from working 2025-08-16 13:25:38 +01:00
Abdelrahman Said
8ec0757b34 Add .venv to gitignore 2025-08-16 13:25:28 +01:00
Abdelrahman Said
eb98de7c2b Unify build flags 2025-08-16 13:16:21 +01:00
d3fccd61b5 Reintroduce C++ support and add usage tests for C++ (#4)
Reviewed-on: #4
Co-authored-by: Abdelrahman <said.abdelrahman89@gmail.com>
Co-committed-by: Abdelrahman <said.abdelrahman89@gmail.com>
2025-08-10 22:33:40 +00:00
011083ab83 Replace bool, true and false with aliases 2025-08-09 22:38:03 +01:00
b8c548ee4b Add static, runtime and debug assert utilities 2025-08-09 22:37:55 +01:00
75be2316e0 Add vim encoding and folding marker 2025-08-09 14:35:28 +01:00
Abdelrahman Said
d452225d02 Don't use uchar.h on macos 2025-05-20 16:52:12 +01:00
74164717d0 Fix bug in array codegen 2025-05-05 19:15:58 +01:00
6c8434a530 Use asserts in array 2025-05-05 20:06:58 +01:00
cac66b9dbb Use asserts in dbl_list 2025-05-05 19:55:42 +01:00
175f627f93 Remove text from asserts 2025-05-05 19:29:44 +01:00
be30189d15 Assert uuid argument isn't NULL 2025-05-05 19:12:13 +01:00
3689c17d09 Use asserts to validate arguments for Str8 2025-05-05 19:08:44 +01:00
8e952d9bc8 Use assert to validate inputs to allocator functions 2025-05-05 19:01:10 +01:00
def7576101 Use asserts in arena 2025-05-05 18:57:11 +01:00
3fed536a74 Use assert in wapp_mem_util_align_forward instead of returning NULL 2025-05-05 18:51:10 +01:00
aae39fe656 Fix MSVC errors 2025-05-05 16:41:56 +01:00
4e3945d1d0 Refactor array to avoid having to include external types 2025-05-05 16:33:08 +01:00
98a802e3eb Remove C++ pseudo support 2025-05-05 02:48:35 +01:00
0d4aa7a9c2 Modify README.md 2025-05-05 02:28:29 +01:00
a229f9be8c Run codegen on Linux 2025-05-05 00:04:24 +01:00
2156d2ff3a Fix MSVC Spectre warnings 2025-05-04 23:59:50 +01:00
12f083edb0 Add code generation for array 2025-05-04 23:26:03 +01:00
f444911452 Refactor strings and allocator to primitives 2025-05-04 23:25:27 +01:00
163283f77f Remove unnecessary separate handling for bool type 2025-05-04 22:20:38 +01:00
6064ed346c Ensure arena capacity is a power of 2 2025-05-04 18:02:32 +01:00
77f3c40ebd Add copy array with allocation and finish writing array tests 2025-04-27 19:30:14 +01:00
d3f1686d58 Add testing for i32 array to test array logic 2025-04-21 17:47:33 +01:00
a359331df7 Complete array implementation before moving it to codegen 2025-04-21 17:46:59 +01:00
14115f7e7e Move rounding up and va_args count to misc_utils 2025-04-21 17:46:27 +01:00
12bd3eb489 Add .clangd config file 2025-04-21 14:21:40 +01:00
266d43e262 Update Makefile 2025-04-21 14:16:54 +01:00
a568b30163 Update snippets 2025-04-21 13:52:24 +01:00
b1773746d8 Add missing include 2025-04-21 13:45:29 +01:00
a479a43f4c Reformat 2025-04-20 21:32:38 +01:00
b476ceaeef Fix MSVC Spectre warnings 2025-04-20 20:28:02 +01:00
4d69b97149 Add /std:c11 to Windows build 2025-04-20 20:20:39 +01:00
181c4b8614 Update xorshift 2025-04-20 20:47:20 +01:00
0d541f6ee8 Add aliases.h and platform.h by default in codegen 2025-04-20 20:10:10 +01:00
9e34b37d8d Update codegen with WAPP_PLATFORM_CPP 2025-04-20 19:57:57 +01:00
b884d0e6a6 Switch to using WAPP_PLATFORM_CPP instead of __cplusplus 2025-04-20 19:52:33 +01:00
494bbeb398 Update platform cracking 2025-04-20 19:42:45 +01:00
7605eb4e57 Add C and CPP version macros 2025-04-20 19:39:16 +01:00
037b0fe698 Enforce C11 with GNU extensions on POSIX platforms 2025-04-20 18:28:17 +01:00
b13274cd81 Add compiler detection macros 2025-04-20 18:27:57 +01:00
4f9f632362 Update windows build script 2025-04-20 17:28:38 +01:00
6b039aeac0 Use posix path separator for codegen even on Windows 2025-04-20 16:47:11 +01:00
2ab3bfc2e1 Fix wrong include 2025-04-20 16:46:31 +01:00
bf99bef291 Support multiple python versions for code generation 2025-04-20 16:23:23 +01:00
50e23d8a13 Testing ideas for array implementation 2025-04-20 00:21:22 +01:00
3a49dba366 Generate dbl_list for default C types 2025-04-19 22:17:26 +01:00
1cfc52b35e Handle pointer types properly in dbl_list codegen 2025-04-19 21:27:00 +01:00
25395553d7 Fix codegen hidden bugs 2025-04-19 21:11:10 +01:00
9a651665ba Remove forward declaration from dbl_list source 2025-04-19 20:56:15 +01:00
8dbdfa2094 Update dbl_list codegen 2025-04-19 20:54:04 +01:00
add2ba541d Merge branch 'codegen' 2025-04-19 13:52:27 +01:00
63ed2633ea Update code generation to create one file for dbl_list 2025-04-19 13:33:09 +01:00
Abdelrahman Said
3c32b247c0 Upgrade codegen 2025-04-17 09:03:30 +01:00
Abdelrahman Said
aa04fab6ea Update codegen 2025-04-16 10:05:42 +01:00
Abdelrahman Said
2017f6de79 Start updating code for new Str8List 2025-04-16 08:14:02 +01:00
Abdelrahman Said
63acdd1336 Fix codegen bugs 2025-04-16 08:13:31 +01:00
Abdelrahman Said
cfa8094260 Fix codegen hidden bugs 2025-04-16 08:06:05 +01:00
Abdelrahman Said
31373eba03 Update dbl_list functionality 2025-04-16 00:42:20 +01:00
Abdelrahman Said
778a4da092 Add utility to create list node from item 2025-04-16 00:27:01 +01:00
Abdelrahman Said
6fb078a868 Remove codegen and implement dbl_list as generic container 2025-04-16 00:07:11 +01:00
0942643b4e Update Makefile 2025-04-13 22:21:55 +01:00
Abdelrahman Said
0e5942af34 Switch to using Makefile for *nix systems 2025-04-13 20:11:05 +01:00
Abdelrahman Said
c83c652b37 Add UUIDv4 generator 2025-03-22 02:27:59 +00:00
Abdelrahman Said
74428f1caf Rename xorshift functions 2025-03-22 00:30:20 +00:00
Abdelrahman Said
d661312cfa Add xorshift prng 2025-03-16 22:34:56 +00:00
70e075d2f6 Add message at top of codegen files to avoid overwriting them 2025-03-02 13:42:23 +00:00
96db885344 Remove codegen as submodule and just add it in place 2025-03-02 13:28:26 +00:00
fb512e4a15 Add code generation for windows 2025-03-02 13:22:05 +00:00
9361f0fe37 Run code generation for posix platforms 2025-03-02 13:20:51 +00:00
e7d2553400 Add code generation for doubly linked list 2025-03-02 13:20:27 +00:00
509724cc31 Update .gitignore 2025-03-02 13:17:50 +00:00
Abdelrahman Said
82c23eed5e Use the wapp.h header in tests 2025-02-24 08:52:46 +00:00
Abdelrahman Said
9403193f09 Update build scripts 2025-02-24 07:58:42 +00:00
Abdelrahman Said
fa1d9eec0d Fix files not using relative includes 2025-02-24 07:58:22 +00:00
Abdelrahman Said
4c14588d92 Update core headers and sources to use relative includes 2025-02-24 07:51:08 +00:00
Abdelrahman Said
9e66bd60bd Update testing headers to user relative includes 2025-02-24 07:24:26 +00:00
Abdelrahman Said
ce4957d0a0 Update common headers to user relative includes 2025-02-24 07:21:28 +00:00
b9ea290322 Update posix compile script 2025-02-24 00:30:48 +00:00
1479c13417 Move os layer to be part of the core 2025-02-24 00:30:25 +00:00
4520f2269d Reorganise memory utilities 2025-02-24 00:21:14 +00:00
6119cf5c5f Improve Str8 macros ergonomics 2025-02-23 23:53:28 +00:00
358f61e556 Reorder tests 2025-02-23 19:27:54 +00:00
7ac6100a5a Add platform detection to Windows build 2025-02-23 16:26:47 +00:00
19efb08a3a Add platform detection to posix compilation script 2025-02-23 15:32:13 +00:00
491c742189 Add single header and single source entries for all components as well as the full library (#2)
Reviewed-on: #2
Co-authored-by: Abdelrahman <said.abdelrahman89@gmail.com>
Co-committed-by: Abdelrahman <said.abdelrahman89@gmail.com>
2025-02-23 15:19:14 +00:00
4f5dd3900f Remove unused join_root_and_leaf 2025-02-22 22:11:51 +00:00
dbedcb3100 Replace char * with Str8 in cpath dirup 2025-02-22 22:09:04 +00:00
d9314fb41e Update slice and substr functions 2025-02-22 21:34:29 +00:00
fe2bb65b06 Fix spectre warning for MSVC 2025-02-22 18:04:05 +00:00
ed4ec54c7a Switch wapp_cpath_join_path to use Str8 2025-02-22 17:48:25 +00:00
ba5e902a1d Add wapp_str8_push_back and wapp_str8_list_empty 2025-02-22 17:48:04 +00:00
01f066d20c Add test for wapp_str8_format 2025-02-22 16:44:19 +00:00
80bd68f313 Add string formatting to Str8 2025-02-22 16:41:05 +00:00
cda7e413e2 Rename tester directory 2025-02-22 15:26:40 +00:00
54da75f89f Update comment for wapp_str8_lit_ro_initialiser_list 2025-02-22 15:03:13 +00:00
7df64a3168 Fix ASan linking error when compiling with gcc 2025-02-22 14:58:41 +00:00
f9f8f092b5 Fix compilation error in gcc 2025-02-22 14:58:19 +00:00
f89a4bf343 Add wapp_str8_lit_ro_initialiser_list to fix gcc compilation errors 2025-02-22 14:33:15 +00:00
0d795cc0d9 Update wapp_str8_alloc_buf to make a single big allocation 2025-02-22 13:54:03 +00:00
28ac9ed8c8 Modify Str8 substr functionality 2025-02-22 13:39:03 +00:00
99f7dcd794 Rename wapp_str8_buf_alloc to wapp_str8_alloc_buf 2025-02-18 21:02:02 +00:00
c5ca39939d Fix shell commander test on Windows 2025-02-16 22:44:42 +00:00
a308359942 Add wapp_str8_equal_to_count function 2025-02-16 22:44:18 +00:00
a3d9bcf1a1 Update .gitignore 2025-02-16 21:42:14 +00:00
Abdelrahman Said
a534d44db5 Reduce arena size in wapp_shell_commander_execute 2025-02-16 21:39:09 +00:00
11949e69be Update shell_commander to use Str8 instead of const char * 2025-02-16 21:31:22 +00:00
2c9e4c91a0 Add function to copy Str8 to C string buffer 2025-02-16 21:30:25 +00:00
76b078fbc0 Use str8_copy function in tester 2025-02-16 17:35:10 +00:00
0569fca193 Add str8_copy functions 2025-02-16 17:34:48 +00:00
6078e54087 Fix windows bugs 2025-02-16 17:09:40 +00:00
180425707b Use Str8 instead of const char * in termcolour functions 2025-02-16 16:32:52 +00:00
62dcfdaa93 Use Str8 instead of const char * in tester functions 2025-02-16 16:32:29 +00:00
19134d0e15 Address Windows Spectre mitigation warnings 2025-02-16 14:55:17 +00:00
ca2b1cbf23 Reformat 2025-02-16 14:53:29 +00:00
f60442bfcf Fix bug with arena allocation on Windows 2025-02-16 14:52:31 +00:00
a4a1e82c40 Add tests for str8 splitting, joining and concatenation 2025-02-15 23:45:37 +00:00
d50b41acac Add str8 split, rsplit, join, concat and concat_capped functions 2025-02-15 23:45:07 +00:00
71b6242f16 Update allocator free to take object size 2025-02-15 23:44:23 +00:00
241edfc7e4 Change Str8Node to use Str8 instead of Str8RO 2025-02-15 20:36:31 +00:00
d635e03cd8 Add tests for Str8List utilities 2025-02-15 20:29:50 +00:00
68fe421ab0 Add Str8List and str8 equality function 2025-02-15 20:29:15 +00:00
622a4391a0 Update compile script 2025-02-15 10:49:23 +00:00
ff4d3c9e99 Add tests for string allocation functions 2025-02-09 18:47:10 +00:00
023c74d8d9 Add functions to dynamically allocate strings 2025-02-09 18:46:32 +00:00
86fe867011 Reformat 2025-02-09 18:21:36 +00:00
98829b8400 Reformat 2025-02-09 18:19:27 +00:00
a7e98211f9 Update find and rfind tests 2025-02-09 16:41:29 +00:00
4642361969 Add tests for find and rfind 2025-02-09 16:35:42 +00:00
093d0daf6f Add find and rfine functions 2025-02-09 16:35:28 +00:00
f8e0804dd2 Fix unused variable error 2025-02-09 16:34:36 +00:00
fdb0650634 Add -Wextra flag for compilation 2025-02-09 16:34:12 +00:00
d1d6a8e64b Add utils for str8 printing 2025-02-09 15:13:50 +00:00
bbf38499ca Implement read-only string literals 2025-02-09 14:29:54 +00:00
7657ad1b58 Remove libc allocator 2025-02-01 21:39:27 +00:00
70399cb797 Change c16 and c32 defintions 2025-02-01 20:21:45 +00:00
76c3b02e45 Change char type to c8 in Str8 functions 2024-10-17 00:13:35 +01:00
abf9b09495 Implement test for wapp_str8_set 2024-10-17 00:08:08 +01:00
6d09059911 Change wapp_str8_lit implementation to support mutable string literals 2024-10-17 00:07:30 +01:00
894ae028b7 Add aliases for character data types 2024-10-17 00:06:56 +01:00
84a4ec223c Commit the Str8 tests 2024-10-08 23:58:24 +01:00
8f10ac2916 Add string buffer macro and tests for Str8 2024-10-08 23:57:55 +01:00
bfb4e87a1e Remove extra spaces in aliases.h 2024-10-08 22:45:48 +01:00
685682e1c8 revamp-strings (#1)
Co-authored-by: Abdelrahman Said <said.abdelrahman@flawlessai.com>
Reviewed-on: #1
Co-authored-by: Abdelrahman <said.abdelrahman89@gmail.com>
Co-committed-by: Abdelrahman <said.abdelrahman89@gmail.com>
2024-10-07 22:35:56 +00:00
40d301fd95 Reformat 2024-10-06 21:31:04 +01:00
7d8df816a5 Move cpath to os 2024-10-06 20:04:38 +01:00
17f0f0eaf3 Fix cpath tests on Windows 2024-10-06 19:54:34 +01:00
ce656a6275 Fix Spectre warnings for MSVC 2024-10-06 19:54:13 +01:00
8d8fcf9dc5 Improve early exit code in test_cpath 2024-10-06 19:33:13 +01:00
77e634ec2d Fix comment 2024-10-06 19:30:19 +01:00
22ece7215a Move path utils to os, fix bugs with it and write tests 2024-10-06 19:28:34 +01:00
4af4b39d6f Remove unnecessary clang-format comments 2024-10-06 12:59:21 +01:00
a48002996e Reorganise src directory 2024-10-06 12:54:04 +01:00
e9451f10f8 Reformat and increase minimum arena capacity to 4 pages 2024-10-06 12:42:12 +01:00
1de3608b1f Pass MemInitType to platform functions 2024-10-05 22:30:11 +01:00
3a25571105 Reformat 2024-10-05 23:18:23 +01:00
139b4ca589 Restore missing mem_utils code 2024-10-05 23:17:23 +01:00
e431cf729e Reformat 2024-10-05 23:15:03 +01:00
1d1c3ca928 Split the platform specific mem_utils implementations 2024-10-05 23:05:32 +01:00
f2f155744a Declare external functions for termcolour and commander in the headers 2024-10-05 23:04:35 +01:00
d3a86ec6cb Add extern alias 2024-10-05 23:03:19 +01:00
e053aa44ab Remove unnecessary termcolour header files 2024-10-05 22:28:24 +01:00
a546a09565 Split commander windows and posix implementations 2024-10-05 22:25:21 +01:00
12f182f0cf Define macros for C linkage 2024-10-05 22:06:13 +01:00
ffb99a3644 Fix MSVC errors and warnings 2024-10-05 20:07:48 +01:00
1ddc5610f9 Remove aligned_alloc from libc allocator since it's not implemented on Windows 2024-10-05 19:11:13 +01:00
d8c7b3162f Split termcolour implementations by platform and simplify the API 2024-10-05 18:46:14 +01:00
9e1e4688e4 Reformat 2024-10-05 18:45:32 +01:00
cd38672581 Add test for Arena's reallocation functionality 2024-09-14 17:28:07 +01:00
7fea236618 Implement reallocation functionality for Arena allocator 2024-09-14 17:27:33 +01:00
16a1b8fa35 Reformat 2024-09-14 14:49:18 +01:00
a0dfe8acd0 Start implementing realloc functions for Arena allocator 2024-09-14 13:39:59 +01:00
95c47ec940 Update libc allocator realloc function 2024-09-14 13:39:32 +01:00
46f32f2ba9 Update signature of realloc functions to expect old and new sizes 2024-09-14 13:38:55 +01:00
8f794dee15 Reformat 2024-09-07 20:54:49 +01:00
034b105ea1 Reformat 2024-09-07 20:53:20 +01:00
c90874ad10 Reformat 2024-09-07 20:49:13 +01:00
8468bb8e28 Reorganise allocators 2024-09-07 20:27:49 +01:00
d30eee0cf8 Add tests for Allocator implementations 2024-09-07 15:43:47 +01:00
59e56a75d3 Reimplement Allocator API for Arena 2024-09-07 15:43:25 +01:00
5d6ce1d2c3 Restore libc Allocator implementation 2024-09-07 15:43:00 +01:00
ce537b7494 Restore Allocator implementation 2024-09-07 15:42:36 +01:00
b8f6e5f187 Fix bug in memory allocation function 2024-08-24 19:07:00 +01:00
775f0864a8 Rename arena default allocation function 2024-08-23 22:29:56 +01:00
8b6fb23bac Use size utils in arena tests 2024-08-23 21:50:22 +01:00
1fb340561f Add size utils 2024-08-23 21:48:38 +01:00
8ed372d938 Ensure stderr is piped to stdout to capture errors in output 2024-06-17 00:18:27 +01:00
8a91a0ec6b Add tests for the shell commander 2024-06-17 00:15:10 +01:00
802b70f5ee Add option to discard command output 2024-06-17 00:14:34 +01:00
149 changed files with 18958 additions and 1174 deletions

2
.clangd Normal file
View File

@@ -0,0 +1,2 @@
CompileFlags:
Add: -ferror-limit=0

6
.gitignore vendored
View File

@@ -1,10 +1,14 @@
.cache
.vscode
.venv
test
test.*
*.dSYM
.DS_Store
*.pdb
*.obj
compile_commands.json
libwapp-build
libwapp.so
dist
*.vs
__pycache__

130
Makefile Normal file
View File

@@ -0,0 +1,130 @@
.PHONY: help full prng testing uuid core primitives all clean builddir build-test run-test codegen install build-lib ccodegen
# External variables
CC = clang
CXX = clang++
AR = ar
BUILD_TYPE = Debug
BUILD_DIR = libwapp-build/$(PLATFORM)-$(BUILD_TYPE)
INSTALL_PREFIX = dist
# Internal variables
override CFLAGS = -Wall -Wextra -Werror -pedantic -Isrc
override LIBFLAGS = -fPIC
override CSTD := -std=gnu11
override CXXSTD := -std=gnu++11
override KERNEL := $(shell uname -s)
override MACHINE := $(shell uname -m)
override PLATFORM := $(KERNEL)_$(MACHINE)
override TEST_INCLUDE := -Isrc $(shell find tests -type d | xargs -I{} echo -n "-I{} ")
override TEST_SRC := $(shell find tests -type f -name "*.c" | xargs -I{} echo -n "{} ")
override TEST_C_SRC := src/wapp.c $(TEST_SRC)
override TEST_CXX_SRC := $(shell find tests -type f -name "*.cc" | xargs -I{} echo -n "{} ")
override LIB_NAME := wapp
override OBJ_OUT := $(BUILD_DIR)/$(LIB_NAME).o
override LIB_OUT := $(BUILD_DIR)/lib$(LIB_NAME).a
override TEST_C_OUT := $(BUILD_DIR)/wapptest
override TEST_CXX_OUT := $(BUILD_DIR)/wapptestcc
override INCLUDE_INSTALL := $(INSTALL_PREFIX)/include/$(LIB_NAME)
override LIB_INSTALL := $(INSTALL_PREFIX)/lib
override HEADER_INSTALL_CMD := scripts/header_install.sh
ifeq ($(BUILD_TYPE),Debug)
override CFLAGS += -g -fsanitize=address,undefined -DWAPP_DEBUG_ASSERT
else ifeq ($(BUILD_TYPE),RelWithDebInfo)
override CFLAGS += -g -O2 -fsanitize=address,undefined -DWAPP_DEBUG_ASSERT
else ifeq ($(BUILD_TYPE),Release)
override CFLAGS += -O3
else
$(error Invalid BUILD type '$(BUILD_TYPE)'. Use 'Debug', 'RelWithDebInfo' or 'Release')
endif
ifeq ($(CC),gcc)
# Used to disable the "ASan runtime does not come first in initial library list" error when compiling with gcc
export ASAN_OPTIONS=verify_asan_link_order=0
endif
all: clean builddir codegen run-c-test full run-cc-test
help:
@echo "Available build variables:"
@echo " CC C compiler to use (Default: clang)."
@echo " CXX C++ compiler to use (Default: clang++)."
@echo " AR Archiving utility to use for building static libraries (Default: ar)."
@echo " BUILD_TYPE Build type. Choose from \`Debug\`, \`RelWithDebInfo\` or \`Release\` (Default: Debug)."
@echo " BUILD_DIR Directory where build files will be written."
@echo " INSTALL_PREFIX Prefix where library and include files will be installed."
@echo
@echo "Available targets:"
@echo " make Build, install and test the full wapp library."
@echo " make full Build and install the full wapp library."
@echo " make core Build and install only the \`core\` component of the wapp library with all its dependencies."
@echo " make prng Build and install only the \`prng\` component of the wapp library with all its dependencies."
@echo " make uuid Build and install only the \`uuid\` component of the wapp library with all its dependencies."
@echo " make testing Build and install only the \`testing\` component of the wapp library with all its dependencies."
@echo " make primitives Build and install only the \`primitives\` component of the wapp library with all its dependencies."
@echo " make clean Clean build directory."
@echo " make help Print this help message and exit."
full: LIB_SRC = src/wapp.c
full: INCLUDES = common core primitives prng testing uuid
full: install
prng: LIB_SRC = src/prng/wapp_prng.c
prng: INCLUDES = common prng
prng: install
testing: LIB_SRC = src/testing/wapp_testing.c
testing: INCLUDES = common core testing
testing: install
uuid: LIB_SRC = src/uuid/wapp_uuid.c
uuid: INCLUDES = common primitives prng
uuid: install
core: LIB_SRC = src/core/wapp_core.c
core: INCLUDES = common core primitives
core: install
primitives: LIB_SRC = src/primitives/wapp_primitives.c
primitives: INCLUDES = common primitives
primitives: install
clean:
@rm -rf $(BUILD_DIR)
builddir:
@mkdir -p $(BUILD_DIR)
build-c-test:
$(CC) $(CSTD) $(CFLAGS) $(TEST_INCLUDE) $(TEST_C_SRC) -o $(TEST_C_OUT)
run-c-test: build-c-test
@echo -e "\n\033[34;1mRUNNING C TESTS\033[0m"
@$(TEST_C_OUT)
@rm $(TEST_C_OUT)
build-cc-test:
$(CXX) $(CXXSTD) $(CFLAGS) $(TEST_INCLUDE) $(TEST_CXX_SRC) $(LIB_OUT) -o $(TEST_CXX_OUT)
run-cc-test: build-cc-test
@echo -e "\n\033[34;1mRUNNING C++ TESTS\033[0m"
@export LD_LIBRARY_PATH=$$LD_LIBRARY_PATH:$(BUILD_DIR) && $(TEST_CXX_OUT)
@rm $(TEST_CXX_OUT)
codegen:
python3 -m codegen
install: build-lib
@mkdir -p $(LIB_INSTALL)
@cp -v $(LIB_OUT) $(LIB_INSTALL)
@mkdir -p $(INCLUDE_INSTALL)
@bash $(HEADER_INSTALL_CMD) $(LIB_SRC) $(INCLUDE_INSTALL) $(INCLUDES)
build-lib: builddir
$(CC) -c $(CSTD) $(CFLAGS) $(LIBFLAGS) $(LIB_SRC) -o $(OBJ_OUT)
$(AR) r $(LIB_OUT) $(OBJ_OUT)
@rm $(OBJ_OUT)
ccodegen:
$(CC) $(CSTD) $(CFLAGS) $(LIBFLAGS) -Isrc/core src/core/wapp_core.c ccodegen/*.c -o ccgen

View File

@@ -1,3 +1,3 @@
# Wizard Apprentice Standard Library
A collection of useful C/C++ utilities for my projects
A collection of useful C utilities for my projects

68
build
View File

@@ -1,3 +1,69 @@
#!/bin/bash
bear -- ./compile $@
# Colors
RED="\033[0;31m"
BOLD="\033[1m"
NC="\033[0m" # No Color
BUILD_TYPE="Debug"
ACCEPTED_BUILD_TYPES=("Debug" "RelWithDebInfo" "Release")
KERNEL="$(uname -s)"
ARGS=""
join_array_elements() {
local IFS=","
echo "$*"
}
contains() {
local item="$1"; shift
local e
for e; do
[[ "$e" == "$item" ]] && return 0
done
return 1
}
print_usage() {
echo -e "Usage: build [-b build_type] ..."
echo -e " Options:"
echo -e " -b, --build-type Choose from $(join_array_elements ${ACCEPTED_BUILD_TYPES[*]}) (Default: Debug)."
echo -e " -h, --help Print this message and exit"
}
while [[ $# > 0 ]];do
case $1 in
-b|--build-type)
BUILD_TYPE="$2"
shift 2
;;
-h|--help)
print_usage
exit 0
;;
*|-*|--*)
rest=("$@")
ARGS+=" ${rest[0]}"
shift
;;
esac
done
if ! contains ${BUILD_TYPE} "${ACCEPTED_BUILD_TYPES[@]}"; then
echo -e "${RED}${BOLD}Unknown build type: ${BUILD_TYPE}${NC}\n"
print_usage
exit 1
fi
if [[ $KERNEL == "Darwin" ]]; then
if [[ ! -d .venv ]]; then
python3 -m venv .venv
fi
source .venv/bin/activate
pip install scan-build
intercept-build make CC=intercept-cc CXX=intercept-c++ BUILD_TYPE=$BUILD_TYPE $ARGS
deactivate
else
bear -- make BUILD_TYPE=$BUILD_TYPE $ARGS
fi

View File

@@ -1,27 +1,31 @@
Param(
[switch]$Release
[switch]$Release
)
$Compiler = "cl.exe"
$GeneralFlags = "/Wall /WX /wd4996"
$GeneralFlags = "/Wall /WX /wd4996 /wd4464 /wd5105 /std:c11"
$LibraryFlags = "/LD"
$IncludeDirs = Get-ChildItem -Path src -Recurse -Directory -ErrorAction SilentlyContinue -Force | %{$("/I " + '"' + $_.FullName + '"')}
$SrcFiles = Get-ChildItem -Path src -Recurse -Filter *.c -ErrorAction SilentlyContinue -Force | %{$('"' + $_.FullName + '"')}
$Kernel = (Get-ChildItem Env:OS).Value
$Machine = (Get-ChildItem Env:PROCESSOR_ARCHITECTURE).Value
$Platform = "${Kernel}_${Machine}"
$IncludeDirs = "/I src"
$SrcFiles = "src/wapp.c"
$TestIncludeDirs = Get-ChildItem -Path tests -Recurse -Directory -ErrorAction SilentlyContinue -Force | %{$("/I " + '"' + $_.FullName + '"')}
$TestSrcFiles = Get-ChildItem -Path tests -Recurse -Filter *.c -ErrorAction SilentlyContinue -Force | %{$('"' + $_.FullName + '"')}
If ($Release -eq $True) {
$GeneralFlags += " /O2 /Og"
$BuildType = "release"
$GeneralFlags += " /O2 /Og"
$BuildType = "release"
} Else {
$GeneralFlags += " /Zi /Od /fsanitize=address"
$BuildType = "debug"
$GeneralFlags += " /Zi /Od /fsanitize=address"
$BuildType = "debug"
}
$BuildDir = "./libwapp-build/windows-$BuildType"
$BuildDir = "./libwapp-build/${Platform}-${BuildType}"
$ObjDir = "$BuildDir/objects"
$OutDir = "$BuildDir/output"
$TestsDir = "$BuildDir/tests"
@@ -34,13 +38,16 @@ $TestOutBasename = "wapptest"
$TestOutputs = "/Fo:$TestsDir/ /Fe:$TestsDir/$TestOutBasename"
If (Test-Path $BuildDir) {
Remove-Item $BuildDir -Recurse -Force
Remove-Item $BuildDir -Recurse -Force
}
mkdir -p $ObjDir > $null
mkdir -p $OutDir > $null
mkdir -p $TestsDir > $null
# Run code generation
Invoke-Expression "python -m codegen"
# Build and run tests
Invoke-Expression "$Compiler $GeneralFlags $IncludeDirs $TestIncludeDirs $SrcFiles $TestSrcFiles $TestOutputs" -ErrorAction Stop
@@ -50,9 +57,9 @@ $Status = $LASTEXITCODE
Remove-Item $TestsDir -Recurse -Force
If ($Status -ne 0) {
Write-Error "Tests failed"
Exit 1
Write-Error "Tests failed"
Exit 1
}
# Build library
Invoke-Expression "$Compiler $GeneralFlags $LibraryFlags $IncludeDirs $SrcFiles $Objects $Outputs"
Invoke-Expression "$Compiler $GeneralFlags $LibraryFlags $SrcFiles $Objects $Outputs"

522
ccodegen/datatypes.c Normal file
View File

@@ -0,0 +1,522 @@
// vim:fileencoding=utf-8:foldmethod=marker
#include "datatypes.h"
#include "dbl_list.h"
#include "type_enums.h"
#include "wapp_core.h"
#define ERR_MSG "Not enough capacity in dst buffer"
#define CFILE_DISCLAIMER "/**\n" \
" * THIS FILE IS AUTOMATICALLY GENERATED. ANY MODIFICATIONS TO IT WILL BE OVERWRITTEN.\n" \
" */\n\n"
void cobject_to_string(Str8 *dst, const CObject *object) {
wapp_debug_assert(dst != NULL && object != NULL, "`allocator`, `dst` and `object` should not be NULL");
switch (object->kind) {
case COBJECT_CTYPE:
ctype_to_string(dst, object->object.c_type);
break;
case COBJECT_CQUALIFIER:
cqualifier_to_string(dst, object->object.c_qualifier);
break;
case COBJECT_CPOINTERTYPE:
cpointertype_to_string(dst, object->object.c_pointertype);
break;
case COBJECT_CPOINTER:
cpointer_to_string(dst, &(object->object.c_pointer));
break;
case COBJECT_CENUMVAL:
cenumval_to_string(dst, &(object->object.c_enumval));
break;
case COBJECT_CENUM:
cenum_to_string(dst, &(object->object.c_enum));
break;
case COBJECT_CMACRO:
cmacro_to_string(dst, &(object->object.c_macro));
break;
case COBJECT_CSTRUCT:
cstruct_to_string(dst, &(object->object.c_struct));
break;
case COBJECT_CUSERTYPE:
cusertype_to_string(dst, &(object->object.c_usertype));
break;
case COBJECT_CDATATYPE:
cdatatype_to_string(dst, &(object->object.c_datatype));
break;
case COBJECT_CARG:
carg_to_string(dst, &(object->object.c_arg));
break;
case COBJECT_CFUNC:
cfunc_to_string(dst, &(object->object.c_func));
break;
case COBJECT_CINCULDE:
cinclude_to_string(dst, &(object->object.c_include));
break;
case COBJECT_CHEADER:
cheader_to_string(dst, &(object->object.c_header));
break;
case COBJECT_CSOURCE:
csource_to_string(dst, &(object->object.c_source));
break;
default:
break;
}
}
void ctype_to_string(Str8 *dst, CType ctype) {
wapp_runtime_assert(ctypes[ctype].size <= dst->capacity, ERR_MSG);
wapp_str8_copy_str8_capped(dst, &ctypes[ctype]);
}
void cqualifier_to_string(Str8 *dst, CQualifier cqualifier) {
wapp_runtime_assert(cqualifiers[cqualifier].size <= dst->capacity, ERR_MSG);
wapp_str8_copy_str8_capped(dst, &cqualifiers[cqualifier]);
}
void cpointertype_to_string(Str8 *dst, CPointerType cpointertype) {
wapp_runtime_assert(cpointertypes[cpointertype].size <= dst->capacity, ERR_MSG);
wapp_str8_copy_str8_capped(dst, &cpointertypes[cpointertype]);
}
void cpointer_to_string(Str8 *dst, const CPointer *cpointer) {
wapp_debug_assert(dst != NULL && cpointer != NULL, "`dst` and `cpointer` should not be NULL");
u64 total_size = cpointertypes[cpointer->type].size + cqualifiers[cpointer->qualifier].size;
wapp_runtime_assert(total_size <= dst->capacity, ERR_MSG);
wapp_str8_format(dst,
WAPP_STR8_SPEC WAPP_STR8_SPEC,
wapp_str8_varg(cpointertypes[cpointer->type]),
wapp_str8_varg(cqualifiers[cpointer->qualifier]));
}
void cenumval_to_string(Str8 *dst, const CEnumVal *cenumval) {
wapp_debug_assert(dst != NULL && cenumval != NULL, "`dst` and `cenumval` should not be NULL");
Str8 tmp = wapp_str8_buf(CCGEN_BUF_TINY);
u64 tmp_size = 0;
if (cenumval->value != NULL) {
wapp_str8_format(&tmp, " = %d", *(cenumval->value));
tmp_size = tmp.size;
}
u64 total_size = cenumval->name.size + tmp_size;
wapp_runtime_assert(total_size <= dst->capacity, ERR_MSG);
wapp_str8_format(dst,
WAPP_STR8_SPEC WAPP_STR8_SPEC,
wapp_str8_varg(cenumval->name),
wapp_str8_varg(tmp));
}
void cenum_to_string(Str8 *dst, const CEnum *cenum) {
wapp_debug_assert(dst != NULL && cenum != NULL, "`dst` and `cenum` should not be NULL");
Str8 header = wapp_str8_buf(CCGEN_BUF_LARGE);
Str8 values = wapp_str8_buf(CCGEN_BUF_MAX);
Str8 footer = wapp_str8_buf(CCGEN_BUF_LARGE);
Str8 tmp = wapp_str8_buf(CCGEN_BUF_LARGE);
if (cenum->add_typedef) {
wapp_str8_copy_cstr_capped(&header, "typedef enum {\n");
wapp_str8_format(&footer, "} " WAPP_STR8_SPEC ";\n", wapp_str8_varg(cenum->name));
} else {
wapp_str8_format(&header, "enum " WAPP_STR8_SPEC " {\n", wapp_str8_varg(cenum->name));
wapp_str8_copy_cstr_capped(&footer, "};\n");
}
for (u64 i = 0; i < cenum->values.node_count; ++i) {
cenumval_to_string(&tmp, wapp_cenumval_list_get(&(cenum->values), i)->item);
// Add 4 for extra characters
wapp_runtime_assert(tmp.size + 4 <= values.capacity - values.size, ERR_MSG);
wapp_str8_concat_capped(&values, &wapp_str8_lit_ro(" "));
wapp_str8_concat_capped(&values, &tmp);
wapp_str8_concat_capped(&values, &wapp_str8_lit_ro(",\n"));
}
u64 total_size = header.size + values.size + footer.size;
wapp_runtime_assert(total_size <= dst->capacity, ERR_MSG);
wapp_str8_format(dst,
WAPP_STR8_SPEC WAPP_STR8_SPEC WAPP_STR8_SPEC,
wapp_str8_varg(header),
wapp_str8_varg(values),
wapp_str8_varg(footer));
}
void cmacro_to_string(Str8 *dst, const CMacro *cmacro) {
wapp_debug_assert(dst != NULL && cmacro != NULL, "`dst` and `cmacro` should not be NULL");
Str8 def = wapp_str8_lit("#define ");
u64 total_size = def.size + cmacro->name.size + cmacro->value.size + 1; // Add 1 for newline
wapp_runtime_assert(total_size <= dst->capacity, ERR_MSG);
wapp_str8_format(dst,
WAPP_STR8_SPEC WAPP_STR8_SPEC " " WAPP_STR8_SPEC "\n",
wapp_str8_varg(def),
wapp_str8_varg(cmacro->name),
wapp_str8_varg(cmacro->value));
}
void cstruct_to_string(Str8 *dst, const CStruct *cstruct) {
wapp_debug_assert(dst != NULL && cstruct != NULL, "`dst` and `cstruct` should not be NULL");
Str8 declaration = wapp_str8_buf(CCGEN_BUF_LARGE);
Str8 definition = wapp_str8_buf(CCGEN_BUF_MAX);
declare_cstruct(&declaration, cstruct);
define_cstruct(&definition, cstruct);
u64 total_size = declaration.size + definition.size;
wapp_runtime_assert(total_size <= dst->capacity, ERR_MSG);
wapp_str8_format(dst, WAPP_STR8_SPEC WAPP_STR8_SPEC,
wapp_str8_varg(declaration), wapp_str8_varg(definition));
}
void declare_cstruct(Str8 *dst, const CStruct *cstruct) {
wapp_debug_assert(dst != NULL && cstruct != NULL, "`dst` and `cstruct` should not be NULL");
Str8 tmp = wapp_str8_buf(CCGEN_BUF_MAX);
wapp_str8_format(&tmp,
"typedef struct " WAPP_STR8_SPEC " " WAPP_STR8_SPEC ";\n",
wapp_str8_varg(cstruct->name),
wapp_str8_varg(cstruct->typedef_name.size > 0 ? cstruct->typedef_name : cstruct->name));
wapp_runtime_assert(tmp.size <= dst->capacity, ERR_MSG);
wapp_str8_copy_str8_capped(dst, &tmp);
}
void define_cstruct(Str8 *dst, const CStruct *cstruct) {
wapp_debug_assert(dst != NULL && cstruct != NULL, "`dst` and `cstruct` should not be NULL");
Str8 definition = wapp_str8_buf(CCGEN_BUF_LARGE);
Str8 args = wapp_str8_buf(CCGEN_BUF_MAX);
Str8 footer = wapp_str8_lit_ro("};\n");
Str8 tmp = wapp_str8_buf(CCGEN_BUF_MEDIUM);
wapp_str8_format(&definition, "struct " WAPP_STR8_SPEC " {\n", wapp_str8_varg(cstruct->name));
for (u64 i = 0; i < cstruct->args.node_count; ++i) {
carg_to_string(&tmp, wapp_carg_list_get(&(cstruct->args), i)->item);
// Add 4 for extra characters
wapp_runtime_assert(tmp.size + 4 <= args.capacity - args.size, ERR_MSG);
wapp_str8_concat_capped(&args, &wapp_str8_lit_ro(" "));
wapp_str8_concat_capped(&args, &tmp);
wapp_str8_concat_capped(&args, &wapp_str8_lit_ro(";\n"));
}
u64 total_size = definition.size + args.size + footer.size;
wapp_runtime_assert(total_size <= dst->capacity, ERR_MSG);
wapp_str8_format(dst,
WAPP_STR8_SPEC WAPP_STR8_SPEC WAPP_STR8_SPEC,
wapp_str8_varg(definition),
wapp_str8_varg(args),
wapp_str8_varg(footer));
}
void cusertype_to_string(Str8 *dst, const CUserType *cusertype) {
wapp_debug_assert(dst != NULL && cusertype != NULL, "`dst` and `cusertype` should not be NULL");
switch (cusertype->kind) {
case CUSERTYPE_CENUM:
cenum_to_string(dst, &(cusertype->type.c_enum));
break;
case CUSERTYPE_CSTRUCT:
cstruct_to_string(dst, &(cusertype->type.c_struct));
break;
default:
break;
}
}
void cdatatype_to_string(Str8 *dst, const CDataType *cdatatype) {
wapp_debug_assert(dst != NULL && cdatatype != NULL, "`dst` and `cdatatype` should not be NULL");
switch (cdatatype->kind) {
case CDATATYPE_CTYPE:
ctype_to_string(dst, cdatatype->type.c_type);
break;
case CDATATYPE_CUSERTYPE:
cusertype_to_string(dst, &(cdatatype->type.c_usertype));
break;
case CDATATYPE_STR:
wapp_runtime_assert(cdatatype->type.str.size <= dst->capacity, ERR_MSG);
wapp_str8_copy_str8_capped(dst, &(cdatatype->type.str));
break;
default:
break;
}
}
void carg_to_string(Str8 *dst, const CArg *carg) {
wapp_debug_assert(dst != NULL && carg != NULL, "`dst` and `carg` should not be NULL");
Str8 qualifier = wapp_str8_buf(CCGEN_BUF_MEDIUM);
Str8 type = wapp_str8_buf(CCGEN_BUF_LARGE);
Str8 pointer = wapp_str8_buf(CCGEN_BUF_MEDIUM);
Str8 array = wapp_str8_buf(CCGEN_BUF_MEDIUM);
cqualifier_to_string(&qualifier, carg->qualifier);
cdatatype_to_string(&type, &(carg->type));
wapp_str8_concat_capped(&type, &wapp_str8_lit_ro(" "));
cpointer_to_string(&pointer, &(carg->pointer));
if (carg->is_array) { wapp_str8_copy_cstr_capped(&array, "[]"); }
u64 total_size = qualifier.size + type.size + pointer.size + array.size + carg->name.size;
wapp_runtime_assert(total_size <= dst->capacity, ERR_MSG);
wapp_str8_format(dst, WAPP_STR8_SPEC WAPP_STR8_SPEC WAPP_STR8_SPEC WAPP_STR8_SPEC WAPP_STR8_SPEC,
wapp_str8_varg(qualifier), wapp_str8_varg(type), wapp_str8_varg(pointer),
wapp_str8_varg(carg->name), wapp_str8_varg(array));
}
void cfunc_to_string(Str8 *dst, const CFunc *cfunc) {
wapp_debug_assert(dst != NULL && cfunc != NULL, "`dst` and `cfunc` should not be NULL");
Str8 qualifiers = wapp_str8_buf(CCGEN_BUF_LARGE);
Str8 args = wapp_str8_buf(CCGEN_BUF_LARGE);
Str8 ret_type = wapp_str8_buf(CCGEN_BUF_SMALL);
Str8 pointer = wapp_str8_buf(CCGEN_BUF_SMALL);
Str8 tmp = wapp_str8_buf(CCGEN_BUF_MEDIUM);
CQualifier *qf = NULL;
CArg *arg = NULL;
for (u64 i = 0; i < cfunc->qualifiers.node_count; ++i) {
qf = wapp_cqualifier_list_get(&(cfunc->qualifiers), i)->item;
if (*qf == CQUALIFIER_NONE) { continue; }
cqualifier_to_string(&tmp, *qf);
wapp_runtime_assert(tmp.size + 1 <= qualifiers.capacity - qualifiers.size, ERR_MSG);
if (qualifiers.size > 0) { wapp_str8_concat_capped(&qualifiers, &wapp_str8_lit_ro(" ")); }
wapp_str8_concat_capped(&qualifiers, &tmp);
}
for (u64 i = 0; i < cfunc->args.node_count; ++i) {
arg = wapp_carg_list_get(&(cfunc->args), i)->item;
carg_to_string(&tmp, arg);
wapp_runtime_assert(tmp.size + 2 <= args.capacity - args.size, ERR_MSG);
wapp_str8_concat_capped(&args, &tmp);
if (i + 1 < cfunc->args.node_count) { wapp_str8_concat_capped(&args, &wapp_str8_lit_ro(", ")); }
}
cdatatype_to_string(&ret_type, &(cfunc->ret_type));
cpointer_to_string(&pointer, &(cfunc->pointer));
u64 total_size = cfunc->name.size + qualifiers.size + args.size + ret_type.size + pointer.size + 4;
wapp_runtime_assert(total_size <= dst->capacity, ERR_MSG);
wapp_str8_format(dst,
WAPP_STR8_SPEC WAPP_STR8_SPEC " " WAPP_STR8_SPEC WAPP_STR8_SPEC "(" WAPP_STR8_SPEC ")",
wapp_str8_varg(qualifiers),
wapp_str8_varg(ret_type),
wapp_str8_varg(pointer),
wapp_str8_varg(cfunc->name),
wapp_str8_varg(args));
}
void declare_cfunc(Str8 *dst, const CFunc *cfunc) {
wapp_debug_assert(dst != NULL && cfunc != NULL, "`dst` and `cfunc` should not be NULL");
Str8 tmp = wapp_str8_buf(CCGEN_BUF_MAX);
cfunc_to_string(&tmp, cfunc);
wapp_runtime_assert(tmp.size + 2 <= dst->capacity, ERR_MSG);
wapp_str8_format(dst, WAPP_STR8_SPEC ";\n", wapp_str8_varg(tmp));
}
void define_cfunc(Str8 *dst, const CFunc *cfunc) {
wapp_debug_assert(dst != NULL && cfunc != NULL, "`dst` and `cfunc` should not be NULL");
Str8 tmp = wapp_str8_buf(CCGEN_BUF_MAX);
cfunc_to_string(&tmp, cfunc);
wapp_runtime_assert(tmp.size + cfunc->body.size + 8 <= dst->capacity, ERR_MSG);
wapp_str8_format(dst, WAPP_STR8_SPEC " {\n" WAPP_STR8_SPEC "\n}\n\n",
wapp_str8_varg(tmp), wapp_str8_varg(cfunc->body));
}
void cinclude_to_string(Str8 *dst, const CInclude *cinclude) {
wapp_debug_assert(dst != NULL && cinclude != NULL, "`dst` and `cinclude` should not be NULL");
Str8 header_str = wapp_str8_buf(CCGEN_BUF_LARGE);
if (!cheaderinclude_to_string(&header_str, &(cinclude->header))) { return; }
Str8 inc = wapp_str8_lit("#include ");
Str8 open_symbol = wapp_str8_buf(CCGEN_BUF_MIN);
Str8 close_symbol = wapp_str8_buf(CCGEN_BUF_MIN);
if (cinclude->is_local) {
wapp_str8_concat_capped(&open_symbol, &wapp_str8_lit_ro("\""));
wapp_str8_concat_capped(&close_symbol, &wapp_str8_lit_ro("\""));
if (cinclude->same_dir) { wapp_str8_concat_capped(&open_symbol, &wapp_str8_lit_ro("./")); }
} else {
wapp_str8_concat_capped(&open_symbol, &wapp_str8_lit_ro("<"));
wapp_str8_concat_capped(&close_symbol, &wapp_str8_lit_ro(">"));
}
u64 total_size = header_str.size + inc.size + open_symbol.size + close_symbol.size;
wapp_runtime_assert(total_size <= dst->capacity, ERR_MSG);
wapp_str8_format(dst,
WAPP_STR8_SPEC WAPP_STR8_SPEC WAPP_STR8_SPEC WAPP_STR8_SPEC "\n",
wapp_str8_varg(inc),
wapp_str8_varg(open_symbol),
wapp_str8_varg(header_str),
wapp_str8_varg(close_symbol));
}
void cheader_to_string(Str8 *dst, const CHeader *cheader) {
wapp_debug_assert(dst != NULL && cheader != NULL, "`dst` and `cheader` should not be NULL");
Allocator arena = wapp_mem_arena_allocator_init(MB(64));
Str8 *output = wapp_str8_alloc_buf(&arena, KB(32));
wapp_runtime_assert(output != NULL, "Failed to allocate buffer");
Str8 header_guard_name = wapp_str8_buf(CCGEN_BUF_SMALL);
Str8 tmp = wapp_str8_buf(CCGEN_BUF_MAX);
// ADD HEADER GUARD AND START C LINKAGE
wapp_str8_to_upper(&header_guard_name, &(cheader->name));
wapp_str8_concat_capped(&header_guard_name, &wapp_str8_lit_ro("_H"));
wapp_str8_format(&tmp, "#ifndef " WAPP_STR8_SPEC "\n#define " WAPP_STR8_SPEC "\n\n"
"#ifdef WAPP_PLATFORM_CPP\nBEGIN_C_LINKAGE\n#endif // !WAPP_PLATFORM_CPP\n\n",
wapp_str8_varg(header_guard_name), wapp_str8_varg(header_guard_name));
wapp_str8_alloc_concat(&arena, output, &tmp);
for (u64 i = 0; i < cheader->includes.node_count; ++i) {
cinclude_to_string(&tmp, wapp_cinclude_list_get(&(cheader->includes), i)->item);
wapp_str8_alloc_concat(&arena, output, &tmp);
}
if (cheader->includes.node_count > 0) { wapp_str8_alloc_concat(&arena, output, &wapp_str8_lit_ro("\n")); }
for (u64 i = 0; i < cheader->macros.node_count; ++i) {
cmacro_to_string(&tmp, wapp_cmacro_list_get(&(cheader->macros), i)->item);
wapp_str8_alloc_concat(&arena, output, &tmp);
}
if (cheader->macros.node_count > 0) { wapp_str8_alloc_concat(&arena, output, &wapp_str8_lit_ro("\n")); }
if (cheader->cpp_macros.node_count > 0) {
wapp_str8_alloc_concat(&arena, output, &wapp_str8_lit_ro("#ifdef WAPP_PLATFORM_CPP\n"));
for (u64 i = 0; i < cheader->cpp_macros.node_count; ++i) {
cmacro_to_string(&tmp, wapp_cmacro_list_get(&(cheader->cpp_macros), i)->item);
wapp_str8_alloc_concat(&arena, output, &tmp);
}
wapp_str8_alloc_concat(&arena, output, &wapp_str8_lit_ro("#else\n"));
for (u64 i = 0; i < cheader->c_macros.node_count; ++i) {
cmacro_to_string(&tmp, wapp_cmacro_list_get(&(cheader->c_macros), i)->item);
wapp_str8_alloc_concat(&arena, output, &tmp);
}
wapp_str8_alloc_concat(&arena, output, &wapp_str8_lit_ro("#endif // !WAPP_PLATFORM_CPP\n\n"));
}
for (u64 i = 0; i < cheader->decl_types.node_count; ++i) {
declare_cstruct(&tmp, wapp_cstruct_list_get(&(cheader->decl_types), i)->item);
wapp_str8_alloc_concat(&arena, output, &tmp);
}
if (cheader->decl_types.node_count > 0) { wapp_str8_alloc_concat(&arena, output, &wapp_str8_lit_ro("\n")); }
for (u64 i = 0; i < cheader->types.node_count; ++i) {
cusertype_to_string(&tmp, wapp_cusertype_list_get(&(cheader->types), i)->item);
wapp_str8_concat_capped(&tmp, &wapp_str8_lit_ro("\n"));
wapp_str8_alloc_concat(&arena, output, &tmp);
}
for (u64 i = 0; i < cheader->funcs.node_count; ++i) {
declare_cfunc(&tmp, wapp_cfunc_list_get(&(cheader->funcs), i)->item);
wapp_str8_alloc_concat(&arena, output, &tmp);
}
// END C LINKAGE AND CLOSE HEADER GUARD
wapp_str8_format(&tmp, "\n#ifdef WAPP_PLATFORM_CPP\nEND_C_LINKAGE\n#endif // !WAPP_PLATFORM_CPP\n\n"
"#endif // !" WAPP_STR8_SPEC "\n", wapp_str8_varg(header_guard_name));
wapp_str8_alloc_concat(&arena, output, &tmp);
wapp_runtime_assert(output->size <= dst->capacity, ERR_MSG);
wapp_str8_copy_str8_capped(dst, output);
wapp_mem_arena_allocator_destroy(&arena);
}
void csource_to_string(Str8 *dst, const CSource *csource) {
wapp_debug_assert(dst != NULL && csource != NULL, "`dst` and `csource` should not be NULL");
Allocator arena = wapp_mem_arena_allocator_init(MB(64));
Str8 *output = wapp_str8_alloc_buf(&arena, KB(32));
Str8 *internal_funcs_def = wapp_str8_alloc_buf(&arena, KB(16));
wapp_runtime_assert(output != NULL && internal_funcs_def != NULL, "Failed to allocate buffer");
Str8 tmp = wapp_str8_buf(CCGEN_BUF_MAX);
for (u64 i = 0; i < csource->includes.node_count; ++i) {
cinclude_to_string(&tmp, wapp_cinclude_list_get(&(csource->includes), i)->item);
wapp_str8_alloc_concat(&arena, output, &tmp);
}
if (csource->includes.node_count > 0) { wapp_str8_alloc_concat(&arena, output, &wapp_str8_lit_ro("\n")); }
for (u64 i = 0; i < csource->macros.node_count; ++i) {
cmacro_to_string(&tmp, wapp_cmacro_list_get(&(csource->macros), i)->item);
wapp_str8_alloc_concat(&arena, output, &tmp);
}
if (csource->macros.node_count > 0) { wapp_str8_alloc_concat(&arena, output, &wapp_str8_lit_ro("\n")); }
for (u64 i = 0; i < csource->decl_types.node_count; ++i) {
declare_cstruct(&tmp, wapp_cstruct_list_get(&(csource->decl_types), i)->item);
wapp_str8_alloc_concat(&arena, output, &tmp);
}
if (csource->decl_types.node_count > 0) { wapp_str8_alloc_concat(&arena, output, &wapp_str8_lit_ro("\n")); }
for (u64 i = 0; i < csource->types.node_count; ++i) {
cusertype_to_string(&tmp, wapp_cusertype_list_get(&(csource->types), i)->item);
wapp_str8_concat_capped(&tmp, &wapp_str8_lit_ro("\n"));
wapp_str8_alloc_concat(&arena, output, &tmp);
}
Str8RO _internal = wapp_str8_lit_ro("internal ");
for (u64 i = 0; i < csource->internal_funcs.node_count; ++i) {
declare_cfunc(&tmp, wapp_cfunc_list_get(&(csource->internal_funcs), i)->item);
wapp_str8_alloc_concat(&arena, output, &_internal);
wapp_str8_alloc_concat(&arena, output, &tmp);
define_cfunc(&tmp, wapp_cfunc_list_get(&(csource->internal_funcs), i)->item);
wapp_str8_alloc_concat(&arena, internal_funcs_def, &_internal);
wapp_str8_alloc_concat(&arena, internal_funcs_def, &tmp);
}
if (csource->internal_funcs.node_count > 0) { wapp_str8_alloc_concat(&arena, output, &wapp_str8_lit_ro("\n")); }
for (u64 i = 0; i < csource->funcs.node_count; ++i) {
define_cfunc(&tmp, wapp_cfunc_list_get(&(csource->funcs), i)->item);
wapp_str8_alloc_concat(&arena, output, &tmp);
}
wapp_runtime_assert(output->size + internal_funcs_def->size <= dst->capacity, ERR_MSG);
wapp_str8_copy_str8_capped(dst, output);
wapp_str8_concat_capped(dst, internal_funcs_def);
wapp_mem_arena_allocator_destroy(&arena);
}
b32 cheaderinclude_to_string(Str8 *dst, const CHeaderInclude *cheaderinclude) {
wapp_debug_assert(dst != NULL && cheaderinclude != NULL, "`dst` and `cheaderinclude` should not be NULL");
switch (cheaderinclude->kind) {
case C_HEADER_INCLUDE_STR:
wapp_runtime_assert(cheaderinclude->header.name.size <= dst->capacity, ERR_MSG);
wapp_str8_format(dst, WAPP_STR8_SPEC, wapp_str8_varg(cheaderinclude->header.name));
return true;
case C_HEADER_INCLUDE_HEADER:
// Take extension into account
wapp_runtime_assert(cheaderinclude->header.header.name.size + 2 <= dst->capacity, ERR_MSG);
wapp_str8_format(
dst,
WAPP_STR8_SPEC ".%s",
wapp_str8_varg(cheaderinclude->header.header.name),
cheaderinclude->header.header.extension == CFILE_EXT_H ? "h" : "c"
);
return true;
default:
return false;
}
return false;
}

280
ccodegen/datatypes.h Normal file
View File

@@ -0,0 +1,280 @@
// vim:fileencoding=utf-8:foldmethod=marker
#ifndef DATATYPES_H
#define DATATYPES_H
#include "wapp_core.h"
#include "dbl_list.h"
#include "type_enums.h"
#ifndef CCGEN_BUF_MIN
#define CCGEN_BUF_MIN 16
#endif // !CCGEN_BUF_MIN
#ifndef CCGEN_BUF_TINY
#define CCGEN_BUF_TINY 32
#endif // !CCGEN_BUF_TINY
#ifndef CCGEN_BUF_SMALL
#define CCGEN_BUF_SMALL 512
#endif // !CCGEN_BUF_SMALL
#ifndef CCGEN_BUF_MEDIUM
#define CCGEN_BUF_MEDIUM 1024
#endif // !CCGEN_BUF_MEDIUM
#ifndef CCGEN_BUF_LARGE
#define CCGEN_BUF_LARGE 4096
#endif // !CCGEN_BUF_LARGE
#ifndef CCGEN_BUF_MAX
#define CCGEN_BUF_MAX 8192
#endif // !CCGEN_BUF_MAX
#define CENUM(NAME, VALUES, TYPEDEF) ((CEnum){ .name = (NAME), .values = (VALUES), .add_typedef = (TYPEDEF) })
#define CSTRUCT(NAME, ARGS, TYPEDEF_NAME_PTR) ((CStruct){ .name = (NAME), .args = (ARGS), .typedef_name = (TYPEDEF_NAME_PTR) })
#define CUSERTYPE_ENUM(ENUM) ((CUserType){ .kind = CUSERTYPE_CENUM, .type.c_enum = ENUM })
#define CUSERTYPE_STRUCT(STRUCT) ((CUserType){ .kind = CUSERTYPE_CSTRUCT, .type.c_struct = STRUCT })
#define CDATATYPE_CTYPE(VALUE) ((CDataType){ .kind = CDATATYPE_CTYPE, .type.c_type = (VALUE) })
#define CDATATYPE_USERTYPE(USERTYPE) ((CDataType){ .kind = CDATATYPE_CUSERTYPE, .type.c_usertype = (USERTYPE) })
#define CDATATYPE_STR(STR) ((CDataType){ .kind = CDATATYPE_STR, .type.str = (STR) })
#define CHEADERINCLUDE_STR(NAME) ((CHeaderInclude){ .kind = C_HEADER_INCLUDE_STR, .header.name = (NAME) })
#define CHEADERINCLUDE_CHEADER(CHEADER) ((CHeaderInclude){ .kind = C_HEADER_INCLUDE_HEADER, .header.header = (CHEADER) })
#define COBJECT_TYPE(VALUE) \
((CObject){ .kind = COBJECT_CTYPE, .object.c_type = (VALUE) })
#define COBJECT_QUALIFIER(VALUE) \
((CObject){ .kind = COBJECT_CQUALIFIER, .object.c_qualifier = (VALUE) })
#define COBJECT_POINTERTYPE(VALUE) \
((CObject){ .kind = COBJECT_CPOINTERTYPE, .object.c_pointertype = (VALUE) })
#define COBJECT_POINTER(CPOINTER) \
((CObject){ .kind = COBJECT_CPOINTER, .object.c_pointer = (CPOINTER) })
#define COBJECT_ENUMVAL(CENUMVAL) \
((CObject){ .kind = COBJECT_CENUMVAL, .object.c_enumval = (CENUMVAL) })
#define COBJECT_ENUM(ENUM) \
((CObject){ .kind = COBJECT_CENUM, .object.c_enum = (ENUM) })
#define COBJECT_MACRO(CMACRO) \
((CObject){ .kind = COBJECT_CMACRO, .object.c_macro = (CMACRO) })
#define COBJECT_STRUCT(STRUCT) \
((CObject){ .kind = COBJECT_CSTRUCT, .object.c_struct = STRUCT })
#define COBJECT_USERTYPE(USERTYPE) \
((CObject){ .kind = COBJECT_CUSERTYPE, .object.c_usertype = (USERTYPE) })
#define COBJECT_DATATYPE(DATATYPE) \
((CObject){ .kind = COBJECT_CDATATYPE, .object.c_datatype = (DATATYPE) })
#define COBJECT_ARG(CARG) \
((CObject){ .kind = COBJECT_CARG, .object.c_arg = (CARG) })
#define COBJECT_FUNC(CFUNC) \
((CObject){ .kind = COBJECT_CFUNC, .object.c_func = (CFUNC) })
#define COBJECT_INCULDE(CINCLUDE) \
((CObject){ .kind = COBJECT_CINCULDE, .object.c_include = (CINCLUDE) })
#define COBJECT_HEADER(CHEADER) \
((CObject){ .kind = COBJECT_CHEADER, .object.c_header = (CHEADER) })
#define COBJECT_SOURCE(CSOURCE) \
((CObject){ .kind = COBJECT_CSOURCE, .object.c_source = (CSOURCE) })
typedef enum {
CUSERTYPE_CENUM,
CUSERTYPE_CSTRUCT,
COUNT_CUSERTYPEKIND,
} CUserTypeKind;
typedef enum {
CDATATYPE_CTYPE,
CDATATYPE_CUSERTYPE,
CDATATYPE_STR,
COUNT_CDATATYPEKIND,
} CDataTypeKind;
typedef enum {
CFILE_EXT_H,
CFILE_EXT_C,
COUNT_CFILE_EXT,
} CFileExtension;
typedef enum {
C_HEADER_INCLUDE_STR,
C_HEADER_INCLUDE_HEADER,
COUNT_CHEADERINCLUDEKIND,
} CHeaderIncludeKind;
typedef enum {
COBJECT_CTYPE,
COBJECT_CQUALIFIER,
COBJECT_CPOINTERTYPE,
COBJECT_CPOINTER,
COBJECT_CENUMVAL,
COBJECT_CENUM,
COBJECT_CMACRO,
COBJECT_CSTRUCT,
COBJECT_CUSERTYPE,
COBJECT_CDATATYPE,
COBJECT_CARG,
COBJECT_CFUNC,
COBJECT_CINCULDE,
COBJECT_CHEADER,
COBJECT_CSOURCE,
COUNT_COBJECTKIND,
} CObjectKind;
typedef struct cpointer CPointer;
typedef struct cenumval CEnumVal;
typedef struct cenum CEnum;
typedef struct cmacro CMacro;
typedef struct cstruct CStruct;
typedef struct cusertype CUserType;
typedef struct cdatatype CDataType;
typedef struct carg CArg;
typedef struct cfunc CFunc;
typedef struct cheader_include CHeaderInclude;
typedef struct cinclude CInclude;
typedef struct cheader CHeader;
typedef struct csource CSource;
typedef struct cobject CObject;
struct cpointer {
CPointerType type;
CQualifier qualifier;
};
struct cenumval {
Str8 name;
i32 *value;
};
struct cenum {
Str8 name;
CEnumValList values;
b32 add_typedef;
};
struct cmacro {
Str8 name;
Str8 value;
};
struct cstruct {
Str8 name;
CArgList args;
Str8 typedef_name;
};
struct cusertype {
CUserTypeKind kind;
union {
CEnum c_enum;
CStruct c_struct;
} type;
};
struct cdatatype {
CDataTypeKind kind;
union {
CType c_type;
CUserType c_usertype;
Str8 str;
} type;
};
struct carg {
Str8 name;
CDataType type;
CPointer pointer;
CQualifier qualifier;
b32 is_array;
};
struct cfunc {
Str8 name;
CDataType ret_type;
CArgList args;
Str8 body;
CPointer pointer;
CQualifierList qualifiers;
};
#define CFILE_ARGS \
Str8 name; \
CFileExtension extension; \
CIncludeList includes; \
CUserTypeList types; \
CFuncList funcs; \
CStructList decl_types; \
CMacroList macros; \
CMacroList c_macros; \
CMacroList cpp_macros \
struct cheader {
CFILE_ARGS;
};
struct csource {
CFILE_ARGS;
CFuncList internal_funcs;
};
struct cheader_include {
CHeaderIncludeKind kind;
union {
Str8 name;
CHeader header;
} header;
};
struct cinclude {
CHeaderInclude header;
b32 is_local;
b32 same_dir;
};
struct cobject {
CObjectKind kind;
union {
CType c_type;
CQualifier c_qualifier;
CPointerType c_pointertype;
CPointer c_pointer;
CEnumVal c_enumval;
CEnum c_enum;
CMacro c_macro;
CStruct c_struct;
CUserType c_usertype;
CDataType c_datatype;
CArg c_arg;
CFunc c_func;
CInclude c_include;
CHeader c_header;
CSource c_source;
} object;
};
void cobject_to_string(Str8 *dst, const CObject *object);
void ctype_to_string(Str8 *dst, CType ctype);
void cqualifier_to_string(Str8 *dst, CQualifier cqualifier);
void cpointertype_to_string(Str8 *dst, CPointerType cpointertype);
void cpointer_to_string(Str8 *dst, const CPointer *cpointer);
void cenumval_to_string(Str8 *dst, const CEnumVal *cenumval);
void cenum_to_string(Str8 *dst, const CEnum *cenum);
void cmacro_to_string(Str8 *dst, const CMacro *cmacro);
void cstruct_to_string(Str8 *dst, const CStruct *cstruct);
void declare_cstruct(Str8 *dst, const CStruct *cstruct);
void define_cstruct(Str8 *dst, const CStruct *cstruct);
void cusertype_to_string(Str8 *dst, const CUserType *cusertype);
void cdatatype_to_string(Str8 *dst, const CDataType *cdatatype);
void carg_to_string(Str8 *dst, const CArg *carg);
void cfunc_to_string(Str8 *dst, const CFunc *cfunc);
void declare_cfunc(Str8 *dst, const CFunc *cfunc);
void define_cfunc(Str8 *dst, const CFunc *cfunc);
void cinclude_to_string(Str8 *dst, const CInclude *cinclude);
void cheader_to_string(Str8 *dst, const CHeader *cheader);
void csource_to_string(Str8 *dst, const CSource *csource);
b32 cheaderinclude_to_string(Str8 *dst, const CHeaderInclude *cheaderinclude);
#endif // !DATATYPES_H

1526
ccodegen/dbl_list.c Normal file

File diff suppressed because it is too large Load Diff

222
ccodegen/dbl_list.h Normal file
View File

@@ -0,0 +1,222 @@
// vim:fileencoding=utf-8:foldmethod=marker
#ifndef CCGEN_DBL_LIST_H
#define CCGEN_DBL_LIST_H
#include "wapp_core.h"
#include "type_enums.h"
#ifdef WAPP_PLATFORM_CPP
BEGIN_C_LINKAGE
#endif // !WAPP_PLATFORM_CPP
#ifdef WAPP_PLATFORM_CPP
#define wapp_cenumval_list_node(ITEM_PTR) CEnumValNode{ITEM_PTR, nullptr, nullptr}
#define wapp_carg_list_node(ITEM_PTR) CArgNode{ITEM_PTR, nullptr, nullptr}
#define wapp_cqualifier_list_node(ITEM_PTR) CQualifierNode{ITEM_PTR, nullptr, nullptr}
#define wapp_cinclude_list_node(ITEM_PTR) CIncludeNode{ITEM_PTR, nullptr, nullptr}
#define wapp_cusertype_list_node(ITEM_PTR) CUserTypeNode{ITEM_PTR, nullptr, nullptr}
#define wapp_cfunc_list_node(ITEM_PTR) CFuncNode{ITEM_PTR, nullptr, nullptr}
#define wapp_cstruct_list_node(ITEM_PTR) CStructNode{ITEM_PTR, nullptr, nullptr}
#define wapp_cmacro_list_node(ITEM_PTR) CMacroNode{ITEM_PTR, nullptr, nullptr}
#else
#define wapp_cenumval_list_node(ITEM_PTR) ((CEnumValNode){.item = ITEM_PTR})
#define wapp_carg_list_node(ITEM_PTR) ((CArgNode){.item = ITEM_PTR})
#define wapp_cqualifier_list_node(ITEM_PTR) ((CQualifierNode){.item = ITEM_PTR})
#define wapp_cinclude_list_node(ITEM_PTR) ((CIncludeNode){.item = ITEM_PTR})
#define wapp_cusertype_list_node(ITEM_PTR) ((CUserTypeNode){.item = ITEM_PTR})
#define wapp_cfunc_list_node(ITEM_PTR) ((CFuncNode){.item = ITEM_PTR})
#define wapp_cstruct_list_node(ITEM_PTR) ((CStructNode){.item = ITEM_PTR})
#define wapp_cmacro_list_node(ITEM_PTR) ((CMacroNode){.item = ITEM_PTR})
#endif // !WAPP_PLATFORM_CPP
typedef struct cenumval CEnumVal;
typedef struct carg CArg;
typedef struct cinclude CInclude;
typedef struct cusertype CUserType;
typedef struct cfunc CFunc;
typedef struct cstruct CStruct;
typedef struct cmacro CMacro;
typedef struct CEnumValNode CEnumValNode;
struct CEnumValNode {
CEnumVal *item;
CEnumValNode *prev;
CEnumValNode *next;
};
typedef struct CEnumValList CEnumValList;
struct CEnumValList {
CEnumValNode *first;
CEnumValNode *last;
u64 node_count;
};
typedef struct CArgNode CArgNode;
struct CArgNode {
CArg *item;
CArgNode *prev;
CArgNode *next;
};
typedef struct CArgList CArgList;
struct CArgList {
CArgNode *first;
CArgNode *last;
u64 node_count;
};
typedef struct CQualifierNode CQualifierNode;
struct CQualifierNode {
CQualifier *item;
CQualifierNode *prev;
CQualifierNode *next;
};
typedef struct CQualifierList CQualifierList;
struct CQualifierList {
CQualifierNode *first;
CQualifierNode *last;
u64 node_count;
};
typedef struct CIncludeNode CIncludeNode;
struct CIncludeNode {
CInclude *item;
CIncludeNode *prev;
CIncludeNode *next;
};
typedef struct CIncludeList CIncludeList;
struct CIncludeList {
CIncludeNode *first;
CIncludeNode *last;
u64 node_count;
};
typedef struct CUserTypeNode CUserTypeNode;
struct CUserTypeNode {
CUserType *item;
CUserTypeNode *prev;
CUserTypeNode *next;
};
typedef struct CUserTypeList CUserTypeList;
struct CUserTypeList {
CUserTypeNode *first;
CUserTypeNode *last;
u64 node_count;
};
typedef struct CFuncNode CFuncNode;
struct CFuncNode {
CFunc *item;
CFuncNode *prev;
CFuncNode *next;
};
typedef struct CFuncList CFuncList;
struct CFuncList {
CFuncNode *first;
CFuncNode *last;
u64 node_count;
};
typedef struct CStructNode CStructNode;
struct CStructNode {
CStruct *item;
CStructNode *prev;
CStructNode *next;
};
typedef struct CStructList CStructList;
struct CStructList {
CStructNode *first;
CStructNode *last;
u64 node_count;
};
typedef struct CMacroNode CMacroNode;
struct CMacroNode {
CMacro *item;
CMacroNode *prev;
CMacroNode *next;
};
typedef struct CMacroList CMacroList;
struct CMacroList {
CMacroNode *first;
CMacroNode *last;
u64 node_count;
};
CEnumValNode *wapp_cenumval_list_get(const CEnumValList *list, u64 index);
void wapp_cenumval_list_push_front(CEnumValList *list, CEnumValNode *node);
void wapp_cenumval_list_push_back(CEnumValList *list, CEnumValNode *node);
void wapp_cenumval_list_insert(CEnumValList *list, CEnumValNode *node, u64 index);
CEnumValNode *wapp_cenumval_list_pop_front(CEnumValList *list);
CEnumValNode *wapp_cenumval_list_pop_back(CEnumValList *list);
CEnumValNode *wapp_cenumval_list_remove(CEnumValList *list, u64 index);
void wapp_cenumval_list_empty(CEnumValList *list);
CArgNode *wapp_carg_list_get(const CArgList *list, u64 index);
void wapp_carg_list_push_front(CArgList *list, CArgNode *node);
void wapp_carg_list_push_back(CArgList *list, CArgNode *node);
void wapp_carg_list_insert(CArgList *list, CArgNode *node, u64 index);
CArgNode *wapp_carg_list_pop_front(CArgList *list);
CArgNode *wapp_carg_list_pop_back(CArgList *list);
CArgNode *wapp_carg_list_remove(CArgList *list, u64 index);
void wapp_carg_list_empty(CArgList *list);
CQualifierNode *wapp_cqualifier_list_get(const CQualifierList *list, u64 index);
void wapp_cqualifier_list_push_front(CQualifierList *list, CQualifierNode *node);
void wapp_cqualifier_list_push_back(CQualifierList *list, CQualifierNode *node);
void wapp_cqualifier_list_insert(CQualifierList *list, CQualifierNode *node, u64 index);
CQualifierNode *wapp_cqualifier_list_pop_front(CQualifierList *list);
CQualifierNode *wapp_cqualifier_list_pop_back(CQualifierList *list);
CQualifierNode *wapp_cqualifier_list_remove(CQualifierList *list, u64 index);
void wapp_cqualifier_list_empty(CQualifierList *list);
CIncludeNode *wapp_cinclude_list_get(const CIncludeList *list, u64 index);
void wapp_cinclude_list_push_front(CIncludeList *list, CIncludeNode *node);
void wapp_cinclude_list_push_back(CIncludeList *list, CIncludeNode *node);
void wapp_cinclude_list_insert(CIncludeList *list, CIncludeNode *node, u64 index);
CIncludeNode *wapp_cinclude_list_pop_front(CIncludeList *list);
CIncludeNode *wapp_cinclude_list_pop_back(CIncludeList *list);
CIncludeNode *wapp_cinclude_list_remove(CIncludeList *list, u64 index);
void wapp_cinclude_list_empty(CIncludeList *list);
CUserTypeNode *wapp_cusertype_list_get(const CUserTypeList *list, u64 index);
void wapp_cusertype_list_push_front(CUserTypeList *list, CUserTypeNode *node);
void wapp_cusertype_list_push_back(CUserTypeList *list, CUserTypeNode *node);
void wapp_cusertype_list_insert(CUserTypeList *list, CUserTypeNode *node, u64 index);
CUserTypeNode *wapp_cusertype_list_pop_front(CUserTypeList *list);
CUserTypeNode *wapp_cusertype_list_pop_back(CUserTypeList *list);
CUserTypeNode *wapp_cusertype_list_remove(CUserTypeList *list, u64 index);
void wapp_cusertype_list_empty(CUserTypeList *list);
CFuncNode *wapp_cfunc_list_get(const CFuncList *list, u64 index);
void wapp_cfunc_list_push_front(CFuncList *list, CFuncNode *node);
void wapp_cfunc_list_push_back(CFuncList *list, CFuncNode *node);
void wapp_cfunc_list_insert(CFuncList *list, CFuncNode *node, u64 index);
CFuncNode *wapp_cfunc_list_pop_front(CFuncList *list);
CFuncNode *wapp_cfunc_list_pop_back(CFuncList *list);
CFuncNode *wapp_cfunc_list_remove(CFuncList *list, u64 index);
void wapp_cfunc_list_empty(CFuncList *list);
CStructNode *wapp_cstruct_list_get(const CStructList *list, u64 index);
void wapp_cstruct_list_push_front(CStructList *list, CStructNode *node);
void wapp_cstruct_list_push_back(CStructList *list, CStructNode *node);
void wapp_cstruct_list_insert(CStructList *list, CStructNode *node, u64 index);
CStructNode *wapp_cstruct_list_pop_front(CStructList *list);
CStructNode *wapp_cstruct_list_pop_back(CStructList *list);
CStructNode *wapp_cstruct_list_remove(CStructList *list, u64 index);
void wapp_cstruct_list_empty(CStructList *list);
CMacroNode *wapp_cmacro_list_get(const CMacroList *list, u64 index);
void wapp_cmacro_list_push_front(CMacroList *list, CMacroNode *node);
void wapp_cmacro_list_push_back(CMacroList *list, CMacroNode *node);
void wapp_cmacro_list_insert(CMacroList *list, CMacroNode *node, u64 index);
CMacroNode *wapp_cmacro_list_pop_front(CMacroList *list);
CMacroNode *wapp_cmacro_list_pop_back(CMacroList *list);
CMacroNode *wapp_cmacro_list_remove(CMacroList *list, u64 index);
void wapp_cmacro_list_empty(CMacroList *list);
#ifdef WAPP_PLATFORM_CPP
END_C_LINKAGE
#endif // !WAPP_PLATFORM_CPP
#endif // !DBL_LIST_H

10
ccodegen/main.c Normal file
View File

@@ -0,0 +1,10 @@
// vim:fileencoding=utf-8:foldmethod=marker
#include "datatypes.h"
#include "type_enums.h"
#include "wapp_core.h"
#include <stdio.h>
int main(void) {
return 0;
}

84
ccodegen/type_enums.h Normal file
View File

@@ -0,0 +1,84 @@
// vim:fileencoding=utf-8:foldmethod=marker
#ifndef TYPE_ENUMS_H
#define TYPE_ENUMS_H
#include "wapp_core.h"
typedef enum {
CTYPE_VOID,
CTYPE_B32,
CTYPE_CHAR,
CTYPE_C8,
CTYPE_C16,
CTYPE_C32,
CTYPE_I8,
CTYPE_I16,
CTYPE_I32,
CTYPE_I64,
CTYPE_U8,
CTYPE_U16,
CTYPE_U32,
CTYPE_U64,
CTYPE_F32,
CTYPE_F64,
CTYPE_F128,
CTYPE_IPTR,
CTYPE_UPTR,
COUNT_CTYPE,
} CType;
internal Str8RO ctypes[COUNT_CTYPE] = {
[CTYPE_VOID] = wapp_str8_lit_ro("void"),
[CTYPE_B32] = wapp_str8_lit_ro("b32"),
[CTYPE_CHAR] = wapp_str8_lit_ro("char"),
[CTYPE_C8] = wapp_str8_lit_ro("c8"),
[CTYPE_C16] = wapp_str8_lit_ro("c16"),
[CTYPE_C32] = wapp_str8_lit_ro("c32"),
[CTYPE_I8] = wapp_str8_lit_ro("i8"),
[CTYPE_I16] = wapp_str8_lit_ro("i16"),
[CTYPE_I32] = wapp_str8_lit_ro("i32"),
[CTYPE_I64] = wapp_str8_lit_ro("i64"),
[CTYPE_U8] = wapp_str8_lit_ro("u8"),
[CTYPE_U16] = wapp_str8_lit_ro("u16"),
[CTYPE_U32] = wapp_str8_lit_ro("u32"),
[CTYPE_U64] = wapp_str8_lit_ro("u64"),
[CTYPE_F32] = wapp_str8_lit_ro("f32"),
[CTYPE_F64] = wapp_str8_lit_ro("f64"),
[CTYPE_F128] = wapp_str8_lit_ro("f128"),
[CTYPE_IPTR] = wapp_str8_lit_ro("iptr"),
[CTYPE_UPTR] = wapp_str8_lit_ro("uptr"),
};
typedef enum {
CQUALIFIER_NONE,
CQUALIFIER_CONST,
CQUALIFIER_EXTERNAL,
CQUALIFIER_INTERNAL,
CQUALIFIER_PERSISTENT,
COUNT_CQUALIFIER,
} CQualifier;
internal Str8RO cqualifiers[COUNT_CQUALIFIER] = {
[CQUALIFIER_NONE] = wapp_str8_lit_ro(""),
[CQUALIFIER_CONST] = wapp_str8_lit_ro("const "),
[CQUALIFIER_EXTERNAL] = wapp_str8_lit_ro("external "),
[CQUALIFIER_INTERNAL] = wapp_str8_lit_ro("internal "),
[CQUALIFIER_PERSISTENT] = wapp_str8_lit_ro("persistent "),
};
typedef enum {
CPOINTERTYPE_NONE,
CPOINTERTYPE_SINGLE,
CPOINTERTYPE_DOUBLE,
COUNT_CPOINTERTYPE,
} CPointerType;
internal Str8RO cpointertypes[COUNT_CPOINTERTYPE] = {
[CPOINTERTYPE_NONE] = wapp_str8_lit_ro(""),
[CPOINTERTYPE_SINGLE] = wapp_str8_lit_ro("*"),
[CPOINTERTYPE_DOUBLE] = wapp_str8_lit_ro("**"),
};
#endif // !TYPE_ENUMS_H

60
codegen/__main__.py Normal file
View File

@@ -0,0 +1,60 @@
import json
from typing import Dict
from pathlib import Path
from codegen.datatypes import CDataType, CStruct
from codegen.constants import WAPP_REPO_ROOT, DBL_LIST_DATA, ARRAY_DATA
from codegen.dbl_list.make_dbl_list import DblListData, make_dbl_list
from codegen.array.make_array import ArrayData, make_array
def main(types_file: Path | None):
dbl_list_datatypes: Dict[CDataType, DblListData] = {}
array_datatypes: Dict[CDataType, ArrayData] = {}
if types_file is not None:
with types_file.open("r") as infile:
datatypes = json.load(infile)
dbl_list_data = datatypes.get(DBL_LIST_DATA)
array_data = datatypes.get(ARRAY_DATA)
if dbl_list_data is not None and isinstance(dbl_list_data, dict):
dbl_list_datatypes = {k: DblListData.from_dict(v) for k, v in dbl_list_data.items()}
if array_data is not None and isinstance(array_data, dict):
array_datatypes = {k: ArrayData.from_dict(v) for k, v in array_data.items()}
make_dbl_list(dbl_list_datatypes)
make_array(array_datatypes)
# Save example types file
custom_struct = CStruct(name="custom_type", cargs=[], typedef_name="CustomType")
example = {
DBL_LIST_DATA: {
"CustomType": DblListData(
node_typename="CustomTypeNode",
list_typename="CustomTypeList",
hdr_decl_types=[custom_struct],
).to_dict()
},
ARRAY_DATA: {
"CustomType": ArrayData(
array_typename="CustomTypeArray",
hdr_decl_types=[custom_struct],
).to_dict()
},
}
example_file = WAPP_REPO_ROOT / "codegen_custom_data_example.json"
with example_file.open("w") as outfile:
json.dump(example, outfile, indent=2)
if __name__ == "__main__":
from argparse import ArgumentParser
parser = ArgumentParser()
parser.add_argument("-f", "--types-file", type=Path, help="JSON file containing custom types for codegen")
args = parser.parse_args()
main(args.types_file)

435
codegen/array/make_array.py Normal file
View File

@@ -0,0 +1,435 @@
from pathlib import Path
from dataclasses import dataclass, field
from typing import List, Dict, Any, Type
from codegen.constants import WAPP_SRC_ROOT
from codegen.utils import load_func_body_from_file, convert_to_relative
from codegen.datatypes import (
CDataType,
CMacro,
CStruct,
CFunc,
CHeader,
CSource,
CArg,
CType,
CPointer,
CPointerType,
CQualifier,
CInclude,
SerialisableDataclass,
get_datatype_string,
)
@dataclass
class ArrayData(SerialisableDataclass):
array_typename: str
hdr_decl_types: List[CStruct] = field(default_factory=list)
src_decl_types: List[CStruct] = field(default_factory=list)
@classmethod
def from_dict(cls: Type["ArrayData"], d: Dict[str, Any]) -> "ArrayData":
data = ArrayData(**d)
data.hdr_decl_types = [CStruct.from_dict(v) for v in data.hdr_decl_types if isinstance(v, dict)]
data.src_decl_types = [CStruct.from_dict(v) for v in data.src_decl_types if isinstance(v, dict)]
return data
def make_array(user_datatypes: Dict[CDataType, ArrayData] = {}):
def __format_func_body(
filename: Path,
type_string: str,
type_string_upper: str,
type_string_lower: str,
array_typename: str
):
return load_func_body_from_file(filename).format(
T=type_string,
ArrayType=array_typename,
Tupper=type_string_upper,
Tlower=type_string_lower,
)
out_dir = WAPP_SRC_ROOT / "primitives" / "array"
out_dir.mkdir(parents=True, exist_ok=True)
common_includes: List[CInclude] = [
CInclude(
header=str(convert_to_relative(WAPP_SRC_ROOT / "primitives" / "mem_allocator" / "mem_allocator.h", out_dir)).replace("\\", "/"),
local=True,
),
CInclude(
header=str(convert_to_relative(WAPP_SRC_ROOT / "common" / "misc" / "misc_utils.h", out_dir)).replace("\\", "/"),
local=True,
),
]
common_decl_types: List[CStruct] = []
datatypes: dict[CDataType, ArrayData] = {
CType.VOID: ArrayData(array_typename="GenericArray"),
"void *": ArrayData(array_typename="VoidPArray"),
"Str8": ArrayData(
array_typename="Str8Array",
hdr_decl_types=[
CStruct(name="str8", cargs=[], typedef_name="Str8"),
],
),
}
for _type in CType:
if _type == CType.VOID:
continue
type_title = _type.value.title()
datatypes[_type] = ArrayData(
array_typename=f"{type_title}Array",
)
datatypes.update(user_datatypes)
snippets_dir = Path(__file__).parent / "snippets"
header = CHeader(
name="array",
decl_types=[*common_decl_types],
includes=[],
types=[],
funcs=[]
)
source = CSource(
name=header.name,
decl_types=[*common_decl_types],
includes=[
CInclude(header, local=True, same_dir=True),
CInclude(
header=str(convert_to_relative(WAPP_SRC_ROOT / "common" / "assert" / "assert.h", out_dir)).replace("\\", "/"),
local=True
),
CInclude(header="stddef.h"),
],
internal_funcs=[],
funcs=header.funcs
)
if len(common_includes) > 0:
header.includes.extend(common_includes)
source.includes.extend(common_includes)
generic_funcs = []
for _type, array_data in datatypes.items():
type_string = get_datatype_string(_type)
clean_type_string = type_string.replace(" ", "").replace("*", "_ptr")
type_string_upper = clean_type_string.upper()
type_string_lower = clean_type_string.lower()
array = CStruct(
name=array_data.array_typename,
cargs=[
CArg(name="items", _type=type_string, pointer=CPointer(_type=CPointerType.SINGLE)),
CArg(name="count", _type=CType.U64),
CArg(name="capacity", _type=CType.U64),
CArg(name="item_size", _type=CType.U64),
],
)
if isinstance(_type, CType) and _type == CType.VOID:
alloc_capacity_func = CFunc(
name=f"_array_alloc_capacity",
ret_type=array,
args=[
CArg(name="allocator", _type="Allocator", pointer=CPointer(CPointerType.SINGLE), qualifier=CQualifier.CONST),
CArg(name="capacity", _type=CType.U64),
CArg(name="item_size", _type=CType.U64),
],
body=__format_func_body(
filename=snippets_dir / "alloc_capacity",
type_string=type_string,
type_string_upper=type_string_upper,
type_string_lower=type_string_lower,
array_typename=array_data.array_typename,
),
pointer=CPointer(CPointerType.SINGLE),
)
generic_funcs.append(alloc_capacity_func)
else:
stack_array_cmacro = CMacro(
name=f"wapp_{type_string_lower}_array(...)",
value=__format_func_body(
filename=snippets_dir / "stack_array",
type_string=type_string,
type_string_upper=type_string_upper,
type_string_lower=type_string_lower,
array_typename=array_data.array_typename,
),
)
stack_array_cppmacro = CMacro(
name=f"wapp_{type_string_lower}_array(...)",
value=__format_func_body(
filename=snippets_dir / "stack_array_cpp",
type_string=type_string,
type_string_upper=type_string_upper,
type_string_lower=type_string_lower,
array_typename=array_data.array_typename,
),
)
stack_capacity_array_cmacro = CMacro(
name=f"wapp_{type_string_lower}_array_with_capacity(CAPACITY)",
value=__format_func_body(
filename=snippets_dir / "stack_capacity_array",
type_string=type_string,
type_string_upper=type_string_upper,
type_string_lower=type_string_lower,
array_typename=array_data.array_typename,
),
)
stack_capacity_array_cppmacro = CMacro(
name=f"wapp_{type_string_lower}_array_with_capacity(CAPACITY)",
value=__format_func_body(
filename=snippets_dir / "stack_capacity_array_cpp",
type_string=type_string,
type_string_upper=type_string_upper,
type_string_lower=type_string_lower,
array_typename=array_data.array_typename,
),
)
alloc_capacity_array_macro = CMacro(
name=f"wapp_{type_string_lower}_array_alloc_capacity(ALLOCATOR_PTR, CAPACITY)",
value=__format_func_body(
filename=snippets_dir / "alloc_capacity_macro",
type_string=type_string,
type_string_upper=type_string_upper,
type_string_lower=type_string_lower,
array_typename=array_data.array_typename,
),
)
array_pop_cmacro = CMacro(
name=f"wapp_{type_string_lower}_array_pop(ARRAY_PTR)",
value=__format_func_body(
filename=snippets_dir / "array_pop_macro",
type_string=type_string,
type_string_upper=type_string_upper,
type_string_lower=type_string_lower,
array_typename=array_data.array_typename,
),
)
array_pop_cppmacro = CMacro(
name=f"wapp_{type_string_lower}_array_pop(ARRAY_PTR)",
value=__format_func_body(
filename=snippets_dir / "array_pop_macro_cpp",
type_string=type_string,
type_string_upper=type_string_upper,
type_string_lower=type_string_lower,
array_typename=array_data.array_typename,
),
)
get_func = CFunc(
name=f"wapp_{type_string_lower}_array_get",
ret_type=type_string,
args=[
CArg(name="array", _type=array, pointer=CPointer(CPointerType.SINGLE), qualifier=CQualifier.CONST),
CArg(name="index", _type=CType.U64),
],
body=__format_func_body(
filename=snippets_dir / "array_get",
type_string=type_string,
type_string_upper=type_string_upper,
type_string_lower=type_string_lower,
array_typename=array_data.array_typename,
),
pointer=CPointer(CPointerType.SINGLE),
)
set_func = CFunc(
name=f"wapp_{type_string_lower}_array_set",
ret_type=CType.VOID,
args=[
CArg(name="array", _type=array, pointer=CPointer(CPointerType.SINGLE)),
CArg(name="index", _type=CType.U64),
CArg(name="item", _type=type_string, pointer=CPointer(CPointerType.SINGLE)),
],
body=__format_func_body(
filename=snippets_dir / "array_set",
type_string=type_string,
type_string_upper=type_string_upper,
type_string_lower=type_string_lower,
array_typename=array_data.array_typename,
),
)
append_capped_func = CFunc(
name=f"wapp_{type_string_lower}_array_append_capped",
ret_type=CType.VOID,
args=[
CArg(name="array", _type=array, pointer=CPointer(CPointerType.SINGLE)),
CArg(name="item", _type=type_string, pointer=CPointer(CPointerType.SINGLE)),
],
body=__format_func_body(
filename=snippets_dir / "append_capped",
type_string=type_string,
type_string_upper=type_string_upper,
type_string_lower=type_string_lower,
array_typename=array_data.array_typename,
),
)
extend_capped_func = CFunc(
name=f"wapp_{type_string_lower}_array_extend_capped",
ret_type=CType.VOID,
args=[
CArg(name="array", _type=array, pointer=CPointer(CPointerType.SINGLE)),
CArg(name="other", _type=array, pointer=CPointer(CPointerType.SINGLE), qualifier=CQualifier.CONST),
],
body=__format_func_body(
filename=snippets_dir / "extend_capped",
type_string=type_string,
type_string_upper=type_string_upper,
type_string_lower=type_string_lower,
array_typename=array_data.array_typename,
),
)
clear_func = CFunc(
name=f"wapp_{type_string_lower}_array_clear",
ret_type=CType.VOID,
args=[
CArg(name="array", _type=array, pointer=CPointer(CPointerType.SINGLE)),
],
body=__format_func_body(
filename=snippets_dir / "clear",
type_string=type_string,
type_string_upper=type_string_upper,
type_string_lower=type_string_lower,
array_typename=array_data.array_typename,
),
)
copy_capped_func = CFunc(
name=f"wapp_{type_string_lower}_array_copy_capped",
ret_type=CType.VOID,
args=[
CArg(name="src", _type=array, pointer=CPointer(CPointerType.SINGLE), qualifier=CQualifier.CONST),
CArg(name="dst", _type=array, pointer=CPointer(CPointerType.SINGLE)),
],
body=__format_func_body(
filename=snippets_dir / "copy_capped",
type_string=type_string,
type_string_upper=type_string_upper,
type_string_lower=type_string_lower,
array_typename=array_data.array_typename,
),
)
append_alloc_func = CFunc(
name=f"wapp_{type_string_lower}_array_append_alloc",
ret_type=array,
args=[
CArg(name="allocator", _type="Allocator", pointer=CPointer(CPointerType.SINGLE), qualifier=CQualifier.CONST),
CArg(name="array", _type=array, pointer=CPointer(CPointerType.SINGLE)),
CArg(name="item", _type=type_string, pointer=CPointer(CPointerType.SINGLE)),
],
body=__format_func_body(
filename=snippets_dir / "append_alloc",
type_string=type_string,
type_string_upper=type_string_upper,
type_string_lower=type_string_lower,
array_typename=array_data.array_typename,
),
pointer=CPointer(CPointerType.SINGLE),
)
extend_alloc_func = CFunc(
name=f"wapp_{type_string_lower}_array_extend_alloc",
ret_type=array,
args=[
CArg(name="allocator", _type="Allocator", pointer=CPointer(CPointerType.SINGLE), qualifier=CQualifier.CONST),
CArg(name="array", _type=array, pointer=CPointer(CPointerType.SINGLE)),
CArg(name="other", _type=array, pointer=CPointer(CPointerType.SINGLE), qualifier=CQualifier.CONST),
],
body=__format_func_body(
filename=snippets_dir / "extend_alloc",
type_string=type_string,
type_string_upper=type_string_upper,
type_string_lower=type_string_lower,
array_typename=array_data.array_typename,
),
pointer=CPointer(CPointerType.SINGLE),
)
copy_alloc_func = CFunc(
name=f"wapp_{type_string_lower}_array_copy_alloc",
ret_type=array,
args=[
CArg(name="allocator", _type="Allocator", pointer=CPointer(CPointerType.SINGLE), qualifier=CQualifier.CONST),
CArg(name="src", _type=array, pointer=CPointer(CPointerType.SINGLE), qualifier=CQualifier.CONST),
CArg(name="dst", _type=array, pointer=CPointer(CPointerType.SINGLE)),
],
body=__format_func_body(
filename=snippets_dir / "copy_alloc",
type_string=type_string,
type_string_upper=type_string_upper,
type_string_lower=type_string_lower,
array_typename=array_data.array_typename,
),
pointer=CPointer(CPointerType.SINGLE),
)
pop_func = CFunc(
name=f"_{type_string_lower}_array_pop",
ret_type=type_string,
args=[
CArg(name="array", _type=array, pointer=CPointer(CPointerType.SINGLE)),
],
body=__format_func_body(
filename=snippets_dir / "array_pop",
type_string=type_string,
type_string_upper=type_string_upper,
type_string_lower=type_string_lower,
array_typename=array_data.array_typename,
),
pointer=CPointer(CPointerType.SINGLE),
)
header.macros.extend([
alloc_capacity_array_macro,
])
header.c_macros.extend([
stack_array_cmacro,
stack_capacity_array_cmacro,
array_pop_cmacro,
])
header.cpp_macros.extend([
stack_array_cppmacro,
stack_capacity_array_cppmacro,
array_pop_cppmacro,
])
header.funcs.extend([
get_func,
set_func,
append_capped_func,
extend_capped_func,
clear_func,
copy_capped_func,
append_alloc_func,
extend_alloc_func,
copy_alloc_func,
pop_func,
])
header.decl_types.extend(array_data.hdr_decl_types)
header.types.extend([array])
source.decl_types.extend(array_data.src_decl_types)
source.funcs = header.funcs
header.funcs.extend(generic_funcs)
header.save(out_dir)
source.save(out_dir)

View File

@@ -0,0 +1,15 @@
wapp_debug_assert(allocator != NULL, "`allocator` should not be NULL");
u64 allocation_size = sizeof({ArrayType}) + item_size * capacity;
{ArrayType} *array = wapp_mem_allocator_alloc(allocator, allocation_size);
if (!array) {{
goto RETURN_GENERIC_ARRAY_ALLOC;
}}
array->items = ({T} *)((u8 *)array + sizeof({ArrayType}));
array->count = 0;
array->capacity = capacity;
array->item_size = item_size;
RETURN_GENERIC_ARRAY_ALLOC:
return array;

View File

@@ -0,0 +1 @@
(({ArrayType} *)_array_alloc_capacity(ALLOCATOR_PTR, CAPACITY, sizeof({T})))

View File

@@ -0,0 +1,18 @@
wapp_debug_assert(allocator != NULL && array != NULL, "`allocator` and `array` should not be NULL");
{ArrayType} *output = array;
if (array->count >= array->capacity) {{
u64 new_capacity = wapp_misc_utils_u64_round_up_pow2(array->capacity * 2);
output = ({ArrayType} *)_array_alloc_capacity(allocator, new_capacity, array->item_size);
if (!output) {{
output = array;
goto RETURN_{Tupper}_ARRAY_APPEND_ALLOC;
}}
wapp_{Tlower}_array_copy_capped(array, output);
}}
wapp_{Tlower}_array_append_capped(output, item);
RETURN_{Tupper}_ARRAY_APPEND_ALLOC:
return output;

View File

@@ -0,0 +1,5 @@
wapp_debug_assert(array != NULL, "`array` should not be NULL");
wapp_runtime_assert(array->count < array->capacity, "`array` is full");
u64 index = (array->count)++;
wapp_{Tlower}_array_set(array, index, item);

View File

@@ -0,0 +1,5 @@
wapp_debug_assert(array != NULL, "`array` should not be NULL");
wapp_runtime_assert(index < array->count, "`index` is out of bounds");
u8 *ptr = (u8 *)(array->items) + (array->item_size * index);
return ({T} *)ptr;

View File

@@ -0,0 +1,4 @@
u64 index = array->count - 1;
{T} *out = wapp_{Tlower}_array_get(array, index);
--(array->count);
return out;

View File

@@ -0,0 +1,4 @@
(ARRAY_PTR != NULL && (ARRAY_PTR)->count > 0 ? \
*_{Tlower}_array_pop(ARRAY_PTR) : \
({T}){{0}} \
)

View File

@@ -0,0 +1,4 @@
(ARRAY_PTR != NULL && (ARRAY_PTR)->count > 0 ? \
*_{Tlower}_array_pop(ARRAY_PTR) : \
{T}{{}} \
)

View File

@@ -0,0 +1,3 @@
{T} *ptr = wapp_{Tlower}_array_get(array, index);
memcpy((void *)ptr, (void *)item, array->item_size);

View File

@@ -0,0 +1,2 @@
wapp_debug_assert(array != NULL, "`array` should not be NULL");
array->count = 0;

View File

@@ -0,0 +1,18 @@
wapp_debug_assert(allocator != NULL && src != NULL && dst != NULL, "`allocator`, `src` and `dst` should not be NULL");
{ArrayType} *output = dst;
if (src->count >= dst->capacity) {{
u64 new_capacity = wapp_misc_utils_u64_round_up_pow2(dst->capacity * 2);
output = ({ArrayType} *)_array_alloc_capacity(allocator, new_capacity, src->item_size);
if (!output) {{
output = dst;
goto RETURN_{Tupper}_ARRAY_COPY_ALLOC;
}}
}}
wapp_{Tlower}_array_clear(output);
wapp_{Tlower}_array_copy_capped(src, output);
RETURN_{Tupper}_ARRAY_COPY_ALLOC:
return output;

View File

@@ -0,0 +1,22 @@
wapp_debug_assert(src != NULL && dst != NULL, "`src` and `dst` should not be NULL");
wapp_{Tlower}_array_clear(dst);
{T} *item;
// NOTE (Abdelrahman): Uses a while loop instead of a for loop to get rid of
// MSVC Spectre mitigation warnings
u64 to_copy = src->count < dst->capacity ? src->count : dst->capacity;
u64 item_index = 0;
b32 running = true;
while (running) {{
item = wapp_{Tlower}_array_get(src, item_index);
++item_index;
running = item_index < to_copy;
if (!item) {{
continue;
}}
wapp_{Tlower}_array_append_capped(dst, item);
}}

View File

@@ -0,0 +1,19 @@
wapp_debug_assert(allocator != NULL && array != NULL && other != NULL, "`allocator`, `array` and `other` should not be NULL");
{ArrayType} *output = array;
u64 remaining_capacity = array->capacity - array->count;
if (other->count >= remaining_capacity) {{
u64 new_capacity = wapp_misc_utils_u64_round_up_pow2(array->capacity * 2);
output = ({ArrayType} *)_array_alloc_capacity(allocator, new_capacity, array->item_size);
if (!output) {{
output = array;
goto RETURN_{Tupper}_ARRAY_EXTEND_ALLOC;
}}
wapp_{Tlower}_array_copy_capped(array, output);
}}
wapp_{Tlower}_array_extend_capped(output, other);
RETURN_{Tupper}_ARRAY_EXTEND_ALLOC:
return output;

View File

@@ -0,0 +1,23 @@
wapp_debug_assert(array != NULL && other != NULL, "`array` and `other` should not be NULL");
u64 remaining_capacity = array->capacity - array->count;
wapp_runtime_assert(other->count < remaining_capacity, "`array` does not have enough capacity");
{T} *item;
// NOTE (Abdelrahman): Uses a while loop instead of a for loop to get rid of
// MSVC Spectre mitigation warnings
u64 items_to_add = other->count;
u64 item_index = 0;
b32 running = true;
while (running) {{
item = wapp_{Tlower}_array_get(other, item_index);
++item_index;
running = item_index < items_to_add;
if (!item) {{
continue;
}}
wapp_{Tlower}_array_append_capped(array, item);
}}

View File

@@ -0,0 +1,6 @@
(({ArrayType}){{ \
.items = ({T}[wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count({T}, __VA_ARGS__) * 2)]){{__VA_ARGS__}}, \
.count = wapp_misc_utils_va_args_count({T}, __VA_ARGS__), \
.capacity = wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count({T}, __VA_ARGS__) * 2), \
.item_size = sizeof({T}) \
}})

View File

@@ -0,0 +1,9 @@
([&]() {{ \
persistent {T} buf[wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count({T}, __VA_ARGS__) * 2)] = {{__VA_ARGS__}}; \
return {ArrayType}{{ \
buf, \
wapp_misc_utils_va_args_count({T}, __VA_ARGS__), \
wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count({T}, __VA_ARGS__) * 2), \
sizeof({T}) \
}}; \
}}())

View File

@@ -0,0 +1 @@
(({ArrayType}){{.items = ({T}[CAPACITY]){{0}}, .count = 0, .capacity = CAPACITY, .item_size = sizeof({T})}})

View File

@@ -0,0 +1,4 @@
([&]() {{ \
persistent {T} buf[CAPACITY] = {{}}; \
return {ArrayType}{{buf, 0, CAPACITY, sizeof({T})}}; \
}}())

10
codegen/constants.py Normal file
View File

@@ -0,0 +1,10 @@
from pathlib import Path
# Paths
PACKAGE_DIR = Path(__file__).parent.resolve()
WAPP_REPO_ROOT = PACKAGE_DIR.parent
WAPP_SRC_ROOT = WAPP_REPO_ROOT / "src"
# Dictionary Keys
DBL_LIST_DATA = "dbl_list_data"
ARRAY_DATA = "array_data"

503
codegen/datatypes.py Normal file
View File

@@ -0,0 +1,503 @@
from enum import Enum
from pathlib import Path
from typing import Optional, Union, List, Dict, Type, Any, TypeVar, cast
from dataclasses import dataclass, asdict, field, fields
from codegen.constants import WAPP_SRC_ROOT
from codegen.utils import convert_to_relative
E = TypeVar("E", bound="Enum")
S = TypeVar("S", bound="SerialisableDataclass")
F = TypeVar("F", bound="CFile")
@dataclass
class SerialisableDataclass:
def to_dict(self) -> Dict[str, Any]:
d = asdict(self)
for f in fields(self):
member = getattr(self, f.name)
if isinstance(member, list):
d[f.name] = [self.__serialise_member(i) for i in member]
else:
d[f.name] = self.__serialise_member(member)
return d
def __serialise_member(self, member: Any) -> Any:
if isinstance(member, Enum):
return member.value
elif isinstance(member, SerialisableDataclass):
return member.to_dict()
return member
@staticmethod
def to_enum_value(value: Any, _type: Type[E]) -> "E":
if isinstance(value, _type):
return value
return _type(value)
@staticmethod
def to_c_usertype(value: dict[str, Any]) -> "CUserType":
try:
output = CStruct.from_dict(value)
except TypeError:
output = CEnum.from_dict(value)
return output
@staticmethod
def to_cdatatype(value: Any) -> "CDataType":
if isinstance(value, dict):
output = SerialisableDataclass.to_c_usertype(value)
else:
try:
output = CType(value)
except ValueError:
output = value
return output
@classmethod
def from_dict(cls: Type[S], d: Dict[str, Any]) -> "S":
return cls(**d)
class CType(Enum):
VOID = "void"
BOOL = "b32"
CHAR = "char"
C8 = "c8"
C16 = "c16"
C32 = "c32"
I8 = "i8"
I16 = "i16"
I32 = "i32"
I64 = "i64"
U8 = "u8"
U16 = "u16"
U32 = "u32"
U64 = "u64"
F32 = "f32"
F64 = "f64"
F128 = "f128"
IPTR = "iptr"
UPTR = "uptr"
def __str__(self) -> str:
return self.value
class CQualifier(Enum):
NONE = ""
CONST = "const "
EXTERNAL = "external "
INTERNAL = "internal "
PERSISTENT = "persistent "
def __str__(self) -> str:
return self.value
class CPointerType(Enum):
NONE = ""
SINGLE = "*"
DOUBLE = "**"
def __str__(self) -> str:
return self.value
@dataclass
class CPointer(SerialisableDataclass):
_type: CPointerType = CPointerType.NONE
qualifier: CQualifier = CQualifier.NONE
def __str__(self) -> str:
return str(self._type) + str(self.qualifier)
@classmethod
def from_dict(cls: Type["CPointer"], d: Dict[str, Any]) -> "CPointer":
ptr = CPointer(**d)
ptr._type = CPointer.to_enum_value(ptr._type, CPointerType)
ptr.qualifier = CPointer.to_enum_value(ptr.qualifier, CQualifier)
return ptr
@dataclass
class CEnumVal(SerialisableDataclass):
name: str
value: Optional[int] = None
def __str__(self) -> str:
return self.name + "" if self.value is None else f" = {self.value}"
@dataclass
class CEnum(SerialisableDataclass):
name: str
values: List[CEnumVal]
typedef: bool = False
def __str__(self) -> str:
if self.typedef:
header = "typedef enum {\n"
footer = f"}} {self.name};\n"
else:
header = f"enum {self.name} {{\n"
footer = "};\n"
values = ""
for value in self.values:
values += f" {str(value)},\n"
return header + values + footer
@classmethod
def from_dict(cls: Type["CEnum"], d: Dict[str, Any]) -> "CEnum":
e = CEnum(**d)
e.values = [CEnumVal.from_dict(v) for v in e.values if isinstance(v, dict)]
return e
@dataclass
class CMacro(SerialisableDataclass):
name: str
value: str
def __str__(self) -> str:
return f"#define {self.name} {self.value}\n"
@dataclass
class CStruct(SerialisableDataclass):
name: str
cargs: List["CArg"]
typedef_name: Optional[str] = None
def __str__(self) -> str:
return self.declare() + self.define()
def declare(self) -> str:
declaration = f"typedef struct {self.name} {self.typedef_name if self.typedef_name is not None else self.name};\n"
return declaration
def define(self):
definition = f"struct {self.name} {{\n"
args = ""
for arg in self.cargs:
args += f" {str(arg)};\n"
footer = "};\n"
return definition + args + footer;
@classmethod
def from_dict(cls: Type["CStruct"], d: Dict[str, Any]) -> "CStruct":
s = CStruct(**d)
s.cargs = [CArg.from_dict(v) for v in s.cargs if isinstance(v, dict)]
return s
CUserType = Union[CStruct, CEnum]
CDataType = Union[CType, CUserType, str]
@dataclass
class CArg(SerialisableDataclass):
name: str
_type: CDataType
array: bool = False
pointer: CPointer = field(default_factory=CPointer)
qualifier: CQualifier = CQualifier.NONE
def __str__(self) -> str:
qualifier = str(self.qualifier)
_type = get_datatype_string(self._type) + " "
pointer = str(self.pointer)
array = "[]" if self.array else ""
return qualifier + _type + pointer + self.name + array
@classmethod
def from_dict(cls: Type["CArg"], d: Dict[str, Any]) -> "CArg":
arg = CArg(**d)
arg._type = CArg.to_cdatatype(arg._type)
if isinstance(arg.pointer, dict):
arg.pointer = CPointer.from_dict(arg.pointer)
arg.qualifier = CArg.to_enum_value(arg.qualifier, CQualifier)
return arg
@dataclass
class CFunc(SerialisableDataclass):
name: str
ret_type: CDataType
args: List[CArg]
body: str
pointer: CPointer = field(default_factory=CPointer)
qualifiers: List[CQualifier] = field(default_factory=list)
def __str__(self) -> str:
qualifiers = ""
for qualifier in self.qualifiers:
if qualifier == CQualifier.NONE:
continue
if len(qualifiers) > 0:
qualifiers += " "
qualifiers += f"{str(qualifier)}"
args = ""
for i, arg in enumerate(self.args):
args += f"{str(arg)}"
if i + 1 < len(self.args):
args += ", "
return qualifiers + get_datatype_string(self.ret_type) + " " + str(self.pointer) + self.name + f"({args})"
def declare(self) -> str:
return f"{str(self)};\n"
def define(self) -> str:
return f"{str(self)} {{\n{self.body}\n}}\n\n"
@classmethod
def from_dict(cls: Type["CFunc"], d: Dict[str, Any]) -> "CFunc":
f = CFunc(**d)
f.ret_type = CFunc.to_cdatatype(f.ret_type)
f.args = [CArg.from_dict(v) for v in f.args if isinstance(v, dict)]
f.qualifiers = [CFunc.to_enum_value(v, CQualifier) for v in f.qualifiers]
if isinstance(f.pointer, dict):
f.pointer = CPointer.from_dict(f.pointer)
return f
@dataclass
class CInclude(SerialisableDataclass):
header: Union[str, "CHeader"]
local: bool = False
same_dir: bool = False
def __str__(self) -> str:
if isinstance(self.header, CHeader):
name = f"{self.header.name}.{self.header.extension}"
else:
name = self.header
if self.local:
open_symbol = '"'
close_symbol = '"'
if self.same_dir:
name = f"./{name}"
else:
open_symbol = '<'
close_symbol = '>'
return f"#include {open_symbol}{name}{close_symbol}\n"
@classmethod
def from_dict(cls: Type["CInclude"], d: Dict[str, Any]) -> "CInclude":
inc = CInclude(**d)
if isinstance(inc.header, dict):
inc.header = CHeader.from_dict(inc.header)
return inc
@dataclass
class CFile(SerialisableDataclass):
name: str
extension: str
includes: List[CInclude] = field(default_factory=list)
types: List[CUserType] = field(default_factory=list)
funcs: List[CFunc] = field(default_factory=list)
decl_types: List[CStruct] = field(default_factory=list)
macros: List[CMacro] = field(default_factory=list)
c_macros: List[CMacro] = field(default_factory=list)
cpp_macros: List[CMacro] = field(default_factory=list)
def save(self, output_dir: Path):
self.includes.extend(
[
CInclude(
header=str(convert_to_relative(WAPP_SRC_ROOT / "common" / "aliases" / "aliases.h", output_dir)).replace("\\", "/"),
local=True,
),
CInclude(
header=str(convert_to_relative(WAPP_SRC_ROOT / "common" / "platform" / "platform.h", output_dir)).replace("\\", "/"),
local=True,
)
]
)
output_file = output_dir / f"{self.name}.{self.extension}"
with open(output_file, "w+") as outfile:
outfile.write(str(self))
def __str__(self) -> str:
return """\
/**
* THIS FILE IS AUTOMATICALLY GENERATED. ANY MODIFICATIONS TO IT WILL BE OVERWRITTEN.
*/
"""
@classmethod
def from_dict(cls: Type["CFile"], d: Dict[str, Any]) -> "CFile":
f = CFile(**d)
f.deserialise_c_file_data()
return f
def deserialise_c_file_data(self) -> None:
self.includes = [CInclude.from_dict(v) for v in self.includes if isinstance(v, dict)]
self.types = [CFile.to_c_usertype(v) for v in self.types if isinstance(v, dict)]
self.funcs = [CFunc.from_dict(v) for v in self.funcs if isinstance(v, dict)]
self.decl_types = [CStruct.from_dict(v) for v in self.decl_types if isinstance(v, dict)]
self.macros = [CMacro.from_dict(v) for v in self.macros if isinstance(v, dict)]
self.c_macros = [CMacro.from_dict(v) for v in self.c_macros if isinstance(v, dict)]
self.cpp_macros = [CMacro.from_dict(v) for v in self.cpp_macros if isinstance(v, dict)]
@dataclass
class CHeader(CFile):
extension: str = "h"
def __str__(self) -> str:
name_upper = self.name.upper()
header_guard_name = f"{name_upper}_H"
header_guard_open = f"#ifndef {header_guard_name}\n#define {header_guard_name}\n\n"
header_guard_close = f"#endif // !{header_guard_name}\n"
c_linkage_open = "#ifdef WAPP_PLATFORM_CPP\nBEGIN_C_LINKAGE\n#endif // !WAPP_PLATFORM_CPP\n\n"
c_linkage_close = "\n#ifdef WAPP_PLATFORM_CPP\nEND_C_LINKAGE\n#endif // !WAPP_PLATFORM_CPP\n\n"
includes = _get_includes_string(self.includes)
macros = ""
for macro in self.macros:
macros += str(macro)
if len(macros) > 0:
macros += "\n"
if len(self.cpp_macros) > 0:
macros += "#ifdef WAPP_PLATFORM_CPP\n"
for macro in self.cpp_macros:
macros += str(macro)
macros += "#else\n"
for macro in self.c_macros:
macros += str(macro)
macros += "#endif // !WAPP_PLATFORM_CPP\n\n"
forward_declarations = ""
for _type in self.decl_types:
forward_declarations += _type.declare()
if len(forward_declarations) > 0:
forward_declarations += "\n"
types = ""
for _type in self.types:
types += str(_type) + "\n"
funcs = ""
for func in self.funcs:
funcs += func.declare()
return (
super().__str__() +
header_guard_open +
includes +
c_linkage_open +
macros +
forward_declarations +
types +
funcs +
c_linkage_close +
header_guard_close
)
@classmethod
def from_dict(cls: Type["CHeader"], d: Dict[str, Any]) -> "CHeader":
return cast("CHeader", super().from_dict(d))
@dataclass
class CSource(CFile):
extension: str = "c"
internal_funcs: List[CFunc] = field(default_factory=list)
def __str__(self) -> str:
includes = _get_includes_string(self.includes)
macros = ""
for macro in self.macros:
macros += str(macro)
if len(macros) > 0:
macros += "\n"
forward_declarations = ""
for _type in self.decl_types:
forward_declarations += _type.declare()
if len(forward_declarations) > 0:
forward_declarations += "\n"
types = ""
for _type in self.types:
types += str(_type) + "\n"
internal_funcs_decl = ""
internal_funcs_def = ""
for func in self.internal_funcs:
internal_funcs_decl += func.declare()
internal_funcs_def += func.define()
if len(internal_funcs_decl) > 0:
internal_funcs_decl += "\n"
funcs = ""
for func in self.funcs:
funcs += func.define()
return (
super().__str__() +
includes +
macros +
forward_declarations +
types +
internal_funcs_decl +
funcs +
internal_funcs_def
)
@classmethod
def from_dict(cls: Type["CSource"], d: Dict[str, Any]) -> "CSource":
s = CSource(**d)
s.deserialise_c_file_data()
s.internal_funcs = [CFunc.from_dict(v) for v in s.funcs if isinstance(v, dict)]
return s
def get_datatype_string(_type: CDataType) -> str:
if isinstance(_type, CType):
return str(_type)
elif isinstance(_type, CStruct) or isinstance(_type, CEnum):
return _type.name
elif isinstance(_type, str):
return _type
def _get_includes_string(includes: List[CInclude]) -> str:
output = ""
for include in sorted(includes, key=lambda inc: inc.local, reverse=True):
output += str(include)
if len(output) > 0:
output += "\n"
return output

View File

@@ -0,0 +1,339 @@
from pathlib import Path
from dataclasses import dataclass, field
from typing import List, Dict, Any, Type
from codegen.constants import WAPP_SRC_ROOT
from codegen.utils import load_func_body_from_file, convert_to_relative
from codegen.datatypes import (
CDataType,
CMacro,
CStruct,
CFunc,
CHeader,
CSource,
CArg,
CType,
CPointer,
CPointerType,
CQualifier,
CInclude,
SerialisableDataclass,
get_datatype_string,
)
@dataclass
class DblListData(SerialisableDataclass):
node_typename: str
list_typename: str
hdr_decl_types: List[CStruct] = field(default_factory=list)
src_decl_types: List[CStruct] = field(default_factory=list)
@classmethod
def from_dict(cls: Type["DblListData"], d: Dict[str, Any]) -> "DblListData":
data = DblListData(**d)
data.hdr_decl_types = [CStruct.from_dict(v) for v in data.hdr_decl_types if isinstance(v, dict)]
data.src_decl_types = [CStruct.from_dict(v) for v in data.src_decl_types if isinstance(v, dict)]
return data
def make_dbl_list(user_datatypes: Dict[CDataType, DblListData] = {}):
def __format_func_body(
filename: Path,
type_string: str,
type_string_upper: str,
type_string_lower: str,
node_typename: str,
list_typename: str
):
return load_func_body_from_file(filename).format(
T=type_string,
NodeType=node_typename,
ListType=list_typename,
Tupper=type_string_upper,
Tlower=type_string_lower,
)
out_dir = WAPP_SRC_ROOT / "primitives" / "dbl_list"
out_dir.mkdir(parents=True, exist_ok=True)
common_decl_types: List[CStruct] = []
datatypes: dict[CDataType, DblListData] = {
CType.VOID: DblListData(node_typename="GenericNode", list_typename="GenericList"),
"void *": DblListData(node_typename="VoidPNode", list_typename="VoidPList"),
"Str8": DblListData(
node_typename="Str8Node",
list_typename="Str8List",
hdr_decl_types=[
CStruct(name="str8", cargs=[], typedef_name="Str8"),
],
),
}
for _type in CType:
if _type == CType.VOID:
continue
type_title = _type.value.title()
datatypes[_type] = DblListData(
node_typename=f"{type_title}Node",
list_typename=f"{type_title}List",
)
datatypes.update(user_datatypes)
snippets_dir = Path(__file__).parent / "snippets"
header = CHeader(
name="dbl_list",
decl_types=[*common_decl_types],
includes=[],
types=[],
funcs=[]
)
source = CSource(
name=header.name,
decl_types=[*common_decl_types],
includes=[
CInclude(header, local=True, same_dir=True),
CInclude(
header=str(convert_to_relative(WAPP_SRC_ROOT / "common" / "assert" / "assert.h", out_dir)).replace("\\", "/"),
local=True
),
CInclude(header="stddef.h"),
],
internal_funcs=[],
funcs=header.funcs
)
for _type, dbl_list_data in datatypes.items():
type_string = get_datatype_string(_type)
clean_type_string = type_string.replace(" ", "").replace("*", "_ptr")
type_string_upper = clean_type_string.upper()
type_string_lower = clean_type_string.lower()
node = CStruct(
name=dbl_list_data.node_typename,
cargs=[
CArg(name="item", _type=type_string, pointer=CPointer(_type=CPointerType.SINGLE)),
],
)
node.cargs.extend([
CArg(name="prev", _type=node, pointer=CPointer(_type=CPointerType.SINGLE)),
CArg(name="next", _type=node, pointer=CPointer(_type=CPointerType.SINGLE)),
])
dl_list = CStruct(
name=dbl_list_data.list_typename,
cargs=[
CArg(name="first", _type=node, pointer=CPointer(_type=CPointerType.SINGLE)),
CArg(name="last", _type=node, pointer=CPointer(_type=CPointerType.SINGLE)),
CArg(name="node_count", _type=CType.U64),
],
)
header.types.extend([node, dl_list])
header.decl_types.extend(dbl_list_data.hdr_decl_types)
source.decl_types.extend(dbl_list_data.src_decl_types)
if isinstance(_type, CType) and _type == CType.VOID:
# Don't define any functions for the generic node and list
continue
node_cmacro = CMacro(
name=f"wapp_{type_string_lower}_list_node(ITEM_PTR)",
value=__format_func_body(
filename=snippets_dir / "list_node",
type_string=type_string,
type_string_upper=type_string_upper,
type_string_lower=type_string_lower,
node_typename=dbl_list_data.node_typename,
list_typename=dbl_list_data.list_typename
),
)
node_cppmacro = CMacro(
name=f"wapp_{type_string_lower}_list_node(ITEM_PTR)",
value=__format_func_body(
filename=snippets_dir / "list_node_cpp",
type_string=type_string,
type_string_upper=type_string_upper,
type_string_lower=type_string_lower,
node_typename=dbl_list_data.node_typename,
list_typename=dbl_list_data.list_typename
),
)
get_func = CFunc(
name=f"wapp_{type_string_lower}_list_get",
ret_type=node,
args=[
CArg(name="list", _type=dl_list, pointer=CPointer(CPointerType.SINGLE), qualifier=CQualifier.CONST),
CArg(name="index", _type=CType.U64),
],
body=__format_func_body(
filename=snippets_dir / "list_get",
type_string=type_string,
type_string_upper=type_string_upper,
type_string_lower=type_string_lower,
node_typename=dbl_list_data.node_typename,
list_typename=dbl_list_data.list_typename
),
pointer=CPointer(CPointerType.SINGLE),
)
push_front_func = CFunc(
name=f"wapp_{type_string_lower}_list_push_front",
ret_type=CType.VOID,
args=[
CArg(name="list", _type=dl_list, pointer=CPointer(CPointerType.SINGLE)),
CArg(name="node", _type=node, pointer=CPointer(CPointerType.SINGLE)),
],
body=__format_func_body(
filename=snippets_dir / "list_push_front",
type_string=type_string,
type_string_upper=type_string_upper,
type_string_lower=type_string_lower,
node_typename=dbl_list_data.node_typename,
list_typename=dbl_list_data.list_typename
),
)
push_back_func = CFunc(
name=f"wapp_{type_string_lower}_list_push_back",
ret_type=CType.VOID,
args=[
CArg(name="list", _type=dl_list, pointer=CPointer(CPointerType.SINGLE)),
CArg(name="node", _type=node, pointer=CPointer(CPointerType.SINGLE)),
],
body=__format_func_body(
filename=snippets_dir / "list_push_back",
type_string=type_string,
type_string_upper=type_string_upper,
type_string_lower=type_string_lower,
node_typename=dbl_list_data.node_typename,
list_typename=dbl_list_data.list_typename
),
)
insert_func = CFunc(
name=f"wapp_{type_string_lower}_list_insert",
ret_type=CType.VOID,
args=[
CArg(name="list", _type=dl_list, pointer=CPointer(CPointerType.SINGLE)),
CArg(name="node", _type=node, pointer=CPointer(CPointerType.SINGLE)),
CArg(name="index", _type=CType.U64),
],
body=__format_func_body(
filename=snippets_dir / "list_insert",
type_string=type_string,
type_string_upper=type_string_upper,
type_string_lower=type_string_lower,
node_typename=dbl_list_data.node_typename,
list_typename=dbl_list_data.list_typename
),
)
pop_front_func = CFunc(
name=f"wapp_{type_string_lower}_list_pop_front",
ret_type=node,
args=[
CArg(name="list", _type=dl_list, pointer=CPointer(CPointerType.SINGLE)),
],
body=__format_func_body(
filename=snippets_dir / "list_pop_front",
type_string=type_string,
type_string_upper=type_string_upper,
type_string_lower=type_string_lower,
node_typename=dbl_list_data.node_typename,
list_typename=dbl_list_data.list_typename
),
pointer=CPointer(CPointerType.SINGLE),
)
pop_back_func = CFunc(
name=f"wapp_{type_string_lower}_list_pop_back",
ret_type=node,
args=[
CArg(name="list", _type=dl_list, pointer=CPointer(CPointerType.SINGLE)),
],
body=__format_func_body(
filename=snippets_dir / "list_pop_back",
type_string=type_string,
type_string_upper=type_string_upper,
type_string_lower=type_string_lower,
node_typename=dbl_list_data.node_typename,
list_typename=dbl_list_data.list_typename
),
pointer=CPointer(CPointerType.SINGLE),
)
remove_func = CFunc(
name=f"wapp_{type_string_lower}_list_remove",
ret_type=node,
args=[
CArg(name="list", _type=dl_list, pointer=CPointer(CPointerType.SINGLE)),
CArg(name="index", _type=CType.U64),
],
body=__format_func_body(
filename=snippets_dir / "list_remove",
type_string=type_string,
type_string_upper=type_string_upper,
type_string_lower=type_string_lower,
node_typename=dbl_list_data.node_typename,
list_typename=dbl_list_data.list_typename
),
pointer=CPointer(CPointerType.SINGLE),
)
empty_func = CFunc(
name=f"wapp_{type_string_lower}_list_empty",
ret_type=CType.VOID,
args=[
CArg(name="list", _type=dl_list, pointer=CPointer(CPointerType.SINGLE)),
],
body=__format_func_body(
filename=snippets_dir / "list_empty",
type_string=type_string,
type_string_upper=type_string_upper,
type_string_lower=type_string_lower,
node_typename=dbl_list_data.node_typename,
list_typename=dbl_list_data.list_typename
),
)
node_to_list_func = CFunc(
name=f"{type_string_lower}_node_to_list",
ret_type=dl_list,
args=[
CArg(name="node", _type=node, pointer=CPointer(CPointerType.SINGLE)),
],
body=__format_func_body(
filename=snippets_dir / "node_to_list",
type_string=type_string,
type_string_upper=type_string_upper,
type_string_lower=type_string_lower,
node_typename=dbl_list_data.node_typename,
list_typename=dbl_list_data.list_typename
),
qualifiers=[CQualifier.INTERNAL],
)
header.c_macros.append(node_cmacro)
header.cpp_macros.append(node_cppmacro)
header.funcs.extend([
get_func,
push_front_func,
push_back_func,
insert_func,
pop_front_func,
pop_back_func,
remove_func,
empty_func,
])
source.internal_funcs.append(node_to_list_func)
source.funcs = header.funcs
header.save(out_dir)
source.save(out_dir)

View File

@@ -0,0 +1,6 @@
wapp_debug_assert(list != NULL, "`list` should not be NULL");
u64 count = list->node_count;
for (u64 i = 0; i < count; ++i) {{
wapp_{Tlower}_list_pop_back(list);
}}

View File

@@ -0,0 +1,11 @@
wapp_runtime_assert(index < list->node_count, "`index` is out of bounds");
{NodeType} *output = NULL;
{NodeType} *current = list->first;
for (u64 i = 1; i <= index; ++i) {{
current = current->next;
}}
output = current;
return output;

View File

@@ -0,0 +1,26 @@
wapp_debug_assert(list != NULL && node != NULL && (node->item) != NULL, "`list`, `node` and `node->item` should not be NULL");
if (index == 0) {{
wapp_{Tlower}_list_push_front(list, node);
return;
}} else if (index == list->node_count) {{
wapp_{Tlower}_list_push_back(list, node);
return;
}}
{NodeType} *dst_node = wapp_{Tlower}_list_get(list, index);
if (!dst_node) {{
return;
}}
{ListType} node_list = {Tlower}_node_to_list(node);
list->node_count += node_list.node_count;
{NodeType} *prev = dst_node->prev;
dst_node->prev = node_list.last;
prev->next = node_list.first;
node_list.first->prev = prev;
node_list.last->next = dst_node;

View File

@@ -0,0 +1 @@
(({NodeType}){{.item = ITEM_PTR}})

View File

@@ -0,0 +1 @@
{NodeType}{{ITEM_PTR, nullptr, nullptr}}

View File

@@ -0,0 +1,22 @@
wapp_debug_assert(list != NULL, "`list` should not be NULL");
{NodeType} *output = NULL;
if (list->node_count == 0) {{
goto RETURN_{Tupper}_LIST_POP_BACK;
}}
output = list->last;
if (list->node_count == 1) {{
*list = ({ListType}){{0}};
goto RETURN_{Tupper}_LIST_POP_BACK;
}}
--(list->node_count);
list->last = output->prev;
output->prev = output->next = NULL;
RETURN_{Tupper}_LIST_POP_BACK:
return output;

View File

@@ -0,0 +1,22 @@
wapp_debug_assert(list != NULL, "`list` should not be NULL");
{NodeType} *output = NULL;
if (list->node_count == 0) {{
goto RETURN_{Tupper}_LIST_POP_FRONT;
}}
output = list->first;
if (list->node_count == 1) {{
*list = ({ListType}){{0}};
goto RETURN_{Tupper}_LIST_POP_FRONT;
}}
--(list->node_count);
list->first = output->next;
output->prev = output->next = NULL;
RETURN_{Tupper}_LIST_POP_FRONT:
return output;

View File

@@ -0,0 +1,18 @@
wapp_debug_assert(list != NULL && node != NULL && (node->item) != NULL, "`list`, `node` and `node->item` should not be NULL");
{ListType} node_list = {Tlower}_node_to_list(node);
if (list->node_count == 0) {{
*list = node_list;
return;
}}
list->node_count += node_list.node_count;
{NodeType} *last = list->last;
if (last) {{
last->next = node_list.first;
}}
list->last = node_list.last;
node_list.first->prev = last;

View File

@@ -0,0 +1,18 @@
wapp_debug_assert(list != NULL && node != NULL && (node->item) != NULL, "`list`, `node` and `node->item` should not be NULL");
{ListType} node_list = {Tlower}_node_to_list(node);
if (list->node_count == 0) {{
*list = node_list;
return;
}}
list->node_count += node_list.node_count;
{NodeType} *first = list->first;
if (first) {{
first->prev = node_list.last;
}}
list->first = node_list.first;
node_list.last->next = first;

View File

@@ -0,0 +1,26 @@
wapp_debug_assert(list != NULL, "`list` should not be NULL");
{NodeType} *output = NULL;
if (index == 0) {{
output = wapp_{Tlower}_list_pop_front(list);
goto RETURN_{Tupper}_LIST_REMOVE;
}} else if (index == list->node_count) {{
output = wapp_{Tlower}_list_pop_back(list);
goto RETURN_{Tupper}_LIST_REMOVE;
}}
output = wapp_{Tlower}_list_get(list, index);
if (!output) {{
goto RETURN_{Tupper}_LIST_REMOVE;
}}
output->prev->next = output->next;
output->next->prev = output->prev;
--(list->node_count);
output->prev = output->next = NULL;
RETURN_{Tupper}_LIST_REMOVE:
return output;

View File

@@ -0,0 +1,13 @@
{ListType} output = {{.first = node, .last = node, .node_count = 1}};
while (output.first->prev != NULL) {{
output.first = output.first->prev;
++(output.node_count);
}}
while (output.last->next != NULL) {{
output.last = output.last->next;
++(output.node_count);
}}
return output;

18
codegen/utils.py Normal file
View File

@@ -0,0 +1,18 @@
import os
import sys
from pathlib import Path
def load_func_body_from_file(filename: Path) -> str:
with open(filename, "r") as infile:
return infile.read().rstrip()
def convert_to_relative(path: Path, target: Path) -> Path:
major = sys.version_info.major
minor = sys.version_info.minor
if major >= 3 and minor >= 12:
return path.relative_to(target, walk_up=True)
else:
return Path(os.path.relpath(str(path), start=str(target)))

View File

@@ -0,0 +1,29 @@
{
"dbl_list_data": {
"CustomType": {
"node_typename": "CustomTypeNode",
"list_typename": "CustomTypeList",
"hdr_decl_types": [
{
"name": "custom_type",
"cargs": [],
"typedef_name": "CustomType"
}
],
"src_decl_types": []
}
},
"array_data": {
"CustomType": {
"array_typename": "CustomTypeArray",
"hdr_decl_types": [
{
"name": "custom_type",
"cargs": [],
"typedef_name": "CustomType"
}
],
"src_decl_types": []
}
}
}

61
compile
View File

@@ -1,61 +0,0 @@
#!/bin/bash
BUILD_TYPE="debug"
while [[ $# > 0 ]];do
case $1 in
--release)
BUILD_TYPE="release"
shift
;;
*|-*|--*)
echo "Unknown option $1"
exit 1
;;
esac
done
CC=clang
CFLAGS="-Wall -Werror -pedantic "
LIBFLAGS="-fPIC -shared"
INCLUDE="$(find src -type d | xargs -I{} echo -n "-I{} ")"
SRC="$(find src -type f -name "*.c" | xargs -I{} echo -n "{} ")"
TEST_INCLUDE="$(find tests -type d | xargs -I{} echo -n "-I{} ")"
TEST_SRC="$(find tests -type f -name "*.c" | xargs -I{} echo -n "{} ")"
BUILD_DIR="libwapp-build/posix-$BUILD_TYPE"
if [[ -d $BUILD_DIR ]]; then
rm -rf $BUILD_DIR
fi
mkdir -p $BUILD_DIR
if [[ $BUILD_TYPE == "release" ]]; then
CFLAGS+="-O3"
else
CFLAGS+="-g -fsanitize=address -fsanitize=undefined"
fi
OUT="$BUILD_DIR/libwapp.so"
TEST_OUT="$BUILD_DIR/wapptest"
# Compile tests
if [[ $(echo $TEST_SRC | xargs) != "" ]]; then
(set -x ; $CC $CFLAGS $INCLUDE $TEST_INCLUDE $SRC $TEST_SRC -o $TEST_OUT)
fi
# Run tests and exit on failure
if [[ -f $TEST_OUT ]]; then
$TEST_OUT
STATUS="$?"
rm $TEST_OUT
if [[ $STATUS != "0" ]]; then
exit 1
fi
fi
# Compile library
(set -x ; $CC $CFLAGS $LIBFLAGS $INCLUDE $SRC -o $OUT)

21
scripts/header_install.sh Normal file
View File

@@ -0,0 +1,21 @@
#!/bin/bash
SCRIPT_DIR="$(dirname $0)"
LIB_SRC="$1"
INSTALL_PREFIX="$2"
shift 2
INCLUDES="$@"
mkdir -p "$INSTALL_PREFIX"
BASE_INCLUDE_DIR="$(dirname "$LIB_SRC")"
find $BASE_INCLUDE_DIR -maxdepth 1 -type f -name "*.h" -exec cp -v {} "$INSTALL_PREFIX" \;
cd "$SCRIPT_DIR/../src"
for INCLUDE in $INCLUDES; do
for f in $(find "$INCLUDE" -type f -name "*.h"); do
DST="$INSTALL_PREFIX/$(dirname $f)"
mkdir -p "$DST"
cp -v "$f" "$DST"
done
done

View File

@@ -1,13 +1,47 @@
// vim:fileencoding=utf-8:foldmethod=marker
#ifndef ALIASES_H
#define ALIASES_H
#include "../platform/platform.h"
#include <stdint.h>
#if WAPP_PLATFORM_C_VERSION >= WAPP_PLATFORM_C11_VERSION && !defined(WAPP_PLATFORM_APPLE)
#include <uchar.h>
#if WAPP_PLATFORM_C_VERSION >= WAPP_PLATFORM_C23_VERSION
#define c8 char8_t
#else
#define c8 uint8_t
#endif // !WAPP_PLATFORM_C23_VERSION
#define c16 char16_t
#define c32 char32_t
#else
#define c8 uint8_t
#define c16 uint16_t
#define c32 uint32_t
#endif // !WAPP_PLATFORM_C11_VERSION
#define u8 uint8_t
#define u16 uint16_t
#define u32 uint32_t
#define u64 uint64_t
#define b32 uint32_t
#ifndef WAPP_PLATFORM_CPP
#ifndef false
#define false (b32)0
#endif // !false
#ifndef true
#define true (b32)1
#endif // !true
#endif // !WAPP_PLATFORM_CPP
#define i8 int8_t
#define i16 int16_t
#define i32 int32_t
@@ -20,11 +54,14 @@
#define uptr uintptr_t
#define iptr intptr_t
#define external extern
#define internal static
#define persistent static
#ifdef __cplusplus
#ifdef WAPP_PLATFORM_CPP
#define class_mem static
#endif // __cplusplus
#define BEGIN_C_LINKAGE extern "C" {
#define END_C_LINKAGE }
#endif // WAPP_PLATFORM_CPP
#endif // !ALIASES_H

View File

@@ -0,0 +1,41 @@
// vim:fileencoding=utf-8:foldmethod=marker
#ifndef WAPP_ASSERT_H
#define WAPP_ASSERT_H
#include "../aliases/aliases.h"
#include "../platform/platform.h"
#include <stdio.h>
#include <stdlib.h>
#include <inttypes.h>
#ifdef WAPP_PLATFORM_CPP
BEGIN_C_LINKAGE
#endif // !WAPP_PLATFORM_CPP
#define wapp_static_assert(EXPR, MSG) extern char ASSERTION_FAILED[EXPR ? 1 : -1]
#define wapp_runtime_assert(EXPR, MSG) __wapp_runtime_assert(EXPR, MSG)
#ifdef WAPP_DEBUG_ASSERT
#define wapp_debug_assert(EXPR, MSG) wapp_runtime_assert(EXPR, MSG)
#else
#define wapp_debug_assert(EXPR, MSG)
#endif
#define __wapp_runtime_assert(EXPR, MSG) do { \
if (!(EXPR)) { \
fprintf( \
stderr, \
"%s:%d (In function `%s`): Assertion failed (%" PRIu32 ")\nDiagnostic: %s\n\n", \
__FILE__, __LINE__, __func__, \
EXPR, MSG \
); \
abort(); \
} \
} while(false)
#ifdef WAPP_PLATFORM_CPP
END_C_LINKAGE
#endif // !WAPP_PLATFORM_CPP
#endif // !WAPP_ASSERT_H

View File

@@ -1,115 +0,0 @@
#include "mem_utils.h"
#include "aliases.h"
#include "platform.h"
#include <assert.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#if defined(WAPP_PLATFORM_WINDOWS)
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
#include <memoryapi.h>
internal const i32 access_types[] = {
[WAPP_MEM_ACCESS_NONE] = PAGE_NOACCESS,
[WAPP_MEM_ACCESS_READ_ONLY] = PAGE_READONLY,
[WAPP_MEM_ACCESS_EXEC_ONLY] = PAGE_EXECUTE,
[WAPP_MEM_ACCESS_READ_WRITE] = PAGE_READWRITE,
[WAPP_MEM_ACCESS_READ_EXEC] = PAGE_EXECUTE_READ,
[WAPP_MEM_ACCESS_READ_WRITE_EXEC] = PAGE_EXECUTE_READWRITE,
};
internal inline void *alloc_windows(void *addr, u64 size, MemAccess access,
MemAllocFlags flags);
#elif defined(WAPP_PLATFORM_POSIX)
#include <sys/mman.h>
internal const i32 access_types[] = {
[WAPP_MEM_ACCESS_NONE] = PROT_NONE,
[WAPP_MEM_ACCESS_READ_ONLY] = PROT_READ,
[WAPP_MEM_ACCESS_EXEC_ONLY] = PROT_EXEC,
[WAPP_MEM_ACCESS_READ_WRITE] = PROT_READ | PROT_WRITE,
[WAPP_MEM_ACCESS_READ_EXEC] = PROT_READ | PROT_EXEC,
[WAPP_MEM_ACCESS_READ_WRITE_EXEC] = PROT_READ | PROT_WRITE | PROT_EXEC,
};
internal inline void *alloc_posix(void *addr, u64 size, MemAccess access,
MemAllocFlags flags);
#else
#error "Unrecognised platform"
#endif
internal bool is_power_of_two(u64 num) { return (num & (num - 1)) == 0; }
void *wapp_mem_util_align_forward(void *ptr, u64 alignment) {
if (!ptr) {
return NULL;
}
assert(is_power_of_two(alignment));
uptr p = (uptr)ptr;
uptr align = (uptr)alignment;
// Similar to p % align, but it's a faster implementation that works fine
// because align is guaranteed to be a power of 2
uptr modulo = p & (align - 1);
if (modulo != 0) {
p += align - modulo;
}
return (void *)p;
}
void *wapp_mem_util_alloc(void *addr, u64 size, MemAccess access,
MemAllocFlags flags, MemInitType type) {
#if defined(WAPP_PLATFORM_WINDOWS)
// Ensure memory is committed if it's meant to be initialised
if (type == WAPP_MEM_INIT_INITIALISED) {
flags |= WAPP_MEM_ALLOC_COMMIT;
}
void *output = alloc_windows(addr, size, access, flags);
#elif defined(WAPP_PLATFORM_POSIX)
void *output = alloc_posix(addr, size, access, flags);
#else
return NULL;
#endif
if (type == WAPP_MEM_INIT_INITIALISED) {
memset(output, 0, size);
}
return output;
}
void wapp_mem_util_free(void *ptr, u64 size) {
#if defined(WAPP_PLATFORM_WINDOWS)
VirtualFree(ptr, size, MEM_RELEASE);
#elif defined(WAPP_PLATFORM_POSIX)
munmap(ptr, size);
#endif
}
#ifdef WAPP_PLATFORM_WINDOWS
internal inline void *alloc_windows(void *addr, u64 size, MemAccess access,
MemAllocFlags flags) {
return VirtualAlloc(addr, (SIZE_T)size, flags, access_types[access]);
}
#endif
#if defined(WAPP_PLATFORM_POSIX)
internal inline void *alloc_posix(void *addr, u64 size, MemAccess access,
MemAllocFlags flags) {
i32 alloc_flags = flags | MAP_ANON | MAP_PRIVATE;
#if defined(WAPP_PLATFORM_LINUX) || defined(WAPP_PLATFORM_GNU) || \
defined(WAPP_PLATFORM_NET_BSD)
alloc_flags |= MAP_NORESERVE;
#endif
return mmap(addr, size, access_types[access], alloc_flags, -1, 0);
}
#endif

View File

@@ -1,61 +0,0 @@
#ifndef MEM_UTILS_H
#define MEM_UTILS_H
#include "aliases.h"
#include "platform.h"
#if defined(WAPP_PLATFORM_WINDOWS)
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
#include <memoryapi.h>
#elif defined(WAPP_PLATFORM_POSIX)
#include <sys/mman.h>
#else
#error "Unrecognised platform"
#endif
#ifdef __cplusplus
extern "C" {
#endif // __cplusplus
typedef enum mem_access {
WAPP_MEM_ACCESS_NONE,
WAPP_MEM_ACCESS_READ_ONLY,
WAPP_MEM_ACCESS_EXEC_ONLY,
WAPP_MEM_ACCESS_READ_WRITE,
WAPP_MEM_ACCESS_READ_EXEC,
WAPP_MEM_ACCESS_READ_WRITE_EXEC,
} MemAccess;
typedef enum mem_alloc_flags {
#if defined(WAPP_PLATFORM_WINDOWS)
WAPP_MEM_ALLOC_RESERVE = MEM_RESERVE,
WAPP_MEM_ALLOC_COMMIT = MEM_COMMIT,
#elif defined(WAPP_PLATFORM_LINUX) || defined(WAPP_PLATFORM_GNU)
WAPP_MEM_ALLOC_RESERVE = 0,
WAPP_MEM_ALLOC_COMMIT = MAP_POPULATE,
#elif defined(WAPP_PLATFORM_FREE_BSD)
WAPP_MEM_ALLOC_RESERVE = 0,
WAPP_MEM_ALLOC_COMMIT = MAP_PREFAULT_READ,
#elif defined(WAPP_PLATFORM_BSD) || defined(WAPP_PLATFORM_UNIX) || \
defined(WAPP_PLATFORM_APPLE)
WAPP_MEM_ALLOC_RESERVE = 0,
WAPP_MEM_ALLOC_COMMIT = 0,
#endif
} MemAllocFlags;
typedef enum mem_init_type {
WAPP_MEM_INIT_UNINITIALISED,
WAPP_MEM_INIT_INITIALISED,
} MemInitType;
void *wapp_mem_util_align_forward(void *ptr, u64 alignment);
void *wapp_mem_util_alloc(void *addr, u64 size, MemAccess access,
MemAllocFlags flags, MemInitType type);
void wapp_mem_util_free(void *ptr, u64 size);
#ifdef __cplusplus
}
#endif // __cplusplus
#endif // !MEM_UTILS_H

View File

@@ -1,9 +1,56 @@
// vim:fileencoding=utf-8:foldmethod=marker
#ifndef MISC_UTILS_H
#define MISC_UTILS_H
#include "aliases.h"
#include "../aliases/aliases.h"
#define wapp_misc_utils_padding_size(SIZE) \
u8 reserved_padding[sizeof(void *) - ((SIZE) % sizeof(void *))]
#ifdef WAPP_PLATFORM_CPP
BEGIN_C_LINKAGE
#endif // !WAPP_PLATFORM_CPP
#define KB(SIZE) (SIZE * 1024ull)
#define MB(SIZE) (KB(SIZE) * 1024)
#define GB(SIZE) (MB(SIZE) * 1024)
#define TB(SIZE) (GB(SIZE) * 1024)
#define wapp_misc_utils_padding_size(SIZE) u8 reserved_padding[sizeof(void *) - ((SIZE) % sizeof(void *))]
#define U64_RSHIFT_OR_1(X) (((u64)X) | (((u64)X) >> 1))
#define U64_RSHIFT_OR_2(X) (((u64)X) | (((u64)X) >> 2))
#define U64_RSHIFT_OR_4(X) (((u64)X) | (((u64)X) >> 4))
#define U64_RSHIFT_OR_8(X) (((u64)X) | (((u64)X) >> 8))
#define U64_RSHIFT_OR_16(X) (((u64)X) | (((u64)X) >> 16))
#define U64_RSHIFT_OR_32(X) (((u64)X) | (((u64)X) >> 32))
#define wapp_misc_utils_u64_round_up_pow2(X) ( \
( \
U64_RSHIFT_OR_32( \
U64_RSHIFT_OR_16( \
U64_RSHIFT_OR_8( \
U64_RSHIFT_OR_4( \
U64_RSHIFT_OR_2( \
U64_RSHIFT_OR_1(X - 1) \
) \
) \
) \
) \
) \
) + 1 \
)
#ifdef WAPP_PLATFORM_CPP
#define wapp_misc_utils_va_args_count(T, ...) va_args_count<T>(__VA_ARGS__)
#else
#define wapp_misc_utils_va_args_count(T, ...) (sizeof((T[]){__VA_ARGS__})/sizeof(T))
#endif // !WAPP_PLATFORM_CPP
#ifdef WAPP_PLATFORM_CPP
END_C_LINKAGE
template <typename T, typename... Args>
constexpr u64 va_args_count(Args&&...) {
return sizeof...(Args);
}
#endif // !WAPP_PLATFORM_CPP
#endif // !MISC_UTILS_H

View File

@@ -1,7 +1,8 @@
// vim:fileencoding=utf-8:foldmethod=marker
#ifndef PLATFORM_H
#define PLATFORM_H
// clang-format off
#if defined(__ANDROID__)
#define WAPP_PLATFORM_ANDROID
#define WAPP_PLATFORM_POSIX
@@ -58,6 +59,56 @@
#else
#error "Unrecognised platform"
#endif
// clang-format on
#ifdef __cplusplus
#define WAPP_PLATFORM_CPP
#define WAPP_PLATFORM_CPP_VERSION __cplusplus
#define WAPP_PLATFORM_CPP98_VERSION 199711L
#define WAPP_PLATFORM_CPP11_VERSION 201103L
#define WAPP_PLATFORM_CPP14_VERSION 201402L
#define WAPP_PLATFORM_CPP17_VERSION 201703L
#define WAPP_PLATFORM_CPP20_VERSION 202002L
#define WAPP_PLATFORM_CPP23_VERSION 202302L
#if WAPP_PLATFORM_CPP_VERSION == WAPP_PLATFORM_CPP98_VERSION
#define WAPP_PLATFORM_CPP98
#elif WAPP_PLATFORM_CPP_VERSION == WAPP_PLATFORM_CPP11_VERSION
#define WAPP_PLATFORM_CPP11
#elif WAPP_PLATFORM_CPP_VERSION == WAPP_PLATFORM_CPP14_VERSION
#define WAPP_PLATFORM_CPP14
#elif WAPP_PLATFORM_CPP_VERSION == WAPP_PLATFORM_CPP17_VERSION
#define WAPP_PLATFORM_CPP17
#elif WAPP_PLATFORM_CPP_VERSION == WAPP_PLATFORM_CPP20_VERSION
#define WAPP_PLATFORM_CPP20
#elif WAPP_PLATFORM_CPP_VERSION == WAPP_PLATFORM_CPP23_VERSION
#define WAPP_PLATFORM_CPP23
#else
#error "Unrecognised C++ version"
#endif
#else
#define WAPP_PLATFORM_C
#if defined(__STDC_VERSION__)
#define WAPP_PLATFORM_C_VERSION __STDC_VERSION__
#define WAPP_PLATFORM_C99_VERSION 199901L
#define WAPP_PLATFORM_C11_VERSION 201112L
#define WAPP_PLATFORM_C17_VERSION 201710L
#define WAPP_PLATFORM_C23_VERSION 202311L
#if WAPP_PLATFORM_C_VERSION == WAPP_PLATFORM_C99_VERSION
#define WAPP_PLATFORM_C99
#elif WAPP_PLATFORM_C_VERSION == WAPP_PLATFORM_C11_VERSION
#define WAPP_PLATFORM_C11
#elif WAPP_PLATFORM_C_VERSION == WAPP_PLATFORM_C17_VERSION
#define WAPP_PLATFORM_C17
#elif WAPP_PLATFORM_C_VERSION == WAPP_PLATFORM_C23_VERSION
#define WAPP_PLATFORM_C23
#else
#error "Unrecognised C version"
#endif
#else
#define WAPP_PLATFORM_C89
#endif
#endif // !__cplusplus
#endif // !PLATFORM_H

View File

@@ -1,132 +0,0 @@
#include "commander.h"
#include "aliases.h"
#include "shell_utils.h"
#include <stdarg.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define CMD_BUF_LEN 8192
#define OUT_BUF_LEN 4096
internal inline CMDError build_command_from_args(char *cmd, u64 buf_len,
va_list args);
internal inline CMDResult execute_command(const char *cmd,
CMDOutHandling out_handling,
char *out_buf, u64 buf_size);
internal inline CMDError get_command_output(FILE *fp,
CMDOutHandling out_handling,
char *out_buf, u64 buf_size);
internal inline CMDError get_output_status(FILE *fp, i32 *status_out);
// clang-format off
CMDResult run_command(CMDOutHandling out_handling, char *out_buf, u64 buf_size, ...) { // clang-format on
va_list args;
va_start(args, buf_size);
char cmd[CMD_BUF_LEN] = {0};
CMDError err = build_command_from_args(cmd, CMD_BUF_LEN, args);
if (err > SHELL_ERR_NO_ERROR) {
va_end(args);
return CMD_NO_EXIT(err);
}
va_end(args);
return execute_command(cmd, out_handling, out_buf, buf_size);
}
internal inline CMDError build_command_from_args(char *cmd, u64 buf_len,
va_list args) {
u64 size = 0;
u64 arg_len = 0;
const char *arg;
while ((arg = va_arg(args, const char *))) {
arg_len = strlen(arg);
if (arg_len >= buf_len - size) {
return SHELL_ERR_CMD_BUF_FULL;
}
strcat(cmd, arg);
cmd[size + arg_len] = ' ';
size += arg_len + 1;
}
return SHELL_ERR_NO_ERROR;
}
internal inline CMDResult execute_command(const char *cmd,
CMDOutHandling out_handling,
char *out_buf, u64 buf_size) {
FILE *fp = wapp_shell_utils_popen(cmd, "r");
if (!fp) {
return CMD_NO_EXIT(SHELL_ERR_PROC_START_FAIL);
}
CMDError err = get_command_output(fp, out_handling, out_buf, buf_size);
if (err > SHELL_ERR_NO_ERROR) {
// Ensure process is closed on failure
wapp_shell_utils_pclose(fp);
return CMD_NO_EXIT(err);
}
i32 st = EXIT_SUCCESS;
err = get_output_status(fp, &st);
if (err > SHELL_ERR_NO_ERROR) {
return CMD_NO_EXIT(err);
}
return (CMDResult){
.exited = true,
.exit_code = st,
.error = SHELL_ERR_NO_ERROR,
};
}
internal inline CMDError get_command_output(FILE *fp,
CMDOutHandling out_handling,
char *out_buf, u64 buf_size) {
char out[OUT_BUF_LEN] = {0};
u64 max_out_length = OUT_BUF_LEN - 1;
u64 buf_filled = 0;
while (fgets(out, max_out_length, fp)) {
if (out_handling == SHELL_OUTPUT_CAPTURE && out_buf != NULL) {
buf_filled += strlen(out);
if (buf_filled >= buf_size) {
return SHELL_ERR_OUT_BUF_FULL;
}
strcat(out_buf, out);
} else {
printf("%s", out);
}
}
return SHELL_ERR_NO_ERROR;
}
internal inline CMDError get_output_status(FILE *fp, i32 *status_out) {
#ifdef WAPP_PLATFORM_WINDOWS
if (!feof(fp)) {
// Ensure process is closed on failure
wapp_shell_utils_pclose(fp);
return SHELL_ERR_PROC_EXIT_FAIL;
}
#endif /* ifdef WAPP_PLATFORM_WINDOWS */
*status_out = wapp_shell_utils_pclose(fp);
#ifdef WAPP_PLATFORM_POSIX
if (!WIFEXITED(*status_out)) {
return SHELL_ERR_PROC_EXIT_FAIL;
}
*status_out = WEXITSTATUS(*status_out);
#endif /* ifdef WAPP_PLATFORM_WINDOWS */
return SHELL_ERR_NO_ERROR;
}

View File

@@ -1,45 +0,0 @@
#ifndef COMMANDER_H
#define COMMANDER_H
#include "aliases.h"
#include <stdbool.h>
#include <stdlib.h>
#ifdef __cplusplus
extern "C" {
#endif // __cplusplus
#define CMD_NO_EXIT(ERR) \
((CMDResult){.exited = false, .exit_code = EXIT_FAILURE})
#define wapp_shell_commander_execute(HANDLE_OUTPUT, OUT_BUF, BUF_SIZE, ...) \
run_command(HANDLE_OUTPUT, OUT_BUF, BUF_SIZE, __VA_ARGS__, NULL)
typedef enum {
SHELL_OUTPUT_PRINT,
SHELL_OUTPUT_CAPTURE,
} CMDOutHandling;
typedef enum {
SHELL_ERR_NO_ERROR,
SHELL_ERR_CMD_BUF_FULL,
SHELL_ERR_PROC_START_FAIL,
SHELL_ERR_OUT_BUF_FULL,
SHELL_ERR_PROC_EXIT_FAIL,
} CMDError;
typedef struct commander_result CMDResult;
struct commander_result {
bool exited;
int exit_code;
CMDError error;
};
// clang-format off
CMDResult run_command(CMDOutHandling out_handling, char *out_buf, u64 buf_size, ...);
// clang-format on
#ifdef __cplusplus
}
#endif // __cplusplus
#endif // !COMMANDER_H

View File

@@ -1,101 +0,0 @@
#include "termcolour.h"
#include "aliases.h"
#include "platform.h"
#include <stdio.h>
internal void print_coloured_text(const TerminalColourist *colourist,
const char *text);
#ifdef WAPP_PLATFORM_WINDOWS
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
internal WORD colours[COUNT_TERM_COLOUR] = {
[WAPP_TERM_COLOUR_FG_BLACK] = 0,
[WAPP_TERM_COLOUR_FG_RED] = FOREGROUND_RED,
[WAPP_TERM_COLOUR_FG_GREEN] = FOREGROUND_GREEN,
[WAPP_TERM_COLOUR_FG_BLUE] = FOREGROUND_BLUE,
[WAPP_TERM_COLOUR_FG_CYAN] = FOREGROUND_GREEN | FOREGROUND_BLUE,
[WAPP_TERM_COLOUR_FG_MAGENTA] = FOREGROUND_RED | FOREGROUND_BLUE,
[WAPP_TERM_COLOUR_FG_YELLOW] = FOREGROUND_RED | FOREGROUND_GREEN,
[WAPP_TERM_COLOUR_FG_WHITE] =
FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE,
[WAPP_TERM_COLOUR_FG_BR_BLACK] = FOREGROUND_INTENSITY,
[WAPP_TERM_COLOUR_FG_BR_RED] = FOREGROUND_RED | FOREGROUND_INTENSITY,
[WAPP_TERM_COLOUR_FG_BR_GREEN] = FOREGROUND_GREEN | FOREGROUND_INTENSITY,
[WAPP_TERM_COLOUR_FG_BR_BLUE] = FOREGROUND_BLUE | FOREGROUND_INTENSITY,
[WAPP_TERM_COLOUR_FG_BR_CYAN] =
FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY,
[WAPP_TERM_COLOUR_FG_BR_MAGENTA] =
FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_INTENSITY,
[WAPP_TERM_COLOUR_FG_BR_YELLOW] =
FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY,
[WAPP_TERM_COLOUR_FG_BR_WHITE] = FOREGROUND_RED | FOREGROUND_GREEN |
FOREGROUND_BLUE | FOREGROUND_INTENSITY,
};
#else
internal const char *colours[COUNT_TERM_COLOUR] = {
[WAPP_TERM_COLOUR_FG_BLACK] = "\033[30m",
[WAPP_TERM_COLOUR_FG_RED] = "\033[31m",
[WAPP_TERM_COLOUR_FG_GREEN] = "\033[32m",
[WAPP_TERM_COLOUR_FG_BLUE] = "\033[34m",
[WAPP_TERM_COLOUR_FG_CYAN] = "\033[36m",
[WAPP_TERM_COLOUR_FG_MAGENTA] = "\033[35m",
[WAPP_TERM_COLOUR_FG_YELLOW] = "\033[33m",
[WAPP_TERM_COLOUR_FG_WHITE] = "\033[37m",
[WAPP_TERM_COLOUR_FG_BR_BLACK] = "\033[90m",
[WAPP_TERM_COLOUR_FG_BR_RED] = "\033[91m",
[WAPP_TERM_COLOUR_FG_BR_GREEN] = "\033[92m",
[WAPP_TERM_COLOUR_FG_BR_BLUE] = "\033[94m",
[WAPP_TERM_COLOUR_FG_BR_CYAN] = "\033[96m",
[WAPP_TERM_COLOUR_FG_BR_MAGENTA] = "\033[95m",
[WAPP_TERM_COLOUR_FG_BR_YELLOW] = "\033[93m",
[WAPP_TERM_COLOUR_FG_BR_WHITE] = "\033[97m",
};
#endif /* ifdef WAPP_PLATFORM_WINDOWS */
TerminalColourist wapp_shell_termcolour_get_colourist(void) {
TerminalColourist colourist;
#ifdef WAPP_PLATFORM_WINDOWS
// create handle
colourist.handle = GetStdHandle(STD_OUTPUT_HANDLE);
// get console colour information
CONSOLE_SCREEN_BUFFER_INFO csbi;
GetConsoleScreenBufferInfo(colourist.handle, &csbi);
colourist.default_colour = csbi.wAttributes;
#else
colourist.default_colour = "\033[0m";
#endif // ifdef WAPP_PLATFORM_WINDOWS
colourist.current_colour = colourist.default_colour;
return colourist;
}
void wapp_shell_termcolour_print_text(TerminalColourist *colourist,
const char *text, TerminalColour colour) {
if (colour < WAPP_TERM_COLOUR_FG_BLACK ||
colour > WAPP_TERM_COLOUR_FG_BR_WHITE) {
return;
}
colourist->current_colour = colours[colour];
print_coloured_text(colourist, text);
}
void wapp_shell_termcolour_clear_colour(TerminalColourist *colourist) {
colourist->current_colour = colourist->default_colour;
print_coloured_text(colourist, "");
}
internal void print_coloured_text(const TerminalColourist *colourist,
const char *text) {
#ifdef WAPP_PLATFORM_WINDOWS
SetConsoleTextAttribute(colourist->handle, colourist->current_colour);
printf("%s", text);
#else
printf("%s%s", colourist->current_colour, text);
#endif // ifdef WAPP_PLATFORM_WINDOWS
}

View File

@@ -1,64 +0,0 @@
#ifndef TERM_COLOUR_H
#define TERM_COLOUR_H
#include "aliases.h"
#include "misc_utils.h"
#include "platform.h"
#ifdef __cplusplus
extern "C" {
#endif // __cplusplus
typedef enum {
WAPP_TERM_COLOUR_FG_BLACK,
WAPP_TERM_COLOUR_FG_RED,
WAPP_TERM_COLOUR_FG_GREEN,
WAPP_TERM_COLOUR_FG_BLUE,
WAPP_TERM_COLOUR_FG_CYAN,
WAPP_TERM_COLOUR_FG_MAGENTA,
WAPP_TERM_COLOUR_FG_YELLOW,
WAPP_TERM_COLOUR_FG_WHITE,
WAPP_TERM_COLOUR_FG_BR_BLACK,
WAPP_TERM_COLOUR_FG_BR_RED,
WAPP_TERM_COLOUR_FG_BR_GREEN,
WAPP_TERM_COLOUR_FG_BR_BLUE,
WAPP_TERM_COLOUR_FG_BR_CYAN,
WAPP_TERM_COLOUR_FG_BR_MAGENTA,
WAPP_TERM_COLOUR_FG_BR_YELLOW,
WAPP_TERM_COLOUR_FG_BR_WHITE,
COUNT_TERM_COLOUR,
} TerminalColour;
typedef struct terminal_colourist TerminalColourist;
// clang-format off
#ifdef WAPP_PLATFORM_WINDOWS
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
#include <WinCon.h>
struct terminal_colourist {
HANDLE handle;
WORD default_colour;
WORD current_colour;
wapp_misc_utils_padding_size(sizeof(HANDLE) + sizeof(WORD) + sizeof(WORD));
};
#else
struct terminal_colourist {
const char *default_colour;
const char *current_colour;
};
#endif // WAPP_PLATFORM_WINDOWS
// clang-format on
TerminalColourist wapp_shell_termcolour_get_colourist(void);
void wapp_shell_termcolour_print_text(TerminalColourist *colourist,
const char *text, TerminalColour colour);
void wapp_shell_termcolour_clear_colour(TerminalColourist *colourist);
#ifdef __cplusplus
}
#endif // __cplusplus
#endif // !TERM_COLOUR_H

View File

@@ -1,16 +0,0 @@
#ifndef SHELL_UTILS_H
#define SHELL_UTILS_H
#include "platform.h"
// clang-format off
#ifdef WAPP_PLATFORM_WINDOWS
#define wapp_shell_utils_popen _popen
#define wapp_shell_utils_pclose _pclose
#else
#define wapp_shell_utils_popen popen
#define wapp_shell_utils_pclose pclose
#endif /* ifdef WAPP_PLATFORM_WINDOWS */
// clang-format on
#endif // !SHELL_UTILS_H

11
src/common/wapp_common.h Normal file
View File

@@ -0,0 +1,11 @@
// vim:fileencoding=utf-8:foldmethod=marker
#ifndef WAPP_COMMON_H
#define WAPP_COMMON_H
#include "aliases/aliases.h"
#include "assert/assert.h"
#include "misc/misc_utils.h"
#include "platform/platform.h"
#endif // !WAPP_COMMON_H

View File

@@ -1,87 +0,0 @@
#include "cpath.h"
#include "aliases.h"
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
#if defined(__unix__) || defined(__APPLE__) || defined(__ANDROID__)
internal char path_sep = '/';
#elif defined(_WIN32) || defined(_WIN64)
internal char path_sep = '\\';
#endif
void join_root_and_leaf(const char *root, const char *leaf, char *dst);
void join_path(char *dst, u64 count, ...) {
va_list args;
va_start(args, count);
for (u64 i = 0; i < count; ++i) {
join_root_and_leaf(dst, va_arg(args, const char *), dst);
}
va_end(args);
}
void dirup(char *dst, u64 levels, const char *path) {
if (levels < 1) {
return;
}
u64 end_index = 0;
u64 sep_count = 0;
u64 full_length;
u64 length;
length = full_length = strlen(path);
if (path[length - 1] == path_sep) {
--length;
}
for (i64 i = length - 1; i >= 0; --i) {
if (path[i] == path_sep) {
++sep_count;
end_index = i;
if (sep_count == levels) {
break;
}
}
}
if (sep_count < levels) {
end_index = 0;
}
if (dst == path) {
memset(&dst[end_index], 0, full_length - end_index);
} else {
u64 dst_length = strlen(dst);
memset(dst, 0, dst_length);
strncpy(dst, path, end_index);
}
}
void join_root_and_leaf(const char *root, const char *leaf, char *dst) {
u64 root_length = strlen(root);
u64 root_end = root_length - 1;
u64 leaf_length = strlen(leaf);
u64 leaf_start = 0;
if (root[root_end] == path_sep) {
--root_end;
}
if (leaf[leaf_start] == path_sep) {
++leaf_start;
}
memcpy(dst, root, ++root_end);
dst[root_end] = path_sep;
memcpy(&(dst[++root_end]), &(leaf[leaf_start]), leaf_length - leaf_start);
}

View File

@@ -1,25 +0,0 @@
#ifndef PATH_UTILS_H
#define PATH_UTILS_H
#include "aliases.h"
#ifdef __cplusplus
extern "C" {
#endif // __cplusplus
#define NUMPARTS(...) \
(sizeof((const char *[]){"", __VA_ARGS__}) / sizeof(const char *) - 1)
#define wapp_cpath_join_path(DST, ...) \
join_path(DST, NUMPARTS(__VA_ARGS__), __VA_ARGS__)
#define wapp_cpath_dirname(DST, PATH) dirup(DST, 1, PATH)
#define wapp_cpath_dirup(DST, COUNT, PATH) dirup(DST, COUNT, PATH)
void join_path(char *dst, u64 count, ...);
void dirup(char *dst, u64 levels, const char *path);
#ifdef __cplusplus
}
#endif // __cplusplus
#endif // !PATH_UTILS_H

103
src/core/file/file.c Normal file
View File

@@ -0,0 +1,103 @@
// vim:fileencoding=utf-8:foldmethod=marker
#include "file.h"
#include "../os/cpath/cpath.h"
#include "../../common/assert/assert.h"
#include "../../common/aliases/aliases.h"
#include "../../primitives/array/array.h"
#include "../../primitives/strings/str8/str8.h"
#include <stdio.h>
File *wapp_file_open(Str8RO *filepath, FileAccessMode mode) {
persistent const char *modes[FILE_ACCESS_MODE_COUNT] = {
[WAPP_FA_MODE_R] = "r",
[WAPP_FA_MODE_W] = "w",
[WAPP_FA_MODE_A] = "a",
[WAPP_FA_MODE_R_EX] = "r+",
[WAPP_FA_MODE_W_EX] = "w+",
[WAPP_FA_MODE_A_EX] = "a+",
[WAPP_FA_MODE_RB] = "rb",
[WAPP_FA_MODE_WB] = "wb",
[WAPP_FA_MODE_AB] = "ab",
[WAPP_FA_MODE_RB_EX] = "rb+",
[WAPP_FA_MODE_WB_EX] = "wb+",
[WAPP_FA_MODE_AB_EX] = "ab+",
[WAPP_FA_MODE_WX] = "wx",
[WAPP_FA_MODE_WX_EX] = "wx+",
[WAPP_FA_MODE_WBX] = "wbx",
[WAPP_FA_MODE_WBX_EX] = "wbx+",
};
persistent c8 tmp[WAPP_PATH_MAX] = {0};
wapp_debug_assert(filepath->size < WAPP_PATH_MAX, "`filepath` exceeds max path limit.");
memset(tmp, 0, WAPP_PATH_MAX);
memcpy(tmp, filepath->buf, filepath->size);
return fopen((const char *)tmp, modes[mode]);
}
u64 wapp_file_get_current_position(File *file) {
wapp_debug_assert(file != NULL, "`file` should not be NULL.");
return (u64)ftell(file);
}
i32 wapp_file_seek(File *file, u64 offset, FileSeekOrigin origin) {
wapp_debug_assert(file != NULL, "`file` should not be NULL.");
return fseek(file, offset, origin);
}
u64 wapp_file_get_length(File *file) {
wapp_debug_assert(file != NULL, "`file` should not be NULL.");
u64 current = wapp_file_get_current_position(file);
wapp_file_seek(file, 0, WAPP_SEEK_END);
u64 output = ftell(file);
// Restore position
wapp_file_seek(file, current, WAPP_SEEK_START);
return output;
}
u64 wapp_file_read(GenericArray *dst, File *file, u64 item_count) {
wapp_debug_assert(dst != NULL && dst->items != NULL && file != NULL,
"`dst`, `dst->items` and `file` should not be NULL.");
u64 file_length = wapp_file_get_length(file);
u64 dst_byte_capacity = dst->item_size * dst->capacity;
u64 req_byte_count = item_count * dst->item_size;
u64 copy_byte_count = 0;
if (req_byte_count <= file_length && req_byte_count <= dst_byte_capacity) {
copy_byte_count = req_byte_count;
} else {
copy_byte_count = file_length <= dst_byte_capacity ? file_length : dst_byte_capacity;
}
dst->count = fread(dst->items, sizeof(u8), copy_byte_count, file) / dst->item_size;
return dst->count;
}
u64 wapp_file_write(const GenericArray *src, File *file, u64 item_count) {
wapp_debug_assert(src != NULL && src->items != NULL && file != NULL,
"`src`, `src->items` and `file` should not be NULL.");
u64 src_byte_count = src->count * src->item_size;
u64 req_byte_count = item_count * src->item_size;
u64 to_copy = req_byte_count <= src_byte_count ? req_byte_count : src_byte_count;
return fwrite(src->items, sizeof(u8), to_copy, file);
}
i32 wapp_file_flush(File *file) {
wapp_debug_assert(file != NULL, "`file` should not be NULL.");
return fflush(file);
}
i32 wapp_file_close(File *file) {
wapp_debug_assert(file != NULL, "`file` should not be NULL.");
return fclose(file);
}

72
src/core/file/file.h Normal file
View File

@@ -0,0 +1,72 @@
// vim:fileencoding=utf-8:foldmethod=marker
#ifndef FILE_H
#define FILE_H
#include "../../common/aliases/aliases.h"
#include "../../primitives/array/array.h"
#include "../../primitives/strings/str8/str8.h"
#include <stdio.h>
#ifdef WAPP_PLATFORM_CPP
BEGIN_C_LINKAGE
#endif // !WAPP_PLATFORM_CPP
#ifdef WAPP_PLATFORM_CPP
#define wapp_file_item_to_array(ITEM) (GenericArray{&(ITEM), 1, 1, sizeof(ITEM)})
#define wapp_file_array_to_item(TYPE, ARRAY) (sizeof(TYPE) == (ARRAY).item_size && (ARRAY).count == 1 ? \
*((TYPE *)((ARRAY).items)) : \
TYPE{})
#else
#define wapp_file_item_to_array(ITEM) ((GenericArray){.items = &(ITEM), \
.count = 1, \
.capacity = 1, \
.item_size = sizeof(ITEM)})
#define wapp_file_array_to_item(TYPE, ARRAY) (sizeof(TYPE) == (ARRAY).item_size && (ARRAY).count == 1 ? \
*((TYPE *)((ARRAY).items)) : \
(TYPE){0})
#endif // !WAPP_PLATFORM_CPP
typedef FILE File;
typedef enum {
WAPP_FA_MODE_R, // Equivalent to r
WAPP_FA_MODE_W, // Equivalent to w
WAPP_FA_MODE_A, // Equivalent to a
WAPP_FA_MODE_R_EX, // Equivalent to r+
WAPP_FA_MODE_W_EX, // Equivalent to w+
WAPP_FA_MODE_A_EX, // Equivalent to a+
WAPP_FA_MODE_RB, // Equivalent to rb
WAPP_FA_MODE_WB, // Equivalent to wb
WAPP_FA_MODE_AB, // Equivalent to ab
WAPP_FA_MODE_RB_EX, // Equivalent to rb+
WAPP_FA_MODE_WB_EX, // Equivalent to wb+
WAPP_FA_MODE_AB_EX, // Equivalent to ab+
WAPP_FA_MODE_WX, // Equivalent to wx
WAPP_FA_MODE_WX_EX, // Equivalent to wx+
WAPP_FA_MODE_WBX, // Equivalent to wbx
WAPP_FA_MODE_WBX_EX, // Equivalent to wbx+
FILE_ACCESS_MODE_COUNT,
} FileAccessMode;
typedef enum {
WAPP_SEEK_START = SEEK_SET,
WAPP_SEEK_CURRENT = SEEK_CUR,
WAPP_SEEK_END = SEEK_END,
} FileSeekOrigin;
File *wapp_file_open(Str8RO *filename, FileAccessMode mode);
u64 wapp_file_get_current_position(File *file);
i32 wapp_file_seek(File *file, u64 offset, FileSeekOrigin origin);
u64 wapp_file_get_length(File *file);
u64 wapp_file_read(GenericArray *dst, File *file, u64 item_count);
u64 wapp_file_write(const GenericArray *src, File *file, u64 item_count);
i32 wapp_file_flush(File *file);
i32 wapp_file_close(File *file);
#ifdef WAPP_PLATFORM_CPP
END_C_LINKAGE
#endif // !WAPP_PLATFORM_CPP
#endif // !FILE_H

View File

@@ -1,8 +1,11 @@
// vim:fileencoding=utf-8:foldmethod=marker
#include "mem_arena.h"
#include "aliases.h"
#include "mem_utils.h"
#include "misc_utils.h"
#include <stdbool.h>
#include "../utils/mem_utils.h"
#include "../../../common/aliases/aliases.h"
#include "../../../common/assert/assert.h"
#include "../../../common/misc/misc_utils.h"
#include "../../os/mem/mem_os.h"
#include <stdlib.h>
#include <string.h>
@@ -12,23 +15,20 @@
#define DEFAULT_ALIGNMENT (2 * sizeof(void *))
#endif /* ifndef DEFAULT_ALIGNMENT */
#define ARENA_MINIMUM_CAPACITY 1024
#define ARENA_MINIMUM_CAPACITY KB(16) // Allocate minimum of 4 pages
struct arena {
u8 *buf;
u8 *offset;
u64 capacity;
bool committed;
b32 committed;
#ifdef WAPP_PLATFORM_WINDOWS
wapp_misc_utils_padding_size(sizeof(u8 *) * 2 + sizeof(u64) + sizeof(bool));
wapp_misc_utils_padding_size(sizeof(u8 *) * 2 + sizeof(u64) + sizeof(b32));
#endif // ifdef WAPP_PLATFORM_WINDOWS
};
// PUBLIC API
bool wapp_mem_arena_init(Arena **arena, u64 base_capacity, MemAllocFlags flags,
bool zero_buffer) {
b32 wapp_mem_arena_init_custom(Arena **arena, u64 base_capacity, MemAllocFlags flags, b32 zero_buffer) {
if (!arena || *arena || base_capacity == 0) {
return false;
}
@@ -39,23 +39,23 @@ bool wapp_mem_arena_init(Arena **arena, u64 base_capacity, MemAllocFlags flags,
return false;
}
u64 arena_capacity = base_capacity >= ARENA_MINIMUM_CAPACITY
? base_capacity
: ARENA_MINIMUM_CAPACITY;
u64 arena_capacity = wapp_misc_utils_u64_round_up_pow2(
base_capacity >= ARENA_MINIMUM_CAPACITY ?
base_capacity :
ARENA_MINIMUM_CAPACITY
);
arena_ptr->buf = (u8 *)wapp_mem_util_alloc(
NULL, arena_capacity, WAPP_MEM_ACCESS_READ_WRITE, flags,
zero_buffer ? WAPP_MEM_INIT_INITIALISED : WAPP_MEM_INIT_UNINITIALISED);
arena_ptr->buf = (u8 *)wapp_mem_util_alloc(NULL, arena_capacity, WAPP_MEM_ACCESS_READ_WRITE, flags,
zero_buffer ? WAPP_MEM_INIT_INITIALISED : WAPP_MEM_INIT_UNINITIALISED);
if (!(arena_ptr->buf)) {
wapp_mem_arena_destroy(arena);
return false;
}
arena_ptr->capacity = arena_capacity;
arena_ptr->offset = arena_ptr->buf;
arena_ptr->committed =
(flags & WAPP_MEM_ALLOC_COMMIT) == WAPP_MEM_ALLOC_COMMIT;
arena_ptr->capacity = arena_capacity;
arena_ptr->offset = arena_ptr->buf;
arena_ptr->committed = (flags & WAPP_MEM_ALLOC_COMMIT) == WAPP_MEM_ALLOC_COMMIT;
return true;
}
@@ -65,9 +65,7 @@ void *wapp_mem_arena_alloc(Arena *arena, u64 size) {
}
void *wapp_mem_arena_alloc_aligned(Arena *arena, u64 size, u64 alignment) {
if (!arena) {
return NULL;
}
wapp_debug_assert(arena != NULL, "`arena` should not be NULL");
u8 *alloc_start = arena->offset;
@@ -80,31 +78,60 @@ void *wapp_mem_arena_alloc_aligned(Arena *arena, u64 size, u64 alignment) {
#ifdef WAPP_PLATFORM_WINDOWS
if (!(arena->committed)) {
output = (u8 *)wapp_mem_util_alloc(
alloc_start, (uptr)(arena->offset) - (uptr)(alloc_start),
WAPP_MEM_ACCESS_READ_WRITE, WAPP_MEM_ALLOC_COMMIT,
WAPP_MEM_INIT_INITIALISED);
wapp_mem_util_alloc(alloc_start, (uptr)(arena->offset) - (uptr)(alloc_start),
WAPP_MEM_ACCESS_READ_WRITE, WAPP_MEM_ALLOC_COMMIT,
WAPP_MEM_INIT_UNINITIALISED);
}
#else
memset(output, 0, size);
#endif // ifdef WAPP_PLATFORM_WINDOWS
memset(output, 0, size);
return (void *)output;
}
void wapp_mem_arena_clear(Arena *arena) {
if (!arena) {
return;
void *wapp_mem_arena_realloc(Arena *arena, void *ptr, u64 old_size, u64 new_size) {
if ((u8*)ptr < arena->buf || (u8*)ptr > arena->offset ||
arena->offset + new_size >= arena->buf + arena->capacity) {
return NULL;
}
void *new_ptr = wapp_mem_arena_alloc(arena, new_size);
if (!new_ptr) {
return NULL;
}
u64 copy_size = new_size <= old_size ? new_size : old_size;
memcpy(new_ptr, ptr, copy_size);
return new_ptr;
}
void *wapp_mem_arena_realloc_aligned(Arena *arena, void *ptr, u64 old_size, u64 new_size, u64 alignment) {
if ((u8*)ptr < arena->buf || (u8*)ptr > arena->offset ||
arena->offset + new_size >= arena->buf + arena->capacity) {
return NULL;
}
void *new_ptr = wapp_mem_arena_alloc_aligned(arena, new_size, alignment);
if (!new_ptr) {
return NULL;
}
u64 copy_size = new_size <= old_size ? new_size : old_size;
memcpy(new_ptr, ptr, copy_size);
return new_ptr;
}
void wapp_mem_arena_clear(Arena *arena) {
wapp_debug_assert(arena != NULL, "`arena` should not be NULL");
memset(arena->buf, 0, arena->offset - arena->buf);
arena->offset = arena->buf;
}
void wapp_mem_arena_destroy(Arena **arena) {
if (!arena) {
return;
}
wapp_debug_assert(arena != NULL && (*arena) != NULL, "`arena` double pointer is not valid");
Arena *arena_ptr = *arena;
if (arena_ptr->buf) {

View File

@@ -1,37 +1,42 @@
// vim:fileencoding=utf-8:foldmethod=marker
#ifndef MEM_ARENA_H
#define MEM_ARENA_H
#include "aliases.h"
#include "mem_utils.h"
#include <stdbool.h>
#include "../../../common/aliases/aliases.h"
#include "../../../common/platform/platform.h"
#include "../../os/mem/mem_os.h"
#ifdef __cplusplus
extern "C" {
#endif // __cplusplus
#ifdef WAPP_PLATFORM_CPP
BEGIN_C_LINKAGE
#endif // !WAPP_PLATFORM_CPP
typedef struct arena Arena;
#define wapp_mem_arena_init_default(arena_dptr, base_capacity) \
(wapp_mem_arena_init(arena_dptr, base_capacity, WAPP_MEM_ALLOC_RESERVE, \
false))
#define wapp_mem_arena_init(arena_dptr, base_capacity) \
(wapp_mem_arena_init_custom(arena_dptr, base_capacity, WAPP_MEM_ALLOC_RESERVE, false))
#define wapp_mem_arena_init_commit(arena_dptr, base_capacity) \
(wapp_mem_arena_init(arena_dptr, base_capacity, \
WAPP_MEM_ALLOC_RESERVE | WAPP_MEM_ALLOC_COMMIT, false))
(wapp_mem_arena_init_custom(arena_dptr, base_capacity, WAPP_MEM_ALLOC_RESERVE | WAPP_MEM_ALLOC_COMMIT, false))
#define wapp_mem_arena_init_zero(arena_dptr, base_capacity) \
(wapp_mem_arena_init(arena_dptr, base_capacity, WAPP_MEM_ALLOC_RESERVE, true))
(wapp_mem_arena_init_custom(arena_dptr, base_capacity, WAPP_MEM_ALLOC_RESERVE, true))
#define wapp_mem_arena_init_commit_and_zero(arena_dptr, base_capacity) \
(wapp_mem_arena_init(arena_dptr, base_capacity, \
WAPP_MEM_ALLOC_RESERVE | WAPP_MEM_ALLOC_COMMIT, true))
(wapp_mem_arena_init_custom(arena_dptr, base_capacity, WAPP_MEM_ALLOC_RESERVE | WAPP_MEM_ALLOC_COMMIT, true))
bool wapp_mem_arena_init(Arena **arena, u64 base_capacity, MemAllocFlags flags,
bool zero_buffer);
/**
* Arena initialisation function. `wapp_mem_arena_init_custom` provides the most
* control over how the Arena is initialised. Wrapper macros are provided for
* easier use.
*/
b32 wapp_mem_arena_init_custom(Arena **arena, u64 base_capacity, MemAllocFlags flags, b32 zero_buffer);
void *wapp_mem_arena_alloc(Arena *arena, u64 size);
void *wapp_mem_arena_alloc_aligned(Arena *arena, u64 size, u64 alignment);
void *wapp_mem_arena_realloc(Arena *arena, void *ptr, u64 old_size, u64 new_size);
void *wapp_mem_arena_realloc_aligned(Arena *arena, void *ptr, u64 old_size, u64 new_size, u64 alignment);
void wapp_mem_arena_clear(Arena *arena);
void wapp_mem_arena_destroy(Arena **arena);
#ifdef __cplusplus
}
#endif // __cplusplus
#ifdef WAPP_PLATFORM_CPP
END_C_LINKAGE
#endif // !WAPP_PLATFORM_CPP
#endif // !MEM_ARENA_H

View File

@@ -0,0 +1,59 @@
// vim:fileencoding=utf-8:foldmethod=marker
#include "mem_arena_allocator.h"
#include "mem_arena.h"
#include "../../../common/aliases/aliases.h"
#include "../../os/mem/mem_os.h"
internal inline void *mem_arena_alloc(u64 size, void *alloc_obj);
internal inline void *mem_arena_alloc_aligned(u64 size, u64 alignment, void *alloc_obj);
internal inline void *mem_arena_realloc(void *ptr, u64 old_size, u64 new_size, void *alloc_obj);
internal inline void *mem_arena_realloc_aligned(void *ptr, u64 old_size, u64 new_size, u64 alignment,
void *alloc_obj);
Allocator wapp_mem_arena_allocator_init_custom(u64 base_capacity, MemAllocFlags flags, b32 zero_buffer) {
Allocator allocator = {0};
b32 initialised = wapp_mem_arena_init_custom((Arena **)(&allocator.obj), base_capacity, flags, zero_buffer);
if (!initialised) {
return allocator;
}
allocator.alloc = mem_arena_alloc;
allocator.alloc_aligned = mem_arena_alloc_aligned;
allocator.realloc = mem_arena_realloc;
allocator.realloc_aligned = mem_arena_realloc_aligned;
return allocator;
}
void wapp_mem_arena_allocator_clear(Allocator *allocator) {
wapp_mem_arena_clear((Arena *)(allocator->obj));
}
void wapp_mem_arena_allocator_destroy(Allocator *allocator) {
wapp_mem_arena_destroy((Arena **)(&(allocator->obj)));
*allocator = (Allocator){0};
}
internal inline void *mem_arena_alloc(u64 size, void *alloc_obj) {
Arena *arena = (Arena *)alloc_obj;
return wapp_mem_arena_alloc(arena, size);
}
internal inline void *mem_arena_alloc_aligned(u64 size, u64 alignment, void *alloc_obj) {
Arena *arena = (Arena *)alloc_obj;
return wapp_mem_arena_alloc_aligned(arena, size, alignment);
}
internal inline void *mem_arena_realloc(void *ptr, u64 old_size, u64 new_size, void *alloc_obj) {
Arena *arena = (Arena *)alloc_obj;
return wapp_mem_arena_realloc(arena, ptr, old_size, new_size);
}
internal inline void *mem_arena_realloc_aligned(void *ptr, u64 old_size, u64 new_size, u64 alignment,
void *alloc_obj) {
Arena *arena = (Arena *)alloc_obj;
return wapp_mem_arena_realloc_aligned(arena, ptr, old_size, new_size, alignment);
}

View File

@@ -0,0 +1,43 @@
// vim:fileencoding=utf-8:foldmethod=marker
#ifndef MEM_ARENA_ALLOCATOR_H
#define MEM_ARENA_ALLOCATOR_H
#include "../../../common/aliases/aliases.h"
#include "../../../common/platform/platform.h"
#include "../../../primitives/mem_allocator/mem_allocator.h"
#include "../../os/mem/mem_os.h"
#ifdef WAPP_PLATFORM_CPP
BEGIN_C_LINKAGE
#endif // !WAPP_PLATFORM_CPP
#define wapp_mem_arena_allocator_init(base_capacity) \
(wapp_mem_arena_allocator_init_custom(base_capacity, WAPP_MEM_ALLOC_RESERVE, false))
#define wapp_mem_arena_allocator_init_commit(base_capacity) \
(wapp_mem_arena_allocator_init_custom(base_capacity, WAPP_MEM_ALLOC_RESERVE | WAPP_MEM_ALLOC_COMMIT, false))
#define wapp_mem_arena_allocator_init_zero(base_capacity) \
(wapp_mem_arena_allocator_init_custom(base_capacity, WAPP_MEM_ALLOC_RESERVE, true))
#define wapp_mem_arena_allocator_init_commit_and_zero(base_capacity) \
(wapp_mem_arena_allocator_init_custom(base_capacity, WAPP_MEM_ALLOC_RESERVE | WAPP_MEM_ALLOC_COMMIT, true))
/**
* Wraps an Arena in an Allocator object. It attempts to initialise the Arena
* and, if successful, defines the operations supported by it to be used by the
* Allocator.
*
* An Arena allocator only supports normal allocation and aligned allocation.
* Reallocation, aligned reallocation and freeing aren't implemented.
*
* The `wapp_mem_arena_allocator_init_custom` provides the most control over how
* the Arena is initialised. Wrapper macros are provided for easier use.
*/
Allocator wapp_mem_arena_allocator_init_custom(u64 base_capacity, MemAllocFlags flags, b32 zero_buffer);
void wapp_mem_arena_allocator_clear(Allocator *allocator);
void wapp_mem_arena_allocator_destroy(Allocator *allocator);
#ifdef WAPP_PLATFORM_CPP
END_C_LINKAGE
#endif // !WAPP_PLATFORM_CPP
#endif // !MEM_ARENA_ALLOCATOR_H

View File

@@ -0,0 +1,26 @@
// vim:fileencoding=utf-8:foldmethod=marker
#include "mem_utils.h"
#include "../../../common/aliases/aliases.h"
#include "../../../common/assert/assert.h"
#include <stddef.h>
internal b32 is_power_of_two(u64 num) { return (num & (num - 1)) == 0; }
void *wapp_mem_util_align_forward(void *ptr, u64 alignment) {
wapp_debug_assert(ptr != NULL, "`ptr` should not be NULL");
wapp_runtime_assert(is_power_of_two(alignment), "`alignment` value is not a power of two");
uptr p = (uptr)ptr;
uptr align = (uptr)alignment;
// Similar to p % align, but it's a faster implementation that works fine
// because align is guaranteed to be a power of 2
uptr modulo = p & (align - 1);
if (modulo != 0) {
p += align - modulo;
}
return (void *)p;
}

View File

@@ -0,0 +1,19 @@
// vim:fileencoding=utf-8:foldmethod=marker
#ifndef MEM_UTILS_H
#define MEM_UTILS_H
#include "../../../common/aliases/aliases.h"
#include "../../../common/platform/platform.h"
#ifdef WAPP_PLATFORM_CPP
BEGIN_C_LINKAGE
#endif // !WAPP_PLATFORM_CPP
void *wapp_mem_util_align_forward(void *ptr, u64 alignment);
#ifdef WAPP_PLATFORM_CPP
END_C_LINKAGE
#endif // !WAPP_PLATFORM_CPP
#endif // !MEM_UTILS_H

135
src/core/os/cpath/cpath.c Normal file
View File

@@ -0,0 +1,135 @@
// vim:fileencoding=utf-8:foldmethod=marker
#include "cpath.h"
#include "../../../common/aliases/aliases.h"
#include "../../../common/misc/misc_utils.h"
#include "../../mem/arena/mem_arena_allocator.h"
#include "../../../primitives/dbl_list/dbl_list.h"
#include "../../../primitives/mem_allocator/mem_allocator.h"
#include "../../../primitives/strings/str8/str8.h"
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
u32 wapp_cpath_join_path(Str8 *dst, const Str8List *parts) {
if (!dst || !parts) {
return CPATH_JOIN_INVALID_ARGS;
}
if (parts->node_count == 0) {
return CPATH_JOIN_EMPTY_PARTS;
}
Str8 separator = wapp_str8_buf(4);
wapp_str8_push_back(&separator, WAPP_PATH_SEP);
u64 required_capacity = parts->node_count * separator.size + wapp_str8_list_total_size(parts);
if (dst->capacity < required_capacity) {
return CPATH_JOIN_INSUFFICIENT_DST_CAPACITY;
}
// Handle first node
const Str8Node *first_node = wapp_str8_list_get(parts, 0);
wapp_str8_copy_str8_capped(dst, first_node->item);
// NOTE (Abdelrahman): Uses a while loop instead of a for loop to get rid of
// MSVC Spectre mitigation warnings
const Str8Node *node = first_node;
u64 node_index = 1;
b32 running = node_index < parts->node_count;
while (running && node->next) {
node = node->next;
if (node->item->size == 0) {
continue;
}
if (dst->size > 0) {
char dst_last = wapp_str8_get(dst, dst->size - 1);
char node_start = wapp_str8_get(node->item, 0);
b32 add_path_sep = dst_last != WAPP_PATH_SEP && node_start != WAPP_PATH_SEP;
if (add_path_sep) {
wapp_str8_concat_capped(dst, &separator);
}
}
wapp_str8_concat_capped(dst, node->item);
++node_index;
running = node_index < parts->node_count;
}
return CPATH_JOIN_SUCCESS;
}
Str8 *dirup(const Allocator *allocator, Str8RO *path, u64 levels) {
Str8 *output = NULL;
if (!allocator || !path) {
goto RETURN_DIRUP;
}
b32 absolute = wapp_str8_get(path, 0) == WAPP_PATH_SEP;
Str8 separator = wapp_str8_buf(4);
wapp_str8_push_back(&separator, WAPP_PATH_SEP);
if (path->size == 0) {
output = wapp_str8_alloc_buf(allocator, 16);
if (!output) {
goto RETURN_DIRUP;
}
wapp_str8_push_back(output, absolute ? WAPP_PATH_SEP : '.');
goto RETURN_DIRUP;
}
if (levels < 1) {
output = wapp_str8_alloc_str8(allocator, path);
goto RETURN_DIRUP;
}
Allocator tmp_arena = wapp_mem_arena_allocator_init(MB(8));
if (wapp_mem_allocator_invalid(&tmp_arena)) {
goto RETURN_DIRUP;
}
Str8List *parts = wapp_str8_split(&tmp_arena, path, &separator);
if (!parts) {
goto RETURN_DIRUP;
}
if (levels >= parts->node_count) {
output = wapp_str8_alloc_buf(allocator, 16);
if (!output) {
goto LIST_CLEANUP_DIRUP;
}
wapp_str8_push_back(output, absolute ? WAPP_PATH_SEP : '.');
} else {
for (u64 i = 0; i < levels; ++i) {
wapp_str8_list_pop_back(parts);
}
u64 alignment = sizeof(void *) * 2;
u64 alloc_size = wapp_str8_list_total_size(parts) + parts->node_count * separator.size;
u64 modulo = alloc_size & (alignment - 1);
alloc_size += alignment - modulo;
output = wapp_str8_alloc_buf(allocator, alloc_size);
if (output) {
if (absolute) {
wapp_str8_push_back(output, WAPP_PATH_SEP);
}
Str8 *joined = wapp_str8_join(&tmp_arena, parts, &separator);
if (joined) {
wapp_str8_concat_capped(output, joined);
}
}
}
LIST_CLEANUP_DIRUP:
wapp_mem_arena_allocator_destroy(&tmp_arena);
RETURN_DIRUP:
return output;
}

44
src/core/os/cpath/cpath.h Normal file
View File

@@ -0,0 +1,44 @@
// vim:fileencoding=utf-8:foldmethod=marker
#ifndef CPATH_H
#define CPATH_H
#include "../../../common/aliases/aliases.h"
#include "../../../common/platform/platform.h"
#include "../../../primitives/mem_allocator/mem_allocator.h"
#include "../../../primitives/strings/str8/str8.h"
#ifdef WAPP_PLATFORM_CPP
BEGIN_C_LINKAGE
#endif // !WAPP_PLATFORM_CPP
#ifdef WAPP_PLATFORM_POSIX
#include <limits.h>
#define WAPP_PATH_SEP '/'
#define WAPP_PATH_MAX PATH_MAX
#elif defined(WAPP_PLATFORM_WINDOWS)
#include <windows.h>
#define WAPP_PATH_SEP '\\'
#define WAPP_PATH_MAX MAX_PATH
#else
#error "Unrecognised platform"
#endif
#define wapp_cpath_dirname(ALLOCATOR, PATH) dirup(ALLOCATOR, PATH, 1)
#define wapp_cpath_dirup(ALLOCATOR, PATH, COUNT) dirup(ALLOCATOR, PATH, COUNT)
enum {
CPATH_JOIN_SUCCESS = 0,
CPATH_JOIN_INVALID_ARGS,
CPATH_JOIN_EMPTY_PARTS,
CPATH_JOIN_INSUFFICIENT_DST_CAPACITY,
};
u32 wapp_cpath_join_path(Str8 *dst, const Str8List *parts);
Str8 *dirup(const Allocator *allocator, Str8RO *path, u64 levels);
#ifdef WAPP_PLATFORM_CPP
END_C_LINKAGE
#endif // !WAPP_PLATFORM_CPP
#endif // !CPATH_H

30
src/core/os/mem/mem_os.c Normal file
View File

@@ -0,0 +1,30 @@
// vim:fileencoding=utf-8:foldmethod=marker
#include "mem_os.h"
#include "mem_os_ops.h"
#include "../../../common/aliases/aliases.h"
#include "../../../common/platform/platform.h"
#include <assert.h>
#include <string.h>
#if defined(WAPP_PLATFORM_WINDOWS)
#include "win/mem_os_win.h"
#elif defined(WAPP_PLATFORM_POSIX)
#include "posix/mem_os_posix.h"
#else
#error "Unrecognised platform"
#endif
void *wapp_mem_util_alloc(void *addr, u64 size, MemAccess access, MemAllocFlags flags, MemInitType type) {
void *output = mem_util_allocate(addr, size, access, flags, type);
if (type == WAPP_MEM_INIT_INITIALISED) {
memset(output, 0, size);
}
return output;
}
void wapp_mem_util_free(void *ptr, u64 size) {
mem_util_free(ptr, size);
}

33
src/core/os/mem/mem_os.h Normal file
View File

@@ -0,0 +1,33 @@
// vim:fileencoding=utf-8:foldmethod=marker
#ifndef MEM_OS_H
#define MEM_OS_H
#include "../../../common/aliases/aliases.h"
#include "../../../common/platform/platform.h"
#include "mem_os_ops.h"
#ifdef WAPP_PLATFORM_CPP
BEGIN_C_LINKAGE
#endif // !WAPP_PLATFORM_CPP
#if defined(WAPP_PLATFORM_WINDOWS)
#include "win/mem_os_win.h"
#elif defined(WAPP_PLATFORM_POSIX)
#include "posix/mem_os_posix.h"
#else
#error "Unrecognised platform"
#endif
void *wapp_mem_util_alloc(void *addr, u64 size, MemAccess access, MemAllocFlags flags, MemInitType type);
void wapp_mem_util_free(void *ptr, u64 size);
external void *mem_util_allocate(void *addr, u64 size, MemAccess access, MemAllocFlags flags, MemInitType type);
external void mem_util_free(void *ptr, u64 size);
#ifdef WAPP_PLATFORM_CPP
END_C_LINKAGE
#endif // !WAPP_PLATFORM_CPP
#endif // !MEM_OS_H

View File

@@ -0,0 +1,30 @@
// vim:fileencoding=utf-8:foldmethod=marker
#ifndef MEM_OS_OPS_H
#define MEM_OS_OPS_H
#include "../../../common/platform/platform.h"
#ifdef WAPP_PLATFORM_CPP
BEGIN_C_LINKAGE
#endif // !WAPP_PLATFORM_CPP
typedef enum mem_access {
WAPP_MEM_ACCESS_NONE,
WAPP_MEM_ACCESS_READ_ONLY,
WAPP_MEM_ACCESS_EXEC_ONLY,
WAPP_MEM_ACCESS_READ_WRITE,
WAPP_MEM_ACCESS_READ_EXEC,
WAPP_MEM_ACCESS_READ_WRITE_EXEC,
} MemAccess;
typedef enum mem_init_type {
WAPP_MEM_INIT_UNINITIALISED,
WAPP_MEM_INIT_INITIALISED,
} MemInitType;
#ifdef WAPP_PLATFORM_CPP
END_C_LINKAGE
#endif // !WAPP_PLATFORM_CPP
#endif // !MEM_OS_OPS_H

View File

@@ -0,0 +1,36 @@
// vim:fileencoding=utf-8:foldmethod=marker
#include "../../../../common/aliases/aliases.h"
#include "../../../../common/platform/platform.h"
#ifdef WAPP_PLATFORM_POSIX
#include "mem_os_posix.h"
#include "../mem_os_ops.h"
#include <sys/mman.h>
internal const i32 access_types[] = {
[WAPP_MEM_ACCESS_NONE] = PROT_NONE,
[WAPP_MEM_ACCESS_READ_ONLY] = PROT_READ,
[WAPP_MEM_ACCESS_EXEC_ONLY] = PROT_EXEC,
[WAPP_MEM_ACCESS_READ_WRITE] = PROT_READ | PROT_WRITE,
[WAPP_MEM_ACCESS_READ_EXEC] = PROT_READ | PROT_EXEC,
[WAPP_MEM_ACCESS_READ_WRITE_EXEC] = PROT_READ | PROT_WRITE | PROT_EXEC,
};
void *mem_util_allocate(void *addr, u64 size, MemAccess access, MemAllocFlags flags, MemInitType type) {
(void)type;
i32 alloc_flags = flags | MAP_ANON | MAP_PRIVATE;
#if defined(WAPP_PLATFORM_LINUX) || defined(WAPP_PLATFORM_GNU) || defined(WAPP_PLATFORM_NET_BSD)
alloc_flags |= MAP_NORESERVE;
#endif
return mmap(addr, size, access_types[access], alloc_flags, -1, 0);
}
void mem_util_free(void *ptr, u64 size) {
munmap(ptr, size);
}
#endif // !WAPP_PLATFORM_POSIX

View File

@@ -0,0 +1,35 @@
// vim:fileencoding=utf-8:foldmethod=marker
#ifndef MEM_OS_POSIX_H
#define MEM_OS_POSIX_H
#include "../../../../common/platform/platform.h"
#ifdef WAPP_PLATFORM_CPP
BEGIN_C_LINKAGE
#endif // !WAPP_PLATFORM_CPP
#ifdef WAPP_PLATFORM_POSIX
#include <sys/mman.h>
typedef enum mem_alloc_flags {
#if defined(WAPP_PLATFORM_LINUX) || defined(WAPP_PLATFORM_GNU)
WAPP_MEM_ALLOC_RESERVE = 0,
WAPP_MEM_ALLOC_COMMIT = MAP_POPULATE,
#elif defined(WAPP_PLATFORM_FREE_BSD)
WAPP_MEM_ALLOC_RESERVE = 0,
WAPP_MEM_ALLOC_COMMIT = MAP_PREFAULT_READ,
#elif defined(WAPP_PLATFORM_BSD) || defined(WAPP_PLATFORM_UNIX) || defined(WAPP_PLATFORM_APPLE)
WAPP_MEM_ALLOC_RESERVE = 0,
WAPP_MEM_ALLOC_COMMIT = 0,
#endif
} MemAllocFlags;
#endif // !WAPP_PLATFORM_POSIX
#ifdef WAPP_PLATFORM_CPP
END_C_LINKAGE
#endif // !WAPP_PLATFORM_CPP
#endif // !MEM_OS_POSIX_H

View File

@@ -0,0 +1,37 @@
// vim:fileencoding=utf-8:foldmethod=marker
#include "../../../../common/aliases/aliases.h"
#include "../../../../common/platform/platform.h"
#ifdef WAPP_PLATFORM_WINDOWS
#include "mem_os_win.h"
#include "../mem_os_ops.h"
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
#include <memoryapi.h>
internal const i32 access_types[] = {
[WAPP_MEM_ACCESS_NONE] = PAGE_NOACCESS,
[WAPP_MEM_ACCESS_READ_ONLY] = PAGE_READONLY,
[WAPP_MEM_ACCESS_EXEC_ONLY] = PAGE_EXECUTE,
[WAPP_MEM_ACCESS_READ_WRITE] = PAGE_READWRITE,
[WAPP_MEM_ACCESS_READ_EXEC] = PAGE_EXECUTE_READ,
[WAPP_MEM_ACCESS_READ_WRITE_EXEC] = PAGE_EXECUTE_READWRITE,
};
void *mem_util_allocate(void *addr, u64 size, MemAccess access, MemAllocFlags flags, MemInitType type) {
// Ensure memory is committed if it's meant to be initialised
if (type == WAPP_MEM_INIT_INITIALISED) {
flags |= WAPP_MEM_ALLOC_COMMIT;
}
return VirtualAlloc(addr, (SIZE_T)size, flags, access_types[access]);
}
void mem_util_free(void *ptr, u64 size) {
VirtualFree(ptr, size, MEM_RELEASE);
}
#endif // !WAPP_PLATFORM_WINDOWS

View File

@@ -0,0 +1,29 @@
// vim:fileencoding=utf-8:foldmethod=marker
#ifndef MEM_OS_WIN_H
#define MEM_OS_WIN_H
#include "../../../../common/platform/platform.h"
#ifdef WAPP_PLATFORM_CPP
BEGIN_C_LINKAGE
#endif // !WAPP_PLATFORM_CPP
#ifdef WAPP_PLATFORM_WINDOWS
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
#include <memoryapi.h>
typedef enum mem_alloc_flags {
WAPP_MEM_ALLOC_RESERVE = MEM_RESERVE,
WAPP_MEM_ALLOC_COMMIT = MEM_COMMIT,
} MemAllocFlags;
#endif // !WAPP_PLATFORM_WINDOWS
#ifdef WAPP_PLATFORM_CPP
END_C_LINKAGE
#endif // !WAPP_PLATFORM_CPP
#endif // !MEM_OS_WIN_H

View File

@@ -0,0 +1,101 @@
// vim:fileencoding=utf-8:foldmethod=marker
#include "commander.h"
#include "commander_output.h"
#include "../utils/shell_utils.h"
#include "../../../mem/arena/mem_arena_allocator.h"
#include "../../../../common/aliases/aliases.h"
#include "../../../../common/misc/misc_utils.h"
#include "../../../../primitives/dbl_list/dbl_list.h"
#include "../../../../primitives/mem_allocator/mem_allocator.h"
#include "../../../../primitives/strings/str8/str8.h"
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define CMD_BUF_LEN 8192
#define OUT_BUF_LEN 4096
internal inline CMDResult execute_command(Str8RO *cmd, CMDOutHandling out_handling, Str8 *out_buf);
internal inline CMDError get_command_output(FILE *fp, CMDOutHandling out_handling, Str8 *out_buf);
CMDResult wapp_shell_commander_execute(CMDOutHandling out_handling, Str8 *out_buf, const Str8List *cmd) {
if (!cmd) {
return CMD_NO_EXIT(SHELL_ERR_INVALID_ARGS);
}
Allocator arena = wapp_mem_arena_allocator_init(KB(500));
Str8 *cmd_str = wapp_str8_join(&arena, cmd, &wapp_str8_lit_ro(" "));
if (!cmd_str) {
wapp_mem_arena_allocator_destroy(&arena);
return CMD_NO_EXIT(SHELL_ERR_ALLOCATION_FAIL);
}
// Redirect output
cmd_str = wapp_str8_alloc_concat(&arena, cmd_str, &wapp_str8_lit_ro(" 2>&1"));
CMDResult output = execute_command(cmd_str, out_handling, out_buf);
wapp_mem_arena_allocator_destroy(&arena);
return output;
}
internal inline CMDResult execute_command(Str8RO *cmd, CMDOutHandling out_handling, Str8 *out_buf) {
char cmd_buf[CMD_BUF_LEN] = {0};
wapp_str8_copy_to_cstr(cmd_buf, cmd, CMD_BUF_LEN);
FILE *fp = wapp_shell_utils_popen(cmd_buf, "r");
if (!fp) {
return CMD_NO_EXIT(SHELL_ERR_PROC_START_FAIL);
}
CMDResult output;
CMDError err = get_command_output(fp, out_handling, out_buf);
if (err > SHELL_ERR_NO_ERROR) {
output = CMD_NO_EXIT(err);
goto EXECUTE_COMMAND_CLOSE;
}
i32 st = EXIT_SUCCESS;
err = get_output_status(fp, &st);
if (err > SHELL_ERR_NO_ERROR) {
output = CMD_NO_EXIT(err);
goto EXECUTE_COMMAND_CLOSE;
}
// Process is already closed in get_output_status
fp = NULL;
output = (CMDResult){
.exited = true,
.exit_code = st,
.error = SHELL_ERR_NO_ERROR,
};
EXECUTE_COMMAND_CLOSE:
if (fp) {
wapp_shell_utils_pclose(fp);
}
return output;
}
internal inline CMDError get_command_output(FILE *fp, CMDOutHandling out_handling, Str8 *out_buf) {
Str8 out = wapp_str8_buf(OUT_BUF_LEN);
out.size = fread((void *)out.buf, sizeof(u8), out.capacity, fp);
if (out_handling == SHELL_OUTPUT_CAPTURE && out_buf != NULL) {
if (out.size >= out_buf->capacity) {
return SHELL_ERR_OUT_BUF_FULL;
}
wapp_str8_concat_capped(out_buf, &out);
} else if (out_handling == SHELL_OUTPUT_PRINT) {
printf(WAPP_STR8_SPEC, wapp_str8_varg(out));
}
return SHELL_ERR_NO_ERROR;
}

View File

@@ -0,0 +1,27 @@
// vim:fileencoding=utf-8:foldmethod=marker
#ifndef COMMANDER_H
#define COMMANDER_H
#include "commander_output.h"
#include "../../../../common/aliases/aliases.h"
#include "../../../../common/platform/platform.h"
#include "../../../../primitives/strings/str8/str8.h"
#include <stdio.h>
#include <stdlib.h>
#ifdef WAPP_PLATFORM_CPP
BEGIN_C_LINKAGE
#endif // !WAPP_PLATFORM_CPP
#define CMD_NO_EXIT(ERR) ((CMDResult){.exited = false, .exit_code = EXIT_FAILURE, .error = ERR})
CMDResult wapp_shell_commander_execute(CMDOutHandling out_handling, Str8 *out_buf, const Str8List *cmd);
external CMDError get_output_status(FILE *fp, i32 *status_out);
#ifdef WAPP_PLATFORM_CPP
END_C_LINKAGE
#endif // !WAPP_PLATFORM_CPP
#endif // !COMMANDER_H

View File

@@ -0,0 +1,44 @@
// vim:fileencoding=utf-8:foldmethod=marker
#ifndef COMMANDER_OUTPUT_H
#define COMMANDER_OUTPUT_H
#include "../../../../common/aliases/aliases.h"
#include "../../../../common/platform/platform.h"
#ifdef WAPP_PLATFORM_CPP
BEGIN_C_LINKAGE
#endif // !WAPP_PLATFORM_CPP
typedef enum {
SHELL_OUTPUT_DISCARD,
SHELL_OUTPUT_PRINT,
SHELL_OUTPUT_CAPTURE,
} CMDOutHandling;
typedef enum {
SHELL_ERR_NO_ERROR,
SHELL_ERR_INVALID_ARGS,
SHELL_ERR_ALLOCATION_FAIL,
SHELL_ERR_PROC_START_FAIL,
SHELL_ERR_OUT_BUF_FULL,
SHELL_ERR_PROC_EXIT_FAIL,
} CMDError;
typedef struct commander_result CMDResult;
struct commander_result {
i32 exit_code;
CMDError error;
b32 exited;
#ifdef WAPP_PLATFORM_WINDOWS
#include "../../../../common/misc/misc_utils.h"
wapp_misc_utils_padding_size(sizeof(b32) + sizeof(i32) + sizeof(CMDError));
#endif // !WAPP_PLATFORM_WINDOWS
};
#ifdef WAPP_PLATFORM_CPP
END_C_LINKAGE
#endif // !WAPP_PLATFORM_CPP
#endif // !COMMANDER_OUTPUT_H

View File

@@ -0,0 +1,25 @@
// vim:fileencoding=utf-8:foldmethod=marker
#include "../../../../../common/aliases/aliases.h"
#include "../../../../../common/platform/platform.h"
#ifdef WAPP_PLATFORM_POSIX
#include "../commander_output.h"
#include "../../utils/shell_utils.h"
#include <stdio.h>
#include <stdlib.h>
CMDError get_output_status(FILE *fp, i32 *status_out) {
*status_out = wapp_shell_utils_pclose(fp);
if (!WIFEXITED(*status_out)) {
return SHELL_ERR_PROC_EXIT_FAIL;
}
*status_out = WEXITSTATUS(*status_out);
return SHELL_ERR_NO_ERROR;
}
#endif // !WAPP_PLATFORM_POSIX

View File

@@ -0,0 +1,24 @@
// vim:fileencoding=utf-8:foldmethod=marker
#include "../../../../../common/aliases/aliases.h"
#include "../../../../../common/platform/platform.h"
#ifdef WAPP_PLATFORM_WINDOWS
#include "../commander_output.h"
#include "../../utils/shell_utils.h"
#include <stdio.h>
CMDError get_output_status(FILE *fp, i32 *status_out) {
if (!feof(fp)) {
// Ensure process is closed on failure
wapp_shell_utils_pclose(fp);
return SHELL_ERR_PROC_EXIT_FAIL;
}
*status_out = wapp_shell_utils_pclose(fp);
return SHELL_ERR_NO_ERROR;
}
#endif // !WAPP_PLATFORM_WINDOWS

View File

@@ -0,0 +1,36 @@
// vim:fileencoding=utf-8:foldmethod=marker
#include "../../../../../common/aliases/aliases.h"
#include "../../../../../common/platform/platform.h"
#include "../../../../../primitives/strings/str8/str8.h"
#ifdef WAPP_PLATFORM_POSIX
#include "../terminal_colours.h"
#include <stdio.h>
internal Str8RO colours[COUNT_TERM_COLOUR] = {
[WAPP_TERM_COLOUR_FG_BLACK] = wapp_str8_lit_ro_initialiser_list("\033[30m"),
[WAPP_TERM_COLOUR_FG_RED] = wapp_str8_lit_ro_initialiser_list("\033[31m"),
[WAPP_TERM_COLOUR_FG_GREEN] = wapp_str8_lit_ro_initialiser_list("\033[32m"),
[WAPP_TERM_COLOUR_FG_BLUE] = wapp_str8_lit_ro_initialiser_list("\033[34m"),
[WAPP_TERM_COLOUR_FG_CYAN] = wapp_str8_lit_ro_initialiser_list("\033[36m"),
[WAPP_TERM_COLOUR_FG_MAGENTA] = wapp_str8_lit_ro_initialiser_list("\033[35m"),
[WAPP_TERM_COLOUR_FG_YELLOW] = wapp_str8_lit_ro_initialiser_list("\033[33m"),
[WAPP_TERM_COLOUR_FG_WHITE] = wapp_str8_lit_ro_initialiser_list("\033[37m"),
[WAPP_TERM_COLOUR_FG_BR_BLACK] = wapp_str8_lit_ro_initialiser_list("\033[90m"),
[WAPP_TERM_COLOUR_FG_BR_RED] = wapp_str8_lit_ro_initialiser_list("\033[91m"),
[WAPP_TERM_COLOUR_FG_BR_GREEN] = wapp_str8_lit_ro_initialiser_list("\033[92m"),
[WAPP_TERM_COLOUR_FG_BR_BLUE] = wapp_str8_lit_ro_initialiser_list("\033[94m"),
[WAPP_TERM_COLOUR_FG_BR_CYAN] = wapp_str8_lit_ro_initialiser_list("\033[96m"),
[WAPP_TERM_COLOUR_FG_BR_MAGENTA] = wapp_str8_lit_ro_initialiser_list("\033[95m"),
[WAPP_TERM_COLOUR_FG_BR_YELLOW] = wapp_str8_lit_ro_initialiser_list("\033[93m"),
[WAPP_TERM_COLOUR_FG_BR_WHITE] = wapp_str8_lit_ro_initialiser_list("\033[97m"),
[WAPP_TERM_COLOUR_CLEAR] = wapp_str8_lit_ro_initialiser_list("\033[0m"),
};
void print_coloured_text(Str8RO *text, TerminalColour colour) {
printf(WAPP_STR8_SPEC WAPP_STR8_SPEC, wapp_str8_varg(colours[colour]), wapp_str8_varg((*text)));
}
#endif // !WAPP_PLATFORM_POSIX

View File

@@ -0,0 +1,18 @@
// vim:fileencoding=utf-8:foldmethod=marker
#include "termcolour.h"
#include "terminal_colours.h"
#include "../../../../primitives/strings/str8/str8.h"
void wapp_shell_termcolour_print_text(Str8RO *text, TerminalColour colour) {
if (colour < WAPP_TERM_COLOUR_FG_BLACK || colour > WAPP_TERM_COLOUR_FG_BR_WHITE) {
return;
}
print_coloured_text(text, colour);
}
void wapp_shell_termcolour_clear_colour(void) {
Str8RO empty = wapp_str8_lit_ro("");
print_coloured_text(&empty, WAPP_TERM_COLOUR_CLEAR);
}

View File

@@ -0,0 +1,24 @@
// vim:fileencoding=utf-8:foldmethod=marker
#ifndef TERM_COLOUR_H
#define TERM_COLOUR_H
#include "terminal_colours.h"
#include "../../../../common/aliases/aliases.h"
#include "../../../../common/platform/platform.h"
#include "../../../../primitives/strings/str8/str8.h"
#ifdef WAPP_PLATFORM_CPP
BEGIN_C_LINKAGE
#endif // !WAPP_PLATFORM_CPP
void wapp_shell_termcolour_print_text(Str8RO *text, TerminalColour colour);
void wapp_shell_termcolour_clear_colour(void);
external void print_coloured_text(Str8RO *text, TerminalColour colour);
#ifdef WAPP_PLATFORM_CPP
END_C_LINKAGE
#endif // !WAPP_PLATFORM_CPP
#endif // !TERM_COLOUR_H

View File

@@ -0,0 +1,39 @@
// vim:fileencoding=utf-8:foldmethod=marker
#ifndef TERMINAL_COLOURS_H
#define TERMINAL_COLOURS_H
#include "../../../../common/aliases/aliases.h"
#include "../../../../common/platform/platform.h"
#ifdef WAPP_PLATFORM_CPP
BEGIN_C_LINKAGE
#endif // !WAPP_PLATFORM_CPP
typedef enum {
WAPP_TERM_COLOUR_FG_BLACK,
WAPP_TERM_COLOUR_FG_RED,
WAPP_TERM_COLOUR_FG_GREEN,
WAPP_TERM_COLOUR_FG_BLUE,
WAPP_TERM_COLOUR_FG_CYAN,
WAPP_TERM_COLOUR_FG_MAGENTA,
WAPP_TERM_COLOUR_FG_YELLOW,
WAPP_TERM_COLOUR_FG_WHITE,
WAPP_TERM_COLOUR_FG_BR_BLACK,
WAPP_TERM_COLOUR_FG_BR_RED,
WAPP_TERM_COLOUR_FG_BR_GREEN,
WAPP_TERM_COLOUR_FG_BR_BLUE,
WAPP_TERM_COLOUR_FG_BR_CYAN,
WAPP_TERM_COLOUR_FG_BR_MAGENTA,
WAPP_TERM_COLOUR_FG_BR_YELLOW,
WAPP_TERM_COLOUR_FG_BR_WHITE,
WAPP_TERM_COLOUR_CLEAR,
COUNT_TERM_COLOUR,
} TerminalColour;
#ifdef WAPP_PLATFORM_CPP
END_C_LINKAGE
#endif // !WAPP_PLATFORM_CPP
#endif // !TERMINAL_COLOURS_H

View File

@@ -0,0 +1,73 @@
// vim:fileencoding=utf-8:foldmethod=marker
#include "../../../../../common/aliases/aliases.h"
#include "../../../../../common/platform/platform.h"
#include "../../../../../primitives/strings/str8/str8.h"
#ifdef WAPP_PLATFORM_WINDOWS
#include "../terminal_colours.h"
#include "../../../../../common/misc/misc_utils.h"
#include <stdio.h>
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
typedef struct termcolour_data TermcolourData;
struct termcolour_data {
HANDLE handle;
WORD default_colour;
WORD current_colour;
wapp_misc_utils_padding_size(sizeof(HANDLE) + sizeof(WORD) + sizeof(WORD));
};
internal void init_data(TermcolourData *data);
internal WORD colours[COUNT_TERM_COLOUR] = {
[WAPP_TERM_COLOUR_FG_BLACK] = 0,
[WAPP_TERM_COLOUR_FG_RED] = FOREGROUND_RED,
[WAPP_TERM_COLOUR_FG_GREEN] = FOREGROUND_GREEN,
[WAPP_TERM_COLOUR_FG_BLUE] = FOREGROUND_BLUE,
[WAPP_TERM_COLOUR_FG_CYAN] = FOREGROUND_GREEN | FOREGROUND_BLUE,
[WAPP_TERM_COLOUR_FG_MAGENTA] = FOREGROUND_RED | FOREGROUND_BLUE,
[WAPP_TERM_COLOUR_FG_YELLOW] = FOREGROUND_RED | FOREGROUND_GREEN,
[WAPP_TERM_COLOUR_FG_WHITE] = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE,
[WAPP_TERM_COLOUR_FG_BR_BLACK] = FOREGROUND_INTENSITY,
[WAPP_TERM_COLOUR_FG_BR_RED] = FOREGROUND_RED | FOREGROUND_INTENSITY,
[WAPP_TERM_COLOUR_FG_BR_GREEN] = FOREGROUND_GREEN | FOREGROUND_INTENSITY,
[WAPP_TERM_COLOUR_FG_BR_BLUE] = FOREGROUND_BLUE | FOREGROUND_INTENSITY,
[WAPP_TERM_COLOUR_FG_BR_CYAN] = FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY,
[WAPP_TERM_COLOUR_FG_BR_MAGENTA] = FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_INTENSITY,
[WAPP_TERM_COLOUR_FG_BR_YELLOW] = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY,
[WAPP_TERM_COLOUR_FG_BR_WHITE] = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY,
};
void print_coloured_text(Str8RO *text, TerminalColour colour) {
persistent TermcolourData data = {0};
if (data.handle == 0) {
init_data(&data);
}
if (colour == WAPP_TERM_COLOUR_CLEAR) {
data.current_colour = data.default_colour;
} else {
data.current_colour = colours[colour];
}
SetConsoleTextAttribute(data.handle, data.current_colour);
printf(WAPP_STR8_SPEC, wapp_str8_varg((*text)));
}
internal void init_data(TermcolourData *data) {
// create handle
data->handle = GetStdHandle(STD_OUTPUT_HANDLE);
// get console colour information
CONSOLE_SCREEN_BUFFER_INFO csbi;
GetConsoleScreenBufferInfo(data->handle, &csbi);
data->default_colour = csbi.wAttributes;
data->current_colour = data->default_colour;
}
#endif // !WAPP_PLATFORM_WINDOWS

View File

@@ -0,0 +1,26 @@
// vim:fileencoding=utf-8:foldmethod=marker
#ifndef SHELL_UTILS_H
#define SHELL_UTILS_H
#include "../../../../common/aliases/aliases.h"
#include "../../../../common/platform/platform.h"
#include <stdio.h>
#ifdef WAPP_PLATFORM_CPP
BEGIN_C_LINKAGE
#endif // !WAPP_PLATFORM_CPP
#ifdef WAPP_PLATFORM_WINDOWS
#define wapp_shell_utils_popen _popen
#define wapp_shell_utils_pclose _pclose
#else
#define wapp_shell_utils_popen popen
#define wapp_shell_utils_pclose pclose
#endif /* ifdef WAPP_PLATFORM_WINDOWS */
#ifdef WAPP_PLATFORM_CPP
END_C_LINKAGE
#endif // !WAPP_PLATFORM_CPP
#endif // !SHELL_UTILS_H

View File

@@ -1,34 +0,0 @@
#ifndef BASIC_STRING_H
#define BASIC_STRING_H
#include "aliases.h"
#include <stdio.h>
#include <string.h>
#ifdef __cplusplus
extern "C" {
#endif // __cplusplus
typedef struct bstr BasicString;
struct bstr {
u64 size;
const char *buf;
};
typedef struct strvw StringView;
struct strvw {
const u64 size;
const char *buf;
};
#define new_string(STR) \
{ .size = strlen(STR), .buf = STR }
#define wapp_bstr_new(STR) ((BasicString)new_string(STR))
#define wapp_strvw_new(STR) ((StringView)new_string(STR))
#define wapp_string_print(STR) (printf("%.*s\n", (i32)STR.size, STR.buf))
#ifdef __cplusplus
}
#endif // __cplusplus
#endif // !BASIC_STRING_H

View File

@@ -1,191 +0,0 @@
#include "dstr.h"
#include "aliases.h"
#include "mem_arena.h"
#include "platform.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// Use this scalar to allocate extra memory in order to avoid having to
// constantly reallocate
#define CAPACITY_SCALAR 8
#define MINIMUM_DSTR_CAPACITY 1024
struct dstr {
u64 capacity;
u64 size;
#ifdef WAPP_PLATFORM_WINDOWS
char *buf;
#else
char buf[];
#endif // WAPP_PLATFORM_WINDOWS
};
String *wapp_dstr_with_capacity(u64 capacity, Arena *arena) {
if (!arena) {
return NULL;
}
String *out =
(String *)wapp_mem_arena_alloc(arena, sizeof(String) + capacity + 1);
if (!out) {
return NULL;
}
out->capacity = capacity;
out->size = 0;
return out;
}
String *wapp_dstr_from_string(const char *str, Arena *arena) {
if (!str || !arena) {
return NULL;
}
u64 length = strlen(str);
u64 capacity = length * CAPACITY_SCALAR;
capacity =
capacity >= MINIMUM_DSTR_CAPACITY ? capacity : MINIMUM_DSTR_CAPACITY;
String *out = wapp_dstr_with_capacity(capacity, arena);
if (!out) {
return NULL;
}
out->size = length;
strncpy(out->buf, str, length + 1);
return out;
}
StringUpdate wapp_dstr_update(String **dst, const char *src, Arena *arena) {
if (!dst || !(*dst)) {
return (StringUpdate){.updated = false, .str = *dst};
}
u64 length = strlen(src);
String *str = *dst;
if (length >= str->capacity) {
if (!arena) {
return (StringUpdate){.updated = false, .str = *dst};
}
String *new_str = wapp_dstr_from_string(src, arena);
if (!new_str) {
return (StringUpdate){.updated = false, .str = *dst};
}
return (StringUpdate){.updated = true, .str = new_str};
}
memset(str->buf, 0, str->capacity);
str->size = length;
strncpy(str->buf, src, length + 1);
return (StringUpdate){.updated = true, .str = *dst};
}
StringUpdate wapp_dstr_concat(String **dst, const char *src, Arena *arena) {
if (!dst || !(*dst)) {
return (StringUpdate){.updated = false, .str = *dst};
}
u64 src_length = strlen(src);
if (src_length == 0) {
return (StringUpdate){.updated = false, .str = *dst};
}
u64 new_length = (*dst)->size + src_length;
#ifdef WAPP_PLATFORM_WINDOWS
char *str =
wapp_mem_util_alloc(NULL, new_length + 1, WAPP_MEM_ACCESS_READ_WRITE,
WAPP_MEM_ALLOC_RESERVE | WAPP_MEM_ALLOC_COMMIT,
WAPP_MEM_INIT_INITIALISED);
if (!str) {
return (StringUpdate){.updated = false, .str = *dst};
}
#else
char str[new_length + 1];
memset(str, 0, new_length + 1);
#endif /* ifdef WAPP_PLATFORM_WINDOWS */
strncpy(str, (*dst)->buf, (*dst)->size);
strncat(str, src, new_length + 1 - (*dst)->size);
return wapp_dstr_update(dst, str, arena);
}
void wapp_dstr_clear(String *str) {
if (!str || str->size == 0) {
return;
}
memset(str->buf, 0, str->capacity);
str->size = 0;
}
void wapp_dstr_print(const String *str) {
if (!str) {
return;
}
printf("%.*s\n", (i32)str->size, str->buf);
}
i64 wapp_dstr_find(const String *str, const char *substr) {
if (!str || !substr) {
return -1;
}
u64 substr_length = strlen(substr);
if (substr_length == 0 || substr_length > str->size) {
return -1;
}
const char *s1;
for (u64 i = 0; i < str->size; ++i) {
if (i + substr_length > str->size) {
break;
}
s1 = &(str->buf[i]);
if (strncmp(s1, substr, substr_length) == 0) {
return i;
}
}
return -1;
}
u64 wapp_dstr_length(const String *str) {
if (!str) {
return 0;
}
return str->size;
}
u64 wapp_dstr_capacity(const String *str) {
if (!str) {
return 0;
}
return str->capacity;
}
const char *wapp_dstr_to_cstr(const String *str) {
if (!str) {
return "";
}
return str->buf;
}

View File

@@ -1,41 +0,0 @@
#ifndef DSTR_H
#define DSTR_H
#include "aliases.h"
#include "mem_arena.h"
#include "misc_utils.h"
#include "platform.h"
#include <stdbool.h>
#ifdef __cplusplus
extern "C" {
#endif // __cplusplus
typedef struct dstr String;
typedef struct string_update StringUpdate;
struct string_update {
String *str;
bool updated;
#ifdef WAPP_PLATFORM_WINDOWS
wapp_misc_utils_padding_size(sizeof(bool) + sizeof(String *));
#endif // WAPP_PLATFORM_WINDOWS
};
String *wapp_dstr_with_capacity(u64 capacity, Arena *arena);
String *wapp_dstr_from_string(const char *str, Arena *arena);
StringUpdate wapp_dstr_update(String **dst, const char *src, Arena *arena);
StringUpdate wapp_dstr_concat(String **dst, const char *src, Arena *arena);
void wapp_dstr_clear(String *str);
void wapp_dstr_print(const String *str);
i64 wapp_dstr_find(const String *str, const char *substr);
u64 wapp_dstr_length(const String *str);
u64 wapp_dstr_capacity(const String *str);
const char *wapp_dstr_to_cstr(const String *str);
#ifdef __cplusplus
}
#endif // __cplusplus
#endif // !DSTR_H

23
src/core/wapp_core.c Normal file
View File

@@ -0,0 +1,23 @@
// vim:fileencoding=utf-8:foldmethod=marker
#ifndef WAPP_CORE_C
#define WAPP_CORE_C
#include "wapp_core.h"
#include "file/file.c"
#include "os/shell/termcolour/posix/termcolour_posix.c"
#include "os/shell/termcolour/win/termcolour_win.c"
#include "os/shell/termcolour/termcolour.c"
#include "os/shell/commander/posix/commander_posix.c"
#include "os/shell/commander/win/commander_win.c"
#include "os/shell/commander/commander.c"
#include "os/cpath/cpath.c"
#include "os/mem/posix/mem_os_posix.c"
#include "os/mem/win/mem_os_win.c"
#include "os/mem/mem_os.c"
#include "mem/utils/mem_utils.c"
#include "mem/arena/mem_arena.c"
#include "mem/arena/mem_arena_allocator.c"
#include "../primitives/wapp_primitives.c"
#endif // !WAPP_CORE_C

23
src/core/wapp_core.h Normal file
View File

@@ -0,0 +1,23 @@
// vim:fileencoding=utf-8:foldmethod=marker
#ifndef WAPP_CORE_H
#define WAPP_CORE_H
#include "file/file.h"
#include "os/shell/termcolour/termcolour.h"
#include "os/shell/termcolour/terminal_colours.h"
#include "os/shell/commander/commander.h"
#include "os/shell/commander/commander_output.h"
#include "os/shell/utils/shell_utils.h"
#include "os/cpath/cpath.h"
#include "os/mem/posix/mem_os_posix.h"
#include "os/mem/win/mem_os_win.h"
#include "os/mem/mem_os_ops.h"
#include "os/mem/mem_os.h"
#include "mem/utils/mem_utils.h"
#include "mem/arena/mem_arena_allocator.h"
#include "mem/arena/mem_arena.h"
#include "../common/wapp_common.h"
#include "../primitives/wapp_primitives.h"
#endif // !WAPP_CORE_H

3010
src/primitives/array/array.c Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,978 @@
/**
* THIS FILE IS AUTOMATICALLY GENERATED. ANY MODIFICATIONS TO IT WILL BE OVERWRITTEN.
*/
#ifndef ARRAY_H
#define ARRAY_H
#include "../mem_allocator/mem_allocator.h"
#include "../../common/misc/misc_utils.h"
#include "../../common/aliases/aliases.h"
#include "../../common/platform/platform.h"
#ifdef WAPP_PLATFORM_CPP
BEGIN_C_LINKAGE
#endif // !WAPP_PLATFORM_CPP
#define wapp_void_ptr_array_alloc_capacity(ALLOCATOR_PTR, CAPACITY) ((VoidPArray *)_array_alloc_capacity(ALLOCATOR_PTR, CAPACITY, sizeof(void *)))
#define wapp_str8_array_alloc_capacity(ALLOCATOR_PTR, CAPACITY) ((Str8Array *)_array_alloc_capacity(ALLOCATOR_PTR, CAPACITY, sizeof(Str8)))
#define wapp_b32_array_alloc_capacity(ALLOCATOR_PTR, CAPACITY) ((B32Array *)_array_alloc_capacity(ALLOCATOR_PTR, CAPACITY, sizeof(b32)))
#define wapp_char_array_alloc_capacity(ALLOCATOR_PTR, CAPACITY) ((CharArray *)_array_alloc_capacity(ALLOCATOR_PTR, CAPACITY, sizeof(char)))
#define wapp_c8_array_alloc_capacity(ALLOCATOR_PTR, CAPACITY) ((C8Array *)_array_alloc_capacity(ALLOCATOR_PTR, CAPACITY, sizeof(c8)))
#define wapp_c16_array_alloc_capacity(ALLOCATOR_PTR, CAPACITY) ((C16Array *)_array_alloc_capacity(ALLOCATOR_PTR, CAPACITY, sizeof(c16)))
#define wapp_c32_array_alloc_capacity(ALLOCATOR_PTR, CAPACITY) ((C32Array *)_array_alloc_capacity(ALLOCATOR_PTR, CAPACITY, sizeof(c32)))
#define wapp_i8_array_alloc_capacity(ALLOCATOR_PTR, CAPACITY) ((I8Array *)_array_alloc_capacity(ALLOCATOR_PTR, CAPACITY, sizeof(i8)))
#define wapp_i16_array_alloc_capacity(ALLOCATOR_PTR, CAPACITY) ((I16Array *)_array_alloc_capacity(ALLOCATOR_PTR, CAPACITY, sizeof(i16)))
#define wapp_i32_array_alloc_capacity(ALLOCATOR_PTR, CAPACITY) ((I32Array *)_array_alloc_capacity(ALLOCATOR_PTR, CAPACITY, sizeof(i32)))
#define wapp_i64_array_alloc_capacity(ALLOCATOR_PTR, CAPACITY) ((I64Array *)_array_alloc_capacity(ALLOCATOR_PTR, CAPACITY, sizeof(i64)))
#define wapp_u8_array_alloc_capacity(ALLOCATOR_PTR, CAPACITY) ((U8Array *)_array_alloc_capacity(ALLOCATOR_PTR, CAPACITY, sizeof(u8)))
#define wapp_u16_array_alloc_capacity(ALLOCATOR_PTR, CAPACITY) ((U16Array *)_array_alloc_capacity(ALLOCATOR_PTR, CAPACITY, sizeof(u16)))
#define wapp_u32_array_alloc_capacity(ALLOCATOR_PTR, CAPACITY) ((U32Array *)_array_alloc_capacity(ALLOCATOR_PTR, CAPACITY, sizeof(u32)))
#define wapp_u64_array_alloc_capacity(ALLOCATOR_PTR, CAPACITY) ((U64Array *)_array_alloc_capacity(ALLOCATOR_PTR, CAPACITY, sizeof(u64)))
#define wapp_f32_array_alloc_capacity(ALLOCATOR_PTR, CAPACITY) ((F32Array *)_array_alloc_capacity(ALLOCATOR_PTR, CAPACITY, sizeof(f32)))
#define wapp_f64_array_alloc_capacity(ALLOCATOR_PTR, CAPACITY) ((F64Array *)_array_alloc_capacity(ALLOCATOR_PTR, CAPACITY, sizeof(f64)))
#define wapp_f128_array_alloc_capacity(ALLOCATOR_PTR, CAPACITY) ((F128Array *)_array_alloc_capacity(ALLOCATOR_PTR, CAPACITY, sizeof(f128)))
#define wapp_iptr_array_alloc_capacity(ALLOCATOR_PTR, CAPACITY) ((IptrArray *)_array_alloc_capacity(ALLOCATOR_PTR, CAPACITY, sizeof(iptr)))
#define wapp_uptr_array_alloc_capacity(ALLOCATOR_PTR, CAPACITY) ((UptrArray *)_array_alloc_capacity(ALLOCATOR_PTR, CAPACITY, sizeof(uptr)))
#ifdef WAPP_PLATFORM_CPP
#define wapp_void_ptr_array(...) ([&]() { \
persistent void * buf[wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(void *, __VA_ARGS__) * 2)] = {__VA_ARGS__}; \
return VoidPArray{ \
buf, \
wapp_misc_utils_va_args_count(void *, __VA_ARGS__), \
wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(void *, __VA_ARGS__) * 2), \
sizeof(void *) \
}; \
}())
#define wapp_void_ptr_array_with_capacity(CAPACITY) ([&]() { \
persistent void * buf[CAPACITY] = {}; \
return VoidPArray{buf, 0, CAPACITY, sizeof(void *)}; \
}())
#define wapp_void_ptr_array_pop(ARRAY_PTR) (ARRAY_PTR != NULL && (ARRAY_PTR)->count > 0 ? \
*_void_ptr_array_pop(ARRAY_PTR) : \
void *{} \
)
#define wapp_str8_array(...) ([&]() { \
persistent Str8 buf[wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(Str8, __VA_ARGS__) * 2)] = {__VA_ARGS__}; \
return Str8Array{ \
buf, \
wapp_misc_utils_va_args_count(Str8, __VA_ARGS__), \
wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(Str8, __VA_ARGS__) * 2), \
sizeof(Str8) \
}; \
}())
#define wapp_str8_array_with_capacity(CAPACITY) ([&]() { \
persistent Str8 buf[CAPACITY] = {}; \
return Str8Array{buf, 0, CAPACITY, sizeof(Str8)}; \
}())
#define wapp_str8_array_pop(ARRAY_PTR) (ARRAY_PTR != NULL && (ARRAY_PTR)->count > 0 ? \
*_str8_array_pop(ARRAY_PTR) : \
Str8{} \
)
#define wapp_b32_array(...) ([&]() { \
persistent b32 buf[wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(b32, __VA_ARGS__) * 2)] = {__VA_ARGS__}; \
return B32Array{ \
buf, \
wapp_misc_utils_va_args_count(b32, __VA_ARGS__), \
wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(b32, __VA_ARGS__) * 2), \
sizeof(b32) \
}; \
}())
#define wapp_b32_array_with_capacity(CAPACITY) ([&]() { \
persistent b32 buf[CAPACITY] = {}; \
return B32Array{buf, 0, CAPACITY, sizeof(b32)}; \
}())
#define wapp_b32_array_pop(ARRAY_PTR) (ARRAY_PTR != NULL && (ARRAY_PTR)->count > 0 ? \
*_b32_array_pop(ARRAY_PTR) : \
b32{} \
)
#define wapp_char_array(...) ([&]() { \
persistent char buf[wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(char, __VA_ARGS__) * 2)] = {__VA_ARGS__}; \
return CharArray{ \
buf, \
wapp_misc_utils_va_args_count(char, __VA_ARGS__), \
wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(char, __VA_ARGS__) * 2), \
sizeof(char) \
}; \
}())
#define wapp_char_array_with_capacity(CAPACITY) ([&]() { \
persistent char buf[CAPACITY] = {}; \
return CharArray{buf, 0, CAPACITY, sizeof(char)}; \
}())
#define wapp_char_array_pop(ARRAY_PTR) (ARRAY_PTR != NULL && (ARRAY_PTR)->count > 0 ? \
*_char_array_pop(ARRAY_PTR) : \
char{} \
)
#define wapp_c8_array(...) ([&]() { \
persistent c8 buf[wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(c8, __VA_ARGS__) * 2)] = {__VA_ARGS__}; \
return C8Array{ \
buf, \
wapp_misc_utils_va_args_count(c8, __VA_ARGS__), \
wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(c8, __VA_ARGS__) * 2), \
sizeof(c8) \
}; \
}())
#define wapp_c8_array_with_capacity(CAPACITY) ([&]() { \
persistent c8 buf[CAPACITY] = {}; \
return C8Array{buf, 0, CAPACITY, sizeof(c8)}; \
}())
#define wapp_c8_array_pop(ARRAY_PTR) (ARRAY_PTR != NULL && (ARRAY_PTR)->count > 0 ? \
*_c8_array_pop(ARRAY_PTR) : \
c8{} \
)
#define wapp_c16_array(...) ([&]() { \
persistent c16 buf[wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(c16, __VA_ARGS__) * 2)] = {__VA_ARGS__}; \
return C16Array{ \
buf, \
wapp_misc_utils_va_args_count(c16, __VA_ARGS__), \
wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(c16, __VA_ARGS__) * 2), \
sizeof(c16) \
}; \
}())
#define wapp_c16_array_with_capacity(CAPACITY) ([&]() { \
persistent c16 buf[CAPACITY] = {}; \
return C16Array{buf, 0, CAPACITY, sizeof(c16)}; \
}())
#define wapp_c16_array_pop(ARRAY_PTR) (ARRAY_PTR != NULL && (ARRAY_PTR)->count > 0 ? \
*_c16_array_pop(ARRAY_PTR) : \
c16{} \
)
#define wapp_c32_array(...) ([&]() { \
persistent c32 buf[wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(c32, __VA_ARGS__) * 2)] = {__VA_ARGS__}; \
return C32Array{ \
buf, \
wapp_misc_utils_va_args_count(c32, __VA_ARGS__), \
wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(c32, __VA_ARGS__) * 2), \
sizeof(c32) \
}; \
}())
#define wapp_c32_array_with_capacity(CAPACITY) ([&]() { \
persistent c32 buf[CAPACITY] = {}; \
return C32Array{buf, 0, CAPACITY, sizeof(c32)}; \
}())
#define wapp_c32_array_pop(ARRAY_PTR) (ARRAY_PTR != NULL && (ARRAY_PTR)->count > 0 ? \
*_c32_array_pop(ARRAY_PTR) : \
c32{} \
)
#define wapp_i8_array(...) ([&]() { \
persistent i8 buf[wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(i8, __VA_ARGS__) * 2)] = {__VA_ARGS__}; \
return I8Array{ \
buf, \
wapp_misc_utils_va_args_count(i8, __VA_ARGS__), \
wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(i8, __VA_ARGS__) * 2), \
sizeof(i8) \
}; \
}())
#define wapp_i8_array_with_capacity(CAPACITY) ([&]() { \
persistent i8 buf[CAPACITY] = {}; \
return I8Array{buf, 0, CAPACITY, sizeof(i8)}; \
}())
#define wapp_i8_array_pop(ARRAY_PTR) (ARRAY_PTR != NULL && (ARRAY_PTR)->count > 0 ? \
*_i8_array_pop(ARRAY_PTR) : \
i8{} \
)
#define wapp_i16_array(...) ([&]() { \
persistent i16 buf[wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(i16, __VA_ARGS__) * 2)] = {__VA_ARGS__}; \
return I16Array{ \
buf, \
wapp_misc_utils_va_args_count(i16, __VA_ARGS__), \
wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(i16, __VA_ARGS__) * 2), \
sizeof(i16) \
}; \
}())
#define wapp_i16_array_with_capacity(CAPACITY) ([&]() { \
persistent i16 buf[CAPACITY] = {}; \
return I16Array{buf, 0, CAPACITY, sizeof(i16)}; \
}())
#define wapp_i16_array_pop(ARRAY_PTR) (ARRAY_PTR != NULL && (ARRAY_PTR)->count > 0 ? \
*_i16_array_pop(ARRAY_PTR) : \
i16{} \
)
#define wapp_i32_array(...) ([&]() { \
persistent i32 buf[wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(i32, __VA_ARGS__) * 2)] = {__VA_ARGS__}; \
return I32Array{ \
buf, \
wapp_misc_utils_va_args_count(i32, __VA_ARGS__), \
wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(i32, __VA_ARGS__) * 2), \
sizeof(i32) \
}; \
}())
#define wapp_i32_array_with_capacity(CAPACITY) ([&]() { \
persistent i32 buf[CAPACITY] = {}; \
return I32Array{buf, 0, CAPACITY, sizeof(i32)}; \
}())
#define wapp_i32_array_pop(ARRAY_PTR) (ARRAY_PTR != NULL && (ARRAY_PTR)->count > 0 ? \
*_i32_array_pop(ARRAY_PTR) : \
i32{} \
)
#define wapp_i64_array(...) ([&]() { \
persistent i64 buf[wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(i64, __VA_ARGS__) * 2)] = {__VA_ARGS__}; \
return I64Array{ \
buf, \
wapp_misc_utils_va_args_count(i64, __VA_ARGS__), \
wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(i64, __VA_ARGS__) * 2), \
sizeof(i64) \
}; \
}())
#define wapp_i64_array_with_capacity(CAPACITY) ([&]() { \
persistent i64 buf[CAPACITY] = {}; \
return I64Array{buf, 0, CAPACITY, sizeof(i64)}; \
}())
#define wapp_i64_array_pop(ARRAY_PTR) (ARRAY_PTR != NULL && (ARRAY_PTR)->count > 0 ? \
*_i64_array_pop(ARRAY_PTR) : \
i64{} \
)
#define wapp_u8_array(...) ([&]() { \
persistent u8 buf[wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(u8, __VA_ARGS__) * 2)] = {__VA_ARGS__}; \
return U8Array{ \
buf, \
wapp_misc_utils_va_args_count(u8, __VA_ARGS__), \
wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(u8, __VA_ARGS__) * 2), \
sizeof(u8) \
}; \
}())
#define wapp_u8_array_with_capacity(CAPACITY) ([&]() { \
persistent u8 buf[CAPACITY] = {}; \
return U8Array{buf, 0, CAPACITY, sizeof(u8)}; \
}())
#define wapp_u8_array_pop(ARRAY_PTR) (ARRAY_PTR != NULL && (ARRAY_PTR)->count > 0 ? \
*_u8_array_pop(ARRAY_PTR) : \
u8{} \
)
#define wapp_u16_array(...) ([&]() { \
persistent u16 buf[wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(u16, __VA_ARGS__) * 2)] = {__VA_ARGS__}; \
return U16Array{ \
buf, \
wapp_misc_utils_va_args_count(u16, __VA_ARGS__), \
wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(u16, __VA_ARGS__) * 2), \
sizeof(u16) \
}; \
}())
#define wapp_u16_array_with_capacity(CAPACITY) ([&]() { \
persistent u16 buf[CAPACITY] = {}; \
return U16Array{buf, 0, CAPACITY, sizeof(u16)}; \
}())
#define wapp_u16_array_pop(ARRAY_PTR) (ARRAY_PTR != NULL && (ARRAY_PTR)->count > 0 ? \
*_u16_array_pop(ARRAY_PTR) : \
u16{} \
)
#define wapp_u32_array(...) ([&]() { \
persistent u32 buf[wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(u32, __VA_ARGS__) * 2)] = {__VA_ARGS__}; \
return U32Array{ \
buf, \
wapp_misc_utils_va_args_count(u32, __VA_ARGS__), \
wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(u32, __VA_ARGS__) * 2), \
sizeof(u32) \
}; \
}())
#define wapp_u32_array_with_capacity(CAPACITY) ([&]() { \
persistent u32 buf[CAPACITY] = {}; \
return U32Array{buf, 0, CAPACITY, sizeof(u32)}; \
}())
#define wapp_u32_array_pop(ARRAY_PTR) (ARRAY_PTR != NULL && (ARRAY_PTR)->count > 0 ? \
*_u32_array_pop(ARRAY_PTR) : \
u32{} \
)
#define wapp_u64_array(...) ([&]() { \
persistent u64 buf[wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(u64, __VA_ARGS__) * 2)] = {__VA_ARGS__}; \
return U64Array{ \
buf, \
wapp_misc_utils_va_args_count(u64, __VA_ARGS__), \
wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(u64, __VA_ARGS__) * 2), \
sizeof(u64) \
}; \
}())
#define wapp_u64_array_with_capacity(CAPACITY) ([&]() { \
persistent u64 buf[CAPACITY] = {}; \
return U64Array{buf, 0, CAPACITY, sizeof(u64)}; \
}())
#define wapp_u64_array_pop(ARRAY_PTR) (ARRAY_PTR != NULL && (ARRAY_PTR)->count > 0 ? \
*_u64_array_pop(ARRAY_PTR) : \
u64{} \
)
#define wapp_f32_array(...) ([&]() { \
persistent f32 buf[wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(f32, __VA_ARGS__) * 2)] = {__VA_ARGS__}; \
return F32Array{ \
buf, \
wapp_misc_utils_va_args_count(f32, __VA_ARGS__), \
wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(f32, __VA_ARGS__) * 2), \
sizeof(f32) \
}; \
}())
#define wapp_f32_array_with_capacity(CAPACITY) ([&]() { \
persistent f32 buf[CAPACITY] = {}; \
return F32Array{buf, 0, CAPACITY, sizeof(f32)}; \
}())
#define wapp_f32_array_pop(ARRAY_PTR) (ARRAY_PTR != NULL && (ARRAY_PTR)->count > 0 ? \
*_f32_array_pop(ARRAY_PTR) : \
f32{} \
)
#define wapp_f64_array(...) ([&]() { \
persistent f64 buf[wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(f64, __VA_ARGS__) * 2)] = {__VA_ARGS__}; \
return F64Array{ \
buf, \
wapp_misc_utils_va_args_count(f64, __VA_ARGS__), \
wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(f64, __VA_ARGS__) * 2), \
sizeof(f64) \
}; \
}())
#define wapp_f64_array_with_capacity(CAPACITY) ([&]() { \
persistent f64 buf[CAPACITY] = {}; \
return F64Array{buf, 0, CAPACITY, sizeof(f64)}; \
}())
#define wapp_f64_array_pop(ARRAY_PTR) (ARRAY_PTR != NULL && (ARRAY_PTR)->count > 0 ? \
*_f64_array_pop(ARRAY_PTR) : \
f64{} \
)
#define wapp_f128_array(...) ([&]() { \
persistent f128 buf[wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(f128, __VA_ARGS__) * 2)] = {__VA_ARGS__}; \
return F128Array{ \
buf, \
wapp_misc_utils_va_args_count(f128, __VA_ARGS__), \
wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(f128, __VA_ARGS__) * 2), \
sizeof(f128) \
}; \
}())
#define wapp_f128_array_with_capacity(CAPACITY) ([&]() { \
persistent f128 buf[CAPACITY] = {}; \
return F128Array{buf, 0, CAPACITY, sizeof(f128)}; \
}())
#define wapp_f128_array_pop(ARRAY_PTR) (ARRAY_PTR != NULL && (ARRAY_PTR)->count > 0 ? \
*_f128_array_pop(ARRAY_PTR) : \
f128{} \
)
#define wapp_iptr_array(...) ([&]() { \
persistent iptr buf[wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(iptr, __VA_ARGS__) * 2)] = {__VA_ARGS__}; \
return IptrArray{ \
buf, \
wapp_misc_utils_va_args_count(iptr, __VA_ARGS__), \
wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(iptr, __VA_ARGS__) * 2), \
sizeof(iptr) \
}; \
}())
#define wapp_iptr_array_with_capacity(CAPACITY) ([&]() { \
persistent iptr buf[CAPACITY] = {}; \
return IptrArray{buf, 0, CAPACITY, sizeof(iptr)}; \
}())
#define wapp_iptr_array_pop(ARRAY_PTR) (ARRAY_PTR != NULL && (ARRAY_PTR)->count > 0 ? \
*_iptr_array_pop(ARRAY_PTR) : \
iptr{} \
)
#define wapp_uptr_array(...) ([&]() { \
persistent uptr buf[wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(uptr, __VA_ARGS__) * 2)] = {__VA_ARGS__}; \
return UptrArray{ \
buf, \
wapp_misc_utils_va_args_count(uptr, __VA_ARGS__), \
wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(uptr, __VA_ARGS__) * 2), \
sizeof(uptr) \
}; \
}())
#define wapp_uptr_array_with_capacity(CAPACITY) ([&]() { \
persistent uptr buf[CAPACITY] = {}; \
return UptrArray{buf, 0, CAPACITY, sizeof(uptr)}; \
}())
#define wapp_uptr_array_pop(ARRAY_PTR) (ARRAY_PTR != NULL && (ARRAY_PTR)->count > 0 ? \
*_uptr_array_pop(ARRAY_PTR) : \
uptr{} \
)
#else
#define wapp_void_ptr_array(...) ((VoidPArray){ \
.items = (void *[wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(void *, __VA_ARGS__) * 2)]){__VA_ARGS__}, \
.count = wapp_misc_utils_va_args_count(void *, __VA_ARGS__), \
.capacity = wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(void *, __VA_ARGS__) * 2), \
.item_size = sizeof(void *) \
})
#define wapp_void_ptr_array_with_capacity(CAPACITY) ((VoidPArray){.items = (void *[CAPACITY]){0}, .count = 0, .capacity = CAPACITY, .item_size = sizeof(void *)})
#define wapp_void_ptr_array_pop(ARRAY_PTR) (ARRAY_PTR != NULL && (ARRAY_PTR)->count > 0 ? \
*_void_ptr_array_pop(ARRAY_PTR) : \
(void *){0} \
)
#define wapp_str8_array(...) ((Str8Array){ \
.items = (Str8[wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(Str8, __VA_ARGS__) * 2)]){__VA_ARGS__}, \
.count = wapp_misc_utils_va_args_count(Str8, __VA_ARGS__), \
.capacity = wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(Str8, __VA_ARGS__) * 2), \
.item_size = sizeof(Str8) \
})
#define wapp_str8_array_with_capacity(CAPACITY) ((Str8Array){.items = (Str8[CAPACITY]){0}, .count = 0, .capacity = CAPACITY, .item_size = sizeof(Str8)})
#define wapp_str8_array_pop(ARRAY_PTR) (ARRAY_PTR != NULL && (ARRAY_PTR)->count > 0 ? \
*_str8_array_pop(ARRAY_PTR) : \
(Str8){0} \
)
#define wapp_b32_array(...) ((B32Array){ \
.items = (b32[wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(b32, __VA_ARGS__) * 2)]){__VA_ARGS__}, \
.count = wapp_misc_utils_va_args_count(b32, __VA_ARGS__), \
.capacity = wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(b32, __VA_ARGS__) * 2), \
.item_size = sizeof(b32) \
})
#define wapp_b32_array_with_capacity(CAPACITY) ((B32Array){.items = (b32[CAPACITY]){0}, .count = 0, .capacity = CAPACITY, .item_size = sizeof(b32)})
#define wapp_b32_array_pop(ARRAY_PTR) (ARRAY_PTR != NULL && (ARRAY_PTR)->count > 0 ? \
*_b32_array_pop(ARRAY_PTR) : \
(b32){0} \
)
#define wapp_char_array(...) ((CharArray){ \
.items = (char[wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(char, __VA_ARGS__) * 2)]){__VA_ARGS__}, \
.count = wapp_misc_utils_va_args_count(char, __VA_ARGS__), \
.capacity = wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(char, __VA_ARGS__) * 2), \
.item_size = sizeof(char) \
})
#define wapp_char_array_with_capacity(CAPACITY) ((CharArray){.items = (char[CAPACITY]){0}, .count = 0, .capacity = CAPACITY, .item_size = sizeof(char)})
#define wapp_char_array_pop(ARRAY_PTR) (ARRAY_PTR != NULL && (ARRAY_PTR)->count > 0 ? \
*_char_array_pop(ARRAY_PTR) : \
(char){0} \
)
#define wapp_c8_array(...) ((C8Array){ \
.items = (c8[wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(c8, __VA_ARGS__) * 2)]){__VA_ARGS__}, \
.count = wapp_misc_utils_va_args_count(c8, __VA_ARGS__), \
.capacity = wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(c8, __VA_ARGS__) * 2), \
.item_size = sizeof(c8) \
})
#define wapp_c8_array_with_capacity(CAPACITY) ((C8Array){.items = (c8[CAPACITY]){0}, .count = 0, .capacity = CAPACITY, .item_size = sizeof(c8)})
#define wapp_c8_array_pop(ARRAY_PTR) (ARRAY_PTR != NULL && (ARRAY_PTR)->count > 0 ? \
*_c8_array_pop(ARRAY_PTR) : \
(c8){0} \
)
#define wapp_c16_array(...) ((C16Array){ \
.items = (c16[wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(c16, __VA_ARGS__) * 2)]){__VA_ARGS__}, \
.count = wapp_misc_utils_va_args_count(c16, __VA_ARGS__), \
.capacity = wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(c16, __VA_ARGS__) * 2), \
.item_size = sizeof(c16) \
})
#define wapp_c16_array_with_capacity(CAPACITY) ((C16Array){.items = (c16[CAPACITY]){0}, .count = 0, .capacity = CAPACITY, .item_size = sizeof(c16)})
#define wapp_c16_array_pop(ARRAY_PTR) (ARRAY_PTR != NULL && (ARRAY_PTR)->count > 0 ? \
*_c16_array_pop(ARRAY_PTR) : \
(c16){0} \
)
#define wapp_c32_array(...) ((C32Array){ \
.items = (c32[wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(c32, __VA_ARGS__) * 2)]){__VA_ARGS__}, \
.count = wapp_misc_utils_va_args_count(c32, __VA_ARGS__), \
.capacity = wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(c32, __VA_ARGS__) * 2), \
.item_size = sizeof(c32) \
})
#define wapp_c32_array_with_capacity(CAPACITY) ((C32Array){.items = (c32[CAPACITY]){0}, .count = 0, .capacity = CAPACITY, .item_size = sizeof(c32)})
#define wapp_c32_array_pop(ARRAY_PTR) (ARRAY_PTR != NULL && (ARRAY_PTR)->count > 0 ? \
*_c32_array_pop(ARRAY_PTR) : \
(c32){0} \
)
#define wapp_i8_array(...) ((I8Array){ \
.items = (i8[wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(i8, __VA_ARGS__) * 2)]){__VA_ARGS__}, \
.count = wapp_misc_utils_va_args_count(i8, __VA_ARGS__), \
.capacity = wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(i8, __VA_ARGS__) * 2), \
.item_size = sizeof(i8) \
})
#define wapp_i8_array_with_capacity(CAPACITY) ((I8Array){.items = (i8[CAPACITY]){0}, .count = 0, .capacity = CAPACITY, .item_size = sizeof(i8)})
#define wapp_i8_array_pop(ARRAY_PTR) (ARRAY_PTR != NULL && (ARRAY_PTR)->count > 0 ? \
*_i8_array_pop(ARRAY_PTR) : \
(i8){0} \
)
#define wapp_i16_array(...) ((I16Array){ \
.items = (i16[wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(i16, __VA_ARGS__) * 2)]){__VA_ARGS__}, \
.count = wapp_misc_utils_va_args_count(i16, __VA_ARGS__), \
.capacity = wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(i16, __VA_ARGS__) * 2), \
.item_size = sizeof(i16) \
})
#define wapp_i16_array_with_capacity(CAPACITY) ((I16Array){.items = (i16[CAPACITY]){0}, .count = 0, .capacity = CAPACITY, .item_size = sizeof(i16)})
#define wapp_i16_array_pop(ARRAY_PTR) (ARRAY_PTR != NULL && (ARRAY_PTR)->count > 0 ? \
*_i16_array_pop(ARRAY_PTR) : \
(i16){0} \
)
#define wapp_i32_array(...) ((I32Array){ \
.items = (i32[wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(i32, __VA_ARGS__) * 2)]){__VA_ARGS__}, \
.count = wapp_misc_utils_va_args_count(i32, __VA_ARGS__), \
.capacity = wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(i32, __VA_ARGS__) * 2), \
.item_size = sizeof(i32) \
})
#define wapp_i32_array_with_capacity(CAPACITY) ((I32Array){.items = (i32[CAPACITY]){0}, .count = 0, .capacity = CAPACITY, .item_size = sizeof(i32)})
#define wapp_i32_array_pop(ARRAY_PTR) (ARRAY_PTR != NULL && (ARRAY_PTR)->count > 0 ? \
*_i32_array_pop(ARRAY_PTR) : \
(i32){0} \
)
#define wapp_i64_array(...) ((I64Array){ \
.items = (i64[wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(i64, __VA_ARGS__) * 2)]){__VA_ARGS__}, \
.count = wapp_misc_utils_va_args_count(i64, __VA_ARGS__), \
.capacity = wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(i64, __VA_ARGS__) * 2), \
.item_size = sizeof(i64) \
})
#define wapp_i64_array_with_capacity(CAPACITY) ((I64Array){.items = (i64[CAPACITY]){0}, .count = 0, .capacity = CAPACITY, .item_size = sizeof(i64)})
#define wapp_i64_array_pop(ARRAY_PTR) (ARRAY_PTR != NULL && (ARRAY_PTR)->count > 0 ? \
*_i64_array_pop(ARRAY_PTR) : \
(i64){0} \
)
#define wapp_u8_array(...) ((U8Array){ \
.items = (u8[wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(u8, __VA_ARGS__) * 2)]){__VA_ARGS__}, \
.count = wapp_misc_utils_va_args_count(u8, __VA_ARGS__), \
.capacity = wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(u8, __VA_ARGS__) * 2), \
.item_size = sizeof(u8) \
})
#define wapp_u8_array_with_capacity(CAPACITY) ((U8Array){.items = (u8[CAPACITY]){0}, .count = 0, .capacity = CAPACITY, .item_size = sizeof(u8)})
#define wapp_u8_array_pop(ARRAY_PTR) (ARRAY_PTR != NULL && (ARRAY_PTR)->count > 0 ? \
*_u8_array_pop(ARRAY_PTR) : \
(u8){0} \
)
#define wapp_u16_array(...) ((U16Array){ \
.items = (u16[wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(u16, __VA_ARGS__) * 2)]){__VA_ARGS__}, \
.count = wapp_misc_utils_va_args_count(u16, __VA_ARGS__), \
.capacity = wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(u16, __VA_ARGS__) * 2), \
.item_size = sizeof(u16) \
})
#define wapp_u16_array_with_capacity(CAPACITY) ((U16Array){.items = (u16[CAPACITY]){0}, .count = 0, .capacity = CAPACITY, .item_size = sizeof(u16)})
#define wapp_u16_array_pop(ARRAY_PTR) (ARRAY_PTR != NULL && (ARRAY_PTR)->count > 0 ? \
*_u16_array_pop(ARRAY_PTR) : \
(u16){0} \
)
#define wapp_u32_array(...) ((U32Array){ \
.items = (u32[wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(u32, __VA_ARGS__) * 2)]){__VA_ARGS__}, \
.count = wapp_misc_utils_va_args_count(u32, __VA_ARGS__), \
.capacity = wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(u32, __VA_ARGS__) * 2), \
.item_size = sizeof(u32) \
})
#define wapp_u32_array_with_capacity(CAPACITY) ((U32Array){.items = (u32[CAPACITY]){0}, .count = 0, .capacity = CAPACITY, .item_size = sizeof(u32)})
#define wapp_u32_array_pop(ARRAY_PTR) (ARRAY_PTR != NULL && (ARRAY_PTR)->count > 0 ? \
*_u32_array_pop(ARRAY_PTR) : \
(u32){0} \
)
#define wapp_u64_array(...) ((U64Array){ \
.items = (u64[wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(u64, __VA_ARGS__) * 2)]){__VA_ARGS__}, \
.count = wapp_misc_utils_va_args_count(u64, __VA_ARGS__), \
.capacity = wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(u64, __VA_ARGS__) * 2), \
.item_size = sizeof(u64) \
})
#define wapp_u64_array_with_capacity(CAPACITY) ((U64Array){.items = (u64[CAPACITY]){0}, .count = 0, .capacity = CAPACITY, .item_size = sizeof(u64)})
#define wapp_u64_array_pop(ARRAY_PTR) (ARRAY_PTR != NULL && (ARRAY_PTR)->count > 0 ? \
*_u64_array_pop(ARRAY_PTR) : \
(u64){0} \
)
#define wapp_f32_array(...) ((F32Array){ \
.items = (f32[wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(f32, __VA_ARGS__) * 2)]){__VA_ARGS__}, \
.count = wapp_misc_utils_va_args_count(f32, __VA_ARGS__), \
.capacity = wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(f32, __VA_ARGS__) * 2), \
.item_size = sizeof(f32) \
})
#define wapp_f32_array_with_capacity(CAPACITY) ((F32Array){.items = (f32[CAPACITY]){0}, .count = 0, .capacity = CAPACITY, .item_size = sizeof(f32)})
#define wapp_f32_array_pop(ARRAY_PTR) (ARRAY_PTR != NULL && (ARRAY_PTR)->count > 0 ? \
*_f32_array_pop(ARRAY_PTR) : \
(f32){0} \
)
#define wapp_f64_array(...) ((F64Array){ \
.items = (f64[wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(f64, __VA_ARGS__) * 2)]){__VA_ARGS__}, \
.count = wapp_misc_utils_va_args_count(f64, __VA_ARGS__), \
.capacity = wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(f64, __VA_ARGS__) * 2), \
.item_size = sizeof(f64) \
})
#define wapp_f64_array_with_capacity(CAPACITY) ((F64Array){.items = (f64[CAPACITY]){0}, .count = 0, .capacity = CAPACITY, .item_size = sizeof(f64)})
#define wapp_f64_array_pop(ARRAY_PTR) (ARRAY_PTR != NULL && (ARRAY_PTR)->count > 0 ? \
*_f64_array_pop(ARRAY_PTR) : \
(f64){0} \
)
#define wapp_f128_array(...) ((F128Array){ \
.items = (f128[wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(f128, __VA_ARGS__) * 2)]){__VA_ARGS__}, \
.count = wapp_misc_utils_va_args_count(f128, __VA_ARGS__), \
.capacity = wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(f128, __VA_ARGS__) * 2), \
.item_size = sizeof(f128) \
})
#define wapp_f128_array_with_capacity(CAPACITY) ((F128Array){.items = (f128[CAPACITY]){0}, .count = 0, .capacity = CAPACITY, .item_size = sizeof(f128)})
#define wapp_f128_array_pop(ARRAY_PTR) (ARRAY_PTR != NULL && (ARRAY_PTR)->count > 0 ? \
*_f128_array_pop(ARRAY_PTR) : \
(f128){0} \
)
#define wapp_iptr_array(...) ((IptrArray){ \
.items = (iptr[wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(iptr, __VA_ARGS__) * 2)]){__VA_ARGS__}, \
.count = wapp_misc_utils_va_args_count(iptr, __VA_ARGS__), \
.capacity = wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(iptr, __VA_ARGS__) * 2), \
.item_size = sizeof(iptr) \
})
#define wapp_iptr_array_with_capacity(CAPACITY) ((IptrArray){.items = (iptr[CAPACITY]){0}, .count = 0, .capacity = CAPACITY, .item_size = sizeof(iptr)})
#define wapp_iptr_array_pop(ARRAY_PTR) (ARRAY_PTR != NULL && (ARRAY_PTR)->count > 0 ? \
*_iptr_array_pop(ARRAY_PTR) : \
(iptr){0} \
)
#define wapp_uptr_array(...) ((UptrArray){ \
.items = (uptr[wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(uptr, __VA_ARGS__) * 2)]){__VA_ARGS__}, \
.count = wapp_misc_utils_va_args_count(uptr, __VA_ARGS__), \
.capacity = wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(uptr, __VA_ARGS__) * 2), \
.item_size = sizeof(uptr) \
})
#define wapp_uptr_array_with_capacity(CAPACITY) ((UptrArray){.items = (uptr[CAPACITY]){0}, .count = 0, .capacity = CAPACITY, .item_size = sizeof(uptr)})
#define wapp_uptr_array_pop(ARRAY_PTR) (ARRAY_PTR != NULL && (ARRAY_PTR)->count > 0 ? \
*_uptr_array_pop(ARRAY_PTR) : \
(uptr){0} \
)
#endif // !WAPP_PLATFORM_CPP
typedef struct str8 Str8;
typedef struct GenericArray GenericArray;
struct GenericArray {
void *items;
u64 count;
u64 capacity;
u64 item_size;
};
typedef struct VoidPArray VoidPArray;
struct VoidPArray {
void * *items;
u64 count;
u64 capacity;
u64 item_size;
};
typedef struct Str8Array Str8Array;
struct Str8Array {
Str8 *items;
u64 count;
u64 capacity;
u64 item_size;
};
typedef struct B32Array B32Array;
struct B32Array {
b32 *items;
u64 count;
u64 capacity;
u64 item_size;
};
typedef struct CharArray CharArray;
struct CharArray {
char *items;
u64 count;
u64 capacity;
u64 item_size;
};
typedef struct C8Array C8Array;
struct C8Array {
c8 *items;
u64 count;
u64 capacity;
u64 item_size;
};
typedef struct C16Array C16Array;
struct C16Array {
c16 *items;
u64 count;
u64 capacity;
u64 item_size;
};
typedef struct C32Array C32Array;
struct C32Array {
c32 *items;
u64 count;
u64 capacity;
u64 item_size;
};
typedef struct I8Array I8Array;
struct I8Array {
i8 *items;
u64 count;
u64 capacity;
u64 item_size;
};
typedef struct I16Array I16Array;
struct I16Array {
i16 *items;
u64 count;
u64 capacity;
u64 item_size;
};
typedef struct I32Array I32Array;
struct I32Array {
i32 *items;
u64 count;
u64 capacity;
u64 item_size;
};
typedef struct I64Array I64Array;
struct I64Array {
i64 *items;
u64 count;
u64 capacity;
u64 item_size;
};
typedef struct U8Array U8Array;
struct U8Array {
u8 *items;
u64 count;
u64 capacity;
u64 item_size;
};
typedef struct U16Array U16Array;
struct U16Array {
u16 *items;
u64 count;
u64 capacity;
u64 item_size;
};
typedef struct U32Array U32Array;
struct U32Array {
u32 *items;
u64 count;
u64 capacity;
u64 item_size;
};
typedef struct U64Array U64Array;
struct U64Array {
u64 *items;
u64 count;
u64 capacity;
u64 item_size;
};
typedef struct F32Array F32Array;
struct F32Array {
f32 *items;
u64 count;
u64 capacity;
u64 item_size;
};
typedef struct F64Array F64Array;
struct F64Array {
f64 *items;
u64 count;
u64 capacity;
u64 item_size;
};
typedef struct F128Array F128Array;
struct F128Array {
f128 *items;
u64 count;
u64 capacity;
u64 item_size;
};
typedef struct IptrArray IptrArray;
struct IptrArray {
iptr *items;
u64 count;
u64 capacity;
u64 item_size;
};
typedef struct UptrArray UptrArray;
struct UptrArray {
uptr *items;
u64 count;
u64 capacity;
u64 item_size;
};
void * *wapp_void_ptr_array_get(const VoidPArray *array, u64 index);
void wapp_void_ptr_array_set(VoidPArray *array, u64 index, void * *item);
void wapp_void_ptr_array_append_capped(VoidPArray *array, void * *item);
void wapp_void_ptr_array_extend_capped(VoidPArray *array, const VoidPArray *other);
void wapp_void_ptr_array_clear(VoidPArray *array);
void wapp_void_ptr_array_copy_capped(const VoidPArray *src, VoidPArray *dst);
VoidPArray *wapp_void_ptr_array_append_alloc(const Allocator *allocator, VoidPArray *array, void * *item);
VoidPArray *wapp_void_ptr_array_extend_alloc(const Allocator *allocator, VoidPArray *array, const VoidPArray *other);
VoidPArray *wapp_void_ptr_array_copy_alloc(const Allocator *allocator, const VoidPArray *src, VoidPArray *dst);
void * *_void_ptr_array_pop(VoidPArray *array);
Str8 *wapp_str8_array_get(const Str8Array *array, u64 index);
void wapp_str8_array_set(Str8Array *array, u64 index, Str8 *item);
void wapp_str8_array_append_capped(Str8Array *array, Str8 *item);
void wapp_str8_array_extend_capped(Str8Array *array, const Str8Array *other);
void wapp_str8_array_clear(Str8Array *array);
void wapp_str8_array_copy_capped(const Str8Array *src, Str8Array *dst);
Str8Array *wapp_str8_array_append_alloc(const Allocator *allocator, Str8Array *array, Str8 *item);
Str8Array *wapp_str8_array_extend_alloc(const Allocator *allocator, Str8Array *array, const Str8Array *other);
Str8Array *wapp_str8_array_copy_alloc(const Allocator *allocator, const Str8Array *src, Str8Array *dst);
Str8 *_str8_array_pop(Str8Array *array);
b32 *wapp_b32_array_get(const B32Array *array, u64 index);
void wapp_b32_array_set(B32Array *array, u64 index, b32 *item);
void wapp_b32_array_append_capped(B32Array *array, b32 *item);
void wapp_b32_array_extend_capped(B32Array *array, const B32Array *other);
void wapp_b32_array_clear(B32Array *array);
void wapp_b32_array_copy_capped(const B32Array *src, B32Array *dst);
B32Array *wapp_b32_array_append_alloc(const Allocator *allocator, B32Array *array, b32 *item);
B32Array *wapp_b32_array_extend_alloc(const Allocator *allocator, B32Array *array, const B32Array *other);
B32Array *wapp_b32_array_copy_alloc(const Allocator *allocator, const B32Array *src, B32Array *dst);
b32 *_b32_array_pop(B32Array *array);
char *wapp_char_array_get(const CharArray *array, u64 index);
void wapp_char_array_set(CharArray *array, u64 index, char *item);
void wapp_char_array_append_capped(CharArray *array, char *item);
void wapp_char_array_extend_capped(CharArray *array, const CharArray *other);
void wapp_char_array_clear(CharArray *array);
void wapp_char_array_copy_capped(const CharArray *src, CharArray *dst);
CharArray *wapp_char_array_append_alloc(const Allocator *allocator, CharArray *array, char *item);
CharArray *wapp_char_array_extend_alloc(const Allocator *allocator, CharArray *array, const CharArray *other);
CharArray *wapp_char_array_copy_alloc(const Allocator *allocator, const CharArray *src, CharArray *dst);
char *_char_array_pop(CharArray *array);
c8 *wapp_c8_array_get(const C8Array *array, u64 index);
void wapp_c8_array_set(C8Array *array, u64 index, c8 *item);
void wapp_c8_array_append_capped(C8Array *array, c8 *item);
void wapp_c8_array_extend_capped(C8Array *array, const C8Array *other);
void wapp_c8_array_clear(C8Array *array);
void wapp_c8_array_copy_capped(const C8Array *src, C8Array *dst);
C8Array *wapp_c8_array_append_alloc(const Allocator *allocator, C8Array *array, c8 *item);
C8Array *wapp_c8_array_extend_alloc(const Allocator *allocator, C8Array *array, const C8Array *other);
C8Array *wapp_c8_array_copy_alloc(const Allocator *allocator, const C8Array *src, C8Array *dst);
c8 *_c8_array_pop(C8Array *array);
c16 *wapp_c16_array_get(const C16Array *array, u64 index);
void wapp_c16_array_set(C16Array *array, u64 index, c16 *item);
void wapp_c16_array_append_capped(C16Array *array, c16 *item);
void wapp_c16_array_extend_capped(C16Array *array, const C16Array *other);
void wapp_c16_array_clear(C16Array *array);
void wapp_c16_array_copy_capped(const C16Array *src, C16Array *dst);
C16Array *wapp_c16_array_append_alloc(const Allocator *allocator, C16Array *array, c16 *item);
C16Array *wapp_c16_array_extend_alloc(const Allocator *allocator, C16Array *array, const C16Array *other);
C16Array *wapp_c16_array_copy_alloc(const Allocator *allocator, const C16Array *src, C16Array *dst);
c16 *_c16_array_pop(C16Array *array);
c32 *wapp_c32_array_get(const C32Array *array, u64 index);
void wapp_c32_array_set(C32Array *array, u64 index, c32 *item);
void wapp_c32_array_append_capped(C32Array *array, c32 *item);
void wapp_c32_array_extend_capped(C32Array *array, const C32Array *other);
void wapp_c32_array_clear(C32Array *array);
void wapp_c32_array_copy_capped(const C32Array *src, C32Array *dst);
C32Array *wapp_c32_array_append_alloc(const Allocator *allocator, C32Array *array, c32 *item);
C32Array *wapp_c32_array_extend_alloc(const Allocator *allocator, C32Array *array, const C32Array *other);
C32Array *wapp_c32_array_copy_alloc(const Allocator *allocator, const C32Array *src, C32Array *dst);
c32 *_c32_array_pop(C32Array *array);
i8 *wapp_i8_array_get(const I8Array *array, u64 index);
void wapp_i8_array_set(I8Array *array, u64 index, i8 *item);
void wapp_i8_array_append_capped(I8Array *array, i8 *item);
void wapp_i8_array_extend_capped(I8Array *array, const I8Array *other);
void wapp_i8_array_clear(I8Array *array);
void wapp_i8_array_copy_capped(const I8Array *src, I8Array *dst);
I8Array *wapp_i8_array_append_alloc(const Allocator *allocator, I8Array *array, i8 *item);
I8Array *wapp_i8_array_extend_alloc(const Allocator *allocator, I8Array *array, const I8Array *other);
I8Array *wapp_i8_array_copy_alloc(const Allocator *allocator, const I8Array *src, I8Array *dst);
i8 *_i8_array_pop(I8Array *array);
i16 *wapp_i16_array_get(const I16Array *array, u64 index);
void wapp_i16_array_set(I16Array *array, u64 index, i16 *item);
void wapp_i16_array_append_capped(I16Array *array, i16 *item);
void wapp_i16_array_extend_capped(I16Array *array, const I16Array *other);
void wapp_i16_array_clear(I16Array *array);
void wapp_i16_array_copy_capped(const I16Array *src, I16Array *dst);
I16Array *wapp_i16_array_append_alloc(const Allocator *allocator, I16Array *array, i16 *item);
I16Array *wapp_i16_array_extend_alloc(const Allocator *allocator, I16Array *array, const I16Array *other);
I16Array *wapp_i16_array_copy_alloc(const Allocator *allocator, const I16Array *src, I16Array *dst);
i16 *_i16_array_pop(I16Array *array);
i32 *wapp_i32_array_get(const I32Array *array, u64 index);
void wapp_i32_array_set(I32Array *array, u64 index, i32 *item);
void wapp_i32_array_append_capped(I32Array *array, i32 *item);
void wapp_i32_array_extend_capped(I32Array *array, const I32Array *other);
void wapp_i32_array_clear(I32Array *array);
void wapp_i32_array_copy_capped(const I32Array *src, I32Array *dst);
I32Array *wapp_i32_array_append_alloc(const Allocator *allocator, I32Array *array, i32 *item);
I32Array *wapp_i32_array_extend_alloc(const Allocator *allocator, I32Array *array, const I32Array *other);
I32Array *wapp_i32_array_copy_alloc(const Allocator *allocator, const I32Array *src, I32Array *dst);
i32 *_i32_array_pop(I32Array *array);
i64 *wapp_i64_array_get(const I64Array *array, u64 index);
void wapp_i64_array_set(I64Array *array, u64 index, i64 *item);
void wapp_i64_array_append_capped(I64Array *array, i64 *item);
void wapp_i64_array_extend_capped(I64Array *array, const I64Array *other);
void wapp_i64_array_clear(I64Array *array);
void wapp_i64_array_copy_capped(const I64Array *src, I64Array *dst);
I64Array *wapp_i64_array_append_alloc(const Allocator *allocator, I64Array *array, i64 *item);
I64Array *wapp_i64_array_extend_alloc(const Allocator *allocator, I64Array *array, const I64Array *other);
I64Array *wapp_i64_array_copy_alloc(const Allocator *allocator, const I64Array *src, I64Array *dst);
i64 *_i64_array_pop(I64Array *array);
u8 *wapp_u8_array_get(const U8Array *array, u64 index);
void wapp_u8_array_set(U8Array *array, u64 index, u8 *item);
void wapp_u8_array_append_capped(U8Array *array, u8 *item);
void wapp_u8_array_extend_capped(U8Array *array, const U8Array *other);
void wapp_u8_array_clear(U8Array *array);
void wapp_u8_array_copy_capped(const U8Array *src, U8Array *dst);
U8Array *wapp_u8_array_append_alloc(const Allocator *allocator, U8Array *array, u8 *item);
U8Array *wapp_u8_array_extend_alloc(const Allocator *allocator, U8Array *array, const U8Array *other);
U8Array *wapp_u8_array_copy_alloc(const Allocator *allocator, const U8Array *src, U8Array *dst);
u8 *_u8_array_pop(U8Array *array);
u16 *wapp_u16_array_get(const U16Array *array, u64 index);
void wapp_u16_array_set(U16Array *array, u64 index, u16 *item);
void wapp_u16_array_append_capped(U16Array *array, u16 *item);
void wapp_u16_array_extend_capped(U16Array *array, const U16Array *other);
void wapp_u16_array_clear(U16Array *array);
void wapp_u16_array_copy_capped(const U16Array *src, U16Array *dst);
U16Array *wapp_u16_array_append_alloc(const Allocator *allocator, U16Array *array, u16 *item);
U16Array *wapp_u16_array_extend_alloc(const Allocator *allocator, U16Array *array, const U16Array *other);
U16Array *wapp_u16_array_copy_alloc(const Allocator *allocator, const U16Array *src, U16Array *dst);
u16 *_u16_array_pop(U16Array *array);
u32 *wapp_u32_array_get(const U32Array *array, u64 index);
void wapp_u32_array_set(U32Array *array, u64 index, u32 *item);
void wapp_u32_array_append_capped(U32Array *array, u32 *item);
void wapp_u32_array_extend_capped(U32Array *array, const U32Array *other);
void wapp_u32_array_clear(U32Array *array);
void wapp_u32_array_copy_capped(const U32Array *src, U32Array *dst);
U32Array *wapp_u32_array_append_alloc(const Allocator *allocator, U32Array *array, u32 *item);
U32Array *wapp_u32_array_extend_alloc(const Allocator *allocator, U32Array *array, const U32Array *other);
U32Array *wapp_u32_array_copy_alloc(const Allocator *allocator, const U32Array *src, U32Array *dst);
u32 *_u32_array_pop(U32Array *array);
u64 *wapp_u64_array_get(const U64Array *array, u64 index);
void wapp_u64_array_set(U64Array *array, u64 index, u64 *item);
void wapp_u64_array_append_capped(U64Array *array, u64 *item);
void wapp_u64_array_extend_capped(U64Array *array, const U64Array *other);
void wapp_u64_array_clear(U64Array *array);
void wapp_u64_array_copy_capped(const U64Array *src, U64Array *dst);
U64Array *wapp_u64_array_append_alloc(const Allocator *allocator, U64Array *array, u64 *item);
U64Array *wapp_u64_array_extend_alloc(const Allocator *allocator, U64Array *array, const U64Array *other);
U64Array *wapp_u64_array_copy_alloc(const Allocator *allocator, const U64Array *src, U64Array *dst);
u64 *_u64_array_pop(U64Array *array);
f32 *wapp_f32_array_get(const F32Array *array, u64 index);
void wapp_f32_array_set(F32Array *array, u64 index, f32 *item);
void wapp_f32_array_append_capped(F32Array *array, f32 *item);
void wapp_f32_array_extend_capped(F32Array *array, const F32Array *other);
void wapp_f32_array_clear(F32Array *array);
void wapp_f32_array_copy_capped(const F32Array *src, F32Array *dst);
F32Array *wapp_f32_array_append_alloc(const Allocator *allocator, F32Array *array, f32 *item);
F32Array *wapp_f32_array_extend_alloc(const Allocator *allocator, F32Array *array, const F32Array *other);
F32Array *wapp_f32_array_copy_alloc(const Allocator *allocator, const F32Array *src, F32Array *dst);
f32 *_f32_array_pop(F32Array *array);
f64 *wapp_f64_array_get(const F64Array *array, u64 index);
void wapp_f64_array_set(F64Array *array, u64 index, f64 *item);
void wapp_f64_array_append_capped(F64Array *array, f64 *item);
void wapp_f64_array_extend_capped(F64Array *array, const F64Array *other);
void wapp_f64_array_clear(F64Array *array);
void wapp_f64_array_copy_capped(const F64Array *src, F64Array *dst);
F64Array *wapp_f64_array_append_alloc(const Allocator *allocator, F64Array *array, f64 *item);
F64Array *wapp_f64_array_extend_alloc(const Allocator *allocator, F64Array *array, const F64Array *other);
F64Array *wapp_f64_array_copy_alloc(const Allocator *allocator, const F64Array *src, F64Array *dst);
f64 *_f64_array_pop(F64Array *array);
f128 *wapp_f128_array_get(const F128Array *array, u64 index);
void wapp_f128_array_set(F128Array *array, u64 index, f128 *item);
void wapp_f128_array_append_capped(F128Array *array, f128 *item);
void wapp_f128_array_extend_capped(F128Array *array, const F128Array *other);
void wapp_f128_array_clear(F128Array *array);
void wapp_f128_array_copy_capped(const F128Array *src, F128Array *dst);
F128Array *wapp_f128_array_append_alloc(const Allocator *allocator, F128Array *array, f128 *item);
F128Array *wapp_f128_array_extend_alloc(const Allocator *allocator, F128Array *array, const F128Array *other);
F128Array *wapp_f128_array_copy_alloc(const Allocator *allocator, const F128Array *src, F128Array *dst);
f128 *_f128_array_pop(F128Array *array);
iptr *wapp_iptr_array_get(const IptrArray *array, u64 index);
void wapp_iptr_array_set(IptrArray *array, u64 index, iptr *item);
void wapp_iptr_array_append_capped(IptrArray *array, iptr *item);
void wapp_iptr_array_extend_capped(IptrArray *array, const IptrArray *other);
void wapp_iptr_array_clear(IptrArray *array);
void wapp_iptr_array_copy_capped(const IptrArray *src, IptrArray *dst);
IptrArray *wapp_iptr_array_append_alloc(const Allocator *allocator, IptrArray *array, iptr *item);
IptrArray *wapp_iptr_array_extend_alloc(const Allocator *allocator, IptrArray *array, const IptrArray *other);
IptrArray *wapp_iptr_array_copy_alloc(const Allocator *allocator, const IptrArray *src, IptrArray *dst);
iptr *_iptr_array_pop(IptrArray *array);
uptr *wapp_uptr_array_get(const UptrArray *array, u64 index);
void wapp_uptr_array_set(UptrArray *array, u64 index, uptr *item);
void wapp_uptr_array_append_capped(UptrArray *array, uptr *item);
void wapp_uptr_array_extend_capped(UptrArray *array, const UptrArray *other);
void wapp_uptr_array_clear(UptrArray *array);
void wapp_uptr_array_copy_capped(const UptrArray *src, UptrArray *dst);
UptrArray *wapp_uptr_array_append_alloc(const Allocator *allocator, UptrArray *array, uptr *item);
UptrArray *wapp_uptr_array_extend_alloc(const Allocator *allocator, UptrArray *array, const UptrArray *other);
UptrArray *wapp_uptr_array_copy_alloc(const Allocator *allocator, const UptrArray *src, UptrArray *dst);
uptr *_uptr_array_pop(UptrArray *array);
GenericArray *_array_alloc_capacity(const Allocator *allocator, u64 capacity, u64 item_size);
#ifdef WAPP_PLATFORM_CPP
END_C_LINKAGE
#endif // !WAPP_PLATFORM_CPP
#endif // !ARRAY_H

File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More