Compare commits

..
458 Commits
Author SHA1 Message Date
Krzosa Karol 2d79790d83 Remove init.project.lua 2025-12-14 12:04:03 +01:00
Krzosa Karol a351d2eb41 restructuring 2025-12-14 10:32:42 +01:00
Krzosa Karol 0424ca62f2 Fix eval error 2025-12-14 08:18:17 +01:00
Krzosa Karol 83d5ddff9d Fix lua bug 2025-12-09 08:31:31 +01:00
Krzosa Karol b600361278 Refactor Command_s 2025-12-08 09:23:07 +01:00
Krzosa Karol 9d29a1c187 Refactoring Command_s, NextWindowID 2025-12-08 09:16:31 +01:00
Krzosa Karol 20207e6040 jump history 2025-12-08 08:37:52 +01:00
Krzosa Karol ef6a7be285 Command bar, undo merge time 2025-12-07 13:57:51 +01:00
Krzosa Karol df84d1605d Bring back status bar with new design, fixing bugs 2025-12-07 10:40:30 +01:00
Krzosa Karol 88a5adaa0a Big refactor new layout 2025-12-06 19:12:06 +01:00
Krzosa Karol e6e1ae0223 Switch to using arrays for Windows, Views, Buffers list, try to make DeleteWindow work 2025-12-05 08:58:46 +01:00
Krzosa Karol 05f0197d50 Fixing tests, Fixed buffer dealloc bug, fixed clipboard bug 2025-12-03 10:38:27 +01:00
Krzosa Karol e34c2b0cef Allow multiple fonts 2025-12-01 09:05:06 +01:00
Krzosa Karol c2f4686bc4 BlockArena, a bit of allocator rework 2025-11-30 19:54:46 +01:00
Krzosa Karol c19c60fe22 Tracking allocator, buffer tests 2025-11-28 09:59:09 +01:00
Krzosa Karol d72485a137 Format string refactor 2025-11-27 23:13:28 +01:00
Krzosa Karol e9e8751981 Refactor windows and web compiling 2025-11-27 22:45:10 +01:00
Krzosa Karol 781c2dc53c Start refactor, restructure basic 2025-11-27 09:00:10 +01:00
Krzosa Karol 38b9b7df10 luaunity.c 2025-11-26 10:21:18 +01:00
Krzosa Karol a2cf5f2284 Misc 2025-11-26 09:49:39 +01:00
Krzosa Karol 38a20bd97a Fix rendering of whitespace, continue wasm porting 2025-11-25 09:47:03 +01:00
Krzosa Karol fcefe9f827 Porting to WASM 2025-11-24 22:59:39 +01:00
Krzosa Karol 56cdb9557d Porting to WASM 2025-11-24 22:59:11 +01:00
krzosa 166f06d1fb Trace buffer vs Debug buffer, print Buffer info, Add SaveAll 2025-08-21 09:16:31 +02:00
krzosa 24533dfe7f Print and print in lua 2025-08-21 08:53:31 +02:00
krzosa 8408f400c8 Cleanup debug reporting situation 2025-08-21 08:46:58 +02:00
krzosa 48574d634c Small fixes 2025-08-20 08:46:55 +02:00
krzosa ad3e58d455 Fix cursor stutter 2025-08-19 09:18:40 +02:00
krzosa 0dc020c429 Add missing config vars 2025-08-19 08:59:34 +02:00
krzosa 2e70d33364 Simplify development config management, reintroduce metaprogram 2025-08-19 08:59:23 +02:00
krzosa b0f314c9e3 release build, fix process kill, baked in font, fix goto on build 2025-08-17 19:05:37 +02:00
krzosa 1276c565da Fix process polling exit code 2025-08-11 18:27:02 +02:00
krzosa 955d92bcc7 Small fixes 2025-08-11 17:57:48 +02:00
krzosa 4e330de1d5 Fix config not loading 2025-08-11 16:03:20 +02:00
krzosa 77b337aed8 Fix Ctrl Period to navigate folders 2025-08-11 15:53:11 +02:00
krzosa b6ef63e817 Fix browser, fix font, GetExeDir 2025-08-11 13:41:28 +02:00
krzosa e6414908b7 Small unix improvements 2025-08-11 11:17:22 +02:00
krzosa 55eecf3177 Bring back linked list 2025-08-11 09:10:31 +02:00
krzosa 12ac285456 Remove build system and those files 2025-08-11 08:42:11 +02:00
krzosa a911707613 Fix working dir when spawning process 2025-08-11 08:41:29 +02:00
krzosa 3e7f09f33f Improve fuzzy search 2025-08-10 23:04:26 +02:00
krzosa 4b55faa41e Porting to linux 2025-08-10 18:44:10 +02:00
Karol Krzosa 720fdd9f34 Success running on linux 2025-05-17 08:22:27 +02:00
Krzosa Karol 76d52d9e1c Testing flag 2025-05-15 08:34:50 +02:00
Krzosa Karol c74c256968 Test stuff 2025-05-15 08:33:18 +02:00
Krzosa Karol aa5b51b88c Small Command_Open fixes 2025-05-13 14:20:41 +02:00
Krzosa Karol cf72182d56 Setting up windows using project lua file 2025-05-13 12:42:11 +02:00
Krzosa Karol 2e9147c47d Fix Command_Open jumping to beginning every time 2025-05-13 09:11:42 +02:00
Krzosa Karol f7f2aafc56 FKey function, fix goto build, GetLine, remedybg 2025-05-13 09:04:52 +02:00
Krzosa Karol 7eec390752 Fix dirty buffer after doing anything in title bar, OnCommand in lua stops c code, FKeys 2025-05-12 22:44:45 +02:00
Krzosa Karol 0c7a424f5e ListCode with || 2025-05-12 17:40:19 +02:00
Krzosa Karol 6aaff7573a ListCode improvements 2025-05-12 17:20:23 +02:00
Krzosa Karol 70858fdec5 ListCode, fix unique buffer opening an existing file on disk 2025-05-12 17:12:37 +02:00
Krzosa Karol a94b914e06 WorkDir concept 2025-05-12 16:35:06 +02:00
Krzosa Karol fd842a1f70 Fix switching windows 2025-05-12 09:25:02 +02:00
Krzosa Karol 872c46c43d Search bar anchor 2025-05-12 08:53:42 +02:00
Krzosa Karol a79f11d137 EncloseSpace, EncloseScope changes 2025-05-11 16:24:06 +02:00
Krzosa Karol 3b48954bc1 EncloseLine, add $ and @ as part of load word 2025-05-11 15:43:32 +02:00
Krzosa Karol 9884ba7dab Exec command as meta to Open 2025-05-11 15:25:07 +02:00
Krzosa Karol 78ea184868 Drawing split, fix split left right behaviour 2025-05-10 11:37:03 +02:00
Krzosa Karol a2b081ec15 Setting window sizes, NewDir 2025-05-10 11:19:09 +02:00
Krzosa Karol c139c44503 "New" command better, GetUniqueBufferName no longer big numbers 2025-05-10 08:12:49 +02:00
Krzosa Karol 8370a2ae67 Lua.OnSave, GetViewForFixingWhenBufferCommand 2025-05-09 20:25:05 +02:00
Krzosa Karol 1590f12b43 Shift selects on last/first line 2025-05-09 10:56:17 +02:00
Krzosa Karol 3180625a41 Open improvements 2025-05-09 10:50:40 +02:00
Krzosa Karol d2ca655178 Add metadata to Command_Open and move the logic that denies the NextGotoBuild to lua 2025-05-09 09:17:45 +02:00
Krzosa Karol c57eedce49 Reorganizing a bit 2025-05-09 08:40:29 +02:00
Krzosa Karol bc9be4927b white search bar 2025-05-08 22:56:47 +02:00
Krzosa Karol a1282af0b5 Change console behaviour 2025-05-08 22:53:56 +02:00
Krzosa Karol 46c109dce4 Fix garbage collect bug, ReplaceWithoutMovingCarets takes buffer now, Reopen buffer happens automatically when not dirty 2025-05-08 22:42:04 +02:00
Krzosa Karol abb2cfb1c4 Fuzzy search, working dir as nullbuffer dir 2025-05-06 16:41:43 +02:00
Krzosa Karol 9ddfed92ff title bar renaming 2025-05-05 21:21:31 +02:00
Krzosa Karol c4419490b6 console goto build results 2025-05-05 20:53:25 +02:00
Krzosa Karol 20422d9023 Bring back GC and new files for commands 2025-05-05 16:49:28 +02:00
Krzosa Karol 2c29df0171 Save state window buffers? 2025-05-05 15:51:21 +02:00
Krzosa Karol 8fc1081cef Go to end, start 2025-05-05 10:18:33 +02:00
Krzosa Karol 556b05cb78 New splitting 2025-05-05 08:49:22 +02:00
Krzosa Karol 4a1554ce28 The new window splits 2025-05-05 08:37:41 +02:00
Krzosa Karol 542b0f0a0a Text editor object management change 2025-05-04 09:57:34 +02:00
Krzosa Karol 101e844ac5 window pos 2025-05-04 09:16:34 +02:00
Krzosa Karol dec70c10e7 Color of title bar when active and window size 2025-05-03 21:16:16 +02:00
Krzosa Karol 7a5d949a12 console size, ListCommands, Indent on bracket 2025-05-03 18:45:05 +02:00
krzosa 93c1ba606a Console update 2025-05-02 22:20:09 +02:00
krzosa 4871494c50 Eval on click, fix reopen buffers, detecting change 2025-05-02 12:53:13 +02:00
krzosa d7908bee54 Improving basic commands 2025-05-02 12:02:13 +02:00
krzosa fd8a319b18 init.lua 2025-05-01 15:06:48 +02:00
krzosa d1d9b39200 save 2025-05-01 15:06:43 +02:00
krzosa 6374f3cd1a Fix mouse, fix allocator in file iter, GetCFiles 2025-05-01 08:26:55 +02:00
krzosa e652d5b0e2 lua api improvements 2025-04-30 22:34:00 +02:00
krzosa dc3861adfe Lua_GetProjectPath, SDLK_Period 2025-04-30 21:38:21 +02:00
krzosa a00f8acd9a Get info for lua commands on buffer, ctrl shift Q thing, packaging 2025-04-30 09:34:54 +02:00
krzosa 46dcd1cc4e unspecial directory buffer 2025-04-29 22:41:44 +02:00
krzosa a5d99ffb9a search bar 2025-04-29 22:25:04 +02:00
krzosa daa0d2d4c4 VCVarsall improvements, reload entire config every time 2025-04-29 18:02:25 +02:00
krzosa 92139cf799 ALOT OF CHANGES 2025-04-29 16:22:26 +02:00
Krzosa Karol ed9ec06eee Reporting errors, set active to console 2024-12-02 08:35:15 +01:00
Krzosa Karol f1e674ca37 Return to project, refactoring 2024-11-30 11:08:08 +01:00
Krzosa Karol 35cc5ae48d Remove exec word, insert titlebar command, error reporting in titlebar, some lua commands 2024-09-28 07:40:00 +02:00
Krzosa Karol 9ea1e254e0 Lua_SetProjectFile 2024-08-17 07:19:43 +02:00
Krzosa Karol 1c0063e834 String16, commands, Lua_New, layout next, build and encodings 2024-08-16 15:40:18 +02:00
Krzosa Karol afd4e1d21c Misc 2024-08-16 07:23:50 +02:00
Krzosa Karol 2065c9ded7 String16 routines 2024-08-15 15:32:51 +02:00
Krzosa Karol bafe0af407 Stop using WindowSize and actually make use of event window size, provide default 2024-08-15 15:09:14 +02:00
Krzosa Karol d0bc7bdc4a Lua_ToggleFullscreen .lua_project 2024-08-15 14:57:20 +02:00
Krzosa Karol fbe34b2d40 Fix autoenclose and override F1 in config 2024-08-15 12:44:27 +02:00
Krzosa Karol e49838b974 Lua_Error, ClangFormatOnSave 2024-08-15 12:28:39 +02:00
Krzosa Karol 7ed46b9724 Report errors idea using titlebar 2024-08-15 11:54:32 +02:00
Krzosa Karol 41a05fb08c Add coroutines on C++ side, Implement the test in C++ 2024-08-15 11:28:27 +02:00
Krzosa Karol 8f09e25710 Move test to data folder 2024-08-15 10:04:46 +02:00
Krzosa Karol a28c172ac1 Add the test projec 2024-08-15 10:03:50 +02:00
Krzosa Karol b5772fa52c OnCommand and OnInit 2024-08-15 10:03:44 +02:00
Krzosa Karol d4ac1dd817 Describe event using macros 2024-08-15 08:50:04 +02:00
Krzosa Karol 5e51e2fbad Auto enclose 2024-08-15 08:22:56 +02:00
Krzosa Karol a3e87b2508 Fix ApplyRules misfires on weird paths, gotos don't include gc buffers 2024-08-15 07:27:05 +02:00
Krzosa Karol eeb6caa58d Improve ApplyRules 2024-08-14 17:22:33 +02:00
Krzosa Karol 212392386c Testing setup using project files 2024-08-14 16:03:29 +02:00
Krzosa Karol a84a7073dc Lua_Play now works in coroutines 2024-08-14 15:08:27 +02:00
Krzosa Karol 8cd754c923 Lua project config 2024-08-14 13:05:38 +02:00
Krzosa Karol 225d1ffc06 Implement coroutine handling 2024-08-14 12:41:09 +02:00
Krzosa Karol f38c20b975 Lua_Play events 2024-08-14 12:17:50 +02:00
Krzosa Karol a0315f161c Serialize and playback events 2024-08-14 09:55:54 +02:00
Krzosa Karol cac092a344 Serializing and de serializing events 2024-08-14 08:40:18 +02:00
Krzosa Karol 5fd790bd54 Event move to separate file 2024-08-14 07:43:39 +02:00
Krzosa Karol b60f846209 Improve reopen buffer 2024-08-14 07:42:11 +02:00
Krzosa Karol 2b4a43ddc1 Reopen changed files 2024-08-14 07:35:12 +02:00
Krzosa Karol f125a38c50 Improve GC 2024-08-13 16:02:22 +02:00
Krzosa Karol 40cb8582fd Begin garbage collector 2024-08-13 13:51:36 +02:00
Krzosa Karol 7db1fc7bd6 Ls and some improvements 2024-08-13 12:27:45 +02:00
Krzosa Karol 50e642483d Refactor 2024-08-13 12:11:16 +02:00
Krzosa Karol 915679b87b Refactor WindowCommands 2024-08-13 11:43:56 +02:00
Krzosa Karol 2ada434925 CtrlF Search 2024-08-13 10:52:41 +02:00
Krzosa Karol 26c1180fad Refactor 2024-08-13 10:43:47 +02:00
Krzosa Karol 9cac98d961 Refactor references to pointers 2024-08-13 10:38:57 +02:00
Krzosa Karol c0877bfe1d Refactor 2024-08-13 10:35:48 +02:00
Krzosa Karol 5ce418995f Some more refactoring 2024-08-13 09:55:28 +02:00
Krzosa Karol 7b21cba834 Refactoring Add BSet 2024-08-13 09:49:34 +02:00
Krzosa Karol b3e95a705f Remove titlebar modification, small refactor 2024-08-13 09:09:48 +02:00
Krzosa Karol da80e2c731 F3, ShiftF3 search, works on main window 2024-08-12 17:31:25 +02:00
Krzosa Karol fcabf96347 Improve process logic 2024-08-12 17:01:33 +02:00
Krzosa Karol 2b48f30cfe Clang format, mouse rebind 2024-08-12 13:45:58 +02:00
Krzosa Karol 3251df6068 ExecAndWait 2024-08-12 08:12:30 +02:00
Krzosa Karol d6dd7c9eab Validate buffer name uniqueness constraint, update todo 2024-08-12 07:28:38 +02:00
Krzosa Karol 3fd728543c Ctrl + P to list buffers 2024-08-10 10:16:55 +02:00
Krzosa Karol b4bc061b76 Remove array alloc, not a good idea 2024-08-10 09:44:44 +02:00
Krzosa Karol f10212f4a0 Move off from object arrays to id arrays 2024-08-10 09:43:23 +02:00
Krzosa Karol 08a385b050 Simplify active windows 2024-08-10 09:08:35 +02:00
Krzosa Karol d5f903eaa2 Reword ListBuffers 2024-08-10 08:46:40 +02:00
Krzosa Karol 26b0ba4828 Remove console designate null view/buffer as console 2024-08-10 08:41:04 +02:00
Krzosa Karol 90aaa375d0 Remove command window 2024-08-10 08:31:14 +02:00
Krzosa Karol a12a10ee0b Generate lua function table 2024-08-10 08:17:37 +02:00
Krzosa Karol 97b1cf9e73 Fix infinite loop in GotoNextInList 2024-08-10 07:32:39 +02:00
Krzosa Karol 3aa4806515 Fix non-edit doing caret adjustment 2024-08-10 07:25:44 +02:00
Krzosa Karol 4e1ae87a8e Del popup window 2024-08-10 07:06:20 +02:00
Krzosa Karol 6bc8c549fc GoToNextInList scans multiple lines, EncloseExecWord looks for an anchor, Add Ctrl Period chop path open 2024-08-10 07:04:25 +02:00
Krzosa Karol 2137a0990e Hack in the goto next in list 2024-08-09 17:45:45 +02:00
Krzosa Karol 7f8b22ff43 Search back 2024-08-09 17:28:50 +02:00
Krzosa Karol d1e645b17e LuaSearch 2024-08-09 16:56:37 +02:00
Krzosa Karol 8bf32a557b Debug memes 2024-08-09 16:33:23 +02:00
Krzosa Karol 93cfe71c21 Remove search window 2024-08-09 16:28:50 +02:00
Krzosa Karol 65ef0b1b0f Lua OnUpdate 2024-08-09 16:19:00 +02:00
Krzosa Karol d98086d869 Improved git pathing 2024-08-09 15:01:15 +02:00
Krzosa Karol 00c1f405c6 GotoForward 2024-08-09 10:36:33 +02:00
Krzosa Karol 19546eea4d Improve ctrl movement, fix delete indent bug 2024-08-09 10:11:19 +02:00
Krzosa Karol 6d9792b1a6 Stop using stack in win32 2024-08-09 09:53:40 +02:00
Krzosa Karol 47ec2b55c7 LuaAppendCmd 2024-08-09 09:46:16 +02:00
Krzosa Karol 68ff6dc2b5 Add lua interrupt on F9 2024-08-09 09:39:40 +02:00
Krzosa Karol ad847a3eaa Save line to clipboard on right click 2024-08-09 09:03:11 +02:00
Krzosa Karol 4564e7bbc2 Even never mouse design 2024-08-09 09:00:04 +02:00
Krzosa Karol 3fb0c131f1 Rework mouse bindings 2024-08-09 08:08:24 +02:00
Krzosa Karol 91ba202562 Simplify mouse left 2024-08-09 07:50:03 +02:00
Krzosa Karol 93530bd089 Convert to LF during copy paste 2024-08-09 07:42:31 +02:00
Krzosa Karol a7dc343fd6 Exec word now tries to extend the lua function call syntax 2024-08-09 07:24:29 +02:00
Krzosa Karol 4c179e3965 Select title bar 2024-08-08 17:52:27 +02:00
Krzosa Karol a5756ab2f5 Improve console behaviour 2024-08-08 17:42:03 +02:00
Krzosa Karol 95b7ded031 Adjust carets in title bar, Command_ReplaceEx, adjust look of underline 2024-08-08 17:36:18 +02:00
Krzosa Karol a004976c6b Toying with windows paths, ExecInNewBuffer, c'', Fix caret loss in title bar 2024-08-08 16:33:19 +02:00
Krzosa Karol eecff81093 Fix crash in LuaPrint 2024-08-08 12:04:55 +02:00
Krzosa Karol d47482bc04 String interning, forgot file 2024-08-08 11:50:30 +02:00
Krzosa Karol 4434cd5764 String interning 2024-08-08 11:50:23 +02:00
Krzosa Karol 3488c71155 Syntax for executing shell commands 2024-08-08 11:07:15 +02:00
Krzosa Karol ad2efab7c8 Add icon and drop file event 2024-08-08 10:49:13 +02:00
Krzosa Karol 28a9656db1 Process error handling and process killing 2024-08-08 08:56:01 +02:00
Krzosa Karol 58db05fcb3 Match git commit properly 2024-08-08 08:14:08 +02:00
Krzosa Karol bfff188726 Opening git commit works properly now 2024-08-08 08:01:49 +02:00
Krzosa Karol 080669b5e9 Opening new buffer which is git show commit command 2024-08-08 07:24:13 +02:00
Krzosa Karol 161a9e3965 Command_Append 2024-08-08 07:02:05 +02:00
Krzosa Karol bb44eab406 Fixing array resize bugs 2024-08-08 06:47:29 +02:00
Krzosa Karol b3b50715b4 Add dynamic array debug - resize on every item added, fix window bug 2024-08-08 06:35:37 +02:00
Krzosa Karol 2565cefe70 Equality operators for ids 2024-08-08 06:22:18 +02:00
Krzosa Karol 8e73057cfb Move selected windows to ids instead of pointers 2024-08-08 06:18:45 +02:00
Krzosa Karol 74ab76344b Remove WaitForExit for now 2024-08-08 06:08:37 +02:00
Krzosa Karol 38afbe8816 Delete raylib_utils, update todo 2024-08-08 06:07:58 +02:00
Krzosa Karol 6d66986b5b Small refactor 2024-08-07 07:56:21 +02:00
Krzosa Karol 327f352872 Create process, poll and send output to console buffer 2024-08-07 07:51:50 +02:00
Krzosa Karol 7b8b8c751d Process polling api 2024-08-07 07:31:37 +02:00
Krzosa Karol fe20d05e13 Add friendly remainders, better console experience 2024-08-06 18:36:58 +02:00
Krzosa Karol b036e48cee Improve edit api 2024-08-06 18:21:52 +02:00
Krzosa Karol 4aaae7773d Update notes 2024-08-06 18:15:37 +02:00
Krzosa Karol 1145a13987 Convert line endings command 2024-08-06 07:55:52 +02:00
Krzosa Karol f8c9e8fd3e Open and navigate directories 2024-08-06 07:49:33 +02:00
Krzosa Karol f419ffd1ca Add dirs to special buffers 2024-08-06 07:35:48 +02:00
Krzosa Karol fa99475912 Command_MoveLine 2024-08-06 07:25:33 +02:00
Krzosa Karol 6e61816e1c Execute and load selection 2024-08-06 06:50:36 +02:00
Krzosa Karol b552f73ac9 Fix underline bug and draw selection underline 2024-08-06 06:44:45 +02:00
Krzosa Karol f0df0b69f0 Refactor cursor underlining 2024-08-06 06:38:21 +02:00
Krzosa Karol f7100ae8ee Misc 2024-08-05 21:03:19 +02:00
Krzosa Karol e514c29de4 EncloseFullLine and enclose scopes on multiple click 2024-08-05 15:49:27 +02:00
Krzosa Karol d81c403a5d Click multiple times to enclose load word or exec word 2024-08-05 15:31:38 +02:00
Krzosa Karol 956f2319b5 Ctrl + G 2024-08-05 13:17:54 +02:00
Krzosa Karol bb2c9a2f32 Misc 2024-08-05 12:45:51 +02:00
Krzosa Karol 3928e2eb96 Fallback font, configure font in lua 2024-08-05 12:39:10 +02:00
Krzosa Karol c4bc48bba1 Backup font based on imgui stuff 2024-08-05 11:50:43 +02:00
Krzosa Karol 8eb58e7dd8 Add debug references to ids 2024-08-05 11:26:55 +02:00
Krzosa Karol e4af56e3eb Remove non-implemented feature 2024-08-05 11:11:15 +02:00
Krzosa Karol 331f75c7ab Address sanitizer 2024-08-05 10:44:43 +02:00
Krzosa Karol 55465ad6de Fix memory issues because of pointer to item in dynamic array, add clang-cl, add address sanitizer stuff 2024-08-05 10:44:00 +02:00
Krzosa Karol 10f0d7dca2 Add titlebar windows everywhere and make them selectable even in disappearing windows 2024-08-05 08:37:46 +02:00
Krzosa Karol c9aabdec68 Experimenting with execution 2024-08-05 08:25:33 +02:00
Krzosa Karol da1def101b Highlight exec word 2024-08-05 07:29:02 +02:00
Krzosa Karol 4d22995ea3 Fix line number matching bug 2024-08-05 07:19:38 +02:00
Krzosa Karol d3b89d22fb Add some external libs to source tree 2024-08-05 07:13:04 +02:00
Krzosa Karol 9215205aba Load lua functions from an array 2024-08-05 07:12:52 +02:00
Krzosa Karol 7fc071154f Small Open improvements 2024-08-04 14:49:02 +02:00
Krzosa Karol e3c1bcb56e Fix wrong selection after cut 2024-08-04 14:25:07 +02:00
Krzosa Karol 7e35e0cbed Misc 2024-08-04 14:22:42 +02:00
Krzosa Karol d59a8d9c8b Mouse rewrite 2024-08-04 14:14:15 +02:00
Krzosa Karol 605f3aa68d Mouse rewrite 2024-08-04 14:08:46 +02:00
Krzosa Karol c6a415f642 Mouse rewrite 2024-08-04 14:00:42 +02:00
Krzosa Karol edff7a4267 Mouse rewrite 2024-08-04 13:37:05 +02:00
Krzosa Karol 48bbef0b10 Before mouse rewrite 2024-08-04 11:00:25 +02:00
Krzosa Karol b267000394 Delete indent in multiples of indent size 2024-08-04 10:40:03 +02:00
Krzosa Karol c3bd96d5d6 Move back mouse stuff to window 2024-08-04 10:19:43 +02:00
Krzosa Karol 28dbac4a35 Ctrl + Q Alt + Q 2024-08-04 10:15:09 +02:00
Krzosa Karol 22dc4be100 Go to last bread crumb but mouse is bugging 2024-08-04 10:07:36 +02:00
Krzosa Karol ffb38664b8 Fix GetWordEnd type of functions to make sure range.max is past the last index even on buffer end 2024-08-04 08:54:08 +02:00
Krzosa Karol 3f16888fe0 Home + left stops at indent 2024-08-04 08:34:09 +02:00
Krzosa Karol 2b5f441e92 Indented new line 2024-08-04 08:28:42 +02:00
Krzosa Karol e761761108 Improve load 2024-08-04 08:09:07 +02:00
Krzosa Karol 324e5e1ea1 Fixing ActiveWindow switching, actual happens switch after event is handled 2024-08-04 08:01:25 +02:00
Krzosa Karol cc04fec1de Command window opens files and move fuzzy search to view 2024-08-04 07:55:49 +02:00
Krzosa Karol b68b80f317 Movement with new semantics fully completed 2024-08-04 07:35:55 +02:00
Krzosa Karol cfad821e8e Command_Move down 2024-08-04 07:10:36 +02:00
Krzosa Karol 815e3c9670 Work on Open 2024-08-03 19:11:36 +02:00
Krzosa Karol 0c4dc62170 EncloseLoadWord 2024-08-03 15:50:55 +02:00
Krzosa Karol 7655ece178 Implement a lot of position moving functions 2024-08-03 12:58:53 +02:00
Krzosa Karol 22899c2523 Add kill selected lines 2024-08-03 10:47:12 +02:00
Krzosa Karol 7f85f8348e Trim whitespace on save and skip lines with cursor 2024-08-03 10:30:35 +02:00
Krzosa Karol ee863e3b09 MoveOnWhitespaceBoundaryVertical 2024-08-03 10:14:22 +02:00
Krzosa Karol 1ebe8d9929 buffer_ops.cpp unify MoveOnWhitespaceBoundary 2024-08-03 10:05:43 +02:00
Krzosa Karol 6c975b98a1 Underline enclose word of main cursor and fix Enclose word 2024-08-03 08:45:49 +02:00
Krzosa Karol e4a248bb60 Fix wrong cursor on line numbers and scroll 2024-08-03 08:27:42 +02:00
Krzosa Karol d382735b80 Fix mouse in full-screen scrolling on edge of monitor 2024-08-03 08:21:25 +02:00
Krzosa Karol a42a4e435d Fixed mouse 2024-08-03 08:05:08 +02:00
Krzosa Karol f79fce83ca Update todo, add indent size option 2024-08-03 07:26:37 +02:00
Krzosa Karol 4c7f6340d6 Add Trim trailing whitespace 2024-08-02 21:52:44 +02:00
Krzosa Karol f3059ec8ea Shift Mouse Press works now 2024-08-02 21:38:12 +02:00
Krzosa Karol 4f12887a91 Fix offseting carets after edit without killing selection, add dedent 2024-08-02 21:30:12 +02:00
Krzosa Karol 03b6b80568 Indent selected lines 2024-08-02 21:16:46 +02:00
Krzosa Karol cbf1cb8c4a Redesign lua reloading and other generation stuff 2024-08-02 20:42:02 +02:00
Krzosa Karol 7fc8e6e8bb Search now has title bar, title bars now have history 2024-08-02 14:51:40 +02:00
Krzosa Karol 48dc808dcb Improve command window 2024-08-02 12:49:03 +02:00
Krzosa Karol 95dc31be91 Fix focus on console buffer and console buffer not drawing 2024-08-02 12:16:08 +02:00
Krzosa Karol 55223b763a Fixing small bugs and add console window 2024-08-02 12:03:51 +02:00
Krzosa Karol cff301499f SDL passthrough hint and default size 2024-08-02 07:51:47 +02:00
Krzosa Karol 4cdb8a986a Basic splitting, column concept 2024-08-02 07:43:33 +02:00
Krzosa Karol 0ae0c03775 Fix a bug 2024-08-01 16:47:44 +02:00
Krzosa Karol d6378922cf Remove dependence on FrameID 2024-08-01 16:44:58 +02:00
Krzosa Karol 6ce5fd59a3 New event loop setup 2024-08-01 16:28:10 +02:00
Krzosa Karol b93cdd8f4c Title bar adjust looks 2024-08-01 08:20:58 +02:00
Krzosa Karol cadf7742ab Add title bar windows 2024-08-01 08:07:13 +02:00
Krzosa Karol 5f8021c570 Improve font rendering 2024-08-01 08:06:57 +02:00
Krzosa Karol 1b0d0520bc Append to end of console 2024-07-31 07:37:56 +02:00
Krzosa Karol be99b0aabb Editing infobar applies changes to buffer 2024-07-31 07:32:42 +02:00
Krzosa Karol 2ab1917b73 Update todo 2024-07-31 06:39:33 +02:00
Krzosa Karol 111781dc71 SetActiveView 2024-07-30 07:31:51 +02:00
Krzosa Karol 7df09a9ebd Implement circular array 2024-07-30 07:27:05 +02:00
Krzosa Karol 7b13dff29c Remove window view children 2024-07-30 06:56:54 +02:00
Krzosa Karol c48abbf5c9 Don't draw carets when inactive, todo update 2024-07-28 21:43:33 +02:00
Krzosa Karol 12b459507a Fix memory corruption 2024-07-28 20:49:40 +02:00
Krzosa Karol 77a6cc5e53 Improve alignment of infobar, set buffer name in window title 2024-07-28 15:16:12 +02:00
Krzosa Karol 978d2d603a Add xwheel 2024-07-28 14:49:46 +02:00
Krzosa Karol 01a0d5f05f Don't draw out of bounds line numbers 2024-07-28 14:38:12 +02:00
Krzosa Karol 0569d64cc9 Highlight line number part 2024-07-28 14:36:04 +02:00
Krzosa Karol f55f895cfd Remove tabs 2024-07-28 14:31:38 +02:00
Krzosa Karol de7f084633 Experimenting with tabs 2024-07-28 14:30:24 +02:00
Krzosa Karol 0c2683afaa Fixing stuff 2024-07-28 11:42:12 +02:00
Krzosa Karol d6b850178e Using file path rules 2024-07-28 10:39:57 +02:00
Krzosa Karol a486a09d9e Error reporting and popup, debug window 2024-07-28 10:12:18 +02:00
Krzosa Karol 07a41e0266 Using app data path, deleting config every time, improve loop 2024-07-27 22:07:58 +02:00
Krzosa Karol 052894a628 Config magic 2024-07-27 20:34:20 +02:00
Krzosa Karol 60f26ca40e Fix delete and loading lua config dynamically 2024-07-27 16:47:28 +02:00
Krzosa Karol d5e392c3bc Debug buffer, scroll highlight 2024-07-27 15:04:21 +02:00
Krzosa Karol 8b00f15710 Improve search 2024-07-27 14:14:47 +02:00
Krzosa Karol 0ebe63eff3 Misc 2024-07-27 14:10:38 +02:00
Krzosa Karol 9955181b0d Small refactor 2024-07-27 13:01:11 +02:00
Krzosa Karol 477b485a34 Replace text_editor and bring back ctrl + f, fix circle rendering pos 2024-07-27 11:38:41 +02:00
Krzosa Karol 03eece4e41 Restructure and reload font 2024-07-27 11:35:14 +02:00
Krzosa Karol a43fe1789b Ported mouse movement and conditional update 2024-07-27 09:43:46 +02:00
Krzosa Karol 1e0c5dac83 Porting mouse related events and abstraction idea 2024-07-27 08:58:52 +02:00
Krzosa Karol 680c782a56 Remove platform, small rendering improvement 2024-07-27 08:30:27 +02:00
Krzosa Karol dfe8aa56e9 Port window commands 2024-07-27 08:21:14 +02:00
Krzosa Karol 71494984de Scrolling clip and global commands 2024-07-27 07:41:15 +02:00
Krzosa Karol 8117d043aa Porting focus based features and fix rendering 2024-07-26 22:27:36 +02:00
Krzosa Karol 9d02d5ab78 Fixing scissoring 2024-07-26 21:47:23 +02:00
Krzosa Karol 7803bc87a6 Transitioning text editor to SDL 2024-07-26 17:08:14 +02:00
Krzosa Karol 27b322bf25 Transitioning text editor to SDL 2024-07-26 17:08:05 +02:00
Krzosa Karol def8b6bdc2 Opengl render and font 2024-07-26 14:47:03 +02:00
Krzosa Karol ee6df45e2d Begin move to SDL 2024-07-26 11:33:12 +02:00
Krzosa Karol a74409c3ec Optimize cursor rendering 2024-07-26 09:57:15 +02:00
Krzosa Karol 672a0b3561 Fix line number rendering 2024-07-26 08:25:42 +02:00
Krzosa Karol 48b918a551 Eval lua, fix ordering and fix caret overdraw 2024-07-26 08:09:19 +02:00
Krzosa Karol 4aa738fcc9 Tried to introduce NextActiveWindow but then we lose events like mouse press 2024-07-26 07:52:53 +02:00
Krzosa Karol 7eefa2e6c2 Fix merge carets 2024-07-26 07:37:02 +02:00
Krzosa Karol d4136ef0e3 Performance - not drawing selection outside of line range, add select all matches 2024-07-25 14:55:56 +02:00
Krzosa Karol 469cf3dd24 FindInBuffer, improve find 2024-07-25 13:50:04 +02:00
Krzosa Karol 2d60e795c0 Scrolling even when window inactive 2024-07-25 13:35:10 +02:00
Krzosa Karol 754d6cd3bd Begin search buffer 2024-07-24 17:07:10 +02:00
Krzosa Karol d1b4053205 Small improvements 2024-07-24 16:28:44 +02:00
Krzosa Karol 1cd5e71904 Improve open command 2024-07-24 16:16:57 +02:00
Krzosa Karol cb4f380313 List files and fix scrolling 2024-07-24 14:16:58 +02:00
Krzosa Karol 93e0104c1e Ctrl + Enter 2024-07-24 13:53:21 +02:00
Krzosa Karol c9aed019d5 Refactor active windows 2024-07-24 13:48:56 +02:00
Krzosa Karol 8b8229f73a Line range refactor 2024-07-24 13:23:20 +02:00
Krzosa Karol 039d2f9350 No history buffer, Active window stack 2024-07-24 13:03:52 +02:00
Krzosa Karol bb3044d168 lua improvements 2024-07-24 10:30:33 +02:00
Krzosa Karol 8dace27f56 Font size adjustment, toying with command windows and lua 2024-07-24 08:33:59 +02:00
Krzosa Karol 30932b0d7c Listing open windows, views and buffers 2024-07-24 08:02:46 +02:00
Krzosa Karol afdd3834b9 Info bar and exec bar 2024-07-24 07:30:36 +02:00
Krzosa Karol 02b63bf8d2 Improving window/view/buffer management 2024-07-24 07:12:50 +02:00
Krzosa Karol fb19abb69f Forgot management.cpp 2024-07-23 22:33:08 +02:00
Krzosa Karol 1528ecac52 Working on resource management stuff 2024-07-23 22:33:01 +02:00
Krzosa Karol 4cb892133f Only one infobar 2024-07-23 17:14:11 +02:00
Krzosa Karol 5864b060a9 Misc 2024-07-23 17:02:25 +02:00
Krzosa Karol 0ebfedbf4d Lua and better cursor movement 2024-07-23 16:49:13 +02:00
Krzosa Karol 45c6495121 Small refactor work on focus and windows 2024-07-23 14:13:03 +02:00
Krzosa Karol 24ad9464b5 Z ordering, prep for command window 2024-07-23 13:34:12 +02:00
Krzosa Karol 0f34416726 Window flags, improve mouse cursor, 2024-07-23 13:04:33 +02:00
Krzosa Karol 7249bbf92b Move globals to text_editor.h 2024-07-23 09:09:18 +02:00
Krzosa Karol 5f18779f1d Null objects 2024-07-23 09:06:39 +02:00
Krzosa Karol 740b0f217f View, window and buffer ids 2024-07-23 08:57:09 +02:00
Krzosa Karol bc4fbfd28a Initial window implementation 2024-07-22 17:16:48 +02:00
Krzosa Karol 37a0c73dc3 Prepare for adding windows 2024-07-22 16:46:41 +02:00
Krzosa Karol 53e153a696 Improve double click 2024-07-22 16:26:50 +02:00
Krzosa Karol 06082f2273 Ctrl + D 2024-07-22 15:35:22 +02:00
Krzosa Karol b1c123977d Fix line numbers 2024-07-22 15:26:39 +02:00
Krzosa Karol 535b6d00c4 Draw line numbers 2024-07-22 15:20:54 +02:00
Krzosa Karol 5594b55e5c Info bar 2024-07-22 15:05:55 +02:00
Krzosa Karol 9229135588 Improve scrollbar 2024-07-22 14:49:09 +02:00
Krzosa Karol 9f2aafb95e Improve scrollbar 2024-07-22 14:43:27 +02:00
Krzosa Karol ce20a1d940 Ctrl + A 2024-07-22 10:36:53 +02:00
Krzosa Karol c2b2c2a6ae Improve scrolling 2024-07-22 10:31:02 +02:00
Krzosa Karol b2d9688fbe Scrollbar 2024-07-22 09:59:52 +02:00
Krzosa Karol 254407e89e Clipboard 2024-07-22 08:15:40 +02:00
Krzosa Karol a5069cd148 Undo redo 2024-07-22 08:03:22 +02:00
Krzosa Karol 91d2db6116 Create cursor above, double click, render whitespace when selecting 2024-07-22 07:30:40 +02:00
Krzosa Karol 4c9366d495 Fix merge carets with mouse 2024-07-21 18:12:43 +02:00
Krzosa Karol 915620da34 Full width line highlight and commands.cpp 2024-07-21 17:47:41 +02:00
Krzosa Karol 5d3f1fcf08 Command refactor 2024-07-21 17:38:02 +02:00
Krzosa Karol 9554160edc Experimenting with key bindings 2024-07-21 15:10:54 +02:00
Krzosa Karol fc928da75b Tune the looks 2024-07-21 14:16:09 +02:00
Krzosa Karol 8c1118b429 Refactor and Escape+Delete+Backspace 2024-07-21 12:39:31 +02:00
Krzosa Karol 846d4e7ab5 Add more testing load buffers 2024-07-21 11:07:32 +02:00
Krzosa Karol 816c24c1b6 Manual rendering and small fixes 2024-07-21 10:46:07 +02:00
Krzosa Karol 6ac1c8711c Forgot to add math int 2024-07-21 10:00:01 +02:00
Krzosa Karol c9cd2e6c1e Move to integer based rendering, fix Big line 2024-07-21 09:59:50 +02:00
Krzosa Karol 4c1630d61d Line highlight improvements and misc 2024-07-21 09:03:30 +02:00
Krzosa Karol ddbee2f0ec Optimize, working on a buffer with million lines 2024-07-21 08:30:27 +02:00
Krzosa Karol 8de8938be1 Mouse scrolling, BUFFER_DEBUG, todo list 2024-07-21 08:09:38 +02:00
Krzosa Karol 675e4a10dd Page up and page down, home and end 2024-07-21 07:43:13 +02:00
Krzosa Karol 2b2cc9cf6c Mouse click add cursor 2024-07-21 06:40:44 +02:00
Krzosa Karol 0b74fd81e3 Writing text 2024-07-20 10:06:25 +02:00
Krzosa Karol 941652b4bc Rename cursor to caret because cursor can be confused with mouse pointer 2024-07-20 09:48:40 +02:00
Krzosa Karol 2ba9d991bf Scrolling left right 2024-07-20 09:45:36 +02:00
Krzosa Karol ba5930b585 Scrolling up and scrolling down 2024-07-20 09:37:02 +02:00
Krzosa Karol 3868afce93 Refactor movement code 2024-07-20 09:20:25 +02:00
Krzosa Karol ba4ed9afff Ctrl cursor movement and fix selection draw bug 2024-07-20 09:15:15 +02:00
Krzosa Karol adeb2de366 Implement decently fast selection 2024-07-20 07:56:56 +02:00
Krzosa Karol 0071136146 Cursor movement, draw selection and fixing bugs 2024-07-20 07:41:02 +02:00
Krzosa Karol cd48094a18 Split buffer into multiple files 2024-07-18 14:19:48 +02:00
Krzosa Karol e0ac9654c3 Buffer multi cursor 2024-07-18 14:10:35 +02:00
Krzosa Karol 196d5353c8 Buffer cursor work 2024-07-18 13:22:55 +02:00
Krzosa Karol e9783b2317 Buffer work 2024-07-18 12:25:40 +02:00
Krzosa Karol 47d92dba14 Working on the buffer 2024-07-18 10:08:16 +02:00
Krzosa Karol 24eeca8f79 New project 2024-07-17 07:30:55 +02:00
Krzosa Karol f7ac92cd01 New project 2024-07-17 07:30:46 +02:00
Krzosa Karol 63bd416e7c Convert to SDL3 and static link 2024-07-13 08:58:30 +02:00
Krzosa Karol e6b23b2a98 MenuOpen mode, deffered read on start, cleanup todos 2024-07-13 07:19:22 +02:00
Krzosa Karol 83bc33015d Delete _main.cpp 2024-07-13 06:53:35 +02:00
Krzosa Karol c660118f8b Read on start and omit file type 2024-07-12 12:47:29 +02:00
Krzosa Karol 1ec217905d Config 2024-07-12 10:34:17 +02:00
Krzosa Karol bd97ecb9eb Big update 2024-07-12 08:27:24 +02:00
Krzosa Karol 9891a302ac Big update 2024-07-12 08:27:19 +02:00
Krzosa Karol 37982e0448 Add pdfio 2024-07-08 10:38:35 +02:00
Krzosa Karol 22828c9d23 Print loaded files and errors, enable loading and searching 2024-07-06 09:51:39 +02:00
Krzosa Karol e3a176b2f9 Trying to improve threading, thread queue 2024-07-06 07:55:38 +02:00
Krzosa Karol 30fa22aed5 Gui improvements and optimizations 2024-07-06 06:56:18 +02:00
Krzosa Karol 0dd6289509 Rewrite to IMGUI 2024-07-05 15:24:58 +02:00
Krzosa Karol e23a7b9c02 Fix move down out of selection 2024-07-04 16:23:12 +02:00
Krzosa Karol b48cffd880 Page up page down 2024-07-04 16:21:02 +02:00
Krzosa Karol 2f52c018cd Add spall profiler and stop generating layout every frame 2024-07-04 14:30:20 +02:00
Krzosa Karol 143a88ac1d String coloring 2024-07-04 10:02:51 +02:00
Krzosa Karol 21df381d12 Coloring strings 2024-07-04 07:35:29 +02:00
Krzosa Karol e7f53d2c07 Line highlights 2024-07-04 07:20:45 +02:00
Krzosa Karol a77a149664 Basic line wrapping works 2024-07-03 07:14:57 +02:00
Krzosa Karol 0a75cde80c Fix scrolling 2024-07-02 11:09:20 +02:00
Krzosa Karol 8250058296 Scroll clamping 2024-07-02 11:06:04 +02:00
Krzosa Karol d3c4c4cd02 Add line number drawing 2024-07-02 08:56:29 +02:00
Krzosa Karol aa41d9e15b Basic scroll bars 2024-07-02 08:42:39 +02:00
Krzosa Karol 186ec3c11d Adding bars to the window 2024-07-02 07:36:40 +02:00
Krzosa Karol 620954631a Add math ops 2024-07-02 07:36:21 +02:00
Krzosa Karol e0505dc974 Implement double click 2024-07-02 07:10:32 +02:00
Krzosa Karol ce13f83d46 Multicursor clipboard 2024-07-01 15:13:23 +02:00
Krzosa Karol 1a420e2f22 Redo working 2024-07-01 07:41:44 +02:00
Krzosa Karol d1f83fa669 Undo working 2024-07-01 07:23:46 +02:00
Krzosa Karol 4425db7ca3 Fix cursor offsetting after change 2024-07-01 07:16:11 +02:00
Krzosa Karol ceecb6cc81 Trying to add undo 2024-06-29 12:15:39 +02:00
Krzosa Karol c8ad9222fd Hopefully fixed BeforeEdit, needs a refactor though 2024-06-29 10:49:07 +02:00
Krzosa Karol 7e68e09b22 Fix BeforeEdit cursor removal, add multicursor deletion 2024-06-29 10:27:16 +02:00
Krzosa Karol e3150f8203 Implement Ctrl + D 2024-06-29 09:52:08 +02:00
Krzosa Karol 93ef620448 Improve mouse selection, add multicursor for mouse selection 2024-06-29 09:05:26 +02:00
Krzosa Karol ba711b7f14 Improve mouse scrolling 2024-06-29 08:55:16 +02:00
Krzosa Karol 0d3cb029d8 Toying with event recording to see if it can be used for testing 2024-06-29 07:35:22 +02:00
Krzosa Karol 2807573012 Toying with raylib automation 2024-06-28 18:04:39 +02:00
Krzosa Karol 8528bfefc1 Fix shadowing bug 2024-06-28 17:26:28 +02:00
Krzosa Karol d561883144 Work on end of buffer 2024-06-28 17:24:58 +02:00
Krzosa Karol 2dacc969a3 Refactored lines to contain 'new line' 2024-06-28 15:43:41 +02:00
Krzosa Karol 63adca1fac Cursor scrolling working 2024-06-28 13:43:58 +02:00
Krzosa Karol 4dfa9b432e Refactor y cursor, add small utility for debugging, fix bug in buffer 2024-06-28 13:30:55 +02:00
Krzosa Karol b8cdb49ea5 Fix visual bug when scrolling 2024-06-28 10:37:47 +02:00
Krzosa Karol ffe1ca643e Fixing bugs, bring back mouse selection 2024-06-28 10:20:17 +02:00
Krzosa Karol 95cafa3200 Major refactor of text layout 2024-06-28 09:30:22 +02:00
Krzosa Karol 784028c7a9 X scrolling using main cursor 2024-06-26 07:31:21 +02:00
Krzosa Karol fcb4d361bc Add todos 2024-06-25 09:57:48 +02:00
Krzosa Karol ceb9985242 Scrolling the main cursor properly 2024-06-25 09:38:43 +02:00
Krzosa Karol 03644c0561 Ctrl+c, ctrlv, ctrlx 2024-06-25 07:45:30 +02:00
Krzosa Karol 7ef502f3b0 Adding commands, BeforeEdit AfterEdit 2024-06-25 07:29:28 +02:00
Krzosa Karol 84f0b65fa9 Fix multiple cursors crashes by sorting cursors by min range 2024-06-24 07:27:38 +02:00
Krzosa Karol 66b9a5d15f Fix cursor merging on boundary 2024-06-24 07:00:15 +02:00
Krzosa Karol e82edb89ae Small improvements 2024-06-24 06:51:34 +02:00
Krzosa Karol 37518ed7b0 Selecting text using mouse and new abstraction for cursors 2024-06-23 12:24:22 +02:00
Krzosa Karol b76d825f55 Drawing selection and overlapping selections 2024-06-23 10:05:54 +02:00
Krzosa Karol 10afbd3e4f Port Seek word, add ctrl+left 2024-06-23 09:17:54 +02:00
Krzosa Karol c0d69521fe More proper offseting of cursors during char insert 2024-06-23 07:53:30 +02:00
Krzosa Karol e54596809e Drawing line numbers 2024-06-23 07:46:00 +02:00
Krzosa Karol 6347b56751 Adding scrollbars and titlebars, laying it out 2024-06-23 07:22:03 +02:00
Krzosa Karol 48eca55a4c Move up down and multi cursor 2024-06-22 20:58:29 +02:00
Krzosa Karol 5ba9975c10 Basic cursor movement, handling end of buffer, end of line in drawing 2024-06-22 16:09:26 +02:00
Krzosa Karol 7b818c5cde Drawing the cursor and cell setup 2024-06-22 14:48:32 +02:00
Krzosa Karol 443e88b4a9 Extract font grid from raylib 2024-06-22 12:29:40 +02:00
Krzosa Karol 64540d2d36 Working on rendering lines and clipping 2024-06-22 10:02:12 +02:00
Krzosa Karol 94555d2a60 Working on rendering 2024-06-22 08:35:11 +02:00
Krzosa Karol a329bc2424 Improving the buffer and bug fixing 2024-06-20 16:35:18 +02:00
Krzosa Karol b3b8a54f7f Buffer iterator and utf8 2024-06-20 11:52:33 +02:00
Krzosa Karol 5539bbd3b9 Basic multiline buffer concept 2024-06-20 09:40:05 +02:00
Krzosa Karol b919678913 Add text editor, misc changes 2024-06-20 08:17:54 +02:00
Krzosa Karol 7fe6aa2a97 Reading multiple directories in transcript browser 2024-06-19 10:40:20 +02:00
Krzosa Karol 055be9b058 Refactor to be more input/output, remove globals from parsing 2024-06-19 07:11:18 +02:00
Krzosa Karol a75c8a2e4f Init repo 2024-06-19 06:51:06 +02:00
186 changed files with 75128 additions and 13867 deletions
+17 -14
View File
@@ -1,16 +1,19 @@
build/
backup
subl.bat
multimedia.c
multimedia.h
playground.py
ui_notes.txt
run_linux.bat
l.log
vendor
x64/Debug
x64/Release
.vs/
*.10x
src/external/SDL/
build/
package/
*.rdbg
*.spall
*.sublime-workspace
*.pdb
te
te_debug
*.wasm
*.o
*sublime-project*
*sublime-workspace*
*.html
text_editor.js
*.map
*.exe
+13 -14
View File
@@ -1,19 +1,18 @@
@echo off
for %%a in (%*) do set "%%~a=1"
mkdir build
cd build
set common=-I ../src/ -g -fdiagnostics-absolute-paths -Wno-unsequenced -Wno-single-bit-bitfield-constant-conversion -Wall -Wno-missing-braces -Wextra -Wno-missing-field-initializers
set wasm_flags=--target=wasm32 -nostdlib -mbulk-memory -msimd128 -Wl,-export-dynamic,--allow-undefined,--import-memory,--no-entry,--initial-memory=131072000,--max-memory=4294967296
set flags=/EHsc- /MD /Zi /FC /nologo /WX /W3 /wd4200 /wd4334 /diagnostics:column -DDEBUG_BUILD=1
if not exist build (
mkdir build
)
pushd build
if "%testing%"=="1" echo [testing] && set didbuild=1 && clang ../src/testing/testing_main.c -o testing.exe %common% || exit 1 /b
if "%scratch%"=="1" echo [scratch] && set didbuild=1 && clang ../src/scratch/scratch_main.c -o ../src/scratch/main.wasm %common% %wasm_flags% || exit 1 /b
popd
cl %flags% -Fe:metaprogram.exe -I../src ../src/metaprogram/metaprogram.cpp
metaprogram.exe
if "%didbuild%"=="" (
echo [WARNING] no valid build target specified
exit /b 1
)
set libs=../src/external/SDL/win32-static/SDL3-static.lib ../src/external/SDL/win32-static/SDL_uclibc.lib kernel32.lib gdi32.lib user32.lib Imm32.lib ole32.lib Shell32.lib OleAut32.lib Cfgmgr32.lib Setupapi.lib Advapi32.lib version.lib winmm.lib
cl %flags% ../src/text_editor/text_editor.cpp -Fe:te.exe -I../src/external/SDL/include -I../src/external/lua/src -I../src/external/glad -I../src/ %libs% -link /SUBSYSTEM:WINDOWS /NODEFAULTLIB:LIBCMT /NODEFAULTLIB:MSVCRTD
copy te.exe ..\data\te.exe
copy te.pdb ..\data\te.pdb
echo written ..\data\te.exe
cd ..
rem /fsanitize=address
Executable → Regular
+79 -7
View File
@@ -1,9 +1,81 @@
cd "$(dirname "$0")"
#!/usr/bin/bash
if [ ! -d build ]; then
mkdir build
fi
mkdir build
cd build
# clang ../src/testing/testing_main.c -o testing_main -I../src/ -ldl -lm -lbacktrace -g -Wall -Wextra -Wno-missing-braces -Wno-missing-field-initializers -Wno-single-bit-bitfield-constant-conversion -fdiagnostics-absolute-paths -Wno-writable-strings -Wno-unsequenced
tcc $(realpath ../src/testing/testing_main.c) -o testing_main -I$(realpath ../src/) -b -g -ldl -lm -Wall -Wextra
./testing_main
if [ "$1" = "release" ]; then
profile_flags="-DDEBUG_BUILD=0 -O2"
else
profile_flags="-DDEBUG_BUILD=1"
fi
if [ ! -f "lbaselib.o" ]; then
clang -g -I../src/external/lua/src -I../src/external/glad \
../src/external/lua/src/lbaselib.c \
../src/external/lua/src/lctype.c \
../src/external/lua/src/ldo.c \
../src/external/lua/src/lgc.c \
../src/external/lua/src/liolib.c \
../src/external/lua/src/lmem.c \
../src/external/lua/src/lopcodes.c \
../src/external/lua/src/lstate.c \
../src/external/lua/src/ltable.c \
../src/external/lua/src/lundump.c \
../src/external/lua/src/lzio.c \
../src/external/lua/src/lapi.c \
../src/external/lua/src/lcode.c \
../src/external/lua/src/ldblib.c \
../src/external/lua/src/ldump.c \
../src/external/lua/src/llex.c \
../src/external/lua/src/loadlib.c \
../src/external/lua/src/loslib.c \
../src/external/lua/src/lstring.c \
../src/external/lua/src/ltablib.c \
../src/external/lua/src/lutf8lib.c \
../src/external/lua/src/lauxlib.c \
../src/external/lua/src/lcorolib.c \
../src/external/lua/src/ldebug.c \
../src/external/lua/src/lfunc.c \
../src/external/lua/src/linit.c \
../src/external/lua/src/lmathlib.c \
../src/external/lua/src/lobject.c \
../src/external/lua/src/lparser.c \
../src/external/lua/src/lstrlib.c \
../src/external/lua/src/ltm.c \
../src/external/lua/src/lvm.c \
../src/external/glad/glad.c \
-c
fi
if [ ! -f "metaprogram.exe" ]; then
clang ../src/metaprogram/metaprogram.cpp ../src/basic/unix.cpp -o metaprogram.exe \
-nostdlib++ -fno-exceptions -fdiagnostics-absolute-paths -g \
-Wno-writable-strings \
-I../src
fi
./metaprogram.exe
clang ../src/text_editor/text_editor.cpp ../src/basic/unix.cpp -o te_linux.exe \
-nostdlib++ -fno-exceptions -fdiagnostics-absolute-paths -g \
$profile_flags \
-Wno-writable-strings \
-I../src/external/SDL/include \
-I../src/external/lua/src \
-I../src/external/glad \
-I../src/ \
-lm \
../src/external/SDL/build/libSDL3.a \
lbaselib.o lctype.o ldo.o lgc.o liolib.o lmem.o \
lopcodes.o lstate.o ltable.o lundump.o lzio.o lapi.o lcode.o ldblib.o ldump.o \
llex.o loadlib.o loslib.o lstring.o ltablib.o lutf8lib.o lauxlib.o lcorolib.o ldebug.o \
lfunc.o linit.o lmathlib.o lobject.o lparser.o lstrlib.o ltm.o lvm.o \
glad.o \
if [ "$1" = "release" ]; then
cp te_linux.exe ../data/te
echo written ../data/te
else
cp te_linux.exe ../data/te_debug
echo written ../data/te_debug
fi
+15
View File
@@ -0,0 +1,15 @@
@echo off
set incs=-Isrc/external/SDL/include -Isrc/external/lua/src -Isrc/external/glad -Lsrc/external/SDL/build_web -Isrc
set wasmflags=-sALLOW_MEMORY_GROWTH=1 -sMAXIMUM_MEMORY=1gb -msimd128 -sTOTAL_STACK=5MB -sINITIAL_MEMORY=256mb -sUSE_WEBGL2 -sFULL_ES3=1 -sASYNCIFY -sASSERTIONS=2
set flags=-Wall -Wno-missing-braces -Wno-writable-strings -nostdlib++ -fno-exceptions -fdiagnostics-absolute-paths
set dbg=-g -DDEBUG_BUILD=1 -gsource-map
set rel=-O3 -DDEBUG_BUILD=0
mkdir build
cd build
clang ../src/metaprogram/metaprogram.cpp -o metaprogram.exe %flags% -g -DDEBUG_BUILD=1 -I../src
metaprogram.exe
cd ..
emcc -o text_editor.html --shell-file=data/shell.html %flags% %incs% %wasmflags% %dbg% -lm -lSDL3 src/text_editor/text_editor.cpp
+64
View File
@@ -0,0 +1,64 @@
#!/usr/bin/bash
mkdir build
cd build
if [ ! -f "metaprogram.exe" ]; then
clang ../src/metaprogram/metaprogram.cpp ../src/basic/unix.cpp -o metaprogram.exe \
-nostdlib++ -fno-exceptions -fdiagnostics-absolute-paths -g \
-Wno-writable-strings \
-I../src
fi
./metaprogram.exe
emcc -o ../text_editor.html \
-nostdlib++ -fno-exceptions -fdiagnostics-absolute-paths -g -gsource-map \
--shell-file=../data/shell.html\
$profile_flags \
-Wno-writable-strings \
-I../src/external/SDL/include \
-I../src/external/lua/src \
-I../src/external/glad \
-I../src/ \
-L../src/external/SDL/build_web \
-lm \
-lSDL3 \
-s ALLOW_MEMORY_GROWTH=1 -s MAXIMUM_MEMORY=1gb -msimd128 -s TOTAL_STACK=5MB -s INITIAL_MEMORY=256mb \
../src/text_editor/text_editor.cpp \
../src/basic/unix.cpp \
../src/external/lua/src/lbaselib.c \
../src/external/lua/src/lctype.c \
../src/external/lua/src/ldo.c \
../src/external/lua/src/lgc.c \
../src/external/lua/src/liolib.c \
../src/external/lua/src/lmem.c \
../src/external/lua/src/lopcodes.c \
../src/external/lua/src/lstate.c \
../src/external/lua/src/ltable.c \
../src/external/lua/src/lundump.c \
../src/external/lua/src/lzio.c \
../src/external/lua/src/lapi.c \
../src/external/lua/src/lcode.c \
../src/external/lua/src/ldblib.c \
../src/external/lua/src/ldump.c \
../src/external/lua/src/llex.c \
../src/external/lua/src/loadlib.c \
../src/external/lua/src/loslib.c \
../src/external/lua/src/lstring.c \
../src/external/lua/src/ltablib.c \
../src/external/lua/src/lutf8lib.c \
../src/external/lua/src/lauxlib.c \
../src/external/lua/src/lcorolib.c \
../src/external/lua/src/ldebug.c \
../src/external/lua/src/lfunc.c \
../src/external/lua/src/linit.c \
../src/external/lua/src/lmathlib.c \
../src/external/lua/src/lobject.c \
../src/external/lua/src/lparser.c \
../src/external/lua/src/lstrlib.c \
../src/external/lua/src/ltm.c \
../src/external/lua/src/lvm.c \
../src/external/glad/glad.c \
cd ..
Binary file not shown.
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

+1
View File
@@ -0,0 +1 @@
id ICON "icon.ico"
+481
View File
@@ -0,0 +1,481 @@
local GruvboxDark0Hard = 0x1d2021ff
local GruvboxDark0 = 0x282828ff
local GruvboxDark0Soft = 0x32302fff
local GruvboxDark1 = 0x3c3836ff
local GruvboxDark2 = 0x504945ff
local GruvboxDark3 = 0x665c54ff
local GruvboxDark4 = 0x7c6f64ff
local GruvboxGray245 = 0x928374ff
local GruvboxGray244 = 0x928374ff
local GruvboxLight0Hard = 0xf9f5d7ff
local GruvboxLight0 = 0xfbf1c7ff
local GruvboxLight0Soft = 0xf2e5bcff
local GruvboxLight1 = 0xebdbb2ff
local GruvboxLight2 = 0xd5c4a1ff
local GruvboxLight3 = 0xbdae93ff
local GruvboxLight4 = 0xa89984ff
local GruvboxBrightRed = 0xfb4934ff
local GruvboxBrightGreen = 0xb8bb26ff
local GruvboxBrightYellow = 0xfabd2fff
local GruvboxBrightBlue = 0x83a598ff
local GruvboxBrightPurple = 0xd3869bff
local GruvboxBrightAqua = 0x8ec07cff
local GruvboxBrightOrange = 0xfe8019ff
local GruvboxNeutralRed = 0xcc241dff
local GruvboxNeutralGreen = 0x98971aff
local GruvboxNeutralYellow = 0xd79921ff
local GruvboxNeutralBlue = 0x458588ff
local GruvboxNeutralPurple = 0xb16286ff
local GruvboxNeutralAqua = 0x689d6aff
local GruvboxNeutralOrange = 0xd65d0eff
local GruvboxFadedRed = 0x9d0006ff
local GruvboxFadedGreen = 0x79740eff
local GruvboxFadedYellow = 0xb57614ff
local GruvboxFadedBlue = 0x076678ff
local GruvboxFadedPurple = 0x8f3f71ff
local GruvboxFadedAqua = 0x427b58ff
local GruvboxFadedOrange = 0xaf3a03ff
Color = {}
Color.Text = GruvboxDark0Hard
Color.LoadTextHighlight = 0x0000000F
Color.Background = GruvboxLight0Hard
Color.InactiveWindow = 0x0000000F
Color.TextLineNumbers = GruvboxDark4
Color.LineHighlight = GruvboxLight0Soft
Color.MainCaret = GruvboxDark0Hard
Color.SubCaret = GruvboxGray245
Color.Selection = GruvboxLight1
Color.WhitespaceDuringSelection = GruvboxLight4
Color.MouseUnderline = GruvboxDark0Hard
Color.CaretUnderline = GruvboxGray245
Color.FuzzySearchLineHighlight = GruvboxDark0
Color.ScrollbarBackground = GruvboxLight2
Color.ScrollbarScroller = GruvboxLight1
Color.ScrollbarScrollerSelected = GruvboxLight0Hard
Color.TitleBarText = GruvboxDark2
Color.TitleBarBackground = GruvboxLight1
Color.TitleBarActiveBackground = 0xfefefefe
Color.TitleBarSelection = GruvboxLight3
Color.ResizerBackground = GruvboxLight0Hard
Color.ResizerOutline = GruvboxLight3
Style = {}
Style.WaitForEvents = 1
Style.DrawLineNumbers = 1
Style.DrawScrollbar = 1
Style.IndentSize = 4
Style.FontSize = 15
Style.Font = GetExeDir().."/CascadiaMono.ttf"
Style.VCVarsall = "C:/Program Files/Microsoft Visual Studio/2022/Community/VC/Auxiliary/Build/vcvars64.bat"
Style.TrimWhitespaceOnSave = true
Style.ClangFormatOnSave = false
Style.StyleUndoMergeTimeout = 0.3
INTERNET_BROWSER = 'C:/Program Files/BraveSoftware/Brave-Browser/Application/brave.exe'
OS_WINDOWS = 0
OS_UNIX = 1
SDLK_CTRL = 1073742048
SDLK_PAGE_DOWN = 1073741902
SDLK_PAGE_UP = 1073741899
SDLK_DOWN = 1073741905 -- 0x40000051
SDLK_UP = 1073741906 -- 0x40000052u
SDLK_RIGHT = 1073741903
SDLK_LEFT = 1073741904
SDLK_Q = 113
SDLK_BACKSLASH = 0x5c
SDLK_RETURN = 13
SDLK_EQUALS = 0x0000003d
SDLK_MINUS = 0x0000002d
SDLK_F1 = 0x4000003a
SDLK_F2 = 0x4000003b
SDLK_F3 = 0x4000003c
SDLK_F4 = 0x4000003d
SDLK_F5 = 0x4000003e
SDLK_F6 = 0x4000003f
SDLK_F7 = 0x40000040
SDLK_F8 = 0x40000041
SDLK_F9 = 0x40000042
SDLK_F10 = 0x40000043
SDLK_F11 = 0x40000044
SDLK_F12 = 0x40000045
SDLK_A = 0x00000061
SDLK_B = 0x00000062
SDLK_C = 0x00000063
SDLK_D = 0x00000064
SDLK_E = 0x00000065
SDLK_F = 0x00000066
SDLK_G = 0x00000067
SDLK_H = 0x00000068
SDLK_I = 0x00000069
SDLK_J = 0x0000006a
SDLK_K = 0x0000006b
SDLK_L = 0x0000006c
SDLK_M = 0x0000006d
SDLK_N = 0x0000006e
SDLK_O = 0x0000006f
SDLK_P = 0x00000070
SDLK_Q = 0x00000071
SDLK_R = 0x00000072
SDLK_S = 0x00000073
SDLK_T = 0x00000074
SDLK_U = 0x00000075
SDLK_V = 0x00000076
SDLK_W = 0x00000077
SDLK_X = 0x00000078
SDLK_Y = 0x00000079
SDLK_Z = 0x0000007a
VERTICAL = 1
HORIZONTAL = 2
function IsAlpha(a)
if a == nil then
return false
end
local x = string.byte(a)
local result = (x >= string.byte('a') and x <= string.byte('z')) or (x >= string.byte('A') and x <= string.byte('Z'))
return result
end
function SkipLineAndColumn(s)
local line, col = "-1", "-1"
function parse_line_and_column(line_and_col, delimiter)
ic, jc = line_and_col:find(delimiter)
line = line_and_col:sub(1, ic - 1)
col = line_and_col:sub(ic + 1)
return line, col
end
do -- :line:column
local i, j = s:find("^:%d+:%d+")
if i then
skip_pattern = s:sub(j + 1)
line, col = parse_line_and_column(s:sub(2, j), ":")
return line, col, skip_pattern
end
end
do -- :line
local i, j = s:find("^:%d+")
if i then
skip_pattern = s:sub(j + 1)
line = s:sub(2, j)
return line, col, skip_pattern
end
end
do -- (line,column)
local i, j = s:find("^%(%d+,%d+%)")
if i then
skip_pattern = s:sub(j + 1)
line, col = parse_line_and_column(s:sub(2, j - 1), ",")
return line, col, skip_pattern
end
end
do -- (line)
local i, j = s:find("^%(%d+%)")
if i then
skip_pattern = s:sub(j + 1)
line = s:sub(2, j - 1)
return line, col, skip_pattern
end
end
return line, col, s
end
function SkipSlashes(s)
found_slash = false
while s:sub(1,1) == '/' or s:sub(1,1) == '\\' do
s = s:sub(2)
found_slash = true
end
return s, found_slash
end
function SkipDrive(s)
local i, j = s:find("^%a:")
if not i then
return s, nil, true
end
local drive = s:sub(i, j)
local new_s = s:sub(j + 1)
new_s, found_slash = SkipSlashes(new_s)
if not found_slash then
return s, drive, false
end
return new_s, drive, true
end
function WindowsSkipPathCell(s)
local i, j = s:find("^[%w_%.-% +]+")
if not i then return s, nil, false end
local word = s:sub(i, j)
local new_s = s:sub(j + 1)
local new_s, found_slash = SkipSlashes(new_s)
return new_s, word, found_slash
end
function WindowsSkipPath(s)
local input_s = s
local s, drive, ok = SkipDrive(s)
if not ok then return s end
local cells = {}
if drive ~= nil then
table.insert(cells, drive)
end
while true do
s, word, slash_eaten = WindowsSkipPathCell(s)
if word then cells[#cells + 1] = word end
if not slash_eaten then break end
end
if #cells == 0 then return s end
local skip_size = input_s:len() - s:len()
local path = input_s:sub(1, skip_size)
return s, path, drive, cells
end
function MatchWindowsPath(_s, meta)
local s, file_path, drive = WindowsSkipPath(_s)
if not file_path and FileExists(drive) then
return {kind = "text", file_path = drive, line = line, col = col}
end
if not file_path then
return nil
end
if not drive then
local d = GetMainDir()
file_path = d..'/'..file_path
end
local line, col, s = SkipLineAndColumn(s)
local exists = FileExists(file_path) or BufferExists(file_path)
if not exists then return nil end
return {kind = "text", file_path = file_path, line = line, col = col}
end
function MatchUnixPath(s, meta)
local i, j = s:find("^[%w_%.-% %/]+")
local path = s:sub(i, j)
local rest = s:sub(j + 1, -1)
local line, col, s = SkipLineAndColumn(rest)
Print(path, rest, line, col)
return {kind = "text", file_path = path, line = line, col = col}
end
if OS_VALUE == OS_WINDOWS then
MatchPath = MatchWindowsPath
else
MatchPath = MatchUnixPath
end
function MatchGitCommit(s, meta)
local i, j = string.find(s, "^commit ([a-zA-Z0-9]+)")
if i then
s = s:sub(8)
local command = "git --no-pager show "..s
return {kind = "exec", cmd = command, working_dir = GetMainDir()}
end
return nil
end
function MatchURL(s, meta)
local i, j = string.find(s, "^https://")
if i then
return {kind = "exec_console", cmd = '"'..INTERNET_BROWSER..'" '..s, working_dir = GetMainDir()}
end
return nil
end
function MatchGotoBuild(s, meta)
if meta ~= "goto_build" then
return nil
end
local windows_path = IsAlpha(s:sub(1,1)) and s:sub(2,2) == ':'
local windows_rela = s:sub(1,1) == '.' and s:sub(2,2) == '\\'
local unix_path = s:sub(1,1) == '/'
local unix_rela = s:sub(1,1) == '.' and s:sub(2,2) == '/'
if not windows_path and not windows_rela and not unix_path and not windows_rela then
return {kind = "skip"}
end
return nil
end
function MatchExec(s, meta)
if s:match(".exe$") or s:match(".bat$") or s:match(".sh$") then
return {kind = "exec_console", cmd = s, working_dir = GetMainDir()}
end
if s:match("^%$") then
return {kind = "exec_console", cmd = s:sub(2, -1), working_dir = GetMainDir()}
end
return nil
end
BuiltinOnOpenMatchers = {
MatchPath,
MatchGitCommit,
MatchURL,
MatchGotoBuild,
MatchExec,
}
OnOpenMatchers = BuiltinOnOpenMatchers
function OnOpen(path, meta)
for i = #OnOpenMatchers,1,-1 do
rule = OnOpenMatchers[i]
result = rule(path, meta)
if result then
return result
end
end
return nil
end
Coroutines = {}
function CoAdd(f)
local i = #Coroutines + 1
Coroutines[i] = coroutine.create(f)
coroutine.resume(Coroutines[i])
return Coroutines[i]
end
function OnUpdate(e)
local new_co_list = {}
for key, co in pairs(Coroutines) do
local status = coroutine.status(co)
if status ~= "dead" then
coroutine.resume(co, e)
new_co_list[#new_co_list + 1] = co
end
end
Coroutines = new_co_list
end
function KeybindsBasic(e)
if e.key == SDLK_F and e.ctrl == 1 and e.shift == 1 then
C("git grep -n "..GetLoadWord().." :/")
return true
end
return false
end
function BasicBuild()
SaveAll()
if OS_VALUE == OS_WINDOWS then
return "build.bat"
else
return "./build.sh"
end
end
FKey = {BasicBuild, "", "", "", "", "", "", "", "", "", "", ""}
FKeySDLK = {SDLK_F1, SDLK_F2, SDLK_F3, SDLK_F4, SDLK_F5, SDLK_F6, SDLK_F7, SDLK_F8, SDLK_F9, SDLK_F10, SDLK_F11, SDLK_F12}
function KeybindsFKeys(e)
for i = #FKey,1,-1 do
if FKey[i] ~= "" then
if e.key == FKeySDLK[i] then
local cmdline = FKey[i]
if type(cmdline) == "function" then cmdline = FKey[i]() end
Cmd { working_dir = GetWorkDir(), kind = "console", cmd = cmdline }
return true
end
end
end
return false
end
BuiltinOnCommandCallbacks = {
KeybindsBasic,
KeybindsFKeys,
}
OnCommandCallbacks = BuiltinOnCommandCallbacks
function OnCommand(e)
for i = #OnCommandCallbacks,1,-1 do
on_command = OnCommandCallbacks[i]
local result = on_command(e)
if result then
return true
end
end
return false
end
function OnInit()
end
function OnSave(buffer_id)
local dont_trim_lines_with_caret = false
ConvertLineEndingsToLF(buffer_id, dont_trim_lines_with_caret)
if Style.TrimWhitespaceOnSave then
TrimTrailingWhitespace(buffer_id, dont_trim_lines_with_caret)
end
local name = GetBufferNameByID(buffer_id)
if Style.ClangFormatOnSave and (name:match(".c$") or name:match(".h$") or name:match(".cpp$") or name:match(".hpp$")) then
ApplyClangFormat(buffer_id)
end
end
function IsCodeExclude(s, meta)
if s:match("/.git$") or s:match("\\.git$") or
s:match(".exe$") or
s:match(".bin$") or
s:match(".obj$") or
s:match(".o$") or
s:match(".lib$") or
s:match(".ilk$") or
s:match(".cache$") or
s:match(".exp$") or
s:match(".pdb$") or
s:match("/external/") or s:match("\\external\\")
then
return false
end
return true
end
BuiltinIsCodeMatchers = {
IsCodeExclude,
}
IsCodeMatchers = BuiltinIsCodeMatchers
function IsCode(path, meta)
for i = #IsCodeMatchers,1,-1 do
rule = IsCodeMatchers[i]
result = rule(path, meta)
if result then
return result
end
end
return false
end
+42
View File
@@ -0,0 +1,42 @@
<!doctype html>
<html lang="en-us">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no"/>
<title>Emscripten-Generated Code</title>
<style>
body { margin: 0; background-color: black }
.game {
position: absolute;
top: 0px;
left: 0px;
margin: 0px;
border: 0;
width: 100%;
height: 100%;
overflow: hidden;
display: block;
image-rendering: optimizeSpeed;
image-rendering: -moz-crisp-edges;
image-rendering: -o-crisp-edges;
image-rendering: -webkit-optimize-contrast;
image-rendering: optimize-contrast;
image-rendering: crisp-edges;
image-rendering: pixelated;
-ms-interpolation-mode: nearest-neighbor;
}
</style>
</head>
<body>
<canvas class="game" id="canvas" oncontextmenu="event.preventDefault()"></canvas>
<script type='text/javascript'>
var Module = {
preRun: [],
print: (...args) => console.log('[stdout]: ' + args.join(' ')),
printErr: (...args) => console.log('[stderr]: ' + args.join(' ')),
};
window.onerror = (event) => console.log('[onerror]: ' + event.message);
</script>
{{{ SCRIPT }}}
</body>
</html>
@@ -0,0 +1,25 @@
-- Style.WaitForEvents = 0
-- CoAdd(function()
-- Play{
-- {kind = 10, key = KEY_DOWN, xwindow = 1280, ywindow = 720},
-- {kind = 10, key = KEY_DOWN, xwindow = 1280, ywindow = 720},
-- {kind = 10, key = KEY_DOWN, xwindow = 1280, ywindow = 720},
-- {kind = 10, key = KEY_DOWN, xwindow = 1280, ywindow = 720},
-- {kind = 10, key = KEY_DOWN, xwindow = 1280, ywindow = 720},
-- {kind = 10, key = KEY_DOWN, xwindow = 1280, ywindow = 720},
-- {kind = 10, key = KEY_DOWN, xwindow = 1280, ywindow = 720},
-- {kind = 10, key = KEY_Q , xwindow = 1280, ywindow = 720, ctrl = 1},
-- {kind = 10, key = KEY_PAGE_DOWN, xmouse = 0, ymouse = 0, xwindow = 1280, ywindow = 720},
-- {kind = 111},
-- }
-- -- for i = 1,8 do coroutine.CoYield() end
-- while coroutine.CoYield().kind ~= 111 do end
-- local buffer_name = GetActiveMainWindowBufferName()
-- Print("buffer name = "..buffer_name)
-- if buffer_name == "C:/Work/text_editor/src/text_editor/buffer_history.cpp" then
-- Play{{kind = 2}}
-- end
-- end)
+19
View File
@@ -0,0 +1,19 @@
left_mouse :: ctrl add cursor, selections work, alt load word
right_mouse :: ctrl exec word,alt go back
ctrl+q exec alt+q load
alt+w go back
ctrl mleft - add cursor
ctrl shift mleft - add cursor and set selection
alt mleft -
alt ctrl mleft -
alt shift mleft -
mright - destroy pointed at selection and copy | copy line
alt mright - go back
ctrl mright - load word
shift mright -
alt shift mright -
alt ctrl mright - go forward
ctrl shift mright - exec word
mmiddle -
+26
View File
@@ -0,0 +1,26 @@
https://learn.microsoft.com/en-us/windows/win32/api/namedpipeapi/nf-namedpipeapi-peeknamedpipe
https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-readfile
https://github.com/sheredom/subprocess.h
https://github.com/4coder-archive/4coder/blob/master/platform_win32/win32_4ed.cpp :486
https://stackoverflow.com/questions/67551213/read-processs-stdout-output-in-win32-c-desktop-application
https://handmade.network/forums/t/1219-win32_asynchronous_pipes_question
- I guess you can just do color matching in rendering, have a table and try matching words etc.
- maybe I should disallow somehow taking pointers to dynamic array items? Just references!
- create process with buffer (append to end)
- create process and put it at specific cursor position in buffer?
- create process without buffer attached (maybe for error?) (we want some notification that it failed or something)
- code indexing: maybe we can do that line based since you want to jump to line not a particular place.
- on edit we could reparse the line for symbol
- I think 4coder first tries to offset the index file on immediate edit, on frame tick it tries to reparse the modified file in entirety
- offseting things doesn't seem that hard since we already figured it out with cursors
- would it be fast enough to just reparse the entire file of certain size every time?
- coloring seems even more hairy to do correctly because there are multiline comments etc.
- it honestly seems no matter what you do it's a very hairy problem, text was not meant for this
+12
View File
@@ -0,0 +1,12 @@
absolute path C:/notes
lower case c:/notes
backwards slash C:\
go back ../notes
current dir ./notes
file without slash notes
allows spaces C:\Program Files/
multiple slashes C:\\\\\\\\\\\\\\\\\\\\\\\\\thing
you can combine the slashes C:\/Work
disallowed characters for names * \ / ? > < | : "
There is literally no way to consistently skip the windows path, you always have to relay on heuristics
+98
View File
@@ -0,0 +1,98 @@
REDESIGN and DELETE CODE
- Reduce the amount of actions needed to navigate using keyboard
- Make mouse important but much less so
Needs to change:
- Make it more similar to sublime like editors
- Need Ctrl + P
- Clickable title bar may be cool or whatever but it's pretty bad
- Executing lua commands is clunky, need a real Ctrl+P and keybind actions, popups: remove a lot of the lua functionality, just for config files
- Window, View, Buffer + flags design (or is completely new kind based approach needed for Windows/Views?)
- How to make non-editable, informative, with different font size, title bar. Which might also contain tabs
- How to design clickable tree view in this way?
- How to design Command view?
- How to design popup view (input field)?
- How to design search view? or search and replace view?
Things I like:
- Basic editing
- Configurable Open
- Lua config files work pretty well
Splits:
- Buffer16 Buffer8?
- Why constraint that name of buffer needs to be unique? For Open() and default behavior but is this required?
- Try to add Tracking Allocator and rewrite the app, free all memory at the end of the app and check all is well
- move titlebar, search to splits?
Linux
- Add backtrace
Commands TODO:
- Search
- Ctrl + F
- Next occurence: Enter
- Prev occurence: Shift + Enter
- next occurence: F3
- prev occurence: Shift + F3
- Console: OK concept but constrain
- Turned off by default
- Special: non editable, hotkeys don't work etc.
DESIGN try to make console less special, make stuff reusable etc.
DESIGN Config file versions, when loading should be checked, at the top of the file, what to do when old version?
ISSUE Ctrl+Alt+Down (DuplicateLine) doesn't work on ubuntu
DESIGN Moving vertically between splits, which keys???
DESIGN Console, when writing commands and evaling in console it should properly insert a new line after our thing when writing on last line
DESIGN The cursor hopping history needs a bit of fixing, probably needs to be more complicated with collapsing commands
FEATURE KillConsole, or maybe some window targetting but how??
ISSUE I hit a case where GC tried deleting a buffer which was not attached to the buffer list, it had zeroed next, prev. It happened after iterating through directories using the ctrl + period
FEATURE Search whole words, case sensitive etc.
FEATURE Select all searched occurences
PLATFORM Fix windows build
ISSUE What to do / how should Reopen work after we delete the file on disk in some other program?
DESIGN Changing window properties by changing the window name?
FEATURE commands for scrolling: center, cursor_at_bottom_of_screen, cursor_at_top
FEATURE Kill buffer command (it should be marked for deletion and deleted at the end of frame!)
DESIGN Check. Convert more commands to taking buffer instead of view
DESIGN Check. Rewrite more commands to use already implemented commands?
FEATURE Lua namespaces for different kinds of commands (by ids, using main_set, using active_set)?
FEATURE Some decl/function indexing in fuzzy format
ISSUE? Fix jump scroll, the query ends up the last line on screen, kind of wacky
FEATURE dump text editor state to file, restore state
DESIGN ask user if he really wants to quit even though he has an unsaved buffer - popup window | we could just show ForceClose() in the titlebar
FEATURE Find matches using grep, change things in that buffer then apply those changes to all items
FEATURE group history entries so the you can rollback through multiple ones at once and not waste time on skipping whitespace trimming or deleting every character
- Search and replace
- word complete
- Search all buffers in 10X style, incrementally searched results popping up on every key press (maybe we need coroutine library in C so this is easier?)
- escapeing multiple cursor after ctrl + d should put the cursor where it was (probably will need to swap secondary and primary cursor for new cursor
- draw indentation levels like in sublime (those lines) - we render chars one by one so seems relatively easy to figure out if whitespace belongs to beginning of line (make sure to add max value like 40 because of big files)
- code sections, visual demarkation if beginning of line has a very specific text + goto next / goto prev section hotkey!
- combine glyph and selection rendering
backlog
- expose a coroutine based scripting enviorment where user can execute shell commands wait for them and perform actions in very linear manner
- Test stdin writing code
- Implement shell interaction (the valid cmd lines should start with '>' or '$', user can add more lines like this to expand the command size maybe?, if we have a case where we have a line with '>' but the last line doesn't have (just a space) then it should execute?)
- drop text into window
- I think the way sublime text and we display line highlights is confusing with multiple cursors (line highlight can be confused with selection)
- make the editor replayable, store events and then replay, be careful about globals
- maybe open should return multiple options if there are many more? (like in sublime if many symbols you get a window and you choose and it automatically jumps you to the symbol in the background)
- I want a way to assign flags to buffers/views/windows from user perspective so that console window concept can be created from user space
- font cache and on demand unicode loads
- color parens, braces
- redo tree
- gap buffer
- optimize rendering - command buffer, and vertice buffer instead of vertice buffer with scissor
!!As little lua code as possible, but lua code should be powerful just in case of quick edits
+98
View File
@@ -0,0 +1,98 @@
Basic Latin
! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q R S T U V W X Y Z [ \ ] ^ _ ` a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~
Latin-1 Supplement
¡ ¢ £ ¤ ¥ ¦ § ¨ © ª « ¬ ­ ® ¯ ° ± ² ³ ´ µ ¶ · ¸ ¹ º » ¼ ½ ¾ ¿ À Á Â Ã Ä Å Æ Ç È É Ê Ë Ì Í Î Ï Ð Ñ Ò Ó Ô Õ Ö × Ø Ù Ú Û Ü Ý Þ ß à á â ã ä å æ ç è é ê ë ì í î ï ð ñ ò ó ô õ ö ÷ ø ù ú û ü ý þ ÿ
Latin Extended-A
Ā ā Ă ă Ą ą Ć ć Ĉ ĉ Ċ ċ Č č Ď ď Đ đ Ē ē Ĕ ĕ Ė ė Ę ę Ě ě Ĝ ĝ Ğ ğ Ġ ġ Ģ ģ Ĥ ĥ Ħ ħ Ĩ ĩ Ī ī Ĭ ĭ Į į İ ı IJ ij Ĵ ĵ Ķ ķ ĸ Ĺ ĺ Ļ ļ Ľ ľ Ŀ ŀ Ł ł Ń ń Ņ ņ Ň ň ʼn Ŋ ŋ Ō ō Ŏ ŏ Ő ő Œ œ Ŕ ŕ Ŗ ŗ Ř ř Ś ś Ŝ ŝ Ş ş Š š Ţ ţ Ť ť Ŧ ŧ Ũ ũ Ū ū Ŭ ŭ Ů ů Ű ű Ų ų Ŵ ŵ Ŷ ŷ Ÿ Ź ź Ż ż Ž ž ſ
Latin Extended-B
ƀ Ɓ Ƃ ƃ Ƅ ƅ Ɔ Ƈ ƈ Ɖ Ɗ Ƌ ƌ ƍ Ǝ Ə Ɛ Ƒ ƒ Ɠ Ɣ ƕ Ɩ Ɨ Ƙ ƙ ƚ ƛ Ɯ Ɲ ƞ Ɵ Ơ ơ Ƣ ƣ Ƥ ƥ Ʀ Ƨ ƨ Ʃ ƪ ƫ Ƭ ƭ Ʈ Ư ư Ʊ Ʋ Ƴ ƴ Ƶ ƶ Ʒ Ƹ ƹ ƺ ƻ Ƽ ƽ ƾ ƿ ǀ ǁ ǂ ǃ DŽ Dž dž LJ Lj lj NJ Nj nj Ǎ ǎ Ǐ ǐ Ǒ ǒ Ǔ ǔ Ǖ ǖ Ǘ ǘ Ǚ ǚ Ǜ ǜ ǝ Ǟ ǟ Ǡ ǡ Ǣ ǣ Ǥ ǥ Ǧ ǧ Ǩ ǩ Ǫ ǫ Ǭ ǭ Ǯ ǯ ǰ DZ Dz dz Ǵ ǵ Ǻ ǻ Ǽ ǽ Ǿ ǿ Ȁ ȁ Ȃ ȃ ...
IPA Extensions
ɐ ɑ ɒ ɓ ɔ ɕ ɖ ɗ ɘ ə ɚ ɛ ɜ ɝ ɞ ɟ ɠ ɡ ɢ ɣ ɤ ɥ ɦ ɧ ɨ ɩ ɪ ɫ ɬ ɭ ɮ ɯ ɰ ɱ ɲ ɳ ɴ ɵ ɶ ɷ ɸ ɹ ɺ ɻ ɼ ɽ ɾ ɿ ʀ ʁ ʂ ʃ ʄ ʅ ʆ ʇ ʈ ʉ ʊ ʋ ʌ ʍ ʎ ʏ ʐ ʑ ʒ ʓ ʔ ʕ ʖ ʗ ʘ ʙ ʚ ʛ ʜ ʝ ʞ ʟ ʠ ʡ ʢ ʣ ʤ ʥ ʦ ʧ ʨ
Spacing Modifier Letters
ʰ ʱ ʲ ʳ ʴ ʵ ʶ ʷ ʸ ʹ ʺ ʻ ʼ ʽ ʾ ʿ ˀ ˁ ˂ ˃ ˄ ˅ ˆ ˇ ˈ ˉ ˊ ˋ ˌ ˍ ˎ ˏ ː ˑ ˒ ˓ ˔ ˕ ˖ ˗ ˘ ˙ ˚ ˛ ˜ ˝ ˞ ˠ ˡ ˢ ˣ ˤ ˥ ˦ ˧ ˨ ˩
Combining Diacritical Marks
̀ ́ ̂ ̃ ̄ ̅ ̆ ̇ ̈ ̉ ̊ ̋ ̌ ̍ ̎ ̏ ̐ ̑ ̒ ̓ ̔ ̕ ̖ ̗ ̘ ̙ ̚ ̛ ̜ ̝ ̞ ̟ ̠ ̡ ̢ ̣ ̤ ̥ ̦ ̧ ̨ ̩ ̪ ̫ ̬ ̭ ̮ ̯ ̰ ̱ ̲ ̳ ̴ ̵ ̶ ̷ ̸ ̹ ̺ ̻ ̼ ̽ ̾ ̿ ̀ ́ ͂ ̓ ̈́ ͅ ͠ ͡
Greek
ʹ ͵ ͺ ; ΄ ΅ Ά · Έ Ή Ί Ό Ύ Ώ ΐ Α Β Γ Δ Ε Ζ Η Θ Ι Κ Λ Μ Ν Ξ Ο Π Ρ Σ Τ Υ Φ Χ Ψ Ω Ϊ Ϋ ά έ ή ί ΰ α β γ δ ε ζ η θ ι κ λ μ ν ξ ο π ρ ς σ τ υ φ χ ψ ω ϊ ϋ ό ύ ώ ϐ ϑ ϒ ϓ ϔ ϕ ϖ Ϛ Ϝ Ϟ Ϡ Ϣ ϣ Ϥ ϥ Ϧ ϧ Ϩ ϩ Ϫ ϫ Ϭ ϭ Ϯ ϯ ϰ ϱ ϲ ϳ
Cyrillic
Ё Ђ Ѓ Є Ѕ І Ї Ј Љ Њ Ћ Ќ Ў Џ А Б В Г Д Е Ж З И Й К Л М Н О П Р С Т У Ф Х Ц Ч Ш Щ Ъ Ы Ь Э Ю Я а б в г д е ж з и й к л м н о п р с т у ф х ц ч ш щ ъ ы ь э ю я ё ђ ѓ є ѕ і ї ј љ њ ћ ќ ў џ Ѡ ѡ Ѣ ѣ Ѥ ѥ Ѧ ѧ Ѩ ѩ Ѫ ѫ Ѭ ѭ Ѯ ѯ Ѱ ѱ Ѳ ѳ Ѵ ѵ Ѷ ѷ Ѹ ѹ Ѻ ѻ Ѽ ѽ Ѿ ѿ Ҁ ҁ ҂ ҃ ...
Armenian
Ա Բ Գ Դ Ե Զ Է Ը Թ Ժ Ի Լ Խ Ծ Կ Հ Ձ Ղ Ճ Մ Յ Ն Շ Ո Չ Պ Ջ Ռ Ս Վ Տ Ր Ց Ւ Փ Ք Օ Ֆ ՙ ՚ ՛ ՜ ՝ ՞ ՟ ա բ գ դ ե զ է ը թ ժ ի լ խ ծ կ հ ձ ղ ճ մ յ ն շ ո չ պ ջ ռ ս վ տ ր ց ւ փ ք օ ֆ և ։
Hebrew
֑ ֒ ֓ ֔ ֕ ֖ ֗ ֘ ֙ ֚ ֛ ֜ ֝ ֞ ֟ ֠ ֡ ֣ ֤ ֥ ֦ ֧ ֨ ֩ ֪ ֫ ֬ ֭ ֮ ֯ ְ ֱ ֲ ֳ ִ ֵ ֶ ַ ָ ֹ ֻ ּ ֽ ־ ֿ ׀ ׁ ׂ ׃ ׄ א ב ג ד ה ו ז ח ט י ך כ ל ם מ ן נ ס ע ף פ ץ צ ק ר ש ת װ ױ ײ ׳ ״
Arabic
، ؛ ؟ ء آ أ ؤ إ ئ ا ب ة ت ث ج ح خ د ذ ر ز س ش ص ض ط ظ ع غ ـ ف ق ك ل م ن ه و ى ي ً ٌ ٍ َ ُ ِ ّ ْ ٠ ١ ٢ ٣ ٤ ٥ ٦ ٧ ٨ ٩ ٪ ٫ ٬ ٭ ٰ ٱ ٲ ٳ ٴ ٵ ٶ ٷ ٸ ٹ ٺ ٻ ټ ٽ پ ٿ ڀ ځ ڂ ڃ ڄ څ چ ڇ ڈ ډ ڊ ڋ ڌ ڍ ڎ ڏ ڐ ڑ ڒ ړ ڔ ڕ ږ ڗ ژ ڙ ښ ڛ ڜ ڝ ڞ ڟ ڠ ڡ ڢ ڣ ڤ ڥ ڦ ڧ ڨ ک ڪ ګ ڬ ڭ ڮ گ ڰ ڱ ...
Devanagari
ँ ं ः अ आ इ ई उ ऊ ऋ ऌ ऍ ऎ ए ऐ ऑ ऒ ओ औ क ख ग घ ङ च छ ज झ ञ ट ठ ड ढ ण त थ द ध न ऩ प फ ब भ म य र ऱ ल ळ ऴ व श ष स ह ़ ऽ ा ि ी ु ू ृ ॄ ॅ ॆ े ै ॉ ॊ ो ौ ् ॐ ॑ ॒ ॓ ॔ क़ ख़ ग़ ज़ ड़ ढ़ फ़ य़ ॠ ॡ ॢ ॣ । ॥ ० १ २ ३ ४ ५ ६ ७ ८ ९ ॰
Bengali
ঁ ং ঃ অ আ ই ঈ উ ঊ ঋ ঌ এ ঐ ও ঔ ক খ গ ঘ ঙ চ ছ জ ঝ ঞ ট ঠ ড ঢ ণ ত থ দ ধ ন প ফ ব ভ ম য র ল শ ষ স হ ় া ি ী ু ূ ৃ ৄ ে ৈ ো ৌ ্ ৗ ড় ঢ় য় ৠ ৡ ৢ ৣ ০ ১ ২ ৩ ৪ ৫ ৬ ৭ ৮ ৯ ৰ ৱ ৲ ৳ ৴ ৵ ৶ ৷ ৸ ৹ ৺
Gurmukhi
ਂ ਅ ਆ ਇ ਈ ਉ ਊ ਏ ਐ ਓ ਔ ਕ ਖ ਗ ਘ ਙ ਚ ਛ ਜ ਝ ਞ ਟ ਠ ਡ ਢ ਣ ਤ ਥ ਦ ਧ ਨ ਪ ਫ ਬ ਭ ਮ ਯ ਰ ਲ ਲ਼ ਵ ਸ਼ ਸ ਹ ਼ ਾ ਿ ੀ ੁ ੂ ੇ ੈ ੋ ੌ ੍ ਖ਼ ਗ਼ ਜ਼ ੜ ਫ਼ ੦ ੧ ੨ ੩ ੪ ੫ ੬ ੭ ੮ ੯ ੰ ੱ ੲ ੳ ੴ
Gujarati
ઁ ં ઃ અ આ ઇ ઈ ઉ ઊ ઋ ઍ એ ઐ ઑ ઓ ઔ ક ખ ગ ઘ ઙ ચ છ જ ઝ ઞ ટ ઠ ડ ઢ ણ ત થ દ ધ ન પ ફ બ ભ મ ય ર લ ળ વ શ ષ સ હ ઼ ઽ ા િ ી ુ ૂ ૃ ૄ ૅ ે ૈ ૉ ો ૌ ્ ૐ ૠ ૦ ૧ ૨ ૩ ૪ ૫ ૬ ૭ ૮ ૯
Oriya
ଁ ଂ ଃ ଅ ଆ ଇ ଈ ଉ ଊ ଋ ଌ ଏ ଐ ଓ ଔ କ ଖ ଗ ଘ ଙ ଚ ଛ ଜ ଝ ଞ ଟ ଠ ଡ ଢ ଣ ତ ଥ ଦ ଧ ନ ପ ଫ ବ ଭ ମ ଯ ର ଲ ଳ ଶ ଷ ସ ହ ଼ ଽ ା ି ୀ ୁ ୂ ୃ େ ୈ ୋ ୌ ୍ ୖ ୗ ଡ଼ ଢ଼ ୟ ୠ ୡ ୦ ୧ ୨ ୩ ୪ ୫ ୬ ୭ ୮ ୯ ୰
Tamil
ஂ ஃ அ ஆ இ ஈ உ ஊ எ ஏ ஐ ஒ ஓ ஔ க ங ச ஜ ஞ ட ண த ந ன ப ம ய ர ற ல ள ழ வ ஷ ஸ ஹ ா ி ீ ு ூ ெ ே ை ொ ோ ௌ ் ௗ ௧ ௨ ௩ ௪ ௫ ௬ ௭ ௮ ௯ ௰ ௱ ௲
Telugu
ఁ ం ః అ ఆ ఇ ఈ ఉ ఊ ఋ ఌ ఎ ఏ ఐ ఒ ఓ ఔ క ఖ గ ఘ ఙ చ ఛ జ ఝ ఞ ట ఠ డ ఢ ణ త థ ద ధ న ప ఫ బ భ మ య ర ఱ ల ళ వ శ ష స హ ా ి ీ ు ూ ృ ౄ ె ే ై ొ ో ౌ ్ ౕ ౖ ౠ ౡ ౦ ౧ ౨ ౩ ౪ ౫ ౬ ౭ ౮ ౯
Kannada
ಂ ಃ ಅ ಆ ಇ ಈ ಉ ಊ ಋ ಌ ಎ ಏ ಐ ಒ ಓ ಔ ಕ ಖ ಗ ಘ ಙ ಚ ಛ ಜ ಝ ಞ ಟ ಠ ಡ ಢ ಣ ತ ಥ ದ ಧ ನ ಪ ಫ ಬ ಭ ಮ ಯ ರ ಱ ಲ ಳ ವ ಶ ಷ ಸ ಹ ಾ ಿ ೀ ು ೂ ೃ ೄ ೆ ೇ ೈ ೊ ೋ ೌ ್ ೕ ೖ ೞ ೠ ೡ ೦ ೧ ೨ ೩ ೪ ೫ ೬ ೭ ೮ ೯
Malayalam
ം ഃ അ ആ ഇ ഈ ഉ ഊ ഋ ഌ എ ഏ ഐ ഒ ഓ ഔ ക ഖ ഗ ഘ ങ ച ഛ ജ ഝ ഞ ട ഠ ഡ ഢ ണ ത ഥ ദ ധ ന പ ഫ ബ ഭ മ യ ര റ ല ള ഴ വ ശ ഷ സ ഹ ാ ി ീ ു ൂ ൃ െ േ ൈ ൊ ോ ൌ ് ൗ ൠ ൡ ൦ ൧ ൨ ൩ ൪ ൫ ൬ ൭ ൮ ൯
Thai
ก ข ฃ ค ฅ ฆ ง จ ฉ ช ซ ฌ ญ ฎ ฏ ฐ ฑ ฒ ณ ด ต ถ ท ธ น บ ป ผ ฝ พ ฟ ภ ม ย ร ฤ ล ฦ ว ศ ษ ส ห ฬ อ ฮ ฯ ะ ั า ำ ิ ี ึ ื ุ ู ฺ ฿ เ แ โ ใ ไ ๅ ๆ ็ ่ ้ ๊ ๋ ์ ํ ๎ ๏ ๐ ๑ ๒ ๓ ๔ ๕ ๖ ๗ ๘ ๙ ๚ ๛
Lao
ກ ຂ ຄ ງ ຈ ຊ ຍ ດ ຕ ຖ ທ ນ ບ ປ ຜ ຝ ພ ຟ ມ ຢ ຣ ລ ວ ສ ຫ ອ ຮ ຯ ະ ັ າ ຳ ິ ີ ຶ ື ຸ ູ ົ ຼ ຽ ເ ແ ໂ ໃ ໄ ໆ ່ ້ ໊ ໋ ໌ ໍ ໐ ໑ ໒ ໓ ໔ ໕ ໖ ໗ ໘ ໙ ໜ ໝ
Tibetan
ༀ ༁ ༂ ༃ ༄ ༅ ༆ ༇ ༈ ༉ ༊ ་ ༌ ། ༎ ༏ ༐ ༑ ༒ ༓ ༔ ༕ ༖ ༗ ༘ ༙ ༚ ༛ ༜ ༝ ༞ ༟ ༠ ༡ ༢ ༣ ༤ ༥ ༦ ༧ ༨ ༩ ༪ ༫ ༬ ༭ ༮ ༯ ༰ ༱ ༲ ༳ ༴ ༵ ༶ ༷ ༸ ༹ ༺ ༻ ༼ ༽ ༾ ༿ ཀ ཁ ག གྷ ང ཅ ཆ ཇ ཉ ཊ ཋ ཌ ཌྷ ཎ ཏ ཐ ད དྷ ན པ ཕ བ བྷ མ ཙ ཚ ཛ ཛྷ ཝ ཞ ཟ འ ཡ ར ལ ཤ ཥ ས ཧ ཨ ཀྵ ཱ ི ཱི ུ ཱུ ྲྀ ཷ ླྀ ཹ ེ ཻ ོ ཽ ཾ ཿ ྀ ཱྀ ྂ ྃ ྄ ྅ ྆ ྇ ...
Georgian
Ⴀ Ⴁ Ⴂ Ⴃ Ⴄ Ⴅ Ⴆ Ⴇ Ⴈ Ⴉ Ⴊ Ⴋ Ⴌ Ⴍ Ⴎ Ⴏ Ⴐ Ⴑ Ⴒ Ⴓ Ⴔ Ⴕ Ⴖ Ⴗ Ⴘ Ⴙ Ⴚ Ⴛ Ⴜ Ⴝ Ⴞ Ⴟ Ⴠ Ⴡ Ⴢ Ⴣ Ⴤ Ⴥ ა ბ გ დ ე ვ ზ თ ი კ ლ მ ნ ო პ ჟ რ ს ტ უ ფ ქ ღ ყ შ ჩ ც ძ წ ჭ ხ ჯ ჰ ჱ ჲ ჳ ჴ ჵ ჶ ჻
Hangul Jamo
ᄀ ᄁ ᄂ ᄃ ᄄ ᄅ ᄆ ᄇ ᄈ ᄉ ᄊ ᄋ ᄌ ᄍ ᄎ ᄏ ᄐ ᄑ ᄒ ᄓ ᄔ ᄕ ᄖ ᄗ ᄘ ᄙ ᄚ ᄛ ᄜ ᄝ ᄞ ᄟ ᄠ ᄡ ᄢ ᄣ ᄤ ᄥ ᄦ ᄧ ᄨ ᄩ ᄪ ᄫ ᄬ ᄭ ᄮ ᄯ ᄰ ᄱ ᄲ ᄳ ᄴ ᄵ ᄶ ᄷ ᄸ ᄹ ᄺ ᄻ ᄼ ᄽ ᄾ ᄿ ᅀ ᅁ ᅂ ᅃ ᅄ ᅅ ᅆ ᅇ ᅈ ᅉ ᅊ ᅋ ᅌ ᅍ ᅎ ᅏ ᅐ ᅑ ᅒ ᅓ ᅔ ᅕ ᅖ ᅗ ᅘ ᅙ ᅟ ᅠ ᅡ ᅢ ᅣ ᅤ ᅥ ᅦ ᅧ ᅨ ᅩ ᅪ ᅫ ᅬ ᅭ ᅮ ᅯ ᅰ ᅱ ᅲ ᅳ ᅴ ᅵ ᅶ ᅷ ᅸ ᅹ ᅺ ᅻ ᅼ ᅽ ᅾ ᅿ ᆀ ᆁ ᆂ ᆃ ᆄ ...
Latin Extended Additional
Ḁ ḁ Ḃ ḃ Ḅ ḅ Ḇ ḇ Ḉ ḉ Ḋ ḋ Ḍ ḍ Ḏ ḏ Ḑ ḑ Ḓ ḓ Ḕ ḕ Ḗ ḗ Ḙ ḙ Ḛ ḛ Ḝ ḝ Ḟ ḟ Ḡ ḡ Ḣ ḣ Ḥ ḥ Ḧ ḧ Ḩ ḩ Ḫ ḫ Ḭ ḭ Ḯ ḯ Ḱ ḱ Ḳ ḳ Ḵ ḵ Ḷ ḷ Ḹ ḹ Ḻ ḻ Ḽ ḽ Ḿ ḿ Ṁ ṁ Ṃ ṃ Ṅ ṅ Ṇ ṇ Ṉ ṉ Ṋ ṋ Ṍ ṍ Ṏ ṏ Ṑ ṑ Ṓ ṓ Ṕ ṕ Ṗ ṗ Ṙ ṙ Ṛ ṛ Ṝ ṝ Ṟ ṟ Ṡ ṡ Ṣ ṣ Ṥ ṥ Ṧ ṧ Ṩ ṩ Ṫ ṫ Ṭ ṭ Ṯ ṯ Ṱ ṱ Ṳ ṳ Ṵ ṵ Ṷ ṷ Ṹ ṹ Ṻ ṻ Ṽ ṽ Ṿ ṿ ...
Greek Extended
ἀ ἁ ἂ ἃ ἄ ἅ ἆ ἇ Ἀ Ἁ Ἂ Ἃ Ἄ Ἅ Ἆ Ἇ ἐ ἑ ἒ ἓ ἔ ἕ Ἐ Ἑ Ἒ Ἓ Ἔ Ἕ ἠ ἡ ἢ ἣ ἤ ἥ ἦ ἧ Ἠ Ἡ Ἢ Ἣ Ἤ Ἥ Ἦ Ἧ ἰ ἱ ἲ ἳ ἴ ἵ ἶ ἷ Ἰ Ἱ Ἲ Ἳ Ἴ Ἵ Ἶ Ἷ ὀ ὁ ὂ ὃ ὄ ὅ Ὀ Ὁ Ὂ Ὃ Ὄ Ὅ ὐ ὑ ὒ ὓ ὔ ὕ ὖ ὗ Ὑ Ὓ Ὕ Ὗ ὠ ὡ ὢ ὣ ὤ ὥ ὦ ὧ Ὠ Ὡ Ὢ Ὣ Ὤ Ὥ Ὦ Ὧ ὰ ά ὲ έ ὴ ή ὶ ί ὸ ό ὺ ύ ὼ ώ ᾀ ᾁ ᾂ ᾃ ᾄ ᾅ ᾆ ᾇ ᾈ ᾉ ᾊ ᾋ ᾌ ᾍ ...
General Punctuation
          ​ ‌ ‍ ‎ ‏ ‐ ‑ ‒ – — ― ‖ ‗ ‘ ’ ‚ ‛ “ ” „ ‟ † ‡ • ‣ ․ ‥ … ‧

 ‪ ‫ ‬ ‭ ‮ ‰ ‱ ′ ″ ‴ ‵ ‶ ‷ ‸ ‹ › ※ ‼ ‽ ‾ ‿ ⁀ ⁁ ⁂ ⁃ ⁄ ⁅ ⁆      
Superscripts and Subscripts
⁰ ⁴ ⁵ ⁶ ⁷ ⁸ ⁹ ⁺ ⁻ ⁼ ⁽ ⁾ ⁿ ₀ ₁ ₂ ₃ ₄ ₅ ₆ ₇ ₈ ₉ ₊ ₋ ₌ ₍ ₎
Currency Symbols
₠ ₡ ₢ ₣ ₤ ₥ ₦ ₧ ₨ ₩ ₪ ₫
Combining Marks for Symbols
⃐ ⃑ ⃒ ⃓ ⃔ ⃕ ⃖ ⃗ ⃘ ⃙ ⃚ ⃛ ⃜ ⃝ ⃞ ⃟ ⃠ ⃡
Letterlike Symbols
℀ ℁ ℂ ℃ ℄ ℅ ℆ ℇ ℈ ℉ ℊ ℋ ℌ ℍ ℎ ℏ ℐ ℑ ℒ ℓ ℔ ℕ № ℗ ℘ ℙ ℚ ℛ ℜ ℝ ℞ ℟ ℠ ℡ ™ ℣ ℤ ℥ Ω ℧ ℨ ℩ K Å ℬ ℭ ℮ ℯ ℰ ℱ Ⅎ ℳ ℴ ℵ ℶ ℷ ℸ
Number Forms
⅓ ⅔ ⅕ ⅖ ⅗ ⅘ ⅙ ⅚ ⅛ ⅜ ⅝ ⅞ ⅟ Ⅰ Ⅱ Ⅲ Ⅳ Ⅴ Ⅵ Ⅶ Ⅷ Ⅸ Ⅹ Ⅺ Ⅻ Ⅼ Ⅽ Ⅾ Ⅿ ⅰ ⅱ ⅲ ⅳ ⅴ ⅵ ⅶ ⅷ ⅸ ⅹ ⅺ ⅻ ⅼ ⅽ ⅾ ⅿ ↀ ↁ ↂ
Arrows
← ↑ → ↓ ↔ ↕ ↖ ↗ ↘ ↙ ↚ ↛ ↜ ↝ ↞ ↟ ↠ ↡ ↢ ↣ ↤ ↥ ↦ ↧ ↨ ↩ ↪ ↫ ↬ ↭ ↮ ↯ ↰ ↱ ↲ ↳ ↴ ↵ ↶ ↷ ↸ ↹ ↺ ↻ ↼ ↽ ↾ ↿ ⇀ ⇁ ⇂ ⇃ ⇄ ⇅ ⇆ ⇇ ⇈ ⇉ ⇊ ⇋ ⇌ ⇍ ⇎ ⇏ ⇐ ⇑ ⇒ ⇓ ⇔ ⇕ ⇖ ⇗ ⇘ ⇙ ⇚ ⇛ ⇜ ⇝ ⇞ ⇟ ⇠ ⇡ ⇢ ⇣ ⇤ ⇥ ⇦ ⇧ ⇨ ⇩ ⇪
Mathematical Operators
∀ ∁ ∂ ∃ ∄ ∅ ∆ ∇ ∈ ∉ ∊ ∋ ∌ ∍ ∎ ∏ ∐ ∑ − ∓ ∔ ∕ ∖ ∗ ∘ ∙ √ ∛ ∜ ∝ ∞ ∟ ∠ ∡ ∢ ∣ ∤ ∥ ∦ ∧ ∨ ∩ ∪ ∫ ∬ ∭ ∮ ∯ ∰ ∱ ∲ ∳ ∴ ∵ ∶ ∷ ∸ ∹ ∺ ∻ ∼ ∽ ∾ ∿ ≀ ≁ ≂ ≃ ≄ ≅ ≆ ≇ ≈ ≉ ≊ ≋ ≌ ≍ ≎ ≏ ≐ ≑ ≒ ≓ ≔ ≕ ≖ ≗ ≘ ≙ ≚ ≛ ≜ ≝ ≞ ≟ ≠ ≡ ≢ ≣ ≤ ≥ ≦ ≧ ≨ ≩ ≪ ≫ ≬ ≭ ≮ ≯ ≰ ≱ ≲ ≳ ≴ ≵ ≶ ≷ ≸ ≹ ≺ ≻ ≼ ≽ ≾ ≿ ...
Miscellaneous Technical
⌀ ⌂ ⌃ ⌄ ⌅ ⌆ ⌇ ⌈ ⌉ ⌊ ⌋ ⌌ ⌍ ⌎ ⌏ ⌐ ⌑ ⌒ ⌓ ⌔ ⌕ ⌖ ⌗ ⌘ ⌙ ⌚ ⌛ ⌜ ⌝ ⌞ ⌟ ⌠ ⌡ ⌢ ⌣ ⌤ ⌥ ⌦ ⌧ ⌨ 〈 〉 ⌫ ⌬ ⌭ ⌮ ⌯ ⌰ ⌱ ⌲ ⌳ ⌴ ⌵ ⌶ ⌷ ⌸ ⌹ ⌺ ⌻ ⌼ ⌽ ⌾ ⌿ ⍀ ⍁ ⍂ ⍃ ⍄ ⍅ ⍆ ⍇ ⍈ ⍉ ⍊ ⍋ ⍌ ⍍ ⍎ ⍏ ⍐ ⍑ ⍒ ⍓ ⍔ ⍕ ⍖ ⍗ ⍘ ⍙ ⍚ ⍛ ⍜ ⍝ ⍞ ⍟ ⍠ ⍡ ⍢ ⍣ ⍤ ⍥ ⍦ ⍧ ⍨ ⍩ ⍪ ⍫ ⍬ ⍭ ⍮ ⍯ ⍰ ⍱ ⍲ ⍳ ⍴ ⍵ ⍶ ⍷ ⍸ ⍹ ⍺
Control Pictures
␀ ␁ ␂ ␃ ␄ ␅ ␆ ␇ ␈ ␉ ␊ ␋ ␌ ␍ ␎ ␏ ␐ ␑ ␒ ␓ ␔ ␕ ␖ ␗ ␘ ␙ ␚ ␛ ␜ ␝ ␞ ␟ ␠ ␡ ␢ ␣ ␤
Optical Character Recognition
⑀ ⑁ ⑂ ⑃ ⑄ ⑅ ⑆ ⑇ ⑈ ⑉ ⑊
Enclosed Alphanumerics
① ② ③ ④ ⑤ ⑥ ⑦ ⑧ ⑨ ⑩ ⑪ ⑫ ⑬ ⑭ ⑮ ⑯ ⑰ ⑱ ⑲ ⑳ ⑴ ⑵ ⑶ ⑷ ⑸ ⑹ ⑺ ⑻ ⑼ ⑽ ⑾ ⑿ ⒀ ⒁ ⒂ ⒃ ⒄ ⒅ ⒆ ⒇ ⒈ ⒉ ⒊ ⒋ ⒌ ⒍ ⒎ ⒏ ⒐ ⒑ ⒒ ⒓ ⒔ ⒕ ⒖ ⒗ ⒘ ⒙ ⒚ ⒛ ⒜ ⒝ ⒞ ⒟ ⒠ ⒡ ⒢ ⒣ ⒤ ⒥ ⒦ ⒧ ⒨ ⒩ ⒪ ⒫ ⒬ ⒭ ⒮ ⒯ ⒰ ⒱ ⒲ ⒳ ⒴ ⒵ Ⓐ Ⓑ Ⓒ Ⓓ Ⓔ Ⓕ Ⓖ Ⓗ Ⓘ Ⓙ Ⓚ Ⓛ Ⓜ Ⓝ Ⓞ Ⓟ Ⓠ Ⓡ Ⓢ Ⓣ Ⓤ Ⓥ Ⓦ Ⓧ Ⓨ Ⓩ ⓐ ⓑ ⓒ ⓓ ⓔ ⓕ ⓖ ⓗ ⓘ ⓙ ⓚ ⓛ ⓜ ⓝ ⓞ ⓟ ...
Box Drawing
─ ━ │ ┃ ┄ ┅ ┆ ┇ ┈ ┉ ┊ ┋ ┌ ┍ ┎ ┏ ┐ ┑ ┒ ┓ └ ┕ ┖ ┗ ┘ ┙ ┚ ┛ ├ ┝ ┞ ┟ ┠ ┡ ┢ ┣ ┤ ┥ ┦ ┧ ┨ ┩ ┪ ┫ ┬ ┭ ┮ ┯ ┰ ┱ ┲ ┳ ┴ ┵ ┶ ┷ ┸ ┹ ┺ ┻ ┼ ┽ ┾ ┿ ╀ ╁ ╂ ╃ ╄ ╅ ╆ ╇ ╈ ╉ ╊ ╋ ╌ ╍ ╎ ╏ ═ ║ ╒ ╓ ╔ ╕ ╖ ╗ ╘ ╙ ╚ ╛ ╜ ╝ ╞ ╟ ╠ ╡ ╢ ╣ ╤ ╥ ╦ ╧ ╨ ╩ ╪ ╫ ╬ ╭ ╮ ╯ ╰ ╱ ╲ ╳ ╴ ╵ ╶ ╷ ╸ ╹ ╺ ╻ ╼ ╽ ╾ ╿
Block Elements
▀ ▁ ▂ ▃ ▄ ▅ ▆ ▇ █ ▉ ▊ ▋ ▌ ▍ ▎ ▏ ▐ ░ ▒ ▓ ▔ ▕
Geometric Shapes
■ □ ▢ ▣ ▤ ▥ ▦ ▧ ▨ ▩ ▪ ▫ ▬ ▭ ▮ ▯ ▰ ▱ ▲ △ ▴ ▵ ▶ ▷ ▸ ▹ ► ▻ ▼ ▽ ▾ ▿ ◀ ◁ ◂ ◃ ◄ ◅ ◆ ◇ ◈ ◉ ◊ ○ ◌ ◍ ◎ ● ◐ ◑ ◒ ◓ ◔ ◕ ◖ ◗ ◘ ◙ ◚ ◛ ◜ ◝ ◞ ◟ ◠ ◡ ◢ ◣ ◤ ◥ ◦ ◧ ◨ ◩ ◪ ◫ ◬ ◭ ◮ ◯
Miscellaneous Symbols
☀ ☁ ☂ ☃ ☄ ★ ☆ ☇ ☈ ☉ ☊ ☋ ☌ ☍ ☎ ☏ ☐ ☑ ☒ ☓ ☚ ☛ ☜ ☝ ☞ ☟ ☠ ☡ ☢ ☣ ☤ ☥ ☦ ☧ ☨ ☩ ☪ ☫ ☬ ☭ ☮ ☯ ☰ ☱ ☲ ☳ ☴ ☵ ☶ ☷ ☸ ☹ ☺ ☻ ☼ ☽ ☾ ☿ ♀ ♁ ♂ ♃ ♄ ♅ ♆ ♇ ♈ ♉ ♊ ♋ ♌ ♍ ♎ ♏ ♐ ♑ ♒ ♓ ♔ ♕ ♖ ♗ ♘ ♙ ♚ ♛ ♜ ♝ ♞ ♟ ♠ ♡ ♢ ♣ ♤ ♥ ♦ ♧ ♨ ♩ ♪ ♫ ♬ ♭ ♮ ♯
Dingbats
✁ ✂ ✃ ✄ ✆ ✇ ✈ ✉ ✌ ✍ ✎ ✏ ✐ ✑ ✒ ✓ ✔ ✕ ✖ ✗ ✘ ✙ ✚ ✛ ✜ ✝ ✞ ✟ ✠ ✡ ✢ ✣ ✤ ✥ ✦ ✧ ✩ ✪ ✫ ✬ ✭ ✮ ✯ ✰ ✱ ✲ ✳ ✴ ✵ ✶ ✷ ✸ ✹ ✺ ✻ ✼ ✽ ✾ ✿ ❀ ❁ ❂ ❃ ❄ ❅ ❆ ❇ ❈ ❉ ❊ ❋ ❍ ❏ ❐ ❑ ❒ ❖ ❘ ❙ ❚ ❛ ❜ ❝ ❞ ❡ ❢ ❣ ❤ ❥ ❦ ❧ ❶ ❷ ❸ ❹ ❺ ❻ ❼ ❽ ❾ ❿ ➀ ➁ ➂ ➃ ➄ ➅ ➆ ➇ ➈ ➉ ➊ ➋ ➌ ➍ ➎ ➏ ➐ ➑ ➒ ➓ ➔ ➘ ➙ ➚ ➛ ➜ ➝ ...
CJK Symbols and Punctuation
  、 。 〃 〄 々 〆 〇 〈 〉 《 》 「 」 『 』 【 】 〒 〓 〔 〕 〖 〗 〘 〙 〚 〛 〜 〝 〞 〟 〠 〡 〢 〣 〤 〥 〦 〧 〨 〩 〪 〫 〬 〭 〮 〯 〰 〱 〲 〳 〴 〵 〶 〷 〿
Hiragana
ぁ あ ぃ い ぅ う ぇ え ぉ お か が き ぎ く ぐ け げ こ ご さ ざ し じ す ず せ ぜ そ ぞ た だ ち ぢ っ つ づ て で と ど な に ぬ ね の は ば ぱ ひ び ぴ ふ ぶ ぷ へ べ ぺ ほ ぼ ぽ ま み む め も ゃ や ゅ ゆ ょ よ ら り る れ ろ ゎ わ ゐ ゑ を ん ゔ ゙ ゚ ゛ ゜ ゝ ゞ
Katakana
ァ ア ィ イ ゥ ウ ェ エ ォ オ カ ガ キ ギ ク グ ケ ゲ コ ゴ サ ザ シ ジ ス ズ セ ゼ ソ ゾ タ ダ チ ヂ ッ ツ ヅ テ デ ト ド ナ ニ ヌ ネ ノ ハ バ パ ヒ ビ ピ フ ブ プ ヘ ベ ペ ホ ボ ポ マ ミ ム メ モ ャ ヤ ュ ユ ョ ヨ ラ リ ル レ ロ ヮ ワ ヰ ヱ ヲ ン ヴ ヵ ヶ ヷ ヸ ヹ ヺ ・ ー ヽ ヾ
Bopomofo
ㄅ ㄆ ㄇ ㄈ ㄉ ㄊ ㄋ ㄌ ㄍ ㄎ ㄏ ㄐ ㄑ ㄒ ㄓ ㄔ ㄕ ㄖ ㄗ ㄘ ㄙ ㄚ ㄛ ㄜ ㄝ ㄞ ㄟ ㄠ ㄡ ㄢ ㄣ ㄤ ㄥ ㄦ ㄧ ㄨ ㄩ ㄪ ㄫ ㄬ
+9
View File
@@ -0,0 +1,9 @@
#define STB_SPRINTF_IMPLEMENTATION
#include "stb_sprintf.h"
#include "basic_string.cpp"
#include "basic_string16.cpp"
#include "basic_unicode.cpp"
#include "basic_alloc.cpp"
#include "basic_os.cpp"
#include "math.cpp"
#include "math_int.cpp"
+10
View File
@@ -0,0 +1,10 @@
#include "basic_head.h"
#include "basic_alloc.h"
#include "basic_array.h"
#include "basic_string.h"
#include "basic_table.h"
#include "basic_string16.h"
#include "basic_unicode.h"
#include "basic_os.h"
#include "basic_list.h"
#include "basic_math.h"
+384
View File
@@ -0,0 +1,384 @@
#if defined(USE_ADDRESS_SANITIZER)
#include <sanitizer/asan_interface.h>
#endif
#if !defined(ASAN_POISON_MEMORY_REGION)
#define MA_ASAN_POISON_MEMORY_REGION(addr, size) ((void)(addr), (void)(size))
#define MA_ASAN_UNPOISON_MEMORY_REGION(addr, size) ((void)(addr), (void)(size))
#else
#define MA_ASAN_POISON_MEMORY_REGION(addr, size) ASAN_POISON_MEMORY_REGION(addr, size)
#define MA_ASAN_UNPOISON_MEMORY_REGION(addr, size) ASAN_UNPOISON_MEMORY_REGION(addr, size)
#endif
#include <stdlib.h>
#if OS_WINDOWS
#ifndef NOMINMAX
#define NOMINMAX
#endif
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#include <windows.h>
API void *VReserve(size_t size) {
void *result = (uint8_t *)VirtualAlloc(0, size, MEM_RESERVE, PAGE_READWRITE);
return result;
}
API bool VCommit(void *p, size_t size) {
void *result = VirtualAlloc(p, size, MEM_COMMIT, PAGE_READWRITE);
return result ? true : false;
}
API bool VRelease(void *p, size_t size) {
BOOL result = VirtualFree(p, 0, MEM_RELEASE);
return result ? true : false;
}
API bool VDecommit(void *p, size_t size) {
BOOL result = VirtualFree(p, size, MEM_DECOMMIT);
return result ? true : false;
}
#elif OS_LINUX || OS_MAC
API void *VReserve(size_t size) {
void *result = mmap(0, size, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, (off_t)0);
return result == (void *)-1 ? 0 : result;
}
API bool VCommit(void *p, size_t size) {
int result = mprotect(p, size, PROT_READ | PROT_WRITE);
return result == 0;
}
API bool VRelease(void *p, size_t size) {
int result = munmap(p, size);
return result == 0;
}
API bool VDecommit(void *p, size_t size) {
mprotect(p, size, PROT_NONE);
madvise(p, size, MADV_DONTNEED);
return true;
}
#else
API void *VReserve(size_t size) {
InvalidCodepath();
return NULL;
}
API bool VCommit(void *p, size_t size) {
InvalidCodepath();
return false;
}
API bool VRelease(void *p, size_t size) {
InvalidCodepath();
return false;
}
API bool VDecommit(void *p, size_t size) {
InvalidCodepath();
return false;
}
#endif
API void *SystemAllocatorProc(void *object, int kind, void *p, size_t size) {
void *result = NULL;
if (kind == AllocatorKind_Allocate) {
result = malloc(size);
Assert(result);
} else if (kind == AllocatorKind_Deallocate) {
free(p);
} else {
InvalidCodepath();
}
return result;
}
API Allocator GetSystemAllocator() {
Allocator result = {SystemAllocatorProc};
return result;
}
API void *_AllocSize_(Allocator alo, size_t size) {
void *result = alo.proc(alo.object, AllocatorKind_Allocate, NULL, size);
memset(result, 0, size);
return result;
}
struct MemoryRecord {
size_t size;
void *addr;
char *file;
int line;
};
thread_local Array<MemoryRecord> MemoryTrackingRecord;
API void *TrackingAllocatorProc(void *object, int kind, void *p, size_t size) {
void *result = NULL;
if (kind == AllocatorKind_Allocate) {
result = malloc(size);
Add(&MemoryTrackingRecord, {size, result, LocationTraceO.file, LocationTraceO.line});
Assert(result);
} else if (kind == AllocatorKind_Deallocate) {
free(p);
bool found = false;
For(IterateInReverse(&MemoryTrackingRecord)) {
if (it.addr == p) {
found = true;
UnorderedRemove(&MemoryTrackingRecord, it);
break;
}
}
Assert(found);
} else {
InvalidCodepath();
}
return result;
}
API void TrackingAllocatorCheck() {
// For (MemoryTrackingRecord) {
// ReportConsolef("%s(%d): error: memory leak");
// }
Assert(MemoryTrackingRecord.len == 0);
}
API Allocator GetTrackingAllocator() {
Allocator result = {TrackingAllocatorProc};
return result;
}
///////////////////////////////
// Virtual Arena
API void InitArena(VirtualArena *arena, size_t reserve) {
reserve = AlignUp(reserve, PAGE_SIZE);
arena->align = DEFAULT_ALIGNMENT;
arena->data = (uint8_t *)VReserve(reserve);
if (arena->data) {
arena->reserve = reserve;
}
}
API VirtualArena *AllocArena(Allocator allocator, size_t size) {
VirtualArena *result = AllocType(allocator, VirtualArena);
result->data = (uint8_t *)AllocSize(allocator, size);
result->reserve = size;
result->commit = size;
result->align = DEFAULT_ALIGNMENT;
return result;
}
API VirtualArena *AllocArena(size_t reserve) {
VirtualArena *result = NULL;
void *data = VReserve(reserve);
if (!data) return result;
bool success = VCommit(data, PAGE_SIZE);
if (!success) {
VRelease(data, reserve);
return result;
}
result = (VirtualArena *)data;
result->data = (uint8_t *)data;
result->reserve = reserve;
result->commit = PAGE_SIZE;
result->len = result->base_len = sizeof(VirtualArena);
result->align = DEFAULT_ALIGNMENT;
return result;
}
API void *PushSize(VirtualArena *arena, size_t size) {
// base_len is used for bootstraping arenas, it denotes the
// space occupied by the arena. If len is smaller then base_len then
// we start to overwrite the arena itself - pure barbarism.
Assert(arena->len >= arena->base_len);
size_t align_offset = 0;
if (arena->align) {
align_offset = GetAlignOffset((uintptr_t)arena->data + arena->len, arena->align);
}
size_t size_with_alignment = size + align_offset;
size_t new_len = arena->len + size_with_alignment;
if (new_len > arena->commit) {
size_t new_len_aligned_to_page_size = AlignUp(new_len, PAGE_SIZE);
size_t to_commit = new_len_aligned_to_page_size - arena->commit;
size_t to_commit_clamped = ClampTop(to_commit, arena->reserve);
if (to_commit_clamped > 0) {
bool success = VCommit(arena->data + arena->commit, to_commit_clamped);
if (success) {
MA_ASAN_POISON_MEMORY_REGION(arena->data + arena->commit, to_commit_clamped);
arena->commit += to_commit_clamped;
}
}
if (new_len > arena->commit) {
return NULL;
}
}
uint8_t *result = arena->data + arena->len + align_offset;
arena->len = new_len;
MA_ASAN_UNPOISON_MEMORY_REGION(result, size);
return (void *)result;
}
API void Release(VirtualArena *arena) {
if (arena == NULL || arena->data == NULL) return;
bool zero_memory = (uint8_t *)arena != arena->data;
VRelease(arena->data, arena->reserve);
if (zero_memory) MemoryZero(arena, sizeof(VirtualArena));
}
API void PopToPos(VirtualArena *arena, size_t pos) {
// base_len is used for bootstraping arenas, it denotes the
// space occupied by the arena. If len is smaller then base_len then
// we start to overwrite the arena itself - pure barbarism.
Assert(arena->len >= arena->base_len);
pos = Clamp(pos, arena->base_len, arena->len);
size_t size = arena->len - pos;
arena->len = pos;
MA_ASAN_POISON_MEMORY_REGION(arena->data + arena->len, size);
}
API void *ArenaAllocatorProc(void *object, int kind, void *p, size_t size) {
if (kind == AllocatorKind_Allocate) {
return PushSize((VirtualArena *)object, size);
} else if (AllocatorKind_Deallocate) {
} else {
Assert(!"invalid codepath");
}
return NULL;
}
///////////////////////////////
// Block Arena
API void *PushSize(BlockArena *arena, size_t size) {
if (size > (size_t)(arena->end - arena->start)) {
size_t block_size = MiB(1);
if (size > block_size) {
block_size = size;
}
if (arena->allocator.proc == NULL) {
arena->allocator = GetSystemAllocator();
}
BlockArenaNode *new_block = (BlockArenaNode *)AllocSize(arena->allocator, block_size + sizeof(BlockArenaNode));
Assert(GetAlignOffset((size_t)new_block->start, DEFAULT_ALIGNMENT) == 0);
arena->start = new_block->start;
new_block->end = arena->end = new_block->start + block_size;
SLL_STACK_ADD(arena->blocks, new_block);
}
U8 *result = arena->start;
Assert(GetAlignOffset((size_t)result, DEFAULT_ALIGNMENT) == 0);
arena->start = (U8 *)AlignUp((size_t)(arena->start + size), DEFAULT_ALIGNMENT);
return result;
}
API void Release(BlockArena *arena) {
for (BlockArenaNode *it = arena->blocks, *next = NULL; it; it = next) {
next = it->next;
Dealloc(arena->allocator, it);
}
MemoryZero(arena, sizeof(BlockArena));
}
API void Unwind(BlockArena *arena, U8 *pos) {
bool contains = false;
for (BlockArenaNode *it = arena->blocks, *next = NULL; it; it = next) {
next = it->next;
if ((pos >= it->start) && (pos < it->end)) {
contains = true;
break;
} else {
arena->blocks = arena->blocks->next;
Dealloc(arena->allocator, it);
}
}
Assert(contains || pos == NULL);
arena->start = pos;
}
API void *BlockArenaAllocatorProc(void *object, int kind, void *p, size_t size) {
BlockArena *arena = (BlockArena *)object;
if (kind == AllocatorKind_Allocate) {
return PushSize(arena, size);
} else if (AllocatorKind_Deallocate) {
} else {
Assert(!"invalid codepath");
}
return NULL;
}
void RunArenaTest() {
Allocator memory_tracking_allocator = GetTrackingAllocator();
{
BlockArena arena = {};
arena.allocator = memory_tracking_allocator;
for (int i = 0; i < 10000; i += 1) {
int *vals = (int *)PushSize(&arena, sizeof(int)*i);
for (int j = 0; j < i; j += 1) {
vals[j] = j;
}
}
Release(&arena);
TrackingAllocatorCheck();
}
{
BlockArena arena = {};
U8 *start = arena.start;
arena.allocator = memory_tracking_allocator;
int *vals = (int *)PushSize(&arena, sizeof(int) * 32);
for (int i = 0; i < 32; i += 1) vals[i] = i;
Unwind(&arena, (U8 *)vals);
Assert(arena.blocks);
Assert(arena.blocks->next == NULL);
Assert(arena.start == (U8 *)vals);
Assert(arena.blocks[0].start == (U8 *)vals);
Unwind(&arena, NULL);
Dealloc(arena.allocator, arena.blocks);
TrackingAllocatorCheck();
}
{
BlockArena arena = {};
arena.allocator = memory_tracking_allocator;
int *vals = (int *)PushSize(&arena, sizeof(int) * 32);
for (int i = 0; i < 32; i += 1) vals[i] = i;
U8 *p = arena.start;
U8 *a = (U8 *)PushSize(&arena, KiB(32));
U8 *b = (U8 *)PushSize(&arena, KiB(1000));
Assert(arena.blocks);
Assert(arena.blocks->next);
Assert(arena.blocks->next->next == NULL);
Unwind(&arena, a);
Assert(arena.blocks);
Assert(arena.blocks->next == NULL);
Assert(arena.start == p);
Release(&arena);
TrackingAllocatorCheck();
}
{
BlockArena arena = {};
arena.allocator = memory_tracking_allocator;
U8 *a = (U8 *)PushSize(&arena, KiB(2000));
Assert((size_t)(arena.blocks[0].end - arena.blocks[0].start) == KiB(2000));
Release(&arena);
TrackingAllocatorCheck();
}
}
+116
View File
@@ -0,0 +1,116 @@
#pragma once
struct LocationTrace {
char *file;
int line;
};
#if DEBUG_BUILD
thread_local LocationTrace LocationTraceO;
#define LOCATION_TRACE (LocationTraceO.file = __FILE__, LocationTraceO.line = __LINE__)
#else
#define LOCATION_TRACE
#endif
const int AllocatorKind_Allocate = 1;
const int AllocatorKind_Deallocate = 2;
struct Allocator {
void *(*proc)(void *object, int kind, void *p, size_t size);
void *object;
};
#define AllocType(alo, Type) (Type *)AllocSize(alo, sizeof(Type))
#define AllocArray(alo, Type, count) (Type *)AllocSize(alo, sizeof(Type) * (count))
#define AllocSize(alo, size) (LOCATION_TRACE, _AllocSize_(alo, size))
API void *_AllocSize_(Allocator alo, size_t size);
inline void Dealloc(Allocator alo, void *p) { if (p) (alo).proc((alo).object, AllocatorKind_Deallocate, (p), 0); }
API Allocator GetSystemAllocator();
API void TrackingAllocatorCheck();
API Allocator GetTrackingAllocator();
#define MemoryZero(x, size) memset(x, 0, size)
#define MemoryZeroStruct(x) memset(x, 0, sizeof(*x))
#define MemoryCopy(dst, src, size) memcpy(dst, src, size)
#define MemoryMove(dst, src, size) memmove(dst, src, size)
///////////////////
// Block Arena
///////////////////
API void *BlockArenaAllocatorProc(void *object, int kind, void *p, size_t size);
struct BlockArenaNode {
BlockArenaNode *next;
U8 *end;
U8 start[0];
};
struct BlockArena {
U8 *start;
U8 *end;
BlockArenaNode *blocks;
Allocator allocator;
operator Allocator() { return {BlockArenaAllocatorProc, this}; }
};
API void *PushSize(BlockArena *arena, size_t size);
API void Release(BlockArena *arena);
API void Unwind(BlockArena *arena, U8 *pos);
///////////////////
// Virtual Arena
///////////////////
struct VirtualArena {
uint8_t *data;
size_t len;
size_t base_len; // to prevent self deleting the arena
size_t reserve;
size_t commit;
size_t align;
operator Allocator() {
void *ArenaAllocatorProc(void *object, int kind, void *p, size_t size);
return {ArenaAllocatorProc, this};
}
};
inline void SetLen(VirtualArena *arena, size_t len) { arena->len = Clamp(len, arena->base_len, arena->len); }
inline void Pop(VirtualArena *arena, size_t size) { SetLen(arena, arena->len - size); }
inline void Clear(VirtualArena *arena) { SetLen(arena, 0); }
API void *VReserve(size_t size);
API bool VCommit(void *p, size_t size);
API bool VRelease(void *p, size_t size);
API bool VDecommit(void *p, size_t size);
API void InitArena(VirtualArena *arena, size_t reserve = MiB(256));
API VirtualArena *AllocArena(size_t reserve = MiB(256));
API VirtualArena *AllocArena(Allocator allocator, size_t size);
API void *PushSize(VirtualArena *arena, size_t size);
API void Release(VirtualArena *arena);
///////////////////////////////
// Scratch
struct Scratch {
BlockArena arena = {};
Scratch() {}
Scratch(BlockArena *conflict) {}
Scratch(BlockArena *c1, BlockArena *c2) {}
Scratch(Allocator conflict) {}
Scratch(Allocator c1, Allocator c2) {}
~Scratch() { Release(&arena); }
operator BlockArena *() { return &arena; }
operator Allocator() { return arena; }
private: // @Note: Disable copy constructors, cause its error prone
Scratch(Scratch &arena);
Scratch(Scratch &arena, Scratch &a2);
};
const int PAGE_SIZE = 4096;
const int DEFAULT_ALIGNMENT = sizeof(void *);
+500
View File
@@ -0,0 +1,500 @@
#pragma once
/*
// Iterating and removing elements
for (int i = 0; i < array.len; i += 1) {
auto &it = array[i];
bool remove_item = false;
defer {
if (remove_item) {
array.ordered_remove(it);
i -= 1;
}
}
}
// Simple delete
IterRemove(arr) {
IterRemovePrepare(arr);
remove_item = true;
}
// Deleting backwards
For(arr.reverse_iter()) {
defer{ arr.unordered_remove(it); };
}
*/
#define IterRemove(a) for (int i = 0; i < (a).len; i += 1)
#define IterRemovePrepare(a) \
auto &it = (a)[i]; \
bool remove_item = false; \
defer { \
if (remove_item) { \
Remove(&(a), it); \
i -= 1; \
} \
}
#define ForItem(it, array) for (auto &it : (array))
#define For(array) ForItem(it, array)
template <class T>
struct Slice {
T *data;
int64_t len;
Slice() = default;
Slice(T *s, int64_t l) : data(s), len(l) {}
T &operator[](int64_t index) {
Assert(index < len);
return data[index];
}
T *begin() { return data; }
T *end() { return data + len; }
};
template <class T>
Slice<T> Copy(Allocator alo, Slice<T> array) {
Slice<T> result = {};
result.data = AllocArray(alo, T, array.len);
memcpy(result.data, array.data, sizeof(T) * array.len);
result.len = array.len;
return result;
}
template <class T>
T Pop(Slice<T> *arr) {
Assert(arr->len > 0);
return arr->data[--arr->len];
}
template <class T>
bool Contains(Slice<T> &arr, T item) {
For(arr) if (it == item) return true;
return false;
}
template <class T>
int64_t GetIndex(Slice<T> &arr, const T &item) {
ptrdiff_t index = (ptrdiff_t)(&item - arr.data);
Assert(index >= 0 && index < arr.len);
return (int64_t)index;
}
template <class T>
T Get(Slice<T> &arr, int64_t i, T default_value = {}) {
T result = default_value;
if (i >= 0 && i < arr.len) result = arr[i];
return result;
}
template <class T>
bool IsLast(Slice<T> &arr, T &item) {
bool result = arr.last() == &item;
return result;
}
template <class T>
bool IsFirst(Slice<T> &arr, T &item) {
bool result = arr.first() == &item;
return result;
}
template <class T>
T *GetFirst(Slice<T> &arr) {
Assert(arr.len > 0);
return arr.data;
}
template <class T>
T *GetLast(Slice<T> &arr) {
Assert(arr.len > 0);
return arr.data + arr.len - 1;
}
template <class T>
Slice<T> Chop(Slice<T> &arr, int64_t len) {
len = ClampTop(len, arr.len);
Slice<T> result = {arr.data, arr.len - len};
return result;
}
template <class T>
Slice<T> Skip(Slice<T> &arr, int64_t len) {
len = ClampTop(len, arr.len);
Slice<T> result = {arr.data + len, arr.len - len};
return result;
}
template <class T>
Slice<T> GetPostfix(Slice<T> &arr, int64_t len) {
len = ClampTop(len, arr.len);
int64_t remain_len = arr.len - len;
Slice<T> result = {arr.data + remain_len, len};
return result;
}
template <class T>
Slice<T> GetPrefix(Slice<T> &arr, int64_t len) {
len = ClampTop(len, arr.len);
Slice<T> result = {arr.data, len};
return result;
}
template <class T>
Slice<T> GetSlice(Slice<T> &arr, int64_t first_index = 0, int64_t one_past_last_index = SLICE_LAST) {
// Negative indexes work in python style, they return you the index counting from end of list
if (one_past_last_index == SLICE_LAST) one_past_last_index = arr.len;
if (one_past_last_index < 0) one_past_last_index = arr.len + one_past_last_index;
if (first_index == SLICE_LAST) first_index = arr.len;
if (first_index < 0) first_index = arr.len + first_index;
Slice<T> result = {arr.data, arr.len};
if (arr.len > 0) {
if (one_past_last_index > first_index) {
first_index = ClampTop(first_index, arr.len - 1);
one_past_last_index = ClampTop(one_past_last_index, arr.len);
result.data += first_index;
result.len = one_past_last_index - first_index;
} else {
result.len = 0;
}
}
return result;
}
// Make arrays resize on every item
#define ARRAY_DEBUG 0
#if ARRAY_DEBUG
#define ARRAY_IF_DEBUG_ELSE(IF, ELSE) IF
#else
#define ARRAY_IF_DEBUG_ELSE(IF, ELSE) ELSE
#endif
template <class T>
struct Array {
Allocator allocator;
int64_t cap;
union {
Slice<T> slice;
struct {
T *data;
int64_t len;
};
};
T &operator[](int64_t index) {
Assert(index >= 0 && index < len);
return data[index];
}
T *begin() { return data; }
T *end() { return data + len; }
};
template <class T>
T *GetFirst(Array<T> &arr) {
Assert(arr.len > 0);
return arr.data;
}
template <class T>
T *GetLast(Array<T> &arr) {
Assert(arr.len > 0);
return arr.data + arr.len - 1;
}
template <class T>
void Reserve(Array<T> *arr, int64_t size) {
if (size > arr->cap) {
if (!arr->allocator.proc) arr->allocator = GetSystemAllocator();
T *new_data = AllocArray(arr->allocator, T, size);
Assert(new_data);
memcpy(new_data, arr->data, arr->len * sizeof(T));
Dealloc(arr->allocator, arr->data);
arr->data = new_data;
arr->cap = size;
}
}
template <class T>
void TryGrowing(Array<T> *arr) {
if (arr->len + 1 > arr->cap) {
int64_t initial_size = (int64_t)ARRAY_IF_DEBUG_ELSE(1, 16);
int64_t new_size = ClampBottom(initial_size, arr->cap ARRAY_IF_DEBUG_ELSE(+1, *2));
Reserve(arr, new_size);
}
}
template <class T>
void TryGrowing(Array<T> *arr, int64_t item_count) {
if (arr->len + item_count > arr->cap) {
int64_t initial_size = (int64_t)ARRAY_IF_DEBUG_ELSE(1, 16);
int64_t new_size = ClampBottom(initial_size, (arr->cap + item_count) ARRAY_IF_DEBUG_ELSE(+1, *2));
Reserve(arr, new_size);
}
}
template <class T>
void Add(Array<T> *arr, T item) {
TryGrowing(arr);
arr->data[arr->len++] = item;
}
template <class T>
void Add(Array<T> *arr, Array<T> &another) {
For(another) Add(arr, it);
}
template <class T>
void Add(Array<T> *arr, T *items, int64_t item_count) {
for (int64_t i = 0; i < item_count; i += 1) Add(arr, items[i]);
}
template <class T>
void BoundedAdd(Array<T> *arr, T item) {
if (arr->len + 1 <= arr->cap) arr->data[arr->len++] = item;
}
template <class T>
void BoundedAddError(Array<T> *arr, T item) {
Assert(arr->len + 1 <= arr->cap);
if (arr->len + 1 <= arr->cap) arr->data[arr->len++] = item;
}
template <class T>
void Insert(Array<T> *arr, T item, int64_t index) {
if (index == arr->len) {
Add(arr, item);
return;
}
Assert(index < arr->len);
Assert(index >= 0);
TryGrowing(arr);
int64_t right_len = arr->len - index;
memmove(arr->data + index + 1, arr->data + index, sizeof(T) * right_len);
arr->data[index] = item;
arr->len += 1;
}
template <class T>
Array<T> Copy(Allocator alo, Array<T> array) {
Array<T> result = {alo};
Reserve(&result, array.cap);
memcpy(result.data, array.data, sizeof(T) * array.len);
result.len = array.len;
return result;
}
template <class T>
Array<T> TightCopy(Allocator alo, Array<T> array) {
Array<T> result = {alo};
Reserve(&result, array.len);
memcpy(result.data, array.data, sizeof(T) * array.len);
result.len = array.len;
return result;
}
template <class T>
T Pop(Array<T> *arr) {
Assert(arr->len > 0);
return arr->data[--arr->len];
}
template <class T>
bool Contains(Array<T> &arr, T item) {
For(arr) if (it == item) return true;
return false;
}
template <class T>
int64_t GetIndex(Array<T> &arr, const T &item) {
ptrdiff_t index = (ptrdiff_t)(&item - arr.data);
Assert(index >= 0 && index < arr.len);
return (int64_t)index;
}
template <class T>
void RemoveByIndex(Array<T> *arr, int64_t index) {
Assert(index >= 0 && index < arr->len);
int64_t right_len = arr->len - index - 1;
memmove(arr->data + index, arr->data + index + 1, right_len * sizeof(T));
arr->len -= 1;
}
template <class T>
void RemoveManyByIndex(Array<T> *arr, int64_t index, int64_t count) {
if (count == 0) return;
Assert(index >= 0 && index < arr->len);
Assert((index + count) > 0 && (index + count) <= arr->len);
int64_t right_len = arr->len - index - count;
memmove(arr->data + index, arr->data + index + count, right_len * sizeof(T));
arr->len -= count;
}
template <class T>
void RemoveMany(Array<T> *arr, T &item, int64_t count) {
Assert(arr->len > 0);
Assert(&item >= arr->begin() && &item < arr->end());
int64_t index = GetIndex(*arr, item);
RemoveManyByIndex(arr, index, count);
}
template <class T>
void Remove(Array<T> *arr, T &item) {
Assert(arr->len > 0);
Assert(&item >= arr->begin() && &item < arr->end());
int64_t index = GetIndex(*arr, item);
RemoveByIndex(arr, index);
}
template <class T>
void UnorderedRemove(Array<T> *arr, T &item) {
Assert(arr->len > 0);
Assert((&item >= arr->begin()) && (&item < arr->end()));
item = arr->data[--arr->len];
}
template <class T>
void UnorderedRemoveByIndex(Array<T> *arr, int64_t index) {
Assert(arr->len > 0);
Assert(index >= 0 && index < arr->len);
arr->data[index] = arr->data[--arr->len];
}
template <class T>
void InsertArray(Array<T> *arr, T *items, int64_t count, int64_t index) {
if (index == arr->len) {
Add(arr, items, count);
return;
}
Assert(index < arr->len);
TryGrowing(arr, count);
T *gap_begin = arr->data + index;
T *gap_end = gap_begin + count;
int64_t item_count = arr->len - index;
memmove(gap_end, gap_begin, item_count * sizeof(T));
for (int64_t i = 0; i < count; i += 1) arr->data[index + i] = items[i];
arr->len += count;
}
template <class T>
T Get(Array<T> &arr, int64_t i, T default_value = {}) {
T result = default_value;
if (i >= 0 && i < arr.len) result = arr[i];
return result;
}
template <class T>
void Dealloc(Array<T> *arr) {
if (arr->data) {
Dealloc(arr->allocator, arr->data);
arr->data = NULL;
}
arr->len = arr->cap = 0;
}
template <class T>
bool IsLast(Array<T> &arr, T &item) {
bool result = GetLast(arr) == &item;
return result;
}
template <class T>
bool IsFirst(Array<T> &arr, T &item) {
bool result = GetFirst(arr) == &item;
return result;
}
template <class T>
Slice<T> Chop(Array<T> &arr, int64_t len) {
len = ClampTop(len, arr.len);
Slice<T> result = {arr.data, arr.len - len};
return result;
}
template <class T>
Slice<T> Skip(Array<T> &arr, int64_t len) {
len = ClampTop(len, arr.len);
Slice<T> result = {arr.data + len, arr.len - len};
return result;
}
template <class T>
Slice<T> GetPostfix(Array<T> &arr, int64_t len) {
len = ClampTop(len, arr.len);
int64_t remain_len = arr.len - len;
Slice<T> result = {arr.data + remain_len, len};
return result;
}
template <class T>
Slice<T> GetPrefix(Array<T> &arr, int64_t len) {
len = ClampTop(len, arr.len);
Slice<T> result = {arr.data, len};
return result;
}
template <class T>
Slice<T> GetSlice(Array<T> &arr, int64_t first_index = 0, int64_t one_past_last_index = SLICE_LAST) {
// Negative indexes work in python style, they return you the index counting from end of list
if (one_past_last_index == SLICE_LAST) one_past_last_index = arr.len;
if (one_past_last_index < 0) one_past_last_index = arr.len + one_past_last_index;
if (first_index == SLICE_LAST) first_index = arr.len;
if (first_index < 0) first_index = arr.len + first_index;
Slice<T> result = {arr.data, arr.len};
if (arr.len > 0) {
if (one_past_last_index > first_index) {
first_index = ClampTop(first_index, arr.len - 1);
one_past_last_index = ClampTop(one_past_last_index, arr.len);
result.data += first_index;
result.len = one_past_last_index - first_index;
} else {
result.len = 0;
}
}
return result;
}
template <class T>
struct ReverseIter {
T *data;
Slice<T> *arr;
ReverseIter operator++(int) {
ReverseIter ret = *this;
data -= 1;
return ret;
}
ReverseIter &operator++() {
data -= 1;
return *this;
}
T &operator*() { return data[0]; }
T *operator->() { return data; }
friend bool operator==(const ReverseIter &a, const ReverseIter &b) { return a.data == b.data; };
friend bool operator!=(const ReverseIter &a, const ReverseIter &b) { return a.data != b.data; };
ReverseIter begin() { return ReverseIter{arr->end() - 1, arr}; }
ReverseIter end() { return ReverseIter{arr->begin() - 1, arr}; }
};
template <class T>
ReverseIter<T> IterateInReverse(Array<T> *arr) {
return {arr->end() - 1, &arr->slice};
}
template <class T>
ReverseIter<T> IterateInReverse(Slice<T> *slice) {
return {slice->end() - 1, slice};
}
+215
View File
@@ -0,0 +1,215 @@
#pragma once
#ifndef _CRT_SECURE_NO_WARNINGS
#define _CRT_SECURE_NO_WARNINGS
#endif
#include <stdint.h>
#include <string.h>
#include <stdarg.h>
#include <signal.h>
#include <stddef.h>
#if defined(__APPLE__) && defined(__MACH__)
#define OS_POSIX 1
#define OS_MAC 1
#elif defined(_WIN32)
#define OS_WINDOWS 1
#elif defined(__linux__)
#define OS_POSIX 1
#define OS_LINUX 1
#elif defined(__EMSCRIPTEN__)
#define OS_WASM 1
#else
#error Unsupported platform
#endif
#if defined(__clang__)
#define COMPILER_CLANG 1
#elif defined(__GNUC__) || defined(__GNUG__)
#define COMPILER_GCC 1
#elif defined(_MSC_VER)
#define COMPILER_MSVC 1
#else
#error Unsupported compiler
#endif
#ifndef OS_WASM
#define OS_WASM 0
#endif
#ifndef OS_MAC
#define OS_MAC 0
#endif
#ifndef OS_WINDOWS
#define OS_WINDOWS 0
#endif
#ifndef OS_LINUX
#define OS_LINUX 0
#endif
#ifndef OS_POSIX
#define OS_POSIX 0
#endif
#ifndef COMPILER_MSVC
#define COMPILER_MSVC 0
#endif
#ifndef COMPILER_CLANG
#define COMPILER_CLANG 0
#endif
#ifndef COMPILER_GCC
#define COMPILER_GCC 0
#endif
#if OS_WINDOWS
#define BREAK() __debugbreak()
#elif OS_LINUX
#define BREAK() raise(SIGTRAP)
#elif OS_WASM
#include <emscripten.h>
EM_JS(void, JS_Breakpoint, (), {
debugger;
})
#define BREAK() JS_Breakpoint()
#endif
#define API
#define Assert(x) \
if (!(x)) { \
BREAK(); \
}
#define InvalidCodepath() Assert(!"invalid codepath")
#define ElseInvalidCodepath() else {InvalidCodepath()}
#define KiB(x) ((x##ull) * 1024ull)
#define MiB(x) (KiB(x) * 1024ull)
#define GiB(x) (MiB(x) * 1024ull)
#define TiB(x) (GiB(x) * 1024ull)
#define Lengthof(x) ((int64_t)((sizeof(x) / sizeof((x)[0]))))
#define SLICE_LAST INT64_MAX
using U8 = uint8_t;
using U16 = uint16_t;
using U32 = uint32_t;
using U64 = uint64_t;
using S8 = int8_t;
using S16 = int16_t;
using S32 = int32_t;
using S64 = int64_t;
using Int = S64;
using UInt = U64;
template <class T>
T Min(T a, T b) {
if (a > b) return b;
return a;
}
template <class T>
T ClampTop(T a, T top) {
return Min(a, top);
}
template <class T>
T Max(T a, T b) {
if (a > b) return a;
return b;
}
template <class T>
T ClampBottom(T bottom, T b) {
return Max(bottom, b);
}
template <class T>
T Clamp(T value, T min, T max) {
if (value < min) return min;
if (value > max) return max;
return value;
}
template <class T>
void Swap(T *a, T *b) {
T temp = *a;
*a = *b;
*b = temp;
}
inline bool IsPowerOf2(size_t x) {
size_t result = (((x) & ((x)-1)) == 0);
return result;
}
inline size_t WrapAroundPowerOf2(size_t x, size_t pow2) {
Assert(IsPowerOf2(pow2));
size_t result = (((x) & ((pow2)-1llu)));
return result;
}
inline uint64_t HashBytes(void *data, unsigned size) {
uint8_t *data8 = (uint8_t *)data;
uint64_t hash = (uint64_t)14695981039346656037ULL;
for (unsigned i = 0; i < size; i++) {
hash = hash ^ (uint64_t)(data8[i]);
hash = hash * (uint64_t)1099511628211ULL;
}
return hash;
}
inline size_t GetAlignOffset(size_t size, size_t align) {
Assert(IsPowerOf2(align));
size_t mask = align - 1;
size_t val = size & mask;
if (val) {
val = align - val;
}
return val;
}
inline size_t AlignUp(size_t size, size_t align) {
size_t result = size + GetAlignOffset(size, align);
return result;
}
inline size_t AlignDown(size_t size, size_t align) {
size += 1; // Make sure when align is 8 doesn't get rounded down to 0
size_t result = size - (align - GetAlignOffset(size, align));
return result;
}
template <typename T>
struct DEFER_ExitScope {
T lambda;
DEFER_ExitScope(T lambda) : lambda(lambda) {}
~DEFER_ExitScope() { lambda(); }
DEFER_ExitScope(const DEFER_ExitScope &i) : lambda(i.lambda){};
private:
DEFER_ExitScope &operator=(const DEFER_ExitScope &);
};
class DEFER_ExitScopeHelp {
public:
template <typename T>
DEFER_ExitScope<T> operator+(T t) { return t; }
};
#define DEFER_CONCAT_INTERNAL(x, y) x##y
#define DEFER_CONCAT(x, y) DEFER_CONCAT_INTERNAL(x, y)
#define defer const auto DEFER_CONCAT(defer__, __LINE__) = DEFER_ExitScopeHelp() + [&]()
struct RandomSeed {
uint64_t a;
};
inline uint64_t GetRandomU64(RandomSeed *state) {
uint64_t x = state->a;
x ^= x << 13;
x ^= x >> 7;
x ^= x << 17;
return state->a = x;
}
+117
View File
@@ -0,0 +1,117 @@
#pragma once
#define SLL_QUEUE_ADD_MOD(f, l, n, next) \
do { \
(n)->next = 0; \
if ((f) == 0) { \
(f) = (l) = (n); \
} else { \
(l) = (l)->next = (n); \
} \
} while (0)
#define SLL_QUEUE_ADD(f, l, n) SLL_QUEUE_ADD_MOD(f, l, n, next)
#define SLL_QUEUE_POP_FIRST_MOD(f, l, next) \
do { \
if ((f) == (l)) { \
(f) = (l) = 0; \
} else { \
(f) = (f)->next; \
} \
} while (0)
#define SLL_QUEUE_POP_FIRST(f, l) SLL_QUEUE_POP_FIRST_MOD(f, l, next)
#define SLL_STACK_ADD_MOD(stack_base, new_stack_base, next) \
do { \
(new_stack_base)->next = (stack_base); \
(stack_base) = (new_stack_base); \
} while (0)
#define SLL_STACK_ADD(stack_base, new_stack_base) \
SLL_STACK_ADD_MOD(stack_base, new_stack_base, next)
#define SLL_STACK_POP_AND_STORE(stack_base, out_node) \
do { \
if (stack_base) { \
(out_node) = (stack_base); \
(stack_base) = (stack_base)->next; \
(out_node)->next = 0; \
} \
} while (0)
#define DLL_QUEUE_ADD_MOD(f, l, node, next, prev) \
do { \
if ((f) == 0) { \
(f) = (l) = (node); \
(node)->prev = 0; \
(node)->next = 0; \
} else { \
(l)->next = (node); \
(node)->prev = (l); \
(node)->next = 0; \
(l) = (node); \
} \
} while (0)
#define DLL_QUEUE_ADD(f, l, node) DLL_QUEUE_ADD_MOD(f, l, node, next, prev)
#define DLL_QUEUE_ADD_FRONT(f, l, node) DLL_QUEUE_ADD_MOD(l, f, node, prev, next)
#define DLL_QUEUE_REMOVE_MOD(first, last, node, next, prev) \
do { \
if ((first) == (last)) { \
(first) = (last) = 0; \
} else if ((last) == (node)) { \
(last) = (last)->prev; \
(last)->next = 0; \
} else if ((first) == (node)) { \
(first) = (first)->next; \
(first)->prev = 0; \
} else { \
(node)->prev->next = (node)->next; \
(node)->next->prev = (node)->prev; \
} \
if (node) { \
(node)->prev = 0; \
(node)->next = 0; \
} \
} while (0)
#define DLL_QUEUE_REMOVE(first, last, node) DLL_QUEUE_REMOVE_MOD(first, last, node, next, prev)
#define DLL_STACK_ADD_MOD(first, node, next, prev) \
do { \
(node)->next = (first); \
if ((first)) \
(first)->prev = (node); \
(first) = (node); \
(node)->prev = 0; \
} while (0)
#define DLL_STACK_ADD(first, node) DLL_STACK_ADD_MOD(first, node, next, prev)
#define DLL_STACK_REMOVE_MOD(first, node, next, prev) \
do { \
if ((node) == (first)) { \
(first) = (first)->next; \
if ((first)) \
(first)->prev = 0; \
} else { \
(node)->prev->next = (node)->next; \
if ((node)->next) \
(node)->next->prev = (node)->prev; \
} \
if (node) { \
(node)->prev = 0; \
(node)->next = 0; \
} \
} while (0)
#define DLL_STACK_REMOVE(first, node) DLL_STACK_REMOVE_MOD(first, node, next, prev)
#define DLL_INSERT_NEXT_MOD(base, new, next, prev) \
do { \
if ((base) == 0) { \
(base) = (new); \
(new)->next = 0; \
(new)->prev = 0; \
} else { \
(new)->next = (base)->next; \
(base)->next = (new); \
(new)->prev = (base); \
if ((new)->next) (new)->next->prev = (new); \
} \
} while (0)
#define DLL_INSERT_NEXT(base, new) DLL_INSERT_NEXT_MOD(base, new, next, prev)
#define DLL_INSERT_PREV(base, new) DLL_INSERT_NEXT_MOD(base, new, next, prev)
+62
View File
@@ -0,0 +1,62 @@
#pragma once
#include <math.h>
struct Vec2 {
float x;
float y;
};
union Vec4 {
struct {
float x;
float y;
float z;
float w;
};
struct {
float r;
float g;
float b;
float a;
};
};
union Vec3 {
struct {
float x;
float y;
float z;
};
struct {
float r;
float g;
float b;
};
};
struct Rect2 {
Vec2 min;
Vec2 max;
};
struct Vec2I {
Int x;
Int y;
};
struct Rect2I {
Vec2I min;
Vec2I max;
};
union Color {
struct {
uint8_t r;
uint8_t g;
uint8_t b;
uint8_t a;
};
uint32_t value;
};
#define PI32 3.14159265359f
File diff suppressed because it is too large Load Diff
+61
View File
@@ -0,0 +1,61 @@
#pragma once
struct FileIter {
bool is_valid;
bool is_directory;
String absolute_path;
String relative_path;
String filename;
String path;
Allocator allocator;
union {
struct Win32_FileIter *w32;
void *dir;
};
};
String ReadFile(Allocator arena, String path);
bool WriteFile(String path, String data);
String GetAbsolutePath(Allocator arena, String relative);
bool IsValid(const FileIter &it);
void Advance(FileIter *it);
FileIter IterateFiles(Allocator allocator, String path);
void InitOS(void (*error_proc)(const char *, ...));
bool DeleteFile(String path);
String GetExePath(Allocator allocator);
String GetExeDir(Allocator allocator);
bool FileExists(String path);
bool IsDir(String path);
bool IsFile(String path);
String GetWorkingDir(Allocator arena);
bool IsAbsolute(String path);
int64_t GetFileModTime(String file);
struct Process {
bool is_valid;
int exit_code;
char platform[6 * 8];
int64_t id;
int64_t view_id; // text editor view
bool scroll_to_end;
};
Process SpawnProcess(String command_line, String working_dir, String write_stdin = {}, Array<String> enviroment = {});
bool IsValid(Process *process);
void KillProcess(Process *process);
String PollStdout(Allocator allocator, Process *process, bool force_read);
void WriteStdin(Process *process, String string);
void CloseStdin(Process *process);
double GetTimeMicros(void);
enum MakeDirResult {
MakeDirResult_Success,
MakeDirResult_Exists,
MakeDirResult_NotFound,
MakeDirResult_ErrorOther,
};
MakeDirResult MakeDir(String path);
+336
View File
@@ -0,0 +1,336 @@
API char ToLowerCase(char a) {
if (a >= 'A' && a <= 'Z') a += 32;
return a;
}
API char ToUpperCase(char a) {
if (a >= 'a' && a <= 'z') a -= 32;
return a;
}
API bool IsWhitespace(char w) {
bool result = w == '\n' || w == ' ' || w == '\t' || w == '\v' || w == '\r';
return result;
}
API bool IsAlphabetic(char a) {
bool result = (a >= 'a' && a <= 'z') || (a >= 'A' && a <= 'Z');
return result;
}
API bool IsIdent(char a) {
bool result = (a >= 'a' && a <= 'z') || (a >= 'A' && a <= 'Z') || a == '_';
return result;
}
API bool IsDigit(char a) {
bool result = a >= '0' && a <= '9';
return result;
}
API bool IsAlphanumeric(char a) {
bool result = IsDigit(a) || IsAlphabetic(a);
return result;
}
API bool IsSymbol(char w) {
bool result = (w >= '!' && w <= '/') || (w >= ':' && w <= '@') || (w >= '[' && w <= '`') || (w >= '{' && w <= '~');
return result;
}
API bool IsNonWord(char w) {
if (w == '_') return false;
bool result = IsSymbol(w) || IsWhitespace(w);
return result;
}
API bool IsWord(char w) {
bool result = !IsNonWord(w);
return result;
}
API bool IsBrace(char c) {
bool result = c == '{' || c == '}';
return result;
}
API bool IsParen(char c) {
bool result = c == '(' || c == ')';
return result;
}
API String Chop(String a, int64_t len) {
len = ClampTop(len, a.len);
String result = {a.data, a.len - len};
return result;
}
API String Skip(String a, int64_t len) {
len = ClampTop(len, a.len);
String result = {a.data + len, a.len - len};
return result;
}
API String GetPostfix(String a, int64_t len) {
len = ClampTop(len, a.len);
int64_t remain_len = a.len - len;
String result = {a.data + remain_len, len};
return result;
}
API String GetPrefix(String a, int64_t len) {
len = ClampTop(len, a.len);
String result = {a.data, len};
return result;
}
API String GetSlice(String arr, int64_t first_index, int64_t one_past_last_index) {
// Negative indexes work in python style, they return you the index counting from end of list
if (one_past_last_index == SLICE_LAST) one_past_last_index = arr.len;
if (one_past_last_index < 0) one_past_last_index = arr.len + one_past_last_index;
if (first_index == SLICE_LAST) first_index = arr.len;
if (first_index < 0) first_index = arr.len + first_index;
String result = {arr.data, arr.len};
if (arr.len > 0) {
if (one_past_last_index > first_index) {
first_index = ClampTop(first_index, arr.len - 1);
one_past_last_index = ClampTop(one_past_last_index, arr.len);
result.data += first_index;
result.len = one_past_last_index - first_index;
} else {
result.len = 0;
}
}
return result;
}
API bool AreEqual(String a, String b, unsigned ignore_case) {
if (a.len != b.len) return false;
for (int64_t i = 0; i < a.len; i++) {
char A = a.data[i];
char B = b.data[i];
if (ignore_case) {
A = ToLowerCase(A);
B = ToLowerCase(B);
}
if (A != B)
return false;
}
return true;
}
API bool EndsWith(String a, String end, unsigned ignore_case) {
String a_end = GetPostfix(a, end.len);
bool result = AreEqual(end, a_end, ignore_case);
return result;
}
API bool StartsWith(String a, String start, unsigned ignore_case) {
String a_start = GetPrefix(a, start.len);
bool result = AreEqual(start, a_start, ignore_case);
return result;
}
API String Trim(String string) {
if (string.len == 0)
return string;
int64_t whitespace_begin = 0;
for (; whitespace_begin < string.len; whitespace_begin++) {
if (!IsWhitespace(string.data[whitespace_begin])) {
break;
}
}
int64_t whitespace_end = string.len;
for (; whitespace_end != whitespace_begin; whitespace_end--) {
if (!IsWhitespace(string.data[whitespace_end - 1])) {
break;
}
}
if (whitespace_begin == whitespace_end) {
string.len = 0;
} else {
string = GetSlice(string, whitespace_begin, whitespace_end);
}
return string;
}
API String TrimEnd(String string) {
int64_t whitespace_end = string.len;
for (; whitespace_end != 0; whitespace_end--) {
if (!IsWhitespace(string.data[whitespace_end - 1])) {
break;
}
}
String result = GetPrefix(string, whitespace_end);
return result;
}
API String Copy(Allocator allocator, String string) {
char *copy = (char *)AllocSize(allocator, sizeof(char) * (string.len + 1));
memcpy(copy, string.data, string.len);
copy[string.len] = 0;
String result = {copy, string.len};
return result;
}
API String Copy(Allocator allocator, char *string) {
return Copy(allocator, {string, (int64_t)strlen(string)});
}
API void NormalizePathInPlace(String s) {
for (int64_t i = 0; i < s.len; i++) {
if (s.data[i] == '\\')
s.data[i] = '/';
}
}
API String NormalizePath(Allocator allocator, String s) {
String copy = Copy(allocator, s);
NormalizePathInPlace(copy);
return copy;
}
API bool Seek(String string, String find, int64_t *index_out, SeekFlag flags) {
bool ignore_case = flags & SeekFlag_IgnoreCase ? true : false;
bool result = false;
if (flags & SeekFlag_MatchFindLast) {
for (int64_t i = string.len; i != 0; i--) {
int64_t index = i - 1;
String substring = GetSlice(string, index, index + find.len);
if (AreEqual(substring, find, ignore_case)) {
if (index_out)
*index_out = index;
result = true;
break;
}
}
} else {
for (int64_t i = 0; i < string.len; i++) {
String substring = GetSlice(string, i, i + find.len);
if (AreEqual(substring, find, ignore_case)) {
if (index_out)
*index_out = i;
result = true;
break;
}
}
}
return result;
}
API String CutLastSlash(String *s) {
String result = *s;
Seek(*s, "/", &s->len, SeekFlag_MatchFindLast);
result = Skip(result, s->len);
return result;
}
API String ChopLastSlash(String s) {
String result = s;
Seek(s, "/", &result.len, SeekFlag_MatchFindLast);
return result;
}
API String ChopLastPeriod(String s) {
String result = s;
Seek(s, ".", &result.len, SeekFlag_MatchFindLast);
return result;
}
API String SkipToLastSlash(String s) {
int64_t pos;
String result = s;
if (Seek(s, "/", &pos, SeekFlag_MatchFindLast)) {
result = Skip(result, pos + 1);
}
return result;
}
API String SkipToLastPeriod(String s) {
int64_t pos;
String result = s;
if (Seek(s, ".", &pos, SeekFlag_MatchFindLast)) {
result = Skip(result, pos + 1);
}
return result;
}
API String CutPrefix(String *string, int64_t len) {
String result = GetPrefix(*string, len);
*string = Skip(*string, len);
return result;
}
API String CutPostfix(String *string, int64_t len) {
String result = GetPostfix(*string, len);
*string = Chop(*string, len);
return result;
}
API String FormatV(Allocator allocator, const char *data, va_list args1) {
va_list args2;
va_copy(args2, args1);
int64_t len = stbsp_vsnprintf(0, 0, data, args2);
va_end(args2);
char *result = (char *)AllocSize(allocator, sizeof(char) * (len + 1));
stbsp_vsnprintf(result, (int)(len + 1), data, args1);
String res = {result, len};
return res;
}
API String Format(Allocator allocator, const char *data, ...) {
STRING_FORMAT(allocator, data, result);
return result;
}
API Array<String> Split(Allocator allocator, String string, String delimiter) {
Array<String> result = {allocator};
int64_t index = 0;
while (Seek(string, delimiter, &index)) {
String before_match = {string.data, index};
Add(&result, before_match);
string = Skip(string, index + delimiter.len);
}
Add(&result, string);
return result;
}
API String Merge(Allocator allocator, Array<String> list, String separator) {
int64_t char_count = 0;
For(list) char_count += it.len;
if (char_count == 0) return {};
int64_t node_count = list.len;
int64_t base_size = (char_count + 1);
int64_t sep_size = (node_count - 1) * separator.len;
int64_t size = base_size + sep_size;
char *buff = (char *)AllocSize(allocator, sizeof(char) * (size + 1));
String string = {buff, 0};
For(list) {
Assert(string.len + it.len <= size);
memcpy(string.data + string.len, it.data, it.len);
string.len += it.len;
if (!IsLast(list, it)) {
memcpy(string.data + string.len, separator.data, separator.len);
string.len += separator.len;
}
}
Assert(string.len == size - 1);
string.data[size] = 0;
return string;
}
API Int GetSize(Array<String> array) {
Int result = 0;
For (array) result += it.len;
return result;
}
+105
View File
@@ -0,0 +1,105 @@
#pragma once
struct String {
char *data;
int64_t len;
String() = default;
String(char *s) : data(s), len(strlen(s)) {}
String(char *s, int64_t l) : data((char *)s), len(l) {}
String(const char *s) : data((char *)s), len(strlen((char *)s)) {}
String(const char *s, int64_t l) : data((char *)s), len(l) {}
char &operator[](int64_t index) {
Assert(index < len);
return data[index];
}
char *begin() { return data; }
char *end() { return data + len; }
struct ReverseIter {
char *data;
String *arr;
ReverseIter operator++(int) {
ReverseIter ret = *this;
data -= 1;
return ret;
}
ReverseIter &operator++() {
data -= 1;
return *this;
}
char &operator*() { return data[0]; }
char *operator->() { return data; }
friend bool operator==(const ReverseIter &a, const ReverseIter &b) { return a.data == b.data; };
friend bool operator!=(const ReverseIter &a, const ReverseIter &b) { return a.data != b.data; };
ReverseIter begin() { return ReverseIter{arr->end() - 1, arr}; }
ReverseIter end() { return ReverseIter{arr->begin() - 1, arr}; }
};
ReverseIter reverse() { return {this->end() - 1, this}; }
};
API char ToLowerCase(char a);
API char ToUpperCase(char a);
API bool IsWhitespace(char w);
API bool IsAlphabetic(char a);
API bool IsIdent(char a);
API bool IsDigit(char a);
API bool IsAlphanumeric(char a);
API bool IsSymbol(char w);
API bool IsNonWord(char w);
API bool IsWord(char w);
API bool IsBrace(char c);
API bool IsParen(char c);
API bool EndsWith(String a, String end, unsigned ignore_case = false);
API bool StartsWith(String a, String start, unsigned ignore_case = false);
API bool AreEqual(String a, String b, unsigned ignore_case = false);
inline bool operator==(String a, String b) { return AreEqual(a, b); }
inline bool operator!=(String a, String b) { return !AreEqual(a, b); }
API String Trim(String string);
API String TrimEnd(String string);
API String Chop(String a, int64_t len);
API String Skip(String a, int64_t len);
API String GetPostfix(String a, int64_t len);
API String GetPrefix(String a, int64_t len);
API String GetSlice(String arr, int64_t first_index = 0, int64_t one_past_last_index = SLICE_LAST);
API String CutLastSlash(String *s);
API String ChopLastSlash(String s);
API String ChopLastPeriod(String s);
API String SkipToLastSlash(String s);
API String SkipToLastPeriod(String s);
API String CutPrefix(String *string, int64_t len);
API String CutPostfix(String *string, int64_t len);
API String Copy(Allocator allocator, String string);
API String Copy(Allocator allocator, char *string);
API void NormalizePathInPlace(String s);
API String NormalizePath(Allocator allocator, String s);
API String FormatV(Allocator allocator, const char *data, va_list args1);
API String Format(Allocator allocator, const char *data, ...);
#define STRING_FORMAT(allocator, data, result) \
va_list args1; \
va_start(args1, data); \
String result = FormatV(allocator, data, args1); \
va_end(args1)
typedef int SeekFlag;
enum {
SeekFlag_None = 0,
SeekFlag_IgnoreCase = 1,
SeekFlag_MatchFindLast = 2,
};
API bool Seek(String string, String find, int64_t *index_out = NULL, SeekFlag flags = SeekFlag_None);
API Array<String> Split(Allocator allocator, String string, String delimiter = " ");
API String Merge(Allocator allocator, Array<String> list, String separator);
API Int GetSize(Array<String> array);
+422
View File
@@ -0,0 +1,422 @@
#include <stdlib.h>
API int64_t WideLength(char16_t *string) {
if (!string) return 0;
int64_t len = 0;
while (*string++ != 0)
len++;
return len;
}
API char16_t ToLowerCase(char16_t a) {
if (a >= u'A' && a <= u'Z') a += 32;
return a;
}
API char16_t ToUpperCase(char16_t a) {
if (a >= u'a' && a <= u'z') a -= 32;
return a;
}
API bool IsWhitespace(char16_t w) {
bool result = w == u'\n' || w == u' ' || w == u'\t' || w == u'\v' || w == u'\r';
return result;
}
API bool IsAlphabetic(char16_t a) {
bool result = (a >= u'a' && a <= u'z') || (a >= u'A' && a <= u'Z');
return result;
}
API bool IsIdent(char16_t a) {
bool result = (a >= u'a' && a <= u'z') || (a >= u'A' && a <= u'Z') || a == u'_';
return result;
}
API bool IsDigit(char16_t a) {
bool result = a >= u'0' && a <= u'9';
return result;
}
API bool IsAlphanumeric(char16_t a) {
bool result = IsDigit(a) || IsAlphabetic(a);
return result;
}
API bool IsSymbol(char16_t w) {
bool result = (w >= u'!' && w <= u'/') || (w >= u':' && w <= u'@') || (w >= u'[' && w <= u'`') || (w >= u'{' && w <= u'~');
return result;
}
API bool IsNonWord(char16_t w) {
if (w == u'_') return false;
bool result = IsSymbol(w) || IsWhitespace(w);
return result;
}
API bool IsWord(char16_t w) {
bool result = !IsNonWord(w);
return result;
}
API bool IsBrace(char16_t c) {
bool result = c == u'{' || c == u'}';
return result;
}
API bool IsParen(char16_t c) {
bool result = c == u'(' || c == u')';
return result;
}
API String16 Chop(String16 a, int64_t len) {
len = ClampTop(len, a.len);
String16 result = {a.data, a.len - len};
return result;
}
API String16 Skip(String16 a, int64_t len) {
len = ClampTop(len, a.len);
String16 result = {a.data + len, a.len - len};
return result;
}
API String16 GetPostfix(String16 a, int64_t len) {
len = ClampTop(len, a.len);
int64_t remain_len = a.len - len;
String16 result = {a.data + remain_len, len};
return result;
}
API String16 GetPrefix(String16 a, int64_t len) {
len = ClampTop(len, a.len);
String16 result = {a.data, len};
return result;
}
API String16 GetSlice(String16 arr, int64_t first_index, int64_t one_past_last_index) {
// Negative indexes work in python style, they return you the index counting from end of list
if (one_past_last_index == SLICE_LAST) one_past_last_index = arr.len;
if (one_past_last_index < 0) one_past_last_index = arr.len + one_past_last_index;
if (first_index == SLICE_LAST) first_index = arr.len;
if (first_index < 0) first_index = arr.len + first_index;
String16 result = {arr.data, arr.len};
if (arr.len > 0) {
if (one_past_last_index > first_index) {
first_index = ClampTop(first_index, arr.len - 1);
one_past_last_index = ClampTop(one_past_last_index, arr.len);
result.data += first_index;
result.len = one_past_last_index - first_index;
} else {
result.len = 0;
}
}
return result;
}
API bool AreEqual(String16 a, String16 b, unsigned ignore_case) {
if (a.len != b.len) return false;
for (int64_t i = 0; i < a.len; i++) {
char16_t A = a.data[i];
char16_t B = b.data[i];
if (ignore_case) {
A = ToLowerCase(A);
B = ToLowerCase(B);
}
if (A != B)
return false;
}
return true;
}
API bool EndsWith(String16 a, String16 end, unsigned ignore_case) {
String16 a_end = GetPostfix(a, end.len);
bool result = AreEqual(end, a_end, ignore_case);
return result;
}
API bool StartsWith(String16 a, String16 start, unsigned ignore_case) {
String16 a_start = GetPrefix(a, start.len);
bool result = AreEqual(start, a_start, ignore_case);
return result;
}
API String16 Trim(String16 string) {
if (string.len == 0)
return string;
int64_t whitespace_begin = 0;
for (; whitespace_begin < string.len; whitespace_begin++) {
if (!IsWhitespace(string.data[whitespace_begin])) {
break;
}
}
int64_t whitespace_end = string.len;
for (; whitespace_end != whitespace_begin; whitespace_end--) {
if (!IsWhitespace(string.data[whitespace_end - 1])) {
break;
}
}
if (whitespace_begin == whitespace_end) {
string.len = 0;
} else {
string = GetSlice(string, whitespace_begin, whitespace_end);
}
return string;
}
API String16 TrimEnd(String16 string) {
int64_t whitespace_end = string.len;
for (; whitespace_end != 0; whitespace_end--) {
if (!IsWhitespace(string.data[whitespace_end - 1])) {
break;
}
}
String16 result = GetPrefix(string, whitespace_end);
return result;
}
API String16 Copy16(Allocator allocator, String16 string) {
char16_t *copy = (char16_t *)AllocSize(allocator, sizeof(char16_t) * (string.len + 1));
memcpy(copy, string.data, string.len * sizeof(char16_t));
copy[string.len] = 0;
String16 result = {copy, string.len};
return result;
}
API String16 Copy16(Allocator allocator, char16_t *string) {
return Copy16(allocator, {string, (int64_t)WideLength(string)});
}
API void NormalizePathInPlace(String16 s) {
for (int64_t i = 0; i < s.len; i++) {
if (s.data[i] == u'\\')
s.data[i] = u'/';
}
}
API String16 NormalizePath(Allocator allocator, String16 s) {
String16 copy = Copy16(allocator, s);
NormalizePathInPlace(copy);
return copy;
}
API bool Seek(String16 string, String16 find, int64_t *index_out, SeekFlag flags) {
bool ignore_case = flags & SeekFlag_IgnoreCase ? true : false;
bool result = false;
if (flags & SeekFlag_MatchFindLast) {
for (int64_t i = string.len; i != 0; i--) {
int64_t index = i - 1;
String16 substring = GetSlice(string, index, index + find.len);
if (AreEqual(substring, find, ignore_case)) {
if (index_out)
*index_out = index;
result = true;
break;
}
}
} else {
for (int64_t i = 0; i < string.len; i++) {
String16 substring = GetSlice(string, i, i + find.len);
if (AreEqual(substring, find, ignore_case)) {
if (index_out)
*index_out = i;
result = true;
break;
}
}
}
return result;
}
API String16 CutLastSlash(String16 *s) {
String16 result = *s;
Seek(*s, u"/", &s->len, SeekFlag_MatchFindLast);
result = Skip(result, s->len);
return result;
}
API String16 ChopLastSlash(String16 s) {
String16 result = s;
Seek(s, u"/", &result.len, SeekFlag_MatchFindLast);
return result;
}
API String16 ChopLastPeriod(String16 s) {
String16 result = s;
Seek(s, u".", &result.len, SeekFlag_MatchFindLast);
return result;
}
API String16 SkipToLastSlash(String16 s) {
int64_t pos;
String16 result = s;
if (Seek(s, u"/", &pos, SeekFlag_MatchFindLast)) {
result = Skip(result, pos + 1);
}
return result;
}
API String16 SkipToLastPeriod(String16 s) {
int64_t pos;
String16 result = s;
if (Seek(s, u".", &pos, SeekFlag_MatchFindLast)) {
result = Skip(result, pos + 1);
}
return result;
}
API String16 CutPrefix(String16 *string, int64_t len) {
String16 result = GetPrefix(*string, len);
*string = Skip(*string, len);
return result;
}
API String16 CutPostfix(String16 *string, int64_t len) {
String16 result = GetPostfix(*string, len);
*string = Chop(*string, len);
return result;
}
API String16 Format16V(Allocator allocator, const char *data, va_list args1) {
Scratch scratch;
va_list args2;
va_copy(args2, args1);
int64_t len = stbsp_vsnprintf(0, 0, data, args2);
va_end(args2);
char *result = (char *)AllocSize(scratch, sizeof(char) * (len + 1));
stbsp_vsnprintf(result, (int)(len + 1), data, args1);
String res = {result, len};
String16 res16 = ToString16(allocator, res);
return res16;
}
API String16 Format16(Allocator allocator, const char *data, ...) {
Scratch scratch;
STRING_FORMAT(scratch, data, result);
String16 result16 = ToString16(allocator, result);
return result16;
}
API Array<String16> Split(Allocator allocator, String16 string, String16 delimiter) {
Array<String16> result = {allocator};
int64_t index = 0;
while (Seek(string, delimiter, &index)) {
String16 before_match = {string.data, index};
Add(&result, before_match);
string = Skip(string, index + delimiter.len);
}
Add(&result, string);
return result;
}
API String16 Merge(Allocator allocator, Array<String16> list, String16 separator) {
int64_t char_count = 0;
For(list) char_count += it.len;
if (char_count == 0) return {};
int64_t node_count = list.len;
int64_t base_size = (char_count + 1);
int64_t sep_size = (node_count - 1) * separator.len;
int64_t size = base_size + sep_size;
char16_t *buff = (char16_t *)AllocSize(allocator, sizeof(char16_t) * (size + 1));
String16 string = {buff, 0};
For(list) {
Assert(string.len + it.len <= size);
memcpy(string.data + string.len, it.data, it.len * sizeof(char16_t));
string.len += it.len;
if (!IsLast(list, it)) {
memcpy(string.data + string.len, separator.data, separator.len * sizeof(char16_t));
string.len += separator.len;
}
}
Assert(string.len == size - 1);
string.data[size] = 0;
return string;
}
API Int GetSize(Array<String16> array) {
Int result = 0;
For (array) result += it.len;
return result;
}
API String16 SkipNumberEx(String16 *string) {
String16 col = {string->data, 0};
for (int64_t i = 0; i < string->len; i += 1) {
if (IsDigit(string->data[i])) {
col.len += 1;
} else {
break;
}
}
*string = Skip(*string, col.len);
return col;
}
API Int SkipNumber(String16 *string) {
String16 col = SkipNumberEx(string);
if (col.len == 0) return -1;
Scratch scratch;
String num_string = ToString(scratch, col);
Int result = strtoll(num_string.data, NULL, 10);
return result;
}
API String16 SkipUntil(String16 *string, String16 str) {
String16 begin = *string;
begin.len = 0;
for (; string->len; begin.len += 1) {
String16 match = GetPrefix(*string, str.len);
if (StartsWith(match, str)) break;
*string = Skip(*string, 1);
}
return begin;
}
API String16 SkipWhitespace(String16 *string) {
String16 begin = {string->data, 0};
for (Int i = 0; i < string->len; i += 1) {
if (!IsWhitespace(string->data[i])) break;
*string = Skip(*string, 1);
begin.len += 1;
}
return begin;
}
// chop this - :324
API String16 ChopNumberEx(String16 *string) {
String16 col = {};
for (int64_t i = string->len - 1; i >= 0; i -= 1) {
if (IsDigit(string->data[i])) {
col.data = string->data + i;
col.len += 1;
} else if (string->data[i] == L':') {
break;
} else {
return {};
}
}
*string = Chop(*string, col.len + 1);
return col;
}
API Int ChopNumber(String16 *string) {
Scratch scratch;
String16 col = ChopNumberEx(string);
if (col.len == 0) return -1;
String num_string = ToString(scratch, col);
Int result = strtoll(num_string.data, NULL, 10) - 1;
return result;
}
+104
View File
@@ -0,0 +1,104 @@
#pragma once
API int64_t WideLength(char16_t *string);
struct String16 {
char16_t *data;
int64_t len;
String16() = default;
String16(char16_t *s) : data(s), len(WideLength(s)) {}
String16(char16_t *s, int64_t l) : data((char16_t *)s), len(l) {}
String16(const char16_t *s) : data((char16_t *)s), len(WideLength((char16_t *)s)) {}
String16(const char16_t *s, int64_t l) : data((char16_t *)s), len(l) {}
char16_t &operator[](int64_t index) {
Assert(index < len);
return data[index];
}
char16_t *begin() { return data; }
char16_t *end() { return data + len; }
struct ReverseIter {
char16_t *data;
String16 *arr;
ReverseIter operator++(int) {
ReverseIter ret = *this;
data -= 1;
return ret;
}
ReverseIter &operator++() {
data -= 1;
return *this;
}
char16_t &operator*() { return data[0]; }
char16_t *operator->() { return data; }
friend bool operator==(const ReverseIter &a, const ReverseIter &b) { return a.data == b.data; };
friend bool operator!=(const ReverseIter &a, const ReverseIter &b) { return a.data != b.data; };
ReverseIter begin() { return ReverseIter{arr->end() - 1, arr}; }
ReverseIter end() { return ReverseIter{arr->begin() - 1, arr}; }
};
ReverseIter reverse() { return {this->end() - 1, this}; }
};
API char16_t ToLowerCase(char16_t a);
API char16_t ToUpperCase(char16_t a);
API bool IsWhitespace(char16_t w);
API bool IsAlphabetic(char16_t a);
API bool IsIdent(char16_t a);
API bool IsDigit(char16_t a);
API bool IsAlphanumeric(char16_t a);
API bool IsSymbol(char16_t w);
API bool IsNonWord(char16_t w);
API bool IsWord(char16_t w);
API bool IsBrace(char16_t c);
API bool IsParen(char16_t c);
API bool EndsWith(String16 a, String16 end, unsigned ignore_case = false);
API bool StartsWith(String16 a, String16 start, unsigned ignore_case = false);
API bool AreEqual(String16 a, String16 b, unsigned ignore_case = false);
inline bool operator==(String16 a, String16 b) { return AreEqual(a, b); }
inline bool operator!=(String16 a, String16 b) { return !AreEqual(a, b); }
API String16 Trim(String16 string);
API String16 TrimEnd(String16 string);
API String16 Chop(String16 a, int64_t len);
API String16 Skip(String16 a, int64_t len);
API String16 GetPostfix(String16 a, int64_t len);
API String16 GetPrefix(String16 a, int64_t len);
API String16 GetSlice(String16 arr, int64_t first_index = 0, int64_t one_past_last_index = SLICE_LAST);
API String16 CutLastSlash(String16 *s);
API String16 ChopLastSlash(String16 s);
API String16 ChopLastPeriod(String16 s);
API String16 SkipToLastSlash(String16 s);
API String16 SkipToLastPeriod(String16 s);
API String16 CutPrefix(String16 *string, int64_t len);
API String16 CutPostfix(String16 *string, int64_t len);
// @todo: think about this API, for parsing, maybe redesign or something
API String16 SkipNumberEx(String16 *string);
API Int SkipNumber(String16 *string);
API String16 SkipUntil(String16 *string, String16 str);
API String16 SkipWhitespace(String16 *string);
API String16 ChopNumberEx(String16 *string);
API Int ChopNumber(String16 *string);
API String16 Copy16(Allocator allocator, String16 string);
API String16 Copy16(Allocator allocator, char16_t *string, int64_t len);
API String16 Copy16(Allocator allocator, char *string);
API void NormalizePathInPlace(String16 s);
API String16 NormalizePath(Allocator allocator, String16 s);
API String16 Format16V(Allocator allocator, const char *data, va_list args1);
API String16 Format16(Allocator allocator, const char *data, ...);
API bool Seek(String16 string, String16 find, int64_t *index_out = NULL, SeekFlag flags = SeekFlag_None);
API Array<String16> Split(Allocator allocator, String16 string, String16 delimiter = u" ");
API String16 Merge(Allocator allocator, Array<String16> list, String16 separator);
API Int GetSize(Array<String16> array);
+187
View File
@@ -0,0 +1,187 @@
/*
Hash table implementation:
Pointers to values
Open adressing
Linear Probing
Power of 2
Robin Hood hashing
Resizes on high probe count (min max load factor)
Hash 0 is reserved for empty hash table entry
*/
template <class Value>
struct HashTable {
struct Entry {
uint64_t hash;
uint64_t key;
size_t distance;
Value value;
};
Allocator allocator;
size_t len, cap;
Entry *values;
static const size_t max_load_factor = 80;
static const size_t min_load_factor = 50;
static const size_t significant_distance = 8;
// load factor calculation was rearranged
// to get rid of division:
//> 100 * len / cap = load_factor
//> len * 100 = load_factor * cap
inline bool reached_load_factor(size_t lfactor) {
return (len + 1) * 100 >= lfactor * cap;
}
inline bool is_empty(Entry *entry) { return entry->hash == 0; }
inline bool is_occupied(Entry *entry) { return entry->hash != 0; }
void reserve(size_t size) {
Assert(size > cap && "New size is smaller then original size");
Assert(IsPowerOf2(size));
if (!allocator.proc) allocator = GetSystemAllocator();
Entry *old_values = values;
size_t old_cap = cap;
values = (Entry *)AllocSize(allocator, sizeof(Entry) * size);
for (size_t i = 0; i < size; i += 1) values[i] = {};
cap = size;
Assert(!(old_values == 0 && len != 0));
if (len == 0) {
if (old_values) {
Dealloc(allocator, old_values);
}
return;
}
len = 0;
for (size_t i = 0; i < old_cap; i += 1) {
Entry *it = old_values + i;
if (is_occupied(it)) {
insert(it->key, it->value);
}
}
Dealloc(allocator, old_values);
}
Entry *get_table_entry(uint64_t key) {
if (len == 0) return 0;
uint64_t hash = HashBytes(&key, sizeof(key));
if (hash == 0) hash += 1;
uint64_t index = WrapAroundPowerOf2(hash, cap);
uint64_t i = index;
uint64_t distance = 0;
for (;;) {
Entry *it = values + i;
if (distance > it->distance) {
return 0;
}
if (it->hash == hash && it->key == key) {
return it;
}
distance += 1;
i = WrapAroundPowerOf2(i + 1, cap);
if (i == index) return 0;
}
Assert(!"Invalid codepath");
}
void insert(uint64_t key, const Value &value) {
if (reached_load_factor(max_load_factor)) {
if (cap == 0) cap = 16; // 32 cause cap*2
reserve(cap * 2);
}
uint64_t hash = HashBytes(&key, sizeof(key));
if (hash == 0) hash += 1;
uint64_t index = WrapAroundPowerOf2(hash, cap);
uint64_t i = index;
Entry to_insert = {hash, key, 0, value};
for (;;) {
Entry *it = values + i;
if (is_empty(it)) {
*it = to_insert;
len += 1;
// If we have more then 8 consecutive items we try to resize
if (to_insert.distance > 8 && reached_load_factor(min_load_factor)) {
reserve(cap * 2);
}
return;
}
if (it->hash == hash && it->key == key) {
*it = to_insert;
// If we have more then 8 consecutive items we try to resize
if (to_insert.distance > 8 && reached_load_factor(min_load_factor)) {
reserve(cap * 2);
}
return;
}
// Robin hood hashing
if (to_insert.distance > it->distance) {
Entry temp = to_insert;
to_insert = *it;
*it = temp;
}
to_insert.distance += 1;
i = WrapAroundPowerOf2(i + 1, cap);
Assert(i != index && "Did a full 360 through a hash table, no good :( that shouldnt be possible");
}
Assert(!"Invalid codepath");
}
void remove(uint64_t key) {
Entry *entry = get_table_entry(key);
entry->hash = 0;
entry->distance = 0;
len -= 1;
}
Value *get(uint64_t key) {
Entry *v = get_table_entry(key);
if (!v) return 0;
return &v->value;
}
Value get(uint64_t key, Value default_value) {
Entry *v = get_table_entry(key);
if (!v) return default_value;
return v->value;
}
Value *get(String s) {
uint64_t hash = HashBytes(s.data, (unsigned)s.len);
return get(hash);
}
Value get(String s, Value default_value) {
uint64_t hash = HashBytes(s.data, (unsigned)s.len);
return get(hash, default_value);
}
void put(String s, const Value &value) {
uint64_t hash = HashBytes(s.data, (unsigned)s.len);
insert(hash, value);
}
void reset() {
len = 0;
for (size_t i = 0; i < cap; i += 1) {
Entry *it = values + i;
it->hash = 0;
}
}
void dealloc() {
Dealloc(allocator, values);
values = NULL;
len = 0;
cap = 0;
}
};
+237
View File
@@ -0,0 +1,237 @@
API UTF32Result UTF16ToUTF32(uint16_t *c, int64_t max_advance) {
UTF32Result result;
MemoryZero(&result, sizeof(result));
if (max_advance >= 1) {
result.advance = 1;
result.out_str = c[0];
if (c[0] >= 0xD800 && c[0] <= 0xDBFF && c[1] >= 0xDC00 && c[1] <= 0xDFFF) {
if (max_advance >= 2) {
result.out_str = 0x10000;
result.out_str += (uint32_t)(c[0] & 0x03FF) << 10u | (c[1] & 0x03FF);
result.advance = 2;
} else
result.error = 2;
}
} else {
result.error = 1;
}
return result;
}
API UTF8Result UTF32ToUTF8(uint32_t codepoint) {
UTF8Result result;
MemoryZero(&result, sizeof(result));
if (codepoint <= 0x7F) {
result.len = 1;
result.out_str[0] = (char)codepoint;
} else if (codepoint <= 0x7FF) {
result.len = 2;
result.out_str[0] = 0xc0 | (0x1f & (codepoint >> 6));
result.out_str[1] = 0x80 | (0x3f & codepoint);
} else if (codepoint <= 0xFFFF) { // 16 bit word
result.len = 3;
result.out_str[0] = 0xe0 | (0xf & (codepoint >> 12)); // 4 bits
result.out_str[1] = 0x80 | (0x3f & (codepoint >> 6)); // 6 bits
result.out_str[2] = 0x80 | (0x3f & codepoint); // 6 bits
} else if (codepoint <= 0x10FFFF) { // 21 bit word
result.len = 4;
result.out_str[0] = 0xf0 | (0x7 & (codepoint >> 18)); // 3 bits
result.out_str[1] = 0x80 | (0x3f & (codepoint >> 12)); // 6 bits
result.out_str[2] = 0x80 | (0x3f & (codepoint >> 6)); // 6 bits
result.out_str[3] = 0x80 | (0x3f & codepoint); // 6 bits
} else {
result.error = 1;
}
return result;
}
API UTF32Result UTF8ToUTF32(uint8_t *c, int64_t max_advance) {
UTF32Result result;
MemoryZero(&result, sizeof(result));
if ((c[0] & 0x80) == 0) { // Check if leftmost zero of first byte is unset
if (max_advance >= 1) {
result.out_str = c[0];
result.advance = 1;
} else result.error = 1;
}
else if ((c[0] & 0xe0) == 0xc0) {
if ((c[1] & 0xc0) == 0x80) { // Continuation byte required
if (max_advance >= 2) {
result.out_str = (uint32_t)(c[0] & 0x1f) << 6u | (c[1] & 0x3f);
result.advance = 2;
} else result.error = 2;
} else result.error = 2;
}
else if ((c[0] & 0xf0) == 0xe0) {
if ((c[1] & 0xc0) == 0x80 && (c[2] & 0xc0) == 0x80) { // Two continuation bytes required
if (max_advance >= 3) {
result.out_str = (uint32_t)(c[0] & 0xf) << 12u | (uint32_t)(c[1] & 0x3f) << 6u | (c[2] & 0x3f);
result.advance = 3;
} else result.error = 3;
} else result.error = 3;
}
else if ((c[0] & 0xf8) == 0xf0) {
if ((c[1] & 0xc0) == 0x80 && (c[2] & 0xc0) == 0x80 && (c[3] & 0xc0) == 0x80) { // Three continuation bytes required
if (max_advance >= 4) {
result.out_str = (uint32_t)(c[0] & 0xf) << 18u | (uint32_t)(c[1] & 0x3f) << 12u | (uint32_t)(c[2] & 0x3f) << 6u | (uint32_t)(c[3] & 0x3f);
result.advance = 4;
} else result.error = 4;
} else result.error = 4;
} else result.error = 4;
return result;
}
API UTF16Result UTF32ToUTF16(uint32_t codepoint) {
UTF16Result result;
MemoryZero(&result, sizeof(result));
if (codepoint < 0x10000) {
result.out_str[0] = (uint16_t)codepoint;
result.out_str[1] = 0;
result.len = 1;
} else if (codepoint <= 0x10FFFF) {
uint32_t code = (codepoint - 0x10000);
result.out_str[0] = (uint16_t)(0xD800 | (code >> 10));
result.out_str[1] = (uint16_t)(0xDC00 | (code & 0x3FF));
result.len = 2;
} else {
result.error = 1;
}
return result;
}
#define UTF__HANDLE_DECODE_ERROR(question_mark, I) \
{ \
if (outlen < buffer_size - 1) buffer[outlen++] = (question_mark); \
i += I; \
}
API int64_t CreateCharFromWidechar(char *buffer, int64_t buffer_size, char16_t *in, int64_t inlen) {
int64_t outlen = 0;
for (int64_t i = 0; i < inlen && in[i];) {
UTF32Result decode = UTF16ToUTF32((uint16_t *)(in + i), (int64_t)(inlen - i));
if (!decode.error) {
i += decode.advance;
UTF8Result encode = UTF32ToUTF8(decode.out_str);
if (!encode.error) {
for (int64_t j = 0; j < encode.len; j++) {
if (outlen < buffer_size - 1) {
buffer[outlen++] = encode.out_str[j];
}
}
} else UTF__HANDLE_DECODE_ERROR('?', 0);
} else UTF__HANDLE_DECODE_ERROR('?', 1);
}
buffer[outlen] = 0;
return outlen;
}
API int64_t CreateWidecharFromChar(char16_t *buffer, int64_t buffer_size, char *in, int64_t inlen) {
int64_t outlen = 0;
for (int64_t i = 0; i < inlen;) {
UTF32Result decode = UTF8ToUTF32((uint8_t *)(in + i), (int64_t)(inlen - i));
if (!decode.error) {
i += decode.advance;
UTF16Result encode = UTF32ToUTF16(decode.out_str);
if (!encode.error) {
for (int64_t j = 0; j < encode.len; j++) {
if (outlen < buffer_size - 1) {
buffer[outlen++] = encode.out_str[j];
}
}
} else UTF__HANDLE_DECODE_ERROR(0x003f, 0);
} else UTF__HANDLE_DECODE_ERROR(0x003f, 1);
}
buffer[outlen] = 0;
return outlen;
}
API bool IsValid(UTF8Iter &iter) {
return iter.item;
}
API void Advance(UTF8Iter *iter) {
iter->i += iter->utf8_codepoint_byte_size;
UTF32Result r = UTF8ToUTF32((uint8_t *)(iter->data + iter->i), iter->len - iter->i);
if (r.error) {
iter->item = 0;
return;
}
iter->utf8_codepoint_byte_size = r.advance;
iter->item = r.out_str;
}
API UTF8Iter IterateUTF8Ex(char *data, int64_t len) {
UTF8Iter result;
MemoryZero(&result, sizeof(result));
result.data = data;
result.len = len;
if (len) Advance(&result);
return result;
}
API UTF8Iter IterateUTF8(char *data) {
int64_t length = 0;
while (data[length]) length += 1;
return IterateUTF8Ex(data, length);
}
API UTF8Iter IterateUTF8(String string) {
return IterateUTF8Ex(string.data, string.len);
}
API bool IsUTF8ContinuationByte(char c) {
char result = (c & 0b11000000) == 0b10000000;
return result;
}
API String16 ToString16(Allocator allocator, String string) {
char16_t *buffer = (char16_t *)AllocSize(allocator, sizeof(char16_t) * (string.len + 1));
int64_t size = CreateWidecharFromChar(buffer, string.len + 1, string.data, string.len);
String16 result = {buffer, size};
return result;
}
API String16 ToString16(Allocator allocator, char *in_string) {
String string(in_string);
String16 result = ToString16(allocator, string);
return result;
}
API char16_t *ToWidechar(Allocator allocator, String string) {
String16 result = ToString16(allocator, string);
return result.data;
}
API String ToString(Allocator allocator, String16 string) {
Assert(sizeof(char16_t) == 2);
int64_t buffer_size = (string.len + 1) * 2;
char *buffer = (char *)AllocSize(allocator, buffer_size);
int64_t size = CreateCharFromWidechar(buffer, buffer_size, string.data, string.len);
String result = {buffer, size};
Assert(size < buffer_size);
return result;
}
API String ToString(Allocator allocator, char16_t *string, int64_t len) {
return ToString(allocator, {string, len});
}
API String ToString(Allocator allocator, char16_t *wstring) {
int64_t size = WideLength(wstring);
String result = ToString(allocator, {wstring, size});
return result;
}
+60
View File
@@ -0,0 +1,60 @@
#pragma once
struct UTF32Result {
uint32_t out_str;
int64_t advance;
int64_t error;
};
struct UTF8Result {
uint8_t out_str[4];
int64_t len;
int64_t error;
};
struct UTF16Result {
uint16_t out_str[2];
int64_t len;
int64_t error;
};
struct UTF8Iter {
char *data;
int64_t len;
int64_t utf8_codepoint_byte_size;
int64_t i;
uint32_t item;
UTF8Iter &operator++() {
void Advance(UTF8Iter * iter);
Advance(this);
return *this;
}
friend bool operator!=(const UTF8Iter &a, const UTF8Iter &b) { return a.item != b.item; }
UTF8Iter &operator*() { return *this; }
UTF8Iter begin() {
UTF8Iter IterateUTF8Ex(char *data, int64_t len);
return {IterateUTF8Ex(data, len)};
}
UTF8Iter end() { return {}; }
};
API UTF32Result UTF16ToUTF32(uint16_t *c, int64_t max_advance);
API UTF8Result UTF32ToUTF8(uint32_t codepoint);
API UTF32Result UTF8ToUTF32(uint8_t *c, int64_t max_advance);
API UTF16Result UTF32ToUTF16(uint32_t codepoint);
API int64_t CreateCharFromWidechar(char *buffer, int64_t buffer_size, char16_t *in, int64_t inlen);
API int64_t CreateWidecharFromChar(char16_t *buffer, int64_t buffer_size, char *in, int64_t inlen);
API char16_t *ToWidechar(Allocator allocator, String string);
API String16 ToString16(Allocator allocator, String string);
API String ToString(Allocator allocator, String16 string);
API String ToString(Allocator allocator, char16_t *string, int64_t len);
API String ToString(Allocator allocator, char16_t *wstring);
API bool IsValid(UTF8Iter &iter);
API void Advance(UTF8Iter *iter);
API UTF8Iter IterateUTF8Ex(char *data, int64_t len);
API UTF8Iter IterateUTF8(char *data);
API UTF8Iter IterateUTF8(String string);
API bool IsUTF8ContinuationByte(char c);
+186
View File
@@ -0,0 +1,186 @@
Vec2 GetSize(Rect2 r) {
Vec2 result = {r.max.x - r.min.x, r.max.y - r.min.y};
return result;
}
Vec2 GetSizeF(Rect2I r) {
Vec2 result = {(float)(r.max.x - r.min.x), (float)(r.max.y - r.min.y)};
return result;
}
Vec2 ToVec2(Vec2I v) { return {(float)v.x, (float)v.y}; }
Vec2I ToVec2I(Vec2 v) { return {(Int)v.x, (Int)v.y}; }
Rect2I ToRect2I(Rect2 r) { return {ToVec2I(r.min), ToVec2I(r.max)}; }
Rect2 ToRect2(Rect2I r) { return {ToVec2(r.min), ToVec2(r.max)}; }
// clang-format off
Rect2 operator-(Rect2 r, Rect2 value) { return { {r.min.x - value.min.x, r.min.y - value.min.y}, {r.max.x - value.max.x, r.max.y - value.max.y} }; }
Rect2 operator+(Rect2 r, Rect2 value) { return { {r.min.x + value.min.x, r.min.y + value.min.y}, {r.max.x + value.max.x, r.max.y + value.max.y} }; }
Rect2 operator*(Rect2 r, Rect2 value) { return { {r.min.x * value.min.x, r.min.y * value.min.y}, {r.max.x * value.max.x, r.max.y * value.max.y} }; }
Rect2 operator/(Rect2 r, Rect2 value) { return { {r.min.x / value.min.x, r.min.y / value.min.y}, {r.max.x / value.max.x, r.max.y / value.max.y} }; }
Rect2 operator-(Rect2 r, Vec2 value) { return { {r.min.x - value.x, r.min.y - value.y}, {r.max.x - value.x, r.max.y - value.y} }; }
Rect2 operator+(Rect2 r, Vec2 value) { return { {r.min.x + value.x, r.min.y + value.y}, {r.max.x + value.x, r.max.y + value.y} }; }
Rect2 operator*(Rect2 r, Vec2 value) { return { {r.min.x * value.x, r.min.y * value.y}, {r.max.x * value.x, r.max.y * value.y} }; }
Rect2 operator/(Rect2 r, Vec2 value) { return { {r.min.x / value.x, r.min.y / value.y}, {r.max.x / value.x, r.max.y / value.y} }; }
Rect2 operator-(Vec2 value, Rect2 r) { return { {r.min.x - value.x, r.min.y - value.y}, {r.max.x - value.x, r.max.y - value.y} }; }
Rect2 operator+(Vec2 value, Rect2 r) { return { {r.min.x + value.x, r.min.y + value.y}, {r.max.x + value.x, r.max.y + value.y} }; }
Rect2 operator*(Vec2 value, Rect2 r) { return { {r.min.x * value.x, r.min.y * value.y}, {r.max.x * value.x, r.max.y * value.y} }; }
Rect2 operator/(Vec2 value, Rect2 r) { return { {r.min.x / value.x, r.min.y / value.y}, {r.max.x / value.x, r.max.y / value.y} }; }
Rect2 operator-(Rect2 r, float value) { return { {r.min.x - value, r.min.y - value}, {r.max.x - value, r.max.y - value} }; }
Rect2 operator+(Rect2 r, float value) { return { {r.min.x + value, r.min.y + value}, {r.max.x + value, r.max.y + value} }; }
Rect2 operator*(Rect2 r, float value) { return { {r.min.x * value, r.min.y * value}, {r.max.x * value, r.max.y * value} }; }
Rect2 operator/(Rect2 r, float value) { return { {r.min.x / value, r.min.y / value}, {r.max.x / value, r.max.y / value} }; }
Rect2 operator-(float value, Rect2 r) { return { {r.min.x - value, r.min.y - value}, {r.max.x - value, r.max.y - value} }; }
Rect2 operator+(float value, Rect2 r) { return { {r.min.x + value, r.min.y + value}, {r.max.x + value, r.max.y + value} }; }
Rect2 operator*(float value, Rect2 r) { return { {r.min.x * value, r.min.y * value}, {r.max.x * value, r.max.y * value} }; }
Rect2 operator/(float value, Rect2 r) { return { {r.min.x / value, r.min.y / value}, {r.max.x / value, r.max.y / value} }; }
Rect2 operator-=(Rect2 &r, Rect2 value) { r = r - value; return r; }
Rect2 operator+=(Rect2 &r, Rect2 value) { r = r + value; return r; }
Rect2 operator*=(Rect2 &r, Rect2 value) { r = r * value; return r; }
Rect2 operator/=(Rect2 &r, Rect2 value) { r = r / value; return r; }
Rect2 operator-=(Rect2 &r, Vec2 value) { r = r - value; return r; }
Rect2 operator+=(Rect2 &r, Vec2 value) { r = r + value; return r; }
Rect2 operator*=(Rect2 &r, Vec2 value) { r = r * value; return r; }
Rect2 operator/=(Rect2 &r, Vec2 value) { r = r / value; return r; }
Rect2 operator-=(Rect2 &r, float value) { r = r - value; return r; }
Rect2 operator+=(Rect2 &r, float value) { r = r + value; return r; }
Rect2 operator*=(Rect2 &r, float value) { r = r * value; return r; }
Rect2 operator/=(Rect2 &r, float value) { r = r / value; return r; }
bool operator==(Rect2 a, Rect2 b) {
bool result = a.min.x == b.min.x && a.min.y == b.min.y && a.max.x == b.max.x && a.max.y == b.max.y;
return result;
}
bool operator!=(Rect2 a, Rect2 b) {
bool result = !(a == b);
return result;
}
Vec2 operator-(Vec2 a, Vec2 b) { return {a.x - b.x, a.y - b.y}; }
Vec2 operator+(Vec2 a, Vec2 b) { return {a.x + b.x, a.y + b.y}; }
Vec2 operator*(Vec2 a, Vec2 b) { return {a.x * b.x, a.y * b.y}; }
Vec2 operator/(Vec2 a, Vec2 b) { return {a.x / b.x, a.y / b.y}; }
Vec2 operator-(Vec2 a, float b) { return {a.x - b, a.y - b}; }
Vec2 operator+(Vec2 a, float b) { return {a.x + b, a.y + b}; }
Vec2 operator*(Vec2 a, float b) { return {a.x * b, a.y * b}; }
Vec2 operator/(Vec2 a, float b) { return {a.x / b, a.y / b}; }
Vec2 operator-(float b, Vec2 a) { return {a.x - b, a.y - b}; }
Vec2 operator+(float b, Vec2 a) { return {a.x + b, a.y + b}; }
Vec2 operator*(float b, Vec2 a) { return {a.x * b, a.y * b}; }
Vec2 operator/(float b, Vec2 a) { return {a.x / b, a.y / b}; }
Vec2 operator-=(Vec2 &a, Vec2 b) { a = a - b; return a; }
Vec2 operator+=(Vec2 &a, Vec2 b) { a = a + b; return a; }
Vec2 operator*=(Vec2 &a, Vec2 b) { a = a * b; return a; }
Vec2 operator/=(Vec2 &a, Vec2 b) { a = a / b; return a; }
Vec2 operator-=(Vec2 &a, float b) { a = a - b; return a; }
Vec2 operator+=(Vec2 &a, float b) { a = a + b; return a; }
Vec2 operator*=(Vec2 &a, float b) { a = a * b; return a; }
Vec2 operator/=(Vec2 &a, float b) { a = a / b; return a; }
// clang-format on
Rect2 Rect0Size(float x, float y) {
Rect2 rect = {0, 0, x, y};
return rect;
}
Rect2 Rect2FromSize(Vec2 pos, Vec2 size) {
Rect2 result = {};
result.min = pos;
result.max = pos + size;
return result;
}
Rect2 Rect2MidHalf(Vec2 mid, Vec2 half_size) {
Rect2 result = {};
result.min = mid - half_size;
result.max = mid + half_size;
return result;
}
Rect2 Shrink(Rect2 result, float v) {
result.min.x += v;
result.max.x -= v;
result.min.y += v;
result.max.y -= v;
return result;
}
Rect2 ShrinkVertical(Rect2 result, float v) {
result.min.y += v;
result.max.y -= v;
return result;
}
Rect2 ShrinkHorizontal(Rect2 result, float v) {
result.min.x += v;
result.max.x -= v;
return result;
}
Vec2 GetMid(Rect2 r) {
Vec2 size = GetSize(r);
size.x /= 2.f;
size.y /= 2.f;
Vec2 result = r.min + size;
return result;
}
Rect2 CutLeft(Rect2 *r, float value) {
float minx = r->min.x;
r->min.x = Min(r->min.x + value, r->max.x);
Rect2 result = {
{ minx, r->min.y},
{r->min.x, r->max.y}
};
return result;
}
Rect2 CutRight(Rect2 *r, float value) {
float maxx = r->max.x;
r->max.x = Max(r->min.x, r->max.x - value);
Rect2 result = {
{r->max.x, r->min.y},
{ maxx, r->max.y},
};
return result;
}
// Y is up
Rect2 CutBottom(Rect2 *r, float value) {
float maxy = r->max.y;
r->max.y = Max(r->min.y, r->max.y - value);
Rect2 result = {
{r->min.x, r->max.y},
{r->max.x, maxy},
};
return result;
}
// Y is up
Rect2 CutTop(Rect2 *r, float value) {
float miny = r->min.y;
r->min.y = Min(r->min.y + value, r->max.y);
Rect2 result = {
{r->min.x, miny},
{r->max.x, r->min.y},
};
return result;
}
float SafeDivide(float a, float b) {
if (b == 0.f) {
return 0.f;
}
return a / b;
}
bool AreOverlapping(Vec2 point, Rect2 rec) {
bool result = (point.x >= rec.min.x) && (point.x < rec.max.x) && (point.y >= rec.min.y) && (point.y < rec.max.y);
return result;
}
+145
View File
@@ -0,0 +1,145 @@
Rect2I operator-(Rect2I r, Rect2I value) { return { {r.min.x - value.min.x, r.min.y - value.min.y}, {r.max.x - value.max.x, r.max.y - value.max.y} }; }
Rect2I operator+(Rect2I r, Rect2I value) { return { {r.min.x + value.min.x, r.min.y + value.min.y}, {r.max.x + value.max.x, r.max.y + value.max.y} }; }
Rect2I operator*(Rect2I r, Rect2I value) { return { {r.min.x * value.min.x, r.min.y * value.min.y}, {r.max.x * value.max.x, r.max.y * value.max.y} }; }
Rect2I operator/(Rect2I r, Rect2I value) { return { {r.min.x / value.min.x, r.min.y / value.min.y}, {r.max.x / value.max.x, r.max.y / value.max.y} }; }
Rect2I operator-(Rect2I r, Vec2I value) { return { {r.min.x - value.x, r.min.y - value.y}, {r.max.x - value.x, r.max.y - value.y} }; }
Rect2I operator+(Rect2I r, Vec2I value) { return { {r.min.x + value.x, r.min.y + value.y}, {r.max.x + value.x, r.max.y + value.y} }; }
Rect2I operator*(Rect2I r, Vec2I value) { return { {r.min.x * value.x, r.min.y * value.y}, {r.max.x * value.x, r.max.y * value.y} }; }
Rect2I operator/(Rect2I r, Vec2I value) { return { {r.min.x / value.x, r.min.y / value.y}, {r.max.x / value.x, r.max.y / value.y} }; }
Rect2I operator-(Vec2I value, Rect2I r) { return { {r.min.x - value.x, r.min.y - value.y}, {r.max.x - value.x, r.max.y - value.y} }; }
Rect2I operator+(Vec2I value, Rect2I r) { return { {r.min.x + value.x, r.min.y + value.y}, {r.max.x + value.x, r.max.y + value.y} }; }
Rect2I operator*(Vec2I value, Rect2I r) { return { {r.min.x * value.x, r.min.y * value.y}, {r.max.x * value.x, r.max.y * value.y} }; }
Rect2I operator/(Vec2I value, Rect2I r) { return { {r.min.x / value.x, r.min.y / value.y}, {r.max.x / value.x, r.max.y / value.y} }; }
Rect2I operator-(Int value, Rect2I r) { return { {r.min.x - value, r.min.y - value}, {r.max.x - value, r.max.y - value} }; }
Rect2I operator+(Int value, Rect2I r) { return { {r.min.x + value, r.min.y + value}, {r.max.x + value, r.max.y + value} }; }
Rect2I operator*(Int value, Rect2I r) { return { {r.min.x * value, r.min.y * value}, {r.max.x * value, r.max.y * value} }; }
Rect2I operator/(Int value, Rect2I r) { return { {r.min.x / value, r.min.y / value}, {r.max.x / value, r.max.y / value} }; }
Rect2I operator-(Rect2I r, Int value) { return { {r.min.x - value, r.min.y - value}, {r.max.x - value, r.max.y - value} }; }
Rect2I operator+(Rect2I r, Int value) { return { {r.min.x + value, r.min.y + value}, {r.max.x + value, r.max.y + value} }; }
Rect2I operator*(Rect2I r, Int value) { return { {r.min.x * value, r.min.y * value}, {r.max.x * value, r.max.y * value} }; }
Rect2I operator/(Rect2I r, Int value) { return { {r.min.x / value, r.min.y / value}, {r.max.x / value, r.max.y / value} }; }
Rect2I operator-=(Rect2I &r, Rect2I value) { r = r - value; return r; }
Rect2I operator+=(Rect2I &r, Rect2I value) { r = r + value; return r; }
Rect2I operator*=(Rect2I &r, Rect2I value) { r = r * value; return r; }
Rect2I operator/=(Rect2I &r, Rect2I value) { r = r / value; return r; }
Rect2I operator-=(Rect2I &r, Vec2I value) { r = r - value; return r; }
Rect2I operator+=(Rect2I &r, Vec2I value) { r = r + value; return r; }
Rect2I operator*=(Rect2I &r, Vec2I value) { r = r * value; return r; }
Rect2I operator/=(Rect2I &r, Vec2I value) { r = r / value; return r; }
Rect2I operator-=(Rect2I &r, Int value) { r = r - value; return r; }
Rect2I operator+=(Rect2I &r, Int value) { r = r + value; return r; }
Rect2I operator*=(Rect2I &r, Int value) { r = r * value; return r; }
Rect2I operator/=(Rect2I &r, Int value) { r = r / value; return r; }
Vec2I operator-(Vec2I a, Vec2I b) { return {a.x - b.x, a.y - b.y}; }
Vec2I operator+(Vec2I a, Vec2I b) { return {a.x + b.x, a.y + b.y}; }
Vec2I operator*(Vec2I a, Vec2I b) { return {a.x * b.x, a.y * b.y}; }
Vec2I operator/(Vec2I a, Vec2I b) { return {a.x / b.x, a.y / b.y}; }
Vec2I operator-(Vec2I a, Int b) { return {a.x - b, a.y - b}; }
Vec2I operator+(Vec2I a, Int b) { return {a.x + b, a.y + b}; }
Vec2I operator*(Vec2I a, Int b) { return {a.x * b, a.y * b}; }
Vec2I operator/(Vec2I a, Int b) { return {a.x / b, a.y / b}; }
Vec2I operator-(Int b, Vec2I a) { return {a.x - b, a.y - b}; }
Vec2I operator+(Int b, Vec2I a) { return {a.x + b, a.y + b}; }
Vec2I operator*(Int b, Vec2I a) { return {a.x * b, a.y * b}; }
Vec2I operator/(Int b, Vec2I a) { return {a.x / b, a.y / b}; }
Vec2I operator-=(Vec2I &a, Vec2I b) { a = a - b; return a; }
Vec2I operator+=(Vec2I &a, Vec2I b) { a = a + b; return a; }
Vec2I operator*=(Vec2I &a, Vec2I b) { a = a * b; return a; }
Vec2I operator/=(Vec2I &a, Vec2I b) { a = a / b; return a; }
Vec2I operator-=(Vec2I &a, Int b) { a = a - b; return a; }
Vec2I operator+=(Vec2I &a, Int b) { a = a + b; return a; }
Vec2I operator*=(Vec2I &a, Int b) { a = a * b; return a; }
Vec2I operator/=(Vec2I &a, Int b) { a = a / b; return a; }
Vec2I GetSize(Rect2I r) {
Vec2I result = {r.max.x - r.min.x, r.max.y - r.min.y};
return result;
}
Rect2I RectI0Size(Int x, Int y) {
Rect2I rect = {0, 0, x, y};
return rect;
}
Rect2I Rect2IFromSize(Vec2I pos, Vec2I size) {
Rect2I result = {};
result.min = pos;
result.max = pos + size;
return result;
}
Rect2I Shrink(Rect2I result, Int v) {
result.min.x += v;
result.max.x -= v;
result.min.y += v;
result.max.y -= v;
return result;
}
Vec2I GetMid(Rect2I r) {
Vec2I size = GetSize(r);
size.x /= 2;
size.y /= 2;
Vec2I result = r.min + size;
return result;
}
Rect2I CutLeft(Rect2I *r, Int value) {
Int minx = r->min.x;
r->min.x = Min(r->min.x + value, r->max.x);
Rect2I result = {
{ minx, r->min.y},
{r->min.x, r->max.y}
};
return result;
}
Rect2I CutRight(Rect2I *r, Int value) {
Int maxx = r->max.x;
r->max.x = Max(r->min.x, r->max.x - value);
Rect2I result = {
{r->max.x, r->min.y},
{ maxx, r->max.y},
};
return result;
}
// Y is up
Rect2I CutBottom(Rect2I *r, Int value) {
Int maxy = r->max.y;
r->max.y = Max(r->min.y, r->max.y - value);
Rect2I result = {
{r->min.x, r->max.y},
{r->max.x, maxy},
};
return result;
}
// Y is up
Rect2I CutTop(Rect2I *r, Int value) {
Int miny = r->min.y;
r->min.y = Min(r->min.y + value, r->max.y);
Rect2I result = {
{r->min.x, miny},
{r->max.x, r->min.y},
};
return result;
}
Int SafeDivide(Int a, Int b) {
if (b == 0) {
return 0;
}
return a / b;
}
bool AreOverlapping(Vec2I point, Rect2I rec) {
bool result = (point.x >= rec.min.x) && (point.x < rec.max.x) && (point.y >= rec.min.y) && (point.y < rec.max.y);
return result;
}
File diff suppressed because it is too large Load Diff
-15
View File
@@ -1,15 +0,0 @@
#include "core_platform.c"
#include "core_intrin.c"
#include "core_unicode.c"
#include "core_math.c"
#include "core_arena.c"
#include "stb_sprintf.c"
#include "core_string.c"
#include "core_string16.c"
#include "core_log.c"
#include "core_lexer.c"
#include "core_type_info.c"
#include "core_hash_table.c"
#include "core_array.c"
#include "core_math.gen.c"
#include "core_ctx.c"
-14
View File
@@ -1,14 +0,0 @@
#include "core_basic.h"
#include "core_unicode.h"
#include "core_arena.h"
#include "core_string.h"
#include "core_string16.h"
#include "core_math.h"
#include "core_type_info.h"
#include "core_lexer.h"
#include "core_log.h"
#include "core_intrin.h"
#include "core_platform.h"
#include "core_hash_table.h"
#include "core_ctx.h"
#include "core_array.h"
-202
View File
@@ -1,202 +0,0 @@
#include "core_arena.h"
#include "core_platform.h"
#include "core_intrin.h"
#include "core_ctx.h"
#if PLATFORM_ADDRESS_SANITIZER
#include <sanitizer/asan_interface.h>
#endif
#if !defined(ASAN_POISON_MEMORY_REGION)
#define MA_ASAN_POISON_MEMORY_REGION(addr, size) ((void)(addr), (void)(size))
#define MA_ASAN_UNPOISON_MEMORY_REGION(addr, size) ((void)(addr), (void)(size))
#else
#define MA_ASAN_POISON_MEMORY_REGION(addr, size) ASAN_POISON_MEMORY_REGION(addr, size)
#define MA_ASAN_UNPOISON_MEMORY_REGION(addr, size) ASAN_UNPOISON_MEMORY_REGION(addr, size)
#endif
fn b32 is_pow2(usize x) {
b32 result = (((x) & ((x)-1)) == 0);
return result;
}
fn usize get_align_offset(usize size, usize align) {
assert(is_pow2(align));
if (align == 0) return 0;
usize mask = align - 1;
usize val = size & mask;
if (val) {
val = align - val;
}
return val;
}
fn usize align_up(usize size, usize align) {
usize result = size + get_align_offset(size, align);
return result;
}
fn usize align_down(usize size, usize align) {
size += 1; // Make sure when align is 8 doesn't get rounded down to 0
usize result = size - (align - get_align_offset(size, align));
return result;
}
fn void ma_init(ma_arena_t *arena, usize reserve) {
reserve = align_up(reserve, ma_page_size);
arena->align = ma_default_alignment;
arena->data = (u8 *)os_vmem_reserve(reserve);
if (arena->data) {
arena->reserve = reserve;
}
}
fn ma_arena_t *ma_create(usize reserve) {
ma_arena_t *result = NULL;
void *data = os_vmem_reserve(reserve);
if (!data) return result;
b32 success = os_vmem_commit(data, ma_page_size);
if (!success) {
os_vmem_release(data);
return result;
}
result = (ma_arena_t *)data;
result->data = (u8 *)data;
result->reserve = reserve;
result->commit = ma_page_size;
result->len = result->base_len = sizeof(ma_arena_t);
result->align = ma_default_alignment;
return result;
}
fn void *ma_push_size_ex(ma_arena_t *arena, usize size) {
// base_len is used for bootstraping arenas, it denotes the
// space occupied by the arena. If len is smaller then base_len then
// we start to overwrite the arena itself - pure barbarism.
assert(arena->len >= arena->base_len);
usize align_offset = 0;
if (arena->align) {
align_offset = get_align_offset((usize)arena->data + arena->len, arena->align);
}
usize size_with_alignment = size + align_offset;
usize new_len = arena->len + size_with_alignment;
if (new_len > arena->commit) {
if (arena->reserve == 0) {
ma_init(arena, ma_default_reserve_size);
}
usize new_len_aligned_to_page_size = align_up(new_len, ma_page_size);
usize to_commit = new_len_aligned_to_page_size - arena->commit;
usize to_commit_clamped = CLAMP_TOP(to_commit, arena->reserve);
if (to_commit_clamped > 0) {
b32 success = os_vmem_commit(arena->data + arena->commit, to_commit_clamped);
if (success) {
MA_ASAN_UNPOISON_MEMORY_REGION(arena->data + arena->commit, to_commit_clamped);
arena->commit += to_commit_clamped;
}
}
if (new_len > arena->commit) {
invalid_codepath;
return NULL;
}
}
u8 *result = arena->data + arena->len + align_offset;
arena->len = new_len;
MA_ASAN_UNPOISON_MEMORY_REGION(result, size);
return (void *)result;
}
fn void *ma_push_size(ma_arena_t *arena, usize size) {
void *result = ma_push_size_ex(arena, size);
if (result) memory_zero(result, size);
return result;
}
fn void ma_push_arena_ex(ma_arena_t *allocator, ma_arena_t *result, usize size) {
result->data = (u8 *)ma_push_size(allocator, size);
result->reserve = size;
result->commit = size;
result->align = ma_default_alignment;
}
fn ma_arena_t *ma_push_arena(ma_arena_t *allocator, usize size) {
ma_arena_t *result = ma_push_type(allocator, ma_arena_t);
ma_push_arena_ex(allocator, result, size);
return result;
}
fn void ma_destroy(ma_arena_t *arena) {
if (arena == NULL || arena->data == NULL) return;
b32 zero_memory = (u8 *)arena != arena->data;
os_vmem_release(arena->data);
if (zero_memory) memory_zero(arena, sizeof(ma_arena_t));
}
fn void ma_set_len(ma_arena_t *arena, usize pos) {
// base_len is used for bootstraping arenas, it denotes the
// space occupied by the arena. If len is smaller then base_len then
// we start to overwrite the arena itself - pure barbarism.
assert(arena->len >= arena->base_len);
pos = CLAMP(pos, arena->base_len, arena->len);
usize size = arena->len - pos;
arena->len = pos;
MA_ASAN_POISON_MEMORY_REGION(arena->data + arena->len, size);
}
fn void ma_pop(ma_arena_t *arena, usize size) { ma_set_len(arena, arena->len - size); }
fn ma_temp_t ma_begin_temp(ma_arena_t *arena) { return (ma_temp_t){arena, arena->len}; }
fn void ma_end_temp(ma_temp_t temp) { ma_set_len(temp.arena, temp.len); }
fn void ma_set0(ma_arena_t *arena) { ma_set_len(arena, 0); }
//
// Scratch arena
fn ma_temp_t ma_begin_scratch_ex(ma_arena_t **conflicts, int conflict_count) {
ma_arena_t *unoccupied = 0;
for (int i = 0; i < lengthof(tcx->scratch); i += 1) {
ma_arena_t *from_pool = tcx->scratch + i;
unoccupied = from_pool;
for (int conflict_i = 0; conflict_i < conflict_count; conflict_i += 1) {
ma_arena_t *from_conflict = conflicts[conflict_i];
if (from_pool == from_conflict) {
unoccupied = 0;
break;
}
}
if (unoccupied) {
break;
}
}
assert(unoccupied); // failed to get free scratch memory, this is a fatal error, this shouldnt happen
ma_temp_t result = ma_begin_temp(unoccupied);
return result;
}
fn ma_temp_t ma_begin_scratch(void) {
ma_temp_t result = ma_begin_temp(tcx->scratch + 0);
return result;
}
fn ma_temp_t ma_begin_scratch1(ma_arena_t *conflict) {
ma_arena_t *conflicts[] = {conflict};
return ma_begin_scratch_ex(conflicts, 1);
}
fn ma_temp_t ma_begin_scratch2(ma_arena_t *a, ma_arena_t *b) {
ma_arena_t *conflicts[] = {a, b};
return ma_begin_scratch_ex(conflicts, 2);
}
fn void *ma_push__copy(ma_arena_t *arena, void *data, u64 size) {
void *result = ma_push_size_ex(arena, size);
if (result) {
memory_copy(result, data, size);
}
return result;
}
-59
View File
@@ -1,59 +0,0 @@
#pragma once
#include "core_basic.h"
static const usize ma_page_size = 4096;
static const usize ma_default_alignment = sizeof(void *);
static const usize ma_default_reserve_size = mib(256);
typedef struct ma_arena_t ma_arena_t;
struct ma_arena_t {
u8 *data;
usize len;
usize base_len; // to prevent self deleting the arena
usize reserve;
usize commit;
usize align;
};
typedef struct ma_temp_t ma_temp_t;
struct ma_temp_t {
ma_arena_t *arena;
usize len;
};
//
// constructors
fn void ma_init(ma_arena_t *arena, usize reserve);
fn ma_arena_t *ma_create(usize reserve);
fn void ma_destroy(ma_arena_t *arena);
//
// push
fn void *ma_push_size(ma_arena_t *arena, usize size);
fn void *ma_push_size_ex(ma_arena_t *arena, usize size);
fn ma_arena_t *ma_push_arena(ma_arena_t *allocator, usize size);
fn void ma_push_arena_ex(ma_arena_t *allocator, ma_arena_t *result, usize size);
#define ma_push_type(arena, Type) (Type *)ma_push_size((arena), sizeof(Type))
#define ma_push_array(arena, Type, count) (Type *)ma_push_size((arena), sizeof(Type) * (count))
#define ma_push_type_copy(ma, data) ma_push__copy((ma), (data), sizeof(*(data)))
#define ma_push_array_copy(ma, data, count) ma_push__copy((ma), (data), (count) * sizeof(*(data)))
//
// pop
fn void ma_set_len(ma_arena_t *arena, usize pos);
fn void ma_pop(ma_arena_t *arena, usize size);
fn void ma_set0(ma_arena_t *arena);
//
// temp
fn ma_temp_t ma_begin_temp(ma_arena_t *arena);
fn void ma_end_temp(ma_temp_t temp);
#define ma_temp_scope(name, InArena) for (ma_temp_t name = ma_begin_temp(InArena); name.arena; (ma_end_temp(name), name.arena = 0))
//
// scratch
fn ma_temp_t ma_begin_scratch_ex(ma_arena_t **conflicts, int conflict_count);
fn ma_temp_t ma_begin_scratch(void);
fn ma_temp_t ma_begin_scratch1(ma_arena_t *conflict);
#define ma_end_scratch(x) ma_end_temp(x)
#define ma_scratch_scope(x) for (ma_temp_t x = ma_begin_scratch(); x.arena; (ma_end_temp(x), x.arena = 0))
-122
View File
@@ -1,122 +0,0 @@
#include "core_array.h"
#include "core_basic.h"
#include "core_platform.h"
#include "core_ctx.h"
#include "core_intrin.h"
fn void array__init(alo_t alo, array_void_t *this, size_t item_size, i64 count) {
assert_expr(this->data == NULL);
this->data = alloc_size(alo, item_size * count);
this->cap = count;
this->len = 0;
this->alo = alo;
}
fn void array__copy(alo_t alo, array_void_t *dst, array_void_t *src, size_t item_size) {
dst->data = alloc_size(alo, item_size * src->cap);
memory_copy(dst->data, src->data, item_size * src->len);
dst->cap = src->cap;
dst->len = src->len;
dst->alo = alo;
}
fn void array__grow(array_void_t *this, size_t item_size, i64 item_count) {
if (this->len + 1 > this->cap) {
i64 new_cap = this->cap == 0 ? 16 : (this->cap + item_count - 1) * 2;
void *new_data = alloc_size(this->alo, new_cap * item_size);
if (this->data) {
memory_copy(new_data, this->data, this->len*item_size);
dealloc(this->alo, this->data);
}
this->data = new_data;
this->cap = new_cap;
}
}
fn void array__del(array_void_t *this, size_t item_size, i64 idx, i64 count) {
if (count == 0) return;
assert(idx >= 0 && idx < this->len);
assert((idx + count) > 0 && (idx + count) <= this->len);
i64 right_len = this->len - idx - count;
u8 *data = (u8 *)this->data;
memory_move(data + idx * item_size, data + (idx + count) * item_size, right_len * item_size);
this->len -= count;
}
fn void array__insert(array_void_t *this, size_t item_size, i64 idx) {
array__grow(this, item_size, 1);
assert(idx >= 0);
assert(idx <= this->len);
assert(this->alo.object);
u8 *data = (u8 *)this->data;
i64 right_len = this->len - idx;
memory_move(data + (idx + 1) * item_size, data + idx * item_size, item_size * right_len);
this->len += 1;
}
fn_test void test_array(void) {
ma_temp_t scratch = ma_begin_scratch();
{
array_i64_t arr = (array_i64_t){.alo = malot(scratch)};
for (int i = 0; i < 512; i += 1) {
array_add(&arr, i);
}
for (int i = 0; i < 512; i += 1) {
assert(arr.data[i] == i);
}
assert(arr.len == 512);
assert(arr.cap == 512);
for (int i = 511; i >= 0; i -= 1) {
i64 a = array_pop(&arr);
assert(a == i);
}
assert(arr.len == 0);
array_dealloc(&arr);
}
{
array_i64_t arr = (array_i64_t){.alo = malot(scratch)};
i64 *i = array_addn(&arr, 10);
assert(arr.len == 10 && arr.cap == 16);
i64 *j = array_addn(&arr, 2);
assert(i == arr.data);
assert(j == arr.data + 10);
array_dealloc(&arr);
}
{
array_i64_t arr = (array_i64_t){.alo = malot(scratch)};
for (int i = 0; i < 512; i += 1) {
array_add(&arr, i);
}
array_insert(&arr, 256, 111);
assert(arr.data[256] == 111);
assert(arr.data[255] == 255);
assert(arr.data[257] == 256);
assert(arr.len == 513);
array_insert(&arr, 4, 222);
assert(arr.len == 514);
assert(arr.data[4] == 222);
assert(arr.data[3] == 3);
assert(arr.data[5] == 4);
array_swapdel(&arr, 2);
assert(arr.len == 513);
assert(arr.data[2] == 511);
assert(arr.data[1] == 1);
assert(arr.data[3] == 3);
array_i64_t copy = {0};
array_copy(malot(scratch), &copy, &arr);
for (i64 i = 0; i < arr.len; i += 1) {
assert(arr.data[i] == copy.data[i]);
}
assert(copy.len == arr.len);
}
ma_end_scratch(scratch);
}
-27
View File
@@ -1,27 +0,0 @@
#pragma once
#include "core_basic.h"
#define array(type) struct { alo_t alo; type *data; i64 len; i64 cap; }
typedef array(void) array_void_t;
typedef array(i64) array_i64_t;
#define arrisz(x) sizeof((x)->data[0])
#define arrcst(x) ((array_void_t *)(x))
#define array_init(a, this, count) (array__init((a), arrcst(this), arrisz(this), (count)))
#define array_add(this, ...) (array__grow(arrcst(this), arrisz(this), 1), (this)->data[(this)->len++] = __VA_ARGS__)
#define array_pop(this) (assert_expr((this)->len > 0), (this)->data[--(this)->len])
#define array_dealloc(this) (dealloc((this)->alo, (this)->data))
#define array_addn(this, n) (array__grow(arrcst(this), arrisz(this), (n)), (this)->len += (n), &(this)->data[(this)->len - (n)])
#define array_insert(this, i, item) (array__insert(arrcst(this), arrisz(this), (i)), (this)->data[(i)] = (item))
#define array_swapdel(this, i) (assert_expr((i) < (this)->len), (this)->data[(i)] = (this)->data[--(this)->len])
#define array_del(this, i) (array__del(arrcst(this), arrisz(this), (i), 1))
#define array_deln(this, i, count) (array__del(arrcst(this), arrisz(this), (i), (count)))
#define array_copy(alo, dst, src) (array__copy((alo), arrcst(dst), (array_void_t *)(src), arrisz(dst)))
#define array_last(x) ((x)->data[(x)->len - 1])
#define array_for(type, it, array) for (type *it = (array)->data; it < (array)->data + (array)->len; it += 1)
fn void array__init(alo_t alo, array_void_t *, size_t item_size, i64 count);
fn void array__copy(alo_t alo, array_void_t *dst, array_void_t *src, size_t item_size);
fn void array__grow(array_void_t *, size_t item_size, i64 item_count);
fn void array__del(array_void_t *, size_t item_size, i64 idx, i64 count);
fn void array__insert(array_void_t *, size_t item_size, i64 idx);
-427
View File
@@ -1,427 +0,0 @@
#pragma once
#ifndef _CRT_SECURE_NO_WARNINGS
#define _CRT_SECURE_NO_WARNINGS
#endif
#if defined(__APPLE__) && defined(__MACH__)
#define PLATFORM_MAC_OS 1
#define PLATFORM_POSIX 1
#elif defined(_WIN32)
#define PLATFORM_WINDOWS 1
#elif defined(__linux__)
#define PLATFORM_POSIX 1
#define PLATFORM_LINUX 1
#elif defined(__wasm)
#define PLATFORM_WASM 1
#endif
#if defined(__clang__)
#define PLATFORM_CLANG 1
#elif defined(__GNUC__) || defined(__GNUG__)
#define PLATFORM_GCC 1
#elif defined(_MSC_VER)
#define PLATFORM_CL 1
#elif defined(__TINYC__)
#define PLATFORM_TCC 1
#endif
#if defined(__EMSCRIPTEN__)
#define PLATFORM_EMSCRIPTEN 1
#endif
#ifndef PLATFORM_EMSCRIPTEN
#define PLATFORM_EMSCRIPTEN 0
#endif
#ifndef PLATFORM_WASM
#define PLATFORM_WASM 0
#endif
#ifndef PLATFORM_WINDOWS
#define PLATFORM_WINDOWS 0
#endif
#ifndef PLATFORM_LINUX
#define PLATFORM_LINUX 0
#endif
#ifndef PLATFORM_POSIX
#define PLATFORM_POSIX 0
#endif
#ifndef PLATFORM_MAC_OS
#define PLATFORM_MAC_OS 0
#endif
#ifndef PLATFORM_CLANG
#define PLATFORM_CLANG 0
#endif
#ifndef PLATFORM_GCC
#define PLATFORM_GCC 0
#endif
#ifndef PLATFORM_CL
#define PLATFORM_CL 0
#endif
#ifndef PLATFORM_TCC
#define PLATFORM_TCC 0
#endif
#ifndef PLATFORM_ADDRESS_SANITIZER
#define PLATFORM_ADDRESS_SANITIZER 0
#endif
#ifndef PLATFORM_DEBUG_ASSERT
#define PLATFORM_DEBUG_ASSERT 1
#endif
#if PLATFORM_WINDOWS
#define SWITCH_PLATFORM_WINDOWS_WASM_ELSE(WINDOWS, WASM, ELSE) WINDOWS
#elif PLATFORM_WASM
#define SWITCH_PLATFORM_WINDOWS_WASM_ELSE(WINDOWS, WASM, ELSE) WASM
#else
#define SWITCH_PLATFORM_WINDOWS_WASM_ELSE(WINDOWS, WASM, ELSE) ELSE
#endif
#if PLATFORM_CLANG
#define IF_PLATFORM_CLANG_ELSE(IF, ELSE) IF
#else
#define IF_PLATFORM_CLANG_ELSE(IF, ELSE) ELSE
#endif
#if PLATFORM_WINDOWS
#define IF_PLATFORM_WINDOWS(x) x
#else
#define IF_PLATFORM_WINDOWS(x)
#endif
#if PLATFORM_LINUX && !defined(_GNU_SOURCE)
#define _GNU_SOURCE
#endif
#include <stdint.h>
#include <stddef.h>
#include <stdarg.h>
typedef uintptr_t usize;
typedef uint64_t u64;
typedef uint32_t u32;
typedef uint16_t u16;
typedef uint8_t u8;
typedef intptr_t isize;
typedef int64_t i64;
typedef int32_t i32;
typedef int16_t i16;
typedef int8_t i8;
typedef int64_t b64;
typedef int32_t b32;
typedef int16_t b16;
typedef int8_t b8;
typedef float f32;
typedef double f64;
#define f32_max FLT_MAX
#define f32_min FLT_MIN
#define f64_max DBL_MAX
#define f64_min DBL_MIN
#define i8_max INT8_MAX
#define i8_min INT8_MIN
#define i16_max INT16_MAX
#define i16_min INT16_MIN
#define i32_max INT32_MAX
#define i32_min INT32_MIN
#define i64_max INT64_MAX
#define i64_min INT64_MIN
#define u8_max UINT8_MAX
#define u8_min 0
#define u16_max UINT16_MAX
#define u16_min 0
#define u32_max UINT32_MAX
#define u32_min 0
#define u64_max UINT64_MAX
#define u64_min 0
#ifndef true
#define true 1
#endif
#ifndef false
#define false 0
#endif
#define fn
#define fn_test
#define gb
#define locl static
typedef union convert_f64_u64_t convert_f64_u64_t;
union convert_f64_u64_t { f64 f; u64 i; };
typedef union convert_f64_i64_t convert_f64_i64_t;
union convert_f64_i64_t { f64 f; i64 i; };
typedef union convert_f32_u32_t convert_f32_u32_t;
union convert_f32_u32_t { f32 f; u32 i; };
typedef union convert_f32_i32_t convert_f32_i32_t;
union convert_f32_i32_t { f32 f; i32 i; };
#define U64_TO_F64(x) (((convert_f64_u64_t) { .i = (x) }).f)
#define U32_TO_F32(x) (((convert_f32_u32_t) { .i = (x) }).f)
#define F64_TO_U64(x) (((convert_f64_u64_t) { .f = (x) }).i)
#define F32_TO_U32(x) (((convert_f32_u32_t) { .f = (x) }).i)
#define I64_TO_F64(x) (((convert_f64_i64_t) { .i = (x) }).f)
#define I32_TO_F32(x) (((convert_f32_i32_t) { .i = (x) }).f)
#define F64_TO_I64(x) (((convert_f64_i64_t) { .f = (x) }).i)
#define F32_TO_I32(x) (((convert_f32_i32_t) { .f = (x) }).i)
#define MIN(x,y) ((x) > (y) ? (y) : (x))
#define MAX(x,y) ((x) > (y) ? (x) : (y))
#define CLAMP_TOP(A,X) MIN(A,X)
#define CLAMP_BOT(X,B) MAX(X,B)
#define CLAMP(x,a,b) (((x)<(a))?(a):((x)>(b))?(b):(x))
#define set_bit(x) (1ULL << (x))
#define lengthof(x) ((int)(sizeof((x))/sizeof((x)[0])))
#ifndef offsetof
#define offsetof(st, m) ((usize)&(((st *)0)->m))
#endif
#define expect(x) if (!(x))
#define unused(x) (void)(x)
#define kib(x) (1024ULL * (x##ULL))
#define mib(x) (1024ULL * kib(x))
#define gib(x) (1024ULL * mib(x))
#define thousand(n) ((n)*1000)
#define million(n) ((n)*1000000)
#define billion(n) ((n)*1000000000)
#define zero_struct(x) memory_zero((x), sizeof(*(x)))
#define defer_if(begin, cond_end) for (b32 PASTE(_i_, __LINE__) = !!begin; PASTE(_i_, __LINE__); PASTE(_i_, __LINE__) = (cond_end, 0))
#define defer_block(begin, end) for (i32 PASTE(_i_, __LINE__) = (begin, 0); !PASTE(_i_, __LINE__); PASTE(_i_, __LINE__) += (end, 1))
#define stack_t(type, size) struct { type data[size]; i32 len; }
#define STACK_CAP(stack) (lengthof((stack).data))
#define STACK_EMPTY(stack) ((stack).len == 0)
#define STACK_FULL(stack) ((stack).len == STACK_CAP(stack))
#define STACK_PUSH(stack, ...) (assert_expr(!STACK_FULL(stack)), (stack).data[(stack).len++] = __VA_ARGS__)
#define STACK_POP(stack) (assert_expr(!STACK_EMPTY(stack)), (stack).data[--(stack).len])
#define STACK_TOP(stack) (assert_expr(!STACK_EMPTY(stack)), (stack).data[((stack).len-1)])
#define STRINGIFY_(S) #S
#define STRINGIFY(S) STRINGIFY_(S)
#define PASTE_(a, b) a##b
#define PASTE(a, b) PASTE_(a, b)
#define SWAP(t, a, b) do { t PASTE(temp__, __LINE__) = a; a = b; b = PASTE(temp__, __LINE__); } while(0)
#define SWAP_PTR(t, a, b) do { t PASTE(temp__, __LINE__) = *a; *a = *b; *b = PASTE(temp__, __LINE__); } while(0)
#define CODE(...) #__VA_ARGS__
#if PLATFORM_CL || (PLATFORM_CLANG && PLATFORM_WINDOWS)
#pragma section(".rdata$", read)
#define gb_read_only __declspec(allocate(".rdata$"))
#elif PLATFORM_CLANG && PLATFORM_LINUX
#define gb_read_only __attribute__((section(".rodata")))
#else
#define gb_read_only
#endif
#if PLATFORM_CL
#define fn_inline __forceinline
#elif PLATFORM_CLANG || PLATFORM_GCC
#define fn_inline __attribute__((always_inline))
#else
#define fn_inline
#endif
#ifndef FILE_AND_LINE_GCC_FORMAT
#define FILE_AND_LINE __FILE__ "(" STRINGIFY(__LINE__) ")"
#else
#define FILE_AND_LINE __FILE__ ":" STRINGIFY(__LINE__)
#endif
#if PLATFORM_WINDOWS
int IsDebuggerPresent(void);
#define debug__break() (IsDebuggerPresent() && (__debugbreak(), 1))
#elif PLATFORM_UNIX
// https://github.com/r-lyeh/tinybits/blob/master/tinyassert.c
#include <signal.h>
static void os_unix_sigtrap(int signum) { signal(SIGTRAP, SIG_DFL); }
#define debug__break() (signal(SIGTRAP, os_unix_sigtrap), raise(SIGTRAP))
#elif PLATFORM_WASM
void wasm_trap(void);
#define debug__break() wasm_trap()
#elif PLATFORM_TCC
#define debug__break() raise(SIGTRAP)
#else
#define debug__break() __builtin_trap()
#endif
#define debug_break() (debug__break(), 1)
#if PLATFORM_WASM | PLATFORM_TCC
#define gb_thread
#elif PLATFORM_GCC | PLATFORM_CLANG
#define gb_thread __thread
#elif PLATFORM_CL
#define gb_thread __declspec(thread)
#else
#define gb_thread _Thread_local
#endif
#if PLATFORM_CL
#pragma warning(disable: 4116)
#endif
// Single linked list Queue
#define SLLQ_APPEND_EX(f, l, n, next) \
do { \
assert_expr((n)->next == NULL); \
if ((f) == 0) { \
(f) = (l) = (n); \
} else { \
(l) = (l)->next = (n); \
} \
} while (0)
#define SLLQ_APPEND(f, l, n) SLLQ_APPEND_EX(f, l, n, next)
#define SLLQ_PREPEND_EX(f, l, n, next) \
do { \
assert_expr((n)->next == NULL); \
if ((f) == 0) { \
(f) = (l) = (n); \
} else { \
(n)->next = (f); \
(f) = (n); \
} \
} while (0)
#define SLLQ_PREPEND(f, l, n) SLLQ_PREPEND_EX(f, l, n, next)
#define SLLQ_REMOVE_FIRST_EX(f, l, next) \
do { \
if ((f) == (l)) { \
(f) = (l) = 0; \
} else { \
(f) = (f)->next; \
} \
} while (0)
#define SLLQ_REMOVE_FIRST(f, l) SLLQ_REMOVE_FIRST_EX(f, l, next)
// Singly linked list stack
#define SLLS_PUSH_EX(stack_base, new_stack_base, next) \
do { \
(new_stack_base)->next = (stack_base); \
(stack_base) = (new_stack_base); \
} while (0)
#define SLLS_PUSH(stack_base, new_stack_base) \
SLLS_PUSH_EX(stack_base, new_stack_base, next)
#define SLLS_POP(stack_base) ((stack_base) = (stack_base)->next)
#define SLLS_POP_AND_STORE(stack_base, out_node) \
do { \
if (stack_base) { \
(out_node) = (stack_base); \
(stack_base) = (stack_base)->next; \
(out_node)->next = 0; \
} \
} while (0)
// Doubly linked list Queue
#define DLLQ_APPEND_EX(f, l, node, next, prev) \
do { \
assert_expr((node)->next == NULL); \
assert_expr((node)->prev == NULL); \
if ((f) == 0) { \
(f) = (l) = (node); \
} else { \
(l)->next = (node); \
(node)->prev = (l); \
(l) = (node); \
} \
} while (0)
#define DLLQ_APPEND(f, l, node) DLLQ_APPEND_EX(f, l, node, next, prev)
#define DLLQ_PREPEND_EX(f, l, node, next, prev) \
do { \
assert_expr((node)->next == NULL); \
assert_expr((node)->prev == NULL); \
if ((f) == 0) { \
(f) = (l) = (node); \
} else { \
(node)->next = (f); \
(f)->prev = (node); \
(f) = (node); \
} \
} while (0)
#define DLLQ_PREPEND(f, l, node) DLLQ_PREPEND_EX(f, l, node, next, prev)
#define DLLQ_CONTAINS(f, l, n, next, prev) for (
#define DLLQ_REMOVE_EX(first, last, node, next, prev) \
do { \
if ((first) == (last)) { \
assert_expr((node) == (first)); \
(first) = (last) = 0; \
} else if ((last) == (node)) { \
(last) = (last)->prev; \
(last)->next = 0; \
} else if ((first) == (node)) { \
(first) = (first)->next; \
(first)->prev = 0; \
} else { \
(node)->prev->next = (node)->next; \
(node)->next->prev = (node)->prev; \
} \
if (node) { \
(node)->prev = 0; \
(node)->next = 0; \
} \
} while (0)
#define DLLQ_REMOVE(first, last, node) DLLQ_REMOVE_EX(first, last, node, next, prev)
// Doubly linked list Stack
#define DLLS_PUSH_EX(first, node, next, prev) \
do { \
assert_expr((node)->next == NULL); \
assert_expr((node)->prev == NULL); \
(node)->next = (first); \
if ((first)) \
(first)->prev = (node); \
(first) = (node); \
} while (0)
#define DLLS_PUSH(first, node) DLLS_PUSH_EX(first, node, next, prev)
#define DLLS_REMOVE_EX(first, node, next, prev) \
do { \
if ((node) == (first)) { \
(first) = (first)->next; \
if ((first)) \
(first)->prev = 0; \
} else { \
(node)->prev->next = (node)->next; \
if ((node)->next) \
(node)->next->prev = (node)->prev; \
} \
if (node) { \
(node)->prev = 0; \
(node)->next = 0; \
} \
} while (0)
#define DLLS_REMOVE(first, node) DLLS_REMOVE_EX(first, node, next, prev)
typedef enum {
alokind_alloc,
alokind_dealloc,
} alokind_t;
typedef struct alo_t alo_t;
struct alo_t {
void *object;
void *(*proc)(alo_t alo, alokind_t kind, void *ptr, size_t size);
};
-30
View File
@@ -1,30 +0,0 @@
#include "core_ctx.h"
#include "core_platform.h"
gb_thread thread_ctx_t *tcx;
fn void *ma_arena_alo_proc(alo_t alo, alokind_t kind, void *ptr, size_t size) {
unused(ptr);
if (kind == alokind_alloc) {
return ma_push_size(alo.object, size);
} else if (kind == alokind_dealloc) {
return NULL;
} else_is_invalid;
return NULL;
}
fn alo_t malo(ma_arena_t *arena) {
return (alo_t){arena, ma_arena_alo_proc};
}
fn alo_t malot(ma_temp_t temp) {
return malo(temp.arena);
}
fn void dealloc(alo_t alo, void *ptr) {
alo.proc(alo, alokind_dealloc, ptr, 0);
}
fn void *alloc_size(alo_t alo, size_t size) {
return alo.proc(alo, alokind_alloc, NULL, size);
}
-34
View File
@@ -1,34 +0,0 @@
#pragma once
#include "core_arena.h"
#include "core_log.h"
typedef struct thread_ctx_t thread_ctx_t;
struct thread_ctx_t {
ma_arena_t scratch[3];
ma_arena_t temp; // application specific arena
// I probably want to discourage using it implicitly like: tcx.perm, instead just pass it around
// to functions that allocate pernament memory. temp and scratch very nicely create reusable code
// perm is basically gb state so it would be nice to annotate which functions are reusable
// and which functions have state
ma_arena_t perm;
void *app_ctx;
void *rn_ctx;
void *ui_ctx;
void *te_ctx;
void *user_ctx;
logger_t log;
int thread_index;
};
#define alloc_type(alo, type) (type *)alloc_size((aloc), sizeof(type))
#define alloc_array(alo, type, count) (type *)alloc_size((alo), sizeof(type) * (count))
fn alo_t malo(ma_arena_t *arena);
fn alo_t malot(ma_temp_t temp);
fn void dealloc(alo_t alo, void *ptr);
fn void *alloc_size(alo_t alo, size_t size);
fn int tcx_alloc_id(void);
extern gb_thread thread_ctx_t *tcx;
-217
View File
@@ -1,217 +0,0 @@
#include "core_hash_table.h"
#include "core_platform.h"
// xorshift64
fn u64 get_random_u64(random_seed_t *seed) {
u64 x = seed->a;
x ^= x << 13;
x ^= x >> 7;
x ^= x << 17;
return seed->a = x;
}
fn u64 get_random_in_range_u64(random_seed_t *seed, u64 start, u64 one_past_end) {
u64 r = get_random_u64(seed);
u64 diff = one_past_end - start;
u64 rr = r % diff;
u64 rrr = rr + start;
return rrr;
}
fn i64 get_random_in_range_i64(random_seed_t *seed, i64 start, i64 one_past_end) {
u64 r = get_random_u64(seed);
i64 diff = one_past_end - start;
u64 rr = r % diff;
i64 rrr = (i64)rr + start;
return rrr;
}
fn f64 get_random_f64(random_seed_t *seed) {
f64 random = (f64)get_random_in_range_u64(seed, 0, UINT32_MAX);
f64 result = random / (f64)(UINT32_MAX - 1u);
return result;
}
fn u64 hash_data(s8_t string) {
u8 *data = (u8 *)string.str;
u64 hash = (u64)14695981039346656037ULL;
for (i64 i = 0; i < string.len; i++) {
hash = hash ^ (u64)(data[i]);
hash = hash * (u64)1099511628211ULL;
}
return hash;
}
fn u64 hash_mix(u64 x, u64 y) {
x ^= y;
x *= 0xff51afd7ed558ccd;
x ^= x >> 32;
return x;
}
fn ht_t *ht_create(ma_arena_t *arena, i32 size) {
ht_t *result = ma_push_type(arena, ht_t);
result->buckets = ma_push_array(arena, ht_bucket_t, size);
result->bucket_count = size;
result->arena = arena;
return result;
}
fn ht_node_t *ht_insert_kv(ht_t *ht, u64 hash, ht_key_value_t kv) {
ht_node_t *result = ma_push_type(ht->arena, ht_node_t);
result->kv = kv;
i64 idx = hash % ht->bucket_count;
SLLQ_APPEND(ht->buckets[idx].first, ht->buckets[idx].last, result);
ht->item_count += 1;
return result;
}
fn ht_node_t *ht_insert_u64(ht_t *ht, u64 key, u64 value) {
u64 hash = hash_data(s8_struct(key));
return ht_insert_kv(ht, hash, (ht_key_value_t){.key_u64 = key, .value_u64 = value});
}
fn ht_node_t *ht_insert_ptr(ht_t *ht, void *key, void *value) {
return ht_insert_u64(ht, (u64)key, (u64)value);
}
fn ht_node_t *ht_insert_string(ht_t *ht, s8_t key, s8_t value) {
u64 hash = hash_data(key);
return ht_insert_kv(ht, hash, (ht_key_value_t){.key_string = key, .value_string = value});
}
fn ht_node_t *ht_insert_string_ptr(ht_t *ht, s8_t key, void *value) {
u64 hash = hash_data(key);
return ht_insert_kv(ht, hash, (ht_key_value_t){.key_string = key, .value_ptr = value});
}
fn ht_node_t *ht_search_u64_ex(ht_t *ht, u64 key) {
u64 hash = hash_data(s8_struct(key));
i64 idx = hash % ht->bucket_count;
ht_bucket_t *bucket = ht->buckets + idx;
for (ht_node_t *it = bucket->first; it; it = it->next) {
if (it->kv.key_u64 == key) {
return it;
}
}
return NULL;
}
fn ht_node_t *ht_search_ptr_ex(ht_t *ht, void *key) {
u64 hash = hash_data(s8_struct(key));
i64 idx = hash % ht->bucket_count;
ht_bucket_t *bucket = ht->buckets + idx;
for (ht_node_t *it = bucket->first; it; it = it->next) {
if (it->kv.key_ptr == key) {
return it;
}
}
return NULL;
}
fn ht_node_t *ht_search_string_ex(ht_t *ht, s8_t key) {
u64 hash = hash_data(key);
i64 idx = hash % ht->bucket_count;
ht_bucket_t *bucket = ht->buckets + idx;
for (ht_node_t *it = bucket->first; it; it = it->next) {
if (s8_are_equal(it->kv.key_string, key)) {
return it;
}
}
return NULL;
}
fn u64 *ht_search_u64(ht_t *ht, u64 key) {
ht_node_t *node = ht_search_u64_ex(ht, key);
if (node) return &node->kv.value_u64;
return NULL;
}
fn void **ht_search_ptr(ht_t *ht, void *key) {
ht_node_t *node = ht_search_ptr_ex(ht, key);
if (node) return &node->kv.value_ptr;
return NULL;
}
fn s8_t *ht_search_string(ht_t *ht, s8_t key) {
ht_node_t *node = ht_search_string_ex(ht, key);
if (node) return &node->kv.value_string;
return NULL;
}
fn void **ht_search_string_ptr(ht_t *ht, s8_t key) {
ht_node_t *node = ht_search_string_ex(ht, key);
if (node) return &node->kv.value_ptr;
return NULL;
}
///////////////////////////////
// string interning
fn s8i_t *intern_string(ht_t *ht, s8_t string) {
s8_t *item = ht_search_string(ht, string);
if (!item) {
string = s8_copy(ht->arena, string);
ht_node_t *node = ht_insert_string(ht, string, string);
item = &node->kv.value_string;
}
return item;
}
fn s8i_t *internf(ht_t *ht, char *str, ...) {
S8_FMT(ht->arena, str, string);
return intern_string(ht, string);
}
///////////////////////////////
// testing
fn_test void test_hash_table(void) {
ma_temp_t scratch = ma_begin_scratch();
{
ht_t *ht = ht_create(scratch.arena, 16);
for (u64 i = 0; i < 128; i += 1) {
ht_insert_u64(ht, i, i);
ht_node_t *node = ht_search_u64_ex(ht, i);
assert_expr(node->kv.value_u64 == i);
assert(node->kv.key_u64 == i);
}
for (u64 i = 0; i < 128; i += 1) {
ht_node_t *node = ht_search_u64_ex(ht, i);
assert(node->kv.value_u64 == i);
assert(node->kv.key_u64 == i);
}
ht_node_t *node = ht_search_u64_ex(ht, 1111);
assert(node == NULL);
}
{
ht_t *ht = ht_create(scratch.arena, 16);
for (i32 i = 0; i < 128; i += 1) {
s8_t s = s8_printf(scratch.arena, "%d", i);
ht_insert_string(ht, s, s);
ht_node_t *node = ht_search_string_ex(ht, s);
assert(s8_are_equal(node->kv.value_string, s));
assert(s8_are_equal(node->kv.key_string, s));
}
ht_node_t *node = ht_search_string_ex(ht, s8("memes"));
assert(node == NULL);
}
ma_end_scratch(scratch);
}
fn_test void test_intern_table(void) {
ma_temp_t scratch = ma_begin_scratch();
ht_t *ht = ht_create(scratch.arena, 4);
assert(internf(ht, "asd") == internf(ht, "asd"));
assert(internf(ht, "asdf") != internf(ht, "asd"));
assert(internf(ht, "asdf") == internf(ht, "asdf"));
assert(internf(ht, "123asdf") == internf(ht, "123asdf"));
assert(internf(ht, "123asdf") != internf(ht, "133asdf"));
assert(internf(ht, "") == internf(ht, ""));
assert(internf(ht, "") != internf(ht, "a"));
ma_end_scratch(scratch);
}
-73
View File
@@ -1,73 +0,0 @@
#pragma once
#include "core_basic.h"
#include "core_arena.h"
#include "core_string.h"
typedef struct ht_key_value_t ht_key_value_t;
struct ht_key_value_t {
union {
s8_t key_string;
u64 key_u64;
void *key_ptr;
};
union {
s8_t value_string;
void *value_ptr;
u64 value_u64;
};
};
typedef struct ht_node_t ht_node_t;
struct ht_node_t {
ht_node_t *next;
ht_key_value_t kv;
};
typedef struct ht_bucket_t ht_bucket_t;
struct ht_bucket_t {
ht_node_t *first;
ht_node_t *last;
};
typedef struct ht_t ht_t;
struct ht_t {
ma_arena_t *arena;
i32 item_count;
i32 bucket_count;
ht_bucket_t *buckets;
};
fn ht_t *ht_create (ma_arena_t *arena, i32 size);
fn ht_node_t *ht_insert_kv (ht_t *ht, u64 hash, ht_key_value_t kv);
fn ht_node_t *ht_insert_u64 (ht_t *ht, u64 key, u64 value);
fn ht_node_t *ht_insert_ptr (ht_t *ht, void *key, void *value);
fn ht_node_t *ht_insert_string (ht_t *ht, s8_t key, s8_t value);
fn ht_node_t *ht_insert_string_ptr (ht_t *ht, s8_t key, void *value);
fn u64 *ht_search_u64 (ht_t *ht, u64 key);
fn void **ht_search_ptr (ht_t *ht, void *key);
fn s8_t *ht_search_string (ht_t *ht, s8_t key);
fn void **ht_search_string_ptr (ht_t *ht, s8_t key);
fn ht_node_t *ht_search_u64_ex (ht_t *ht, u64 key);
fn ht_node_t *ht_search_ptr_ex (ht_t *ht, void *key);
fn ht_node_t *ht_search_string_ex (ht_t *ht, s8_t key);
///////////////////////////////
// string interning
#define s8i_t s8_t
fn s8i_t *intern_string(ht_t *ht, s8_t string);
fn s8i_t *internf(ht_t *ht, char *str, ...);
///////////////////////////////
// Hashing
typedef struct random_seed_t random_seed_t;
struct random_seed_t {
u64 a;
};
fn u64 get_random_u64(random_seed_t *seed);
fn u64 get_random_in_range_u64(random_seed_t *seed, u64 start, u64 one_past_end);
fn i64 get_random_in_range_i64(random_seed_t *seed, i64 start, i64 one_past_end);
fn f64 get_random_f64(random_seed_t *seed);
fn u64 hash_data(s8_t string);
fn u64 hash_mix(u64 x, u64 y);
-242
View File
@@ -1,242 +0,0 @@
#include "core_intrin.h"
#include "core_basic.h"
#include "core_platform.h"
fn void memory_copy(void *dst, void *src, usize n) {
IF_PLATFORM_CLANG_ELSE(__builtin_memcpy(dst, src, n), memcpy(dst, src, n));
}
fn void memory_move(void *dest, const void *src, usize n) {
IF_PLATFORM_CLANG_ELSE(__builtin_memmove(dest, src, n), memmove(dest, src, n));
}
fn void memory_set(void *dst, i32 c, usize size) {
IF_PLATFORM_CLANG_ELSE(__builtin_memset(dst, c, size), memset(dst, c, size));
}
fn int bad_memory__compare(void *left, void *right, usize size) {
u8 *l = left;
u8 *r = right;
for (usize i = 0; i < size; i += 1) {
if (l[i] != r[i]) return 1;
}
return 0;
}
fn b32 memory_equal(void *left, void *right, usize size) {
int cmp = IF_PLATFORM_CLANG_ELSE(bad_memory__compare(left, right, size), memcmp(left, right, size));
return cmp == 0;
}
fn void memory_zero(void *dst, usize size) {
memory_set(dst, 0, size);
}
fn f32 f32_sqrt(f32 x) { return IF_PLATFORM_CLANG_ELSE(__builtin_sqrtf(x), sqrtf(x)); }
fn f64 f64_sqrt(f64 x) { return IF_PLATFORM_CLANG_ELSE(__builtin_sqrt(x), sqrt(x)); }
fn f32 f32_ceil(f32 x) { return IF_PLATFORM_CLANG_ELSE(__builtin_ceilf(x), ceilf(x)); }
fn f64 f64_ceil(f64 x) { return IF_PLATFORM_CLANG_ELSE(__builtin_ceil(x), ceil(x)); }
fn f32 f32_floor(f32 x) { return IF_PLATFORM_CLANG_ELSE(__builtin_floorf(x), floorf(x)); }
fn f64 f64_floor(f64 x) { return IF_PLATFORM_CLANG_ELSE(__builtin_floor(x), floor(x)); }
fn f32 f32_abs(f32 x) { return IF_PLATFORM_CLANG_ELSE(__builtin_fabsf(x), fabsf(x)); }
fn f64 f64_abs(f64 x) { return IF_PLATFORM_CLANG_ELSE(__builtin_fabs(x), fabs(x)); }
// fn f32 f32_round(f32 x) { return IF_PLATFORM_CLANG_ELSE(__builtin_roundf(x), roundf(x)); }
fn f64 f64_round(f64 x) { return IF_PLATFORM_CLANG_ELSE(__builtin_round(x), round(x)); }
fn f64 f64_mod(f64 a, f64 b) { return IF_PLATFORM_CLANG_ELSE(__builtin_fmod(a, b), fmod(a, b)); }
fn f32 f32_mod(f32 a, f32 b) { return IF_PLATFORM_CLANG_ELSE(__builtin_fmodf(a, b), fmodf(a, b)); }
/* https://gitlab.com/nakst/essence/-/blob/master/shared/math.cpp
**
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
** SOFTWARE.
**
*/
fn f64 f64_exp2(f64 x) {
f64 a = f64_floor(x * 8);
int64_t ai = (i64)a;
if (ai < -1024) {
return 0;
}
f64 b = x - a / 8;
f64 y = U64_TO_F64(0x3FF0000000000000) +
b * (U64_TO_F64(0x3FE62E42FEFA3A00) +
b * (U64_TO_F64(0x3FCEBFBDFF829140) +
b * (U64_TO_F64(0x3FAC6B08D73C4A40) +
b * (U64_TO_F64(0x3F83B2AB53873280) +
b * (U64_TO_F64(0x3F55D88F363C6C00) +
b * (U64_TO_F64(0x3F242C003E4A2000) +
b * U64_TO_F64(0x3EF0B291F6C00000)))))));
f64 m[8] = {
U64_TO_F64(0x3FF0000000000000),
U64_TO_F64(0x3FF172B83C7D517B),
U64_TO_F64(0x3FF306FE0A31B715),
U64_TO_F64(0x3FF4BFDAD5362A27),
U64_TO_F64(0x3FF6A09E667F3BCD),
U64_TO_F64(0x3FF8ACE5422AA0DB),
U64_TO_F64(0x3FFAE89F995AD3AD),
U64_TO_F64(0x3FFD5818DCFBA487),
};
y *= m[ai & 7];
convert_f64_u64_t c;
c.f = y;
c.i += (ai >> 3) << 52;
return c.f;
}
fn f32 f32_exp2(f32 x) {
f32 a = f32_floor(x);
i32 ai = (i32)a;
if (ai < -128) {
return 0;
}
f32 b = x - a;
f32 y = U32_TO_F32(0x3F7FFFFE) + b * (U32_TO_F32(0x3F31729A) + b * (U32_TO_F32(0x3E75E700) + b * (U32_TO_F32(0x3D64D520) + b * (U32_TO_F32(0x3C128280) + b * U32_TO_F32(0x3AF89400)))));
convert_f32_u32_t c;
c.f = y;
c.i += ai << 23;
return c.f;
}
fn f64 f64_log2(f64 x) {
convert_f64_u64_t c;
c.f = x;
int64_t e = ((c.i >> 52) & 2047) - 0x3FF;
c.i = (c.i & ~((uint64_t)0x7FF << 52)) + ((uint64_t)0x3FF << 52);
x = c.f;
f64 a;
if (x < 1.125) {
a = 0;
} else if (x < 1.250) {
x *= 1.125 / 1.250;
a = U64_TO_F64(0xBFC374D65D9E608E);
} else if (x < 1.375) {
x *= 1.125 / 1.375;
a = U64_TO_F64(0xBFD28746C334FECB);
} else if (x < 1.500) {
x *= 1.125 / 1.500;
a = U64_TO_F64(0xBFDA8FF971810A5E);
} else if (x < 1.625) {
x *= 1.125 / 1.625;
a = U64_TO_F64(0xBFE0F9F9FFC8932A);
} else if (x < 1.750) {
x *= 1.125 / 1.750;
a = U64_TO_F64(0xBFE465D36ED11B11);
} else if (x < 1.875) {
x *= 1.125 / 1.875;
a = U64_TO_F64(0xBFE79538DEA712F5);
} else {
x *= 1.125 / 2.000;
a = U64_TO_F64(0xBFEA8FF971810A5E);
}
f64 y = U64_TO_F64(0xC00FF8445026AD97) + x * (U64_TO_F64(0x40287A7A02D9353F) + x * (U64_TO_F64(0xC03711C58D55CEE2) + x * (U64_TO_F64(0x4040E8263C321A26) + x * (U64_TO_F64(0xC041EB22EA691BB3) + x * (U64_TO_F64(0x403B00FB376D1F10) + x * (U64_TO_F64(0xC02C416ABE857241) + x * (U64_TO_F64(0x40138BA7FAA3523A) + x * (U64_TO_F64(0xBFF019731AF80316) + x * U64_TO_F64(0x3FB7F1CD3852C200)))))))));
return y - a + e;
}
fn f32 f32_log2(f32 x) {
// TODO f32_log2(0.9999971379999999f) gives 0.00000143051147460938 (should be negative!!).
convert_f32_u32_t c;
c.f = x;
i32 e = ((c.i >> 23) & 255) - 0x7F;
c.i = (c.i & ~(0xFF << 23)) + (0x7F << 23);
x = c.f;
f32 y = U32_TO_F32(0xC05B5154) + x * (U32_TO_F32(0x410297C6) + x * (U32_TO_F32(0xC1205CEB) + x * (U32_TO_F32(0x4114DF63) + x * (U32_TO_F32(0xC0C0DBBB) + x * (U32_TO_F32(0x402942C6) + x * (U32_TO_F32(0xBF3FF98A) + x * (U32_TO_F32(0x3DFE1050) + x * U32_TO_F32(0xBC151480))))))));
return y + e;
}
fn f64 f64_pow(f64 x, f64 y) {
return f64_exp2(y * f64_log2(x));
}
fn f32 f32_pow(f32 x, f32 y) {
return f32_exp2(y * f32_log2(x));
}
//
/* https://sourceware.org/git/gitweb.cgi?p=newlib-cygwin.git;a=blob;f=newlib/libm/common/s_round.c;hb=master
* ====================================================
* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
*
* Developed at SunPro, a Sun Microsystems, Inc. business.
* Permission to use, copy, modify, and distribute this
* software is freely granted, provided that this notice
* is preserved.
* ====================================================
**/
fn f32 f32_round(f32 x) {
u32 w = F32_TO_U32(x);
/* Most significant word, least significant word. */
int exponent_less_127;
/* Extract exponent field. */
exponent_less_127 = (int)((w & 0x7f800000) >> 23) - 127;
if (exponent_less_127 < 23) {
if (exponent_less_127 < 0) {
w &= 0x80000000;
if (exponent_less_127 == -1)
/* Result is +1.0 or -1.0. */
w |= ((u32)127 << 23);
} else {
unsigned int exponent_mask = 0x007fffff >> exponent_less_127;
if ((w & exponent_mask) == 0)
/* x has an integral value. */
return x;
w += 0x00400000 >> exponent_less_127;
w &= ~exponent_mask;
}
} else {
if (exponent_less_127 == 128)
/* x is NaN or infinite. */
return x + x;
else
return x;
}
x = U32_TO_F32(w);
return x;
}
///////////////////////////////
// other
fn u32 u32_safe_cast(u64 v) {
assert_expr(v <= u32_max);
return (u32)v;
}
fn u16 u16_safe_cast(u64 v) {
assert(v <= u16_max);
return (u16)v;
}
fn u8 u8_safe_cast(u64 v) {
assert(v <= u8_max);
return (u8)v;
}
fn i32 i32_safe_cast(i64 v) {
assert(v >= i32_min && v <= i32_max);
return (i32)v;
}
-32
View File
@@ -1,32 +0,0 @@
#pragma once
#include "core_basic.h"
fn void memory_copy(void *dst, void *src, usize n);
fn void memory_move(void *dest, const void *src, usize n);
fn void memory_set(void *dst, i32 c, usize size);
fn b32 memory_equal(void *left, void *right, usize size);
fn void memory_zero(void *dst, usize size);
fn f32 f32_sqrt(f32 x);
fn f64 f64_sqrt(f64 x);
fn f32 f32_ceil(f32 x);
fn f64 f64_ceil(f64 x);
fn f32 f32_floor(f32 x);
fn f64 f64_floor(f64 x);
fn f32 f32_abs(f32 x);
fn f64 f64_abs(f64 x);
fn f32 f32_round(f32 x);
fn f64 f64_round(f64 x);
fn f64 f64_mod(f64 a, f64 b);
fn f32 f32_mod(f32 a, f32 b);
fn f64 f64_exp2(f64 x);
fn f32 f32_exp2(f32 x);
fn f64 f64_log2(f64 x);
fn f32 f32_log2(f32 x);
fn f64 f64_pow(f64 x, f64 y);
fn f32 f32_pow(f32 x, f32 y);
fn f32 f32_round(f32 x);
fn u32 u32_safe_cast(u64 v);
fn u16 u16_safe_cast(u64 v);
fn u8 u8_safe_cast(u64 v);
fn i32 i32_safe_cast(i64 v);
-469
View File
@@ -1,469 +0,0 @@
#include "core_lexer.h"
#include "core_log.h"
#include "core_platform.h"
#include "core_ctx.h"
#define lex_error(TOKEN, STRING) do {\
errorf(STRING);\
TOKEN->kind = lex_kind_error;\
TOKEN->string = s8(STRING);\
} while (0)
fn lexer_t lex_make(s8_t stream, char *file_name) {
lexer_t result = {.at = stream.str, .end = stream.str + stream.len, .file = file_name};
return result;
}
fn b32 lex_at_end(lexer_t *lex) {
b32 result = lex->at >= lex->end;
return result;
}
fn void lex_advance(lexer_t *lex) {
if (lex_at_end(lex)) return;
if (lex->at[0] == '\n') { lex->column = 0; lex->line += 1; }
lex->column += 1;
lex->at += 1;
}
fn b32 lex_match(lexer_t *lex, char c) {
if (lex->at[0] == c) {
lex_advance(lex);
return true;
}
return false;
}
fn void lex_eat_whitespace(lexer_t *lex) {
for (;;) {
if (char_is_whitespace(lex->at[0])) {
if (lex->at[0] == '\n') lex->inside_macro = false;
lex_advance(lex);
} else if (lex->at[0] == '\\' && lex->at[1] == '\n') {
lex_advance(lex); lex_advance(lex);
} else if (lex->at[0] == '\\' && lex->at[1] == '\r' && lex->at[2] == '\n') {
lex_advance(lex); lex_advance(lex); lex_advance(lex);
} else {
break;
}
}
}
fn void lex_eat_macro_whitespace(lexer_t *lex) {
while (lex->at[0] == ' ' || lex->at[0] == '\t') lex_advance(lex);
}
fn void lex_suffix(lexer_t *lex, lex_t *token) {
if (lex_match(lex, 'f')) {
token->kind = lex_kind_real;
token->suffix = lex_suffix_f;
} else if (lex_match(lex, 'd')) {
token->kind = lex_kind_real;
token->suffix = lex_suffix_d;
} else if (token->kind == lex_kind_integer && ((lex->at[0] == 'u' && lex->at[1] == 'l' && lex->at[2] == 'l') || (lex->at[0] == 'U' && lex->at[1] == 'L' && lex->at[2] == 'L'))) {
token->suffix = lex_suffix_ull;
lex_advance(lex); lex_advance(lex); lex_advance(lex);
} else if (token->kind == lex_kind_integer && ((lex->at[0] == 'u' && lex->at[1] == 'l') || (lex->at[0] == 'U' && lex->at[1] == 'L'))) {
token->suffix = lex_suffix_ul;
lex_advance(lex); lex_advance(lex);
} else if (token->kind == lex_kind_integer && (lex->at[0] == 'l' || lex->at[0] == 'L')) {
token->suffix = lex_suffix_l;
lex_advance(lex);
} else if (token->kind == lex_kind_integer && ((lex->at[0] == 'l' && lex->at[1] == 'l') || (lex->at[0] == 'L' && lex->at[1] == 'L'))) {
token->suffix = lex_suffix_ll;
lex_advance(lex); lex_advance(lex);
}
}
fn void lex_eat_number(lexer_t *lex, lex_t *token) {
token->kind = lex_kind_integer;
for (;;) {
if (char_is_digit(lex->at[0])) {
lex_advance(lex);
continue;
}
if (lex_match(lex, '.')) {
if (token->kind == lex_kind_real) {
lex_error(token, "multiple '.' periods in floating point number literal");
return;
}
token->kind = lex_kind_real;
continue;
}
break;
}
lex_suffix(lex, token);
}
fn void lex_eat_until(lexer_t *lex, char c) {
while (lex->at[0] != c && !lex_at_end(lex)) lex_advance(lex);
}
fn void lex_eat_string(lexer_t *lex, lex_t *token) {
token->kind = lex_kind_string;
for (;;) {
if (lex->at[0] == '\\') {
lex_advance(lex);
} else if (lex_match(lex, token->str[0])) {
break;
}
if (lex->at[0] == 0) {
lex_error(token, "unclosed string");
return;
}
lex_advance(lex);
}
}
fn b32 lex_macro(lexer_t *lex, lex_t *token) {
lex_eat_macro_whitespace(lex);
token->str = lex->at;
while (char_is_alphabetic(lex->at[0])) lex_advance(lex);
token->len = (i32)(lex->at - token->str);
if (s8_are_equal(token->string, s8("define"))) {
token->kind = lex_kind_preproc_define;
} else if (s8_are_equal(token->string, s8("ifdef"))) {
token->kind = lex_kind_preproc_ifdef;
} else if (s8_are_equal(token->string, s8("ifndef"))) {
token->kind = lex_kind_preproc_ifndef;
} else if (s8_are_equal(token->string, s8("include"))) {
token->kind = lex_kind_preproc_include;
lex_eat_macro_whitespace(lex);
char end = 0;
if (lex_match(lex, '"')) {
end = '"';
} else if (lex_match(lex, '<')) {
end = '>';
token->system_include = true;
} else {
lex_error(token, "invalid include directive, should be followed by string or '<'");
return false;
}
token->str = lex->at;
while (lex->at[0] != end) {
if (lex_at_end(lex)) {
lex_error(token, "invalid include directive, reached end of file");
return false;
}
if (lex->at[0] == '\n') {
lex_error(token, "invalid include directive, reached end of line");
return false;
}
lex_advance(lex);
}
lex_advance(lex);
} else if (s8_are_equal(token->string, s8("if"))) {
token->kind = lex_kind_preproc_if;
} else if (s8_are_equal(token->string, s8("endif"))) {
token->kind = lex_kind_preproc_endif;
} else if (s8_are_equal(token->string, s8("error"))) {
token->kind = lex_kind_preproc_error;
lex_eat_macro_whitespace(lex);
token->str = lex->at;
lex_eat_until(lex, '\n');
} else if (s8_are_equal(token->string, s8("else"))) {
token->kind = lex_kind_preproc_else;
} else if (s8_are_equal(token->string, s8("elif"))) {
token->kind = lex_kind_preproc_elif;
} else if (s8_are_equal(token->string, s8("pragma"))) {
token->kind = lex_kind_preproc_pragma;
} else if (s8_are_equal(token->string, s8("undef"))) {
token->kind = lex_kind_preproc_undef;
} else {
return false;
}
return true;
}
#define LEX_CASE3(C1, K1, C2, K2, C3, K3) \
case C1: { \
token->kind = K1; \
if (lex_match(lex, C2)) { \
lex_advance(lex); \
token->kind = K2; \
} else if (lex_match(lex, C3)) { \
lex_advance(lex); \
token->kind = K3; \
} \
} break
fn void lex_token_ex(lexer_t *lex, lex_t *token) {
lex_eat_whitespace(lex);
*token = (lex_t){.str = lex->at, .file = lex->file, .line = lex->line, .column = lex->column};
lex_advance(lex);
switch (token->str[0]) {
case '\0': token->kind = lex_kind_eof; break;
case '{': token->kind = lex_kind_open_brace; break;
case '}': token->kind = lex_kind_close_brace; break;
case '(': token->kind = lex_kind_open_paren; break;
case ')': token->kind = lex_kind_close_paren; break;
case '[': token->kind = lex_kind_open_bracket; break;
case ']': token->kind = lex_kind_close_bracket; break;
case '~': token->kind = lex_kind_bit_negation; break;
case ';': token->kind = lex_kind_semicolon; break;
case ':': token->kind = lex_kind_colon; break;
case ',': token->kind = lex_kind_comma; break;
case '@': token->kind = lex_kind_tag; break;
case '?': token->kind = lex_kind_question; break;
case '\\': token->kind = lex_kind_escape; break;
case '"': lex_eat_string(lex, token); break;
case '`': lex_eat_string(lex, token); break;
case '\'': lex_eat_string(lex, token); break;
LEX_CASE3('^', lex_kind_bit_xor, '=', lex_kind_bit_xor_assign, /*ignored option*/'=', lex_kind_bit_xor_assign);
LEX_CASE3('=', lex_kind_assign, '=', lex_kind_equals, /*ignored option*/'=', lex_kind_equals);
LEX_CASE3('!', lex_kind_negation, '=', lex_kind_not_equals, /*ignored option*/'=', lex_kind_not_equals);
LEX_CASE3('%', lex_kind_modulo, '=', lex_kind_modulo_assign, /*ignored option*/'=', lex_kind_modulo_assign);
LEX_CASE3('*', lex_kind_multiply, '=', lex_kind_multiply_assign, /*ignored option*/'=', lex_kind_multiply_assign);
LEX_CASE3('+', lex_kind_plus, '+', lex_kind_increment, '=', lex_kind_plus_assign);
LEX_CASE3('-', lex_kind_minus, '-', lex_kind_decrement, '=', lex_kind_minus_assign);
LEX_CASE3('&', lex_kind_bit_and, '&', lex_kind_and, '=', lex_kind_bit_and_assign);
LEX_CASE3('|', lex_kind_bit_or, '|', lex_kind_or, '=', lex_kind_bit_or_assign);
case '.': {
token->kind = lex_kind_dot;
if (lex->at[0] == '.' && lex->at[1] == '.') {
lex_advance(lex);
lex_advance(lex);
token->kind = lex_kind_three_dots;
}
} break;
case '/': {
token->kind = lex_kind_divide;
if (lex_match(lex, '/')) {
token->kind = lex_kind_comment;
lex_eat_until(lex, '\n');
} else if (lex_match(lex, '*')) {
token->kind = lex_kind_comment;
for (;;) {
if (lex->at[0] == '*' && lex->at[1] == '/') {
break;
}
if (lex->at[0] == 0) {
lex_error(token, "unclosed block comment");
return;
}
lex_advance(lex);
}
lex_advance(lex);
lex_advance(lex);
} else if (lex_match(lex, '=')) {
token->kind = lex_kind_divide_assign;
}
} break;
case '>': {
token->kind = lex_kind_greater;
if (lex_match(lex, '=')) {
token->kind = lex_kind_greater_or_equal;
} else if (lex_match(lex, '>')) {
token->kind = lex_kind_bit_right_shift;
if (lex_match(lex, '=')) {
token->kind = lex_kind_bit_right_shift_assign;
}
}
} break;
case '<': {
token->kind = lex_kind_lesser;
if (lex_match(lex, '=')) {
token->kind = lex_kind_lesser_or_equal;
} else if (lex_match(lex, '<')) {
token->kind = lex_kind_bit_left_shift;
if (lex_match(lex, '=')) {
token->kind = lex_kind_bit_left_shift_assign;
}
}
} break;
case '#': {
if (lex_match(lex, '#')) {
token->kind = lex_kind_preproc_concat;
} else {
b32 inside_macro = lex_macro(lex, token);
if (inside_macro) {
lex->inside_macro = true;
} else {
if (!lex->inside_macro) {
lex_error(token, "invalid preprocessor directive");
return;
}
token->kind = lex_kind_preproc_stringify;
token->str = lex->at;
// this is slighly wrong, first letter can't be number
while (char_is_alphanumeric(lex->at[0]) || lex->at[0] == '_') lex_advance(lex);
}
}
} break;
case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': case '0': {
lex_eat_number(lex, token);
} break;
case 'A': case 'a': case 'B': case 'b': case 'C': case 'c':
case 'D': case 'd': case 'E': case 'e': case 'F': case 'f':
case 'G': case 'g': case 'H': case 'h': case 'I': case 'i':
case 'J': case 'j': case 'K': case 'k': case 'L': case 'l':
case 'M': case 'm': case 'N': case 'n': case 'O': case 'o':
case 'P': case 'p': case 'Q': case 'q': case 'R': case 'r':
case 'S': case 's': case 'T': case 't': case 'U': case 'u':
case 'V': case 'v': case 'W': case 'w': case 'X': case 'x':
case 'Y': case 'y': case 'Z': case 'z': case '_': {
token->kind = lex_kind_ident;
while (char_is_alphanumeric(lex->at[0]) || lex->at[0] == '_') lex_advance(lex);
} break;
default: {
lex_error(token, "found invalid character in the token stream");
}
}
token->len = (i32)(lex->at - token->str);
if (token->kind == lex_kind_integer) {
s8_t string_to_lex = token->string;
if (token->suffix != lex_suffix_none) {
s8_t string_value = ti_enum_value_to_name(token->suffix, type(lex_suffix_t));
s8_t prefix = s8("lex_suffix_");
string_to_lex.len -= string_value.len - prefix.len;
}
token->integer = u64_from_s8(string_to_lex, 10);
} else if (token->kind == lex_kind_real) {
s8_t string_to_lex = token->string;
if (token->suffix != lex_suffix_none) {
s8_t string_value = ti_enum_value_to_name(token->suffix, type(lex_suffix_t));
s8_t prefix = s8("lex_suffix_");
string_to_lex.len -= string_value.len - prefix.len;
}
token->real = f64_from_s8(string_to_lex);
} else if (token->kind == lex_kind_string) {
token->str += 1;
token->len -= 2;
} else if (token->kind == lex_kind_preproc_include) {
token->len -= 1;
}
if (lex->inside_macro) token->inside_macro = true;
}
fn lex_t lex_token(lexer_t *lex) {
lex_t result = {0};
lex_token_ex(lex, &result);
return result;
}
fn lex_array_t lex_tokens(ma_arena_t *arena, char *file_name, s8_t stream) {
usize align = arena->align;
arena->align = 0;
lex_array_t token_array = {0};
lexer_t l = lex_make(stream, file_name);
for (;;) {
lex_t *token = ma_push_type(arena, lex_t);
if (token_array.data == NULL) {
token_array.data = token;
}
token_array.len += 1;
do {
lex_token_ex(&l, token);
} while (token->kind == lex_kind_comment);
if (token->kind == lex_kind_eof) break;
}
arena->align = align;
return token_array;
}
gb_read_only s8_t lex_kind_simple_strings[] = {
#define X(KIND, STR, SIMPLE) s8_const(SIMPLE),
LEX_KIND_XLIST
#undef X
};
fn s8_t lex_kind_to_simple_s8(lex_kind_t kind) {
assert_expr(kind >= 0 && kind < lex_kind_count);
return lex_kind_simple_strings[kind];
}
gb_read_only s8_t lex_kind_strings[] = {
#define X(KIND, STR, SIMPLE) s8_const(STR),
LEX_KIND_XLIST
#undef X
};
fn s8_t lex_kind_to_s8(lex_kind_t kind) {
assert(kind >= 0 && kind < lex_kind_count);
return lex_kind_strings[kind];
}
fn lex_t *parser_next(parser_t *par) {
lex_t *result = par->at;
if (result->kind != lex_kind_eof) par->at += 1;
return result;
}
fn lex_t *parser_match(parser_t *par, lex_kind_t kind) {
if (par->at->kind == kind) {
return parser_next(par);
} else {
return NULL;
}
}
fn lex_t *parser_matchi(parser_t *par, s8_t str) {
if (par->at->kind == lex_kind_ident && s8_are_equal(par->at->string, str)) {
return parser_next(par);
} else {
return NULL;
}
}
fn void parser_panicf(b32 print_only_file, lex_t *token, const char *str, ...) {
ma_temp_t scratch = ma_begin_scratch();
b8 p = tcx->log.print_file_and_line;
tcx->log.print_file_and_line = false;
S8_FMT(scratch.arena, str, str8);
if (print_only_file) {
fatalf("%s: error: %.*s", token->file, s8_fmtspec(str8));
} else {
fatalf("%s(%d): error: %.*s", token->file, token->line, s8_fmtspec(str8));
}
tcx->log.print_file_and_line = p;
ma_end_scratch(scratch);
}
fn lex_t *parser_expect(parser_t *par, lex_kind_t kind) {
lex_t *token = parser_match(par, kind);
if (!token) parser_panicf(par->print_only_file, par->at, "expected token kind: %s, got instead: %s", lex_kind_to_s8(kind).str, lex_kind_to_s8(par->at->kind).str);
return token;
}
fn lex_t *parser_expecti(parser_t *par, s8_t ident) {
lex_t *token = parser_matchi(par, ident);
if (!token) parser_panicf(par->print_only_file, par->at, "expected identifier: '%.*s'", s8_fmtspec(ident));
return token;
}
fn void parser_eat_until(parser_t *par, lex_kind_t kind) {
while (par->at->kind != kind && par->at->kind != lex_kind_eof) {
parser_next(par);
}
}
fn void parser_eat_including(parser_t *par, lex_kind_t kind) {
parser_eat_until(par, kind);
parser_next(par);
}
-182
View File
@@ -1,182 +0,0 @@
#pragma once
#include "core_basic.h"
#include "core_string.h"
#include "core_arena.h"
#include "core_type_info.h"
typedef enum lex_kind_t {
#define LEX_KIND_XLIST\
X(lex_kind_eof , "end of file" , "---" )\
X(lex_kind_error , "error" , "---" )\
X(lex_kind_integer , "integer" , "---" )\
X(lex_kind_real , "real" , "---" )\
X(lex_kind_ident , "identifier" , "---" )\
X(lex_kind_string , "string" , "---" )\
X(lex_kind_comment , "comment" , "---" )\
X(lex_kind_open_brace , "'{' open brace" , "{" )\
X(lex_kind_close_brace , "'}' close brace" , "}" )\
X(lex_kind_open_paren , "'(' open parenthesis" , "(" )\
X(lex_kind_close_paren , "')' close parenthesis" , ")" )\
X(lex_kind_open_bracket , "'[' open bracket" , "[" )\
X(lex_kind_close_bracket , "']' close bracket" , "]" )\
X(lex_kind_plus , "'+' plus" , "+" )\
X(lex_kind_minus , "'-' minus" , "-" )\
X(lex_kind_divide , "'/' division sign" , "/" )\
X(lex_kind_multiply , "'*' multiplication sign" , "*" )\
X(lex_kind_modulo , "'%' modulo" , "%" )\
X(lex_kind_or , "'||' logical or" , "||" )\
X(lex_kind_and , "'&&' logical and" , "&&" )\
X(lex_kind_negation , "'!' logical negation" , "!" )\
X(lex_kind_bit_negation , "'~' bit negation" , "~" )\
X(lex_kind_bit_left_shift , "'<<' bit left shift" , "<<" )\
X(lex_kind_bit_right_shift , "'>>' bit right shift" , ">>" )\
X(lex_kind_bit_or , "'|' bit or" , "|" )\
X(lex_kind_bit_and , "'&' bit and" , "&" )\
X(lex_kind_bit_xor , "'^' bit xor" , "^" )\
X(lex_kind_decrement , "'--' decrement" , "--" )\
X(lex_kind_increment , "'++' increment" , "++" )\
X(lex_kind_post_decrement , "'--' post decrement" , "--" )\
X(lex_kind_post_increment , "'++' post increment" , "++" )\
X(lex_kind_assign , "'=' assignment" , "=" )\
X(lex_kind_divide_assign , "'/=' divide assignment" , "/=" )\
X(lex_kind_multiply_assign , "'*=' multiply assignment" , "*=" )\
X(lex_kind_plus_assign , "'+=' plus assignment" , "+=" )\
X(lex_kind_minus_assign , "'-=' minus assignment" , "-=" )\
X(lex_kind_modulo_assign , "'%=' modulo assignment" , "%=" )\
X(lex_kind_bit_and_assign , "'&=' bit and assignment" , "&=" )\
X(lex_kind_bit_or_assign , "'|=' bit or assignment" , "|=" )\
X(lex_kind_bit_xor_assign , "'^=' bit xor assignment" , "^=" )\
X(lex_kind_bit_left_shift_assign , "'<<=' bit left shift assignment" , "<<=" )\
X(lex_kind_bit_right_shift_assign , "'>>=' bit right shift assignment" , ">>=" )\
X(lex_kind_equals , "'==' equals sign" , "==" )\
X(lex_kind_not_equals , "'!=' not equals sign" , "!=" )\
X(lex_kind_lesser , "'<' lesser then" , "<" )\
X(lex_kind_greater , "'>' greater then" , ">" )\
X(lex_kind_lesser_or_equal , "'<=' lesser then or equal" , "<=" )\
X(lex_kind_greater_or_equal , "'>=' greater then or equal" , ">=" )\
X(lex_kind_comma , "',' comma" , "," )\
X(lex_kind_dot , "'.' dot" , "." )\
X(lex_kind_three_dots , "'...' three dots" , "..." )\
X(lex_kind_semicolon , "';' semicolon" , ";" )\
X(lex_kind_colon , "':' colon" , ":" )\
X(lex_kind_arrow , "'->' arrow" , "->" )\
X(lex_kind_question , "'?' question mark" , "?" )\
X(lex_kind_tag , "'@' tag sign" , "@" )\
X(lex_kind_escape , "'\\' escape" , "\\" )\
X(lex_kind_preproc_null , "preproc_null" , "---" )\
X(lex_kind_preproc_define , "preproc_define" , "---" )\
X(lex_kind_preproc_ifdef , "preproc_ifdef" , "---" )\
X(lex_kind_preproc_ifndef , "preproc_ifndef" , "---" )\
X(lex_kind_preproc_include , "preproc_include" , "---" )\
X(lex_kind_preproc_endif , "preproc_endif" , "---" )\
X(lex_kind_preproc_if , "preproc_if" , "---" )\
X(lex_kind_preproc_pragma , "preproc_pragma" , "---" )\
X(lex_kind_preproc_error , "preproc_error" , "---" )\
X(lex_kind_preproc_else , "preproc_else" , "---" )\
X(lex_kind_preproc_elif , "preproc_elif" , "---" )\
X(lex_kind_preproc_undef , "preproc_undef" , "---" )\
X(lex_kind_preproc_concat , "preproc_concat" , "---" )\
X(lex_kind_preproc_stringify , "preproc_stringify" , "---" )\
#define X(KIND, STR, SIMPLE) KIND,
LEX_KIND_XLIST
#undef X
lex_kind_count,
} lex_kind_t;
typedef enum lex_suffix_t {
#define LEX_SUFFIX_XLIST\
X(lex_suffix_none) \
X(lex_suffix_f) \
X(lex_suffix_d) \
X(lex_suffix_u) \
X(lex_suffix_ul) \
X(lex_suffix_ull) \
X(lex_suffix_l) \
X(lex_suffix_ll) \
#define X(KIND) KIND,
LEX_SUFFIX_XLIST
#undef X
lex_suffix_count,
} lex_suffix_t;
typedef struct lex_t lex_t;
struct lex_t {
lex_kind_t kind;
lex_suffix_t suffix;
struct {
b8 inside_macro: 1;
b8 system_include: 1;
};
union {
struct {char *str; i64 len;};
s8_t string;
};
i32 line;
i32 column;
char *file;
union {
u64 integer;
f64 real;
char *error;
};
};
typedef struct lexer_t lexer_t;
struct lexer_t {
char *at;
char *end;
char *file;
i32 line;
i32 column;
b8 inside_macro;
};
typedef struct lex_array_t lex_array_t;
struct lex_array_t {
lex_t *data;
i32 len;
};
fn lex_array_t lex_tokens(ma_arena_t *arena, char *filename, s8_t stream);
fn s8_t lex_kind_to_simple_s8(lex_kind_t kind);
fn s8_t lex_kind_to_s8(lex_kind_t kind);
typedef struct parser_t parser_t;
struct parser_t {
ma_arena_t *arena;
lex_t *at;
b8 print_only_file;
};
#define parser_make(ARENA, TOKEN) &(parser_t){.arena = ARENA, .at = TOKEN}
fn lex_t *parser_next(parser_t *par);
fn lex_t *parser_match(parser_t *par, lex_kind_t kind);
fn lex_t *parser_matchi(parser_t *par, s8_t str);
fn lex_t *parser_expect(parser_t *par, lex_kind_t kind);
fn void parser_panicf(b32 print_only_file, lex_t *token, const char *str, ...);
fn void parser_eat_until(parser_t *par, lex_kind_t kind);
fn void parser_eat_including(parser_t *par, lex_kind_t kind);
static gb_read_only lex_t lex_null;
static gb_read_only type_member_t members__lex_kind_t[] = {
#define X(KIND, STR, SIMPLE) {.name = s8_const("lex_kind_" #KIND), .value = KIND},
LEX_KIND_XLIST
#undef X
};
static DEFINE_ENUM(lex_kind_t);
static gb_read_only type_member_t members__lex_suffix_t[] = {
#define X(KIND) {.name = s8_const(#KIND), .value = KIND},
LEX_SUFFIX_XLIST
#undef X
};
static DEFINE_ENUM(lex_suffix_t);
-42
View File
@@ -1,42 +0,0 @@
#include "core_log.h"
#include "core_ctx.h"
#include "core_platform.h"
fn void log_basef(log_level_t level, s8_t file_and_line, const char *str, ...) {
ma_temp_t scratch = ma_begin_scratch();
S8_FMT(scratch.arena, str, string);
tcx->log.log_proc(level, file_and_line, string);
ma_end_scratch(scratch);
}
fn void default_log_proc(log_level_t level, s8_t file_and_line, s8_t string) {
ma_temp_t scratch = ma_begin_scratch();
char *colon = ": ";
if (tcx->log.print_file_and_line == false) {
file_and_line.len = 0;
colon = "";
}
switch(level) {
case log_level_debug:
case log_level_info: {
os_console_log(s8_printf(scratch.arena, "%.*s\n", s8_fmtspec(string)).str);
} break;
case log_level_warning: {
os_console_log(s8_printf(scratch.arena, "%.*s%s%.*s\n", s8_fmtspec(file_and_line), colon, s8_fmtspec(string)).str);
if (tcx->log.break_on_warning) debug_break();
} break;
case log_level_error: {
os_console_log(s8_printf(scratch.arena, "%.*s%s%.*s\n", s8_fmtspec(file_and_line), colon, s8_fmtspec(string)).str);
if (tcx->log.break_on_error) debug_break();
} break;
case log_level_fatal: {
os_error_box(s8_printf(scratch.arena, "%.*s%s%.*s\n", s8_fmtspec(file_and_line), colon, s8_fmtspec(string)).str);
if (tcx->log.break_on_fatal) debug_break();
} break;
default_is_invalid;
}
ma_end_scratch(scratch);
}
-30
View File
@@ -1,30 +0,0 @@
#pragma once
#include "core_basic.h"
#include "core_string.h"
typedef enum {
log_level_debug,
log_level_info,
log_level_warning,
log_level_error,
log_level_fatal,
} log_level_t;
typedef struct logger_t logger_t;
struct logger_t {
void (*log_proc)(log_level_t level, s8_t file_and_line, s8_t string);
void *user_data;
b8 break_on_fatal;
b8 break_on_error;
b8 break_on_warning;
b8 print_file_and_line;
};
///////////////////////////////
// main api
#define debugf(...) log_basef(log_level_debug, S8_FILE_AND_LINE, __VA_ARGS__)
#define errorf(...) log_basef(log_level_error, S8_FILE_AND_LINE, __VA_ARGS__)
#define fatalf(...) (log_basef(log_level_fatal, S8_FILE_AND_LINE, __VA_ARGS__), 0)
fn void default_log_proc(log_level_t level, s8_t file_and_line, s8_t string);
fn void log_basef(log_level_t level, s8_t file_and_line, const char *str, ...);
-555
View File
@@ -1,555 +0,0 @@
#include "core_math.h"
#include "core_intrin.h"
/*
* Converts an RGB color value to HSL. Conversion formula
* adapted from http://en.wikipedia.org/wiki/HSL_color_space.
* also https://gist.github.com/ciembor/1494530
* alpha is ignored
*/
fn v3f32_t v3f32_rgb_to_hsl(v3f32_t color) {
v3f32_t result;
f32 max = MAX(MAX(color.r, color.g), color.b);
f32 min = MIN(MIN(color.r, color.g), color.b);
result.h = result.s = result.l = (max + min) / 2.f;
if (max == min) {
result.h = result.s = 0.f; // achromatic
} else {
f32 d = max - min;
result.s = (result.l > 0.5f) ? d / (2.f - max - min) : d / (max + min);
if (max == color.r) {
result.h = (color.g - color.b) / d + (color.g < color.b ? 6.f : 0.f);
} else if (max == color.g) {
result.h = (color.b - color.r) / d + 2.f;
} else if (max == color.b) {
result.h = (color.r - color.g) / d + 4.f;
}
result.h /= 6.f;
}
return result;
}
/*
* Converts an HUE to r, g or b.
* returns f32 in the set [0, 1].
*/
fn f32 f32_hue_to_rgb(f32 p, f32 q, f32 t) {
if (t < 0.f)
t += 1.f;
if (t > 1.f)
t -= 1.f;
if (t < 1.f / 6.f)
return p + (q - p) * 6.f * t;
if (t < 1.f / 2.f)
return q;
if (t < 2.f / 3.f)
return p + (q - p) * (2.f / 3.f - t) * 6.f;
return p;
}
fn v3f32_t v3f32_hsl_to_rgb(v3f32_t color) {
v3f32_t result;
if (0 == color.s) {
result.r = result.g = result.b = color.l; // achromatic
} else {
f32 q = color.l < 0.5f ? color.l * (1.f + color.s)
: color.l + color.s - color.l * color.s;
f32 p = 2.f * color.l - q;
result.r = f32_hue_to_rgb(p, q, color.h + 1.f / 3.f);
result.g = f32_hue_to_rgb(p, q, color.h);
result.b = f32_hue_to_rgb(p, q, color.h - 1.f / 3.f);
}
return result;
}
fn v4f32_t v4f32_rgba_to_hsla(v4f32_t rgba) {
v3f32_t result = v3f32_rgb_to_hsl(rgba.xyz);
return (v4f32_t){result.r, result.g, result.b, rgba.a};
}
fn v4f32_t v4f32_hsla_to_rgba(v4f32_t color) {
v3f32_t result = v3f32_hsl_to_rgb(color.xyz);
return (v4f32_t){result.r, result.g, result.b, color.a};
}
/*
https://git.musl-libc.org/cgit/musl/tree/src/math
https://gitlab.com/nakst/essence/-/blob/master/shared/math.cpp
*/
fn f64 f64_clamp01(f64 a) { return CLAMP(a, 0, 1); }
fn f64 f64_lerp(f64 a, f64 b, f64 t) { return (1 - t) * a + t * b; }
fn f64 f64_smooth_step(f64 t) { return t*t*(3-2*t); }
fn f64 f64_ease_in_quint(f64 x) { return x * x * x * x * x; }
fn f64 f64_ease_in_cubic(f64 x) { return x * x * x; }
fn f64 f64_ping_pong(f64 x) { return 1.0 - f64_abs(1.0 - f64_mod(x,2)); }
fn f32 f32_clamp01(f32 a) { return CLAMP(a, 0, 1); }
fn f32 f32_lerp(f32 a, f32 b, f32 t) { return (1 - t) * a + t * b; }
fn f32 f32_smooth_step(f32 t) { return t*t*(3-2*t); }
fn f32 f32_ease_in_quint(f32 x) { return x * x * x * x * x; }
fn f32 f32_ease_in_cubic(f32 x) { return x * x * x; }
fn f32 f32_ping_pong(f32 x) { return 1.0f - f32_abs(1.0f - f32_mod(x,2)); }
fn v4f32_t v4f32_lerp(v4f32_t a, v4f32_t b, f32 t) {
return (v4f32_t){f32_lerp(a.x, b.x, t), f32_lerp(a.y, b.y, t), f32_lerp(a.z, b.z, t), f32_lerp(a.w, b.w, t)};
}
fn v4f32_t v4f32_lerp_noa(v4f32_t a, v4f32_t b, f32 t) {
return (v4f32_t){f32_lerp(a.x, b.x, t), f32_lerp(a.y, b.y, t), f32_lerp(a.z, b.z, t), a.w};
}
fn f64 _Sine(f64 x) {
// Calculates sin(x) for x in [0, pi/4].
f64 x2 = x * x;
return x * (U64_TO_F64(0x3FF0000000000000) + x2 * (U64_TO_F64(0xBFC5555555555540) + x2 * (U64_TO_F64(0x3F8111111110ED80) + x2 * (U64_TO_F64(0xBF2A01A019AE6000)
+ x2 * (U64_TO_F64(0x3EC71DE349280000) + x2 * (U64_TO_F64(0xBE5AE5DC48000000) + x2 * U64_TO_F64(0x3DE5D68200000000)))))));
}
fn f32 _SineFloat(f32 x) {
// Calculates sin(x) for x in [0, pi/4].
f32 x2 = x * x;
return x * (U32_TO_F32(0x3F800000) + x2 * (U32_TO_F32(0xBE2AAAA0) + x2 * (U32_TO_F32(0x3C0882C0) + x2 * U32_TO_F32(0xB94C6000))));
}
fn f64 _ArcSine(f64 x) {
// Calculates arcsin(x) for x in [0, 0.5].
f64 x2 = x * x;
return x * (U64_TO_F64(0x3FEFFFFFFFFFFFE6) + x2 * (U64_TO_F64(0x3FC555555555FE00) + x2 * (U64_TO_F64(0x3FB333333292DF90) + x2 * (U64_TO_F64(0x3FA6DB6DFD3693A0)
+ x2 * (U64_TO_F64(0x3F9F1C608DE51900) + x2 * (U64_TO_F64(0x3F96EA0659B9A080) + x2 * (U64_TO_F64(0x3F91B4ABF1029100)
+ x2 * (U64_TO_F64(0x3F8DA8DAF31ECD00) + x2 * (U64_TO_F64(0x3F81C01FD5000C00) + x2 * (U64_TO_F64(0x3F94BDA038CF6B00)
+ x2 * (U64_TO_F64(0xBF8E849CA75B1E00) + x2 * U64_TO_F64(0x3FA146C2D37F2C60))))))))))));
}
fn f32 _ArcSineFloat(f32 x) {
// Calculates arcsin(x) for x in [0, 0.5].
f32 x2 = x * x;
return x * (U32_TO_F32(0x3F800004) + x2 * (U32_TO_F32(0x3E2AA130) + x2 * (U32_TO_F32(0x3D9B2C28) + x2 * (U32_TO_F32(0x3D1C1800) + x2 * U32_TO_F32(0x3D5A97C0)))));
}
fn f64 _ArcTangent(f64 x) {
// Calculates arctan(x) for x in [0, 0.5].
f64 x2 = x * x;
return x * (U64_TO_F64(0x3FEFFFFFFFFFFFF8) + x2 * (U64_TO_F64(0xBFD5555555553B44) + x2 * (U64_TO_F64(0x3FC9999999803988) + x2 * (U64_TO_F64(0xBFC249248C882E80)
+ x2 * (U64_TO_F64(0x3FBC71C5A4E4C220) + x2 * (U64_TO_F64(0xBFB745B3B75243F0) + x2 * (U64_TO_F64(0x3FB3AFAE9A2939E0)
+ x2 * (U64_TO_F64(0xBFB1030C4A4A1B90) + x2 * (U64_TO_F64(0x3FAD6F65C35579A0) + x2 * (U64_TO_F64(0xBFA805BCFDAFEDC0)
+ x2 * (U64_TO_F64(0x3F9FC6B5E115F2C0) + x2 * U64_TO_F64(0xBF87DCA5AB25BF80))))))))))));
}
fn f32 _ArcTangentFloat(f32 x) {
// Calculates arctan(x) for x in [0, 0.5].
f32 x2 = x * x;
return x * (U32_TO_F32(0x3F7FFFF8) + x2 * (U32_TO_F32(0xBEAAA53C) + x2 * (U32_TO_F32(0x3E4BC990) + x2 * (U32_TO_F32(0xBE084A60) + x2 * U32_TO_F32(0x3D8864B0)))));
}
fn f64 _Cosine(f64 x) {
// Calculates cos(x) for x in [0, pi/4].
f64 x2 = x * x;
return U64_TO_F64(0x3FF0000000000000) + x2 * (U64_TO_F64(0xBFDFFFFFFFFFFFA0) + x2 * (U64_TO_F64(0x3FA555555554F7C0) + x2 * (U64_TO_F64(0xBF56C16C16475C00)
+ x2 * (U64_TO_F64(0x3EFA019F87490000) + x2 * (U64_TO_F64(0xBE927DF66B000000) + x2 * U64_TO_F64(0x3E21B949E0000000))))));
}
fn f32 _CosineFloat(f32 x) {
// Calculates cos(x) for x in [0, pi/4].
f32 x2 = x * x;
return U32_TO_F32(0x3F800000) + x2 * (U32_TO_F32(0xBEFFFFDA) + x2 * (U32_TO_F32(0x3D2A9F60) + x2 * U32_TO_F32(0xBAB22C00)));
}
fn f64 _Tangent(f64 x) {
// Calculates tan(x) for x in [0, pi/4].
f64 x2 = x * x;
return x * (U64_TO_F64(0x3FEFFFFFFFFFFFE8) + x2 * (U64_TO_F64(0x3FD5555555558000) + x2 * (U64_TO_F64(0x3FC1111110FACF90) + x2 * (U64_TO_F64(0x3FABA1BA266BFD20)
+ x2 * (U64_TO_F64(0x3F9664F30E56E580) + x2 * (U64_TO_F64(0x3F822703B08BDC00) + x2 * (U64_TO_F64(0x3F6D698D2E4A4C00)
+ x2 * (U64_TO_F64(0x3F57FF4F23EA4400) + x2 * (U64_TO_F64(0x3F424F3BEC845800) + x2 * (U64_TO_F64(0x3F34C78CA9F61000)
+ x2 * (U64_TO_F64(0xBF042089F8510000) + x2 * (U64_TO_F64(0x3F29D7372D3A8000) + x2 * (U64_TO_F64(0xBF19D1C5EF6F0000)
+ x2 * (U64_TO_F64(0x3F0980BDF11E8000)))))))))))))));
}
fn f32 _TangentFloat(f32 x) {
// Calculates tan(x) for x in [0, pi/4].
f32 x2 = x * x;
return x * (U32_TO_F32(0x3F800001) + x2 * (U32_TO_F32(0x3EAAA9AA) + x2 * (U32_TO_F32(0x3E08ABA8) + x2 * (U32_TO_F32(0x3D58EC90)
+ x2 * (U32_TO_F32(0x3CD24840) + x2 * (U32_TO_F32(0x3AC3CA00) + x2 * U32_TO_F32(0x3C272F00)))))));
}
fn f64 f64_sin(f64 x) {
b32 negate = false;
// x in -infty, infty
if (x < 0) {
x = -x;
negate = true;
}
// x in 0, infty
x -= 2 * F64_PI * f64_floor(x / (2 * F64_PI));
// x in 0, 2*pi
if (x < F64_PI / 2) {
} else if (x < F64_PI) {
x = F64_PI - x;
} else if (x < 3 * F64_PI / 2) {
x = x - F64_PI;
negate = !negate;
} else {
x = F64_PI * 2 - x;
negate = !negate;
}
// x in 0, pi/2
f64 y = x < F64_PI / 4 ? _Sine(x) : _Cosine(F64_PI / 2 - x);
return negate ? -y : y;
}
fn f32 f32_sin(f32 x) {
b32 negate = false;
// x in -infty, infty
if (x < 0) {
x = -x;
negate = true;
}
// x in 0, infty
x -= 2 * F32_PI * f32_floor(x / (2 * F32_PI));
// x in 0, 2*pi
if (x < F32_PI / 2) {
} else if (x < F32_PI) {
x = F32_PI - x;
} else if (x < 3 * F32_PI / 2) {
x = x - F32_PI;
negate = !negate;
} else {
x = F32_PI * 2 - x;
negate = !negate;
}
// x in 0, pi/2
f32 y = x < F32_PI / 4 ? _SineFloat(x) : _CosineFloat(F32_PI / 2 - x);
return negate ? -y : y;
}
fn f64 f64_cos(f64 x) {
b32 negate = false;
// x in -infty, infty
if (x < 0) {
x = -x;
}
// x in 0, infty
x -= 2 * F64_PI * f64_floor(x / (2 * F64_PI));
// x in 0, 2*pi
if (x < F64_PI / 2) {
} else if (x < F64_PI) {
x = F64_PI - x;
negate = !negate;
} else if (x < 3 * F64_PI / 2) {
x = x - F64_PI;
negate = !negate;
} else {
x = F64_PI * 2 - x;
}
// x in 0, pi/2
f64 y = x < F64_PI / 4 ? _Cosine(x) : _Sine(F64_PI / 2 - x);
return negate ? -y : y;
}
fn f32 f32_cos(f32 x) {
b32 negate = false;
// x in -infty, infty
if (x < 0) {
x = -x;
}
// x in 0, infty
x -= 2 * F32_PI * f32_floor(x / (2 * F32_PI));
// x in 0, 2*pi
if (x < F32_PI / 2) {
} else if (x < F32_PI) {
x = F32_PI - x;
negate = !negate;
} else if (x < 3 * F32_PI / 2) {
x = x - F32_PI;
negate = !negate;
} else {
x = F32_PI * 2 - x;
}
// x in 0, pi/2
f32 y = x < F32_PI / 4 ? _CosineFloat(x) : _SineFloat(F32_PI / 2 - x);
return negate ? -y : y;
}
fn f64 f64_tan(f64 x) {
b32 negate = false;
// x in -infty, infty
if (x < 0) {
x = -x;
negate = !negate;
}
// x in 0, infty
x -= F64_PI * f64_floor(x / F64_PI);
// x in 0, pi
if (x > F64_PI / 2) {
x = F64_PI - x;
negate = !negate;
}
// x in 0, pi/2
f64 y = x < F64_PI / 4 ? _Tangent(x) : (1.0 / _Tangent(F64_PI / 2 - x));
return negate ? -y : y;
}
fn f32 f32_tan(f32 x) {
b32 negate = false;
// x in -infty, infty
if (x < 0) {
x = -x;
negate = !negate;
}
// x in 0, infty
x -= F32_PI * f32_floor(x / F32_PI);
// x in 0, pi
if (x > F32_PI / 2) {
x = F32_PI - x;
negate = !negate;
}
// x in 0, pi/2
f32 y = x < F32_PI / 4 ? _TangentFloat(x) : (1.0f / _TangentFloat(F32_PI / 2 - x));
return negate ? -y : y;
}
fn f64 f64_asin(f64 x) {
b32 negate = false;
if (x < 0) {
x = -x;
negate = true;
}
f64 y;
if (x < 0.5) {
y = _ArcSine(x);
} else {
y = F64_PI / 2 - 2 * _ArcSine(f64_sqrt(0.5 - 0.5 * x));
}
return negate ? -y : y;
}
fn f32 f32_asin(f32 x) {
b32 negate = false;
if (x < 0) {
x = -x;
negate = true;
}
f32 y;
if (x < 0.5) {
y = _ArcSineFloat(x);
} else {
y = F32_PI / 2 - 2 * _ArcSineFloat(f32_sqrt(0.5f - 0.5f * x));
}
return negate ? -y : y;
}
fn f64 f64_acos(f64 x) {
return f64_asin(-x) + F64_PI / 2;
}
fn f32 f32_acos(f32 x) {
return f32_asin(-x) + F32_PI / 2;
}
fn f64 f64_atan(f64 x) {
b32 negate = false;
if (x < 0) {
x = -x;
negate = true;
}
b32 reciprocalTaken = false;
if (x > 1) {
x = 1 / x;
reciprocalTaken = true;
}
f64 y;
if (x < 0.5) {
y = _ArcTangent(x);
} else {
y = 0.463647609000806116 + _ArcTangent((2 * x - 1) / (2 + x));
}
if (reciprocalTaken) {
y = F64_PI / 2 - y;
}
return negate ? -y : y;
}
fn f32 f32_atan(f32 x) {
b32 negate = false;
if (x < 0) {
x = -x;
negate = true;
}
b32 reciprocalTaken = false;
if (x > 1) {
x = 1 / x;
reciprocalTaken = true;
}
f32 y;
if (x < 0.5f) {
y = _ArcTangentFloat(x);
} else {
y = 0.463647609000806116f + _ArcTangentFloat((2 * x - 1) / (2 + x));
}
if (reciprocalTaken) {
y = F32_PI / 2 - y;
}
return negate ? -y : y;
}
fn f64 f64_atan2(f64 y, f64 x) {
if (x == 0) return y > 0 ? F64_PI / 2 : -F64_PI / 2;
else if (x > 0) return f64_atan(y / x);
else if (y >= 0) return F64_PI + f64_atan(y / x);
else return -F64_PI + f64_atan(y / x);
}
fn f32 f32_atan2(f32 y, f32 x) {
if (x == 0) return y > 0 ? F32_PI / 2 : -F32_PI / 2;
else if (x > 0) return f32_atan(y / x);
else if (y >= 0) return F32_PI + f32_atan(y / x);
else return -F32_PI + f32_atan(y / x);
}
fn b32 f32_are_equal(f32 a, f32 b) {
f32 diff = f32_abs(a - b);
b32 result = diff <= 0.00001f;
return result;
}
fn b32 f64_are_equal(f64 a, f64 b) {
f64 diff = f64_abs(a - b);
b32 result = diff <= 0.00001;
return result;
}
fn f32 f32_ease_out_bounce(f32 x) {
f32 n1 = 7.5625f;
f32 d1 = 2.75f;
if (x < 1.f / d1) {
return n1 * x * x;
} else if (x < 2.f / d1) {
return n1 * (x -= 1.5f / d1) * x + 0.75f;
} else if (x < 2.5f / d1) {
return n1 * (x -= 2.25f / d1) * x + 0.9375f;
} else {
return n1 * (x -= 2.625f / d1) * x + 0.984375f;
}
}
fn f32 f32_ease_out_elastic(f32 x) {
f32 c4 = (2 * F32_PI) / 3;
return x == 0.f
? 0
: x == 1.f
? 1
: f32_pow(2.f, -10.f * x) * f32_sin((x * 10.f - 0.75f) * c4) + 1.f;
}
fn f32 f32_ease_out_cubic(f32 x) {
return 1.f - f32_pow(1.f - x, 3.f);
}
fn f32 f32_ease_out_n(f32 x, f32 n) {
return 1.f - f32_pow(1.f - x, n);
}
fn r2f32_t r2f32_lerp(r2f32_t a, r2f32_t b, f32 t) {
r2f32_t result = { .min = {f32_lerp(a.min.x, b.min.x, t), f32_lerp(a.min.y, b.min.y, t)}, .max = {f32_lerp(a.max.x, b.max.x, t), f32_lerp(a.max.y, b.max.y, t)} };
return result;
}
-959
View File
@@ -1,959 +0,0 @@
#include "core_math.h"
#include "core_intrin.h"
fn_inline v2f32_t v2f32(f32 x, f32 y) { return (v2f32_t){ x, y }; }
gb_read_only v2f32_t v2f32_null = {0};
fn_inline b32 v2f32_is_null(v2f32_t a) { return memory_equal(&a, &v2f32_null, sizeof(a)); }
fn_inline b32 v2f32_are_equal(v2f32_t a, v2f32_t b) { return memory_equal(&a, &b, sizeof(a)); }
fn_inline v2f32_t v2f32_add(v2f32_t a, v2f32_t b) { return (v2f32_t){ a.x + b.x, a.y + b.y }; }
fn_inline v2f32_t v2f32_adds(v2f32_t a, f32 b) { return (v2f32_t){ a.x + b, a.y + b }; }
fn_inline v2f32_t v2f32_sub(v2f32_t a, v2f32_t b) { return (v2f32_t){ a.x - b.x, a.y - b.y }; }
fn_inline v2f32_t v2f32_subs(v2f32_t a, f32 b) { return (v2f32_t){ a.x - b, a.y - b }; }
fn_inline v2f32_t v2f32_mul(v2f32_t a, v2f32_t b) { return (v2f32_t){ a.x * b.x, a.y * b.y }; }
fn_inline v2f32_t v2f32_muls(v2f32_t a, f32 b) { return (v2f32_t){ a.x * b, a.y * b }; }
fn_inline v2f32_t v2f32_div(v2f32_t a, v2f32_t b) { return (v2f32_t){ a.x / b.x, a.y / b.y }; }
fn_inline v2f32_t v2f32_divs(v2f32_t a, f32 b) { return (v2f32_t){ a.x / b, a.y / b }; }
fn_inline v3f32_t v3f32(f32 x, f32 y, f32 z) { return (v3f32_t){ x, y, z }; }
gb_read_only v3f32_t v3f32_null = {0};
fn_inline b32 v3f32_is_null(v3f32_t a) { return memory_equal(&a, &v3f32_null, sizeof(a)); }
fn_inline b32 v3f32_are_equal(v3f32_t a, v3f32_t b) { return memory_equal(&a, &b, sizeof(a)); }
fn_inline v3f32_t v3f32_add(v3f32_t a, v3f32_t b) { return (v3f32_t){ a.x + b.x, a.y + b.y, a.z + b.z }; }
fn_inline v3f32_t v3f32_adds(v3f32_t a, f32 b) { return (v3f32_t){ a.x + b, a.y + b, a.z + b }; }
fn_inline v3f32_t v3f32_sub(v3f32_t a, v3f32_t b) { return (v3f32_t){ a.x - b.x, a.y - b.y, a.z - b.z }; }
fn_inline v3f32_t v3f32_subs(v3f32_t a, f32 b) { return (v3f32_t){ a.x - b, a.y - b, a.z - b }; }
fn_inline v3f32_t v3f32_mul(v3f32_t a, v3f32_t b) { return (v3f32_t){ a.x * b.x, a.y * b.y, a.z * b.z }; }
fn_inline v3f32_t v3f32_muls(v3f32_t a, f32 b) { return (v3f32_t){ a.x * b, a.y * b, a.z * b }; }
fn_inline v3f32_t v3f32_div(v3f32_t a, v3f32_t b) { return (v3f32_t){ a.x / b.x, a.y / b.y, a.z / b.z }; }
fn_inline v3f32_t v3f32_divs(v3f32_t a, f32 b) { return (v3f32_t){ a.x / b, a.y / b, a.z / b }; }
fn_inline v4f32_t v4f32(f32 x, f32 y, f32 z, f32 w) { return (v4f32_t){ x, y, z, w }; }
gb_read_only v4f32_t v4f32_null = {0};
fn_inline b32 v4f32_is_null(v4f32_t a) { return memory_equal(&a, &v4f32_null, sizeof(a)); }
fn_inline b32 v4f32_are_equal(v4f32_t a, v4f32_t b) { return memory_equal(&a, &b, sizeof(a)); }
fn_inline v4f32_t v4f32_add(v4f32_t a, v4f32_t b) { return (v4f32_t){ a.x + b.x, a.y + b.y, a.z + b.z, a.w + b.w }; }
fn_inline v4f32_t v4f32_adds(v4f32_t a, f32 b) { return (v4f32_t){ a.x + b, a.y + b, a.z + b, a.w + b }; }
fn_inline v4f32_t v4f32_sub(v4f32_t a, v4f32_t b) { return (v4f32_t){ a.x - b.x, a.y - b.y, a.z - b.z, a.w - b.w }; }
fn_inline v4f32_t v4f32_subs(v4f32_t a, f32 b) { return (v4f32_t){ a.x - b, a.y - b, a.z - b, a.w - b }; }
fn_inline v4f32_t v4f32_mul(v4f32_t a, v4f32_t b) { return (v4f32_t){ a.x * b.x, a.y * b.y, a.z * b.z, a.w * b.w }; }
fn_inline v4f32_t v4f32_muls(v4f32_t a, f32 b) { return (v4f32_t){ a.x * b, a.y * b, a.z * b, a.w * b }; }
fn_inline v4f32_t v4f32_div(v4f32_t a, v4f32_t b) { return (v4f32_t){ a.x / b.x, a.y / b.y, a.z / b.z, a.w / b.w }; }
fn_inline v4f32_t v4f32_divs(v4f32_t a, f32 b) { return (v4f32_t){ a.x / b, a.y / b, a.z / b, a.w / b }; }
fn_inline r2f32_t r2f32(f32 x0, f32 y0, f32 x1, f32 y1) { return (r2f32_t){ x0, y0, x1, y1 }; }
gb_read_only r2f32_t r2f32_null = {0};
fn_inline b32 r2f32_is_null(r2f32_t a) { return memory_equal(&a, &r2f32_null, sizeof(a)); }
fn_inline b32 r2f32_are_equal(r2f32_t a, r2f32_t b) { return memory_equal(&a, &b, sizeof(a)); }
fn_inline r2f32_t r2f32_add(r2f32_t a, r2f32_t b) { return (r2f32_t){ a.x0 + b.x0, a.y0 + b.y0, a.x1 + b.x1, a.y1 + b.y1 }; }
fn_inline r2f32_t r2f32_adds(r2f32_t a, f32 b) { return (r2f32_t){ a.x0 + b, a.y0 + b, a.x1 + b, a.y1 + b }; }
fn_inline r2f32_t r2f32_sub(r2f32_t a, r2f32_t b) { return (r2f32_t){ a.x0 - b.x0, a.y0 - b.y0, a.x1 - b.x1, a.y1 - b.y1 }; }
fn_inline r2f32_t r2f32_subs(r2f32_t a, f32 b) { return (r2f32_t){ a.x0 - b, a.y0 - b, a.x1 - b, a.y1 - b }; }
fn_inline r2f32_t r2f32_mul(r2f32_t a, r2f32_t b) { return (r2f32_t){ a.x0 * b.x0, a.y0 * b.y0, a.x1 * b.x1, a.y1 * b.y1 }; }
fn_inline r2f32_t r2f32_muls(r2f32_t a, f32 b) { return (r2f32_t){ a.x0 * b, a.y0 * b, a.x1 * b, a.y1 * b }; }
fn_inline r2f32_t r2f32_div(r2f32_t a, r2f32_t b) { return (r2f32_t){ a.x0 / b.x0, a.y0 / b.y0, a.x1 / b.x1, a.y1 / b.y1 }; }
fn_inline r2f32_t r2f32_divs(r2f32_t a, f32 b) { return (r2f32_t){ a.x0 / b, a.y0 / b, a.x1 / b, a.y1 / b }; }
fn_inline r3f32_t r3f32(f32 x0, f32 y0, f32 z0, f32 x1, f32 y1, f32 z1) { return (r3f32_t){ x0, y0, z0, x1, y1, z1 }; }
gb_read_only r3f32_t r3f32_null = {0};
fn_inline b32 r3f32_is_null(r3f32_t a) { return memory_equal(&a, &r3f32_null, sizeof(a)); }
fn_inline b32 r3f32_are_equal(r3f32_t a, r3f32_t b) { return memory_equal(&a, &b, sizeof(a)); }
fn_inline r3f32_t r3f32_add(r3f32_t a, r3f32_t b) { return (r3f32_t){ a.x0 + b.x0, a.y0 + b.y0, a.z0 + b.z0, a.x1 + b.x1, a.y1 + b.y1, a.z1 + b.z1 }; }
fn_inline r3f32_t r3f32_adds(r3f32_t a, f32 b) { return (r3f32_t){ a.x0 + b, a.y0 + b, a.z0 + b, a.x1 + b, a.y1 + b, a.z1 + b }; }
fn_inline r3f32_t r3f32_sub(r3f32_t a, r3f32_t b) { return (r3f32_t){ a.x0 - b.x0, a.y0 - b.y0, a.z0 - b.z0, a.x1 - b.x1, a.y1 - b.y1, a.z1 - b.z1 }; }
fn_inline r3f32_t r3f32_subs(r3f32_t a, f32 b) { return (r3f32_t){ a.x0 - b, a.y0 - b, a.z0 - b, a.x1 - b, a.y1 - b, a.z1 - b }; }
fn_inline r3f32_t r3f32_mul(r3f32_t a, r3f32_t b) { return (r3f32_t){ a.x0 * b.x0, a.y0 * b.y0, a.z0 * b.z0, a.x1 * b.x1, a.y1 * b.y1, a.z1 * b.z1 }; }
fn_inline r3f32_t r3f32_muls(r3f32_t a, f32 b) { return (r3f32_t){ a.x0 * b, a.y0 * b, a.z0 * b, a.x1 * b, a.y1 * b, a.z1 * b }; }
fn_inline r3f32_t r3f32_div(r3f32_t a, r3f32_t b) { return (r3f32_t){ a.x0 / b.x0, a.y0 / b.y0, a.z0 / b.z0, a.x1 / b.x1, a.y1 / b.y1, a.z1 / b.z1 }; }
fn_inline r3f32_t r3f32_divs(r3f32_t a, f32 b) { return (r3f32_t){ a.x0 / b, a.y0 / b, a.z0 / b, a.x1 / b, a.y1 / b, a.z1 / b }; }
fn_inline v2f64_t v2f64(f64 x, f64 y) { return (v2f64_t){ x, y }; }
gb_read_only v2f64_t v2f64_null = {0};
fn_inline b32 v2f64_is_null(v2f64_t a) { return memory_equal(&a, &v2f64_null, sizeof(a)); }
fn_inline b32 v2f64_are_equal(v2f64_t a, v2f64_t b) { return memory_equal(&a, &b, sizeof(a)); }
fn_inline v2f64_t v2f64_add(v2f64_t a, v2f64_t b) { return (v2f64_t){ a.x + b.x, a.y + b.y }; }
fn_inline v2f64_t v2f64_adds(v2f64_t a, f64 b) { return (v2f64_t){ a.x + b, a.y + b }; }
fn_inline v2f64_t v2f64_sub(v2f64_t a, v2f64_t b) { return (v2f64_t){ a.x - b.x, a.y - b.y }; }
fn_inline v2f64_t v2f64_subs(v2f64_t a, f64 b) { return (v2f64_t){ a.x - b, a.y - b }; }
fn_inline v2f64_t v2f64_mul(v2f64_t a, v2f64_t b) { return (v2f64_t){ a.x * b.x, a.y * b.y }; }
fn_inline v2f64_t v2f64_muls(v2f64_t a, f64 b) { return (v2f64_t){ a.x * b, a.y * b }; }
fn_inline v2f64_t v2f64_div(v2f64_t a, v2f64_t b) { return (v2f64_t){ a.x / b.x, a.y / b.y }; }
fn_inline v2f64_t v2f64_divs(v2f64_t a, f64 b) { return (v2f64_t){ a.x / b, a.y / b }; }
fn_inline v3f64_t v3f64(f64 x, f64 y, f64 z) { return (v3f64_t){ x, y, z }; }
gb_read_only v3f64_t v3f64_null = {0};
fn_inline b32 v3f64_is_null(v3f64_t a) { return memory_equal(&a, &v3f64_null, sizeof(a)); }
fn_inline b32 v3f64_are_equal(v3f64_t a, v3f64_t b) { return memory_equal(&a, &b, sizeof(a)); }
fn_inline v3f64_t v3f64_add(v3f64_t a, v3f64_t b) { return (v3f64_t){ a.x + b.x, a.y + b.y, a.z + b.z }; }
fn_inline v3f64_t v3f64_adds(v3f64_t a, f64 b) { return (v3f64_t){ a.x + b, a.y + b, a.z + b }; }
fn_inline v3f64_t v3f64_sub(v3f64_t a, v3f64_t b) { return (v3f64_t){ a.x - b.x, a.y - b.y, a.z - b.z }; }
fn_inline v3f64_t v3f64_subs(v3f64_t a, f64 b) { return (v3f64_t){ a.x - b, a.y - b, a.z - b }; }
fn_inline v3f64_t v3f64_mul(v3f64_t a, v3f64_t b) { return (v3f64_t){ a.x * b.x, a.y * b.y, a.z * b.z }; }
fn_inline v3f64_t v3f64_muls(v3f64_t a, f64 b) { return (v3f64_t){ a.x * b, a.y * b, a.z * b }; }
fn_inline v3f64_t v3f64_div(v3f64_t a, v3f64_t b) { return (v3f64_t){ a.x / b.x, a.y / b.y, a.z / b.z }; }
fn_inline v3f64_t v3f64_divs(v3f64_t a, f64 b) { return (v3f64_t){ a.x / b, a.y / b, a.z / b }; }
fn_inline v4f64_t v4f64(f64 x, f64 y, f64 z, f64 w) { return (v4f64_t){ x, y, z, w }; }
gb_read_only v4f64_t v4f64_null = {0};
fn_inline b32 v4f64_is_null(v4f64_t a) { return memory_equal(&a, &v4f64_null, sizeof(a)); }
fn_inline b32 v4f64_are_equal(v4f64_t a, v4f64_t b) { return memory_equal(&a, &b, sizeof(a)); }
fn_inline v4f64_t v4f64_add(v4f64_t a, v4f64_t b) { return (v4f64_t){ a.x + b.x, a.y + b.y, a.z + b.z, a.w + b.w }; }
fn_inline v4f64_t v4f64_adds(v4f64_t a, f64 b) { return (v4f64_t){ a.x + b, a.y + b, a.z + b, a.w + b }; }
fn_inline v4f64_t v4f64_sub(v4f64_t a, v4f64_t b) { return (v4f64_t){ a.x - b.x, a.y - b.y, a.z - b.z, a.w - b.w }; }
fn_inline v4f64_t v4f64_subs(v4f64_t a, f64 b) { return (v4f64_t){ a.x - b, a.y - b, a.z - b, a.w - b }; }
fn_inline v4f64_t v4f64_mul(v4f64_t a, v4f64_t b) { return (v4f64_t){ a.x * b.x, a.y * b.y, a.z * b.z, a.w * b.w }; }
fn_inline v4f64_t v4f64_muls(v4f64_t a, f64 b) { return (v4f64_t){ a.x * b, a.y * b, a.z * b, a.w * b }; }
fn_inline v4f64_t v4f64_div(v4f64_t a, v4f64_t b) { return (v4f64_t){ a.x / b.x, a.y / b.y, a.z / b.z, a.w / b.w }; }
fn_inline v4f64_t v4f64_divs(v4f64_t a, f64 b) { return (v4f64_t){ a.x / b, a.y / b, a.z / b, a.w / b }; }
fn_inline r2f64_t r2f64(f64 x0, f64 y0, f64 x1, f64 y1) { return (r2f64_t){ x0, y0, x1, y1 }; }
gb_read_only r2f64_t r2f64_null = {0};
fn_inline b32 r2f64_is_null(r2f64_t a) { return memory_equal(&a, &r2f64_null, sizeof(a)); }
fn_inline b32 r2f64_are_equal(r2f64_t a, r2f64_t b) { return memory_equal(&a, &b, sizeof(a)); }
fn_inline r2f64_t r2f64_add(r2f64_t a, r2f64_t b) { return (r2f64_t){ a.x0 + b.x0, a.y0 + b.y0, a.x1 + b.x1, a.y1 + b.y1 }; }
fn_inline r2f64_t r2f64_adds(r2f64_t a, f64 b) { return (r2f64_t){ a.x0 + b, a.y0 + b, a.x1 + b, a.y1 + b }; }
fn_inline r2f64_t r2f64_sub(r2f64_t a, r2f64_t b) { return (r2f64_t){ a.x0 - b.x0, a.y0 - b.y0, a.x1 - b.x1, a.y1 - b.y1 }; }
fn_inline r2f64_t r2f64_subs(r2f64_t a, f64 b) { return (r2f64_t){ a.x0 - b, a.y0 - b, a.x1 - b, a.y1 - b }; }
fn_inline r2f64_t r2f64_mul(r2f64_t a, r2f64_t b) { return (r2f64_t){ a.x0 * b.x0, a.y0 * b.y0, a.x1 * b.x1, a.y1 * b.y1 }; }
fn_inline r2f64_t r2f64_muls(r2f64_t a, f64 b) { return (r2f64_t){ a.x0 * b, a.y0 * b, a.x1 * b, a.y1 * b }; }
fn_inline r2f64_t r2f64_div(r2f64_t a, r2f64_t b) { return (r2f64_t){ a.x0 / b.x0, a.y0 / b.y0, a.x1 / b.x1, a.y1 / b.y1 }; }
fn_inline r2f64_t r2f64_divs(r2f64_t a, f64 b) { return (r2f64_t){ a.x0 / b, a.y0 / b, a.x1 / b, a.y1 / b }; }
fn_inline r3f64_t r3f64(f64 x0, f64 y0, f64 z0, f64 x1, f64 y1, f64 z1) { return (r3f64_t){ x0, y0, z0, x1, y1, z1 }; }
gb_read_only r3f64_t r3f64_null = {0};
fn_inline b32 r3f64_is_null(r3f64_t a) { return memory_equal(&a, &r3f64_null, sizeof(a)); }
fn_inline b32 r3f64_are_equal(r3f64_t a, r3f64_t b) { return memory_equal(&a, &b, sizeof(a)); }
fn_inline r3f64_t r3f64_add(r3f64_t a, r3f64_t b) { return (r3f64_t){ a.x0 + b.x0, a.y0 + b.y0, a.z0 + b.z0, a.x1 + b.x1, a.y1 + b.y1, a.z1 + b.z1 }; }
fn_inline r3f64_t r3f64_adds(r3f64_t a, f64 b) { return (r3f64_t){ a.x0 + b, a.y0 + b, a.z0 + b, a.x1 + b, a.y1 + b, a.z1 + b }; }
fn_inline r3f64_t r3f64_sub(r3f64_t a, r3f64_t b) { return (r3f64_t){ a.x0 - b.x0, a.y0 - b.y0, a.z0 - b.z0, a.x1 - b.x1, a.y1 - b.y1, a.z1 - b.z1 }; }
fn_inline r3f64_t r3f64_subs(r3f64_t a, f64 b) { return (r3f64_t){ a.x0 - b, a.y0 - b, a.z0 - b, a.x1 - b, a.y1 - b, a.z1 - b }; }
fn_inline r3f64_t r3f64_mul(r3f64_t a, r3f64_t b) { return (r3f64_t){ a.x0 * b.x0, a.y0 * b.y0, a.z0 * b.z0, a.x1 * b.x1, a.y1 * b.y1, a.z1 * b.z1 }; }
fn_inline r3f64_t r3f64_muls(r3f64_t a, f64 b) { return (r3f64_t){ a.x0 * b, a.y0 * b, a.z0 * b, a.x1 * b, a.y1 * b, a.z1 * b }; }
fn_inline r3f64_t r3f64_div(r3f64_t a, r3f64_t b) { return (r3f64_t){ a.x0 / b.x0, a.y0 / b.y0, a.z0 / b.z0, a.x1 / b.x1, a.y1 / b.y1, a.z1 / b.z1 }; }
fn_inline r3f64_t r3f64_divs(r3f64_t a, f64 b) { return (r3f64_t){ a.x0 / b, a.y0 / b, a.z0 / b, a.x1 / b, a.y1 / b, a.z1 / b }; }
fn_inline v2i32_t v2i32(i32 x, i32 y) { return (v2i32_t){ x, y }; }
gb_read_only v2i32_t v2i32_null = {0};
fn_inline b32 v2i32_is_null(v2i32_t a) { return memory_equal(&a, &v2i32_null, sizeof(a)); }
fn_inline b32 v2i32_are_equal(v2i32_t a, v2i32_t b) { return memory_equal(&a, &b, sizeof(a)); }
fn_inline v2i32_t v2i32_add(v2i32_t a, v2i32_t b) { return (v2i32_t){ a.x + b.x, a.y + b.y }; }
fn_inline v2i32_t v2i32_adds(v2i32_t a, i32 b) { return (v2i32_t){ a.x + b, a.y + b }; }
fn_inline v2i32_t v2i32_sub(v2i32_t a, v2i32_t b) { return (v2i32_t){ a.x - b.x, a.y - b.y }; }
fn_inline v2i32_t v2i32_subs(v2i32_t a, i32 b) { return (v2i32_t){ a.x - b, a.y - b }; }
fn_inline v2i32_t v2i32_mul(v2i32_t a, v2i32_t b) { return (v2i32_t){ a.x * b.x, a.y * b.y }; }
fn_inline v2i32_t v2i32_muls(v2i32_t a, i32 b) { return (v2i32_t){ a.x * b, a.y * b }; }
fn_inline v2i32_t v2i32_div(v2i32_t a, v2i32_t b) { return (v2i32_t){ a.x / b.x, a.y / b.y }; }
fn_inline v2i32_t v2i32_divs(v2i32_t a, i32 b) { return (v2i32_t){ a.x / b, a.y / b }; }
fn_inline v3i32_t v3i32(i32 x, i32 y, i32 z) { return (v3i32_t){ x, y, z }; }
gb_read_only v3i32_t v3i32_null = {0};
fn_inline b32 v3i32_is_null(v3i32_t a) { return memory_equal(&a, &v3i32_null, sizeof(a)); }
fn_inline b32 v3i32_are_equal(v3i32_t a, v3i32_t b) { return memory_equal(&a, &b, sizeof(a)); }
fn_inline v3i32_t v3i32_add(v3i32_t a, v3i32_t b) { return (v3i32_t){ a.x + b.x, a.y + b.y, a.z + b.z }; }
fn_inline v3i32_t v3i32_adds(v3i32_t a, i32 b) { return (v3i32_t){ a.x + b, a.y + b, a.z + b }; }
fn_inline v3i32_t v3i32_sub(v3i32_t a, v3i32_t b) { return (v3i32_t){ a.x - b.x, a.y - b.y, a.z - b.z }; }
fn_inline v3i32_t v3i32_subs(v3i32_t a, i32 b) { return (v3i32_t){ a.x - b, a.y - b, a.z - b }; }
fn_inline v3i32_t v3i32_mul(v3i32_t a, v3i32_t b) { return (v3i32_t){ a.x * b.x, a.y * b.y, a.z * b.z }; }
fn_inline v3i32_t v3i32_muls(v3i32_t a, i32 b) { return (v3i32_t){ a.x * b, a.y * b, a.z * b }; }
fn_inline v3i32_t v3i32_div(v3i32_t a, v3i32_t b) { return (v3i32_t){ a.x / b.x, a.y / b.y, a.z / b.z }; }
fn_inline v3i32_t v3i32_divs(v3i32_t a, i32 b) { return (v3i32_t){ a.x / b, a.y / b, a.z / b }; }
fn_inline v4i32_t v4i32(i32 x, i32 y, i32 z, i32 w) { return (v4i32_t){ x, y, z, w }; }
gb_read_only v4i32_t v4i32_null = {0};
fn_inline b32 v4i32_is_null(v4i32_t a) { return memory_equal(&a, &v4i32_null, sizeof(a)); }
fn_inline b32 v4i32_are_equal(v4i32_t a, v4i32_t b) { return memory_equal(&a, &b, sizeof(a)); }
fn_inline v4i32_t v4i32_add(v4i32_t a, v4i32_t b) { return (v4i32_t){ a.x + b.x, a.y + b.y, a.z + b.z, a.w + b.w }; }
fn_inline v4i32_t v4i32_adds(v4i32_t a, i32 b) { return (v4i32_t){ a.x + b, a.y + b, a.z + b, a.w + b }; }
fn_inline v4i32_t v4i32_sub(v4i32_t a, v4i32_t b) { return (v4i32_t){ a.x - b.x, a.y - b.y, a.z - b.z, a.w - b.w }; }
fn_inline v4i32_t v4i32_subs(v4i32_t a, i32 b) { return (v4i32_t){ a.x - b, a.y - b, a.z - b, a.w - b }; }
fn_inline v4i32_t v4i32_mul(v4i32_t a, v4i32_t b) { return (v4i32_t){ a.x * b.x, a.y * b.y, a.z * b.z, a.w * b.w }; }
fn_inline v4i32_t v4i32_muls(v4i32_t a, i32 b) { return (v4i32_t){ a.x * b, a.y * b, a.z * b, a.w * b }; }
fn_inline v4i32_t v4i32_div(v4i32_t a, v4i32_t b) { return (v4i32_t){ a.x / b.x, a.y / b.y, a.z / b.z, a.w / b.w }; }
fn_inline v4i32_t v4i32_divs(v4i32_t a, i32 b) { return (v4i32_t){ a.x / b, a.y / b, a.z / b, a.w / b }; }
fn_inline r2i32_t r2i32(i32 x0, i32 y0, i32 x1, i32 y1) { return (r2i32_t){ x0, y0, x1, y1 }; }
gb_read_only r2i32_t r2i32_null = {0};
fn_inline b32 r2i32_is_null(r2i32_t a) { return memory_equal(&a, &r2i32_null, sizeof(a)); }
fn_inline b32 r2i32_are_equal(r2i32_t a, r2i32_t b) { return memory_equal(&a, &b, sizeof(a)); }
fn_inline r2i32_t r2i32_add(r2i32_t a, r2i32_t b) { return (r2i32_t){ a.x0 + b.x0, a.y0 + b.y0, a.x1 + b.x1, a.y1 + b.y1 }; }
fn_inline r2i32_t r2i32_adds(r2i32_t a, i32 b) { return (r2i32_t){ a.x0 + b, a.y0 + b, a.x1 + b, a.y1 + b }; }
fn_inline r2i32_t r2i32_sub(r2i32_t a, r2i32_t b) { return (r2i32_t){ a.x0 - b.x0, a.y0 - b.y0, a.x1 - b.x1, a.y1 - b.y1 }; }
fn_inline r2i32_t r2i32_subs(r2i32_t a, i32 b) { return (r2i32_t){ a.x0 - b, a.y0 - b, a.x1 - b, a.y1 - b }; }
fn_inline r2i32_t r2i32_mul(r2i32_t a, r2i32_t b) { return (r2i32_t){ a.x0 * b.x0, a.y0 * b.y0, a.x1 * b.x1, a.y1 * b.y1 }; }
fn_inline r2i32_t r2i32_muls(r2i32_t a, i32 b) { return (r2i32_t){ a.x0 * b, a.y0 * b, a.x1 * b, a.y1 * b }; }
fn_inline r2i32_t r2i32_div(r2i32_t a, r2i32_t b) { return (r2i32_t){ a.x0 / b.x0, a.y0 / b.y0, a.x1 / b.x1, a.y1 / b.y1 }; }
fn_inline r2i32_t r2i32_divs(r2i32_t a, i32 b) { return (r2i32_t){ a.x0 / b, a.y0 / b, a.x1 / b, a.y1 / b }; }
fn_inline r3i32_t r3i32(i32 x0, i32 y0, i32 z0, i32 x1, i32 y1, i32 z1) { return (r3i32_t){ x0, y0, z0, x1, y1, z1 }; }
gb_read_only r3i32_t r3i32_null = {0};
fn_inline b32 r3i32_is_null(r3i32_t a) { return memory_equal(&a, &r3i32_null, sizeof(a)); }
fn_inline b32 r3i32_are_equal(r3i32_t a, r3i32_t b) { return memory_equal(&a, &b, sizeof(a)); }
fn_inline r3i32_t r3i32_add(r3i32_t a, r3i32_t b) { return (r3i32_t){ a.x0 + b.x0, a.y0 + b.y0, a.z0 + b.z0, a.x1 + b.x1, a.y1 + b.y1, a.z1 + b.z1 }; }
fn_inline r3i32_t r3i32_adds(r3i32_t a, i32 b) { return (r3i32_t){ a.x0 + b, a.y0 + b, a.z0 + b, a.x1 + b, a.y1 + b, a.z1 + b }; }
fn_inline r3i32_t r3i32_sub(r3i32_t a, r3i32_t b) { return (r3i32_t){ a.x0 - b.x0, a.y0 - b.y0, a.z0 - b.z0, a.x1 - b.x1, a.y1 - b.y1, a.z1 - b.z1 }; }
fn_inline r3i32_t r3i32_subs(r3i32_t a, i32 b) { return (r3i32_t){ a.x0 - b, a.y0 - b, a.z0 - b, a.x1 - b, a.y1 - b, a.z1 - b }; }
fn_inline r3i32_t r3i32_mul(r3i32_t a, r3i32_t b) { return (r3i32_t){ a.x0 * b.x0, a.y0 * b.y0, a.z0 * b.z0, a.x1 * b.x1, a.y1 * b.y1, a.z1 * b.z1 }; }
fn_inline r3i32_t r3i32_muls(r3i32_t a, i32 b) { return (r3i32_t){ a.x0 * b, a.y0 * b, a.z0 * b, a.x1 * b, a.y1 * b, a.z1 * b }; }
fn_inline r3i32_t r3i32_div(r3i32_t a, r3i32_t b) { return (r3i32_t){ a.x0 / b.x0, a.y0 / b.y0, a.z0 / b.z0, a.x1 / b.x1, a.y1 / b.y1, a.z1 / b.z1 }; }
fn_inline r3i32_t r3i32_divs(r3i32_t a, i32 b) { return (r3i32_t){ a.x0 / b, a.y0 / b, a.z0 / b, a.x1 / b, a.y1 / b, a.z1 / b }; }
fn_inline v2i64_t v2i64(i64 x, i64 y) { return (v2i64_t){ x, y }; }
gb_read_only v2i64_t v2i64_null = {0};
fn_inline b32 v2i64_is_null(v2i64_t a) { return memory_equal(&a, &v2i64_null, sizeof(a)); }
fn_inline b32 v2i64_are_equal(v2i64_t a, v2i64_t b) { return memory_equal(&a, &b, sizeof(a)); }
fn_inline v2i64_t v2i64_add(v2i64_t a, v2i64_t b) { return (v2i64_t){ a.x + b.x, a.y + b.y }; }
fn_inline v2i64_t v2i64_adds(v2i64_t a, i64 b) { return (v2i64_t){ a.x + b, a.y + b }; }
fn_inline v2i64_t v2i64_sub(v2i64_t a, v2i64_t b) { return (v2i64_t){ a.x - b.x, a.y - b.y }; }
fn_inline v2i64_t v2i64_subs(v2i64_t a, i64 b) { return (v2i64_t){ a.x - b, a.y - b }; }
fn_inline v2i64_t v2i64_mul(v2i64_t a, v2i64_t b) { return (v2i64_t){ a.x * b.x, a.y * b.y }; }
fn_inline v2i64_t v2i64_muls(v2i64_t a, i64 b) { return (v2i64_t){ a.x * b, a.y * b }; }
fn_inline v2i64_t v2i64_div(v2i64_t a, v2i64_t b) { return (v2i64_t){ a.x / b.x, a.y / b.y }; }
fn_inline v2i64_t v2i64_divs(v2i64_t a, i64 b) { return (v2i64_t){ a.x / b, a.y / b }; }
fn_inline v3i64_t v3i64(i64 x, i64 y, i64 z) { return (v3i64_t){ x, y, z }; }
gb_read_only v3i64_t v3i64_null = {0};
fn_inline b32 v3i64_is_null(v3i64_t a) { return memory_equal(&a, &v3i64_null, sizeof(a)); }
fn_inline b32 v3i64_are_equal(v3i64_t a, v3i64_t b) { return memory_equal(&a, &b, sizeof(a)); }
fn_inline v3i64_t v3i64_add(v3i64_t a, v3i64_t b) { return (v3i64_t){ a.x + b.x, a.y + b.y, a.z + b.z }; }
fn_inline v3i64_t v3i64_adds(v3i64_t a, i64 b) { return (v3i64_t){ a.x + b, a.y + b, a.z + b }; }
fn_inline v3i64_t v3i64_sub(v3i64_t a, v3i64_t b) { return (v3i64_t){ a.x - b.x, a.y - b.y, a.z - b.z }; }
fn_inline v3i64_t v3i64_subs(v3i64_t a, i64 b) { return (v3i64_t){ a.x - b, a.y - b, a.z - b }; }
fn_inline v3i64_t v3i64_mul(v3i64_t a, v3i64_t b) { return (v3i64_t){ a.x * b.x, a.y * b.y, a.z * b.z }; }
fn_inline v3i64_t v3i64_muls(v3i64_t a, i64 b) { return (v3i64_t){ a.x * b, a.y * b, a.z * b }; }
fn_inline v3i64_t v3i64_div(v3i64_t a, v3i64_t b) { return (v3i64_t){ a.x / b.x, a.y / b.y, a.z / b.z }; }
fn_inline v3i64_t v3i64_divs(v3i64_t a, i64 b) { return (v3i64_t){ a.x / b, a.y / b, a.z / b }; }
fn_inline v4i64_t v4i64(i64 x, i64 y, i64 z, i64 w) { return (v4i64_t){ x, y, z, w }; }
gb_read_only v4i64_t v4i64_null = {0};
fn_inline b32 v4i64_is_null(v4i64_t a) { return memory_equal(&a, &v4i64_null, sizeof(a)); }
fn_inline b32 v4i64_are_equal(v4i64_t a, v4i64_t b) { return memory_equal(&a, &b, sizeof(a)); }
fn_inline v4i64_t v4i64_add(v4i64_t a, v4i64_t b) { return (v4i64_t){ a.x + b.x, a.y + b.y, a.z + b.z, a.w + b.w }; }
fn_inline v4i64_t v4i64_adds(v4i64_t a, i64 b) { return (v4i64_t){ a.x + b, a.y + b, a.z + b, a.w + b }; }
fn_inline v4i64_t v4i64_sub(v4i64_t a, v4i64_t b) { return (v4i64_t){ a.x - b.x, a.y - b.y, a.z - b.z, a.w - b.w }; }
fn_inline v4i64_t v4i64_subs(v4i64_t a, i64 b) { return (v4i64_t){ a.x - b, a.y - b, a.z - b, a.w - b }; }
fn_inline v4i64_t v4i64_mul(v4i64_t a, v4i64_t b) { return (v4i64_t){ a.x * b.x, a.y * b.y, a.z * b.z, a.w * b.w }; }
fn_inline v4i64_t v4i64_muls(v4i64_t a, i64 b) { return (v4i64_t){ a.x * b, a.y * b, a.z * b, a.w * b }; }
fn_inline v4i64_t v4i64_div(v4i64_t a, v4i64_t b) { return (v4i64_t){ a.x / b.x, a.y / b.y, a.z / b.z, a.w / b.w }; }
fn_inline v4i64_t v4i64_divs(v4i64_t a, i64 b) { return (v4i64_t){ a.x / b, a.y / b, a.z / b, a.w / b }; }
fn_inline r2i64_t r2i64(i64 x0, i64 y0, i64 x1, i64 y1) { return (r2i64_t){ x0, y0, x1, y1 }; }
gb_read_only r2i64_t r2i64_null = {0};
fn_inline b32 r2i64_is_null(r2i64_t a) { return memory_equal(&a, &r2i64_null, sizeof(a)); }
fn_inline b32 r2i64_are_equal(r2i64_t a, r2i64_t b) { return memory_equal(&a, &b, sizeof(a)); }
fn_inline r2i64_t r2i64_add(r2i64_t a, r2i64_t b) { return (r2i64_t){ a.x0 + b.x0, a.y0 + b.y0, a.x1 + b.x1, a.y1 + b.y1 }; }
fn_inline r2i64_t r2i64_adds(r2i64_t a, i64 b) { return (r2i64_t){ a.x0 + b, a.y0 + b, a.x1 + b, a.y1 + b }; }
fn_inline r2i64_t r2i64_sub(r2i64_t a, r2i64_t b) { return (r2i64_t){ a.x0 - b.x0, a.y0 - b.y0, a.x1 - b.x1, a.y1 - b.y1 }; }
fn_inline r2i64_t r2i64_subs(r2i64_t a, i64 b) { return (r2i64_t){ a.x0 - b, a.y0 - b, a.x1 - b, a.y1 - b }; }
fn_inline r2i64_t r2i64_mul(r2i64_t a, r2i64_t b) { return (r2i64_t){ a.x0 * b.x0, a.y0 * b.y0, a.x1 * b.x1, a.y1 * b.y1 }; }
fn_inline r2i64_t r2i64_muls(r2i64_t a, i64 b) { return (r2i64_t){ a.x0 * b, a.y0 * b, a.x1 * b, a.y1 * b }; }
fn_inline r2i64_t r2i64_div(r2i64_t a, r2i64_t b) { return (r2i64_t){ a.x0 / b.x0, a.y0 / b.y0, a.x1 / b.x1, a.y1 / b.y1 }; }
fn_inline r2i64_t r2i64_divs(r2i64_t a, i64 b) { return (r2i64_t){ a.x0 / b, a.y0 / b, a.x1 / b, a.y1 / b }; }
fn_inline r3i64_t r3i64(i64 x0, i64 y0, i64 z0, i64 x1, i64 y1, i64 z1) { return (r3i64_t){ x0, y0, z0, x1, y1, z1 }; }
gb_read_only r3i64_t r3i64_null = {0};
fn_inline b32 r3i64_is_null(r3i64_t a) { return memory_equal(&a, &r3i64_null, sizeof(a)); }
fn_inline b32 r3i64_are_equal(r3i64_t a, r3i64_t b) { return memory_equal(&a, &b, sizeof(a)); }
fn_inline r3i64_t r3i64_add(r3i64_t a, r3i64_t b) { return (r3i64_t){ a.x0 + b.x0, a.y0 + b.y0, a.z0 + b.z0, a.x1 + b.x1, a.y1 + b.y1, a.z1 + b.z1 }; }
fn_inline r3i64_t r3i64_adds(r3i64_t a, i64 b) { return (r3i64_t){ a.x0 + b, a.y0 + b, a.z0 + b, a.x1 + b, a.y1 + b, a.z1 + b }; }
fn_inline r3i64_t r3i64_sub(r3i64_t a, r3i64_t b) { return (r3i64_t){ a.x0 - b.x0, a.y0 - b.y0, a.z0 - b.z0, a.x1 - b.x1, a.y1 - b.y1, a.z1 - b.z1 }; }
fn_inline r3i64_t r3i64_subs(r3i64_t a, i64 b) { return (r3i64_t){ a.x0 - b, a.y0 - b, a.z0 - b, a.x1 - b, a.y1 - b, a.z1 - b }; }
fn_inline r3i64_t r3i64_mul(r3i64_t a, r3i64_t b) { return (r3i64_t){ a.x0 * b.x0, a.y0 * b.y0, a.z0 * b.z0, a.x1 * b.x1, a.y1 * b.y1, a.z1 * b.z1 }; }
fn_inline r3i64_t r3i64_muls(r3i64_t a, i64 b) { return (r3i64_t){ a.x0 * b, a.y0 * b, a.z0 * b, a.x1 * b, a.y1 * b, a.z1 * b }; }
fn_inline r3i64_t r3i64_div(r3i64_t a, r3i64_t b) { return (r3i64_t){ a.x0 / b.x0, a.y0 / b.y0, a.z0 / b.z0, a.x1 / b.x1, a.y1 / b.y1, a.z1 / b.z1 }; }
fn_inline r3i64_t r3i64_divs(r3i64_t a, i64 b) { return (r3i64_t){ a.x0 / b, a.y0 / b, a.z0 / b, a.x1 / b, a.y1 / b, a.z1 / b }; }
fn_inline r2f32_t r2f32_min_dim(v2f32_t pos, v2f32_t size) { return (r2f32_t){ pos, v2f32_add(pos, size) }; }
fn_inline r2f32_t r2f32_center_half_dim(v2f32_t center, v2f32_t halfdim) { return (r2f32_t){ v2f32_sub(center, halfdim), v2f32_add(center, halfdim) }; }
fn_inline r3f32_t r3f32_min_dim(v3f32_t pos, v3f32_t size) { return (r3f32_t){ pos, v3f32_add(pos, size) }; }
fn_inline r3f32_t r3f32_center_half_dim(v3f32_t center, v3f32_t halfdim) { return (r3f32_t){ v3f32_sub(center, halfdim), v3f32_add(center, halfdim) }; }
fn_inline r2f64_t r2f64_min_dim(v2f64_t pos, v2f64_t size) { return (r2f64_t){ pos, v2f64_add(pos, size) }; }
fn_inline r2f64_t r2f64_center_half_dim(v2f64_t center, v2f64_t halfdim) { return (r2f64_t){ v2f64_sub(center, halfdim), v2f64_add(center, halfdim) }; }
fn_inline r3f64_t r3f64_min_dim(v3f64_t pos, v3f64_t size) { return (r3f64_t){ pos, v3f64_add(pos, size) }; }
fn_inline r3f64_t r3f64_center_half_dim(v3f64_t center, v3f64_t halfdim) { return (r3f64_t){ v3f64_sub(center, halfdim), v3f64_add(center, halfdim) }; }
fn_inline r2i32_t r2i32_min_dim(v2i32_t pos, v2i32_t size) { return (r2i32_t){ pos, v2i32_add(pos, size) }; }
fn_inline r2i32_t r2i32_center_half_dim(v2i32_t center, v2i32_t halfdim) { return (r2i32_t){ v2i32_sub(center, halfdim), v2i32_add(center, halfdim) }; }
fn_inline r3i32_t r3i32_min_dim(v3i32_t pos, v3i32_t size) { return (r3i32_t){ pos, v3i32_add(pos, size) }; }
fn_inline r3i32_t r3i32_center_half_dim(v3i32_t center, v3i32_t halfdim) { return (r3i32_t){ v3i32_sub(center, halfdim), v3i32_add(center, halfdim) }; }
fn_inline r2i64_t r2i64_min_dim(v2i64_t pos, v2i64_t size) { return (r2i64_t){ pos, v2i64_add(pos, size) }; }
fn_inline r2i64_t r2i64_center_half_dim(v2i64_t center, v2i64_t halfdim) { return (r2i64_t){ v2i64_sub(center, halfdim), v2i64_add(center, halfdim) }; }
fn_inline r3i64_t r3i64_min_dim(v3i64_t pos, v3i64_t size) { return (r3i64_t){ pos, v3i64_add(pos, size) }; }
fn_inline r3i64_t r3i64_center_half_dim(v3i64_t center, v3i64_t halfdim) { return (r3i64_t){ v3i64_sub(center, halfdim), v3i64_add(center, halfdim) }; }
fn r2f32_t r2f32_cut_left(r2f32_t *r, f32 value) {
f32 minx = r->min.x;
r->min.x = MIN(r->min.x + value, r->max.x);
r2f32_t result = { .min = {.x = minx, .y = r->min.y}, .max = {.x = r->min.x, .y =r->max.y} };
return result;
}
fn r2f32_t r2f32_cut_right(r2f32_t *r, f32 value) {
f32 maxx = r->max.x;
r->max.x = MAX(r->min.x, r->max.x - value);
r2f32_t result = { .min = {.x = r->max.x, .y = r->min.y}, .max = {.x = maxx, .y = r->max.y} };
return result;
}
fn r2f32_t r2f32_cut_top(r2f32_t *r, f32 value) { /* Y is down */
f32 miny = r->min.y;
r->min.y = MIN(r->max.y, r->min.y + value);
r2f32_t result = { .min = {.x = r->min.x, .y = miny}, .max = {.x = r->max.x, .y = r->min.y} };
return result;
}
fn r2f32_t r2f32_cut_bottom(r2f32_t *r, f32 value) { /* Y is down */
f32 maxy = r->max.y;
r->max.y = MAX(r->min.y, r->max.y - value);
r2f32_t result = { .min = {.x = r->min.x, .y = r->max.y}, .max = {.x = r->max.x, .y = maxy} };
return result;
}
fn r2f32_t r2f32_cut_left_no_squash(r2f32_t *r, f32 value) {
f32 minx = r->min.x;
r->min.x = r->min.x + value;
r2f32_t result = { .min = {.x = minx, .y = r->min.y}, .max = {.x = r->min.x, .y =r->max.y} };
return result;
}
fn r2f32_t r2f32_cut_right_no_squash(r2f32_t *r, f32 value) {
f32 maxx = r->max.x;
r->max.x = r->max.x - value;
r2f32_t result = { .min = {.x = r->max.x, .y = r->min.y}, .max = {.x = maxx, .y = r->max.y} };
return result;
}
fn r2f32_t r2f32_cut_top_no_squash(r2f32_t *r, f32 value) { /* Y is down */
f32 miny = r->min.y;
r->min.y = r->min.y + value;
r2f32_t result = { .min = {.x = r->min.x, .y = miny}, .max = {.x = r->max.x, .y = r->min.y} };
return result;
}
fn r2f32_t r2f32_cut_bottom_no_squash(r2f32_t *r, f32 value) { /* Y is down */
f32 maxy = r->max.y;
r->max.y = r->max.y - value;
r2f32_t result = { .min = {.x = r->min.x, .y = r->max.y}, .max = {.x = r->max.x, .y = maxy} };
return result;
}
fn r2f32_t r2f32_add_left(r2f32_t *r, f32 value) {
r2f32_t result = { .min = {r->min.x - value, r->min.y}, .max = {r->min.x, r->max.y} };
r->min.x -= value;
return result;
}
fn r2f32_t r2f32_add_right(r2f32_t *r, f32 value) {
r2f32_t result = { .min = {r->max.x, r->min.y}, .max = {r->max.x + value, r->max.y} };
r->max.x += value;
return result;
}
fn r2f32_t r2f32_add_top(r2f32_t *r, f32 value) {
r2f32_t result = { .min = {r->min.x, r->min.y - value}, .max = {r->max.x, r->min.y} };
r->min.y -= value;
return result;
}
fn r2f32_t r2f32_add_bottom(r2f32_t *r, f32 value) {
r2f32_t result = { .min = {r->min.x, r->max.y}, .max = {r->max.x, r->max.y + value} };
r->max.y += value;
return result;
}
// get past left
fn r2f32_t r2f32_getp_left(const r2f32_t *rect, f32 value) {
r2f32_t result = r2f32(rect->min.x - value, rect->min.y, rect->min.x, rect->max.y);
return result;
}
fn r2f32_t r2f32_getp_right(const r2f32_t *rect, f32 value) {
r2f32_t result = r2f32(rect->max.x, rect->min.y, rect->max.x + value, rect->max.y);
return result;
}
fn r2f32_t r2f32_getp_bottom(const r2f32_t *rect, f32 value) {
r2f32_t result = r2f32(rect->min.x, rect->max.y, rect->max.x, rect->max.y + value);
return result;
}
fn r2f32_t r2f32_getp_top(const r2f32_t *rect, f32 value) {
r2f32_t result = r2f32(rect->min.x, rect->min.y - value, rect->max.x, rect->min.y);
return result;
}
fn r2f32_t r2f32_get_left(const r2f32_t *r, f32 value) {
f32 minx = r->min.x;
r2f32_t result = (r2f32_t){ .min = {.x = minx, .y = r->min.y}, .max = {.x = MIN(r->min.x + value, r->max.x), .y =r->max.y} };
return result;
}
fn r2f32_t r2f32_get_right(const r2f32_t *r, f32 value) {
f32 maxx = r->max.x;
r2f32_t result = (r2f32_t){ .min = {.x = MAX(r->min.x, r->max.x - value), .y = r->min.y}, .max = {.x = maxx, .y = r->max.y} };
return result;
}
fn r2f32_t r2f32_get_top(const r2f32_t *r, f32 value) { /* Y is down */
f32 miny = r->min.y;
r2f32_t result = (r2f32_t){ .min = {.x = r->min.x, .y = miny}, .max = {.x = r->max.x, .y = MIN(r->max.y, r->min.y + value)} };
return result;
}
fn r2f32_t r2f32_get_bottom(const r2f32_t *r, f32 value) { /* Y is down */
f32 maxy = r->max.y;
r2f32_t result = (r2f32_t){ .min = {.x = r->min.x, .y = MAX(r->min.y, r->max.y - value)}, .max = {.x = r->max.x, .y = maxy} };
return result;
}
fn_inline r2f32_t r2f32_expand(r2f32_t rect, v2f32_t value) { return (r2f32_t){ v2f32_sub(rect.min, value), v2f32_add(rect.max, value) }; }
fn_inline r2f32_t r2f32_shrink(r2f32_t rect, v2f32_t value) { return (r2f32_t){ v2f32_add(rect.min, value), v2f32_sub(rect.max, value) }; }
fn_inline r2f32_t r2f32_shrinks(r2f32_t rect, f32 value) { return (r2f32_t){ v2f32_adds(rect.min, value), v2f32_subs(rect.max, value) }; }
fn_inline v2f32_t r2f32_size(r2f32_t r) { return (v2f32_t){r.max.x - r.min.x, r.max.y - r.min.y}; }
fn_inline v2f32_t r2f32_get_mid(r2f32_t r) { return v2f32_add(r.min, v2f32_divs(r2f32_size(r), 2)); }
fn_inline b32 r2f32_contains(r2f32_t rec, v2f32_t point) { return (point.x >= rec.min.x) && (point.x < rec.max.x) && (point.y >= rec.min.y) && (point.y < rec.max.y); }
fn_inline r2f32_t r2f32_intersect(r2f32_t a, r2f32_t b) { return (r2f32_t){ .min.x = MAX(a.min.x, b.min.x), .min.y = MAX(a.min.y, b.min.y), .max.x = MIN(a.max.x, b.max.x), .max.y = MIN(a.max.y, b.max.y) }; }
fn_inline r2f32_t r2f32_union(r2f32_t a, r2f32_t b) { return (r2f32_t){ .min.x = MIN(a.min.x, b.min.x), .min.y = MIN(a.min.y, b.min.y), .max.x = MAX(a.max.x, b.max.x), .max.y = MAX(a.max.y, b.max.y) }; }
fn_inline f32 r1f32_size(r1f32_t a) { return a.max - a.min; }
fn_inline r1f32_t r1f32(f32 min, f32 max) { return (r1f32_t){min,max}; }
fn_inline r1f32_t r1f32_auto(f32 a, f32 b) { return (r1f32_t){MIN(a,b),MAX(a,b)}; }
fn_inline r1f32_t r1f32s(f32 a) { return (r1f32_t){a,a}; }
fn_inline r1f32_t r1f32_clamp(r1f32_t a, f32 min, f32 max) { return (r1f32_t){ .min = CLAMP(a.min, min, max), .max = CLAMP(a.max, min, max) }; }
fn_inline b32 r1f32_contains(r1f32_t rec, f32 point) { return (point >= rec.min) && (point < rec.max) && (point >= rec.min) && (point < rec.max); }
fn_inline b32 r1f32_are_equal(r1f32_t a, r1f32_t b) { return a.min == b.min && a.max == b.max; }
gb_read_only r1f32_t r1f32_null;
fn b32 r1f32_overlap(r1f32_t a, r1f32_t b) {
b32 r1 = (a.max >= b.min && a.max <= b.max) || (a.min >= b.min && a.min <= b.max);
b32 r2 = (b.max >= a.min && b.max <= a.max) || (b.min >= a.min && b.min <= a.max);
return r1 || r2;
}
fn v2f32_t v2f32_clamps(v2f32_t v, f32 min, f32 max) {
v2f32_t result = { CLAMP(v.x, min, max), CLAMP(v.y, min, max) };
return result;
}
fn v2f32_t v2f32_clamp(v2f32_t v, v2f32_t min, v2f32_t max) {
v2f32_t result = { CLAMP(v.x, min.x, max.x), CLAMP(v.y, min.y, max.y) };
return result;
}
fn r2f32_t r2f32_fix(r2f32_t n) {
r2f32_t result = {
.min = {MIN(n.min.x, n.max.x), MIN(n.min.y, n.max.y)},
.max = {MAX(n.min.x, n.max.x), MAX(n.min.y, n.max.y)},
};
return result;
}
fn r2f64_t r2f64_cut_left(r2f64_t *r, f64 value) {
f64 minx = r->min.x;
r->min.x = MIN(r->min.x + value, r->max.x);
r2f64_t result = { .min = {.x = minx, .y = r->min.y}, .max = {.x = r->min.x, .y =r->max.y} };
return result;
}
fn r2f64_t r2f64_cut_right(r2f64_t *r, f64 value) {
f64 maxx = r->max.x;
r->max.x = MAX(r->min.x, r->max.x - value);
r2f64_t result = { .min = {.x = r->max.x, .y = r->min.y}, .max = {.x = maxx, .y = r->max.y} };
return result;
}
fn r2f64_t r2f64_cut_top(r2f64_t *r, f64 value) { /* Y is down */
f64 miny = r->min.y;
r->min.y = MIN(r->max.y, r->min.y + value);
r2f64_t result = { .min = {.x = r->min.x, .y = miny}, .max = {.x = r->max.x, .y = r->min.y} };
return result;
}
fn r2f64_t r2f64_cut_bottom(r2f64_t *r, f64 value) { /* Y is down */
f64 maxy = r->max.y;
r->max.y = MAX(r->min.y, r->max.y - value);
r2f64_t result = { .min = {.x = r->min.x, .y = r->max.y}, .max = {.x = r->max.x, .y = maxy} };
return result;
}
fn r2f64_t r2f64_cut_left_no_squash(r2f64_t *r, f64 value) {
f64 minx = r->min.x;
r->min.x = r->min.x + value;
r2f64_t result = { .min = {.x = minx, .y = r->min.y}, .max = {.x = r->min.x, .y =r->max.y} };
return result;
}
fn r2f64_t r2f64_cut_right_no_squash(r2f64_t *r, f64 value) {
f64 maxx = r->max.x;
r->max.x = r->max.x - value;
r2f64_t result = { .min = {.x = r->max.x, .y = r->min.y}, .max = {.x = maxx, .y = r->max.y} };
return result;
}
fn r2f64_t r2f64_cut_top_no_squash(r2f64_t *r, f64 value) { /* Y is down */
f64 miny = r->min.y;
r->min.y = r->min.y + value;
r2f64_t result = { .min = {.x = r->min.x, .y = miny}, .max = {.x = r->max.x, .y = r->min.y} };
return result;
}
fn r2f64_t r2f64_cut_bottom_no_squash(r2f64_t *r, f64 value) { /* Y is down */
f64 maxy = r->max.y;
r->max.y = r->max.y - value;
r2f64_t result = { .min = {.x = r->min.x, .y = r->max.y}, .max = {.x = r->max.x, .y = maxy} };
return result;
}
fn r2f64_t r2f64_add_left(r2f64_t *r, f64 value) {
r2f64_t result = { .min = {r->min.x - value, r->min.y}, .max = {r->min.x, r->max.y} };
r->min.x -= value;
return result;
}
fn r2f64_t r2f64_add_right(r2f64_t *r, f64 value) {
r2f64_t result = { .min = {r->max.x, r->min.y}, .max = {r->max.x + value, r->max.y} };
r->max.x += value;
return result;
}
fn r2f64_t r2f64_add_top(r2f64_t *r, f64 value) {
r2f64_t result = { .min = {r->min.x, r->min.y - value}, .max = {r->max.x, r->min.y} };
r->min.y -= value;
return result;
}
fn r2f64_t r2f64_add_bottom(r2f64_t *r, f64 value) {
r2f64_t result = { .min = {r->min.x, r->max.y}, .max = {r->max.x, r->max.y + value} };
r->max.y += value;
return result;
}
// get past left
fn r2f64_t r2f64_getp_left(const r2f64_t *rect, f64 value) {
r2f64_t result = r2f64(rect->min.x - value, rect->min.y, rect->min.x, rect->max.y);
return result;
}
fn r2f64_t r2f64_getp_right(const r2f64_t *rect, f64 value) {
r2f64_t result = r2f64(rect->max.x, rect->min.y, rect->max.x + value, rect->max.y);
return result;
}
fn r2f64_t r2f64_getp_bottom(const r2f64_t *rect, f64 value) {
r2f64_t result = r2f64(rect->min.x, rect->max.y, rect->max.x, rect->max.y + value);
return result;
}
fn r2f64_t r2f64_getp_top(const r2f64_t *rect, f64 value) {
r2f64_t result = r2f64(rect->min.x, rect->min.y - value, rect->max.x, rect->min.y);
return result;
}
fn r2f64_t r2f64_get_left(const r2f64_t *r, f64 value) {
f64 minx = r->min.x;
r2f64_t result = (r2f64_t){ .min = {.x = minx, .y = r->min.y}, .max = {.x = MIN(r->min.x + value, r->max.x), .y =r->max.y} };
return result;
}
fn r2f64_t r2f64_get_right(const r2f64_t *r, f64 value) {
f64 maxx = r->max.x;
r2f64_t result = (r2f64_t){ .min = {.x = MAX(r->min.x, r->max.x - value), .y = r->min.y}, .max = {.x = maxx, .y = r->max.y} };
return result;
}
fn r2f64_t r2f64_get_top(const r2f64_t *r, f64 value) { /* Y is down */
f64 miny = r->min.y;
r2f64_t result = (r2f64_t){ .min = {.x = r->min.x, .y = miny}, .max = {.x = r->max.x, .y = MIN(r->max.y, r->min.y + value)} };
return result;
}
fn r2f64_t r2f64_get_bottom(const r2f64_t *r, f64 value) { /* Y is down */
f64 maxy = r->max.y;
r2f64_t result = (r2f64_t){ .min = {.x = r->min.x, .y = MAX(r->min.y, r->max.y - value)}, .max = {.x = r->max.x, .y = maxy} };
return result;
}
fn_inline r2f64_t r2f64_expand(r2f64_t rect, v2f64_t value) { return (r2f64_t){ v2f64_sub(rect.min, value), v2f64_add(rect.max, value) }; }
fn_inline r2f64_t r2f64_shrink(r2f64_t rect, v2f64_t value) { return (r2f64_t){ v2f64_add(rect.min, value), v2f64_sub(rect.max, value) }; }
fn_inline r2f64_t r2f64_shrinks(r2f64_t rect, f64 value) { return (r2f64_t){ v2f64_adds(rect.min, value), v2f64_subs(rect.max, value) }; }
fn_inline v2f64_t r2f64_size(r2f64_t r) { return (v2f64_t){r.max.x - r.min.x, r.max.y - r.min.y}; }
fn_inline v2f64_t r2f64_get_mid(r2f64_t r) { return v2f64_add(r.min, v2f64_divs(r2f64_size(r), 2)); }
fn_inline b32 r2f64_contains(r2f64_t rec, v2f64_t point) { return (point.x >= rec.min.x) && (point.x < rec.max.x) && (point.y >= rec.min.y) && (point.y < rec.max.y); }
fn_inline r2f64_t r2f64_intersect(r2f64_t a, r2f64_t b) { return (r2f64_t){ .min.x = MAX(a.min.x, b.min.x), .min.y = MAX(a.min.y, b.min.y), .max.x = MIN(a.max.x, b.max.x), .max.y = MIN(a.max.y, b.max.y) }; }
fn_inline r2f64_t r2f64_union(r2f64_t a, r2f64_t b) { return (r2f64_t){ .min.x = MIN(a.min.x, b.min.x), .min.y = MIN(a.min.y, b.min.y), .max.x = MAX(a.max.x, b.max.x), .max.y = MAX(a.max.y, b.max.y) }; }
fn_inline f64 r1f64_size(r1f64_t a) { return a.max - a.min; }
fn_inline r1f64_t r1f64(f64 min, f64 max) { return (r1f64_t){min,max}; }
fn_inline r1f64_t r1f64_auto(f64 a, f64 b) { return (r1f64_t){MIN(a,b),MAX(a,b)}; }
fn_inline r1f64_t r1f64s(f64 a) { return (r1f64_t){a,a}; }
fn_inline r1f64_t r1f64_clamp(r1f64_t a, f64 min, f64 max) { return (r1f64_t){ .min = CLAMP(a.min, min, max), .max = CLAMP(a.max, min, max) }; }
fn_inline b32 r1f64_contains(r1f64_t rec, f64 point) { return (point >= rec.min) && (point < rec.max) && (point >= rec.min) && (point < rec.max); }
fn_inline b32 r1f64_are_equal(r1f64_t a, r1f64_t b) { return a.min == b.min && a.max == b.max; }
gb_read_only r1f64_t r1f64_null;
fn b32 r1f64_overlap(r1f64_t a, r1f64_t b) {
b32 r1 = (a.max >= b.min && a.max <= b.max) || (a.min >= b.min && a.min <= b.max);
b32 r2 = (b.max >= a.min && b.max <= a.max) || (b.min >= a.min && b.min <= a.max);
return r1 || r2;
}
fn v2f64_t v2f64_clamps(v2f64_t v, f64 min, f64 max) {
v2f64_t result = { CLAMP(v.x, min, max), CLAMP(v.y, min, max) };
return result;
}
fn v2f64_t v2f64_clamp(v2f64_t v, v2f64_t min, v2f64_t max) {
v2f64_t result = { CLAMP(v.x, min.x, max.x), CLAMP(v.y, min.y, max.y) };
return result;
}
fn r2f64_t r2f64_fix(r2f64_t n) {
r2f64_t result = {
.min = {MIN(n.min.x, n.max.x), MIN(n.min.y, n.max.y)},
.max = {MAX(n.min.x, n.max.x), MAX(n.min.y, n.max.y)},
};
return result;
}
fn r2i32_t r2i32_cut_left(r2i32_t *r, i32 value) {
i32 minx = r->min.x;
r->min.x = MIN(r->min.x + value, r->max.x);
r2i32_t result = { .min = {.x = minx, .y = r->min.y}, .max = {.x = r->min.x, .y =r->max.y} };
return result;
}
fn r2i32_t r2i32_cut_right(r2i32_t *r, i32 value) {
i32 maxx = r->max.x;
r->max.x = MAX(r->min.x, r->max.x - value);
r2i32_t result = { .min = {.x = r->max.x, .y = r->min.y}, .max = {.x = maxx, .y = r->max.y} };
return result;
}
fn r2i32_t r2i32_cut_top(r2i32_t *r, i32 value) { /* Y is down */
i32 miny = r->min.y;
r->min.y = MIN(r->max.y, r->min.y + value);
r2i32_t result = { .min = {.x = r->min.x, .y = miny}, .max = {.x = r->max.x, .y = r->min.y} };
return result;
}
fn r2i32_t r2i32_cut_bottom(r2i32_t *r, i32 value) { /* Y is down */
i32 maxy = r->max.y;
r->max.y = MAX(r->min.y, r->max.y - value);
r2i32_t result = { .min = {.x = r->min.x, .y = r->max.y}, .max = {.x = r->max.x, .y = maxy} };
return result;
}
fn r2i32_t r2i32_cut_left_no_squash(r2i32_t *r, i32 value) {
i32 minx = r->min.x;
r->min.x = r->min.x + value;
r2i32_t result = { .min = {.x = minx, .y = r->min.y}, .max = {.x = r->min.x, .y =r->max.y} };
return result;
}
fn r2i32_t r2i32_cut_right_no_squash(r2i32_t *r, i32 value) {
i32 maxx = r->max.x;
r->max.x = r->max.x - value;
r2i32_t result = { .min = {.x = r->max.x, .y = r->min.y}, .max = {.x = maxx, .y = r->max.y} };
return result;
}
fn r2i32_t r2i32_cut_top_no_squash(r2i32_t *r, i32 value) { /* Y is down */
i32 miny = r->min.y;
r->min.y = r->min.y + value;
r2i32_t result = { .min = {.x = r->min.x, .y = miny}, .max = {.x = r->max.x, .y = r->min.y} };
return result;
}
fn r2i32_t r2i32_cut_bottom_no_squash(r2i32_t *r, i32 value) { /* Y is down */
i32 maxy = r->max.y;
r->max.y = r->max.y - value;
r2i32_t result = { .min = {.x = r->min.x, .y = r->max.y}, .max = {.x = r->max.x, .y = maxy} };
return result;
}
fn r2i32_t r2i32_add_left(r2i32_t *r, i32 value) {
r2i32_t result = { .min = {r->min.x - value, r->min.y}, .max = {r->min.x, r->max.y} };
r->min.x -= value;
return result;
}
fn r2i32_t r2i32_add_right(r2i32_t *r, i32 value) {
r2i32_t result = { .min = {r->max.x, r->min.y}, .max = {r->max.x + value, r->max.y} };
r->max.x += value;
return result;
}
fn r2i32_t r2i32_add_top(r2i32_t *r, i32 value) {
r2i32_t result = { .min = {r->min.x, r->min.y - value}, .max = {r->max.x, r->min.y} };
r->min.y -= value;
return result;
}
fn r2i32_t r2i32_add_bottom(r2i32_t *r, i32 value) {
r2i32_t result = { .min = {r->min.x, r->max.y}, .max = {r->max.x, r->max.y + value} };
r->max.y += value;
return result;
}
// get past left
fn r2i32_t r2i32_getp_left(const r2i32_t *rect, i32 value) {
r2i32_t result = r2i32(rect->min.x - value, rect->min.y, rect->min.x, rect->max.y);
return result;
}
fn r2i32_t r2i32_getp_right(const r2i32_t *rect, i32 value) {
r2i32_t result = r2i32(rect->max.x, rect->min.y, rect->max.x + value, rect->max.y);
return result;
}
fn r2i32_t r2i32_getp_bottom(const r2i32_t *rect, i32 value) {
r2i32_t result = r2i32(rect->min.x, rect->max.y, rect->max.x, rect->max.y + value);
return result;
}
fn r2i32_t r2i32_getp_top(const r2i32_t *rect, i32 value) {
r2i32_t result = r2i32(rect->min.x, rect->min.y - value, rect->max.x, rect->min.y);
return result;
}
fn r2i32_t r2i32_get_left(const r2i32_t *r, i32 value) {
i32 minx = r->min.x;
r2i32_t result = (r2i32_t){ .min = {.x = minx, .y = r->min.y}, .max = {.x = MIN(r->min.x + value, r->max.x), .y =r->max.y} };
return result;
}
fn r2i32_t r2i32_get_right(const r2i32_t *r, i32 value) {
i32 maxx = r->max.x;
r2i32_t result = (r2i32_t){ .min = {.x = MAX(r->min.x, r->max.x - value), .y = r->min.y}, .max = {.x = maxx, .y = r->max.y} };
return result;
}
fn r2i32_t r2i32_get_top(const r2i32_t *r, i32 value) { /* Y is down */
i32 miny = r->min.y;
r2i32_t result = (r2i32_t){ .min = {.x = r->min.x, .y = miny}, .max = {.x = r->max.x, .y = MIN(r->max.y, r->min.y + value)} };
return result;
}
fn r2i32_t r2i32_get_bottom(const r2i32_t *r, i32 value) { /* Y is down */
i32 maxy = r->max.y;
r2i32_t result = (r2i32_t){ .min = {.x = r->min.x, .y = MAX(r->min.y, r->max.y - value)}, .max = {.x = r->max.x, .y = maxy} };
return result;
}
fn_inline r2i32_t r2i32_expand(r2i32_t rect, v2i32_t value) { return (r2i32_t){ v2i32_sub(rect.min, value), v2i32_add(rect.max, value) }; }
fn_inline r2i32_t r2i32_shrink(r2i32_t rect, v2i32_t value) { return (r2i32_t){ v2i32_add(rect.min, value), v2i32_sub(rect.max, value) }; }
fn_inline r2i32_t r2i32_shrinks(r2i32_t rect, i32 value) { return (r2i32_t){ v2i32_adds(rect.min, value), v2i32_subs(rect.max, value) }; }
fn_inline v2i32_t r2i32_size(r2i32_t r) { return (v2i32_t){r.max.x - r.min.x, r.max.y - r.min.y}; }
fn_inline v2i32_t r2i32_get_mid(r2i32_t r) { return v2i32_add(r.min, v2i32_divs(r2i32_size(r), 2)); }
fn_inline b32 r2i32_contains(r2i32_t rec, v2i32_t point) { return (point.x >= rec.min.x) && (point.x < rec.max.x) && (point.y >= rec.min.y) && (point.y < rec.max.y); }
fn_inline r2i32_t r2i32_intersect(r2i32_t a, r2i32_t b) { return (r2i32_t){ .min.x = MAX(a.min.x, b.min.x), .min.y = MAX(a.min.y, b.min.y), .max.x = MIN(a.max.x, b.max.x), .max.y = MIN(a.max.y, b.max.y) }; }
fn_inline r2i32_t r2i32_union(r2i32_t a, r2i32_t b) { return (r2i32_t){ .min.x = MIN(a.min.x, b.min.x), .min.y = MIN(a.min.y, b.min.y), .max.x = MAX(a.max.x, b.max.x), .max.y = MAX(a.max.y, b.max.y) }; }
fn_inline i32 r1i32_size(r1i32_t a) { return a.max - a.min; }
fn_inline r1i32_t r1i32(i32 min, i32 max) { return (r1i32_t){min,max}; }
fn_inline r1i32_t r1i32_auto(i32 a, i32 b) { return (r1i32_t){MIN(a,b),MAX(a,b)}; }
fn_inline r1i32_t r1i32s(i32 a) { return (r1i32_t){a,a}; }
fn_inline r1i32_t r1i32_clamp(r1i32_t a, i32 min, i32 max) { return (r1i32_t){ .min = CLAMP(a.min, min, max), .max = CLAMP(a.max, min, max) }; }
fn_inline b32 r1i32_contains(r1i32_t rec, i32 point) { return (point >= rec.min) && (point < rec.max) && (point >= rec.min) && (point < rec.max); }
fn_inline b32 r1i32_are_equal(r1i32_t a, r1i32_t b) { return a.min == b.min && a.max == b.max; }
gb_read_only r1i32_t r1i32_null;
fn b32 r1i32_overlap(r1i32_t a, r1i32_t b) {
b32 r1 = (a.max >= b.min && a.max <= b.max) || (a.min >= b.min && a.min <= b.max);
b32 r2 = (b.max >= a.min && b.max <= a.max) || (b.min >= a.min && b.min <= a.max);
return r1 || r2;
}
fn v2i32_t v2i32_clamps(v2i32_t v, i32 min, i32 max) {
v2i32_t result = { CLAMP(v.x, min, max), CLAMP(v.y, min, max) };
return result;
}
fn v2i32_t v2i32_clamp(v2i32_t v, v2i32_t min, v2i32_t max) {
v2i32_t result = { CLAMP(v.x, min.x, max.x), CLAMP(v.y, min.y, max.y) };
return result;
}
fn r2i32_t r2i32_fix(r2i32_t n) {
r2i32_t result = {
.min = {MIN(n.min.x, n.max.x), MIN(n.min.y, n.max.y)},
.max = {MAX(n.min.x, n.max.x), MAX(n.min.y, n.max.y)},
};
return result;
}
fn r2i64_t r2i64_cut_left(r2i64_t *r, i64 value) {
i64 minx = r->min.x;
r->min.x = MIN(r->min.x + value, r->max.x);
r2i64_t result = { .min = {.x = minx, .y = r->min.y}, .max = {.x = r->min.x, .y =r->max.y} };
return result;
}
fn r2i64_t r2i64_cut_right(r2i64_t *r, i64 value) {
i64 maxx = r->max.x;
r->max.x = MAX(r->min.x, r->max.x - value);
r2i64_t result = { .min = {.x = r->max.x, .y = r->min.y}, .max = {.x = maxx, .y = r->max.y} };
return result;
}
fn r2i64_t r2i64_cut_top(r2i64_t *r, i64 value) { /* Y is down */
i64 miny = r->min.y;
r->min.y = MIN(r->max.y, r->min.y + value);
r2i64_t result = { .min = {.x = r->min.x, .y = miny}, .max = {.x = r->max.x, .y = r->min.y} };
return result;
}
fn r2i64_t r2i64_cut_bottom(r2i64_t *r, i64 value) { /* Y is down */
i64 maxy = r->max.y;
r->max.y = MAX(r->min.y, r->max.y - value);
r2i64_t result = { .min = {.x = r->min.x, .y = r->max.y}, .max = {.x = r->max.x, .y = maxy} };
return result;
}
fn r2i64_t r2i64_cut_left_no_squash(r2i64_t *r, i64 value) {
i64 minx = r->min.x;
r->min.x = r->min.x + value;
r2i64_t result = { .min = {.x = minx, .y = r->min.y}, .max = {.x = r->min.x, .y =r->max.y} };
return result;
}
fn r2i64_t r2i64_cut_right_no_squash(r2i64_t *r, i64 value) {
i64 maxx = r->max.x;
r->max.x = r->max.x - value;
r2i64_t result = { .min = {.x = r->max.x, .y = r->min.y}, .max = {.x = maxx, .y = r->max.y} };
return result;
}
fn r2i64_t r2i64_cut_top_no_squash(r2i64_t *r, i64 value) { /* Y is down */
i64 miny = r->min.y;
r->min.y = r->min.y + value;
r2i64_t result = { .min = {.x = r->min.x, .y = miny}, .max = {.x = r->max.x, .y = r->min.y} };
return result;
}
fn r2i64_t r2i64_cut_bottom_no_squash(r2i64_t *r, i64 value) { /* Y is down */
i64 maxy = r->max.y;
r->max.y = r->max.y - value;
r2i64_t result = { .min = {.x = r->min.x, .y = r->max.y}, .max = {.x = r->max.x, .y = maxy} };
return result;
}
fn r2i64_t r2i64_add_left(r2i64_t *r, i64 value) {
r2i64_t result = { .min = {r->min.x - value, r->min.y}, .max = {r->min.x, r->max.y} };
r->min.x -= value;
return result;
}
fn r2i64_t r2i64_add_right(r2i64_t *r, i64 value) {
r2i64_t result = { .min = {r->max.x, r->min.y}, .max = {r->max.x + value, r->max.y} };
r->max.x += value;
return result;
}
fn r2i64_t r2i64_add_top(r2i64_t *r, i64 value) {
r2i64_t result = { .min = {r->min.x, r->min.y - value}, .max = {r->max.x, r->min.y} };
r->min.y -= value;
return result;
}
fn r2i64_t r2i64_add_bottom(r2i64_t *r, i64 value) {
r2i64_t result = { .min = {r->min.x, r->max.y}, .max = {r->max.x, r->max.y + value} };
r->max.y += value;
return result;
}
// get past left
fn r2i64_t r2i64_getp_left(const r2i64_t *rect, i64 value) {
r2i64_t result = r2i64(rect->min.x - value, rect->min.y, rect->min.x, rect->max.y);
return result;
}
fn r2i64_t r2i64_getp_right(const r2i64_t *rect, i64 value) {
r2i64_t result = r2i64(rect->max.x, rect->min.y, rect->max.x + value, rect->max.y);
return result;
}
fn r2i64_t r2i64_getp_bottom(const r2i64_t *rect, i64 value) {
r2i64_t result = r2i64(rect->min.x, rect->max.y, rect->max.x, rect->max.y + value);
return result;
}
fn r2i64_t r2i64_getp_top(const r2i64_t *rect, i64 value) {
r2i64_t result = r2i64(rect->min.x, rect->min.y - value, rect->max.x, rect->min.y);
return result;
}
fn r2i64_t r2i64_get_left(const r2i64_t *r, i64 value) {
i64 minx = r->min.x;
r2i64_t result = (r2i64_t){ .min = {.x = minx, .y = r->min.y}, .max = {.x = MIN(r->min.x + value, r->max.x), .y =r->max.y} };
return result;
}
fn r2i64_t r2i64_get_right(const r2i64_t *r, i64 value) {
i64 maxx = r->max.x;
r2i64_t result = (r2i64_t){ .min = {.x = MAX(r->min.x, r->max.x - value), .y = r->min.y}, .max = {.x = maxx, .y = r->max.y} };
return result;
}
fn r2i64_t r2i64_get_top(const r2i64_t *r, i64 value) { /* Y is down */
i64 miny = r->min.y;
r2i64_t result = (r2i64_t){ .min = {.x = r->min.x, .y = miny}, .max = {.x = r->max.x, .y = MIN(r->max.y, r->min.y + value)} };
return result;
}
fn r2i64_t r2i64_get_bottom(const r2i64_t *r, i64 value) { /* Y is down */
i64 maxy = r->max.y;
r2i64_t result = (r2i64_t){ .min = {.x = r->min.x, .y = MAX(r->min.y, r->max.y - value)}, .max = {.x = r->max.x, .y = maxy} };
return result;
}
fn_inline r2i64_t r2i64_expand(r2i64_t rect, v2i64_t value) { return (r2i64_t){ v2i64_sub(rect.min, value), v2i64_add(rect.max, value) }; }
fn_inline r2i64_t r2i64_shrink(r2i64_t rect, v2i64_t value) { return (r2i64_t){ v2i64_add(rect.min, value), v2i64_sub(rect.max, value) }; }
fn_inline r2i64_t r2i64_shrinks(r2i64_t rect, i64 value) { return (r2i64_t){ v2i64_adds(rect.min, value), v2i64_subs(rect.max, value) }; }
fn_inline v2i64_t r2i64_size(r2i64_t r) { return (v2i64_t){r.max.x - r.min.x, r.max.y - r.min.y}; }
fn_inline v2i64_t r2i64_get_mid(r2i64_t r) { return v2i64_add(r.min, v2i64_divs(r2i64_size(r), 2)); }
fn_inline b32 r2i64_contains(r2i64_t rec, v2i64_t point) { return (point.x >= rec.min.x) && (point.x < rec.max.x) && (point.y >= rec.min.y) && (point.y < rec.max.y); }
fn_inline r2i64_t r2i64_intersect(r2i64_t a, r2i64_t b) { return (r2i64_t){ .min.x = MAX(a.min.x, b.min.x), .min.y = MAX(a.min.y, b.min.y), .max.x = MIN(a.max.x, b.max.x), .max.y = MIN(a.max.y, b.max.y) }; }
fn_inline r2i64_t r2i64_union(r2i64_t a, r2i64_t b) { return (r2i64_t){ .min.x = MIN(a.min.x, b.min.x), .min.y = MIN(a.min.y, b.min.y), .max.x = MAX(a.max.x, b.max.x), .max.y = MAX(a.max.y, b.max.y) }; }
fn_inline i64 r1i64_size(r1i64_t a) { return a.max - a.min; }
fn_inline r1i64_t r1i64(i64 min, i64 max) { return (r1i64_t){min,max}; }
fn_inline r1i64_t r1i64_auto(i64 a, i64 b) { return (r1i64_t){MIN(a,b),MAX(a,b)}; }
fn_inline r1i64_t r1i64s(i64 a) { return (r1i64_t){a,a}; }
fn_inline r1i64_t r1i64_clamp(r1i64_t a, i64 min, i64 max) { return (r1i64_t){ .min = CLAMP(a.min, min, max), .max = CLAMP(a.max, min, max) }; }
fn_inline b32 r1i64_contains(r1i64_t rec, i64 point) { return (point >= rec.min) && (point < rec.max) && (point >= rec.min) && (point < rec.max); }
fn_inline b32 r1i64_are_equal(r1i64_t a, r1i64_t b) { return a.min == b.min && a.max == b.max; }
gb_read_only r1i64_t r1i64_null;
fn b32 r1i64_overlap(r1i64_t a, r1i64_t b) {
b32 r1 = (a.max >= b.min && a.max <= b.max) || (a.min >= b.min && a.min <= b.max);
b32 r2 = (b.max >= a.min && b.max <= a.max) || (b.min >= a.min && b.min <= a.max);
return r1 || r2;
}
fn v2i64_t v2i64_clamps(v2i64_t v, i64 min, i64 max) {
v2i64_t result = { CLAMP(v.x, min, max), CLAMP(v.y, min, max) };
return result;
}
fn v2i64_t v2i64_clamp(v2i64_t v, v2i64_t min, v2i64_t max) {
v2i64_t result = { CLAMP(v.x, min.x, max.x), CLAMP(v.y, min.y, max.y) };
return result;
}
fn r2i64_t r2i64_fix(r2i64_t n) {
r2i64_t result = {
.min = {MIN(n.min.x, n.max.x), MIN(n.min.y, n.max.y)},
.max = {MAX(n.min.x, n.max.x), MAX(n.min.y, n.max.y)},
};
return result;
}
fn_inline v2f64_t v2f32_to_v2f64(v2f32_t v) { return (v2f64_t){ (f64)v.x, (f64)v.y }; }
fn_inline v3f64_t v3f32_to_v3f64(v3f32_t v) { return (v3f64_t){ (f64)v.x, (f64)v.y, (f64)v.z }; }
fn_inline v4f64_t v4f32_to_v4f64(v4f32_t v) { return (v4f64_t){ (f64)v.x, (f64)v.y, (f64)v.z, (f64)v.w }; }
fn_inline r2f64_t r2f32_to_r2f64(r2f32_t v) { return (r2f64_t){ (f64)v.x0, (f64)v.y0, (f64)v.x1, (f64)v.y1 }; }
fn_inline r3f64_t r3f32_to_r3f64(r3f32_t v) { return (r3f64_t){ (f64)v.x0, (f64)v.y0, (f64)v.z0, (f64)v.x1, (f64)v.y1, (f64)v.z1 }; }
fn_inline v2i32_t v2f32_to_v2i32(v2f32_t v) { return (v2i32_t){ (i32)v.x, (i32)v.y }; }
fn_inline v3i32_t v3f32_to_v3i32(v3f32_t v) { return (v3i32_t){ (i32)v.x, (i32)v.y, (i32)v.z }; }
fn_inline v4i32_t v4f32_to_v4i32(v4f32_t v) { return (v4i32_t){ (i32)v.x, (i32)v.y, (i32)v.z, (i32)v.w }; }
fn_inline r2i32_t r2f32_to_r2i32(r2f32_t v) { return (r2i32_t){ (i32)v.x0, (i32)v.y0, (i32)v.x1, (i32)v.y1 }; }
fn_inline r3i32_t r3f32_to_r3i32(r3f32_t v) { return (r3i32_t){ (i32)v.x0, (i32)v.y0, (i32)v.z0, (i32)v.x1, (i32)v.y1, (i32)v.z1 }; }
fn_inline v2i64_t v2f32_to_v2i64(v2f32_t v) { return (v2i64_t){ (i64)v.x, (i64)v.y }; }
fn_inline v3i64_t v3f32_to_v3i64(v3f32_t v) { return (v3i64_t){ (i64)v.x, (i64)v.y, (i64)v.z }; }
fn_inline v4i64_t v4f32_to_v4i64(v4f32_t v) { return (v4i64_t){ (i64)v.x, (i64)v.y, (i64)v.z, (i64)v.w }; }
fn_inline r2i64_t r2f32_to_r2i64(r2f32_t v) { return (r2i64_t){ (i64)v.x0, (i64)v.y0, (i64)v.x1, (i64)v.y1 }; }
fn_inline r3i64_t r3f32_to_r3i64(r3f32_t v) { return (r3i64_t){ (i64)v.x0, (i64)v.y0, (i64)v.z0, (i64)v.x1, (i64)v.y1, (i64)v.z1 }; }
fn_inline v2f32_t v2f64_to_v2f32(v2f64_t v) { return (v2f32_t){ (f32)v.x, (f32)v.y }; }
fn_inline v3f32_t v3f64_to_v3f32(v3f64_t v) { return (v3f32_t){ (f32)v.x, (f32)v.y, (f32)v.z }; }
fn_inline v4f32_t v4f64_to_v4f32(v4f64_t v) { return (v4f32_t){ (f32)v.x, (f32)v.y, (f32)v.z, (f32)v.w }; }
fn_inline r2f32_t r2f64_to_r2f32(r2f64_t v) { return (r2f32_t){ (f32)v.x0, (f32)v.y0, (f32)v.x1, (f32)v.y1 }; }
fn_inline r3f32_t r3f64_to_r3f32(r3f64_t v) { return (r3f32_t){ (f32)v.x0, (f32)v.y0, (f32)v.z0, (f32)v.x1, (f32)v.y1, (f32)v.z1 }; }
fn_inline v2i32_t v2f64_to_v2i32(v2f64_t v) { return (v2i32_t){ (i32)v.x, (i32)v.y }; }
fn_inline v3i32_t v3f64_to_v3i32(v3f64_t v) { return (v3i32_t){ (i32)v.x, (i32)v.y, (i32)v.z }; }
fn_inline v4i32_t v4f64_to_v4i32(v4f64_t v) { return (v4i32_t){ (i32)v.x, (i32)v.y, (i32)v.z, (i32)v.w }; }
fn_inline r2i32_t r2f64_to_r2i32(r2f64_t v) { return (r2i32_t){ (i32)v.x0, (i32)v.y0, (i32)v.x1, (i32)v.y1 }; }
fn_inline r3i32_t r3f64_to_r3i32(r3f64_t v) { return (r3i32_t){ (i32)v.x0, (i32)v.y0, (i32)v.z0, (i32)v.x1, (i32)v.y1, (i32)v.z1 }; }
fn_inline v2i64_t v2f64_to_v2i64(v2f64_t v) { return (v2i64_t){ (i64)v.x, (i64)v.y }; }
fn_inline v3i64_t v3f64_to_v3i64(v3f64_t v) { return (v3i64_t){ (i64)v.x, (i64)v.y, (i64)v.z }; }
fn_inline v4i64_t v4f64_to_v4i64(v4f64_t v) { return (v4i64_t){ (i64)v.x, (i64)v.y, (i64)v.z, (i64)v.w }; }
fn_inline r2i64_t r2f64_to_r2i64(r2f64_t v) { return (r2i64_t){ (i64)v.x0, (i64)v.y0, (i64)v.x1, (i64)v.y1 }; }
fn_inline r3i64_t r3f64_to_r3i64(r3f64_t v) { return (r3i64_t){ (i64)v.x0, (i64)v.y0, (i64)v.z0, (i64)v.x1, (i64)v.y1, (i64)v.z1 }; }
fn_inline v2f32_t v2i32_to_v2f32(v2i32_t v) { return (v2f32_t){ (f32)v.x, (f32)v.y }; }
fn_inline v3f32_t v3i32_to_v3f32(v3i32_t v) { return (v3f32_t){ (f32)v.x, (f32)v.y, (f32)v.z }; }
fn_inline v4f32_t v4i32_to_v4f32(v4i32_t v) { return (v4f32_t){ (f32)v.x, (f32)v.y, (f32)v.z, (f32)v.w }; }
fn_inline r2f32_t r2i32_to_r2f32(r2i32_t v) { return (r2f32_t){ (f32)v.x0, (f32)v.y0, (f32)v.x1, (f32)v.y1 }; }
fn_inline r3f32_t r3i32_to_r3f32(r3i32_t v) { return (r3f32_t){ (f32)v.x0, (f32)v.y0, (f32)v.z0, (f32)v.x1, (f32)v.y1, (f32)v.z1 }; }
fn_inline v2f64_t v2i32_to_v2f64(v2i32_t v) { return (v2f64_t){ (f64)v.x, (f64)v.y }; }
fn_inline v3f64_t v3i32_to_v3f64(v3i32_t v) { return (v3f64_t){ (f64)v.x, (f64)v.y, (f64)v.z }; }
fn_inline v4f64_t v4i32_to_v4f64(v4i32_t v) { return (v4f64_t){ (f64)v.x, (f64)v.y, (f64)v.z, (f64)v.w }; }
fn_inline r2f64_t r2i32_to_r2f64(r2i32_t v) { return (r2f64_t){ (f64)v.x0, (f64)v.y0, (f64)v.x1, (f64)v.y1 }; }
fn_inline r3f64_t r3i32_to_r3f64(r3i32_t v) { return (r3f64_t){ (f64)v.x0, (f64)v.y0, (f64)v.z0, (f64)v.x1, (f64)v.y1, (f64)v.z1 }; }
fn_inline v2i64_t v2i32_to_v2i64(v2i32_t v) { return (v2i64_t){ (i64)v.x, (i64)v.y }; }
fn_inline v3i64_t v3i32_to_v3i64(v3i32_t v) { return (v3i64_t){ (i64)v.x, (i64)v.y, (i64)v.z }; }
fn_inline v4i64_t v4i32_to_v4i64(v4i32_t v) { return (v4i64_t){ (i64)v.x, (i64)v.y, (i64)v.z, (i64)v.w }; }
fn_inline r2i64_t r2i32_to_r2i64(r2i32_t v) { return (r2i64_t){ (i64)v.x0, (i64)v.y0, (i64)v.x1, (i64)v.y1 }; }
fn_inline r3i64_t r3i32_to_r3i64(r3i32_t v) { return (r3i64_t){ (i64)v.x0, (i64)v.y0, (i64)v.z0, (i64)v.x1, (i64)v.y1, (i64)v.z1 }; }
fn_inline v2f32_t v2i64_to_v2f32(v2i64_t v) { return (v2f32_t){ (f32)v.x, (f32)v.y }; }
fn_inline v3f32_t v3i64_to_v3f32(v3i64_t v) { return (v3f32_t){ (f32)v.x, (f32)v.y, (f32)v.z }; }
fn_inline v4f32_t v4i64_to_v4f32(v4i64_t v) { return (v4f32_t){ (f32)v.x, (f32)v.y, (f32)v.z, (f32)v.w }; }
fn_inline r2f32_t r2i64_to_r2f32(r2i64_t v) { return (r2f32_t){ (f32)v.x0, (f32)v.y0, (f32)v.x1, (f32)v.y1 }; }
fn_inline r3f32_t r3i64_to_r3f32(r3i64_t v) { return (r3f32_t){ (f32)v.x0, (f32)v.y0, (f32)v.z0, (f32)v.x1, (f32)v.y1, (f32)v.z1 }; }
fn_inline v2f64_t v2i64_to_v2f64(v2i64_t v) { return (v2f64_t){ (f64)v.x, (f64)v.y }; }
fn_inline v3f64_t v3i64_to_v3f64(v3i64_t v) { return (v3f64_t){ (f64)v.x, (f64)v.y, (f64)v.z }; }
fn_inline v4f64_t v4i64_to_v4f64(v4i64_t v) { return (v4f64_t){ (f64)v.x, (f64)v.y, (f64)v.z, (f64)v.w }; }
fn_inline r2f64_t r2i64_to_r2f64(r2i64_t v) { return (r2f64_t){ (f64)v.x0, (f64)v.y0, (f64)v.x1, (f64)v.y1 }; }
fn_inline r3f64_t r3i64_to_r3f64(r3i64_t v) { return (r3f64_t){ (f64)v.x0, (f64)v.y0, (f64)v.z0, (f64)v.x1, (f64)v.y1, (f64)v.z1 }; }
fn_inline v2i32_t v2i64_to_v2i32(v2i64_t v) { return (v2i32_t){ (i32)v.x, (i32)v.y }; }
fn_inline v3i32_t v3i64_to_v3i32(v3i64_t v) { return (v3i32_t){ (i32)v.x, (i32)v.y, (i32)v.z }; }
fn_inline v4i32_t v4i64_to_v4i32(v4i64_t v) { return (v4i32_t){ (i32)v.x, (i32)v.y, (i32)v.z, (i32)v.w }; }
fn_inline r2i32_t r2i64_to_r2i32(r2i64_t v) { return (r2i32_t){ (i32)v.x0, (i32)v.y0, (i32)v.x1, (i32)v.y1 }; }
fn_inline r3i32_t r3i64_to_r3i32(r3i64_t v) { return (r3i32_t){ (i32)v.x0, (i32)v.y0, (i32)v.z0, (i32)v.x1, (i32)v.y1, (i32)v.z1 }; }
fn_inline r2f32_t r2f32_add_v2f32(r2f32_t a, v2f32_t b) { return (r2f32_t){ v2f32_add(a.min, b), v2f32_add(a.max, b) }; }
fn_inline r2f32_t r2f32_sub_v2f32(r2f32_t a, v2f32_t b) { return (r2f32_t){ v2f32_sub(a.min, b), v2f32_sub(a.max, b) }; }
fn_inline r2f32_t r2f32_mul_v2f32(r2f32_t a, v2f32_t b) { return (r2f32_t){ v2f32_mul(a.min, b), v2f32_mul(a.max, b) }; }
fn_inline r2f32_t r2f32_div_v2f32(r2f32_t a, v2f32_t b) { return (r2f32_t){ v2f32_div(a.min, b), v2f32_div(a.max, b) }; }
fn_inline r2f64_t r2f64_add_v2f64(r2f64_t a, v2f64_t b) { return (r2f64_t){ v2f64_add(a.min, b), v2f64_add(a.max, b) }; }
fn_inline r2f64_t r2f64_sub_v2f64(r2f64_t a, v2f64_t b) { return (r2f64_t){ v2f64_sub(a.min, b), v2f64_sub(a.max, b) }; }
fn_inline r2f64_t r2f64_mul_v2f64(r2f64_t a, v2f64_t b) { return (r2f64_t){ v2f64_mul(a.min, b), v2f64_mul(a.max, b) }; }
fn_inline r2f64_t r2f64_div_v2f64(r2f64_t a, v2f64_t b) { return (r2f64_t){ v2f64_div(a.min, b), v2f64_div(a.max, b) }; }
fn_inline r2i32_t r2i32_add_v2i32(r2i32_t a, v2i32_t b) { return (r2i32_t){ v2i32_add(a.min, b), v2i32_add(a.max, b) }; }
fn_inline r2i32_t r2i32_sub_v2i32(r2i32_t a, v2i32_t b) { return (r2i32_t){ v2i32_sub(a.min, b), v2i32_sub(a.max, b) }; }
fn_inline r2i32_t r2i32_mul_v2i32(r2i32_t a, v2i32_t b) { return (r2i32_t){ v2i32_mul(a.min, b), v2i32_mul(a.max, b) }; }
fn_inline r2i32_t r2i32_div_v2i32(r2i32_t a, v2i32_t b) { return (r2i32_t){ v2i32_div(a.min, b), v2i32_div(a.max, b) }; }
fn_inline r2i64_t r2i64_add_v2i64(r2i64_t a, v2i64_t b) { return (r2i64_t){ v2i64_add(a.min, b), v2i64_add(a.max, b) }; }
fn_inline r2i64_t r2i64_sub_v2i64(r2i64_t a, v2i64_t b) { return (r2i64_t){ v2i64_sub(a.min, b), v2i64_sub(a.max, b) }; }
fn_inline r2i64_t r2i64_mul_v2i64(r2i64_t a, v2i64_t b) { return (r2i64_t){ v2i64_mul(a.min, b), v2i64_mul(a.max, b) }; }
fn_inline r2i64_t r2i64_div_v2i64(r2i64_t a, v2i64_t b) { return (r2i64_t){ v2i64_div(a.min, b), v2i64_div(a.max, b) }; }
fn f32 f32_safe_ratio(f32 a, f32 b, f32 if0) {
f32 result = if0;
if (b != 0.0) {
result = a / b;
}
return result;
}
fn_inline f32 f32_safe_ratio0(f32 a, f32 b) { return f32_safe_ratio(a, b, 0); }
fn_inline f32 f32_safe_ratio1(f32 a, f32 b) { return f32_safe_ratio(a, b, 0); }
fn f64 f64_safe_ratio(f64 a, f64 b, f64 if0) {
f64 result = if0;
if (b != 0.0) {
result = a / b;
}
return result;
}
fn_inline f64 f64_safe_ratio0(f64 a, f64 b) { return f64_safe_ratio(a, b, 0); }
fn_inline f64 f64_safe_ratio1(f64 a, f64 b) { return f64_safe_ratio(a, b, 0); }
-215
View File
@@ -1,215 +0,0 @@
#pragma once
#include "core_basic.h"
typedef union v2f32_t v2f32_t;
union v2f32_t {
struct { f32 x, y; };
f32 e[2];
};
typedef union v3f32_t v3f32_t;
union v3f32_t {
struct { f32 x, y, z; };
struct { v2f32_t xy; };
struct { f32 _x0; v2f32_t zw; };
struct { f32 r, g, b; };
struct { f32 h, s, l; };
f32 e[3];
};
typedef union v4f32_t v4f32_t;
union v4f32_t {
struct { f32 x, y, z, w; };
struct { v2f32_t xy; v2f32_t zw; };
struct { v3f32_t xyz; };
struct { f32 _x0; f32 yzw; };
struct { f32 r, g, b, a; };
struct { f32 h, s, l, _a; };
f32 e[4];
};
typedef union r1f32_t r1f32_t;
union r1f32_t {
struct { f32 min, max; };
struct { f32 x0, x1; };
f32 e[2];
};
typedef union r2f32_t r2f32_t;
union r2f32_t {
struct { v2f32_t min, max; };
struct { f32 x0, y0, x1, y1; };
v4f32_t e4;
f32 e[4];
};
typedef union r3f32_t r3f32_t;
union r3f32_t {
struct { v3f32_t min, max; };
struct { f32 x0, y0, z0, x1, y1, z1; };
f32 e[6];
};
typedef union v2f64_t v2f64_t;
union v2f64_t {
struct { f64 x, y; };
f64 e[2];
};
typedef union v3f64_t v3f64_t;
union v3f64_t {
struct { f64 x, y, z; };
struct { v2f64_t xy; };
struct { f64 _x0; v2f64_t zw; };
struct { f64 r, g, b; };
struct { f64 h, s, l; };
f64 e[3];
};
typedef union v4f64_t v4f64_t;
union v4f64_t {
struct { f64 x, y, z, w; };
struct { v2f64_t xy; v2f64_t zw; };
struct { v3f64_t xyz; };
struct { f64 _x0; f64 yzw; };
struct { f64 r, g, b, a; };
struct { f64 h, s, l, _a; };
f64 e[4];
};
typedef union r1f64_t r1f64_t;
union r1f64_t {
struct { f64 min, max; };
struct { f64 x0, x1; };
f64 e[2];
};
typedef union r2f64_t r2f64_t;
union r2f64_t {
struct { v2f64_t min, max; };
struct { f64 x0, y0, x1, y1; };
v4f64_t e4;
f64 e[4];
};
typedef union r3f64_t r3f64_t;
union r3f64_t {
struct { v3f64_t min, max; };
struct { f64 x0, y0, z0, x1, y1, z1; };
f64 e[6];
};
typedef union v2i32_t v2i32_t;
union v2i32_t {
struct { i32 x, y; };
i32 e[2];
};
typedef union v3i32_t v3i32_t;
union v3i32_t {
struct { i32 x, y, z; };
struct { v2i32_t xy; };
struct { i32 _x0; v2i32_t zw; };
struct { i32 r, g, b; };
struct { i32 h, s, l; };
i32 e[3];
};
typedef union v4i32_t v4i32_t;
union v4i32_t {
struct { i32 x, y, z, w; };
struct { v2i32_t xy; v2i32_t zw; };
struct { v3i32_t xyz; };
struct { i32 _x0; i32 yzw; };
struct { i32 r, g, b, a; };
struct { i32 h, s, l, _a; };
i32 e[4];
};
typedef union r1i32_t r1i32_t;
union r1i32_t {
struct { i32 min, max; };
struct { i32 x0, x1; };
i32 e[2];
};
typedef union r2i32_t r2i32_t;
union r2i32_t {
struct { v2i32_t min, max; };
struct { i32 x0, y0, x1, y1; };
v4i32_t e4;
i32 e[4];
};
typedef union r3i32_t r3i32_t;
union r3i32_t {
struct { v3i32_t min, max; };
struct { i32 x0, y0, z0, x1, y1, z1; };
i32 e[6];
};
typedef union v2i64_t v2i64_t;
union v2i64_t {
struct { i64 x, y; };
i64 e[2];
};
typedef union v3i64_t v3i64_t;
union v3i64_t {
struct { i64 x, y, z; };
struct { v2i64_t xy; };
struct { i64 _x0; v2i64_t zw; };
struct { i64 r, g, b; };
struct { i64 h, s, l; };
i64 e[3];
};
typedef union v4i64_t v4i64_t;
union v4i64_t {
struct { i64 x, y, z, w; };
struct { v2i64_t xy; v2i64_t zw; };
struct { v3i64_t xyz; };
struct { i64 _x0; i64 yzw; };
struct { i64 r, g, b, a; };
struct { i64 h, s, l, _a; };
i64 e[4];
};
typedef union r1i64_t r1i64_t;
union r1i64_t {
struct { i64 min, max; };
struct { i64 x0, x1; };
i64 e[2];
};
typedef union r2i64_t r2i64_t;
union r2i64_t {
struct { v2i64_t min, max; };
struct { i64 x0, y0, x1, y1; };
v4i64_t e4;
i64 e[4];
};
typedef union r3i64_t r3i64_t;
union r3i64_t {
struct { v3i64_t min, max; };
struct { i64 x0, y0, z0, x1, y1, z1; };
i64 e[6];
};
#define F64_PI (3.1415926535897932384626433832795028841971693994)
#define F64_DEG2RAD (F64_PI / 180.0); // @Usage: degree * DEG2RAD = radians;
#define F64_RAD2DEG (180.0 / F64_PI);
#define F32_PI ((f32)F64_PI)
#define v4f32_const_rgba255(r, g, b, a) { (f32)(r) / 255.0f, (f32)(g) / 255.0f, (f32)(b) / 255.0f, (f32)(a) / 255.0f }
#define v4f32_rgba255(r, g, b, a) (v4f32_t){ (f32)(r) / 255.0f, (f32)(g) / 255.0f, (f32)(b) / 255.0f, (f32)(a) / 255.0f }
static gb_read_only v4f32_t white_color = v4f32_const_rgba255(255, 255, 255, 255);
static gb_read_only v4f32_t black_color = v4f32_const_rgba255(0, 0, 0, 255);
static gb_read_only v4f32_t magenta_color = v4f32_const_rgba255(255, 0, 255, 255);
static gb_read_only v4f32_t red_color = v4f32_const_rgba255(255, 0, 0, 255);
static gb_read_only v4f32_t blue_color = v4f32_const_rgba255(0, 0, 255, 255);
-406
View File
@@ -1,406 +0,0 @@
import sys
op_idx = 0
opname_idx = 1
symbols = [
["+", "add"],
["-", "sub"],
["*", "mul"],
["/", "div"],
]
basic_types = [
"f32",
"f64",
"i32",
"i64",
]
name_idx = 0
member_idx = 1
vec_types = [
["v2", ["x", "y"]],
["v3", ["x", "y", "z"]],
["v4", ["x", "y", "z", "w"]],
]
rect_types = [
["r2", ["x0", "y0", "x1", "y1"]],
["r3", ["x0", "y0", "z0", "x1", "y1", "z1"]],
]
struct_types = vec_types + rect_types
# fd = open("core_math.gen.h", "w")
# sys.stdout = fd
# print("// auto generated using:", __file__)
# for bt in basic_types:
# s = """
# typedef union v2f64_t v2f64_t;
# union v2f64_t {
# struct { f64 x, y; };
# f64 e[2];
# };
# typedef union v3f64_t v3f64_t;
# union v3f64_t {
# struct { f64 x, y, z; };
# struct { v2f64_t xy; };
# struct { f64 _x0; v2f64_t zw; };
# struct { f64 r, g, b; };
# struct { f64 h, s, l; };
# f64 e[3];
# };
# typedef union v4f64_t v4f64_t;
# union v4f64_t {
# struct { f64 x, y, z, w; };
# struct { v2f64_t xy; v2f64_t zw; };
# struct { v3f64_t xyz; };
# struct { f64 _x0; f64 yzw; };
# struct { f64 r, g, b, a; };
# struct { f64 h, s, l, _a; };
# f64 e[4];
# };
# typedef union r1f64_t r1f64_t;
# union r1f64_t {
# struct { f64 min, max; };
# struct { f64 x0, x1; };
# f64 e[2];
# };
# typedef union r2f64_t r2f64_t;
# union r2f64_t {
# struct { v2f64_t min, max; };
# struct { f64 x0, y0, x1, y1; };
# v4f64_t e4;
# f64 e[4];
# };
# typedef union r3f64_t r3f64_t;
# union r3f64_t {
# struct { v3f64_t min, max; };
# struct { f64 x0, y0, z0, x1, y1, z1; };
# f64 e[6];
# };
#
#
# type_t type__v2f64_t = { type_kind_struct, s8_const("v2f64_t"), sizeof(v2f64_t), .count = 2,
# .members = (type_member_t[]){
# {s8_const("x"), &type__f64, .offset = offsetof(v2f64_t, x)},
# {s8_const("y"), &type__f64, .offset = offsetof(v2f64_t, y)},
# }
# };
# type_t type__v3f64_t = { type_kind_struct, s8_const("v3f64_t"), sizeof(v3f64_t), .count = 3,
# .members = (type_member_t[]){
# {s8_const("x"), &type__f64, .offset = offsetof(v3f64_t, x)},
# {s8_const("y"), &type__f64, .offset = offsetof(v3f64_t, y)},
# {s8_const("z"), &type__f64, .offset = offsetof(v3f64_t, z)},
# }
# };
# type_t type__v4f64_t = { type_kind_struct, s8_const("v4f64_t"), sizeof(v4f64_t), .count = 4,
# .members = (type_member_t[]){
# {s8_const("x"), &type__f64, .offset = offsetof(v4f64_t, x)},
# {s8_const("y"), &type__f64, .offset = offsetof(v4f64_t, y)},
# {s8_const("z"), &type__f64, .offset = offsetof(v4f64_t, z)},
# {s8_const("w"), &type__f64, .offset = offsetof(v4f64_t, w)},
# }
# };
# type_t type__r3f64_t = { type_kind_struct, s8_const("r3f64_t"), sizeof(r3f64_t), .count = 6,
# .members = (type_member_t[]){
# {s8_const("x0"), &type__f64, .offset = offsetof(r3f64_t, x0)},
# {s8_const("y0"), &type__f64, .offset = offsetof(r3f64_t, y0)},
# {s8_const("x0"), &type__f64, .offset = offsetof(r3f64_t, z0)},
# {s8_const("x1"), &type__f64, .offset = offsetof(r3f64_t, x1)},
# {s8_const("y1"), &type__f64, .offset = offsetof(r3f64_t, y1)},
# {s8_const("x1"), &type__f64, .offset = offsetof(r3f64_t, z1)},
# }
# };
# type_member_t members__r2f64_t[] = {
# {s8_const("x0"), &type__f64, .offset = offsetof(r2f64_t, x0)},
# {s8_const("y0"), &type__f64, .offset = offsetof(r2f64_t, y0)},
# {s8_const("x1"), &type__f64, .offset = offsetof(r2f64_t, x1)},
# {s8_const("y1"), &type__f64, .offset = offsetof(r2f64_t, y1)},
# };
# DEFINE_STRUCT(r2f64_t);
# type_member_t members__r1f64_t[] = {
# {s8_const("x0"), &type__f64, .offset = offsetof(r1f64_t, x0)},
# {s8_const("x1"), &type__f64, .offset = offsetof(r1f64_t, x1)},
# };
# DEFINE_STRUCT(r1f64_t);
# """
# s = s.replace("f64", bt)
# print(s)
fd = open("core_math.gen.c", "w", newline = "\n", encoding = "utf-8")
sys.stdout = fd
for basic_type in basic_types:
for st in struct_types:
type = f"{st[name_idx]}{basic_type}"
typedef = f"{type}_t"
members = st[member_idx]
def members_as_func_params(members, basic_type):
result = ""
for i, m in enumerate(members):
result += f"{basic_type} {m}"
if i != len(members) - 1:
result += ", "
return result
print(f"""fn_inline {type}_t {type}({members_as_func_params(members, basic_type)}) {{ return ({type}_t){{ {members_as_func_params(members, "")} }}; }}""")
print(f"""gb_read_only {type}_t {type}_null = {{0}};""")
print(f"""fn_inline b32 {type}_is_null({type}_t a) {{ return memory_equal(&a, &{type}_null, sizeof(a)); }}""")
print(f"""fn_inline b32 {type}_are_equal({type}_t a, {type}_t b) {{ return memory_equal(&a, &b, sizeof(a)); }}""")
for sym in symbols:
op = sym[op_idx]
opname = sym[opname_idx]
def op_str(members, op, skip_right = False):
result = ""
for i in range(len(members)):
mem = members[i]
if skip_right:
result += f"a.{mem} {op} b"
else:
result += f"a.{mem} {op} b.{mem}"
if i != len(members) - 1:
result += ", "
return result
print(f"fn_inline {type}_t {type}_{opname}({type}_t a, {type}_t b) {{ return ({type}_t){{ {op_str(members, op)} }}; }}")
print(f"fn_inline {type}_t {type}_{opname}s({type}_t a, {basic_type} b) {{ return ({type}_t){{ {op_str(members, op, skip_right = True)} }}; }}")
for basic_type in basic_types:
for i in range(len(rect_types)):
vec_type = vec_types[i]
rect_type = rect_types[i]
vec_name = vec_type[name_idx] + basic_type
vec_members = vec_type[member_idx]
rect_name = rect_type[name_idx] + basic_type
rect_members = rect_type[member_idx]
print(f"fn_inline {rect_name}_t {rect_name}_min_dim({vec_name}_t pos, {vec_name}_t size) {{ return ({rect_name}_t){{ pos, {vec_name}_add(pos, size) }}; }}")
print(f"fn_inline {rect_name}_t {rect_name}_center_half_dim({vec_name}_t center, {vec_name}_t halfdim) {{ return ({rect_name}_t){{ {vec_name}_sub(center, halfdim), {vec_name}_add(center, halfdim) }}; }}")
for basic_type in basic_types:
s = """
fn r2f64_t r2f64_cut_left(r2f64_t *r, f64 value) {
f64 minx = r->min.x;
r->min.x = MIN(r->min.x + value, r->max.x);
r2f64_t result = { .min = {.x = minx, .y = r->min.y}, .max = {.x = r->min.x, .y =r->max.y} };
return result;
}
fn r2f64_t r2f64_cut_right(r2f64_t *r, f64 value) {
f64 maxx = r->max.x;
r->max.x = MAX(r->min.x, r->max.x - value);
r2f64_t result = { .min = {.x = r->max.x, .y = r->min.y}, .max = {.x = maxx, .y = r->max.y} };
return result;
}
fn r2f64_t r2f64_cut_top(r2f64_t *r, f64 value) { /* Y is down */
f64 miny = r->min.y;
r->min.y = MIN(r->max.y, r->min.y + value);
r2f64_t result = { .min = {.x = r->min.x, .y = miny}, .max = {.x = r->max.x, .y = r->min.y} };
return result;
}
fn r2f64_t r2f64_cut_bottom(r2f64_t *r, f64 value) { /* Y is down */
f64 maxy = r->max.y;
r->max.y = MAX(r->min.y, r->max.y - value);
r2f64_t result = { .min = {.x = r->min.x, .y = r->max.y}, .max = {.x = r->max.x, .y = maxy} };
return result;
}
fn r2f64_t r2f64_cut_left_no_squash(r2f64_t *r, f64 value) {
f64 minx = r->min.x;
r->min.x = r->min.x + value;
r2f64_t result = { .min = {.x = minx, .y = r->min.y}, .max = {.x = r->min.x, .y =r->max.y} };
return result;
}
fn r2f64_t r2f64_cut_right_no_squash(r2f64_t *r, f64 value) {
f64 maxx = r->max.x;
r->max.x = r->max.x - value;
r2f64_t result = { .min = {.x = r->max.x, .y = r->min.y}, .max = {.x = maxx, .y = r->max.y} };
return result;
}
fn r2f64_t r2f64_cut_top_no_squash(r2f64_t *r, f64 value) { /* Y is down */
f64 miny = r->min.y;
r->min.y = r->min.y + value;
r2f64_t result = { .min = {.x = r->min.x, .y = miny}, .max = {.x = r->max.x, .y = r->min.y} };
return result;
}
fn r2f64_t r2f64_cut_bottom_no_squash(r2f64_t *r, f64 value) { /* Y is down */
f64 maxy = r->max.y;
r->max.y = r->max.y - value;
r2f64_t result = { .min = {.x = r->min.x, .y = r->max.y}, .max = {.x = r->max.x, .y = maxy} };
return result;
}
fn r2f64_t r2f64_add_left(r2f64_t *r, f64 value) {
r2f64_t result = { .min = {r->min.x - value, r->min.y}, .max = {r->min.x, r->max.y} };
r->min.x -= value;
return result;
}
fn r2f64_t r2f64_add_right(r2f64_t *r, f64 value) {
r2f64_t result = { .min = {r->max.x, r->min.y}, .max = {r->max.x + value, r->max.y} };
r->max.x += value;
return result;
}
fn r2f64_t r2f64_add_top(r2f64_t *r, f64 value) {
r2f64_t result = { .min = {r->min.x, r->min.y - value}, .max = {r->max.x, r->min.y} };
r->min.y -= value;
return result;
}
fn r2f64_t r2f64_add_bottom(r2f64_t *r, f64 value) {
r2f64_t result = { .min = {r->min.x, r->max.y}, .max = {r->max.x, r->max.y + value} };
r->max.y += value;
return result;
}
// get past left
fn r2f64_t r2f64_getp_left(const r2f64_t *rect, f64 value) {
r2f64_t result = r2f64(rect->min.x - value, rect->min.y, rect->min.x, rect->max.y);
return result;
}
fn r2f64_t r2f64_getp_right(const r2f64_t *rect, f64 value) {
r2f64_t result = r2f64(rect->max.x, rect->min.y, rect->max.x + value, rect->max.y);
return result;
}
fn r2f64_t r2f64_getp_bottom(const r2f64_t *rect, f64 value) {
r2f64_t result = r2f64(rect->min.x, rect->max.y, rect->max.x, rect->max.y + value);
return result;
}
fn r2f64_t r2f64_getp_top(const r2f64_t *rect, f64 value) {
r2f64_t result = r2f64(rect->min.x, rect->min.y - value, rect->max.x, rect->min.y);
return result;
}
fn r2f64_t r2f64_get_left(const r2f64_t *r, f64 value) {
f64 minx = r->min.x;
r2f64_t result = (r2f64_t){ .min = {.x = minx, .y = r->min.y}, .max = {.x = MIN(r->min.x + value, r->max.x), .y =r->max.y} };
return result;
}
fn r2f64_t r2f64_get_right(const r2f64_t *r, f64 value) {
f64 maxx = r->max.x;
r2f64_t result = (r2f64_t){ .min = {.x = MAX(r->min.x, r->max.x - value), .y = r->min.y}, .max = {.x = maxx, .y = r->max.y} };
return result;
}
fn r2f64_t r2f64_get_top(const r2f64_t *r, f64 value) { /* Y is down */
f64 miny = r->min.y;
r2f64_t result = (r2f64_t){ .min = {.x = r->min.x, .y = miny}, .max = {.x = r->max.x, .y = MIN(r->max.y, r->min.y + value)} };
return result;
}
fn r2f64_t r2f64_get_bottom(const r2f64_t *r, f64 value) { /* Y is down */
f64 maxy = r->max.y;
r2f64_t result = (r2f64_t){ .min = {.x = r->min.x, .y = MAX(r->min.y, r->max.y - value)}, .max = {.x = r->max.x, .y = maxy} };
return result;
}
fn_inline r2f64_t r2f64_expand(r2f64_t rect, v2f64_t value) { return (r2f64_t){ v2f64_sub(rect.min, value), v2f64_add(rect.max, value) }; }
fn_inline r2f64_t r2f64_shrink(r2f64_t rect, v2f64_t value) { return (r2f64_t){ v2f64_add(rect.min, value), v2f64_sub(rect.max, value) }; }
fn_inline r2f64_t r2f64_shrinks(r2f64_t rect, f64 value) { return (r2f64_t){ v2f64_adds(rect.min, value), v2f64_subs(rect.max, value) }; }
fn_inline v2f64_t r2f64_size(r2f64_t r) { return (v2f64_t){r.max.x - r.min.x, r.max.y - r.min.y}; }
fn_inline v2f64_t r2f64_get_mid(r2f64_t r) { return v2f64_add(r.min, v2f64_divs(r2f64_size(r), 2)); }
fn_inline b32 r2f64_contains(r2f64_t rec, v2f64_t point) { return (point.x >= rec.min.x) && (point.x < rec.max.x) && (point.y >= rec.min.y) && (point.y < rec.max.y); }
fn_inline r2f64_t r2f64_intersect(r2f64_t a, r2f64_t b) { return (r2f64_t){ .min.x = MAX(a.min.x, b.min.x), .min.y = MAX(a.min.y, b.min.y), .max.x = MIN(a.max.x, b.max.x), .max.y = MIN(a.max.y, b.max.y) }; }
fn_inline r2f64_t r2f64_union(r2f64_t a, r2f64_t b) { return (r2f64_t){ .min.x = MIN(a.min.x, b.min.x), .min.y = MIN(a.min.y, b.min.y), .max.x = MAX(a.max.x, b.max.x), .max.y = MAX(a.max.y, b.max.y) }; }
fn_inline f64 r1f64_size(r1f64_t a) { return a.max - a.min; }
fn_inline r1f64_t r1f64(f64 min, f64 max) { return (r1f64_t){min,max}; }
fn_inline r1f64_t r1f64_auto(f64 a, f64 b) { return (r1f64_t){MIN(a,b),MAX(a,b)}; }
fn_inline r1f64_t r1f64s(f64 a) { return (r1f64_t){a,a}; }
fn_inline r1f64_t r1f64_clamp(r1f64_t a, f64 min, f64 max) { return (r1f64_t){ .min = CLAMP(a.min, min, max), .max = CLAMP(a.max, min, max) }; }
fn_inline b32 r1f64_contains(r1f64_t rec, f64 point) { return (point >= rec.min) && (point < rec.max) && (point >= rec.min) && (point < rec.max); }
fn_inline b32 r1f64_are_equal(r1f64_t a, r1f64_t b) { return a.min == b.min && a.max == b.max; }
gb_read_only r1f64_t r1f64_null;
fn b32 r1f64_overlap(r1f64_t a, r1f64_t b) {
b32 r1 = (a.max >= b.min && a.max <= b.max) || (a.min >= b.min && a.min <= b.max);
b32 r2 = (b.max >= a.min && b.max <= a.max) || (b.min >= a.min && b.min <= a.max);
return r1 || r2;
}
fn v2f64_t v2f64_clamps(v2f64_t v, f64 min, f64 max) {
v2f64_t result = { CLAMP(v.x, min, max), CLAMP(v.y, min, max) };
return result;
}
fn v2f64_t v2f64_clamp(v2f64_t v, v2f64_t min, v2f64_t max) {
v2f64_t result = { CLAMP(v.x, min.x, max.x), CLAMP(v.y, min.y, max.y) };
return result;
}
fn r2f64_t r2f64_fix(r2f64_t n) {
r2f64_t result = {
.min = {MIN(n.min.x, n.max.x), MIN(n.min.y, n.max.y)},
.max = {MAX(n.min.x, n.max.x), MAX(n.min.y, n.max.y)},
};
return result;
}
""".strip()
s = s.replace("f64", basic_type)
print(s)
for at in basic_types:
for bt in basic_types:
if at == bt: continue
for st in struct_types:
atype = f"{st[name_idx]}{at}"
btype = f"{st[name_idx]}{bt}"
members = st[member_idx]
def cast_members(members, type):
result = ""
for i in range(len(members)):
result += f"({type})v.{members[i]}"
if i != len(members) - 1:
result += ", "
return result
print(f"fn_inline {btype}_t {atype}_to_{btype}({atype}_t v) {{ return ({btype}_t){{ {cast_members(members, bt)} }}; }}")
#######
# generate r2f64_sub_v2f64 for +-*/ and types
for bt in basic_types:
for sym in symbols:
word_op = sym[1]
s = """
fn_inline r2f64_t r2f64_sub_v2f64(r2f64_t a, v2f64_t b) { return (r2f64_t){ v2f64_sub(a.min, b), v2f64_sub(a.max, b) }; }
""".strip()
s = s.replace("f64", bt)
s = s.replace("sub", word_op)
print(s)
for bt in ["f32", "f64"]:
s = """
fn f64 f64_safe_ratio(f64 a, f64 b, f64 if0) {
f64 result = if0;
if (b != 0.0) {
result = a / b;
}
return result;
}
fn_inline f64 f64_safe_ratio0(f64 a, f64 b) { return f64_safe_ratio(a, b, 0); }
fn_inline f64 f64_safe_ratio1(f64 a, f64 b) { return f64_safe_ratio(a, b, 0); }
""".strip()
s = s.replace("f64", bt)
print(s)
-613
View File
@@ -1,613 +0,0 @@
#include "core_platform.h"
#include "core_ctx.h"
#include "stb_sprintf.h"
#if PLATFORM_WASM && PLATFORM_EMSCRIPTEN == 0
#define gb_wasm_export __attribute__((visibility("default")))
#define fn_export __attribute__((visibility("default")))
#define fn_wasm_import
fn_wasm_import void wasm_alert(isize ptr, i32 len);
fn_wasm_import f64 wasm_parse_float(isize str, i32 len);
fn_wasm_import void wasm_write_to_console(isize str, i32 len);
fn_wasm_import void wasm_trap(void);
extern char __heap_base;
fn void *os_vmem_reserve(usize size) {
unused(size);
return NULL;
}
fn b32 os_vmem_commit(void *p, usize size) {
unused(p);
unused(size);
return false;
}
fn b32 os_vmem_release(void *p) {
unused(p);
return true;
}
fn b32 os_vmem_decommit(void *p, usize size) {
unused(p);
unused(size);
return true;
}
fn void os_error_box(char *str) {
wasm_alert((isize)str, str_len(str));
}
fn void os_console_log(char *str) {
s8_t string = s8_from_char(str);
if (s8_ends_with(string, s8("\n"))) {
string = s8_chop(string, 1);
}
wasm_write_to_console((isize)string.str, (i32)string.len);
}
fn f64 os_parse_float(char *str) {
return wasm_parse_float((isize)str, str_len((char *)str));
}
fn void os_core_small_init(ma_arena_t *arena) {
tcx = ma_push_type(arena, thread_ctx_t);
tcx->log.break_on_error = true;
tcx->log.break_on_fatal = true;
tcx->log.break_on_warning = true;
tcx->log.print_file_and_line = true;
tcx->log.log_proc = default_log_proc;
}
fn void os_core_init(void) {
ma_arena_t perm = {0};
isize page_size = kib(64);
isize page_count = __builtin_wasm_memory_size(0);
u8 *memory = (u8 *)&__heap_base;
usize memory_size = page_count * (page_size) - (isize)memory;
perm.data = memory;
perm.commit = perm.reserve = memory_size;
os_core_small_init(&perm);
tcx->perm = perm;
ma_push_arena_ex(&tcx->perm, &tcx->temp, mib(64));
ma_push_arena_ex(&tcx->perm, &tcx->scratch[0], mib(2));
ma_push_arena_ex(&tcx->perm, &tcx->scratch[1], kib(256));
ma_push_arena_ex(&tcx->perm, &tcx->scratch[2], kib(64));
debugf("memory size = %lld", memory_size);
}
#elif PLATFORM_WINDOWS
#pragma comment(lib, "user32.lib")
#pragma comment(lib, "DbgHelp.lib")
#pragma comment(lib, "Shell32.lib")
#pragma comment(lib, "Ole32.lib")
#define NOMINMAX
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <DbgHelp.h>
#include <TlHelp32.h>
#include <Shlobj.h>
#include <math.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
typedef struct b_stacktrace_tag* b_stacktrace_handle;
/*
Returns a stack-trace handle from the point of view of the caller which
can be expanded to a string via b_stacktrace_to_string.
The handle is allocated with `malloc` and needs to be freed with `free`
*/
fn b_stacktrace_handle b_stacktrace_get();
/*
Converts a stack-trace handle to a human-readable string.
The string is allocated with `malloc` and needs to be freed with `free`
*/
fn char* b_stacktrace_to_string(b_stacktrace_handle stacktrace);
/*
Returns a human-readable stack-trace string from the point of view of the
caller.
The string is allocated with `malloc` and needs to be freed with `free`
*/
fn char* b_stacktrace_get_string(void);
/* version */
typedef struct print_buf {
char* buf;
int pos;
int size;
} print_buf;
static print_buf buf_init(void) {
print_buf ret = {
(char*) malloc(1024),
0,
1024
};
return ret;
}
static void buf_printf(print_buf* b, const char* fmt, ...) {
va_list args;
va_start(args, fmt);
const int len = stbsp_vsnprintf(NULL, 0, fmt, args) + 1;
va_end(args);
const int new_end = b->pos + len;
if (new_end > b->size) {
while (new_end > b->size) b->size *= 2;
b->buf = (char*)realloc(b->buf, b->size);
}
va_start(args, fmt);
b->pos += stbsp_vsnprintf(b->buf + b->pos, len, fmt, args);
va_end(args);
}
char* b_stacktrace_get_string(void) {
b_stacktrace_handle h = b_stacktrace_get();
char* ret = b_stacktrace_to_string(h);
free(h);
return ret;
}
#define B_STACKTRACE_MAX_DEPTH 1024
#define B_STACKTRACE_ERROR_FLAG ((DWORD64)1 << 63)
typedef struct b_stacktrace_entry {
DWORD64 AddrPC_Offset;
DWORD64 AddrReturn_Offset;
} b_stacktrace_entry;
static int SymInitialize_called = 0;
b_stacktrace_handle b_stacktrace_get(void) {
HANDLE process = GetCurrentProcess();
HANDLE thread = GetCurrentThread();
CONTEXT context;
STACKFRAME64 frame; /* in/out stackframe */
DWORD imageType;
b_stacktrace_entry* ret = (b_stacktrace_entry*)malloc(B_STACKTRACE_MAX_DEPTH * sizeof(b_stacktrace_entry));
int i = 0;
if (!SymInitialize_called) {
SymInitialize(process, NULL, TRUE);
SymInitialize_called = 1;
}
RtlCaptureContext(&context);
memset(&frame, 0, sizeof(frame));
#ifdef _M_IX86
imageType = IMAGE_FILE_MACHINE_I386;
frame.AddrPC.Offset = context.Eip;
frame.AddrPC.Mode = AddrModeFlat;
frame.AddrFrame.Offset = context.Ebp;
frame.AddrFrame.Mode = AddrModeFlat;
frame.AddrStack.Offset = context.Esp;
frame.AddrStack.Mode = AddrModeFlat;
#elif _M_X64
imageType = IMAGE_FILE_MACHINE_AMD64;
frame.AddrPC.Offset = context.Rip;
frame.AddrPC.Mode = AddrModeFlat;
frame.AddrFrame.Offset = context.Rsp;
frame.AddrFrame.Mode = AddrModeFlat;
frame.AddrStack.Offset = context.Rsp;
frame.AddrStack.Mode = AddrModeFlat;
#elif _M_IA64
imageType = IMAGE_FILE_MACHINE_IA64;
frame.AddrPC.Offset = context.StIIP;
frame.AddrPC.Mode = AddrModeFlat;
frame.AddrFrame.Offset = context.IntSp;
frame.AddrFrame.Mode = AddrModeFlat;
frame.AddrBStore.Offset = context.RsBSP;
frame.AddrBStore.Mode = AddrModeFlat;
frame.AddrStack.Offset = context.IntSp;
frame.AddrStack.Mode = AddrModeFlat;
#else
#error "Platform not supported!"
#endif
while (1) {
b_stacktrace_entry* cur = ret + i++;
if (i == B_STACKTRACE_MAX_DEPTH) {
cur->AddrPC_Offset = 0;
cur->AddrReturn_Offset = 0;
break;
}
if (!StackWalk64(imageType, process, thread, &frame, &context, NULL, SymFunctionTableAccess64, SymGetModuleBase64, NULL)) {
cur->AddrPC_Offset = frame.AddrPC.Offset;
cur->AddrReturn_Offset = B_STACKTRACE_ERROR_FLAG; /* mark error */
cur->AddrReturn_Offset |= GetLastError();
break;
}
cur->AddrPC_Offset = frame.AddrPC.Offset;
cur->AddrReturn_Offset = frame.AddrReturn.Offset;
if (frame.AddrReturn.Offset == 0) {
break;
}
}
return (b_stacktrace_handle)(ret);
}
char* b_stacktrace_to_string(b_stacktrace_handle h) {
const b_stacktrace_entry* entries = (b_stacktrace_entry*)h;
int i = 0;
HANDLE process = GetCurrentProcess();
print_buf out = buf_init();
IMAGEHLP_SYMBOL64* symbol = (IMAGEHLP_SYMBOL64*)malloc(sizeof(IMAGEHLP_SYMBOL64) + 1024);
symbol->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL64);
symbol->MaxNameLength = 1024;
while (1) {
IMAGEHLP_LINE64 lineData;
DWORD lineOffset = 0;
DWORD64 symOffset = 0;
const b_stacktrace_entry* cur = entries + i++;
if (cur->AddrReturn_Offset & B_STACKTRACE_ERROR_FLAG) {
DWORD error = cur->AddrReturn_Offset & 0xFFFFFFFF;
buf_printf(&out, "StackWalk64 error: %d @ %p\n", error, cur->AddrPC_Offset);
break;
}
if (cur->AddrPC_Offset == cur->AddrReturn_Offset) {
buf_printf(&out, "Stack overflow @ %p\n", cur->AddrPC_Offset);
break;
}
SymGetLineFromAddr64(process, cur->AddrPC_Offset, &lineOffset, &lineData);
buf_printf(&out, "%s(%d): ", lineData.FileName, lineData.LineNumber);
if (SymGetSymFromAddr64(process, cur->AddrPC_Offset, &symOffset, symbol)) {
buf_printf(&out, "%s\n", symbol->Name);
}
else {
buf_printf(&out, " Unkown symbol @ %p\n", cur->AddrPC_Offset);
}
if (cur->AddrReturn_Offset == 0) {
break;
}
}
free(symbol);
return out.buf;
}
fn void *os_vmem_reserve(usize size) {
void *result = VirtualAlloc(0, size, MEM_RESERVE, PAGE_READWRITE);
return result;
}
fn b32 os_vmem_commit(void *p, usize size) {
void *result = VirtualAlloc(p, size, MEM_COMMIT, PAGE_READWRITE);
return result ? true : false;
}
fn b32 os_vmem_release(void *p) {
BOOL result = VirtualFree(p, 0, MEM_RELEASE);
return result ? true : false;
}
fn b32 os_vmem_decommit(void *p, usize size) {
BOOL result = VirtualFree(p, size, MEM_DECOMMIT);
return result ? true : false;
}
fn void os_error_box(char *str) {
OutputDebugStringA(str);
fprintf(stderr, "%s", str);
fflush(stderr);
MessageBoxA(NULL, str, "fatal error", MB_OK);
}
fn void os_console_log(char *str) {
OutputDebugStringA(str);
fputs(str, stdout);
fflush(stdout);
}
fn f64 os_parse_float(char *str) {
return strtod(str, NULL);
}
fn void os_win32_crash_handler(int signal) {
printf("signal: %d\n", signal);
puts(b_stacktrace_get_string());
exit(1);
}
fn void os_win32_register_crash_handler() {
signal(SIGSEGV, os_win32_crash_handler);
signal(SIGABRT, os_win32_crash_handler);
}
fn void os_core_small_init(ma_arena_t *arena) {
tcx = ma_push_type(arena, thread_ctx_t);
tcx->log.break_on_error = true;
tcx->log.break_on_fatal = true;
tcx->log.break_on_warning = true;
tcx->log.print_file_and_line = true;
tcx->log.log_proc = default_log_proc;
os_win32_register_crash_handler();
}
fn void os_core_init(void) {
ma_arena_t perm = {0};
os_core_small_init(&perm);
tcx->perm = perm;
}
#elif PLATFORM_POSIX
#if defined(__linux__) && !defined(_GNU_SOURCE)
#define _GNU_SOURCE
#endif
#if !PLATFORM_EMSCRIPTEN
#include <execinfo.h>
#include <ucontext.h>
#endif
#include <unistd.h>
#include <dlfcn.h>
#include <string.h>
#include <stdarg.h>
#include <math.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <sys/mman.h>
#include <signal.h>
#include <unistd.h>
#include <dlfcn.h>
fn void *os_vmem_reserve(usize size) {
void *result = mmap(0, size, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
return result == MAP_FAILED ? NULL : result;
}
fn b32 os_vmem_commit(void *ptr, usize size) {
mprotect(ptr, size, PROT_READ|PROT_WRITE);
return true;
}
fn b32 os_vmem_release(void *ptr) {
int result = munmap(ptr, 0);
return result == 0 ? true : false;
}
fn b32 os_vmem_decommit(void *ptr, usize size) {
madvise(ptr, size, MADV_DONTNEED);
mprotect(ptr, size, PROT_NONE);
return true;
}
fn void os_error_box(char *str) {
fprintf(stderr, "%s", str);
fflush(stderr);
}
fn void os_console_log(char *str) {
fputs(str, stdout);
fflush(stdout);
}
fn f64 os_parse_float(char *str) {
return strtod(str, NULL);
}
#if !PLATFORM_EMSCRIPTEN
typedef struct b_stacktrace_tag* b_stacktrace_handle;
b_stacktrace_handle b_stacktrace_get();
int b_stacktrace_depth(b_stacktrace_handle stacktrace);
char* b_stacktrace_to_string(b_stacktrace_handle stacktrace);
char* malloc_backtrace(void);
typedef struct print_buf {
char* buf;
int pos;
int size;
} print_buf;
static print_buf buf_init(void) {
print_buf ret = {
(char*) malloc(1024),
0,
1024
};
return ret;
}
static void buf_printf(print_buf* b, const char* fmt, ...) {
va_list args;
va_start(args, fmt);
const int len = vsnprintf(NULL, 0, fmt, args) + 1;
va_end(args);
const int new_end = b->pos + len;
if (new_end > b->size) {
while (new_end > b->size) b->size *= 2;
b->buf = (char*)realloc(b->buf, b->size);
}
va_start(args, fmt);
b->pos += vsnprintf(b->buf + b->pos, len, fmt, args);
va_end(args);
}
char* malloc_backtrace(void) {
b_stacktrace_handle h = b_stacktrace_get();
char* ret = b_stacktrace_to_string(h);
free(h);
return ret;
}
#define B_STACKTRACE_MAX_DEPTH 1024
typedef struct b_stacktrace {
void* trace[B_STACKTRACE_MAX_DEPTH];
int trace_size;
} b_stacktrace;
b_stacktrace_handle b_stacktrace_get(void) {
b_stacktrace* ret = (b_stacktrace*)malloc(sizeof(b_stacktrace));
ret->trace_size = backtrace(ret->trace, B_STACKTRACE_MAX_DEPTH);
return (b_stacktrace_handle)(ret);
}
int b_stacktrace_depth(b_stacktrace_handle h) {
const b_stacktrace* stacktrace = (b_stacktrace*)h;
return stacktrace->trace_size;
}
char* b_stacktrace_to_string(b_stacktrace_handle h) {
const b_stacktrace* stacktrace = (b_stacktrace*)h;
char** messages = backtrace_symbols(stacktrace->trace, stacktrace->trace_size);
print_buf out = buf_init();
int i;
int skip_count = 5;
for (i = 0; i < stacktrace->trace_size; ++i) {
void* tracei = stacktrace->trace[i];
char* msg = messages[i];
if (i < skip_count) {
continue;
}
/* calculate load offset */
Dl_info info;
dladdr(tracei, &info);
if (info.dli_fbase == (void*)0x400000) {
/* address from executable, so don't offset */
info.dli_fbase = NULL;
}
while (*msg && *msg != '(') ++msg;
*msg = 0;
{
char cmd[1024];
char line[2048];
FILE* fp;
snprintf(cmd, 1024, "addr2line -e %s -f -C -p %p 2>/dev/null", messages[i], (void*)((char*)tracei - (char*)info.dli_fbase));
fp = popen(cmd, "r");
if (!fp) {
buf_printf(&out, "Failed to generate trace further...\n");
break;
}
while (fgets(line, sizeof(line), fp)) {
buf_printf(&out, " ");
if (strstr(line, "?? ")) {
/* just output address if nothing can be found */
buf_printf(&out, "%p\n", tracei);
}
else {
int len = strlen(line);
char *at = strstr(line, " at ");
if (at) {
char *function = line;
int function_len = at - line;
char *file = at + 4;
int file_len = strlen(file) - 1;
buf_printf(&out, " %.*s %.*s (%s)\n", file_len, file, function_len, function, messages[i]);
} else {
buf_printf(&out, " %.*s (%s)\n", len - 1, line, messages[i]);
}
}
}
pclose(fp);
}
}
free(messages);
return out.buf;
}
void print_backtrace(void) {
char *backtrace = malloc_backtrace();
puts(backtrace);
free(backtrace);
}
const char *signal_to_string(int signal) {
switch (signal) {
case SIGINT: return "SIGINT";
case SIGILL: return "SIGILL";
case SIGABRT: return "SIGABRT";
case SIGFPE: return "SIGFPE";
case SIGSEGV: return "SIGSEGV";
case SIGTERM: return "SIGTERM";
case SIGHUP: return "SIGALRM";
case SIGQUIT: return "SIGQUIT";
case SIGTRAP: return "SIGTRAP";
case SIGKILL: return "SIGKILL";
case SIGPIPE: return "SIGPIPE";
case SIGALRM: return "SIGHUP";
case SIGPOLL: return "SIGPOLL";
default: return "";
}
}
void backtrace_handle_signal(int signal, siginfo_t* info, void* context) {
(void)context; // unused
printf("Stack trace (%s/%d):", signal_to_string(signal), signal);
if (signal == SIGSEGV) {
printf(" at addr: %p", info->si_addr);
}
puts("");
print_backtrace();
exit(1);
}
void setup_backtrace() {
struct sigaction sa;
sa.sa_sigaction = backtrace_handle_signal;
sigemptyset(&sa.sa_mask);
sa.sa_flags = SA_RESTART | SA_SIGINFO;
sigaction(SIGSEGV, &sa, NULL);
sigaction(SIGABRT, &sa, NULL);
sigaction(SIGFPE, &sa, NULL);
sigaction(SIGBUS, &sa, NULL);
sigaction(SIGILL, &sa, NULL);
sigaction(SIGTRAP, &sa, NULL);
}
#endif
fn void os_core_small_init(ma_arena_t *arena) {
tcx = ma_push_type(arena, thread_ctx_t);
tcx->log.break_on_error = true;
tcx->log.break_on_fatal = true;
tcx->log.break_on_warning = true;
tcx->log.print_file_and_line = true;
tcx->log.log_proc = default_log_proc;
#if !PLATFORM_EMSCRIPTEN
setup_backtrace();
#endif
}
fn void os_core_init(void) {
ma_arena_t perm = {0};
os_core_small_init(&perm);
tcx->perm = perm;
}
#endif
-30
View File
@@ -1,30 +0,0 @@
#pragma once
#include "core_basic.h"
#include "core_arena.h"
fn void os_error_box(char *str);
fn void os_console_log(char *str);
fn void *os_vmem_reserve(usize size);
fn b32 os_vmem_commit(void *p, usize size);
fn b32 os_vmem_release(void *p);
fn b32 os_vmem_decommit(void *p, usize size);
fn void os_core_init(void);
fn void os_core_small_init(ma_arena_t *arena);
fn f64 os_parse_float(char *str);
#if PLATFORM_DEBUG_ASSERT
#define assert_expr(x) (!(x) && (os_error_box(FILE_AND_LINE ": assertion failed: " #x "\n"), debug_break()))
#define assert(x) do { assert_expr(x); } while(0)
#define assert_ex(x, msg) (!(x) && (os_error_box(FILE_AND_LINE ": assertion failed: " #x " :: " #msg "\n"), debug_break()))
#else
#define assert_expr(x) (void)(x)
#define assert(x) do { (void)(x); } while(0)
#define assert_ex(x, msg) do { (void)(x); } while(0)
#endif
#define not_implemented assert(!"not implemented!")
#define invalid_codepath assert(!"invalid code path!")
#define default_is_invalid default: assert(!"invalid default case")
#define else_is_invalid else { assert(!"else was not expected to be executed!"); }
-557
View File
@@ -1,557 +0,0 @@
#include "core_string.h"
#include "core_intrin.h"
#include "core_platform.h"
#include "stb_sprintf.h"
fn i32 str_len(char *str) {
i32 i = 0;
while (str[i]) i += 1;
return i;
}
fn b32 str_eq(char *a, char *b) {
return s8_are_equal(s8_from_char(a), s8_from_char(b));
}
fn char char_to_lower_case(char a) {
if (a >= 'A' && a <= 'Z') a += 32;
return a;
}
fn char char_to_upper_case(char a) {
if (a >= 'a' && a <= 'z') a -= 32;
return a;
}
fn b32 char_is_whitespace(char w) {
b32 result = w == '\n' || w == ' ' || w == '\t' || w == '\v' || w == '\r';
return result;
}
fn b32 char_is_alphabetic(char a) {
b32 result = (a >= 'a' && a <= 'z') || (a >= 'A' && a <= 'Z');
return result;
}
fn b32 char_is_ident(char a) {
b32 result = (a >= 'a' && a <= 'z') || (a >= 'A' && a <= 'Z') || a == '_';
return result;
}
fn b32 char_is_digit(char a) {
b32 result = a >= '0' && a <= '9';
return result;
}
fn b32 char_is_alphanumeric(char a) {
b32 result = char_is_digit(a) || char_is_alphabetic(a);
return result;
}
fn b32 char_is_symbol(char w) {
b32 result = (w >= '!' && w <= '/') || (w >= ':' && w <= '@') || (w >= '[' && w <= '`') || (w >= '{' && w <= '~');
return result;
}
fn b32 char_is_non_word(char w) {
b32 result = w != '_' && (char_is_symbol(w) || char_is_whitespace(w));
return result;
}
fn b32 char_is_word(char w) {
b32 result = !char_is_non_word(w);
return result;
}
fn s8_t s8_from_range(char *begin, char *end) {
assert(end >= begin);
intptr_t size = (intptr_t)end - (intptr_t)begin;
s8_t result = {begin, size};
return result;
}
fn s8_t s8_from_char(char *string) {
s8_t result;
result.str = (char *)string;
result.len = str_len(string);
return result;
}
fn s8_t s8_copy(ma_arena_t *ma, s8_t string) {
char *copy = (char *)ma_push_size(ma, sizeof(char) * (string.len + 1));
memory_copy(copy, string.str, string.len);
copy[string.len] = 0;
s8_t result = s8_make(copy, string.len);
return result;
}
fn s8_t s8_copy_char(ma_arena_t *ma, char *s) {
int64_t len = str_len(s);
char *copy = (char *)ma_push_size(ma, sizeof(char) * (len + 1));
memory_copy(copy, s, len);
copy[len] = 0;
s8_t result = s8_make(copy, len);
return result;
}
fn b32 s8_are_equal_ex(s8_t a, s8_t b, b32 ignore_case) {
if (a.len != b.len) return false;
for (int64_t i = 0; i < a.len; i++) {
char A = a.str[i];
char B = b.str[i];
if (ignore_case) {
A = char_to_lower_case(A);
B = char_to_lower_case(B);
}
if (A != B)
return false;
}
return true;
}
fn b32 s8_are_equal(s8_t a, s8_t b) {
return s8_are_equal_ex(a, b, false);
}
fn s8_t s8_get_postfix(s8_t string, int64_t len) {
len = CLAMP_TOP(len, string.len);
int64_t remain_len = string.len - len;
s8_t result = s8_make(string.str + remain_len, len);
return result;
}
fn s8_t s8_get_prefix(s8_t string, int64_t len) {
len = CLAMP_TOP(len, string.len);
s8_t result = s8_make(string.str, len);
return result;
}
fn s8_t s8_chop(s8_t string, int64_t len) {
len = CLAMP_TOP(len, string.len);
s8_t result = s8_make(string.str, string.len - len);
return result;
}
fn s8_t s8_skip(s8_t string, int64_t len) {
len = CLAMP_TOP(len, string.len);
int64_t remain = string.len - len;
s8_t result = s8_make(string.str + len, remain);
return result;
}
fn b32 s8_ends_with_ex(s8_t a, s8_t end, b32 ignore_case) {
s8_t a_end = s8_get_postfix(a, end.len);
b32 result = s8_are_equal_ex(end, a_end, ignore_case);
return result;
}
fn b32 s8_starts_with_ex(s8_t a, s8_t start, b32 ignore_case) {
s8_t a_start = s8_get_prefix(a, start.len);
b32 result = s8_are_equal_ex(start, a_start, ignore_case);
return result;
}
fn b32 s8_ends_with(s8_t a, s8_t end) {
return s8_ends_with_ex(a, end, false);
}
fn b32 s8_starts_with(s8_t a, s8_t start) {
return s8_starts_with_ex(a, start, false);
}
fn void s8_normalize_path_unsafe(s8_t s) {
for (int64_t i = 0; i < s.len; i++) {
if (s.str[i] == '\\')
s.str[i] = '/';
}
}
fn b32 s8_is_pointer_inside(s8_t string, char *p) {
uintptr_t pointer = (uintptr_t)p;
uintptr_t start = (uintptr_t)string.str;
uintptr_t stop = start + (uintptr_t)string.len;
b32 result = pointer >= start && pointer < stop;
return result;
}
fn s8_t s8_cut_start(s8_t *in, i64 size) {
s8_t result = s8_get_prefix(*in, size);
*in = s8_skip(*in, result.len);
return result;
}
fn s8_t s8_cut_end(s8_t *in, i64 size) {
s8_t result = s8_get_postfix(*in, size);
*in = s8_chop(*in, result.len);
return result;
}
#if 0
s8_t s8_skip_to_p(s8_t string, char *p) {
if (s8_is_pointer_inside(string, p)) {
s8_t result = s8_make(p, p - string.str);
return result;
}
return string;
}
s8_t s8_skip_past(s8_t string, s8_t a) {
if (s8_is_pointer_inside(string, a.str)) {
s8_t on_p = s8_make(a.str, a.str - string.str);
s8_t result = s8_skip(on_p, a.len);
return result;
}
return string;
}
#endif
fn s8_t s8_slice(s8_t string, int64_t first_index, int64_t one_past_last_index) {
if (one_past_last_index < 0) one_past_last_index = string.len + one_past_last_index + 1;
if (first_index < 0) first_index = string.len + first_index;
assert(first_index < one_past_last_index);
assert(string.len > 0);
s8_t result = string;
if (string.len > 0) {
if (one_past_last_index > first_index) {
first_index = CLAMP_TOP(first_index, string.len - 1);
one_past_last_index = CLAMP_TOP(one_past_last_index, string.len);
result.str += first_index;
result.len = one_past_last_index - first_index;
}
else {
result.len = 0;
}
}
return result;
}
fn s8_t s8_trim(s8_t string) {
if (string.len == 0)
return string;
int64_t whitespace_begin = 0;
for (; whitespace_begin < string.len; whitespace_begin++) {
if (!char_is_whitespace(string.str[whitespace_begin])) {
break;
}
}
int64_t whitespace_end = string.len;
for (; whitespace_end != whitespace_begin; whitespace_end--) {
if (!char_is_whitespace(string.str[whitespace_end - 1])) {
break;
}
}
if (whitespace_begin == whitespace_end) {
string.len = 0;
}
else {
string = s8_slice(string, whitespace_begin, whitespace_end);
}
return string;
}
fn s8_t s8_trim_end(s8_t string) {
int64_t whitespace_end = string.len;
for (; whitespace_end != 0; whitespace_end--) {
if (!char_is_whitespace(string.str[whitespace_end - 1])) {
break;
}
}
s8_t result = s8_get_prefix(string, whitespace_end);
return result;
}
fn b32 s8_seek(s8_t string, s8_t find, s8_seek_t flags, int64_t *index_out) {
b32 ignore_case = flags & s8_seek_ignore_case ? true : false;
b32 result = false;
if (flags & s8_seek_match_find_last) {
for (int64_t i = string.len; i != 0; i--) {
int64_t index = i - 1;
s8_t substring = s8_slice(string, index, index + find.len);
if (s8_are_equal_ex(substring, find, ignore_case)) {
if (index_out)
*index_out = index;
result = true;
break;
}
}
}
else {
for (int64_t i = 0; i < string.len; i++) {
s8_t substring = s8_slice(string, i, i + find.len);
if (s8_are_equal_ex(substring, find, ignore_case)) {
if (index_out)
*index_out = i;
result = true;
break;
}
}
}
return result;
}
fn int64_t s8_find(s8_t string, s8_t find, s8_seek_t flag) {
int64_t result = -1;
s8_seek(string, find, flag, &result);
return result;
}
fn s8_t s8_chop_last_char(s8_t s, s8_t ch) {
s8_t result = s;
s8_seek(s, ch, s8_seek_match_find_last, &result.len);
return result;
}
fn s8_t s8_chop_last_slash(s8_t s) {
return s8_chop_last_char(s, s8("/"));
}
fn s8_t s8_chop_last_period(s8_t s) {
return s8_chop_last_char(s, s8("."));
}
fn s8_t s8_skip_to_last_char(s8_t s, s8_t ch) {
int64_t pos;
s8_t result = s;
if (s8_seek(s, ch, s8_seek_match_find_last, &pos)) {
result = s8_skip(result, pos + 1);
}
return result;
}
fn s8_t s8_skip_to_last_slash(s8_t s) {
return s8_skip_to_last_char(s, s8("/"));
}
fn s8_t s8_skip_to_last_period(s8_t s) {
return s8_skip_to_last_char(s, s8("."));
}
fn s8_t s8_get_name_no_ext(s8_t s) {
return s8_skip_to_last_slash(s8_chop_last_period(s));
}
fn s8_t s8_normalize_path(ma_arena_t *ma, s8_t s) {
s8_t copy = s8_copy(ma, s);
s8_normalize_path_unsafe(copy);
return copy;
}
fn s8_t s8_to_lower_case(ma_arena_t *ma, s8_t s) {
s8_t copy = s8_copy(ma, s);
for (int64_t i = 0; i < copy.len; i++) {
copy.str[i] = char_to_lower_case(copy.str[i]);
}
return copy;
}
fn s8_t s8_to_upper_case(ma_arena_t *ma, s8_t s) {
s8_t copy = s8_copy(ma, s);
for (int64_t i = 0; i < copy.len; i++) {
copy.str[i] = char_to_upper_case(copy.str[i]);
}
return copy;
}
fn s8_t s8_vfmt(ma_arena_t *ma, const char *str, va_list args1) {
va_list args2;
va_copy(args2, args1);
int64_t len = s8_vsnprintf(0, 0, str, args2);
va_end(args2);
char *result = (char *)ma_push_size(ma, sizeof(char) * (len + 1));
s8_vsnprintf(result, (i32)(len + 1), str, args1);
s8_t res = s8_make(result, len);
return res;
}
fn s8_t s8_printf(ma_arena_t *ma, const char *str, ...) {
S8_FMT(ma, str, result);
return result;
}
fn sb8_node_t *sb8_create_node(ma_arena_t *ma, s8_t str) {
sb8_node_t *node = ma_push_type(ma, sb8_node_t);
node->string = str;
return node;
}
fn sb8_node_t *sb8_append(sb8_t *list, s8_t string) {
assert(list->arena != NULL);
sb8_node_t *node = sb8_create_node(list->arena, string);
SLLQ_APPEND(list->first, list->last, node);
return node;
}
fn s8_t sb8_printf(sb8_t *sb, const char *str, ...) {
S8_FMT(sb->arena, str, result);
sb8_append(sb, result);
return result;
}
fn void sb8_indent(sb8_t *sb) {
sb8_printf(sb, "\n%.*s", sb->indent*4, " ");
}
fn s8_t sb8_stmtf(sb8_t *sb, const char *str, ...) {
S8_FMT(sb->arena, str, result);
sb8_indent(sb);
sb8_append(sb, result);
return result;
}
fn int64_t sb8_char_size(sb8_t *sb) {
int64_t result = 0;
for (sb8_node_t *it = sb->first; it; it = it->next) {
result += it->len;
}
return result;
}
fn s8_t sb8_merge(ma_arena_t *arena, sb8_t *sb) {
int64_t size = sb8_char_size(sb) + 1;
char *str = ma_push_size(arena, size);
s8_t result = {str, 0};
for (sb8_node_t *it = sb->first; it; it = it->next) {
memory_copy(result.str + result.len, it->str, it->len);
result.len += it->len;
}
result.str[result.len] = 0;
return result;
}
fn sb8_t s8_split(ma_arena_t *ma, s8_t string, s8_t find, s8_split_t flags) {
sb8_t result = (sb8_t){ma};
int64_t index = 0;
s8_seek_t find_flag = flags & s8_split_ignore_case ? s8_seek_ignore_case : s8_seek_none;
while (s8_seek(string, find, find_flag, &index)) {
s8_t before_match = s8_make(string.str, index);
if (flags & s8_split_cleanup) {
before_match = s8_trim(before_match);
if (before_match.len) {
sb8_append(&result, before_match);
}
} else {
sb8_append(&result, before_match);
}
if (flags & s8_split_inclusive) {
s8_t match = s8_make(string.str + index, find.len);
sb8_append(&result, match);
}
string = s8_skip(string, index + find.len);
}
if (string.len) sb8_append(&result, string);
return result;
}
fn u64 u64_from_hexchar(char c) {
switch (c) {
case '0': return 0; break;
case '1': return 1; break;
case '2': return 2; break;
case '3': return 3; break;
case '4': return 4; break;
case '5': return 5; break;
case '6': return 6; break;
case '7': return 7; break;
case '8': return 8; break;
case '9': return 9; break;
case 'a':
case 'A': return 10; break;
case 'b':
case 'B': return 11; break;
case 'c':
case 'C': return 12; break;
case 'd':
case 'D': return 13; break;
case 'e':
case 'E': return 14; break;
case 'f':
case 'F': return 15; break;
default: return 255;
}
}
fn u64 u64_from_s8(s8_t s, u64 base) {
assert(base >= 2 && base <= 16);
u64 acc = 0;
for (i64 i = 0; i < s.len; i++) {
u64 num = u64_from_hexchar(s.str[i]);
assert(num < base);
acc *= base;
acc += num;
}
return acc;
}
fn u64 u64_from_s8_loose(s8_t s, u64 base) {
assert(base >= 2 && base <= 16);
u64 acc = 0;
for (i64 i = 0; i < s.len; i++) {
u64 num = u64_from_hexchar(s.str[i]);
if (num >= base) {
break;
}
acc *= base;
acc += num;
}
return acc;
}
fn f64 f64_from_s8(s8_t string) {
ma_temp_t scratch = ma_begin_scratch();
s8_t num_string = s8_copy(scratch.arena, string);
f64 result = os_parse_float(num_string.str);
ma_end_scratch(scratch);
return result;
}
gb_read_only i64 s8_fuzzy_closer_word_begin = 5;
gb_read_only i64 s8_fuzzy_consecutive_multiplier = 3;
fn i64 s8_fuzzy_rate_string(s8_t string, s8_t with) {
if (with.len == 0) return 0;
i64 points = 0;
i64 consecutive = 0;
i64 with_i = 0;
for (i64 i = 0; i < string.len; i++) {
if (string.str[i] == with.str[with_i]) {
i64 closer_begin = CLAMP_BOT((i64)0, s8_fuzzy_closer_word_begin - i);
points += closer_begin;
consecutive++;
with_i += 1;
} else {
points += consecutive * s8_fuzzy_consecutive_multiplier;
consecutive = 0;
with_i = 0;
}
if (with_i >= with.len) with_i = 0;
}
points += consecutive * s8_fuzzy_consecutive_multiplier;
return points;
}
fn fuzzy_pair_t *s8_fuzzy_rate_array(ma_arena_t *arena, s8_t needle, s8_t *array, i32 len) {
fuzzy_pair_t *pairs = ma_push_array(arena, fuzzy_pair_t, len);
for (i32 i = 0; i < len; i += 1) {
pairs[i].rating = s8_fuzzy_rate_string(array[i], needle);
pairs[i].index = i;
}
for (i32 i = 0; i < len - 1; i++) {
for (i32 j = 0; j < len - 1; j++) {
if (pairs[j].rating < pairs[j + 1].rating) {
SWAP(fuzzy_pair_t, pairs[j], pairs[j + 1]);
}
}
}
return pairs;
}
-180
View File
@@ -1,180 +0,0 @@
#pragma once
#include "core_basic.h"
#include "core_arena.h"
typedef struct s8_t s8_t;
struct s8_t {
char *str;
int64_t len;
};
typedef struct sb8_node_t sb8_node_t;
struct sb8_node_t {
sb8_node_t *next;
union {
struct { char *str; int64_t len; };
s8_t string;
};
};
typedef struct sb8_t sb8_t;
struct sb8_t {
ma_arena_t *arena;
sb8_node_t *first;
sb8_node_t *last;
// WARNING: remember to update typeinfo after editing this
i32 indent;
};
typedef i32 s8_seek_t;
enum {
s8_seek_none = 0,
s8_seek_ignore_case = 1,
s8_seek_match_find_last = 2,
};
typedef i32 s8_split_t;
enum {
s8_split_none = 0,
s8_split_ignore_case = 1,
s8_split_inclusive = 2,
s8_split_cleanup = 4,
};
enum { s8_ignore_case = 1 };
//
// char and char string operations
fn i32 str_len(char *str);
fn b32 str_eq(char *a, char *b);
fn char char_to_lower_case(char a);
fn char char_to_upper_case(char a);
fn b32 char_is_whitespace(char w);
fn b32 char_is_alphabetic(char a);
fn b32 char_is_ident(char a);
fn b32 char_is_digit(char a);
fn b32 char_is_alphanumeric(char a);
fn u64 u64_from_hexchar(char c);
fn u64 u64_from_s8(s8_t s, u64 base);
fn f64 f64_from_s8(s8_t string);
//
// string8 constructors
#define s8_make(str,len) (s8_t){str, len}
#define s8_null (s8_t){0}
#define s8_invalid s8("<INVALID>")
#define s8(string) (s8_t){(char *)string, sizeof(string) - 1}
#define s8_const(string) { string, sizeof(string) - 1 }
#define s8_struct(DATA) (s8_t){.str = (char *)&(DATA), .len = sizeof(DATA)}
#define s8_array(DATA) (s8_t){.str = (char *)(DATA), .len = lengthof(DATA)}
#define s8_array_lit(DATA) {.str = (char *)(DATA), .len = lengthof(DATA)}
fn s8_t s8_from_range(char *begin, char *end);
fn s8_t s8_from_char(char *string);
fn s8_t s8_copy(ma_arena_t *ma, s8_t string);
//
// conditional
fn b32 s8_are_equal_ex(s8_t a, s8_t b, b32 ignore_case);
fn b32 s8_are_equal(s8_t a, s8_t b);
fn b32 s8_ends_with_ex(s8_t a, s8_t end, b32 ignore_case);
fn b32 s8_starts_with_ex(s8_t a, s8_t start, b32 ignore_case);
fn b32 s8_ends_with(s8_t a, s8_t end);
fn b32 s8_starts_with(s8_t a, s8_t start);
fn b32 s8_is_pointer_inside(s8_t string, char *p);// @todo: maybe more general?
//
// search
fn b32 s8_seek(s8_t string, s8_t find, s8_seek_t flags, int64_t *index_out);
fn int64_t s8_find(s8_t string, s8_t find, s8_seek_t flag);
fn sb8_t s8_split(ma_arena_t *ma, s8_t string, s8_t find, s8_split_t flags);
//
// string view transforms
fn s8_t s8_slice(s8_t string, int64_t first_index, int64_t one_past_last_index);
fn s8_t s8_get_postfix(s8_t string, int64_t len);
fn s8_t s8_get_prefix(s8_t string, int64_t len);
fn s8_t s8_chop(s8_t string, int64_t len);
fn s8_t s8_skip(s8_t string, int64_t len);
fn s8_t s8_chop_last_slash(s8_t s);
fn s8_t s8_chop_last_period(s8_t s);
fn s8_t s8_skip_to_last_slash(s8_t s);
fn s8_t s8_skip_to_last_period(s8_t s);
fn s8_t s8_get_name_no_ext(s8_t s);
fn s8_t s8_trim(s8_t string);
fn s8_t s8_trim_end(s8_t string);
fn s8_t s8_cut_start(s8_t *in, i64 size);
fn s8_t s8_cut_end(s8_t *in, i64 size);
//
// formatting
fn void s8_normalize_path_unsafe(s8_t s);
fn s8_t s8_normalize_path(ma_arena_t *ma, s8_t s);
fn s8_t s8_to_lower_case(ma_arena_t *ma, s8_t s);
fn s8_t s8_to_upper_case(ma_arena_t *ma, s8_t s);
fn s8_t s8_vfmt(ma_arena_t *ma, const char *str, va_list args1);
fn s8_t s8_printf(ma_arena_t *ma, const char *str, ...);
//
// string builder
#define sb8(ARENA) &(sb8_t){.arena = arena}
#define sb8_serial_begin(ARENA) &(sb8_t){.arena = ARENA}
#define sb8_serial_end(ARENA, SB) sb8_merge(ARENA, SB)
fn s8_t sb8_printf(sb8_t *sb, const char *str, ...);
fn sb8_node_t *sb8_append(sb8_t *list, s8_t string);
fn sb8_node_t *sb8_create_node(ma_arena_t *ma, s8_t str);
fn s8_t sb8_merge(ma_arena_t *arena, sb8_t *sb);
fn void sb8_indent(sb8_t *sb);
fn s8_t sb8_stmtf(sb8_t *sb, const char *str, ...);
fn int64_t sb8_char_size(sb8_t *sb);
#if 0
sb8_t *sbin_write_begin(ma_arena_t *arena);
s8_t sbin_write_end(sb8_t *sb);
void *sbin_write_data(sb8_t *sb, void *p, i64 size);
void *sbin_write_size(sb8_t *sb, i64 size);
void *sbin_write_u64(sb8_t *sb, u64 value);
void *sbin_write_u32(sb8_t *sb, u32 value);
void *sbin_write_u16(sb8_t *sb, u16 value);
void *sbin_write_u8(sb8_t *sb, u8 value);
s8_t *sbin_write_s8(sb8_t *sb, s8_t string);
char *sbin_write_str(sb8_t *sb, char *string);
stream_t sbin_read_begin(void *p, i64 size);
void sbin_read_end(stream_t *stream);
void *sbin_read_data(stream_t *stream, i64 size);
#endif
//
// other
#define s8_fmtspec(string) (int)(string).len, (string).str
#define S8_CODE(...) s8(#__VA_ARGS__)
#define S8_FILE s8(__FILE__)
#define S8_FILE_AND_LINE s8(FILE_AND_LINE)
#define S8_FMT(ma, str, result) \
va_list args1; \
va_start(args1, str); \
s8_t result = s8_vfmt(ma, str, args1); \
va_end(args1)
#if PLATFORM_TCC
#define s8_vsnprintf vsnprintf
#else
#define s8_vsnprintf stbsp_vsnprintf
#endif
#define STR_FMT(buff, str) \
va_list args1; \
va_start(args1, str); \
i32 len = s8_vsnprintf(buff, sizeof(buff), str, args1); \
va_end(args1)
typedef struct fuzzy_pair_t fuzzy_pair_t;
struct fuzzy_pair_t {
i64 index;
i64 rating;
};
-622
View File
@@ -1,622 +0,0 @@
#include "core_string16.h"
#include "core_platform.h"
#include "core_intrin.h"
#include "core_unicode.h"
#include "core_ctx.h"
fn i64 str16_len(u16 *string) {
i64 len = 0;
while (*string++ != 0)
len++;
return len;
}
fn u16 char16_to_lower_case(u16 a) {
if (a >= 'A' && a <= 'Z') a += 32;
return a;
}
fn u16 char16_to_upper_case(u16 a) {
if (a >= 'a' && a <= 'z') a -= 32;
return a;
}
fn b32 char16_is_whitespace(u16 w) {
b32 result = w == '\n' || w == ' ' || w == '\t' || w == '\v' || w == '\r';
return result;
}
fn b32 char16_is_alphabetic(u16 a) {
b32 result = (a >= 'a' && a <= 'z') || (a >= 'A' && a <= 'Z');
return result;
}
fn b32 char16_is_ident(u16 a) {
b32 result = (a >= 'a' && a <= 'z') || (a >= 'A' && a <= 'Z') || a == '_';
return result;
}
fn b32 char16_is_digit(u16 a) {
b32 result = a >= '0' && a <= '9';
return result;
}
fn b32 char16_is_symbol(u16 w) {
b32 result = (w >= '!' && w <= '/') || (w >= ':' && w <= '@') || (w >= '[' && w <= '`') || (w >= '{' && w <= '~');
return result;
}
fn b32 char16_is_non_word(u16 w) {
b32 result = w != '_' && (char16_is_symbol(w) || char16_is_whitespace(w));
return result;
}
fn b32 char16_is_word(u16 w) {
b32 result = !char16_is_non_word(w);
return result;
}
fn b32 char16_is_alphanumeric(u16 a) {
b32 result = char16_is_digit(a) || char16_is_alphabetic(a);
return result;
}
fn s16_t s16_from_range(u16 *begin, u16 *end) {
assert_expr(end >= begin);
intptr_t size = (intptr_t)end - (intptr_t)begin;
s16_t result = {begin, size / 2};
return result;
}
fn s16_t s16_from_str16(u16 *string) {
s16_t result;
result.str = string;
result.len = str16_len(string);
return result;
}
fn s16_t s16_copy(ma_arena_t *ma, s16_t string) {
i64 byte_size = sizeof(u16) * string.len;
u16 *copy = (u16 *)ma_push_size(ma, byte_size + sizeof(u16));
memory_copy(copy, string.str, byte_size);
copy[string.len] = 0;
s16_t result = s16_make(copy, string.len);
return result;
}
fn s16_t s16_copy_str16(ma_arena_t *ma, u16 *s) {
return s16_copy(ma, s16_make(s, str16_len(s)));
}
fn b32 s16_are_equal_ex(s16_t a, s16_t b, b32 ignore_case) {
if (a.len != b.len) return false;
for (i64 i = 0; i < a.len; i++) {
u16 A = a.str[i];
u16 B = b.str[i];
if (ignore_case) {
A = char16_to_lower_case(A);
B = char16_to_lower_case(B);
}
if (A != B)
return false;
}
return true;
}
fn b32 s16_are_equal(s16_t a, s16_t b) {
return s16_are_equal_ex(a, b, false);
}
fn s16_t s16_from_s8(ma_arena_t *ma, s8_t string) {
u16 *buffer = ma_push_array(ma, u16, string.len + 1);
i64 len = wstr_from_str(buffer, string.len + 1, string.str, string.len);
assert(len <= string.len); // @todo: verify
return (s16_t){buffer, len};
}
fn s8_t s8_from_s16(ma_arena_t *ma, s16_t string) {
i64 buffer_size = (string.len + 1) * 2;
char *buffer = ma_push_array(ma, char, buffer_size);
i64 len = str_from_wstr(buffer, buffer_size, string.str, string.len);
assert(len < buffer_size);
return (s8_t){buffer, len};
}
fn s16_t s16_get_postfix(s16_t string, i64 len) {
len = CLAMP_TOP(len, string.len);
i64 remain_len = string.len - len;
s16_t result = s16_make(string.str + remain_len, len);
return result;
}
fn s16_t s16_get_prefix(s16_t string, i64 len) {
len = CLAMP_TOP(len, string.len);
s16_t result = s16_make(string.str, len);
return result;
}
fn s16_t s16_chop(s16_t string, i64 len) {
len = CLAMP_TOP(len, string.len);
s16_t result = s16_make(string.str, string.len - len);
return result;
}
fn s16_t s16_skip(s16_t string, i64 len) {
len = CLAMP_TOP(len, string.len);
i64 remain = string.len - len;
s16_t result = s16_make(string.str + len, remain);
return result;
}
fn b32 s16_ends_with_ex(s16_t a, s16_t end, b32 ignore_case) {
s16_t a_end = s16_get_postfix(a, end.len);
b32 result = s16_are_equal_ex(end, a_end, ignore_case);
return result;
}
fn b32 s16_starts_with_ex(s16_t a, s16_t start, b32 ignore_case) {
s16_t a_start = s16_get_prefix(a, start.len);
b32 result = s16_are_equal_ex(start, a_start, ignore_case);
return result;
}
fn b32 s16_ends_with(s16_t a, s16_t end) {
return s16_ends_with_ex(a, end, false);
}
fn b32 s16_starts_with(s16_t a, s16_t start) {
return s16_ends_with_ex(a, start, false);
}
fn void s16_normalize_path_unsafe(s16_t s) {
for (i64 i = 0; i < s.len; i++) {
if (s.str[i] == '\\')
s.str[i] = '/';
}
}
fn s16_t s16_normalize_path(ma_arena_t *ma, s16_t s) {
s16_t copy = s16_copy(ma, s);
s16_normalize_path_unsafe(copy);
return copy;
}
fn b32 s16_is_pointer_inside(s16_t string, u16 *p) {
uintptr_t pointer = (uintptr_t)p;
uintptr_t start = (uintptr_t)string.str;
uintptr_t stop = start + (uintptr_t)string.len * sizeof(u16);
b32 result = pointer >= start && pointer < stop;
return result;
}
fn s16_t s16_cut_start(s16_t *in, i64 size) {
s16_t result = s16_get_prefix(*in, size);
*in = s16_skip(*in, result.len);
return result;
}
fn s16_t s16_cut_end(s16_t *in, i64 size) {
s16_t result = s16_get_postfix(*in, size);
*in = s16_chop(*in, result.len);
return result;
}
fn s16_t s16_slice(s16_t string, i64 first_index, i64 one_past_last_index) {
if (one_past_last_index < 0) one_past_last_index = string.len + one_past_last_index + 1;
if (first_index < 0) first_index = string.len + first_index;
assert(first_index < one_past_last_index);
assert(string.len > 0);
s16_t result = string;
if (string.len > 0) {
if (one_past_last_index > first_index) {
first_index = CLAMP_TOP(first_index, string.len - 1);
one_past_last_index = CLAMP_TOP(one_past_last_index, string.len);
result.str += first_index;
result.len = one_past_last_index - first_index;
}
else {
result.len = 0;
}
}
return result;
}
fn s16_t s16_trim(s16_t string) {
if (string.len == 0)
return string;
i64 whitespace_begin = 0;
for (; whitespace_begin < string.len; whitespace_begin++) {
if (!char16_is_whitespace(string.str[whitespace_begin])) {
break;
}
}
i64 whitespace_end = string.len;
for (; whitespace_end != whitespace_begin; whitespace_end--) {
if (!char16_is_whitespace(string.str[whitespace_end - 1])) {
break;
}
}
if (whitespace_begin == whitespace_end) {
string.len = 0;
}
else {
string = s16_slice(string, whitespace_begin, whitespace_end);
}
return string;
}
fn s16_t s16_trim_end(s16_t string) {
i64 whitespace_end = string.len;
for (; whitespace_end != 0; whitespace_end--) {
if (!char16_is_whitespace(string.str[whitespace_end - 1])) {
break;
}
}
s16_t result = s16_get_prefix(string, whitespace_end);
return result;
}
fn b32 s16_seek(s16_t string, s16_t find, s16_seek_t flags, int64_t *index_out) {
b32 ignore_case = flags & s16_seek_ignore_case ? true : false;
b32 result = false;
if (flags & s16_seek_match_find_last) {
for (int64_t i = string.len; i != 0; i--) {
int64_t index = i - 1;
s16_t substring = s16_slice(string, index, index + find.len);
if (s16_are_equal_ex(substring, find, ignore_case)) {
if (index_out)
*index_out = index;
result = true;
break;
}
}
}
else {
for (int64_t i = 0; i < string.len; i++) {
s16_t substring = s16_slice(string, i, i + find.len);
if (s16_are_equal_ex(substring, find, ignore_case)) {
if (index_out)
*index_out = i;
result = true;
break;
}
}
}
return result;
}
fn int64_t s16_find(s16_t string, s16_t find, s16_seek_t flag) {
int64_t result = -1;
s16_seek(string, find, flag, &result);
return result;
}
fn s16_t s16_chop_last_char(s16_t s, s16_t ch) {
s16_t result = s;
s16_seek(s, ch, s16_seek_match_find_last, &result.len);
return result;
}
// fn s16_t s16_chop_last_slash(s16_t s) {
// return s16_chop_last_char(s, s16("/"));
// }
// fn s16_t s16_chop_last_period(s16_t s) {
// return s16_chop_last_char(s, s16("."));
// }
fn s16_t s16_skip_to_last_char(s16_t s, s16_t ch) {
int64_t pos;
s16_t result = s;
if (s16_seek(s, ch, s16_seek_match_find_last, &pos)) {
result = s16_skip(result, pos + 1);
}
return result;
}
// fn s16_t s16_skip_to_last_slash(s16_t s) {
// return s16_skip_to_last_char(s, s16("/"));
// }
// fn s16_t s16_skip_to_last_period(s16_t s) {
// return s16_skip_to_last_char(s, s16("."));
// }
// fn s16_t s16_get_name_no_ext(s16_t s) {
// return s16_skip_to_last_slash(s16_chop_last_period(s));
// }
fn s16_t s16_to_lower_case(ma_arena_t *ma, s16_t s) {
s16_t copy = s16_copy(ma, s);
for (int64_t i = 0; i < copy.len; i++) {
copy.str[i] = char16_to_lower_case(copy.str[i]);
}
return copy;
}
fn s16_t s16_to_upper_case(ma_arena_t *ma, s16_t s) {
s16_t copy = s16_copy(ma, s);
for (int64_t i = 0; i < copy.len; i++) {
copy.str[i] = char16_to_upper_case(copy.str[i]);
}
return copy;
}
fn s16_t s16_printf(ma_arena_t *ma, const char *str, ...) {
ma_temp_t scratch = ma_begin_scratch1(ma);
S8_FMT(scratch.arena, str, result);
s16_t result16 = s16_from_s8(ma, result);
ma_end_scratch(scratch);
return result16;
}
fn u64 u64_from_s16(s16_t s, u64 base) {
assert(base >= 2 && base <= 16);
u64 acc = 0;
for (i64 i = 0; i < s.len; i++) {
u64 num = u64_from_hexchar((char)s.str[i]);
assert(num < base);
acc *= base;
acc += num;
}
return acc;
}
fn f64 f64_from_s16(s16_t string) {
ma_temp_t scratch = ma_begin_scratch();
s8_t num_string = s8_from_s16(scratch.arena, string);
f64 result = os_parse_float(num_string.str);
ma_end_scratch(scratch);
return result;
}
gb_read_only i64 s16_fuzzy_closer_word_begin = 5;
gb_read_only i64 s16_fuzzy_consecutive_multiplier = 3;
fn i64 s16_fuzzy_rate(s16_t string, s16_t with) {
if (with.len == 0) return 0;
i64 points = 0;
i64 consecutive = 0;
i64 with_i = 0;
for (i64 i = 0; i < string.len; i++) {
if (string.str[i] == with.str[with_i]) {
i64 closer_begin = CLAMP_BOT((i64)0, s16_fuzzy_closer_word_begin - i);
points += closer_begin;
consecutive++;
with_i += 1;
} else {
points += consecutive * s16_fuzzy_consecutive_multiplier;
consecutive = 0;
with_i = 0;
}
if (with_i >= with.len) with_i = 0;
}
points += consecutive * s16_fuzzy_consecutive_multiplier;
return points;
}
fn fuzzy_pair_t *s16_fuzzy_rate_array(ma_arena_t *arena, s16_t needle, s16_t *array, i32 len) {
fuzzy_pair_t *pairs = ma_push_array(arena, fuzzy_pair_t, len);
for (i32 i = 0; i < len; i += 1) {
pairs[i].rating = s16_fuzzy_rate(array[i], needle);
pairs[i].index = i;
}
for (i32 i = 0; i < len - 1; i++) {
for (i32 j = 0; j < len - 1; j++) {
if (pairs[j].rating < pairs[j + 1].rating) {
SWAP(fuzzy_pair_t, pairs[j], pairs[j + 1]);
}
}
}
return pairs;
}
fn sb16_node_t *sb16_create_node(ma_arena_t *ma, s16_t str) {
sb16_node_t *node = ma_push_type(ma, sb16_node_t);
node->string = str;
return node;
}
fn sb16_node_t *sb16_append(sb16_t *list, s16_t string) {
assert(list->arena != NULL);
sb16_node_t *node = sb16_create_node(list->arena, string);
SLLQ_APPEND(list->first, list->last, node);
return node;
}
fn s16_t sb16_printf(sb16_t *sb, const char *str, ...) {
ma_temp_t scratch = ma_begin_scratch1(sb->arena);
S8_FMT(scratch.arena, str, result);
s16_t result16 = s16_from_s8(sb->arena, result);
sb16_append(sb, result16);
ma_end_scratch(scratch);
return result16;
}
fn void sb16_indent(sb16_t *sb) {
sb16_printf(sb, "\n%.*s", sb->indent*4, " ");
}
fn s16_t sb16_stmtf(sb16_t *sb, const char *str, ...) {
ma_temp_t scratch = ma_begin_scratch1(sb->arena);
S8_FMT(scratch.arena, str, result);
s16_t result16 = s16_from_s8(sb->arena, result);
sb16_indent(sb);
sb16_append(sb, result16);
ma_end_scratch(scratch);
return result16;
}
fn int64_t sb16_char_size(sb16_t *sb) {
int64_t result = 0;
for (sb16_node_t *it = sb->first; it; it = it->next) {
result += it->len;
}
return result;
}
fn s16_t sb16_merge(ma_arena_t *arena, sb16_t *sb) {
int64_t size = sb16_char_size(sb) + 1;
i64 byte_size = size * sizeof(u16);
u16 *str = ma_push_size(arena, byte_size);
s16_t result = {str, 0};
for (sb16_node_t *it = sb->first; it; it = it->next) {
memory_copy(result.str + result.len, it->str, it->len * sizeof(u16));
result.len += it->len;
}
result.str[result.len] = 0;
return result;
}
fn sb16_t s16_split(ma_arena_t *ma, s16_t string, s16_t find, s16_split_t flags) {
sb16_t result = (sb16_t){ma};
int64_t index = 0;
s16_seek_t find_flag = flags & s16_split_ignore_case ? s16_seek_ignore_case : s16_seek_none;
while (s16_seek(string, find, find_flag, &index)) {
s16_t before_match = s16_make(string.str, index);
sb16_append(&result, before_match);
if (flags & s16_split_inclusive) {
s16_t match = s16_make(string.str + index, find.len);
sb16_append(&result, match);
}
string = s16_skip(string, index + find.len);
}
if (string.len) sb16_append(&result, string);
return result;
}
fn s16_t s16_copy_ex(alo_t ma, s16_t string) {
i64 byte_size = sizeof(u16) * string.len;
u16 *copy = (u16 *)alloc_size(ma, byte_size + sizeof(u16));
memory_copy(copy, string.str, byte_size);
copy[string.len] = 0;
s16_t result = s16_make(copy, string.len);
return result;
}
#if 0
fn_test void test_string16(void) {
ma_temp_t scratch = ma_begin_scratch();
// string16 lit basic tests
{
s16_t a = s16("memes");
assert(a.len == 5);
assert(a.str[0] == char16('m'));
assert(a.str[4] == char16('s'));
s16_t b = s16("not memes");
s16_t c = s16("MEMES");
assert(s16_are_equal(a, b) == false);
assert(s16_are_equal(a, a) == true);
assert(s16_are_equal_ex(a, c, true) == true);
}
{
assert(char16_to_upper_case('a') == char16('A'));
assert(char16_to_upper_case('a') == 'A');
assert(char16_to_upper_case(char16('a')) == 'A');
assert(char16_is_digit('3'));
}
{
s16_t a = s16_from_str16(str16("memes"));
assert(a.len == 5);
assert(s16_are_equal(a, s16("memes")) == true);
s16_t b = s16_copy(scratch.arena, a);
assert(a.str != b.str);
assert(b.len == a.len);
assert(s16_are_equal(a, b));
s16_t c = s16_from_range(a.str, a.str + a.len);
assert(s16_are_equal(a, c));
}
{
s16_t a = s16("thing itself");
assert(s16_starts_with_ex(a, s16("thing"), false));
assert(!s16_starts_with_ex(a, s16("thing itself and"), false));
assert(!s16_starts_with_ex(a, s16("thing itself "), false));
assert(s16_starts_with_ex(a, s16("THING"), true));
assert(!s16_starts_with_ex(a, s16("a"), false));
assert(s16_ends_with_ex(a, s16("itself"), false));
assert(s16_ends_with_ex(a, s16("thing itself"), false));
assert(!s16_ends_with_ex(a, s16("thing itselfa"), false));
s16_t b = s16("memes");
assert(s16_is_pointer_inside(b, b.str));
assert(s16_is_pointer_inside(b, b.str + 4));
assert(!s16_is_pointer_inside(b, b.str + 5));
}
{
s16_t a = s16("C:\\Program Files\\Memes");
u16 memes[256] = {0};
memory_copy(memes, a.str, a.len * 2 + 2);
s16_t b = s16_make(memes, a.len);
s16_normalize_path_unsafe(b);
assert(b.str[2] == '/');
}
{
s16_t a = s16(" thing ");
s16_t b = s16_trim(a);
assert(s16_are_equal(b, s16("thing")));
}
{
s16_t a = s16_printf(scratch.arena, "%d", 432);
assert(s16_are_equal(a, s16("432")));
assert(f64_from_s16(s16("432.0")) == 432.0);
assert(u64_from_s16(s16("432"), 10) == 432);
}
{
sb16_t *list = sb16_serial_begin(scratch.arena);
sb16_printf(list, "%d ", 987);
sb16_printf(list, "ter ");
sb16_printf(list, "|");
s16_t string = sb16_serial_end(scratch.arena, list);
assert(s16_are_equal(string, s16("987 ter |")));
}
{
s16_t a = s16("A|B|dek|mek|vek|");
sb16_t b = s16_split(scratch.arena, a, s16("|"), s16_split_none);
assert(s16_are_equal(b.first->string, s16("A")));
assert(s16_are_equal(b.first->next->string, s16("B")));
assert(s16_are_equal(b.first->next->next->string, s16("dek")));
assert(s16_are_equal(b.first->next->next->next->string, s16("mek")));
assert(s16_are_equal(b.first->next->next->next->next->string, s16("vek")));
assert(b.first->next->next->next->next->next == NULL);
}
{
s16_t a = s16_to_upper_case(scratch.arena, s16("thing Meme"));
assert(s16_are_equal(a, s16("THING MEME")));
a = s16_to_lower_case(scratch.arena, s16("THING Meme"));
assert(s16_are_equal(a, s16("thing meme")));
}
{
s16_t a = s16("C:/thing/itself");
assert(s16_are_equal(s16_chop_last_slash(a), s16("C:/thing")));
}
ma_end_scratch(scratch);
}
#endif
-128
View File
@@ -1,128 +0,0 @@
#pragma once
#include "core_basic.h"
#include "core_arena.h"
#include "core_string.h"
typedef struct s16_t s16_t;
struct s16_t {
u16 *str;
i64 len;
};
typedef struct sb16_node_t sb16_node_t;
struct sb16_node_t {
sb16_node_t *next;
union {
struct { u16 *str; int64_t len; };
s16_t string;
};
};
typedef struct sb16_t sb16_t;
struct sb16_t {
ma_arena_t *arena;
sb16_node_t *first;
sb16_node_t *last;
// WARNING: remember to update typeinfo after editing this
i32 indent;
};
typedef i32 s16_seek_t;
enum {
s16_seek_none = 0,
s16_seek_ignore_case = 1,
s16_seek_match_find_last = 2,
};
typedef i32 s16_split_t;
enum {
s16_split_none = 0,
s16_split_ignore_case = 1,
s16_split_inclusive = 2,
};
enum { s16_ignore_case = 1 };
typedef struct s32_t s32_t;
struct s32_t {
u32 *str;
i64 len;
};
#define s16_make(str,len) (s16_t){str, len}
#define s16(str) (s16_t){(u16 *)u##str, lengthof(str) - 1}
#define s16_const(string) { (u16 *)u##string, lengthof(string) - 1 }
#define s16_invalid s16_lit("<INVALID>")
#define s16_null (s16_t){0}
#define str16(str) ((u16 *)u##str)
#define char16(str) ((u16)u##str)
#define sb16(ARENA) &(sb16_t){.arena = arena}
#define sb16_serial_begin(ARENA) &(sb16_t){.arena = ARENA}
#define sb16_serial_end(ARENA, SB) sb16_merge(ARENA, SB)
fn i64 str16_len(u16 *string);
fn u16 char16_to_lower_case(u16 a);
fn u16 char16_to_upper_case(u16 a);
fn b32 char16_is_whitespace(u16 w);
fn b32 char16_is_alphabetic(u16 a);
fn b32 char16_is_ident(u16 a);
fn b32 char16_is_digit(u16 a);
fn b32 char16_is_symbol(u16 w);
fn b32 char16_is_non_word(u16 w);
fn b32 char16_is_word(u16 w);
fn b32 char16_is_alphanumeric(u16 a);
fn s16_t s16_from_range(u16 *begin, u16 *end);
fn s16_t s16_from_str16(u16 *string);
fn s16_t s16_copy(ma_arena_t *ma, s16_t string);
fn s16_t s16_copy_str16(ma_arena_t *ma, u16 *s);
fn b32 s16_are_equal_ex(s16_t a, s16_t b, b32 ignore_case);
fn b32 s16_are_equal(s16_t a, s16_t b);
fn s16_t s16_from_s8(ma_arena_t *ma, s8_t string);
fn s8_t s8_from_s16(ma_arena_t *ma, s16_t string);
fn s16_t s16_get_postfix(s16_t string, i64 len);
fn s16_t s16_get_prefix(s16_t string, i64 len);
fn s16_t s16_chop(s16_t string, i64 len);
fn s16_t s16_skip(s16_t string, i64 len);
fn b32 s16_ends_with_ex(s16_t a, s16_t end, b32 ignore_case);
fn b32 s16_starts_with_ex(s16_t a, s16_t start, b32 ignore_case);
fn b32 s16_ends_with(s16_t a, s16_t end);
fn b32 s16_starts_with(s16_t a, s16_t start);
fn void s16_normalize_path_unsafe(s16_t s);
fn s16_t s16_normalize_path(ma_arena_t *ma, s16_t s);
fn b32 s16_is_pointer_inside(s16_t string, u16 *p);
fn s16_t s16_cut_start(s16_t *in, i64 size);
fn s16_t s16_cut_end(s16_t *in, i64 size);
fn s16_t s16_slice(s16_t string, i64 first_index, i64 one_past_last_index);
fn s16_t s16_trim(s16_t string);
fn s16_t s16_trim_end(s16_t string);
fn b32 s16_seek(s16_t string, s16_t find, s16_seek_t flags, int64_t *index_out);
fn int64_t s16_find(s16_t string, s16_t find, s16_seek_t flag);
fn s16_t s16_chop_last_char(s16_t s, s16_t ch);
fn s16_t s16_chop_last_slash(s16_t s);
fn s16_t s16_chop_last_period(s16_t s);
fn s16_t s16_skip_to_last_char(s16_t s, s16_t ch);
fn s16_t s16_skip_to_last_slash(s16_t s);
fn s16_t s16_skip_to_last_period(s16_t s);
fn s16_t s16_get_name_no_ext(s16_t s);
fn s16_t s16_to_lower_case(ma_arena_t *ma, s16_t s);
fn s16_t s16_to_upper_case(ma_arena_t *ma, s16_t s);
fn s16_t s16_printf(ma_arena_t *ma, const char *str, ...);
fn u64 u64_from_s16(s16_t s, u64 base);
fn f64 f64_from_s16(s16_t string);
fn i64 s16_fuzzy_rate(s16_t string, s16_t with);
fn fuzzy_pair_t *s16_fuzzy_rate_array(ma_arena_t *arena, s16_t needle, s16_t *array, i32 len);
fn sb16_node_t *sb16_create_node(ma_arena_t *ma, s16_t str);
fn sb16_node_t *sb16_append(sb16_t *list, s16_t string);
fn s16_t sb16_printf(sb16_t *sb, const char *str, ...);
fn void sb16_indent(sb16_t *sb);
fn s16_t sb16_stmtf(sb16_t *sb, const char *str, ...);
fn int64_t sb16_char_size(sb16_t *sb);
fn s16_t sb16_merge(ma_arena_t *arena, sb16_t *sb);
fn sb16_t s16_split(ma_arena_t *ma, s16_t string, s16_t find, s16_split_t flags);
fn s16_t s16_copy_ex(alo_t ma, s16_t string);
fn_test void test_string16(void);
-466
View File
@@ -1,466 +0,0 @@
#include "core_type_info.h"
#include "core_platform.h"
#include "core_log.h"
#include "core_lexer.h"
fn s8_t ti_enum_value_to_name(i64 value, type_t *type) {
assert(type->kind == type_kind_enum);
for (i32 i = 0; i < type->count; i += 1) {
type_member_t *it = type->members + i;
if (value == it->value) {
return it->name;
}
}
return s8("invalid");
}
fn i64 ti_enum_name_to_value(s8_t name, type_t *type) {
assert(type->kind == type_kind_enum);
for (i32 i = 0; i < type->count; i += 1) {
type_member_t *it = type->members + i;
if (s8_are_equal(it->name, name)) {
return it->value;
}
}
return -1;
}
fn i64 ti_enum_read_value(void *p, type_t *type) {
assert(type->kind == type_kind_enum);
i64 value = 0;
if (type->size == 1) {
value = *(i8 *)p;
} else if (type->size == 2) {
value = *(i16 *)p;
} else if (type->size == 4) {
value = *(i32 *)p;
} else if (type->size == 8) {
value = *(i64 *)p;
} else {
fatalf("invalid size of enum: %d", type->size);
}
return value;
}
fn void ti_enum_write_value(void *p, i64 value, type_t *type) {
assert(type->kind == type_kind_enum);
if (type->size == 1) {
*(i8 *)p = (i8)value;
} else if (type->size == 2) {
*(i16 *)p = (i16)value;
} else if (type->size == 4) {
*(i32 *)p = (i32)value;
} else if (type->size == 8) {
*(i64 *)p = (i64)value;
} else {
fatalf("invalid size of enum: %d", type->size);
}
}
fn i64 ti_enum_next_value(i64 value, type_t *type) {
assert(type->kind == type_kind_enum);
i32 next_i = 0;
for (i32 i = 0; i < type->count; i += 1) {
type_member_t *it = type->members + i;
if (value == it->value) {
if (i + 1 < type->count) {
next_i = i + 1;
break;
}
}
}
type_member_t *tm = type->members + next_i;
return tm->value;
}
fn type_member_t *ti_get_member(s8_t name, type_t *type) {
for (i32 i = 0; i < type->count; i += 1) {
type_member_t *it = type->members + i;
if (s8_are_equal(it->name, name)) {
return it;
}
}
return NULL;
}
fn void *ti_extract_member(void *p, type_member_t *tm) {
u8 *p8 = (u8 *)p;
u8 *result = p8 + tm->offset;
return result;
}
fn void *ti_extract_array_idx(void *p, type_t *type, i32 idx) {
assert(idx < type->count);
u8 *p8 = (u8 *)p;
u8 *result = p8 + type->base->size * idx;
return result;
}
fn void ti__serial_data_ex(sb8_t *sb, void *p, type_t *type) {
assert(type->kind != type_kind_invalid);
switch(type->kind) {
case type_kind_i8: {
i8 n = *(i8 *)p;
sb8_printf(sb, "%d", n);
return;
} break;
case type_kind_i16: {
i16 n = *(i16 *)p;
sb8_printf(sb, "%d", n);
return;
} break;
case type_kind_i32: {
i32 n = *(i32 *)p;
sb8_printf(sb, "%d", n);
return;
} break;
case type_kind_i64: {
i64 n = *(i64 *)p;
sb8_printf(sb, "%lld", (long long)n);
return;
} break;
case type_kind_u8: {
u8 n = *(u8 *)p;
sb8_printf(sb, "%u", n);
return;
} break;
case type_kind_u16: {
u16 n = *(u16 *)p;
sb8_printf(sb, "%u", n);
return;
} break;
case type_kind_u32: {
u32 n = *(u32 *)p;
sb8_printf(sb, "%u", n);
return;
} break;
case type_kind_u64: {
u64 n = *(u64 *)p;
sb8_printf(sb, "%llu", (unsigned long long)n);
return;
} break;
case type_kind_b8: {
b8 n = *(b8 *)p;
sb8_printf(sb, "%d", n);
return;
} break;
case type_kind_b16: {
b16 n = *(b16 *)p;
sb8_printf(sb, "%d", n);
return;
} break;
case type_kind_b32: {
b32 n = *(b32 *)p;
sb8_printf(sb, "%d", n);
return;
} break;
case type_kind_b64: {
b64 n = *(b64 *)p;
sb8_printf(sb, "%lld", (long long)n);
return;
} break;
case type_kind_f32: {
f32 n = *(f32 *)p;
sb8_printf(sb, "%f", n);
return;
} break;
case type_kind_f64: {
f64 n = *(f64 *)p;
sb8_printf(sb, "%f", n);
return;
} break;
case type_kind_isize: {
isize n = *(isize *)p;
sb8_printf(sb, "%lld", (long long)n);
return;
} break;
case type_kind_usize: {
usize n = *(usize *)p;
sb8_printf(sb, "%llu", (unsigned long long)n);
return;
} break;
case type_kind_int: {
int n = *(int *)p;
sb8_printf(sb, "%d", n);
return;
} break;
case type_kind_char: {
char n = *(char *)p;
sb8_printf(sb, "%c", n);
return;
} break;
}
if (type == &type__s8_t) {
s8_t n = *(s8_t *)p;
sb8_printf(sb, "\"%.*s\"", s8_fmtspec(n));
return;
}
if (type->kind == type_kind_pointer) {
sb8_printf(sb, "0x%x", p);
return;
}
if (type->kind == type_kind_enum) {
i64 value = ti_enum_read_value(p, type);
s8_t s = ti_enum_value_to_name(value, type);
sb8_append(sb, s);
return;
}
if (type->kind == type_kind_array) {
sb8_printf(sb, "{");
sb->indent += 1;
for (i32 i = 0; i < type->count; i += 1) {
void *mem_p = ti_extract_array_idx(p, type, i);
sb8_indent(sb);
ti__serial_data_ex(sb, mem_p, type->base);
sb8_printf(sb, ",");
}
sb->indent -= 1;
sb8_stmtf(sb, "}");
return;
}
if (type->kind == type_kind_struct) {
sb8_printf(sb, "{");
sb->indent += 1;
for (i32 i = 0; i < type->count; i += 1) {
type_member_t *mem = type->members + i;
void *mem_p = ti_extract_member(p, mem);
sb8_indent(sb);
sb8_printf(sb, "%.*s: ", s8_fmtspec(mem->name));
ti__serial_data_ex(sb, mem_p, mem->type);
sb8_printf(sb, ",");
}
sb->indent -= 1;
sb8_stmtf(sb, "}");
return;
}
fatalf("can't serialize: unhandled type");
}
fn s8_t ti__serial_data(ma_arena_t *arena, void *p, type_t *type) {
ma_temp_t scratch = ma_begin_scratch1(arena);
sb8_t *sb = sb8_serial_begin(scratch.arena);
ti__serial_data_ex(sb, p, type);
s8_t string = sb8_serial_end(arena, sb);
ma_end_scratch(scratch);
return string;
}
fn i64 ti__parser_match_i64(parser_t *par) {
i64 minus = 1;
if (parser_match(par, lex_kind_minus)) {
minus = -1;
}
lex_t *token = parser_expect(par, lex_kind_integer);
i64 result = (i64)token->integer * minus;
return result;
}
fn void ti__deserial_data_ex(ma_arena_t *arena, parser_t *par, void *p, type_t *type) {
switch(type->kind) {
case type_kind_i8: {
i8 *n = (i8 *)p;
n[0] = (i8)ti__parser_match_i64(par);
return;
} break;
case type_kind_i16: {
i16 *n = (i16 *)p;
n[0] = (i16)ti__parser_match_i64(par);
return;
} break;
case type_kind_i32: {
i32 *n = (i32 *)p;
n[0] = (i32)ti__parser_match_i64(par);
return;
} break;
case type_kind_i64: {
i64 *n = (i64 *)p;
n[0] = (i64)ti__parser_match_i64(par);
return;
} break;
case type_kind_b8: {
b8 *n = (b8 *)p;
n[0] = (b8)ti__parser_match_i64(par);
return;
} break;
case type_kind_b16: {
b16 *n = (b16 *)p;
n[0] = (b16)ti__parser_match_i64(par);
return;
} break;
case type_kind_b32: {
b32 *n = (b32 *)p;
n[0] = (b32)ti__parser_match_i64(par);
return;
} break;
case type_kind_b64: {
b64 *n = (b64 *)p;
n[0] = (b64)ti__parser_match_i64(par);
return;
} break;
case type_kind_u8: {
lex_t *token = parser_expect(par, lex_kind_integer);
u8 *n = (u8 *)p;
n[0] = (u8)token->integer;
return;
} break;
case type_kind_u16: {
lex_t *token = parser_expect(par, lex_kind_integer);
u16 *n = (u16 *)p;
n[0] = (u16)token->integer;
return;
} break;
case type_kind_u32: {
lex_t *token = parser_expect(par, lex_kind_integer);
u32 *n = (u32 *)p;
n[0] = (u32)token->integer;
return;
} break;
case type_kind_u64: {
lex_t *token = parser_expect(par, lex_kind_integer);
u64 *n = (u64 *)p;
n[0] = (u64)token->integer;
return;
} break;
case type_kind_f32: {
lex_t *token = parser_expect(par, lex_kind_real);
f32 *n = (f32 *)p;
n[0] = (f32)token->real;
return;
} break;
case type_kind_f64: {
lex_t *token = parser_expect(par, lex_kind_real);
f64 *n = (f64 *)p;
n[0] = token->real;
return;
} break;
case type_kind_isize: {
isize *n = (isize *)p;
n[0] = (isize)ti__parser_match_i64(par);
return;
} break;
case type_kind_usize: {
lex_t *token = parser_expect(par, lex_kind_integer);
usize *n = (usize *)p;
n[0] = (usize)token->integer;
return;
} break;
case type_kind_int: {
int *n = (int *)p;
n[0] = (int)ti__parser_match_i64(par);
return;
} break;
case type_kind_char: {
char *n = (char *)p;
n[0] = (char)ti__parser_match_i64(par);
return;
} break;
}
if (type == &type__s8_t) {
lex_t *token = parser_expect(par, lex_kind_string);
s8_t *n = (s8_t *)p;
n[0] = s8_copy(arena, token->string);
return;
}
if (type->kind == type_kind_enum) {
lex_t *token = parser_expect(par, lex_kind_ident);
i64 value = ti_enum_name_to_value(token->string, type);
if (value == -1) {
fatalf("invalid enum value: %.*s", s8_fmtspec(token->string));
}
ti_enum_write_value(p, value, type);
return;
}
if (type->kind == type_kind_struct) {
#if 0
parser_expect(par, lex_kind_open_brace);
while (!parser_match(par, lex_kind_close_brace)) {
lex_t *ident = parser_expect(par, lex_kind_ident);
parser_expect(par, lex_kind_colon);
type_member_t *mem = ti_get_member(type, ident->string);
if (mem) {
u8 *mem_p = p8 + mem->offset;
ti__deserial_data_ex(arena, par, mem_p, mem->type);
} else {
debugf("deserial - skipping field: %.*s", s8_fmtspec(ident->string));
parser_eat_until(par, lex_kind_comma);
}
parser_expect(par, lex_kind_comma);
}
#else // strict
parser_expect(par, lex_kind_open_brace);
for (i32 i = 0; i < type->count; i += 1) {
type_member_t *mem = type->members + i;
void *memp = ti_extract_member(p, mem);
lex_t *ident = parser_expect(par, lex_kind_ident);
parser_expect(par, lex_kind_colon);
expect (s8_are_equal(ident->string, mem->name)) fatalf("expected identifier: %.*s, got instead %.*s", s8_fmtspec(mem->name), s8_fmtspec(ident->string));
ti__deserial_data_ex(arena, par, memp, mem->type);
parser_expect(par, lex_kind_comma);
}
parser_expect(par, lex_kind_close_brace);
#endif
}
if (type->kind == type_kind_array) {
parser_expect(par, lex_kind_open_brace);
for (i32 i = 0; i < type->count; i += 1) {
void *memp = ti_extract_array_idx(p, type, i);
ti__deserial_data_ex(arena, par, memp, type->base);
parser_expect(par, lex_kind_comma);
}
parser_expect(par, lex_kind_close_brace);
}
}
fn void *ti__deserial_data(ma_arena_t *arena, s8_t data, type_t *type) {
void *p = ma_push_size(arena, type->size);
ma_temp_t scratch = ma_begin_scratch();
lex_array_t tokens = lex_tokens(scratch.arena, "data serializing", data);
parser_t *par = parser_make(scratch.arena, tokens.data);
ti__deserial_data_ex(arena, par, p, type);
ma_end_scratch(scratch);
return p;
}
fn b32 ti_is_basic(type_t *type) {
b32 result = type->kind >= type_kind_first_basic && type->kind <= type_kind_last_basic;
return result;
}
fn b32 ti_has_type_name(type_t *type) {
b32 result = ti_is_basic(type) || type->kind == type_kind_struct || type->kind == type_kind_enum || type->kind == type_kind_union;
return result;
}
fn s8_t ti_serial_type(ma_arena_t *arena, type_t *type) {
if (ti_has_type_name(type)) {
return type->name;
} else if (type->kind == type_kind_pointer) {
s8_t name = ti_serial_type(arena, type->base);
return s8_printf(arena, "%.*s*", s8_fmtspec(name));
} else if (type->kind == type_kind_array) {
s8_t name = ti_serial_type(arena, type->base);
return s8_printf(arena, "%.*s[%d]", s8_fmtspec(name), type->count);
} else_is_invalid;
return s8_invalid;
}
-364
View File
@@ -1,364 +0,0 @@
#pragma once
#include "core_basic.h"
#include "core_arena.h"
#include "core_string.h"
#include "core_string16.h"
#include "core_math.h"
typedef int type_kind_t;
enum {
type_kind_invalid,
type_kind_i8,
type_kind_i16,
type_kind_i32,
type_kind_i64,
type_kind_b8,
type_kind_b16,
type_kind_b32,
type_kind_b64,
type_kind_u8,
type_kind_u16,
type_kind_u32,
type_kind_u64,
type_kind_f32,
type_kind_f64,
type_kind_isize,
type_kind_usize,
type_kind_int,
type_kind_char,
type_kind_void,
type_kind_pointer,
type_kind_array,
type_kind_struct,
type_kind_union,
type_kind_enum,
type_kind_first_basic = type_kind_i8,
type_kind_last_basic = type_kind_void,
};
typedef struct type_t type_t;
struct type_t {
type_kind_t kind;
s8_t name;
i32 size;
i32 count;
struct type_member_t *members;
type_t *base;
};
typedef struct type_member_t type_member_t;
struct type_member_t {
s8_t name;
type_t *type;
i64 value;
u64 offset;
b8 dont_serialize;
};
typedef struct mt_tweak_t mt_tweak_t;
struct mt_tweak_t {
type_t *type;
s8_t name;
void *ptr;
f32 min, max;
};
#define mt_embed_file(name, path)
#define mt_tweak_f32(name, default, min, max)
#define mt_tweak_color(name, ...)
#define mt_tweak_b32(name, default)
//
// serialization to string
#define ti_deserial_data(ARENA, DATA, TYPE) (TYPE *)ti__deserial_data(ARENA, DATA, type(TYPE))
#define ti_serial_data(ARENA, DATA, TYPE) ti__serial_data(ARENA, DATA, type(TYPE))
fn void *ti__deserial_data(ma_arena_t *arena, s8_t data, type_t *type);
fn s8_t ti__serial_data(ma_arena_t *arena, void *p, type_t *type);
//
// utilities
fn s8_t ti_enum_value_to_name(i64 value, type_t *type);
fn i64 ti_enum_name_to_value(s8_t name, type_t *type);
fn type_member_t *ti_get_member(s8_t name, type_t *type);
//
// core type info data
#define type(X) (&type__##X)
#define DEFINE_ENUM(x) type_t type__##x = {type_kind_enum, s8_const(#x), sizeof(x), .members = members__##x, .count = lengthof(members__##x)}
#define DEFINE_STRUCT(x) type_t type__##x = {type_kind_struct, s8_const(#x), sizeof(x), .members = members__##x, .count = lengthof(members__##x)}
#define POINTER(x) (type_t){type_kind_pointer, s8_const(#x "*"), sizeof(void *), .base = &type__##x}
static gb_read_only type_t type__i8 = {type_kind_i8, s8_const("i8"), sizeof(i8)};
static gb_read_only type_t type__i16 = {type_kind_i16, s8_const("i16"), sizeof(i16)};
static gb_read_only type_t type__i32 = {type_kind_i32, s8_const("i32"), sizeof(i32)};
static gb_read_only type_t type__i64 = {type_kind_i64, s8_const("i64"), sizeof(i64)};
static gb_read_only type_t type__u8 = {type_kind_u8, s8_const("u8"), sizeof(u8)};
static gb_read_only type_t type__u16 = {type_kind_u16, s8_const("u16"), sizeof(u16)};
static gb_read_only type_t type__u32 = {type_kind_u32, s8_const("u32"), sizeof(u32)};
static gb_read_only type_t type__u64 = {type_kind_u64, s8_const("u64"), sizeof(u64)};
static gb_read_only type_t type__b8 = {type_kind_b8, s8_const("b8"), sizeof(b8)};
static gb_read_only type_t type__b16 = {type_kind_b16, s8_const("b16"), sizeof(b16)};
static gb_read_only type_t type__b32 = {type_kind_b32, s8_const("b32"), sizeof(b32)};
static gb_read_only type_t type__b64 = {type_kind_b64, s8_const("b64"), sizeof(b64)};
static gb_read_only type_t type__f32 = {type_kind_f32, s8_const("f32"), sizeof(f32)};
static gb_read_only type_t type__f64 = {type_kind_f64, s8_const("f64"), sizeof(f64)};
static gb_read_only type_t type__isize = {type_kind_isize, s8_const("isize"), sizeof(isize)};
static gb_read_only type_t type__usize = {type_kind_usize, s8_const("usize"), sizeof(usize)};
static gb_read_only type_t type__int = {type_kind_int, s8_const("int"), sizeof(int)};
static gb_read_only type_t type__char = {type_kind_char, s8_const("char"), sizeof(char)};
static gb_read_only type_t type__void = {type_kind_void, s8_const("void")};
static gb_read_only type_t type__s8_t = { type_kind_struct, s8_const("s8_t"), sizeof(s8_t), .count = 2,
.members = (type_member_t[]){
{s8_const("str"), &POINTER(char), .offset = offsetof(s8_t, str)},
{s8_const("len"), &type__i64, .offset = offsetof(s8_t, len)},
}
};
static gb_read_only type_t type__s16_t = { type_kind_struct, s8_const("s16_t"), sizeof(s16_t), .count = 2,
.members = (type_member_t[]){
{s8_const("str"), &POINTER(u16), .offset = offsetof(s16_t, str)},
{s8_const("len"), &type__i64, .offset = offsetof(s16_t, len)},
}
};
static gb_read_only type_t type__s32_t = { type_kind_struct, s8_const("s32_t"), sizeof(s32_t), .count = 2,
.members = (type_member_t[]){
{s8_const("str"), &POINTER(u32), .offset = offsetof(s32_t, str)},
{s8_const("len"), &type__i64, .offset = offsetof(s32_t, len)},
}
};
static gb_read_only type_t type__ma_arena_t = { type_kind_struct, s8_const("ma_arena_t"), sizeof(ma_arena_t), .count = 6,
.members = (type_member_t[]){
{s8_const("data"), &POINTER(u8), .offset = offsetof(ma_arena_t, data)},
{s8_const("len"), &type__usize, .offset = offsetof(ma_arena_t, len)},
{s8_const("base_len"), &type__usize, .offset = offsetof(ma_arena_t, base_len)},
{s8_const("reserve"), &type__usize, .offset = offsetof(ma_arena_t, reserve)},
{s8_const("commit"), &type__usize, .offset = offsetof(ma_arena_t, commit)},
{s8_const("align"), &type__usize, .offset = offsetof(ma_arena_t, align)},
}
};
static gb_read_only type_t type__sb8_node_t = {type_kind_struct, s8_const("sb8_node_t"), sizeof(sb8_t), .count = 2,
.members = (type_member_t[]){
{s8_const("next"), &POINTER(sb8_node_t), .offset = offsetof(sb8_node_t, next)},
{s8_const("string"), &type__s8_t, .offset = offsetof(sb8_node_t, string)},
}
};
static gb_read_only type_t type__sb8_t = { type_kind_struct, s8_const("sb8_t"), sizeof(sb8_t), .count = 4,
.members = (type_member_t[]){
{s8_const("arena"), &POINTER(ma_arena_t), .offset = offsetof(sb8_t, arena)},
{s8_const("first"), &POINTER(sb8_node_t), .offset = offsetof(sb8_t, first)},
{s8_const("last"), &POINTER(sb8_node_t), .offset = offsetof(sb8_t, last)},
{s8_const("indent"), &type__i32, .offset = offsetof(sb8_t, indent)},
}
};
static gb_read_only type_t type__ma_temp_t = { type_kind_struct, s8_const("ma_temp_t"), sizeof(ma_temp_t), .count = 2,
.members = (type_member_t[]){
{s8_const("arena"), &POINTER(ma_arena_t), .offset = offsetof(ma_temp_t, arena)},
{s8_const("len"), &type__usize, .offset = offsetof(ma_temp_t, len)},
}
};
static gb_read_only type_t type__v2f32_t = { type_kind_struct, s8_const("v2f32_t"), sizeof(v2f32_t), .count = 2,
.members = (type_member_t[]){
{s8_const("x"), &type__f32, .offset = offsetof(v2f32_t, x)},
{s8_const("y"), &type__f32, .offset = offsetof(v2f32_t, y)},
}
};
static gb_read_only type_t type__v3f32_t = { type_kind_struct, s8_const("v3f32_t"), sizeof(v3f32_t), .count = 3,
.members = (type_member_t[]){
{s8_const("x"), &type__f32, .offset = offsetof(v3f32_t, x)},
{s8_const("y"), &type__f32, .offset = offsetof(v3f32_t, y)},
{s8_const("z"), &type__f32, .offset = offsetof(v3f32_t, z)},
}
};
static gb_read_only type_t type__v4f32_t = { type_kind_struct, s8_const("v4f32_t"), sizeof(v4f32_t), .count = 4,
.members = (type_member_t[]){
{s8_const("x"), &type__f32, .offset = offsetof(v4f32_t, x)},
{s8_const("y"), &type__f32, .offset = offsetof(v4f32_t, y)},
{s8_const("z"), &type__f32, .offset = offsetof(v4f32_t, z)},
{s8_const("w"), &type__f32, .offset = offsetof(v4f32_t, w)},
}
};
static gb_read_only type_t type__r3f32_t = { type_kind_struct, s8_const("r3f32_t"), sizeof(r3f32_t), .count = 6,
.members = (type_member_t[]){
{s8_const("x0"), &type__f32, .offset = offsetof(r3f32_t, x0)},
{s8_const("y0"), &type__f32, .offset = offsetof(r3f32_t, y0)},
{s8_const("x0"), &type__f32, .offset = offsetof(r3f32_t, z0)},
{s8_const("x1"), &type__f32, .offset = offsetof(r3f32_t, x1)},
{s8_const("y1"), &type__f32, .offset = offsetof(r3f32_t, y1)},
{s8_const("x1"), &type__f32, .offset = offsetof(r3f32_t, z1)},
}
};
static gb_read_only type_member_t members__r2f32_t[] = {
{s8_const("x0"), &type__f32, .offset = offsetof(r2f32_t, x0)},
{s8_const("y0"), &type__f32, .offset = offsetof(r2f32_t, y0)},
{s8_const("x1"), &type__f32, .offset = offsetof(r2f32_t, x1)},
{s8_const("y1"), &type__f32, .offset = offsetof(r2f32_t, y1)},
};
static gb_read_only DEFINE_STRUCT(r2f32_t);
static gb_read_only type_member_t members__r1f32_t[] = {
{s8_const("x0"), &type__f32, .offset = offsetof(r1f32_t, x0)},
{s8_const("x1"), &type__f32, .offset = offsetof(r1f32_t, x1)},
};
static gb_read_only DEFINE_STRUCT(r1f32_t);
static gb_read_only type_t type__v2f64_t = { type_kind_struct, s8_const("v2f64_t"), sizeof(v2f64_t), .count = 2,
.members = (type_member_t[]){
{s8_const("x"), &type__f64, .offset = offsetof(v2f64_t, x)},
{s8_const("y"), &type__f64, .offset = offsetof(v2f64_t, y)},
}
};
static gb_read_only type_t type__v3f64_t = { type_kind_struct, s8_const("v3f64_t"), sizeof(v3f64_t), .count = 3,
.members = (type_member_t[]){
{s8_const("x"), &type__f64, .offset = offsetof(v3f64_t, x)},
{s8_const("y"), &type__f64, .offset = offsetof(v3f64_t, y)},
{s8_const("z"), &type__f64, .offset = offsetof(v3f64_t, z)},
}
};
static gb_read_only type_t type__v4f64_t = { type_kind_struct, s8_const("v4f64_t"), sizeof(v4f64_t), .count = 4,
.members = (type_member_t[]){
{s8_const("x"), &type__f64, .offset = offsetof(v4f64_t, x)},
{s8_const("y"), &type__f64, .offset = offsetof(v4f64_t, y)},
{s8_const("z"), &type__f64, .offset = offsetof(v4f64_t, z)},
{s8_const("w"), &type__f64, .offset = offsetof(v4f64_t, w)},
}
};
static gb_read_only type_t type__r3f64_t = { type_kind_struct, s8_const("r3f64_t"), sizeof(r3f64_t), .count = 6,
.members = (type_member_t[]){
{s8_const("x0"), &type__f64, .offset = offsetof(r3f64_t, x0)},
{s8_const("y0"), &type__f64, .offset = offsetof(r3f64_t, y0)},
{s8_const("x0"), &type__f64, .offset = offsetof(r3f64_t, z0)},
{s8_const("x1"), &type__f64, .offset = offsetof(r3f64_t, x1)},
{s8_const("y1"), &type__f64, .offset = offsetof(r3f64_t, y1)},
{s8_const("x1"), &type__f64, .offset = offsetof(r3f64_t, z1)},
}
};
static gb_read_only type_member_t members__r2f64_t[] = {
{s8_const("x0"), &type__f64, .offset = offsetof(r2f64_t, x0)},
{s8_const("y0"), &type__f64, .offset = offsetof(r2f64_t, y0)},
{s8_const("x1"), &type__f64, .offset = offsetof(r2f64_t, x1)},
{s8_const("y1"), &type__f64, .offset = offsetof(r2f64_t, y1)},
};
static gb_read_only DEFINE_STRUCT(r2f64_t);
static gb_read_only type_member_t members__r1f64_t[] = {
{s8_const("x0"), &type__f64, .offset = offsetof(r1f64_t, x0)},
{s8_const("x1"), &type__f64, .offset = offsetof(r1f64_t, x1)},
};
static gb_read_only DEFINE_STRUCT(r1f64_t);
static gb_read_only type_t type__v2i32_t = { type_kind_struct, s8_const("v2i32_t"), sizeof(v2i32_t), .count = 2,
.members = (type_member_t[]){
{s8_const("x"), &type__i32, .offset = offsetof(v2i32_t, x)},
{s8_const("y"), &type__i32, .offset = offsetof(v2i32_t, y)},
}
};
static gb_read_only type_t type__v3i32_t = { type_kind_struct, s8_const("v3i32_t"), sizeof(v3i32_t), .count = 3,
.members = (type_member_t[]){
{s8_const("x"), &type__i32, .offset = offsetof(v3i32_t, x)},
{s8_const("y"), &type__i32, .offset = offsetof(v3i32_t, y)},
{s8_const("z"), &type__i32, .offset = offsetof(v3i32_t, z)},
}
};
static gb_read_only type_t type__v4i32_t = { type_kind_struct, s8_const("v4i32_t"), sizeof(v4i32_t), .count = 4,
.members = (type_member_t[]){
{s8_const("x"), &type__i32, .offset = offsetof(v4i32_t, x)},
{s8_const("y"), &type__i32, .offset = offsetof(v4i32_t, y)},
{s8_const("z"), &type__i32, .offset = offsetof(v4i32_t, z)},
{s8_const("w"), &type__i32, .offset = offsetof(v4i32_t, w)},
}
};
static gb_read_only type_t type__r3i32_t = { type_kind_struct, s8_const("r3i32_t"), sizeof(r3i32_t), .count = 6,
.members = (type_member_t[]){
{s8_const("x0"), &type__i32, .offset = offsetof(r3i32_t, x0)},
{s8_const("y0"), &type__i32, .offset = offsetof(r3i32_t, y0)},
{s8_const("x0"), &type__i32, .offset = offsetof(r3i32_t, z0)},
{s8_const("x1"), &type__i32, .offset = offsetof(r3i32_t, x1)},
{s8_const("y1"), &type__i32, .offset = offsetof(r3i32_t, y1)},
{s8_const("x1"), &type__i32, .offset = offsetof(r3i32_t, z1)},
}
};
static gb_read_only type_member_t members__r2i32_t[] = {
{s8_const("x0"), &type__i32, .offset = offsetof(r2i32_t, x0)},
{s8_const("y0"), &type__i32, .offset = offsetof(r2i32_t, y0)},
{s8_const("x1"), &type__i32, .offset = offsetof(r2i32_t, x1)},
{s8_const("y1"), &type__i32, .offset = offsetof(r2i32_t, y1)},
};
static gb_read_only DEFINE_STRUCT(r2i32_t);
static gb_read_only type_member_t members__r1i32_t[] = {
{s8_const("x0"), &type__i32, .offset = offsetof(r1i32_t, x0)},
{s8_const("x1"), &type__i32, .offset = offsetof(r1i32_t, x1)},
};
static gb_read_only DEFINE_STRUCT(r1i32_t);
static gb_read_only type_t type__v2i64_t = { type_kind_struct, s8_const("v2i64_t"), sizeof(v2i64_t), .count = 2,
.members = (type_member_t[]){
{s8_const("x"), &type__i64, .offset = offsetof(v2i64_t, x)},
{s8_const("y"), &type__i64, .offset = offsetof(v2i64_t, y)},
}
};
static gb_read_only type_t type__v3i64_t = { type_kind_struct, s8_const("v3i64_t"), sizeof(v3i64_t), .count = 3,
.members = (type_member_t[]){
{s8_const("x"), &type__i64, .offset = offsetof(v3i64_t, x)},
{s8_const("y"), &type__i64, .offset = offsetof(v3i64_t, y)},
{s8_const("z"), &type__i64, .offset = offsetof(v3i64_t, z)},
}
};
static gb_read_only type_t type__v4i64_t = { type_kind_struct, s8_const("v4i64_t"), sizeof(v4i64_t), .count = 4,
.members = (type_member_t[]){
{s8_const("x"), &type__i64, .offset = offsetof(v4i64_t, x)},
{s8_const("y"), &type__i64, .offset = offsetof(v4i64_t, y)},
{s8_const("z"), &type__i64, .offset = offsetof(v4i64_t, z)},
{s8_const("w"), &type__i64, .offset = offsetof(v4i64_t, w)},
}
};
static gb_read_only type_t type__r3i64_t = { type_kind_struct, s8_const("r3i64_t"), sizeof(r3i64_t), .count = 6,
.members = (type_member_t[]){
{s8_const("x0"), &type__i64, .offset = offsetof(r3i64_t, x0)},
{s8_const("y0"), &type__i64, .offset = offsetof(r3i64_t, y0)},
{s8_const("x0"), &type__i64, .offset = offsetof(r3i64_t, z0)},
{s8_const("x1"), &type__i64, .offset = offsetof(r3i64_t, x1)},
{s8_const("y1"), &type__i64, .offset = offsetof(r3i64_t, y1)},
{s8_const("x1"), &type__i64, .offset = offsetof(r3i64_t, z1)},
}
};
static gb_read_only type_member_t members__r2i64_t[] = {
{s8_const("x0"), &type__i64, .offset = offsetof(r2i64_t, x0)},
{s8_const("y0"), &type__i64, .offset = offsetof(r2i64_t, y0)},
{s8_const("x1"), &type__i64, .offset = offsetof(r2i64_t, x1)},
{s8_const("y1"), &type__i64, .offset = offsetof(r2i64_t, y1)},
};
static gb_read_only DEFINE_STRUCT(r2i64_t);
static gb_read_only type_member_t members__r1i64_t[] = {
{s8_const("x0"), &type__i64, .offset = offsetof(r1i64_t, x0)},
{s8_const("x1"), &type__i64, .offset = offsetof(r1i64_t, x1)},
};
static gb_read_only DEFINE_STRUCT(r1i64_t);
-199
View File
@@ -1,199 +0,0 @@
#include "core_unicode.h"
fn utf32_result_t utf16_to_utf32(uint16_t *c, int max_advance) {
utf32_result_t result = {0};
if (max_advance >= 1) {
result.advance = 1;
result.out_str = c[0];
if (c[0] >= 0xD800 && c[0] <= 0xDBFF && c[1] >= 0xDC00 && c[1] <= 0xDFFF) {
if (max_advance >= 2) {
result.out_str = 0x10000;
result.out_str += (uint32_t)(c[0] & 0x03FF) << 10u | (c[1] & 0x03FF);
result.advance = 2;
} else {
result.error = 2;
}
}
}
else {
result.error = 1;
}
return result;
}
fn utf8_result_t utf32_to_utf8(uint32_t codepoint) {
utf8_result_t result = {0};
if (codepoint <= 0x7F) {
result.len = 1;
result.out_str[0] = (char)codepoint;
}
else if (codepoint <= 0x7FF) {
result.len = 2;
result.out_str[0] = 0xc0 | (0x1f & (codepoint >> 6));
result.out_str[1] = 0x80 | (0x3f & codepoint);
}
else if (codepoint <= 0xFFFF) { // 16 bit word
result.len = 3;
result.out_str[0] = 0xe0 | (0xf & (codepoint >> 12)); // 4 bits
result.out_str[1] = 0x80 | (0x3f & (codepoint >> 6)); // 6 bits
result.out_str[2] = 0x80 | (0x3f & codepoint); // 6 bits
}
else if (codepoint <= 0x10FFFF) { // 21 bit word
result.len = 4;
result.out_str[0] = 0xf0 | (0x7 & (codepoint >> 18)); // 3 bits
result.out_str[1] = 0x80 | (0x3f & (codepoint >> 12)); // 6 bits
result.out_str[2] = 0x80 | (0x3f & (codepoint >> 6)); // 6 bits
result.out_str[3] = 0x80 | (0x3f & codepoint); // 6 bits
}
else {
result.error = 1;
}
return result;
}
fn utf32_result_t utf8_to_utf32(char *c, int max_advance) {
utf32_result_t result = {0};
if ((c[0] & 0x80) == 0) { // Check if leftmost zero of first byte is unset
if (max_advance >= 1) {
result.out_str = c[0];
result.advance = 1;
}
else result.error = 1;
}
else if ((c[0] & 0xe0) == 0xc0) {
if ((c[1] & 0xc0) == 0x80) { // Continuation byte required
if (max_advance >= 2) {
result.out_str = (uint32_t)(c[0] & 0x1f) << 6u | (c[1] & 0x3f);
result.advance = 2;
}
else result.error = 2;
}
else result.error = 2;
}
else if ((c[0] & 0xf0) == 0xe0) {
if ((c[1] & 0xc0) == 0x80 && (c[2] & 0xc0) == 0x80) { // Two continuation bytes required
if (max_advance >= 3) {
result.out_str = (uint32_t)(c[0] & 0xf) << 12u | (uint32_t)(c[1] & 0x3f) << 6u | (c[2] & 0x3f);
result.advance = 3;
}
else result.error = 3;
}
else result.error = 3;
}
else if ((c[0] & 0xf8) == 0xf0) {
if ((c[1] & 0xc0) == 0x80 && (c[2] & 0xc0) == 0x80 && (c[3] & 0xc0) == 0x80) { // Three continuation bytes required
if (max_advance >= 4) {
result.out_str = (uint32_t)(c[0] & 0xf) << 18u | (uint32_t)(c[1] & 0x3f) << 12u | (uint32_t)(c[2] & 0x3f) << 6u | (uint32_t)(c[3] & 0x3f);
result.advance = 4;
}
else result.error = 4;
}
else result.error = 4;
}
else result.error = 4;
return result;
}
fn utf16_result_t utf32_to_utf16(uint32_t codepoint) {
utf16_result_t result = {0};
if (codepoint < 0x10000) {
result.out_str[0] = (uint16_t)codepoint;
result.out_str[1] = 0;
result.len = 1;
}
else if (codepoint <= 0x10FFFF) {
uint32_t code = (codepoint - 0x10000);
result.out_str[0] = (uint16_t)(0xD800 | (code >> 10));
result.out_str[1] = (uint16_t)(0xDC00 | (code & 0x3FF));
result.len = 2;
}
else {
result.error = 1;
}
return result;
}
#define UTF__HANDLE_DECODE_ERROR(question_mark) \
{ \
if (outlen < buffer_size - 1) buffer[outlen++] = (question_mark); \
break; \
}
fn int64_t str_from_wstr(char *buffer, int64_t buffer_size, uint16_t *in, int64_t inlen) {
int64_t outlen = 0;
for (int64_t i = 0; i < inlen && in[i];) {
utf32_result_t decode = utf16_to_utf32((uint16_t *)(in + i), (int)(inlen - i));
if (!decode.error) {
i += decode.advance;
utf8_result_t encode = utf32_to_utf8(decode.out_str);
if (!encode.error) {
for (int64_t j = 0; j < encode.len; j++) {
if (outlen < buffer_size - 1) {
buffer[outlen++] = encode.out_str[j];
}
}
}
else UTF__HANDLE_DECODE_ERROR('?');
}
else UTF__HANDLE_DECODE_ERROR('?');
}
buffer[outlen] = 0;
return outlen;
}
fn int64_t wstr_from_str(uint16_t *buffer, int64_t buffer_size, char *in, int64_t inlen) {
int64_t outlen = 0;
for (int64_t i = 0; i < inlen;) {
utf32_result_t decode = utf8_to_utf32(in + i, (int)(inlen - i));
if (!decode.error) {
i += decode.advance;
utf16_result_t encode = utf32_to_utf16(decode.out_str);
if (!encode.error) {
for (int64_t j = 0; j < encode.len; j++) {
if (outlen < buffer_size - 1) {
buffer[outlen++] = encode.out_str[j];
}
}
}
else UTF__HANDLE_DECODE_ERROR(0x003f);
}
else UTF__HANDLE_DECODE_ERROR(0x003f);
}
buffer[outlen] = 0;
return outlen;
}
fn void utf8_advance(utf8_iter_t *iter) {
iter->i += iter->utf8_codepoint_byte_size;
utf32_result_t r = utf8_to_utf32(iter->str + iter->i, iter->len - iter->i);
if (r.error) {
iter->item = 0;
return;
}
iter->utf8_codepoint_byte_size = r.advance;
iter->item = r.out_str;
}
// @todo: s8_t, change name
fn utf8_iter_t utf8_iterate_ex(char *str, int len) {
utf8_iter_t result = {str, len};
if (len) utf8_advance(&result);
return result;
}
fn utf8_iter_t utf8_iterate(char *str) {
int length = 0;
while (str[length]) length += 1;
return utf8_iterate_ex(str, length);
}
-56
View File
@@ -1,56 +0,0 @@
#pragma once
#include "core_basic.h"
typedef struct utf32_result_t utf32_result_t;
struct utf32_result_t {
uint32_t out_str;
int advance;
int error;
};
typedef struct utf16_result_t utf16_result_t;
struct utf16_result_t {
uint16_t out_str[2];
int len;
int error;
};
typedef struct utf8_result_t utf8_result_t;
struct utf8_result_t {
uint8_t out_str[4];
int len;
int error;
};
typedef struct utf8_iter_t utf8_iter_t;
struct utf8_iter_t {
char *str;
int len;
int utf8_codepoint_byte_size;
int i;
uint32_t item;
};
//
// codepoint conversions
fn utf32_result_t utf16_to_utf32(uint16_t *c, int max_advance);
fn utf8_result_t utf32_to_utf8(uint32_t codepoint);
fn utf32_result_t utf8_to_utf32(char *c, int max_advance);
fn utf16_result_t utf32_to_utf16(uint32_t codepoint);
//
// widestring / string conversions
fn int64_t str_from_wstr(char *buffer, int64_t buffer_size, uint16_t *in, int64_t inlen);
fn int64_t wstr_from_str(uint16_t *buffer, int64_t buffer_size, char *in, int64_t inlen);
//
// codepoint iterator
fn utf8_iter_t utf8_iterate(char *str);
fn utf8_iter_t utf8_iterate_ex(char *str, int len);
fn void utf8_advance(utf8_iter_t *iter);
/* example:
for (utf8_iter_t iter = utf8_iterate(string); iter.item; utf8_advance(&iter)) {
u32 codepoint = iter.item;
}
*/
-3
View File
@@ -1,3 +0,0 @@
#define STB_SPRINTF_IMPLEMENTATION
#include "stb_sprintf.h"
#undef STB_SPRINTF_IMPLEMENTATION
File diff suppressed because it is too large Load Diff
+1819
View File
File diff suppressed because it is too large Load Diff
+3655
View File
File diff suppressed because it is too large Load Diff
+311
View File
@@ -0,0 +1,311 @@
#ifndef __khrplatform_h_
#define __khrplatform_h_
/*
** Copyright (c) 2008-2018 The Khronos Group Inc.
**
** Permission is hereby granted, free of charge, to any person obtaining a
** copy of this software and/or associated documentation files (the
** "Materials"), to deal in the Materials without restriction, including
** without limitation the rights to use, copy, modify, merge, publish,
** distribute, sublicense, and/or sell copies of the Materials, and to
** permit persons to whom the Materials are furnished to do so, subject to
** the following conditions:
**
** The above copyright notice and this permission notice shall be included
** in all copies or substantial portions of the Materials.
**
** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
*/
/* Khronos platform-specific types and definitions.
*
* The master copy of khrplatform.h is maintained in the Khronos EGL
* Registry repository at https://github.com/KhronosGroup/EGL-Registry
* The last semantic modification to khrplatform.h was at commit ID:
* 67a3e0864c2d75ea5287b9f3d2eb74a745936692
*
* Adopters may modify this file to suit their platform. Adopters are
* encouraged to submit platform specific modifications to the Khronos
* group so that they can be included in future versions of this file.
* Please submit changes by filing pull requests or issues on
* the EGL Registry repository linked above.
*
*
* See the Implementer's Guidelines for information about where this file
* should be located on your system and for more details of its use:
* http://www.khronos.org/registry/implementers_guide.pdf
*
* This file should be included as
* #include <KHR/khrplatform.h>
* by Khronos client API header files that use its types and defines.
*
* The types in khrplatform.h should only be used to define API-specific types.
*
* Types defined in khrplatform.h:
* khronos_int8_t signed 8 bit
* khronos_uint8_t unsigned 8 bit
* khronos_int16_t signed 16 bit
* khronos_uint16_t unsigned 16 bit
* khronos_int32_t signed 32 bit
* khronos_uint32_t unsigned 32 bit
* khronos_int64_t signed 64 bit
* khronos_uint64_t unsigned 64 bit
* khronos_intptr_t signed same number of bits as a pointer
* khronos_uintptr_t unsigned same number of bits as a pointer
* khronos_ssize_t signed size
* khronos_usize_t unsigned size
* khronos_float_t signed 32 bit floating point
* khronos_time_ns_t unsigned 64 bit time in nanoseconds
* khronos_utime_nanoseconds_t unsigned time interval or absolute time in
* nanoseconds
* khronos_stime_nanoseconds_t signed time interval in nanoseconds
* khronos_boolean_enum_t enumerated boolean type. This should
* only be used as a base type when a client API's boolean type is
* an enum. Client APIs which use an integer or other type for
* booleans cannot use this as the base type for their boolean.
*
* Tokens defined in khrplatform.h:
*
* KHRONOS_FALSE, KHRONOS_TRUE Enumerated boolean false/true values.
*
* KHRONOS_SUPPORT_INT64 is 1 if 64 bit integers are supported; otherwise 0.
* KHRONOS_SUPPORT_FLOAT is 1 if floats are supported; otherwise 0.
*
* Calling convention macros defined in this file:
* KHRONOS_APICALL
* KHRONOS_APIENTRY
* KHRONOS_APIATTRIBUTES
*
* These may be used in function prototypes as:
*
* KHRONOS_APICALL void KHRONOS_APIENTRY funcname(
* int arg1,
* int arg2) KHRONOS_APIATTRIBUTES;
*/
#if defined(__SCITECH_SNAP__) && !defined(KHRONOS_STATIC)
# define KHRONOS_STATIC 1
#endif
/*-------------------------------------------------------------------------
* Definition of KHRONOS_APICALL
*-------------------------------------------------------------------------
* This precedes the return type of the function in the function prototype.
*/
#if defined(KHRONOS_STATIC)
/* If the preprocessor constant KHRONOS_STATIC is defined, make the
* header compatible with static linking. */
# define KHRONOS_APICALL
#elif defined(_WIN32)
# define KHRONOS_APICALL __declspec(dllimport)
#elif defined (__SYMBIAN32__)
# define KHRONOS_APICALL IMPORT_C
#elif defined(__ANDROID__)
# define KHRONOS_APICALL __attribute__((visibility("default")))
#else
# define KHRONOS_APICALL
#endif
/*-------------------------------------------------------------------------
* Definition of KHRONOS_APIENTRY
*-------------------------------------------------------------------------
* This follows the return type of the function and precedes the function
* name in the function prototype.
*/
#if defined(_WIN32) && !defined(_WIN32_WCE) && !defined(__SCITECH_SNAP__)
/* Win32 but not WinCE */
# define KHRONOS_APIENTRY __stdcall
#else
# define KHRONOS_APIENTRY
#endif
/*-------------------------------------------------------------------------
* Definition of KHRONOS_APIATTRIBUTES
*-------------------------------------------------------------------------
* This follows the closing parenthesis of the function prototype arguments.
*/
#if defined (__ARMCC_2__)
#define KHRONOS_APIATTRIBUTES __softfp
#else
#define KHRONOS_APIATTRIBUTES
#endif
/*-------------------------------------------------------------------------
* basic type definitions
*-----------------------------------------------------------------------*/
#if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || defined(__GNUC__) || defined(__SCO__) || defined(__USLC__)
/*
* Using <stdint.h>
*/
#include <stdint.h>
typedef int32_t khronos_int32_t;
typedef uint32_t khronos_uint32_t;
typedef int64_t khronos_int64_t;
typedef uint64_t khronos_uint64_t;
#define KHRONOS_SUPPORT_INT64 1
#define KHRONOS_SUPPORT_FLOAT 1
/*
* To support platform where unsigned long cannot be used interchangeably with
* inptr_t (e.g. CHERI-extended ISAs), we can use the stdint.h intptr_t.
* Ideally, we could just use (u)intptr_t everywhere, but this could result in
* ABI breakage if khronos_uintptr_t is changed from unsigned long to
* unsigned long long or similar (this results in different C++ name mangling).
* To avoid changes for existing platforms, we restrict usage of intptr_t to
* platforms where the size of a pointer is larger than the size of long.
*/
#if defined(__SIZEOF_LONG__) && defined(__SIZEOF_POINTER__)
#if __SIZEOF_POINTER__ > __SIZEOF_LONG__
#define KHRONOS_USE_INTPTR_T
#endif
#endif
#elif defined(__VMS ) || defined(__sgi)
/*
* Using <inttypes.h>
*/
#include <inttypes.h>
typedef int32_t khronos_int32_t;
typedef uint32_t khronos_uint32_t;
typedef int64_t khronos_int64_t;
typedef uint64_t khronos_uint64_t;
#define KHRONOS_SUPPORT_INT64 1
#define KHRONOS_SUPPORT_FLOAT 1
#elif defined(_WIN32) && !defined(__SCITECH_SNAP__)
/*
* Win32
*/
typedef __int32 khronos_int32_t;
typedef unsigned __int32 khronos_uint32_t;
typedef __int64 khronos_int64_t;
typedef unsigned __int64 khronos_uint64_t;
#define KHRONOS_SUPPORT_INT64 1
#define KHRONOS_SUPPORT_FLOAT 1
#elif defined(__sun__) || defined(__digital__)
/*
* Sun or Digital
*/
typedef int khronos_int32_t;
typedef unsigned int khronos_uint32_t;
#if defined(__arch64__) || defined(_LP64)
typedef long int khronos_int64_t;
typedef unsigned long int khronos_uint64_t;
#else
typedef long long int khronos_int64_t;
typedef unsigned long long int khronos_uint64_t;
#endif /* __arch64__ */
#define KHRONOS_SUPPORT_INT64 1
#define KHRONOS_SUPPORT_FLOAT 1
#elif 0
/*
* Hypothetical platform with no float or int64 support
*/
typedef int khronos_int32_t;
typedef unsigned int khronos_uint32_t;
#define KHRONOS_SUPPORT_INT64 0
#define KHRONOS_SUPPORT_FLOAT 0
#else
/*
* Generic fallback
*/
#include <stdint.h>
typedef int32_t khronos_int32_t;
typedef uint32_t khronos_uint32_t;
typedef int64_t khronos_int64_t;
typedef uint64_t khronos_uint64_t;
#define KHRONOS_SUPPORT_INT64 1
#define KHRONOS_SUPPORT_FLOAT 1
#endif
/*
* Types that are (so far) the same on all platforms
*/
typedef signed char khronos_int8_t;
typedef unsigned char khronos_uint8_t;
typedef signed short int khronos_int16_t;
typedef unsigned short int khronos_uint16_t;
/*
* Types that differ between LLP64 and LP64 architectures - in LLP64,
* pointers are 64 bits, but 'long' is still 32 bits. Win64 appears
* to be the only LLP64 architecture in current use.
*/
#ifdef KHRONOS_USE_INTPTR_T
typedef intptr_t khronos_intptr_t;
typedef uintptr_t khronos_uintptr_t;
#elif defined(_WIN64)
typedef signed long long int khronos_intptr_t;
typedef unsigned long long int khronos_uintptr_t;
#else
typedef signed long int khronos_intptr_t;
typedef unsigned long int khronos_uintptr_t;
#endif
#if defined(_WIN64)
typedef signed long long int khronos_ssize_t;
typedef unsigned long long int khronos_usize_t;
#else
typedef signed long int khronos_ssize_t;
typedef unsigned long int khronos_usize_t;
#endif
#if KHRONOS_SUPPORT_FLOAT
/*
* Float type
*/
typedef float khronos_float_t;
#endif
#if KHRONOS_SUPPORT_INT64
/* Time types
*
* These types can be used to represent a time interval in nanoseconds or
* an absolute Unadjusted System Time. Unadjusted System Time is the number
* of nanoseconds since some arbitrary system event (e.g. since the last
* time the system booted). The Unadjusted System Time is an unsigned
* 64 bit value that wraps back to 0 every 584 years. Time intervals
* may be either signed or unsigned.
*/
typedef khronos_uint64_t khronos_utime_nanoseconds_t;
typedef khronos_int64_t khronos_stime_nanoseconds_t;
#endif
/*
* Dummy value used to pad enum types to 32 bits.
*/
#ifndef KHRONOS_MAX_ENUM
#define KHRONOS_MAX_ENUM 0x7FFFFFFF
#endif
/*
* Enumerated boolean type
*
* Values other than zero should be considered to be true. Therefore
* comparisons should not be made against KHRONOS_TRUE.
*/
typedef enum {
KHRONOS_FALSE = 0,
KHRONOS_TRUE = 1,
KHRONOS_BOOLEAN_ENUM_FORCE_SIZE = KHRONOS_MAX_ENUM
} khronos_boolean_enum_t;
#endif /* __khrplatform_h_ */
+106
View File
@@ -0,0 +1,106 @@
# Makefile for installing Lua
# See doc/readme.html for installation and customization instructions.
# == CHANGE THE SETTINGS BELOW TO SUIT YOUR ENVIRONMENT =======================
# Your platform. See PLATS for possible values.
PLAT= guess
# Where to install. The installation starts in the src and doc directories,
# so take care if INSTALL_TOP is not an absolute path. See the local target.
# You may want to make INSTALL_LMOD and INSTALL_CMOD consistent with
# LUA_ROOT, LUA_LDIR, and LUA_CDIR in luaconf.h.
INSTALL_TOP= /usr/local
INSTALL_BIN= $(INSTALL_TOP)/bin
INSTALL_INC= $(INSTALL_TOP)/include
INSTALL_LIB= $(INSTALL_TOP)/lib
INSTALL_MAN= $(INSTALL_TOP)/man/man1
INSTALL_LMOD= $(INSTALL_TOP)/share/lua/$V
INSTALL_CMOD= $(INSTALL_TOP)/lib/lua/$V
# How to install. If your install program does not support "-p", then
# you may have to run ranlib on the installed liblua.a.
INSTALL= install -p
INSTALL_EXEC= $(INSTALL) -m 0755
INSTALL_DATA= $(INSTALL) -m 0644
#
# If you don't have "install" you can use "cp" instead.
# INSTALL= cp -p
# INSTALL_EXEC= $(INSTALL)
# INSTALL_DATA= $(INSTALL)
# Other utilities.
MKDIR= mkdir -p
RM= rm -f
# == END OF USER SETTINGS -- NO NEED TO CHANGE ANYTHING BELOW THIS LINE =======
# Convenience platforms targets.
PLATS= guess aix bsd c89 freebsd generic ios linux linux-readline macosx mingw posix solaris
# What to install.
TO_BIN= lua luac
TO_INC= lua.h luaconf.h lualib.h lauxlib.h lua.hpp
TO_LIB= liblua.a
TO_MAN= lua.1 luac.1
# Lua version and release.
V= 5.4
R= $V.7
# Targets start here.
all: $(PLAT)
$(PLATS) help test clean:
@cd src && $(MAKE) $@
install: dummy
cd src && $(MKDIR) $(INSTALL_BIN) $(INSTALL_INC) $(INSTALL_LIB) $(INSTALL_MAN) $(INSTALL_LMOD) $(INSTALL_CMOD)
cd src && $(INSTALL_EXEC) $(TO_BIN) $(INSTALL_BIN)
cd src && $(INSTALL_DATA) $(TO_INC) $(INSTALL_INC)
cd src && $(INSTALL_DATA) $(TO_LIB) $(INSTALL_LIB)
cd doc && $(INSTALL_DATA) $(TO_MAN) $(INSTALL_MAN)
uninstall:
cd src && cd $(INSTALL_BIN) && $(RM) $(TO_BIN)
cd src && cd $(INSTALL_INC) && $(RM) $(TO_INC)
cd src && cd $(INSTALL_LIB) && $(RM) $(TO_LIB)
cd doc && cd $(INSTALL_MAN) && $(RM) $(TO_MAN)
local:
$(MAKE) install INSTALL_TOP=../install
# make may get confused with install/ if it does not support .PHONY.
dummy:
# Echo config parameters.
echo:
@cd src && $(MAKE) -s echo
@echo "PLAT= $(PLAT)"
@echo "V= $V"
@echo "R= $R"
@echo "TO_BIN= $(TO_BIN)"
@echo "TO_INC= $(TO_INC)"
@echo "TO_LIB= $(TO_LIB)"
@echo "TO_MAN= $(TO_MAN)"
@echo "INSTALL_TOP= $(INSTALL_TOP)"
@echo "INSTALL_BIN= $(INSTALL_BIN)"
@echo "INSTALL_INC= $(INSTALL_INC)"
@echo "INSTALL_LIB= $(INSTALL_LIB)"
@echo "INSTALL_MAN= $(INSTALL_MAN)"
@echo "INSTALL_LMOD= $(INSTALL_LMOD)"
@echo "INSTALL_CMOD= $(INSTALL_CMOD)"
@echo "INSTALL_EXEC= $(INSTALL_EXEC)"
@echo "INSTALL_DATA= $(INSTALL_DATA)"
# Echo pkg-config data.
pc:
@echo "version=$R"
@echo "prefix=$(INSTALL_TOP)"
@echo "libdir=$(INSTALL_LIB)"
@echo "includedir=$(INSTALL_INC)"
# Targets that do not create files (not all makes understand .PHONY).
.PHONY: all $(PLATS) help test clean install uninstall local dummy echo pc
# (end of Makefile)
+6
View File
@@ -0,0 +1,6 @@
This is Lua 5.4.7, released on 13 Jun 2024.
For installation instructions, license details, and
further information about Lua, see doc/readme.html.
Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

+678
View File
@@ -0,0 +1,678 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<HTML>
<HEAD>
<TITLE>Lua 5.4 Reference Manual - contents</TITLE>
<LINK REL="stylesheet" TYPE="text/css" HREF="lua.css">
<LINK REL="stylesheet" TYPE="text/css" HREF="index.css">
<META HTTP-EQUIV="content-type" CONTENT="text/html; charset=iso-8859-1">
</HEAD>
<BODY>
<H1>
<A HREF="https://www.lua.org/"><IMG SRC="logo.gif" ALT="Lua"></A>
Lua 5.4 Reference Manual
</H1>
<P>
The reference manual is the official definition of the Lua language.
<BR>
For a complete introduction to Lua programming, see the book
<A HREF="https://www.lua.org/pil/">Programming in Lua</A>.
<DIV CLASS="menubar">
<A HREF="manual.html">start</A>
&middot;
<A HREF="#contents">contents</A>
&middot;
<A HREF="#index">index</A>
&middot;
<A HREF="https://www.lua.org/manual/">other versions</A>
</DIV>
<P>
<SMALL>
Copyright &copy; 2020&ndash;2024 Lua.org, PUC-Rio.
Freely available under the terms of the
<A HREF="https://www.lua.org/license.html">Lua license</A>.
</SMALL>
<H2><A NAME="contents">Contents</A></H2>
<UL CLASS="contents menubar">
<LI><A HREF="manual.html">1 &ndash; Introduction</A>
<P>
<LI><A HREF="manual.html#2">2 &ndash; Basic Concepts</A>
<UL>
<LI><A HREF="manual.html#2.1">2.1 &ndash; Values and Types</A>
<LI><A HREF="manual.html#2.2">2.2 &ndash; Environments and the Global Environment</A>
<LI><A HREF="manual.html#2.3">2.3 &ndash; Error Handling</A>
<LI><A HREF="manual.html#2.4">2.4 &ndash; Metatables and Metamethods</A>
<LI><A HREF="manual.html#2.5">2.5 &ndash; Garbage Collection</A>
<UL>
<LI><A HREF="manual.html#2.5.1">2.5.1 &ndash; Incremental Garbage Collection</A>
<LI><A HREF="manual.html#2.5.2">2.5.2 &ndash; Generational Garbage Collection</A>
<LI><A HREF="manual.html#2.5.3">2.5.3 &ndash; Garbage-Collection Metamethods</A>
<LI><A HREF="manual.html#2.5.4">2.5.4 &ndash; Weak Tables</A>
</UL>
<LI><A HREF="manual.html#2.6">2.6 &ndash; Coroutines</A>
</UL>
<P>
<LI><A HREF="manual.html#3">3 &ndash; The Language</A>
<UL>
<LI><A HREF="manual.html#3.1">3.1 &ndash; Lexical Conventions</A>
<LI><A HREF="manual.html#3.2">3.2 &ndash; Variables</A>
<LI><A HREF="manual.html#3.3">3.3 &ndash; Statements</A>
<UL>
<LI><A HREF="manual.html#3.3.1">3.3.1 &ndash; Blocks</A>
<LI><A HREF="manual.html#3.3.2">3.3.2 &ndash; Chunks</A>
<LI><A HREF="manual.html#3.3.3">3.3.3 &ndash; Assignment</A>
<LI><A HREF="manual.html#3.3.4">3.3.4 &ndash; Control Structures</A>
<LI><A HREF="manual.html#3.3.5">3.3.5 &ndash; For Statement</A>
<LI><A HREF="manual.html#3.3.6">3.3.6 &ndash; Function Calls as Statements</A>
<LI><A HREF="manual.html#3.3.7">3.3.7 &ndash; Local Declarations</A>
<LI><A HREF="manual.html#3.3.8">3.3.8 &ndash; To-be-closed Variables</A>
</UL>
<LI><A HREF="manual.html#3.4">3.4 &ndash; Expressions</A>
<UL>
<LI><A HREF="manual.html#3.4.1">3.4.1 &ndash; Arithmetic Operators</A>
<LI><A HREF="manual.html#3.4.2">3.4.2 &ndash; Bitwise Operators</A>
<LI><A HREF="manual.html#3.4.3">3.4.3 &ndash; Coercions and Conversions</A>
<LI><A HREF="manual.html#3.4.4">3.4.4 &ndash; Relational Operators</A>
<LI><A HREF="manual.html#3.4.5">3.4.5 &ndash; Logical Operators</A>
<LI><A HREF="manual.html#3.4.6">3.4.6 &ndash; Concatenation</A>
<LI><A HREF="manual.html#3.4.7">3.4.7 &ndash; The Length Operator</A>
<LI><A HREF="manual.html#3.4.8">3.4.8 &ndash; Precedence</A>
<LI><A HREF="manual.html#3.4.9">3.4.9 &ndash; Table Constructors</A>
<LI><A HREF="manual.html#3.4.10">3.4.10 &ndash; Function Calls</A>
<LI><A HREF="manual.html#3.4.11">3.4.11 &ndash; Function Definitions</A>
<LI><A HREF="manual.html#3.4.12">3.4.12 &ndash; Lists of expressions, multiple results, and adjustment<A>
</UL>
<LI><A HREF="manual.html#3.5">3.5 &ndash; Visibility Rules</A>
</UL>
<P>
<LI><A HREF="manual.html#4">4 &ndash; The Application Program Interface</A>
<UL>
<LI><A HREF="manual.html#4.1">4.1 &ndash; The Stack</A>
<UL>
<LI><A HREF="manual.html#4.1.1">4.1.1 &ndash; Stack Size</A>
<LI><A HREF="manual.html#4.1.2">4.1.2 &ndash; Valid and Acceptable Indices</A>
<LI><A HREF="manual.html#4.1.3">4.1.3 &ndash; Pointers to strings</A>
</UL>
<LI><A HREF="manual.html#4.2">4.2 &ndash; C Closures</A>
<LI><A HREF="manual.html#4.3">4.3 &ndash; Registry</A>
<LI><A HREF="manual.html#4.4">4.4 &ndash; Error Handling in C</A>
<UL>
<LI><A HREF="manual.html#4.4.1">4.4.1 &ndash; Status Codes</A>
</UL>
<LI><A HREF="manual.html#4.5">4.5 &ndash; Handling Yields in C</A>
<LI><A HREF="manual.html#4.6">4.6 &ndash; Functions and Types</A>
<LI><A HREF="manual.html#4.7">4.7 &ndash; The Debug Interface</A>
</UL>
<P>
<LI><A HREF="manual.html#5">5 &ndash; The Auxiliary Library</A>
<UL>
<LI><A HREF="manual.html#5.1">5.1 &ndash; Functions and Types</A>
</UL>
<P>
<LI><A HREF="manual.html#6">6 &ndash; The Standard Libraries</A>
<UL>
<LI><A HREF="manual.html#6.1">6.1 &ndash; Basic Functions</A>
<LI><A HREF="manual.html#6.2">6.2 &ndash; Coroutine Manipulation</A>
<LI><A HREF="manual.html#6.3">6.3 &ndash; Modules</A>
<LI><A HREF="manual.html#6.4">6.4 &ndash; String Manipulation</A>
<UL>
<LI><A HREF="manual.html#6.4.1">6.4.1 &ndash; Patterns</A>
<LI><A HREF="manual.html#6.4.2">6.4.2 &ndash; Format Strings for Pack and Unpack</A>
</UL>
<LI><A HREF="manual.html#6.5">6.5 &ndash; UTF-8 Support</A>
<LI><A HREF="manual.html#6.6">6.6 &ndash; Table Manipulation</A>
<LI><A HREF="manual.html#6.7">6.7 &ndash; Mathematical Functions</A>
<LI><A HREF="manual.html#6.8">6.8 &ndash; Input and Output Facilities</A>
<LI><A HREF="manual.html#6.9">6.9 &ndash; Operating System Facilities</A>
<LI><A HREF="manual.html#6.10">6.10 &ndash; The Debug Library</A>
</UL>
<P>
<LI><A HREF="manual.html#7">7 &ndash; Lua Standalone</A>
<P>
<LI><A HREF="manual.html#8">8 &ndash; Incompatibilities with the Previous Version</A>
<UL>
<LI><A HREF="manual.html#8.1">8.1 &ndash; Incompatibilities in the Language</A>
<LI><A HREF="manual.html#8.2">8.2 &ndash; Incompatibilities in the Libraries</A>
<LI><A HREF="manual.html#8.3">8.3 &ndash; Incompatibilities in the API</A>
</UL>
<P>
<LI><A HREF="manual.html#9">9 &ndash; The Complete Syntax of Lua</A>
</UL>
<H2><A NAME="index">Index</A></H2>
<TABLE CLASS="menubar" WIDTH="100%">
<TR>
<TD>
<H3><A NAME="functions">Lua functions</A></H3>
<P>
<A HREF="manual.html#6.1">basic</A><BR>
<A HREF="manual.html#pdf-_G">_G</A><BR>
<A HREF="manual.html#pdf-_VERSION">_VERSION</A><BR>
<A HREF="manual.html#pdf-assert">assert</A><BR>
<A HREF="manual.html#pdf-collectgarbage">collectgarbage</A><BR>
<A HREF="manual.html#pdf-dofile">dofile</A><BR>
<A HREF="manual.html#pdf-error">error</A><BR>
<A HREF="manual.html#pdf-getmetatable">getmetatable</A><BR>
<A HREF="manual.html#pdf-ipairs">ipairs</A><BR>
<A HREF="manual.html#pdf-load">load</A><BR>
<A HREF="manual.html#pdf-loadfile">loadfile</A><BR>
<A HREF="manual.html#pdf-next">next</A><BR>
<A HREF="manual.html#pdf-pairs">pairs</A><BR>
<A HREF="manual.html#pdf-pcall">pcall</A><BR>
<A HREF="manual.html#pdf-print">print</A><BR>
<A HREF="manual.html#pdf-rawequal">rawequal</A><BR>
<A HREF="manual.html#pdf-rawget">rawget</A><BR>
<A HREF="manual.html#pdf-rawlen">rawlen</A><BR>
<A HREF="manual.html#pdf-rawset">rawset</A><BR>
<A HREF="manual.html#pdf-require">require</A><BR>
<A HREF="manual.html#pdf-select">select</A><BR>
<A HREF="manual.html#pdf-setmetatable">setmetatable</A><BR>
<A HREF="manual.html#pdf-tonumber">tonumber</A><BR>
<A HREF="manual.html#pdf-tostring">tostring</A><BR>
<A HREF="manual.html#pdf-type">type</A><BR>
<A HREF="manual.html#pdf-warn">warn</A><BR>
<A HREF="manual.html#pdf-xpcall">xpcall</A><BR>
<P>
<A HREF="manual.html#6.2">coroutine</A><BR>
<A HREF="manual.html#pdf-coroutine.close">coroutine.close</A><BR>
<A HREF="manual.html#pdf-coroutine.create">coroutine.create</A><BR>
<A HREF="manual.html#pdf-coroutine.isyieldable">coroutine.isyieldable</A><BR>
<A HREF="manual.html#pdf-coroutine.resume">coroutine.resume</A><BR>
<A HREF="manual.html#pdf-coroutine.running">coroutine.running</A><BR>
<A HREF="manual.html#pdf-coroutine.status">coroutine.status</A><BR>
<A HREF="manual.html#pdf-coroutine.wrap">coroutine.wrap</A><BR>
<A HREF="manual.html#pdf-coroutine.yield">coroutine.yield</A><BR>
<P>
<A HREF="manual.html#6.10">debug</A><BR>
<A HREF="manual.html#pdf-debug.debug">debug.debug</A><BR>
<A HREF="manual.html#pdf-debug.gethook">debug.gethook</A><BR>
<A HREF="manual.html#pdf-debug.getinfo">debug.getinfo</A><BR>
<A HREF="manual.html#pdf-debug.getlocal">debug.getlocal</A><BR>
<A HREF="manual.html#pdf-debug.getmetatable">debug.getmetatable</A><BR>
<A HREF="manual.html#pdf-debug.getregistry">debug.getregistry</A><BR>
<A HREF="manual.html#pdf-debug.getupvalue">debug.getupvalue</A><BR>
<A HREF="manual.html#pdf-debug.getuservalue">debug.getuservalue</A><BR>
<A HREF="manual.html#pdf-debug.sethook">debug.sethook</A><BR>
<A HREF="manual.html#pdf-debug.setlocal">debug.setlocal</A><BR>
<A HREF="manual.html#pdf-debug.setmetatable">debug.setmetatable</A><BR>
<A HREF="manual.html#pdf-debug.setupvalue">debug.setupvalue</A><BR>
<A HREF="manual.html#pdf-debug.setuservalue">debug.setuservalue</A><BR>
<A HREF="manual.html#pdf-debug.traceback">debug.traceback</A><BR>
<A HREF="manual.html#pdf-debug.upvalueid">debug.upvalueid</A><BR>
<A HREF="manual.html#pdf-debug.upvaluejoin">debug.upvaluejoin</A><BR>
<P>
<A HREF="manual.html#6.8">io</A><BR>
<A HREF="manual.html#pdf-io.close">io.close</A><BR>
<A HREF="manual.html#pdf-io.flush">io.flush</A><BR>
<A HREF="manual.html#pdf-io.input">io.input</A><BR>
<A HREF="manual.html#pdf-io.lines">io.lines</A><BR>
<A HREF="manual.html#pdf-io.open">io.open</A><BR>
<A HREF="manual.html#pdf-io.output">io.output</A><BR>
<A HREF="manual.html#pdf-io.popen">io.popen</A><BR>
<A HREF="manual.html#pdf-io.read">io.read</A><BR>
<A HREF="manual.html#pdf-io.stderr">io.stderr</A><BR>
<A HREF="manual.html#pdf-io.stdin">io.stdin</A><BR>
<A HREF="manual.html#pdf-io.stdout">io.stdout</A><BR>
<A HREF="manual.html#pdf-io.tmpfile">io.tmpfile</A><BR>
<A HREF="manual.html#pdf-io.type">io.type</A><BR>
<A HREF="manual.html#pdf-io.write">io.write</A><BR>
<A HREF="manual.html#pdf-file:close">file:close</A><BR>
<A HREF="manual.html#pdf-file:flush">file:flush</A><BR>
<A HREF="manual.html#pdf-file:lines">file:lines</A><BR>
<A HREF="manual.html#pdf-file:read">file:read</A><BR>
<A HREF="manual.html#pdf-file:seek">file:seek</A><BR>
<A HREF="manual.html#pdf-file:setvbuf">file:setvbuf</A><BR>
<A HREF="manual.html#pdf-file:write">file:write</A><BR>
</TD>
<TD>
<H3>&nbsp;</H3>
<P>
<A HREF="manual.html#6.7">math</A><BR>
<A HREF="manual.html#pdf-math.abs">math.abs</A><BR>
<A HREF="manual.html#pdf-math.acos">math.acos</A><BR>
<A HREF="manual.html#pdf-math.asin">math.asin</A><BR>
<A HREF="manual.html#pdf-math.atan">math.atan</A><BR>
<A HREF="manual.html#pdf-math.ceil">math.ceil</A><BR>
<A HREF="manual.html#pdf-math.cos">math.cos</A><BR>
<A HREF="manual.html#pdf-math.deg">math.deg</A><BR>
<A HREF="manual.html#pdf-math.exp">math.exp</A><BR>
<A HREF="manual.html#pdf-math.floor">math.floor</A><BR>
<A HREF="manual.html#pdf-math.fmod">math.fmod</A><BR>
<A HREF="manual.html#pdf-math.huge">math.huge</A><BR>
<A HREF="manual.html#pdf-math.log">math.log</A><BR>
<A HREF="manual.html#pdf-math.max">math.max</A><BR>
<A HREF="manual.html#pdf-math.maxinteger">math.maxinteger</A><BR>
<A HREF="manual.html#pdf-math.min">math.min</A><BR>
<A HREF="manual.html#pdf-math.mininteger">math.mininteger</A><BR>
<A HREF="manual.html#pdf-math.modf">math.modf</A><BR>
<A HREF="manual.html#pdf-math.pi">math.pi</A><BR>
<A HREF="manual.html#pdf-math.rad">math.rad</A><BR>
<A HREF="manual.html#pdf-math.random">math.random</A><BR>
<A HREF="manual.html#pdf-math.randomseed">math.randomseed</A><BR>
<A HREF="manual.html#pdf-math.sin">math.sin</A><BR>
<A HREF="manual.html#pdf-math.sqrt">math.sqrt</A><BR>
<A HREF="manual.html#pdf-math.tan">math.tan</A><BR>
<A HREF="manual.html#pdf-math.tointeger">math.tointeger</A><BR>
<A HREF="manual.html#pdf-math.type">math.type</A><BR>
<A HREF="manual.html#pdf-math.ult">math.ult</A><BR>
<P>
<A HREF="manual.html#6.9">os</A><BR>
<A HREF="manual.html#pdf-os.clock">os.clock</A><BR>
<A HREF="manual.html#pdf-os.date">os.date</A><BR>
<A HREF="manual.html#pdf-os.difftime">os.difftime</A><BR>
<A HREF="manual.html#pdf-os.execute">os.execute</A><BR>
<A HREF="manual.html#pdf-os.exit">os.exit</A><BR>
<A HREF="manual.html#pdf-os.getenv">os.getenv</A><BR>
<A HREF="manual.html#pdf-os.remove">os.remove</A><BR>
<A HREF="manual.html#pdf-os.rename">os.rename</A><BR>
<A HREF="manual.html#pdf-os.setlocale">os.setlocale</A><BR>
<A HREF="manual.html#pdf-os.time">os.time</A><BR>
<A HREF="manual.html#pdf-os.tmpname">os.tmpname</A><BR>
<P>
<A HREF="manual.html#6.3">package</A><BR>
<A HREF="manual.html#pdf-package.config">package.config</A><BR>
<A HREF="manual.html#pdf-package.cpath">package.cpath</A><BR>
<A HREF="manual.html#pdf-package.loaded">package.loaded</A><BR>
<A HREF="manual.html#pdf-package.loadlib">package.loadlib</A><BR>
<A HREF="manual.html#pdf-package.path">package.path</A><BR>
<A HREF="manual.html#pdf-package.preload">package.preload</A><BR>
<A HREF="manual.html#pdf-package.searchers">package.searchers</A><BR>
<A HREF="manual.html#pdf-package.searchpath">package.searchpath</A><BR>
<P>
<A HREF="manual.html#6.4">string</A><BR>
<A HREF="manual.html#pdf-string.byte">string.byte</A><BR>
<A HREF="manual.html#pdf-string.char">string.char</A><BR>
<A HREF="manual.html#pdf-string.dump">string.dump</A><BR>
<A HREF="manual.html#pdf-string.find">string.find</A><BR>
<A HREF="manual.html#pdf-string.format">string.format</A><BR>
<A HREF="manual.html#pdf-string.gmatch">string.gmatch</A><BR>
<A HREF="manual.html#pdf-string.gsub">string.gsub</A><BR>
<A HREF="manual.html#pdf-string.len">string.len</A><BR>
<A HREF="manual.html#pdf-string.lower">string.lower</A><BR>
<A HREF="manual.html#pdf-string.match">string.match</A><BR>
<A HREF="manual.html#pdf-string.pack">string.pack</A><BR>
<A HREF="manual.html#pdf-string.packsize">string.packsize</A><BR>
<A HREF="manual.html#pdf-string.rep">string.rep</A><BR>
<A HREF="manual.html#pdf-string.reverse">string.reverse</A><BR>
<A HREF="manual.html#pdf-string.sub">string.sub</A><BR>
<A HREF="manual.html#pdf-string.unpack">string.unpack</A><BR>
<A HREF="manual.html#pdf-string.upper">string.upper</A><BR>
<P>
<A HREF="manual.html#6.6">table</A><BR>
<A HREF="manual.html#pdf-table.concat">table.concat</A><BR>
<A HREF="manual.html#pdf-table.insert">table.insert</A><BR>
<A HREF="manual.html#pdf-table.move">table.move</A><BR>
<A HREF="manual.html#pdf-table.pack">table.pack</A><BR>
<A HREF="manual.html#pdf-table.remove">table.remove</A><BR>
<A HREF="manual.html#pdf-table.sort">table.sort</A><BR>
<A HREF="manual.html#pdf-table.unpack">table.unpack</A><BR>
<P>
<A HREF="manual.html#6.5">utf8</A><BR>
<A HREF="manual.html#pdf-utf8.char">utf8.char</A><BR>
<A HREF="manual.html#pdf-utf8.charpattern">utf8.charpattern</A><BR>
<A HREF="manual.html#pdf-utf8.codepoint">utf8.codepoint</A><BR>
<A HREF="manual.html#pdf-utf8.codes">utf8.codes</A><BR>
<A HREF="manual.html#pdf-utf8.len">utf8.len</A><BR>
<A HREF="manual.html#pdf-utf8.offset">utf8.offset</A><BR>
<H3><A NAME="metamethods">metamethods</A></H3>
<P>
<A HREF="manual.html#2.4">__add</A><BR>
<A HREF="manual.html#2.4">__band</A><BR>
<A HREF="manual.html#2.4">__bnot</A><BR>
<A HREF="manual.html#2.4">__bor</A><BR>
<A HREF="manual.html#2.4">__bxor</A><BR>
<A HREF="manual.html#2.4">__call</A><BR>
<A HREF="manual.html#3.3.8">__close</A><BR>
<A HREF="manual.html#2.4">__concat</A><BR>
<A HREF="manual.html#2.4">__div</A><BR>
<A HREF="manual.html#2.4">__eq</A><BR>
<A HREF="manual.html#2.5.3">__gc</A><BR>
<A HREF="manual.html#2.4">__idiv</A><BR>
<A HREF="manual.html#2.4">__index</A><BR>
<A HREF="manual.html#2.4">__le</A><BR>
<A HREF="manual.html#2.4">__len</A><BR>
<A HREF="manual.html#2.4">__lt</A><BR>
<A HREF="manual.html#pdf-getmetatable">__metatable</A><BR>
<A HREF="manual.html#2.4">__mod</A><BR>
<A HREF="manual.html#2.5.4">__mode</A><BR>
<A HREF="manual.html#2.4">__mul</A><BR>
<A HREF="manual.html#luaL_newmetatable">__name</A><BR>
<A HREF="manual.html#2.4">__newindex</A><BR>
<A HREF="manual.html#pdf-pairs">__pairs</A><BR>
<A HREF="manual.html#2.4">__pow</A><BR>
<A HREF="manual.html#2.4">__shl</A><BR>
<A HREF="manual.html#2.4">__shr</A><BR>
<A HREF="manual.html#2.4">__sub</A><BR>
<A HREF="manual.html#pdf-tostring">__tostring</A><BR>
<A HREF="manual.html#2.4">__unm</A><BR>
<H3><A NAME="env">environment<BR>variables</A></H3>
<P>
<A HREF="manual.html#pdf-LUA_CPATH">LUA_CPATH</A><BR>
<A HREF="manual.html#pdf-LUA_CPATH_5_4">LUA_CPATH_5_4</A><BR>
<A HREF="manual.html#pdf-LUA_INIT">LUA_INIT</A><BR>
<A HREF="manual.html#pdf-LUA_INIT_5_4">LUA_INIT_5_4</A><BR>
<A HREF="manual.html#pdf-LUA_PATH">LUA_PATH</A><BR>
<A HREF="manual.html#pdf-LUA_PATH_5_4">LUA_PATH_5_4</A><BR>
</TD>
<TD>
<H3><A NAME="api">C API</A></H3>
<P>
<A HREF="manual.html#lua_Alloc">lua_Alloc</A><BR>
<A HREF="manual.html#lua_CFunction">lua_CFunction</A><BR>
<A HREF="manual.html#lua_Debug">lua_Debug</A><BR>
<A HREF="manual.html#lua_Hook">lua_Hook</A><BR>
<A HREF="manual.html#lua_Integer">lua_Integer</A><BR>
<A HREF="manual.html#lua_KContext">lua_KContext</A><BR>
<A HREF="manual.html#lua_KFunction">lua_KFunction</A><BR>
<A HREF="manual.html#lua_Number">lua_Number</A><BR>
<A HREF="manual.html#lua_Reader">lua_Reader</A><BR>
<A HREF="manual.html#lua_State">lua_State</A><BR>
<A HREF="manual.html#lua_Unsigned">lua_Unsigned</A><BR>
<A HREF="manual.html#lua_WarnFunction">lua_WarnFunction</A><BR>
<A HREF="manual.html#lua_Writer">lua_Writer</A><BR>
<P>
<A HREF="manual.html#lua_absindex">lua_absindex</A><BR>
<A HREF="manual.html#lua_arith">lua_arith</A><BR>
<A HREF="manual.html#lua_atpanic">lua_atpanic</A><BR>
<A HREF="manual.html#lua_call">lua_call</A><BR>
<A HREF="manual.html#lua_callk">lua_callk</A><BR>
<A HREF="manual.html#lua_checkstack">lua_checkstack</A><BR>
<A HREF="manual.html#lua_close">lua_close</A><BR>
<A HREF="manual.html#lua_closeslot">lua_closeslot</A><BR>
<A HREF="manual.html#lua_compare">lua_compare</A><BR>
<A HREF="manual.html#lua_concat">lua_concat</A><BR>
<A HREF="manual.html#lua_copy">lua_copy</A><BR>
<A HREF="manual.html#lua_createtable">lua_createtable</A><BR>
<A HREF="manual.html#lua_dump">lua_dump</A><BR>
<A HREF="manual.html#lua_error">lua_error</A><BR>
<A HREF="manual.html#lua_gc">lua_gc</A><BR>
<A HREF="manual.html#lua_getallocf">lua_getallocf</A><BR>
<A HREF="manual.html#lua_getextraspace">lua_getextraspace</A><BR>
<A HREF="manual.html#lua_getfield">lua_getfield</A><BR>
<A HREF="manual.html#lua_getglobal">lua_getglobal</A><BR>
<A HREF="manual.html#lua_gethook">lua_gethook</A><BR>
<A HREF="manual.html#lua_gethookcount">lua_gethookcount</A><BR>
<A HREF="manual.html#lua_gethookmask">lua_gethookmask</A><BR>
<A HREF="manual.html#lua_geti">lua_geti</A><BR>
<A HREF="manual.html#lua_getinfo">lua_getinfo</A><BR>
<A HREF="manual.html#lua_getiuservalue">lua_getiuservalue</A><BR>
<A HREF="manual.html#lua_getlocal">lua_getlocal</A><BR>
<A HREF="manual.html#lua_getmetatable">lua_getmetatable</A><BR>
<A HREF="manual.html#lua_getstack">lua_getstack</A><BR>
<A HREF="manual.html#lua_gettable">lua_gettable</A><BR>
<A HREF="manual.html#lua_gettop">lua_gettop</A><BR>
<A HREF="manual.html#lua_getupvalue">lua_getupvalue</A><BR>
<A HREF="manual.html#lua_insert">lua_insert</A><BR>
<A HREF="manual.html#lua_isboolean">lua_isboolean</A><BR>
<A HREF="manual.html#lua_iscfunction">lua_iscfunction</A><BR>
<A HREF="manual.html#lua_isfunction">lua_isfunction</A><BR>
<A HREF="manual.html#lua_isinteger">lua_isinteger</A><BR>
<A HREF="manual.html#lua_islightuserdata">lua_islightuserdata</A><BR>
<A HREF="manual.html#lua_isnil">lua_isnil</A><BR>
<A HREF="manual.html#lua_isnone">lua_isnone</A><BR>
<A HREF="manual.html#lua_isnoneornil">lua_isnoneornil</A><BR>
<A HREF="manual.html#lua_isnumber">lua_isnumber</A><BR>
<A HREF="manual.html#lua_isstring">lua_isstring</A><BR>
<A HREF="manual.html#lua_istable">lua_istable</A><BR>
<A HREF="manual.html#lua_isthread">lua_isthread</A><BR>
<A HREF="manual.html#lua_isuserdata">lua_isuserdata</A><BR>
<A HREF="manual.html#lua_isyieldable">lua_isyieldable</A><BR>
<A HREF="manual.html#lua_len">lua_len</A><BR>
<A HREF="manual.html#lua_load">lua_load</A><BR>
<A HREF="manual.html#lua_newstate">lua_newstate</A><BR>
<A HREF="manual.html#lua_newtable">lua_newtable</A><BR>
<A HREF="manual.html#lua_newthread">lua_newthread</A><BR>
<A HREF="manual.html#lua_newuserdatauv">lua_newuserdatauv</A><BR>
<A HREF="manual.html#lua_next">lua_next</A><BR>
<A HREF="manual.html#lua_numbertointeger">lua_numbertointeger</A><BR>
<A HREF="manual.html#lua_pcall">lua_pcall</A><BR>
<A HREF="manual.html#lua_pcallk">lua_pcallk</A><BR>
<A HREF="manual.html#lua_pop">lua_pop</A><BR>
<A HREF="manual.html#lua_pushboolean">lua_pushboolean</A><BR>
<A HREF="manual.html#lua_pushcclosure">lua_pushcclosure</A><BR>
<A HREF="manual.html#lua_pushcfunction">lua_pushcfunction</A><BR>
<A HREF="manual.html#lua_pushfstring">lua_pushfstring</A><BR>
<A HREF="manual.html#lua_pushglobaltable">lua_pushglobaltable</A><BR>
<A HREF="manual.html#lua_pushinteger">lua_pushinteger</A><BR>
<A HREF="manual.html#lua_pushlightuserdata">lua_pushlightuserdata</A><BR>
<A HREF="manual.html#lua_pushliteral">lua_pushliteral</A><BR>
<A HREF="manual.html#lua_pushlstring">lua_pushlstring</A><BR>
<A HREF="manual.html#lua_pushnil">lua_pushnil</A><BR>
<A HREF="manual.html#lua_pushnumber">lua_pushnumber</A><BR>
<A HREF="manual.html#lua_pushstring">lua_pushstring</A><BR>
<A HREF="manual.html#lua_pushthread">lua_pushthread</A><BR>
<A HREF="manual.html#lua_pushvalue">lua_pushvalue</A><BR>
<A HREF="manual.html#lua_pushvfstring">lua_pushvfstring</A><BR>
<A HREF="manual.html#lua_rawequal">lua_rawequal</A><BR>
<A HREF="manual.html#lua_rawget">lua_rawget</A><BR>
<A HREF="manual.html#lua_rawgeti">lua_rawgeti</A><BR>
<A HREF="manual.html#lua_rawgetp">lua_rawgetp</A><BR>
<A HREF="manual.html#lua_rawlen">lua_rawlen</A><BR>
<A HREF="manual.html#lua_rawset">lua_rawset</A><BR>
<A HREF="manual.html#lua_rawseti">lua_rawseti</A><BR>
<A HREF="manual.html#lua_rawsetp">lua_rawsetp</A><BR>
<A HREF="manual.html#lua_register">lua_register</A><BR>
<A HREF="manual.html#lua_remove">lua_remove</A><BR>
<A HREF="manual.html#lua_replace">lua_replace</A><BR>
<A HREF="manual.html#lua_resetthread">lua_resetthread</A><BR>
<A HREF="manual.html#lua_resume">lua_resume</A><BR>
<A HREF="manual.html#lua_rotate">lua_rotate</A><BR>
<A HREF="manual.html#lua_setallocf">lua_setallocf</A><BR>
<A HREF="manual.html#lua_setfield">lua_setfield</A><BR>
<A HREF="manual.html#lua_setglobal">lua_setglobal</A><BR>
<A HREF="manual.html#lua_sethook">lua_sethook</A><BR>
<A HREF="manual.html#lua_seti">lua_seti</A><BR>
<A HREF="manual.html#lua_setiuservalue">lua_setiuservalue</A><BR>
<A HREF="manual.html#lua_setlocal">lua_setlocal</A><BR>
<A HREF="manual.html#lua_setmetatable">lua_setmetatable</A><BR>
<A HREF="manual.html#lua_settable">lua_settable</A><BR>
<A HREF="manual.html#lua_settop">lua_settop</A><BR>
<A HREF="manual.html#lua_setupvalue">lua_setupvalue</A><BR>
<A HREF="manual.html#lua_setwarnf">lua_setwarnf</A><BR>
<A HREF="manual.html#lua_status">lua_status</A><BR>
<A HREF="manual.html#lua_stringtonumber">lua_stringtonumber</A><BR>
<A HREF="manual.html#lua_toboolean">lua_toboolean</A><BR>
<A HREF="manual.html#lua_tocfunction">lua_tocfunction</A><BR>
<A HREF="manual.html#lua_toclose">lua_toclose</A><BR>
<A HREF="manual.html#lua_tointeger">lua_tointeger</A><BR>
<A HREF="manual.html#lua_tointegerx">lua_tointegerx</A><BR>
<A HREF="manual.html#lua_tolstring">lua_tolstring</A><BR>
<A HREF="manual.html#lua_tonumber">lua_tonumber</A><BR>
<A HREF="manual.html#lua_tonumberx">lua_tonumberx</A><BR>
<A HREF="manual.html#lua_topointer">lua_topointer</A><BR>
<A HREF="manual.html#lua_tostring">lua_tostring</A><BR>
<A HREF="manual.html#lua_tothread">lua_tothread</A><BR>
<A HREF="manual.html#lua_touserdata">lua_touserdata</A><BR>
<A HREF="manual.html#lua_type">lua_type</A><BR>
<A HREF="manual.html#lua_typename">lua_typename</A><BR>
<A HREF="manual.html#lua_upvalueid">lua_upvalueid</A><BR>
<A HREF="manual.html#lua_upvalueindex">lua_upvalueindex</A><BR>
<A HREF="manual.html#lua_upvaluejoin">lua_upvaluejoin</A><BR>
<A HREF="manual.html#lua_version">lua_version</A><BR>
<A HREF="manual.html#lua_warning">lua_warning</A><BR>
<A HREF="manual.html#lua_xmove">lua_xmove</A><BR>
<A HREF="manual.html#lua_yield">lua_yield</A><BR>
<A HREF="manual.html#lua_yieldk">lua_yieldk</A><BR>
</TD>
<TD>
<H3><A NAME="auxlib">auxiliary library</A></H3>
<P>
<A HREF="manual.html#luaL_Buffer">luaL_Buffer</A><BR>
<A HREF="manual.html#luaL_Reg">luaL_Reg</A><BR>
<A HREF="manual.html#luaL_Stream">luaL_Stream</A><BR>
<P>
<A HREF="manual.html#luaL_addchar">luaL_addchar</A><BR>
<A HREF="manual.html#luaL_addgsub">luaL_addgsub</A><BR>
<A HREF="manual.html#luaL_addlstring">luaL_addlstring</A><BR>
<A HREF="manual.html#luaL_addsize">luaL_addsize</A><BR>
<A HREF="manual.html#luaL_addstring">luaL_addstring</A><BR>
<A HREF="manual.html#luaL_addvalue">luaL_addvalue</A><BR>
<A HREF="manual.html#luaL_argcheck">luaL_argcheck</A><BR>
<A HREF="manual.html#luaL_argerror">luaL_argerror</A><BR>
<A HREF="manual.html#luaL_argexpected">luaL_argexpected</A><BR>
<A HREF="manual.html#luaL_buffaddr">luaL_buffaddr</A><BR>
<A HREF="manual.html#luaL_buffinit">luaL_buffinit</A><BR>
<A HREF="manual.html#luaL_buffinitsize">luaL_buffinitsize</A><BR>
<A HREF="manual.html#luaL_bufflen">luaL_bufflen</A><BR>
<A HREF="manual.html#luaL_buffsub">luaL_buffsub</A><BR>
<A HREF="manual.html#luaL_callmeta">luaL_callmeta</A><BR>
<A HREF="manual.html#luaL_checkany">luaL_checkany</A><BR>
<A HREF="manual.html#luaL_checkinteger">luaL_checkinteger</A><BR>
<A HREF="manual.html#luaL_checklstring">luaL_checklstring</A><BR>
<A HREF="manual.html#luaL_checknumber">luaL_checknumber</A><BR>
<A HREF="manual.html#luaL_checkoption">luaL_checkoption</A><BR>
<A HREF="manual.html#luaL_checkstack">luaL_checkstack</A><BR>
<A HREF="manual.html#luaL_checkstring">luaL_checkstring</A><BR>
<A HREF="manual.html#luaL_checktype">luaL_checktype</A><BR>
<A HREF="manual.html#luaL_checkudata">luaL_checkudata</A><BR>
<A HREF="manual.html#luaL_checkversion">luaL_checkversion</A><BR>
<A HREF="manual.html#luaL_dofile">luaL_dofile</A><BR>
<A HREF="manual.html#luaL_dostring">luaL_dostring</A><BR>
<A HREF="manual.html#luaL_error">luaL_error</A><BR>
<A HREF="manual.html#luaL_execresult">luaL_execresult</A><BR>
<A HREF="manual.html#luaL_fileresult">luaL_fileresult</A><BR>
<A HREF="manual.html#luaL_getmetafield">luaL_getmetafield</A><BR>
<A HREF="manual.html#luaL_getmetatable">luaL_getmetatable</A><BR>
<A HREF="manual.html#luaL_getsubtable">luaL_getsubtable</A><BR>
<A HREF="manual.html#luaL_gsub">luaL_gsub</A><BR>
<A HREF="manual.html#luaL_len">luaL_len</A><BR>
<A HREF="manual.html#luaL_loadbuffer">luaL_loadbuffer</A><BR>
<A HREF="manual.html#luaL_loadbufferx">luaL_loadbufferx</A><BR>
<A HREF="manual.html#luaL_loadfile">luaL_loadfile</A><BR>
<A HREF="manual.html#luaL_loadfilex">luaL_loadfilex</A><BR>
<A HREF="manual.html#luaL_loadstring">luaL_loadstring</A><BR>
<A HREF="manual.html#luaL_newlib">luaL_newlib</A><BR>
<A HREF="manual.html#luaL_newlibtable">luaL_newlibtable</A><BR>
<A HREF="manual.html#luaL_newmetatable">luaL_newmetatable</A><BR>
<A HREF="manual.html#luaL_newstate">luaL_newstate</A><BR>
<A HREF="manual.html#luaL_openlibs">luaL_openlibs</A><BR>
<A HREF="manual.html#luaL_opt">luaL_opt</A><BR>
<A HREF="manual.html#luaL_optinteger">luaL_optinteger</A><BR>
<A HREF="manual.html#luaL_optlstring">luaL_optlstring</A><BR>
<A HREF="manual.html#luaL_optnumber">luaL_optnumber</A><BR>
<A HREF="manual.html#luaL_optstring">luaL_optstring</A><BR>
<A HREF="manual.html#luaL_prepbuffer">luaL_prepbuffer</A><BR>
<A HREF="manual.html#luaL_prepbuffsize">luaL_prepbuffsize</A><BR>
<A HREF="manual.html#luaL_pushfail">luaL_pushfail</A><BR>
<A HREF="manual.html#luaL_pushresult">luaL_pushresult</A><BR>
<A HREF="manual.html#luaL_pushresultsize">luaL_pushresultsize</A><BR>
<A HREF="manual.html#luaL_ref">luaL_ref</A><BR>
<A HREF="manual.html#luaL_requiref">luaL_requiref</A><BR>
<A HREF="manual.html#luaL_setfuncs">luaL_setfuncs</A><BR>
<A HREF="manual.html#luaL_setmetatable">luaL_setmetatable</A><BR>
<A HREF="manual.html#luaL_testudata">luaL_testudata</A><BR>
<A HREF="manual.html#luaL_tolstring">luaL_tolstring</A><BR>
<A HREF="manual.html#luaL_traceback">luaL_traceback</A><BR>
<A HREF="manual.html#luaL_typeerror">luaL_typeerror</A><BR>
<A HREF="manual.html#luaL_typename">luaL_typename</A><BR>
<A HREF="manual.html#luaL_unref">luaL_unref</A><BR>
<A HREF="manual.html#luaL_where">luaL_where</A><BR>
<H3><A NAME="library">standard library</A></H3>
<P>
<A HREF="manual.html#pdf-luaopen_base">luaopen_base</A><BR>
<A HREF="manual.html#pdf-luaopen_coroutine">luaopen_coroutine</A><BR>
<A HREF="manual.html#pdf-luaopen_debug">luaopen_debug</A><BR>
<A HREF="manual.html#pdf-luaopen_io">luaopen_io</A><BR>
<A HREF="manual.html#pdf-luaopen_math">luaopen_math</A><BR>
<A HREF="manual.html#pdf-luaopen_os">luaopen_os</A><BR>
<A HREF="manual.html#pdf-luaopen_package">luaopen_package</A><BR>
<A HREF="manual.html#pdf-luaopen_string">luaopen_string</A><BR>
<A HREF="manual.html#pdf-luaopen_table">luaopen_table</A><BR>
<A HREF="manual.html#pdf-luaopen_utf8">luaopen_utf8</A><BR>
<H3><A NAME="constants">constants</A></H3>
<P>
<A HREF="manual.html#pdf-LUA_ERRERR">LUA_ERRERR</A><BR>
<A HREF="manual.html#pdf-LUA_ERRFILE">LUA_ERRFILE</A><BR>
<A HREF="manual.html#pdf-LUA_ERRMEM">LUA_ERRMEM</A><BR>
<A HREF="manual.html#pdf-LUA_ERRRUN">LUA_ERRRUN</A><BR>
<A HREF="manual.html#pdf-LUA_ERRSYNTAX">LUA_ERRSYNTAX</A><BR>
<A HREF="manual.html#pdf-LUA_HOOKCALL">LUA_HOOKCALL</A><BR>
<A HREF="manual.html#pdf-LUA_HOOKCOUNT">LUA_HOOKCOUNT</A><BR>
<A HREF="manual.html#pdf-LUA_HOOKLINE">LUA_HOOKLINE</A><BR>
<A HREF="manual.html#pdf-LUA_HOOKRET">LUA_HOOKRET</A><BR>
<A HREF="manual.html#pdf-LUA_HOOKTAILCALL">LUA_HOOKTAILCALL</A><BR>
<A HREF="manual.html#pdf-LUA_LOADED_TABLE">LUA_LOADED_TABLE</A><BR>
<A HREF="manual.html#pdf-LUA_MASKCALL">LUA_MASKCALL</A><BR>
<A HREF="manual.html#pdf-LUA_MASKCOUNT">LUA_MASKCOUNT</A><BR>
<A HREF="manual.html#pdf-LUA_MASKLINE">LUA_MASKLINE</A><BR>
<A HREF="manual.html#pdf-LUA_MASKRET">LUA_MASKRET</A><BR>
<A HREF="manual.html#pdf-LUA_MAXINTEGER">LUA_MAXINTEGER</A><BR>
<A HREF="manual.html#pdf-LUA_MININTEGER">LUA_MININTEGER</A><BR>
<A HREF="manual.html#pdf-LUA_MINSTACK">LUA_MINSTACK</A><BR>
<A HREF="manual.html#pdf-LUA_MULTRET">LUA_MULTRET</A><BR>
<A HREF="manual.html#pdf-LUA_NOREF">LUA_NOREF</A><BR>
<A HREF="manual.html#pdf-LUA_OK">LUA_OK</A><BR>
<A HREF="manual.html#pdf-LUA_OPADD">LUA_OPADD</A><BR>
<A HREF="manual.html#pdf-LUA_OPBAND">LUA_OPBAND</A><BR>
<A HREF="manual.html#pdf-LUA_OPBNOT">LUA_OPBNOT</A><BR>
<A HREF="manual.html#pdf-LUA_OPBOR">LUA_OPBOR</A><BR>
<A HREF="manual.html#pdf-LUA_OPBXOR">LUA_OPBXOR</A><BR>
<A HREF="manual.html#pdf-LUA_OPDIV">LUA_OPDIV</A><BR>
<A HREF="manual.html#pdf-LUA_OPEQ">LUA_OPEQ</A><BR>
<A HREF="manual.html#pdf-LUA_OPIDIV">LUA_OPIDIV</A><BR>
<A HREF="manual.html#pdf-LUA_OPLE">LUA_OPLE</A><BR>
<A HREF="manual.html#pdf-LUA_OPLT">LUA_OPLT</A><BR>
<A HREF="manual.html#pdf-LUA_OPMOD">LUA_OPMOD</A><BR>
<A HREF="manual.html#pdf-LUA_OPMUL">LUA_OPMUL</A><BR>
<A HREF="manual.html#pdf-LUA_OPPOW">LUA_OPPOW</A><BR>
<A HREF="manual.html#pdf-LUA_OPSHL">LUA_OPSHL</A><BR>
<A HREF="manual.html#pdf-LUA_OPSHR">LUA_OPSHR</A><BR>
<A HREF="manual.html#pdf-LUA_OPSUB">LUA_OPSUB</A><BR>
<A HREF="manual.html#pdf-LUA_OPUNM">LUA_OPUNM</A><BR>
<A HREF="manual.html#pdf-LUA_PRELOAD_TABLE">LUA_PRELOAD_TABLE</A><BR>
<A HREF="manual.html#pdf-LUA_REFNIL">LUA_REFNIL</A><BR>
<A HREF="manual.html#pdf-LUA_REGISTRYINDEX">LUA_REGISTRYINDEX</A><BR>
<A HREF="manual.html#pdf-LUA_RIDX_GLOBALS">LUA_RIDX_GLOBALS</A><BR>
<A HREF="manual.html#pdf-LUA_RIDX_MAINTHREAD">LUA_RIDX_MAINTHREAD</A><BR>
<A HREF="manual.html#pdf-LUA_TBOOLEAN">LUA_TBOOLEAN</A><BR>
<A HREF="manual.html#pdf-LUA_TFUNCTION">LUA_TFUNCTION</A><BR>
<A HREF="manual.html#pdf-LUA_TLIGHTUSERDATA">LUA_TLIGHTUSERDATA</A><BR>
<A HREF="manual.html#pdf-LUA_TNIL">LUA_TNIL</A><BR>
<A HREF="manual.html#pdf-LUA_TNONE">LUA_TNONE</A><BR>
<A HREF="manual.html#pdf-LUA_TNUMBER">LUA_TNUMBER</A><BR>
<A HREF="manual.html#pdf-LUA_TSTRING">LUA_TSTRING</A><BR>
<A HREF="manual.html#pdf-LUA_TTABLE">LUA_TTABLE</A><BR>
<A HREF="manual.html#pdf-LUA_TTHREAD">LUA_TTHREAD</A><BR>
<A HREF="manual.html#pdf-LUA_TUSERDATA">LUA_TUSERDATA</A><BR>
<A HREF="manual.html#pdf-LUA_USE_APICHECK">LUA_USE_APICHECK</A><BR>
<A HREF="manual.html#pdf-LUA_YIELD">LUA_YIELD</A><BR>
<A HREF="manual.html#pdf-LUAL_BUFFERSIZE">LUAL_BUFFERSIZE</A><BR>
</TD>
</TR>
</TABLE>
<P CLASS="footer">
Last update:
Thu May 9 14:47:09 UTC 2024
</P>
<!--
Last change: revised for Lua 5.4.7
-->
</BODY>
</HTML>
+21
View File
@@ -0,0 +1,21 @@
ul {
list-style-type: none ;
}
ul.contents {
padding: 0 ;
}
table {
border: none ;
border-spacing: 0 ;
border-collapse: collapse ;
}
td {
vertical-align: top ;
padding: 0 ;
text-align: left ;
line-height: 1.25 ;
width: 15% ;
}
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 9.7 KiB

+155
View File
@@ -0,0 +1,155 @@
.\" $Id: lua.man,v 1.14 2024/05/08 18:48:27 lhf Exp $
.TH LUA 1 "$Date: 2024/05/08 18:48:27 $"
.SH NAME
lua \- Lua interpreter
.SH SYNOPSIS
.B lua
[
.I options
]
[
.I script
[
.I args
]
]
.SH DESCRIPTION
.B lua
is the standalone Lua interpreter.
It loads and executes Lua programs,
either in textual source form or
in precompiled binary form.
(Precompiled binaries are output by
.BR luac ,
the Lua compiler.)
.B lua
can be used as a batch interpreter and also interactively.
.LP
After handling the
.IR options ,
the Lua program in file
.I script
is loaded and executed.
The
.I args
are available to
.I script
as strings in a global table named
.B arg
and also as arguments to its main function.
When called without arguments,
.B lua
behaves as
.B "lua \-v \-i"
if the standard input is a terminal,
and as
.B "lua \-"
otherwise.
.LP
In interactive mode,
.B lua
prompts the user,
reads lines from the standard input,
and executes them as they are read.
If the line contains an expression,
then the line is evaluated and the result is printed.
If a line does not contain a complete statement,
then a secondary prompt is displayed and
lines are read until a complete statement is formed or
a syntax error is found.
.LP
Before handling command line options and scripts,
.B lua
checks the contents of the environment variables
.B LUA_INIT_5_4
and
.BR LUA_INIT ,
in that order.
If the contents are of the form
.RI '@ filename ',
then
.I filename
is executed.
Otherwise, the contents are assumed to be a Lua statement and is executed.
When
.B LUA_INIT_5_4
is defined,
.B LUA_INIT
is ignored.
.SH OPTIONS
.TP
.BI \-e " stat"
execute statement
.IR stat .
.TP
.B \-i
enter interactive mode after executing
.IR script .
.TP
.BI \-l " mod"
require library
.I mod
into global
.IR mod .
.TP
.BI \-l " g=mod"
require library
.I mod
into global
.IR g .
.TP
.B \-v
show version information.
.TP
.B \-E
ignore environment variables.
.TP
.B \-W
turn warnings on.
.TP
.B \-\-
stop handling options.
.TP
.B \-
stop handling options and execute the standard input as a file.
.SH ENVIRONMENT VARIABLES
The following environment variables affect the execution of
.BR lua .
When defined,
the version-specific variants take priority
and the version-neutral variants are ignored.
.TP
.B LUA_INIT, LUA_INIT_5_4
Code to be executed before command line options and scripts.
.TP
.B LUA_PATH, LUA_PATH_5_4
Initial value of package.path,
the path used by require to search for Lua loaders.
.TP
.B LUA_CPATH, LUA_CPATH_5_4
Initial value of package.cpath,
the path used by require to search for C loaders.
.SH EXIT STATUS
If a script calls os.exit,
then
.B lua
exits with the given exit status.
Otherwise,
.B lua
exits
with EXIT_SUCCESS (0 on POSIX systems) if there were no errors
and
with EXIT_FAILURE (1 on POSIX systems) if there were errors.
Errors raised in interactive mode do not cause exits.
.SH DIAGNOSTICS
Error messages should be self explanatory.
.SH "SEE ALSO"
.BR luac (1)
.br
The documentation at lua.org,
especially section 7 of the reference manual.
.SH AUTHORS
R. Ierusalimschy,
L. H. de Figueiredo,
W. Celes
.\" EOF
+162
View File
@@ -0,0 +1,162 @@
html {
background-color: #F8F8F8 ;
}
body {
background-color: #FFFFFF ;
color: #000000 ;
font-family: Helvetica, Arial, sans-serif ;
text-align: justify ;
line-height: 1.25 ;
margin: 16px auto ;
padding: 32px ;
border: solid #ccc 1px ;
border-radius: 20px ;
max-width: 70em ;
width: 90% ;
}
h1, h2, h3, h4 {
color: #000080 ;
font-family: Verdana, Geneva, sans-serif ;
font-weight: normal ;
font-style: normal ;
text-align: left ;
}
h1 {
font-size: 28pt ;
}
h1 img {
vertical-align: text-bottom ;
}
h2:before {
content: "\2756" ;
padding-right: 0.5em ;
}
a {
text-decoration: none ;
}
a:link {
color: #000080 ;
}
a:link:hover, a:visited:hover {
background-color: #D0D0FF ;
color: #000080 ;
border-radius: 4px ;
}
a:link:active, a:visited:active {
color: #FF0000 ;
}
div.menubar {
padding-bottom: 0.5em ;
}
p.menubar {
margin-left: 2.5em ;
}
.menubar a:hover {
margin: -3px -3px -3px -3px ;
padding: 3px 3px 3px 3px ;
border-radius: 4px ;
}
:target {
background-color: #F0F0F0 ;
margin: -8px ;
padding: 8px ;
border-radius: 8px ;
outline: none ;
}
hr {
display: none ;
}
table hr {
background-color: #a0a0a0 ;
color: #a0a0a0 ;
border: 0 ;
height: 1px ;
display: block ;
}
.footer {
color: gray ;
font-size: x-small ;
text-transform: lowercase ;
}
input[type=text] {
border: solid #a0a0a0 2px ;
border-radius: 2em ;
background-image: url('images/search.png') ;
background-repeat: no-repeat ;
background-position: 4px center ;
padding-left: 20px ;
height: 2em ;
}
pre.session {
background-color: #F8F8F8 ;
padding: 1em ;
border-radius: 8px ;
}
table {
border: none ;
border-spacing: 0 ;
border-collapse: collapse ;
}
td {
padding: 0 ;
margin: 0 ;
}
td.gutter {
width: 4% ;
}
table.columns td {
vertical-align: top ;
padding-bottom: 1em ;
text-align: justify ;
line-height: 1.25 ;
}
table.book td {
vertical-align: top ;
}
table.book td.cover {
padding-right: 1em ;
}
table.book img {
border: solid #000080 1px ;
border-radius: 2px ;
}
table.book span {
font-size: small ;
text-align: left ;
display: block ;
margin-top: 0.25em ;
}
p.logos a:link:hover, p.logos a:visited:hover {
background-color: inherit ;
}
img {
background-color: white ;
}
+118
View File
@@ -0,0 +1,118 @@
.\" $Id: luac.man,v 1.29 2011/11/16 13:53:40 lhf Exp $
.TH LUAC 1 "$Date: 2011/11/16 13:53:40 $"
.SH NAME
luac \- Lua compiler
.SH SYNOPSIS
.B luac
[
.I options
] [
.I filenames
]
.SH DESCRIPTION
.B luac
is the Lua compiler.
It translates programs written in the Lua programming language
into binary files containing precompiled chunks
that can be later loaded and executed.
.LP
The main advantages of precompiling chunks are:
faster loading,
protecting source code from accidental user changes,
and
off-line syntax checking.
Precompiling does not imply faster execution
because in Lua chunks are always compiled into bytecodes before being executed.
.B luac
simply allows those bytecodes to be saved in a file for later execution.
Precompiled chunks are not necessarily smaller than the corresponding source.
The main goal in precompiling is faster loading.
.LP
In the command line,
you can mix
text files containing Lua source and
binary files containing precompiled chunks.
.B luac
produces a single output file containing the combined bytecodes
for all files given.
Executing the combined file is equivalent to executing the given files.
By default,
the output file is named
.BR luac.out ,
but you can change this with the
.B \-o
option.
.LP
Precompiled chunks are
.I not
portable across different architectures.
Moreover,
the internal format of precompiled chunks
is likely to change when a new version of Lua is released.
Make sure you save the source files of all Lua programs that you precompile.
.LP
.SH OPTIONS
.TP
.B \-l
produce a listing of the compiled bytecode for Lua's virtual machine.
Listing bytecodes is useful to learn about Lua's virtual machine.
If no files are given, then
.B luac
loads
.B luac.out
and lists its contents.
Use
.B \-l \-l
for a full listing.
.TP
.BI \-o " file"
output to
.IR file ,
instead of the default
.BR luac.out .
(You can use
.B "'\-'"
for standard output,
but not on platforms that open standard output in text mode.)
The output file may be one of the given files because
all files are loaded before the output file is written.
Be careful not to overwrite precious files.
.TP
.B \-p
load files but do not generate any output file.
Used mainly for syntax checking and for testing precompiled chunks:
corrupted files will probably generate errors when loaded.
If no files are given, then
.B luac
loads
.B luac.out
and tests its contents.
No messages are displayed if the file loads without errors.
.TP
.B \-s
strip debug information before writing the output file.
This saves some space in very large chunks,
but if errors occur when running a stripped chunk,
then the error messages may not contain the full information they usually do.
In particular,
line numbers and names of local variables are lost.
.TP
.B \-v
show version information.
.TP
.B \-\-
stop handling options.
.TP
.B \-
stop handling options and process standard input.
.SH "SEE ALSO"
.BR lua (1)
.br
The documentation at lua.org.
.SH DIAGNOSTICS
Error messages should be self explanatory.
.SH AUTHORS
R. Ierusalimschy,
L. H. de Figueiredo,
W. Celes
.\" EOF
+21
View File
@@ -0,0 +1,21 @@
h3 code {
font-family: inherit ;
font-size: inherit ;
}
pre, code {
font-size: 12pt ;
}
span.apii {
color: gray ;
float: right ;
font-family: inherit ;
font-style: normal ;
font-size: small ;
}
h2:before {
content: "" ;
padding-right: 0em ;
}
+12060
View File
File diff suppressed because it is too large Load Diff
+339
View File
@@ -0,0 +1,339 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<HTML>
<HEAD>
<TITLE>Lua 5.4 readme</TITLE>
<LINK REL="stylesheet" TYPE="text/css" HREF="lua.css">
<META HTTP-EQUIV="content-type" CONTENT="text/html; charset=iso-8859-1">
<STYLE TYPE="text/css">
blockquote, .display {
border: solid #a0a0a0 2px ;
border-radius: 8px ;
padding: 1em ;
margin: 0px ;
}
.display {
word-spacing: 0.25em ;
}
dl.display dd {
padding-bottom: 0.2em ;
}
tt, kbd, code {
font-size: 12pt ;
}
</STYLE>
</HEAD>
<BODY>
<H1>
<A HREF="https://www.lua.org/"><IMG SRC="logo.gif" ALT="Lua"></A>
Welcome to Lua 5.4
</H1>
<DIV CLASS="menubar">
<A HREF="#about">about</A>
&middot;
<A HREF="#install">installation</A>
&middot;
<A HREF="#changes">changes</A>
&middot;
<A HREF="#license">license</A>
&middot;
<A HREF="contents.html">reference manual</A>
</DIV>
<H2><A NAME="about">About Lua</A></H2>
<P>
Lua is a powerful, efficient, lightweight, embeddable scripting language
developed by a
<A HREF="https://www.lua.org/authors.html">team</A>
at
<A HREF="https://www.puc-rio.br/">PUC-Rio</A>,
the Pontifical Catholic University of Rio de Janeiro in Brazil.
Lua is
<A HREF="#license">free software</A>
used in
<A HREF="https://www.lua.org/uses.html">many products and projects</A>
around the world.
<P>
Lua's
<A HREF="https://www.lua.org/">official website</A>
provides complete information
about Lua,
including
an
<A HREF="https://www.lua.org/about.html">executive summary</A>,
tips on
<A HREF="https://www.lua.org/start.html">getting started</A>,
and
updated
<A HREF="https://www.lua.org/docs.html">documentation</A>,
especially the
<A HREF="https://www.lua.org/manual/5.4/">reference manual</A>,
which may differ slightly from the
<A HREF="contents.html">local copy</A>
distributed in this package.
<H2><A NAME="install">Installing Lua</A></H2>
<P>
Lua is distributed in
<A HREF="https://www.lua.org/ftp/">source</A>
form.
You need to build it before using it.
Building Lua should be straightforward
because
Lua is implemented in pure ANSI C and compiles unmodified in all known
platforms that have an ANSI C compiler.
Lua also compiles unmodified as C++.
The instructions given below for building Lua are for Unix-like platforms,
such as Linux and macOS.
See also
<A HREF="#other">instructions for other systems</A>
and
<A HREF="#customization">customization options</A>.
<P>
If you don't have the time or the inclination to compile Lua yourself,
get a binary from
<A HREF="https://luabinaries.sourceforge.net">LuaBinaries</A>.
<H3>Building Lua</H3>
<P>
In most common Unix-like platforms, simply do "<KBD>make</KBD>".
Here are the details.
<OL>
<LI>
Open a terminal window and move to
the top-level directory, which is named <TT>lua-5.4.7</TT>.
The <TT>Makefile</TT> there controls both the build process and the installation process.
<P>
<LI>
Do "<KBD>make</KBD>". The <TT>Makefile</TT> will guess your platform and build Lua for it.
<P>
<LI>
If the guess failed, do "<KBD>make help</KBD>" and see if your platform is listed.
The platforms currently supported are:
<P>
<P CLASS="display">
guess aix bsd c89 freebsd generic ios linux linux-readline macosx mingw posix solaris
</P>
<P>
If your platform is listed, just do "<KBD>make xxx</KBD>", where xxx
is your platform name.
<P>
If your platform is not listed, try the closest one or posix, generic,
c89, in this order.
<P>
<LI>
The compilation takes only a few moments
and produces three files in the <TT>src</TT> directory:
lua (the interpreter),
luac (the compiler),
and liblua.a (the library).
<P>
<LI>
To check that Lua has been built correctly, do "<KBD>make test</KBD>"
after building Lua. This will run the interpreter and print its version.
</OL>
<P>
If you're running Linux, try "<KBD>make linux-readline</KBD>" to build the interactive Lua interpreter with handy line-editing and history capabilities.
If you get compilation errors,
make sure you have installed the <TT>readline</TT> development package
(which is probably named <TT>libreadline-dev</TT> or <TT>readline-devel</TT>).
If you get link errors after that,
then try "<KBD>make linux-readline MYLIBS=-ltermcap</KBD>".
<H3>Installing Lua</H3>
<P>
Once you have built Lua, you may want to install it in an official
place in your system. In this case, do "<KBD>make install</KBD>". The official
place and the way to install files are defined in the <TT>Makefile</TT>. You'll
probably need the right permissions to install files, and so may need to do "<KBD>sudo make install</KBD>".
<P>
To build and install Lua in one step, do "<KBD>make all install</KBD>",
or "<KBD>make xxx install</KBD>",
where xxx is your platform name.
<P>
To install Lua locally after building it, do "<KBD>make local</KBD>".
This will create a directory <TT>install</TT> with subdirectories
<TT>bin</TT>, <TT>include</TT>, <TT>lib</TT>, <TT>man</TT>, <TT>share</TT>,
and install Lua as listed below.
To install Lua locally, but in some other directory, do
"<KBD>make install INSTALL_TOP=xxx</KBD>", where xxx is your chosen directory.
The installation starts in the <TT>src</TT> and <TT>doc</TT> directories,
so take care if <TT>INSTALL_TOP</TT> is not an absolute path.
<DL CLASS="display">
<DT>
bin:
<DD>
lua luac
<DT>
include:
<DD>
lua.h luaconf.h lualib.h lauxlib.h lua.hpp
<DT>
lib:
<DD>
liblua.a
<DT>
man/man1:
<DD>
lua.1 luac.1
</DL>
<P>
These are the only directories you need for development.
If you only want to run Lua programs,
you only need the files in <TT>bin</TT> and <TT>man</TT>.
The files in <TT>include</TT> and <TT>lib</TT> are needed for
embedding Lua in C or C++ programs.
<H3><A NAME="customization">Customization</A></H3>
<P>
Three kinds of things can be customized by editing a file:
<UL>
<LI> Where and how to install Lua &mdash; edit <TT>Makefile</TT>.
<LI> How to build Lua &mdash; edit <TT>src/Makefile</TT>.
<LI> Lua features &mdash; edit <TT>src/luaconf.h</TT>.
</UL>
<P>
You don't actually need to edit the Makefiles because you may set the
relevant variables in the command line when invoking make.
Nevertheless, it's probably best to edit and save the Makefiles to
record the changes you've made.
<P>
On the other hand, if you need to customize some Lua features,
edit <TT>src/luaconf.h</TT> before building and installing Lua.
The edited file will be the one installed, and
it will be used by any Lua clients that you build, to ensure consistency.
Further customization is available to experts by editing the Lua sources.
<H3><A NAME="other">Building Lua on other systems</A></H3>
<P>
If you're not using the usual Unix tools, then the instructions for
building Lua depend on the compiler you use. You'll need to create
projects (or whatever your compiler uses) for building the library,
the interpreter, and the compiler, as follows:
<DL CLASS="display">
<DT>
library:
<DD>
lapi.c lcode.c lctype.c ldebug.c ldo.c ldump.c lfunc.c lgc.c llex.c lmem.c lobject.c lopcodes.c lparser.c lstate.c lstring.c ltable.c ltm.c lundump.c lvm.c lzio.c
lauxlib.c lbaselib.c lcorolib.c ldblib.c liolib.c lmathlib.c loadlib.c loslib.c lstrlib.c ltablib.c lutf8lib.c linit.c
<DT>
interpreter:
<DD>
library, lua.c
<DT>
compiler:
<DD>
library, luac.c
</DL>
<P>
To use Lua as a library in your own programs, you need to know how to
create and use libraries with your compiler. Moreover, to dynamically load
C libraries for Lua, you'll need to know how to create dynamic libraries
and you'll need to make sure that the Lua API functions are accessible to
those dynamic libraries &mdash; but <EM>don't</EM> link the Lua library
into each dynamic library. For Unix, we recommend that the Lua library
be linked statically into the host program and its symbols exported for
dynamic linking; <TT>src/Makefile</TT> does this for the Lua interpreter.
For Windows, we recommend that the Lua library be a DLL.
In all cases, the compiler luac should be linked statically.
<P>
As mentioned above, you may edit <TT>src/luaconf.h</TT> to customize
some features before building Lua.
<H2><A NAME="changes">Changes since Lua 5.3</A></H2>
<P>
Here are the main changes introduced in Lua 5.4.
The
<A HREF="contents.html">reference manual</A>
lists the
<A HREF="manual.html#8">incompatibilities</A> that had to be introduced.
<H3>Main changes</H3>
<UL>
<LI> new generational mode for garbage collection
<LI> to-be-closed variables
<LI> const variables
<LI> userdata can have multiple user values
<LI> new implementation for math.random
<LI> warning system
<LI> debug information about function arguments and returns
<LI> new semantics for the integer 'for' loop
<LI> optional 'init' argument to 'string.gmatch'
<LI> new functions 'lua_resetthread' and 'coroutine.close'
<LI> string-to-number coercions moved to the string library
<LI> allocation function allowed to fail when shrinking a memory block
<LI> new format '%p' in 'string.format'
<LI> utf8 library accepts codepoints up to 2^31
</UL>
<H2><A NAME="license">License</A></H2>
<P>
<A HREF="https://opensource.org/osd">
<IMG SRC="OSIApproved_100X125.png" ALIGN="right" ALT="[Open Source Initiative Approved License]" STYLE="padding-left: 1em" WIDTH=50>
</A>
Lua is free software distributed under the terms of the
<A HREF="https://opensource.org/license/mit">MIT license</A>
reproduced below;
it may be used for any purpose, including commercial purposes,
at absolutely no cost without having to ask us.
The only requirement is that if you do use Lua,
then you should give us credit by including the appropriate copyright notice somewhere in your product or its documentation.
For details, see the
<A HREF="https://www.lua.org/license.html">license page</A>.
<BLOCKQUOTE STYLE="padding-bottom: 0em">
Copyright &copy; 1994&ndash;2024 Lua.org, PUC-Rio.
<P>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
<P>
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
<P>
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
</BLOCKQUOTE>
<P>
<P CLASS="footer">
Last update:
Wed May 8 21:56:16 UTC 2024
</P>
<!--
Last change: revised for Lua 5.4.7
-->
</BODY>
</HTML>
+225
View File
@@ -0,0 +1,225 @@
# Makefile for building Lua
# See ../doc/readme.html for installation and customization instructions.
# == CHANGE THE SETTINGS BELOW TO SUIT YOUR ENVIRONMENT =======================
# Your platform. See PLATS for possible values.
PLAT= guess
CC= gcc -std=gnu99
CFLAGS= -O2 -Wall -Wextra -DLUA_COMPAT_5_3 $(SYSCFLAGS) $(MYCFLAGS)
LDFLAGS= $(SYSLDFLAGS) $(MYLDFLAGS)
LIBS= -lm $(SYSLIBS) $(MYLIBS)
AR= ar rcu
RANLIB= ranlib
RM= rm -f
UNAME= uname
SYSCFLAGS=
SYSLDFLAGS=
SYSLIBS=
MYCFLAGS=
MYLDFLAGS=
MYLIBS=
MYOBJS=
# Special flags for compiler modules; -Os reduces code size.
CMCFLAGS=
# == END OF USER SETTINGS -- NO NEED TO CHANGE ANYTHING BELOW THIS LINE =======
PLATS= guess aix bsd c89 freebsd generic ios linux linux-readline macosx mingw posix solaris
LUA_A= liblua.a
CORE_O= lapi.o lcode.o lctype.o ldebug.o ldo.o ldump.o lfunc.o lgc.o llex.o lmem.o lobject.o lopcodes.o lparser.o lstate.o lstring.o ltable.o ltm.o lundump.o lvm.o lzio.o
LIB_O= lauxlib.o lbaselib.o lcorolib.o ldblib.o liolib.o lmathlib.o loadlib.o loslib.o lstrlib.o ltablib.o lutf8lib.o linit.o
BASE_O= $(CORE_O) $(LIB_O) $(MYOBJS)
LUA_T= lua
LUA_O= lua.o
LUAC_T= luac
LUAC_O= luac.o
ALL_O= $(BASE_O) $(LUA_O) $(LUAC_O)
ALL_T= $(LUA_A) $(LUA_T) $(LUAC_T)
ALL_A= $(LUA_A)
# Targets start here.
default: $(PLAT)
all: $(ALL_T)
o: $(ALL_O)
a: $(ALL_A)
$(LUA_A): $(BASE_O)
$(AR) $@ $(BASE_O)
$(RANLIB) $@
$(LUA_T): $(LUA_O) $(LUA_A)
$(CC) -o $@ $(LDFLAGS) $(LUA_O) $(LUA_A) $(LIBS)
$(LUAC_T): $(LUAC_O) $(LUA_A)
$(CC) -o $@ $(LDFLAGS) $(LUAC_O) $(LUA_A) $(LIBS)
test:
./$(LUA_T) -v
clean:
$(RM) $(ALL_T) $(ALL_O)
depend:
@$(CC) $(CFLAGS) -MM l*.c
echo:
@echo "PLAT= $(PLAT)"
@echo "CC= $(CC)"
@echo "CFLAGS= $(CFLAGS)"
@echo "LDFLAGS= $(LDFLAGS)"
@echo "LIBS= $(LIBS)"
@echo "AR= $(AR)"
@echo "RANLIB= $(RANLIB)"
@echo "RM= $(RM)"
@echo "UNAME= $(UNAME)"
# Convenience targets for popular platforms.
ALL= all
help:
@echo "Do 'make PLATFORM' where PLATFORM is one of these:"
@echo " $(PLATS)"
@echo "See doc/readme.html for complete instructions."
guess:
@echo Guessing `$(UNAME)`
@$(MAKE) `$(UNAME)`
AIX aix:
$(MAKE) $(ALL) CC="xlc" CFLAGS="-O2 -DLUA_USE_POSIX -DLUA_USE_DLOPEN" SYSLIBS="-ldl" SYSLDFLAGS="-brtl -bexpall"
bsd:
$(MAKE) $(ALL) SYSCFLAGS="-DLUA_USE_POSIX -DLUA_USE_DLOPEN" SYSLIBS="-Wl,-E"
c89:
$(MAKE) $(ALL) SYSCFLAGS="-DLUA_USE_C89" CC="gcc -std=c89"
@echo ''
@echo '*** C89 does not guarantee 64-bit integers for Lua.'
@echo '*** Make sure to compile all external Lua libraries'
@echo '*** with LUA_USE_C89 to ensure consistency'
@echo ''
FreeBSD NetBSD OpenBSD freebsd:
$(MAKE) $(ALL) SYSCFLAGS="-DLUA_USE_LINUX -DLUA_USE_READLINE -I/usr/include/edit" SYSLIBS="-Wl,-E -ledit" CC="cc"
generic: $(ALL)
ios:
$(MAKE) $(ALL) SYSCFLAGS="-DLUA_USE_IOS"
Linux linux: linux-noreadline
linux-noreadline:
$(MAKE) $(ALL) SYSCFLAGS="-DLUA_USE_LINUX" SYSLIBS="-Wl,-E -ldl"
linux-readline:
$(MAKE) $(ALL) SYSCFLAGS="-DLUA_USE_LINUX -DLUA_USE_READLINE" SYSLIBS="-Wl,-E -ldl -lreadline"
Darwin macos macosx:
$(MAKE) $(ALL) SYSCFLAGS="-DLUA_USE_MACOSX -DLUA_USE_READLINE" SYSLIBS="-lreadline"
mingw:
$(MAKE) "LUA_A=lua54.dll" "LUA_T=lua.exe" \
"AR=$(CC) -shared -o" "RANLIB=strip --strip-unneeded" \
"SYSCFLAGS=-DLUA_BUILD_AS_DLL" "SYSLIBS=" "SYSLDFLAGS=-s" lua.exe
$(MAKE) "LUAC_T=luac.exe" luac.exe
posix:
$(MAKE) $(ALL) SYSCFLAGS="-DLUA_USE_POSIX"
SunOS solaris:
$(MAKE) $(ALL) SYSCFLAGS="-DLUA_USE_POSIX -DLUA_USE_DLOPEN -D_REENTRANT" SYSLIBS="-ldl"
# Targets that do not create files (not all makes understand .PHONY).
.PHONY: all $(PLATS) help test clean default o a depend echo
# Compiler modules may use special flags.
llex.o:
$(CC) $(CFLAGS) $(CMCFLAGS) -c llex.c
lparser.o:
$(CC) $(CFLAGS) $(CMCFLAGS) -c lparser.c
lcode.o:
$(CC) $(CFLAGS) $(CMCFLAGS) -c lcode.c
# DO NOT DELETE
lapi.o: lapi.c lprefix.h lua.h luaconf.h lapi.h llimits.h lstate.h \
lobject.h ltm.h lzio.h lmem.h ldebug.h ldo.h lfunc.h lgc.h lstring.h \
ltable.h lundump.h lvm.h
lauxlib.o: lauxlib.c lprefix.h lua.h luaconf.h lauxlib.h
lbaselib.o: lbaselib.c lprefix.h lua.h luaconf.h lauxlib.h lualib.h
lcode.o: lcode.c lprefix.h lua.h luaconf.h lcode.h llex.h lobject.h \
llimits.h lzio.h lmem.h lopcodes.h lparser.h ldebug.h lstate.h ltm.h \
ldo.h lgc.h lstring.h ltable.h lvm.h
lcorolib.o: lcorolib.c lprefix.h lua.h luaconf.h lauxlib.h lualib.h
lctype.o: lctype.c lprefix.h lctype.h lua.h luaconf.h llimits.h
ldblib.o: ldblib.c lprefix.h lua.h luaconf.h lauxlib.h lualib.h
ldebug.o: ldebug.c lprefix.h lua.h luaconf.h lapi.h llimits.h lstate.h \
lobject.h ltm.h lzio.h lmem.h lcode.h llex.h lopcodes.h lparser.h \
ldebug.h ldo.h lfunc.h lstring.h lgc.h ltable.h lvm.h
ldo.o: ldo.c lprefix.h lua.h luaconf.h lapi.h llimits.h lstate.h \
lobject.h ltm.h lzio.h lmem.h ldebug.h ldo.h lfunc.h lgc.h lopcodes.h \
lparser.h lstring.h ltable.h lundump.h lvm.h
ldump.o: ldump.c lprefix.h lua.h luaconf.h lobject.h llimits.h lstate.h \
ltm.h lzio.h lmem.h lundump.h
lfunc.o: lfunc.c lprefix.h lua.h luaconf.h ldebug.h lstate.h lobject.h \
llimits.h ltm.h lzio.h lmem.h ldo.h lfunc.h lgc.h
lgc.o: lgc.c lprefix.h lua.h luaconf.h ldebug.h lstate.h lobject.h \
llimits.h ltm.h lzio.h lmem.h ldo.h lfunc.h lgc.h lstring.h ltable.h
linit.o: linit.c lprefix.h lua.h luaconf.h lualib.h lauxlib.h
liolib.o: liolib.c lprefix.h lua.h luaconf.h lauxlib.h lualib.h
llex.o: llex.c lprefix.h lua.h luaconf.h lctype.h llimits.h ldebug.h \
lstate.h lobject.h ltm.h lzio.h lmem.h ldo.h lgc.h llex.h lparser.h \
lstring.h ltable.h
lmathlib.o: lmathlib.c lprefix.h lua.h luaconf.h lauxlib.h lualib.h
lmem.o: lmem.c lprefix.h lua.h luaconf.h ldebug.h lstate.h lobject.h \
llimits.h ltm.h lzio.h lmem.h ldo.h lgc.h
loadlib.o: loadlib.c lprefix.h lua.h luaconf.h lauxlib.h lualib.h
lobject.o: lobject.c lprefix.h lua.h luaconf.h lctype.h llimits.h \
ldebug.h lstate.h lobject.h ltm.h lzio.h lmem.h ldo.h lstring.h lgc.h \
lvm.h
lopcodes.o: lopcodes.c lprefix.h lopcodes.h llimits.h lua.h luaconf.h
loslib.o: loslib.c lprefix.h lua.h luaconf.h lauxlib.h lualib.h
lparser.o: lparser.c lprefix.h lua.h luaconf.h lcode.h llex.h lobject.h \
llimits.h lzio.h lmem.h lopcodes.h lparser.h ldebug.h lstate.h ltm.h \
ldo.h lfunc.h lstring.h lgc.h ltable.h
lstate.o: lstate.c lprefix.h lua.h luaconf.h lapi.h llimits.h lstate.h \
lobject.h ltm.h lzio.h lmem.h ldebug.h ldo.h lfunc.h lgc.h llex.h \
lstring.h ltable.h
lstring.o: lstring.c lprefix.h lua.h luaconf.h ldebug.h lstate.h \
lobject.h llimits.h ltm.h lzio.h lmem.h ldo.h lstring.h lgc.h
lstrlib.o: lstrlib.c lprefix.h lua.h luaconf.h lauxlib.h lualib.h
ltable.o: ltable.c lprefix.h lua.h luaconf.h ldebug.h lstate.h lobject.h \
llimits.h ltm.h lzio.h lmem.h ldo.h lgc.h lstring.h ltable.h lvm.h
ltablib.o: ltablib.c lprefix.h lua.h luaconf.h lauxlib.h lualib.h
ltm.o: ltm.c lprefix.h lua.h luaconf.h ldebug.h lstate.h lobject.h \
llimits.h ltm.h lzio.h lmem.h ldo.h lgc.h lstring.h ltable.h lvm.h
lua.o: lua.c lprefix.h lua.h luaconf.h lauxlib.h lualib.h
luac.o: luac.c lprefix.h lua.h luaconf.h lauxlib.h ldebug.h lstate.h \
lobject.h llimits.h ltm.h lzio.h lmem.h lopcodes.h lopnames.h lundump.h
lundump.o: lundump.c lprefix.h lua.h luaconf.h ldebug.h lstate.h \
lobject.h llimits.h ltm.h lzio.h lmem.h ldo.h lfunc.h lstring.h lgc.h \
lundump.h
lutf8lib.o: lutf8lib.c lprefix.h lua.h luaconf.h lauxlib.h lualib.h
lvm.o: lvm.c lprefix.h lua.h luaconf.h ldebug.h lstate.h lobject.h \
llimits.h ltm.h lzio.h lmem.h ldo.h lfunc.h lgc.h lopcodes.h lstring.h \
ltable.h lvm.h ljumptab.h
lzio.o: lzio.c lprefix.h lua.h luaconf.h llimits.h lmem.h lstate.h \
lobject.h ltm.h lzio.h
# (end of Makefile)
+1463
View File
File diff suppressed because it is too large Load Diff
+52
View File
@@ -0,0 +1,52 @@
/*
** $Id: lapi.h $
** Auxiliary functions from Lua API
** See Copyright Notice in lua.h
*/
#ifndef lapi_h
#define lapi_h
#include "llimits.h"
#include "lstate.h"
/* Increments 'L->top.p', checking for stack overflows */
#define api_incr_top(L) {L->top.p++; \
api_check(L, L->top.p <= L->ci->top.p, \
"stack overflow");}
/*
** If a call returns too many multiple returns, the callee may not have
** stack space to accommodate all results. In this case, this macro
** increases its stack space ('L->ci->top.p').
*/
#define adjustresults(L,nres) \
{ if ((nres) <= LUA_MULTRET && L->ci->top.p < L->top.p) \
L->ci->top.p = L->top.p; }
/* Ensure the stack has at least 'n' elements */
#define api_checknelems(L,n) \
api_check(L, (n) < (L->top.p - L->ci->func.p), \
"not enough elements in the stack")
/*
** To reduce the overhead of returning from C functions, the presence of
** to-be-closed variables in these functions is coded in the CallInfo's
** field 'nresults', in a way that functions with no to-be-closed variables
** with zero, one, or "all" wanted results have no overhead. Functions
** with other number of wanted results, as well as functions with
** variables to be closed, have an extra check.
*/
#define hastocloseCfunc(n) ((n) < LUA_MULTRET)
/* Map [-1, inf) (range of 'nresults') into (-inf, -2] */
#define codeNresults(n) (-(n) - 3)
#define decodeNresults(n) (-(n) - 3)
#endif
+1126
View File
File diff suppressed because it is too large Load Diff
+301
View File
@@ -0,0 +1,301 @@
/*
** $Id: lauxlib.h $
** Auxiliary functions for building Lua libraries
** See Copyright Notice in lua.h
*/
#ifndef lauxlib_h
#define lauxlib_h
#include <stddef.h>
#include <stdio.h>
#include "luaconf.h"
#include "lua.h"
/* global table */
#define LUA_GNAME "_G"
typedef struct luaL_Buffer luaL_Buffer;
/* extra error code for 'luaL_loadfilex' */
#define LUA_ERRFILE (LUA_ERRERR+1)
/* key, in the registry, for table of loaded modules */
#define LUA_LOADED_TABLE "_LOADED"
/* key, in the registry, for table of preloaded loaders */
#define LUA_PRELOAD_TABLE "_PRELOAD"
typedef struct luaL_Reg {
const char *name;
lua_CFunction func;
} luaL_Reg;
#define LUAL_NUMSIZES (sizeof(lua_Integer)*16 + sizeof(lua_Number))
LUALIB_API void (luaL_checkversion_) (lua_State *L, lua_Number ver, size_t sz);
#define luaL_checkversion(L) \
luaL_checkversion_(L, LUA_VERSION_NUM, LUAL_NUMSIZES)
LUALIB_API int (luaL_getmetafield) (lua_State *L, int obj, const char *e);
LUALIB_API int (luaL_callmeta) (lua_State *L, int obj, const char *e);
LUALIB_API const char *(luaL_tolstring) (lua_State *L, int idx, size_t *len);
LUALIB_API int (luaL_argerror) (lua_State *L, int arg, const char *extramsg);
LUALIB_API int (luaL_typeerror) (lua_State *L, int arg, const char *tname);
LUALIB_API const char *(luaL_checklstring) (lua_State *L, int arg,
size_t *l);
LUALIB_API const char *(luaL_optlstring) (lua_State *L, int arg,
const char *def, size_t *l);
LUALIB_API lua_Number (luaL_checknumber) (lua_State *L, int arg);
LUALIB_API lua_Number (luaL_optnumber) (lua_State *L, int arg, lua_Number def);
LUALIB_API lua_Integer (luaL_checkinteger) (lua_State *L, int arg);
LUALIB_API lua_Integer (luaL_optinteger) (lua_State *L, int arg,
lua_Integer def);
LUALIB_API void (luaL_checkstack) (lua_State *L, int sz, const char *msg);
LUALIB_API void (luaL_checktype) (lua_State *L, int arg, int t);
LUALIB_API void (luaL_checkany) (lua_State *L, int arg);
LUALIB_API int (luaL_newmetatable) (lua_State *L, const char *tname);
LUALIB_API void (luaL_setmetatable) (lua_State *L, const char *tname);
LUALIB_API void *(luaL_testudata) (lua_State *L, int ud, const char *tname);
LUALIB_API void *(luaL_checkudata) (lua_State *L, int ud, const char *tname);
LUALIB_API void (luaL_where) (lua_State *L, int lvl);
LUALIB_API int (luaL_error) (lua_State *L, const char *fmt, ...);
LUALIB_API int (luaL_checkoption) (lua_State *L, int arg, const char *def,
const char *const lst[]);
LUALIB_API int (luaL_fileresult) (lua_State *L, int stat, const char *fname);
LUALIB_API int (luaL_execresult) (lua_State *L, int stat);
/* predefined references */
#define LUA_NOREF (-2)
#define LUA_REFNIL (-1)
LUALIB_API int (luaL_ref) (lua_State *L, int t);
LUALIB_API void (luaL_unref) (lua_State *L, int t, int ref);
LUALIB_API int (luaL_loadfilex) (lua_State *L, const char *filename,
const char *mode);
#define luaL_loadfile(L,f) luaL_loadfilex(L,f,NULL)
LUALIB_API int (luaL_loadbufferx) (lua_State *L, const char *buff, size_t sz,
const char *name, const char *mode);
LUALIB_API int (luaL_loadstring) (lua_State *L, const char *s);
LUALIB_API lua_State *(luaL_newstate) (void);
LUALIB_API lua_Integer (luaL_len) (lua_State *L, int idx);
LUALIB_API void (luaL_addgsub) (luaL_Buffer *b, const char *s,
const char *p, const char *r);
LUALIB_API const char *(luaL_gsub) (lua_State *L, const char *s,
const char *p, const char *r);
LUALIB_API void (luaL_setfuncs) (lua_State *L, const luaL_Reg *l, int nup);
LUALIB_API int (luaL_getsubtable) (lua_State *L, int idx, const char *fname);
LUALIB_API void (luaL_traceback) (lua_State *L, lua_State *L1,
const char *msg, int level);
LUALIB_API void (luaL_requiref) (lua_State *L, const char *modname,
lua_CFunction openf, int glb);
/*
** ===============================================================
** some useful macros
** ===============================================================
*/
#define luaL_newlibtable(L,l) \
lua_createtable(L, 0, sizeof(l)/sizeof((l)[0]) - 1)
#define luaL_newlib(L,l) \
(luaL_checkversion(L), luaL_newlibtable(L,l), luaL_setfuncs(L,l,0))
#define luaL_argcheck(L, cond,arg,extramsg) \
((void)(luai_likely(cond) || luaL_argerror(L, (arg), (extramsg))))
#define luaL_argexpected(L,cond,arg,tname) \
((void)(luai_likely(cond) || luaL_typeerror(L, (arg), (tname))))
#define luaL_checkstring(L,n) (luaL_checklstring(L, (n), NULL))
#define luaL_optstring(L,n,d) (luaL_optlstring(L, (n), (d), NULL))
#define luaL_typename(L,i) lua_typename(L, lua_type(L,(i)))
#define luaL_dofile(L, fn) \
(luaL_loadfile(L, fn) || lua_pcall(L, 0, LUA_MULTRET, 0))
#define luaL_dostring(L, s) \
(luaL_loadstring(L, s) || lua_pcall(L, 0, LUA_MULTRET, 0))
#define luaL_getmetatable(L,n) (lua_getfield(L, LUA_REGISTRYINDEX, (n)))
#define luaL_opt(L,f,n,d) (lua_isnoneornil(L,(n)) ? (d) : f(L,(n)))
#define luaL_loadbuffer(L,s,sz,n) luaL_loadbufferx(L,s,sz,n,NULL)
/*
** Perform arithmetic operations on lua_Integer values with wrap-around
** semantics, as the Lua core does.
*/
#define luaL_intop(op,v1,v2) \
((lua_Integer)((lua_Unsigned)(v1) op (lua_Unsigned)(v2)))
/* push the value used to represent failure/error */
#define luaL_pushfail(L) lua_pushnil(L)
/*
** Internal assertions for in-house debugging
*/
#if !defined(lua_assert)
#if defined LUAI_ASSERT
#include <assert.h>
#define lua_assert(c) assert(c)
#else
#define lua_assert(c) ((void)0)
#endif
#endif
/*
** {======================================================
** Generic Buffer manipulation
** =======================================================
*/
struct luaL_Buffer {
char *b; /* buffer address */
size_t size; /* buffer size */
size_t n; /* number of characters in buffer */
lua_State *L;
union {
LUAI_MAXALIGN; /* ensure maximum alignment for buffer */
char b[LUAL_BUFFERSIZE]; /* initial buffer */
} init;
};
#define luaL_bufflen(bf) ((bf)->n)
#define luaL_buffaddr(bf) ((bf)->b)
#define luaL_addchar(B,c) \
((void)((B)->n < (B)->size || luaL_prepbuffsize((B), 1)), \
((B)->b[(B)->n++] = (c)))
#define luaL_addsize(B,s) ((B)->n += (s))
#define luaL_buffsub(B,s) ((B)->n -= (s))
LUALIB_API void (luaL_buffinit) (lua_State *L, luaL_Buffer *B);
LUALIB_API char *(luaL_prepbuffsize) (luaL_Buffer *B, size_t sz);
LUALIB_API void (luaL_addlstring) (luaL_Buffer *B, const char *s, size_t l);
LUALIB_API void (luaL_addstring) (luaL_Buffer *B, const char *s);
LUALIB_API void (luaL_addvalue) (luaL_Buffer *B);
LUALIB_API void (luaL_pushresult) (luaL_Buffer *B);
LUALIB_API void (luaL_pushresultsize) (luaL_Buffer *B, size_t sz);
LUALIB_API char *(luaL_buffinitsize) (lua_State *L, luaL_Buffer *B, size_t sz);
#define luaL_prepbuffer(B) luaL_prepbuffsize(B, LUAL_BUFFERSIZE)
/* }====================================================== */
/*
** {======================================================
** File handles for IO library
** =======================================================
*/
/*
** A file handle is a userdata with metatable 'LUA_FILEHANDLE' and
** initial structure 'luaL_Stream' (it may contain other fields
** after that initial structure).
*/
#define LUA_FILEHANDLE "FILE*"
typedef struct luaL_Stream {
FILE *f; /* stream (NULL for incompletely created streams) */
lua_CFunction closef; /* to close stream (NULL for closed streams) */
} luaL_Stream;
/* }====================================================== */
/*
** {==================================================================
** "Abstraction Layer" for basic report of messages and errors
** ===================================================================
*/
/* print a string */
#if !defined(lua_writestring)
#define lua_writestring(s,l) fwrite((s), sizeof(char), (l), stdout)
#endif
/* print a newline and flush the output */
#if !defined(lua_writeline)
#define lua_writeline() (lua_writestring("\n", 1), fflush(stdout))
#endif
/* print an error message */
#if !defined(lua_writestringerror)
#define lua_writestringerror(s,p) \
(fprintf(stderr, (s), (p)), fflush(stderr))
#endif
/* }================================================================== */
/*
** {============================================================
** Compatibility with deprecated conversions
** =============================================================
*/
#if defined(LUA_COMPAT_APIINTCASTS)
#define luaL_checkunsigned(L,a) ((lua_Unsigned)luaL_checkinteger(L,a))
#define luaL_optunsigned(L,a,d) \
((lua_Unsigned)luaL_optinteger(L,a,(lua_Integer)(d)))
#define luaL_checkint(L,n) ((int)luaL_checkinteger(L, (n)))
#define luaL_optint(L,n,d) ((int)luaL_optinteger(L, (n), (d)))
#define luaL_checklong(L,n) ((long)luaL_checkinteger(L, (n)))
#define luaL_optlong(L,n,d) ((long)luaL_optinteger(L, (n), (d)))
#endif
/* }============================================================ */
#endif
+549
View File
@@ -0,0 +1,549 @@
/*
** $Id: lbaselib.c $
** Basic library
** See Copyright Notice in lua.h
*/
#define lbaselib_c
#define LUA_LIB
#include "lprefix.h"
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "lua.h"
#include "lauxlib.h"
#include "lualib.h"
static int luaB_print (lua_State *L) {
int n = lua_gettop(L); /* number of arguments */
int i;
for (i = 1; i <= n; i++) { /* for each argument */
size_t l;
const char *s = luaL_tolstring(L, i, &l); /* convert it to string */
if (i > 1) /* not the first element? */
lua_writestring("\t", 1); /* add a tab before it */
lua_writestring(s, l); /* print it */
lua_pop(L, 1); /* pop result */
}
lua_writeline();
return 0;
}
/*
** Creates a warning with all given arguments.
** Check first for errors; otherwise an error may interrupt
** the composition of a warning, leaving it unfinished.
*/
static int luaB_warn (lua_State *L) {
int n = lua_gettop(L); /* number of arguments */
int i;
luaL_checkstring(L, 1); /* at least one argument */
for (i = 2; i <= n; i++)
luaL_checkstring(L, i); /* make sure all arguments are strings */
for (i = 1; i < n; i++) /* compose warning */
lua_warning(L, lua_tostring(L, i), 1);
lua_warning(L, lua_tostring(L, n), 0); /* close warning */
return 0;
}
#define SPACECHARS " \f\n\r\t\v"
static const char *b_str2int (const char *s, int base, lua_Integer *pn) {
lua_Unsigned n = 0;
int neg = 0;
s += strspn(s, SPACECHARS); /* skip initial spaces */
if (*s == '-') { s++; neg = 1; } /* handle sign */
else if (*s == '+') s++;
if (!isalnum((unsigned char)*s)) /* no digit? */
return NULL;
do {
int digit = (isdigit((unsigned char)*s)) ? *s - '0'
: (toupper((unsigned char)*s) - 'A') + 10;
if (digit >= base) return NULL; /* invalid numeral */
n = n * base + digit;
s++;
} while (isalnum((unsigned char)*s));
s += strspn(s, SPACECHARS); /* skip trailing spaces */
*pn = (lua_Integer)((neg) ? (0u - n) : n);
return s;
}
static int luaB_tonumber (lua_State *L) {
if (lua_isnoneornil(L, 2)) { /* standard conversion? */
if (lua_type(L, 1) == LUA_TNUMBER) { /* already a number? */
lua_settop(L, 1); /* yes; return it */
return 1;
}
else {
size_t l;
const char *s = lua_tolstring(L, 1, &l);
if (s != NULL && lua_stringtonumber(L, s) == l + 1)
return 1; /* successful conversion to number */
/* else not a number */
luaL_checkany(L, 1); /* (but there must be some parameter) */
}
}
else {
size_t l;
const char *s;
lua_Integer n = 0; /* to avoid warnings */
lua_Integer base = luaL_checkinteger(L, 2);
luaL_checktype(L, 1, LUA_TSTRING); /* no numbers as strings */
s = lua_tolstring(L, 1, &l);
luaL_argcheck(L, 2 <= base && base <= 36, 2, "base out of range");
if (b_str2int(s, (int)base, &n) == s + l) {
lua_pushinteger(L, n);
return 1;
} /* else not a number */
} /* else not a number */
luaL_pushfail(L); /* not a number */
return 1;
}
static int luaB_error (lua_State *L) {
int level = (int)luaL_optinteger(L, 2, 1);
lua_settop(L, 1);
if (lua_type(L, 1) == LUA_TSTRING && level > 0) {
luaL_where(L, level); /* add extra information */
lua_pushvalue(L, 1);
lua_concat(L, 2);
}
return lua_error(L);
}
static int luaB_getmetatable (lua_State *L) {
luaL_checkany(L, 1);
if (!lua_getmetatable(L, 1)) {
lua_pushnil(L);
return 1; /* no metatable */
}
luaL_getmetafield(L, 1, "__metatable");
return 1; /* returns either __metatable field (if present) or metatable */
}
static int luaB_setmetatable (lua_State *L) {
int t = lua_type(L, 2);
luaL_checktype(L, 1, LUA_TTABLE);
luaL_argexpected(L, t == LUA_TNIL || t == LUA_TTABLE, 2, "nil or table");
if (l_unlikely(luaL_getmetafield(L, 1, "__metatable") != LUA_TNIL))
return luaL_error(L, "cannot change a protected metatable");
lua_settop(L, 2);
lua_setmetatable(L, 1);
return 1;
}
static int luaB_rawequal (lua_State *L) {
luaL_checkany(L, 1);
luaL_checkany(L, 2);
lua_pushboolean(L, lua_rawequal(L, 1, 2));
return 1;
}
static int luaB_rawlen (lua_State *L) {
int t = lua_type(L, 1);
luaL_argexpected(L, t == LUA_TTABLE || t == LUA_TSTRING, 1,
"table or string");
lua_pushinteger(L, lua_rawlen(L, 1));
return 1;
}
static int luaB_rawget (lua_State *L) {
luaL_checktype(L, 1, LUA_TTABLE);
luaL_checkany(L, 2);
lua_settop(L, 2);
lua_rawget(L, 1);
return 1;
}
static int luaB_rawset (lua_State *L) {
luaL_checktype(L, 1, LUA_TTABLE);
luaL_checkany(L, 2);
luaL_checkany(L, 3);
lua_settop(L, 3);
lua_rawset(L, 1);
return 1;
}
static int pushmode (lua_State *L, int oldmode) {
if (oldmode == -1)
luaL_pushfail(L); /* invalid call to 'lua_gc' */
else
lua_pushstring(L, (oldmode == LUA_GCINC) ? "incremental"
: "generational");
return 1;
}
/*
** check whether call to 'lua_gc' was valid (not inside a finalizer)
*/
#define checkvalres(res) { if (res == -1) break; }
static int luaB_collectgarbage (lua_State *L) {
static const char *const opts[] = {"stop", "restart", "collect",
"count", "step", "setpause", "setstepmul",
"isrunning", "generational", "incremental", NULL};
static const int optsnum[] = {LUA_GCSTOP, LUA_GCRESTART, LUA_GCCOLLECT,
LUA_GCCOUNT, LUA_GCSTEP, LUA_GCSETPAUSE, LUA_GCSETSTEPMUL,
LUA_GCISRUNNING, LUA_GCGEN, LUA_GCINC};
int o = optsnum[luaL_checkoption(L, 1, "collect", opts)];
switch (o) {
case LUA_GCCOUNT: {
int k = lua_gc(L, o);
int b = lua_gc(L, LUA_GCCOUNTB);
checkvalres(k);
lua_pushnumber(L, (lua_Number)k + ((lua_Number)b/1024));
return 1;
}
case LUA_GCSTEP: {
int step = (int)luaL_optinteger(L, 2, 0);
int res = lua_gc(L, o, step);
checkvalres(res);
lua_pushboolean(L, res);
return 1;
}
case LUA_GCSETPAUSE:
case LUA_GCSETSTEPMUL: {
int p = (int)luaL_optinteger(L, 2, 0);
int previous = lua_gc(L, o, p);
checkvalres(previous);
lua_pushinteger(L, previous);
return 1;
}
case LUA_GCISRUNNING: {
int res = lua_gc(L, o);
checkvalres(res);
lua_pushboolean(L, res);
return 1;
}
case LUA_GCGEN: {
int minormul = (int)luaL_optinteger(L, 2, 0);
int majormul = (int)luaL_optinteger(L, 3, 0);
return pushmode(L, lua_gc(L, o, minormul, majormul));
}
case LUA_GCINC: {
int pause = (int)luaL_optinteger(L, 2, 0);
int stepmul = (int)luaL_optinteger(L, 3, 0);
int stepsize = (int)luaL_optinteger(L, 4, 0);
return pushmode(L, lua_gc(L, o, pause, stepmul, stepsize));
}
default: {
int res = lua_gc(L, o);
checkvalres(res);
lua_pushinteger(L, res);
return 1;
}
}
luaL_pushfail(L); /* invalid call (inside a finalizer) */
return 1;
}
static int luaB_type (lua_State *L) {
int t = lua_type(L, 1);
luaL_argcheck(L, t != LUA_TNONE, 1, "value expected");
lua_pushstring(L, lua_typename(L, t));
return 1;
}
static int luaB_next (lua_State *L) {
luaL_checktype(L, 1, LUA_TTABLE);
lua_settop(L, 2); /* create a 2nd argument if there isn't one */
if (lua_next(L, 1))
return 2;
else {
lua_pushnil(L);
return 1;
}
}
static int pairscont (lua_State *L, int status, lua_KContext k) {
(void)L; (void)status; (void)k; /* unused */
return 3;
}
static int luaB_pairs (lua_State *L) {
luaL_checkany(L, 1);
if (luaL_getmetafield(L, 1, "__pairs") == LUA_TNIL) { /* no metamethod? */
lua_pushcfunction(L, luaB_next); /* will return generator, */
lua_pushvalue(L, 1); /* state, */
lua_pushnil(L); /* and initial value */
}
else {
lua_pushvalue(L, 1); /* argument 'self' to metamethod */
lua_callk(L, 1, 3, 0, pairscont); /* get 3 values from metamethod */
}
return 3;
}
/*
** Traversal function for 'ipairs'
*/
static int ipairsaux (lua_State *L) {
lua_Integer i = luaL_checkinteger(L, 2);
i = luaL_intop(+, i, 1);
lua_pushinteger(L, i);
return (lua_geti(L, 1, i) == LUA_TNIL) ? 1 : 2;
}
/*
** 'ipairs' function. Returns 'ipairsaux', given "table", 0.
** (The given "table" may not be a table.)
*/
static int luaB_ipairs (lua_State *L) {
luaL_checkany(L, 1);
lua_pushcfunction(L, ipairsaux); /* iteration function */
lua_pushvalue(L, 1); /* state */
lua_pushinteger(L, 0); /* initial value */
return 3;
}
static int load_aux (lua_State *L, int status, int envidx) {
if (l_likely(status == LUA_OK)) {
if (envidx != 0) { /* 'env' parameter? */
lua_pushvalue(L, envidx); /* environment for loaded function */
if (!lua_setupvalue(L, -2, 1)) /* set it as 1st upvalue */
lua_pop(L, 1); /* remove 'env' if not used by previous call */
}
return 1;
}
else { /* error (message is on top of the stack) */
luaL_pushfail(L);
lua_insert(L, -2); /* put before error message */
return 2; /* return fail plus error message */
}
}
static int luaB_loadfile (lua_State *L) {
const char *fname = luaL_optstring(L, 1, NULL);
const char *mode = luaL_optstring(L, 2, NULL);
int env = (!lua_isnone(L, 3) ? 3 : 0); /* 'env' index or 0 if no 'env' */
int status = luaL_loadfilex(L, fname, mode);
return load_aux(L, status, env);
}
/*
** {======================================================
** Generic Read function
** =======================================================
*/
/*
** reserved slot, above all arguments, to hold a copy of the returned
** string to avoid it being collected while parsed. 'load' has four
** optional arguments (chunk, source name, mode, and environment).
*/
#define RESERVEDSLOT 5
/*
** Reader for generic 'load' function: 'lua_load' uses the
** stack for internal stuff, so the reader cannot change the
** stack top. Instead, it keeps its resulting string in a
** reserved slot inside the stack.
*/
static const char *generic_reader (lua_State *L, void *ud, size_t *size) {
(void)(ud); /* not used */
luaL_checkstack(L, 2, "too many nested functions");
lua_pushvalue(L, 1); /* get function */
lua_call(L, 0, 1); /* call it */
if (lua_isnil(L, -1)) {
lua_pop(L, 1); /* pop result */
*size = 0;
return NULL;
}
else if (l_unlikely(!lua_isstring(L, -1)))
luaL_error(L, "reader function must return a string");
lua_replace(L, RESERVEDSLOT); /* save string in reserved slot */
return lua_tolstring(L, RESERVEDSLOT, size);
}
static int luaB_load (lua_State *L) {
int status;
size_t l;
const char *s = lua_tolstring(L, 1, &l);
const char *mode = luaL_optstring(L, 3, "bt");
int env = (!lua_isnone(L, 4) ? 4 : 0); /* 'env' index or 0 if no 'env' */
if (s != NULL) { /* loading a string? */
const char *chunkname = luaL_optstring(L, 2, s);
status = luaL_loadbufferx(L, s, l, chunkname, mode);
}
else { /* loading from a reader function */
const char *chunkname = luaL_optstring(L, 2, "=(load)");
luaL_checktype(L, 1, LUA_TFUNCTION);
lua_settop(L, RESERVEDSLOT); /* create reserved slot */
status = lua_load(L, generic_reader, NULL, chunkname, mode);
}
return load_aux(L, status, env);
}
/* }====================================================== */
static int dofilecont (lua_State *L, int d1, lua_KContext d2) {
(void)d1; (void)d2; /* only to match 'lua_Kfunction' prototype */
return lua_gettop(L) - 1;
}
static int luaB_dofile (lua_State *L) {
const char *fname = luaL_optstring(L, 1, NULL);
lua_settop(L, 1);
if (l_unlikely(luaL_loadfile(L, fname) != LUA_OK))
return lua_error(L);
lua_callk(L, 0, LUA_MULTRET, 0, dofilecont);
return dofilecont(L, 0, 0);
}
static int luaB_assert (lua_State *L) {
if (l_likely(lua_toboolean(L, 1))) /* condition is true? */
return lua_gettop(L); /* return all arguments */
else { /* error */
luaL_checkany(L, 1); /* there must be a condition */
lua_remove(L, 1); /* remove it */
lua_pushliteral(L, "assertion failed!"); /* default message */
lua_settop(L, 1); /* leave only message (default if no other one) */
return luaB_error(L); /* call 'error' */
}
}
static int luaB_select (lua_State *L) {
int n = lua_gettop(L);
if (lua_type(L, 1) == LUA_TSTRING && *lua_tostring(L, 1) == '#') {
lua_pushinteger(L, n-1);
return 1;
}
else {
lua_Integer i = luaL_checkinteger(L, 1);
if (i < 0) i = n + i;
else if (i > n) i = n;
luaL_argcheck(L, 1 <= i, 1, "index out of range");
return n - (int)i;
}
}
/*
** Continuation function for 'pcall' and 'xpcall'. Both functions
** already pushed a 'true' before doing the call, so in case of success
** 'finishpcall' only has to return everything in the stack minus
** 'extra' values (where 'extra' is exactly the number of items to be
** ignored).
*/
static int finishpcall (lua_State *L, int status, lua_KContext extra) {
if (l_unlikely(status != LUA_OK && status != LUA_YIELD)) { /* error? */
lua_pushboolean(L, 0); /* first result (false) */
lua_pushvalue(L, -2); /* error message */
return 2; /* return false, msg */
}
else
return lua_gettop(L) - (int)extra; /* return all results */
}
static int luaB_pcall (lua_State *L) {
int status;
luaL_checkany(L, 1);
lua_pushboolean(L, 1); /* first result if no errors */
lua_insert(L, 1); /* put it in place */
status = lua_pcallk(L, lua_gettop(L) - 2, LUA_MULTRET, 0, 0, finishpcall);
return finishpcall(L, status, 0);
}
/*
** Do a protected call with error handling. After 'lua_rotate', the
** stack will have <f, err, true, f, [args...]>; so, the function passes
** 2 to 'finishpcall' to skip the 2 first values when returning results.
*/
static int luaB_xpcall (lua_State *L) {
int status;
int n = lua_gettop(L);
luaL_checktype(L, 2, LUA_TFUNCTION); /* check error function */
lua_pushboolean(L, 1); /* first result */
lua_pushvalue(L, 1); /* function */
lua_rotate(L, 3, 2); /* move them below function's arguments */
status = lua_pcallk(L, n - 2, LUA_MULTRET, 2, 2, finishpcall);
return finishpcall(L, status, 2);
}
static int luaB_tostring (lua_State *L) {
luaL_checkany(L, 1);
luaL_tolstring(L, 1, NULL);
return 1;
}
static const luaL_Reg base_funcs[] = {
{"assert", luaB_assert},
{"collectgarbage", luaB_collectgarbage},
{"dofile", luaB_dofile},
{"error", luaB_error},
{"getmetatable", luaB_getmetatable},
{"ipairs", luaB_ipairs},
{"loadfile", luaB_loadfile},
{"load", luaB_load},
{"next", luaB_next},
{"pairs", luaB_pairs},
{"pcall", luaB_pcall},
{"print", luaB_print},
{"warn", luaB_warn},
{"rawequal", luaB_rawequal},
{"rawlen", luaB_rawlen},
{"rawget", luaB_rawget},
{"rawset", luaB_rawset},
{"select", luaB_select},
{"setmetatable", luaB_setmetatable},
{"tonumber", luaB_tonumber},
{"tostring", luaB_tostring},
{"type", luaB_type},
{"xpcall", luaB_xpcall},
/* placeholders */
{LUA_GNAME, NULL},
{"_VERSION", NULL},
{NULL, NULL}
};
LUAMOD_API int luaopen_base (lua_State *L) {
/* open lib into global table */
lua_pushglobaltable(L);
luaL_setfuncs(L, base_funcs, 0);
/* set global _G */
lua_pushvalue(L, -1);
lua_setfield(L, -2, LUA_GNAME);
/* set global _VERSION */
lua_pushliteral(L, LUA_VERSION);
lua_setfield(L, -2, "_VERSION");
return 1;
}
+1874
View File
File diff suppressed because it is too large Load Diff
+101
View File
@@ -0,0 +1,101 @@
/*
** $Id: lcode.h $
** Code generator for Lua
** See Copyright Notice in lua.h
*/
#ifndef lcode_h
#define lcode_h
#include "llex.h"
#include "lobject.h"
#include "lopcodes.h"
#include "lparser.h"
/*
** Marks the end of a patch list. It is an invalid value both as an absolute
** address, and as a list link (would link an element to itself).
*/
#define NO_JUMP (-1)
/*
** grep "ORDER OPR" if you change these enums (ORDER OP)
*/
typedef enum BinOpr {
/* arithmetic operators */
OPR_ADD, OPR_SUB, OPR_MUL, OPR_MOD, OPR_POW,
OPR_DIV, OPR_IDIV,
/* bitwise operators */
OPR_BAND, OPR_BOR, OPR_BXOR,
OPR_SHL, OPR_SHR,
/* string operator */
OPR_CONCAT,
/* comparison operators */
OPR_EQ, OPR_LT, OPR_LE,
OPR_NE, OPR_GT, OPR_GE,
/* logical operators */
OPR_AND, OPR_OR,
OPR_NOBINOPR
} BinOpr;
/* true if operation is foldable (that is, it is arithmetic or bitwise) */
#define foldbinop(op) ((op) <= OPR_SHR)
#define luaK_codeABC(fs,o,a,b,c) luaK_codeABCk(fs,o,a,b,c,0)
typedef enum UnOpr { OPR_MINUS, OPR_BNOT, OPR_NOT, OPR_LEN, OPR_NOUNOPR } UnOpr;
/* get (pointer to) instruction of given 'expdesc' */
#define getinstruction(fs,e) ((fs)->f->code[(e)->u.info])
#define luaK_setmultret(fs,e) luaK_setreturns(fs, e, LUA_MULTRET)
#define luaK_jumpto(fs,t) luaK_patchlist(fs, luaK_jump(fs), t)
LUAI_FUNC int luaK_code (FuncState *fs, Instruction i);
LUAI_FUNC int luaK_codeABx (FuncState *fs, OpCode o, int A, unsigned int Bx);
LUAI_FUNC int luaK_codeABCk (FuncState *fs, OpCode o, int A,
int B, int C, int k);
LUAI_FUNC int luaK_exp2const (FuncState *fs, const expdesc *e, TValue *v);
LUAI_FUNC void luaK_fixline (FuncState *fs, int line);
LUAI_FUNC void luaK_nil (FuncState *fs, int from, int n);
LUAI_FUNC void luaK_reserveregs (FuncState *fs, int n);
LUAI_FUNC void luaK_checkstack (FuncState *fs, int n);
LUAI_FUNC void luaK_int (FuncState *fs, int reg, lua_Integer n);
LUAI_FUNC void luaK_dischargevars (FuncState *fs, expdesc *e);
LUAI_FUNC int luaK_exp2anyreg (FuncState *fs, expdesc *e);
LUAI_FUNC void luaK_exp2anyregup (FuncState *fs, expdesc *e);
LUAI_FUNC void luaK_exp2nextreg (FuncState *fs, expdesc *e);
LUAI_FUNC void luaK_exp2val (FuncState *fs, expdesc *e);
LUAI_FUNC void luaK_self (FuncState *fs, expdesc *e, expdesc *key);
LUAI_FUNC void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k);
LUAI_FUNC void luaK_goiftrue (FuncState *fs, expdesc *e);
LUAI_FUNC void luaK_goiffalse (FuncState *fs, expdesc *e);
LUAI_FUNC void luaK_storevar (FuncState *fs, expdesc *var, expdesc *e);
LUAI_FUNC void luaK_setreturns (FuncState *fs, expdesc *e, int nresults);
LUAI_FUNC void luaK_setoneret (FuncState *fs, expdesc *e);
LUAI_FUNC int luaK_jump (FuncState *fs);
LUAI_FUNC void luaK_ret (FuncState *fs, int first, int nret);
LUAI_FUNC void luaK_patchlist (FuncState *fs, int list, int target);
LUAI_FUNC void luaK_patchtohere (FuncState *fs, int list);
LUAI_FUNC void luaK_concat (FuncState *fs, int *l1, int l2);
LUAI_FUNC int luaK_getlabel (FuncState *fs);
LUAI_FUNC void luaK_prefix (FuncState *fs, UnOpr op, expdesc *v, int line);
LUAI_FUNC void luaK_infix (FuncState *fs, BinOpr op, expdesc *v);
LUAI_FUNC void luaK_posfix (FuncState *fs, BinOpr op, expdesc *v1,
expdesc *v2, int line);
LUAI_FUNC void luaK_settablesize (FuncState *fs, int pc,
int ra, int asize, int hsize);
LUAI_FUNC void luaK_setlist (FuncState *fs, int base, int nelems, int tostore);
LUAI_FUNC void luaK_finish (FuncState *fs);
LUAI_FUNC l_noret luaK_semerror (LexState *ls, const char *msg);
#endif
+210
View File
@@ -0,0 +1,210 @@
/*
** $Id: lcorolib.c $
** Coroutine Library
** See Copyright Notice in lua.h
*/
#define lcorolib_c
#define LUA_LIB
#include "lprefix.h"
#include <stdlib.h>
#include "lua.h"
#include "lauxlib.h"
#include "lualib.h"
static lua_State *getco (lua_State *L) {
lua_State *co = lua_tothread(L, 1);
luaL_argexpected(L, co, 1, "thread");
return co;
}
/*
** Resumes a coroutine. Returns the number of results for non-error
** cases or -1 for errors.
*/
static int auxresume (lua_State *L, lua_State *co, int narg) {
int status, nres;
if (l_unlikely(!lua_checkstack(co, narg))) {
lua_pushliteral(L, "too many arguments to resume");
return -1; /* error flag */
}
lua_xmove(L, co, narg);
status = lua_resume(co, L, narg, &nres);
if (l_likely(status == LUA_OK || status == LUA_YIELD)) {
if (l_unlikely(!lua_checkstack(L, nres + 1))) {
lua_pop(co, nres); /* remove results anyway */
lua_pushliteral(L, "too many results to resume");
return -1; /* error flag */
}
lua_xmove(co, L, nres); /* move yielded values */
return nres;
}
else {
lua_xmove(co, L, 1); /* move error message */
return -1; /* error flag */
}
}
static int luaB_coresume (lua_State *L) {
lua_State *co = getco(L);
int r;
r = auxresume(L, co, lua_gettop(L) - 1);
if (l_unlikely(r < 0)) {
lua_pushboolean(L, 0);
lua_insert(L, -2);
return 2; /* return false + error message */
}
else {
lua_pushboolean(L, 1);
lua_insert(L, -(r + 1));
return r + 1; /* return true + 'resume' returns */
}
}
static int luaB_auxwrap (lua_State *L) {
lua_State *co = lua_tothread(L, lua_upvalueindex(1));
int r = auxresume(L, co, lua_gettop(L));
if (l_unlikely(r < 0)) { /* error? */
int stat = lua_status(co);
if (stat != LUA_OK && stat != LUA_YIELD) { /* error in the coroutine? */
stat = lua_closethread(co, L); /* close its tbc variables */
lua_assert(stat != LUA_OK);
lua_xmove(co, L, 1); /* move error message to the caller */
}
if (stat != LUA_ERRMEM && /* not a memory error and ... */
lua_type(L, -1) == LUA_TSTRING) { /* ... error object is a string? */
luaL_where(L, 1); /* add extra info, if available */
lua_insert(L, -2);
lua_concat(L, 2);
}
return lua_error(L); /* propagate error */
}
return r;
}
static int luaB_cocreate (lua_State *L) {
lua_State *NL;
luaL_checktype(L, 1, LUA_TFUNCTION);
NL = lua_newthread(L);
lua_pushvalue(L, 1); /* move function to top */
lua_xmove(L, NL, 1); /* move function from L to NL */
return 1;
}
static int luaB_cowrap (lua_State *L) {
luaB_cocreate(L);
lua_pushcclosure(L, luaB_auxwrap, 1);
return 1;
}
static int luaB_yield (lua_State *L) {
return lua_yield(L, lua_gettop(L));
}
#define COS_RUN 0
#define COS_DEAD 1
#define COS_YIELD 2
#define COS_NORM 3
static const char *const statname[] =
{"running", "dead", "suspended", "normal"};
static int auxstatus (lua_State *L, lua_State *co) {
if (L == co) return COS_RUN;
else {
switch (lua_status(co)) {
case LUA_YIELD:
return COS_YIELD;
case LUA_OK: {
lua_Debug ar;
if (lua_getstack(co, 0, &ar)) /* does it have frames? */
return COS_NORM; /* it is running */
else if (lua_gettop(co) == 0)
return COS_DEAD;
else
return COS_YIELD; /* initial state */
}
default: /* some error occurred */
return COS_DEAD;
}
}
}
static int luaB_costatus (lua_State *L) {
lua_State *co = getco(L);
lua_pushstring(L, statname[auxstatus(L, co)]);
return 1;
}
static int luaB_yieldable (lua_State *L) {
lua_State *co = lua_isnone(L, 1) ? L : getco(L);
lua_pushboolean(L, lua_isyieldable(co));
return 1;
}
static int luaB_corunning (lua_State *L) {
int ismain = lua_pushthread(L);
lua_pushboolean(L, ismain);
return 2;
}
static int luaB_close (lua_State *L) {
lua_State *co = getco(L);
int status = auxstatus(L, co);
switch (status) {
case COS_DEAD: case COS_YIELD: {
status = lua_closethread(co, L);
if (status == LUA_OK) {
lua_pushboolean(L, 1);
return 1;
}
else {
lua_pushboolean(L, 0);
lua_xmove(co, L, 1); /* move error message */
return 2;
}
}
default: /* normal or running coroutine */
return luaL_error(L, "cannot close a %s coroutine", statname[status]);
}
}
static const luaL_Reg co_funcs[] = {
{"create", luaB_cocreate},
{"resume", luaB_coresume},
{"running", luaB_corunning},
{"status", luaB_costatus},
{"wrap", luaB_cowrap},
{"yield", luaB_yield},
{"isyieldable", luaB_yieldable},
{"close", luaB_close},
{NULL, NULL}
};
LUAMOD_API int luaopen_coroutine (lua_State *L) {
luaL_newlib(L, co_funcs);
return 1;
}
+64
View File
@@ -0,0 +1,64 @@
/*
** $Id: lctype.c $
** 'ctype' functions for Lua
** See Copyright Notice in lua.h
*/
#define lctype_c
#define LUA_CORE
#include "lprefix.h"
#include "lctype.h"
#if !LUA_USE_CTYPE /* { */
#include <limits.h>
#if defined (LUA_UCID) /* accept UniCode IDentifiers? */
/* consider all non-ascii codepoints to be alphabetic */
#define NONA 0x01
#else
#define NONA 0x00 /* default */
#endif
LUAI_DDEF const lu_byte luai_ctype_[UCHAR_MAX + 2] = {
0x00, /* EOZ */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0. */
0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 1. */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x0c, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, /* 2. */
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, /* 3. */
0x16, 0x16, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
0x04, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x05, /* 4. */
0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, /* 5. */
0x05, 0x05, 0x05, 0x04, 0x04, 0x04, 0x04, 0x05,
0x04, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x05, /* 6. */
0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, /* 7. */
0x05, 0x05, 0x05, 0x04, 0x04, 0x04, 0x04, 0x00,
NONA, NONA, NONA, NONA, NONA, NONA, NONA, NONA, /* 8. */
NONA, NONA, NONA, NONA, NONA, NONA, NONA, NONA,
NONA, NONA, NONA, NONA, NONA, NONA, NONA, NONA, /* 9. */
NONA, NONA, NONA, NONA, NONA, NONA, NONA, NONA,
NONA, NONA, NONA, NONA, NONA, NONA, NONA, NONA, /* a. */
NONA, NONA, NONA, NONA, NONA, NONA, NONA, NONA,
NONA, NONA, NONA, NONA, NONA, NONA, NONA, NONA, /* b. */
NONA, NONA, NONA, NONA, NONA, NONA, NONA, NONA,
0x00, 0x00, NONA, NONA, NONA, NONA, NONA, NONA, /* c. */
NONA, NONA, NONA, NONA, NONA, NONA, NONA, NONA,
NONA, NONA, NONA, NONA, NONA, NONA, NONA, NONA, /* d. */
NONA, NONA, NONA, NONA, NONA, NONA, NONA, NONA,
NONA, NONA, NONA, NONA, NONA, NONA, NONA, NONA, /* e. */
NONA, NONA, NONA, NONA, NONA, NONA, NONA, NONA,
NONA, NONA, NONA, NONA, NONA, 0x00, 0x00, 0x00, /* f. */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
#endif /* } */
+101
View File
@@ -0,0 +1,101 @@
/*
** $Id: lctype.h $
** 'ctype' functions for Lua
** See Copyright Notice in lua.h
*/
#ifndef lctype_h
#define lctype_h
#include "lua.h"
/*
** WARNING: the functions defined here do not necessarily correspond
** to the similar functions in the standard C ctype.h. They are
** optimized for the specific needs of Lua.
*/
#if !defined(LUA_USE_CTYPE)
#if 'A' == 65 && '0' == 48
/* ASCII case: can use its own tables; faster and fixed */
#define LUA_USE_CTYPE 0
#else
/* must use standard C ctype */
#define LUA_USE_CTYPE 1
#endif
#endif
#if !LUA_USE_CTYPE /* { */
#include <limits.h>
#include "llimits.h"
#define ALPHABIT 0
#define DIGITBIT 1
#define PRINTBIT 2
#define SPACEBIT 3
#define XDIGITBIT 4
#define MASK(B) (1 << (B))
/*
** add 1 to char to allow index -1 (EOZ)
*/
#define testprop(c,p) (luai_ctype_[(c)+1] & (p))
/*
** 'lalpha' (Lua alphabetic) and 'lalnum' (Lua alphanumeric) both include '_'
*/
#define lislalpha(c) testprop(c, MASK(ALPHABIT))
#define lislalnum(c) testprop(c, (MASK(ALPHABIT) | MASK(DIGITBIT)))
#define lisdigit(c) testprop(c, MASK(DIGITBIT))
#define lisspace(c) testprop(c, MASK(SPACEBIT))
#define lisprint(c) testprop(c, MASK(PRINTBIT))
#define lisxdigit(c) testprop(c, MASK(XDIGITBIT))
/*
** In ASCII, this 'ltolower' is correct for alphabetic characters and
** for '.'. That is enough for Lua needs. ('check_exp' ensures that
** the character either is an upper-case letter or is unchanged by
** the transformation, which holds for lower-case letters and '.'.)
*/
#define ltolower(c) \
check_exp(('A' <= (c) && (c) <= 'Z') || (c) == ((c) | ('A' ^ 'a')), \
(c) | ('A' ^ 'a'))
/* one entry for each character and for -1 (EOZ) */
LUAI_DDEC(const lu_byte luai_ctype_[UCHAR_MAX + 2];)
#else /* }{ */
/*
** use standard C ctypes
*/
#include <ctype.h>
#define lislalpha(c) (isalpha(c) || (c) == '_')
#define lislalnum(c) (isalnum(c) || (c) == '_')
#define lisdigit(c) (isdigit(c))
#define lisspace(c) (isspace(c))
#define lisprint(c) (isprint(c))
#define lisxdigit(c) (isxdigit(c))
#define ltolower(c) (tolower(c))
#endif /* } */
#endif
+483
View File
@@ -0,0 +1,483 @@
/*
** $Id: ldblib.c $
** Interface from Lua to its debug API
** See Copyright Notice in lua.h
*/
#define ldblib_c
#define LUA_LIB
#include "lprefix.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "lua.h"
#include "lauxlib.h"
#include "lualib.h"
/*
** The hook table at registry[HOOKKEY] maps threads to their current
** hook function.
*/
static const char *const HOOKKEY = "_HOOKKEY";
/*
** If L1 != L, L1 can be in any state, and therefore there are no
** guarantees about its stack space; any push in L1 must be
** checked.
*/
static void checkstack (lua_State *L, lua_State *L1, int n) {
if (l_unlikely(L != L1 && !lua_checkstack(L1, n)))
luaL_error(L, "stack overflow");
}
static int db_getregistry (lua_State *L) {
lua_pushvalue(L, LUA_REGISTRYINDEX);
return 1;
}
static int db_getmetatable (lua_State *L) {
luaL_checkany(L, 1);
if (!lua_getmetatable(L, 1)) {
lua_pushnil(L); /* no metatable */
}
return 1;
}
static int db_setmetatable (lua_State *L) {
int t = lua_type(L, 2);
luaL_argexpected(L, t == LUA_TNIL || t == LUA_TTABLE, 2, "nil or table");
lua_settop(L, 2);
lua_setmetatable(L, 1);
return 1; /* return 1st argument */
}
static int db_getuservalue (lua_State *L) {
int n = (int)luaL_optinteger(L, 2, 1);
if (lua_type(L, 1) != LUA_TUSERDATA)
luaL_pushfail(L);
else if (lua_getiuservalue(L, 1, n) != LUA_TNONE) {
lua_pushboolean(L, 1);
return 2;
}
return 1;
}
static int db_setuservalue (lua_State *L) {
int n = (int)luaL_optinteger(L, 3, 1);
luaL_checktype(L, 1, LUA_TUSERDATA);
luaL_checkany(L, 2);
lua_settop(L, 2);
if (!lua_setiuservalue(L, 1, n))
luaL_pushfail(L);
return 1;
}
/*
** Auxiliary function used by several library functions: check for
** an optional thread as function's first argument and set 'arg' with
** 1 if this argument is present (so that functions can skip it to
** access their other arguments)
*/
static lua_State *getthread (lua_State *L, int *arg) {
if (lua_isthread(L, 1)) {
*arg = 1;
return lua_tothread(L, 1);
}
else {
*arg = 0;
return L; /* function will operate over current thread */
}
}
/*
** Variations of 'lua_settable', used by 'db_getinfo' to put results
** from 'lua_getinfo' into result table. Key is always a string;
** value can be a string, an int, or a boolean.
*/
static void settabss (lua_State *L, const char *k, const char *v) {
lua_pushstring(L, v);
lua_setfield(L, -2, k);
}
static void settabsi (lua_State *L, const char *k, int v) {
lua_pushinteger(L, v);
lua_setfield(L, -2, k);
}
static void settabsb (lua_State *L, const char *k, int v) {
lua_pushboolean(L, v);
lua_setfield(L, -2, k);
}
/*
** In function 'db_getinfo', the call to 'lua_getinfo' may push
** results on the stack; later it creates the result table to put
** these objects. Function 'treatstackoption' puts the result from
** 'lua_getinfo' on top of the result table so that it can call
** 'lua_setfield'.
*/
static void treatstackoption (lua_State *L, lua_State *L1, const char *fname) {
if (L == L1)
lua_rotate(L, -2, 1); /* exchange object and table */
else
lua_xmove(L1, L, 1); /* move object to the "main" stack */
lua_setfield(L, -2, fname); /* put object into table */
}
/*
** Calls 'lua_getinfo' and collects all results in a new table.
** L1 needs stack space for an optional input (function) plus
** two optional outputs (function and line table) from function
** 'lua_getinfo'.
*/
static int db_getinfo (lua_State *L) {
lua_Debug ar;
int arg;
lua_State *L1 = getthread(L, &arg);
const char *options = luaL_optstring(L, arg+2, "flnSrtu");
checkstack(L, L1, 3);
luaL_argcheck(L, options[0] != '>', arg + 2, "invalid option '>'");
if (lua_isfunction(L, arg + 1)) { /* info about a function? */
options = lua_pushfstring(L, ">%s", options); /* add '>' to 'options' */
lua_pushvalue(L, arg + 1); /* move function to 'L1' stack */
lua_xmove(L, L1, 1);
}
else { /* stack level */
if (!lua_getstack(L1, (int)luaL_checkinteger(L, arg + 1), &ar)) {
luaL_pushfail(L); /* level out of range */
return 1;
}
}
if (!lua_getinfo(L1, options, &ar))
return luaL_argerror(L, arg+2, "invalid option");
lua_newtable(L); /* table to collect results */
if (strchr(options, 'S')) {
lua_pushlstring(L, ar.source, ar.srclen);
lua_setfield(L, -2, "source");
settabss(L, "short_src", ar.short_src);
settabsi(L, "linedefined", ar.linedefined);
settabsi(L, "lastlinedefined", ar.lastlinedefined);
settabss(L, "what", ar.what);
}
if (strchr(options, 'l'))
settabsi(L, "currentline", ar.currentline);
if (strchr(options, 'u')) {
settabsi(L, "nups", ar.nups);
settabsi(L, "nparams", ar.nparams);
settabsb(L, "isvararg", ar.isvararg);
}
if (strchr(options, 'n')) {
settabss(L, "name", ar.name);
settabss(L, "namewhat", ar.namewhat);
}
if (strchr(options, 'r')) {
settabsi(L, "ftransfer", ar.ftransfer);
settabsi(L, "ntransfer", ar.ntransfer);
}
if (strchr(options, 't'))
settabsb(L, "istailcall", ar.istailcall);
if (strchr(options, 'L'))
treatstackoption(L, L1, "activelines");
if (strchr(options, 'f'))
treatstackoption(L, L1, "func");
return 1; /* return table */
}
static int db_getlocal (lua_State *L) {
int arg;
lua_State *L1 = getthread(L, &arg);
int nvar = (int)luaL_checkinteger(L, arg + 2); /* local-variable index */
if (lua_isfunction(L, arg + 1)) { /* function argument? */
lua_pushvalue(L, arg + 1); /* push function */
lua_pushstring(L, lua_getlocal(L, NULL, nvar)); /* push local name */
return 1; /* return only name (there is no value) */
}
else { /* stack-level argument */
lua_Debug ar;
const char *name;
int level = (int)luaL_checkinteger(L, arg + 1);
if (l_unlikely(!lua_getstack(L1, level, &ar))) /* out of range? */
return luaL_argerror(L, arg+1, "level out of range");
checkstack(L, L1, 1);
name = lua_getlocal(L1, &ar, nvar);
if (name) {
lua_xmove(L1, L, 1); /* move local value */
lua_pushstring(L, name); /* push name */
lua_rotate(L, -2, 1); /* re-order */
return 2;
}
else {
luaL_pushfail(L); /* no name (nor value) */
return 1;
}
}
}
static int db_setlocal (lua_State *L) {
int arg;
const char *name;
lua_State *L1 = getthread(L, &arg);
lua_Debug ar;
int level = (int)luaL_checkinteger(L, arg + 1);
int nvar = (int)luaL_checkinteger(L, arg + 2);
if (l_unlikely(!lua_getstack(L1, level, &ar))) /* out of range? */
return luaL_argerror(L, arg+1, "level out of range");
luaL_checkany(L, arg+3);
lua_settop(L, arg+3);
checkstack(L, L1, 1);
lua_xmove(L, L1, 1);
name = lua_setlocal(L1, &ar, nvar);
if (name == NULL)
lua_pop(L1, 1); /* pop value (if not popped by 'lua_setlocal') */
lua_pushstring(L, name);
return 1;
}
/*
** get (if 'get' is true) or set an upvalue from a closure
*/
static int auxupvalue (lua_State *L, int get) {
const char *name;
int n = (int)luaL_checkinteger(L, 2); /* upvalue index */
luaL_checktype(L, 1, LUA_TFUNCTION); /* closure */
name = get ? lua_getupvalue(L, 1, n) : lua_setupvalue(L, 1, n);
if (name == NULL) return 0;
lua_pushstring(L, name);
lua_insert(L, -(get+1)); /* no-op if get is false */
return get + 1;
}
static int db_getupvalue (lua_State *L) {
return auxupvalue(L, 1);
}
static int db_setupvalue (lua_State *L) {
luaL_checkany(L, 3);
return auxupvalue(L, 0);
}
/*
** Check whether a given upvalue from a given closure exists and
** returns its index
*/
static void *checkupval (lua_State *L, int argf, int argnup, int *pnup) {
void *id;
int nup = (int)luaL_checkinteger(L, argnup); /* upvalue index */
luaL_checktype(L, argf, LUA_TFUNCTION); /* closure */
id = lua_upvalueid(L, argf, nup);
if (pnup) {
luaL_argcheck(L, id != NULL, argnup, "invalid upvalue index");
*pnup = nup;
}
return id;
}
static int db_upvalueid (lua_State *L) {
void *id = checkupval(L, 1, 2, NULL);
if (id != NULL)
lua_pushlightuserdata(L, id);
else
luaL_pushfail(L);
return 1;
}
static int db_upvaluejoin (lua_State *L) {
int n1, n2;
checkupval(L, 1, 2, &n1);
checkupval(L, 3, 4, &n2);
luaL_argcheck(L, !lua_iscfunction(L, 1), 1, "Lua function expected");
luaL_argcheck(L, !lua_iscfunction(L, 3), 3, "Lua function expected");
lua_upvaluejoin(L, 1, n1, 3, n2);
return 0;
}
/*
** Call hook function registered at hook table for the current
** thread (if there is one)
*/
static void hookf (lua_State *L, lua_Debug *ar) {
static const char *const hooknames[] =
{"call", "return", "line", "count", "tail call"};
lua_getfield(L, LUA_REGISTRYINDEX, HOOKKEY);
lua_pushthread(L);
if (lua_rawget(L, -2) == LUA_TFUNCTION) { /* is there a hook function? */
lua_pushstring(L, hooknames[(int)ar->event]); /* push event name */
if (ar->currentline >= 0)
lua_pushinteger(L, ar->currentline); /* push current line */
else lua_pushnil(L);
lua_assert(lua_getinfo(L, "lS", ar));
lua_call(L, 2, 0); /* call hook function */
}
}
/*
** Convert a string mask (for 'sethook') into a bit mask
*/
static int makemask (const char *smask, int count) {
int mask = 0;
if (strchr(smask, 'c')) mask |= LUA_MASKCALL;
if (strchr(smask, 'r')) mask |= LUA_MASKRET;
if (strchr(smask, 'l')) mask |= LUA_MASKLINE;
if (count > 0) mask |= LUA_MASKCOUNT;
return mask;
}
/*
** Convert a bit mask (for 'gethook') into a string mask
*/
static char *unmakemask (int mask, char *smask) {
int i = 0;
if (mask & LUA_MASKCALL) smask[i++] = 'c';
if (mask & LUA_MASKRET) smask[i++] = 'r';
if (mask & LUA_MASKLINE) smask[i++] = 'l';
smask[i] = '\0';
return smask;
}
static int db_sethook (lua_State *L) {
int arg, mask, count;
lua_Hook func;
lua_State *L1 = getthread(L, &arg);
if (lua_isnoneornil(L, arg+1)) { /* no hook? */
lua_settop(L, arg+1);
func = NULL; mask = 0; count = 0; /* turn off hooks */
}
else {
const char *smask = luaL_checkstring(L, arg+2);
luaL_checktype(L, arg+1, LUA_TFUNCTION);
count = (int)luaL_optinteger(L, arg + 3, 0);
func = hookf; mask = makemask(smask, count);
}
if (!luaL_getsubtable(L, LUA_REGISTRYINDEX, HOOKKEY)) {
/* table just created; initialize it */
lua_pushliteral(L, "k");
lua_setfield(L, -2, "__mode"); /** hooktable.__mode = "k" */
lua_pushvalue(L, -1);
lua_setmetatable(L, -2); /* metatable(hooktable) = hooktable */
}
checkstack(L, L1, 1);
lua_pushthread(L1); lua_xmove(L1, L, 1); /* key (thread) */
lua_pushvalue(L, arg + 1); /* value (hook function) */
lua_rawset(L, -3); /* hooktable[L1] = new Lua hook */
lua_sethook(L1, func, mask, count);
return 0;
}
static int db_gethook (lua_State *L) {
int arg;
lua_State *L1 = getthread(L, &arg);
char buff[5];
int mask = lua_gethookmask(L1);
lua_Hook hook = lua_gethook(L1);
if (hook == NULL) { /* no hook? */
luaL_pushfail(L);
return 1;
}
else if (hook != hookf) /* external hook? */
lua_pushliteral(L, "external hook");
else { /* hook table must exist */
lua_getfield(L, LUA_REGISTRYINDEX, HOOKKEY);
checkstack(L, L1, 1);
lua_pushthread(L1); lua_xmove(L1, L, 1);
lua_rawget(L, -2); /* 1st result = hooktable[L1] */
lua_remove(L, -2); /* remove hook table */
}
lua_pushstring(L, unmakemask(mask, buff)); /* 2nd result = mask */
lua_pushinteger(L, lua_gethookcount(L1)); /* 3rd result = count */
return 3;
}
static int db_debug (lua_State *L) {
for (;;) {
char buffer[250];
lua_writestringerror("%s", "lua_debug> ");
if (fgets(buffer, sizeof(buffer), stdin) == NULL ||
strcmp(buffer, "cont\n") == 0)
return 0;
if (luaL_loadbuffer(L, buffer, strlen(buffer), "=(debug command)") ||
lua_pcall(L, 0, 0, 0))
lua_writestringerror("%s\n", luaL_tolstring(L, -1, NULL));
lua_settop(L, 0); /* remove eventual returns */
}
}
static int db_traceback (lua_State *L) {
int arg;
lua_State *L1 = getthread(L, &arg);
const char *msg = lua_tostring(L, arg + 1);
if (msg == NULL && !lua_isnoneornil(L, arg + 1)) /* non-string 'msg'? */
lua_pushvalue(L, arg + 1); /* return it untouched */
else {
int level = (int)luaL_optinteger(L, arg + 2, (L == L1) ? 1 : 0);
luaL_traceback(L, L1, msg, level);
}
return 1;
}
static int db_setcstacklimit (lua_State *L) {
int limit = (int)luaL_checkinteger(L, 1);
int res = lua_setcstacklimit(L, limit);
lua_pushinteger(L, res);
return 1;
}
static const luaL_Reg dblib[] = {
{"debug", db_debug},
{"getuservalue", db_getuservalue},
{"gethook", db_gethook},
{"getinfo", db_getinfo},
{"getlocal", db_getlocal},
{"getregistry", db_getregistry},
{"getmetatable", db_getmetatable},
{"getupvalue", db_getupvalue},
{"upvaluejoin", db_upvaluejoin},
{"upvalueid", db_upvalueid},
{"setuservalue", db_setuservalue},
{"sethook", db_sethook},
{"setlocal", db_setlocal},
{"setmetatable", db_setmetatable},
{"setupvalue", db_setupvalue},
{"traceback", db_traceback},
{"setcstacklimit", db_setcstacklimit},
{NULL, NULL}
};
LUAMOD_API int luaopen_debug (lua_State *L) {
luaL_newlib(L, dblib);
return 1;
}
+962
View File
@@ -0,0 +1,962 @@
/*
** $Id: ldebug.c $
** Debug Interface
** See Copyright Notice in lua.h
*/
#define ldebug_c
#define LUA_CORE
#include "lprefix.h"
#include <stdarg.h>
#include <stddef.h>
#include <string.h>
#include "lua.h"
#include "lapi.h"
#include "lcode.h"
#include "ldebug.h"
#include "ldo.h"
#include "lfunc.h"
#include "lobject.h"
#include "lopcodes.h"
#include "lstate.h"
#include "lstring.h"
#include "ltable.h"
#include "ltm.h"
#include "lvm.h"
#define LuaClosure(f) ((f) != NULL && (f)->c.tt == LUA_VLCL)
static const char *funcnamefromcall (lua_State *L, CallInfo *ci,
const char **name);
static int currentpc (CallInfo *ci) {
lua_assert(isLua(ci));
return pcRel(ci->u.l.savedpc, ci_func(ci)->p);
}
/*
** Get a "base line" to find the line corresponding to an instruction.
** Base lines are regularly placed at MAXIWTHABS intervals, so usually
** an integer division gets the right place. When the source file has
** large sequences of empty/comment lines, it may need extra entries,
** so the original estimate needs a correction.
** If the original estimate is -1, the initial 'if' ensures that the
** 'while' will run at least once.
** The assertion that the estimate is a lower bound for the correct base
** is valid as long as the debug info has been generated with the same
** value for MAXIWTHABS or smaller. (Previous releases use a little
** smaller value.)
*/
static int getbaseline (const Proto *f, int pc, int *basepc) {
if (f->sizeabslineinfo == 0 || pc < f->abslineinfo[0].pc) {
*basepc = -1; /* start from the beginning */
return f->linedefined;
}
else {
int i = cast_uint(pc) / MAXIWTHABS - 1; /* get an estimate */
/* estimate must be a lower bound of the correct base */
lua_assert(i < 0 ||
(i < f->sizeabslineinfo && f->abslineinfo[i].pc <= pc));
while (i + 1 < f->sizeabslineinfo && pc >= f->abslineinfo[i + 1].pc)
i++; /* low estimate; adjust it */
*basepc = f->abslineinfo[i].pc;
return f->abslineinfo[i].line;
}
}
/*
** Get the line corresponding to instruction 'pc' in function 'f';
** first gets a base line and from there does the increments until
** the desired instruction.
*/
int luaG_getfuncline (const Proto *f, int pc) {
if (f->lineinfo == NULL) /* no debug information? */
return -1;
else {
int basepc;
int baseline = getbaseline(f, pc, &basepc);
while (basepc++ < pc) { /* walk until given instruction */
lua_assert(f->lineinfo[basepc] != ABSLINEINFO);
baseline += f->lineinfo[basepc]; /* correct line */
}
return baseline;
}
}
static int getcurrentline (CallInfo *ci) {
return luaG_getfuncline(ci_func(ci)->p, currentpc(ci));
}
/*
** Set 'trap' for all active Lua frames.
** This function can be called during a signal, under "reasonable"
** assumptions. A new 'ci' is completely linked in the list before it
** becomes part of the "active" list, and we assume that pointers are
** atomic; see comment in next function.
** (A compiler doing interprocedural optimizations could, theoretically,
** reorder memory writes in such a way that the list could be
** temporarily broken while inserting a new element. We simply assume it
** has no good reasons to do that.)
*/
static void settraps (CallInfo *ci) {
for (; ci != NULL; ci = ci->previous)
if (isLua(ci))
ci->u.l.trap = 1;
}
/*
** This function can be called during a signal, under "reasonable"
** assumptions.
** Fields 'basehookcount' and 'hookcount' (set by 'resethookcount')
** are for debug only, and it is no problem if they get arbitrary
** values (causes at most one wrong hook call). 'hookmask' is an atomic
** value. We assume that pointers are atomic too (e.g., gcc ensures that
** for all platforms where it runs). Moreover, 'hook' is always checked
** before being called (see 'luaD_hook').
*/
LUA_API void lua_sethook (lua_State *L, lua_Hook func, int mask, int count) {
if (func == NULL || mask == 0) { /* turn off hooks? */
mask = 0;
func = NULL;
}
L->hook = func;
L->basehookcount = count;
resethookcount(L);
L->hookmask = cast_byte(mask);
if (mask)
settraps(L->ci); /* to trace inside 'luaV_execute' */
}
LUA_API lua_Hook lua_gethook (lua_State *L) {
return L->hook;
}
LUA_API int lua_gethookmask (lua_State *L) {
return L->hookmask;
}
LUA_API int lua_gethookcount (lua_State *L) {
return L->basehookcount;
}
LUA_API int lua_getstack (lua_State *L, int level, lua_Debug *ar) {
int status;
CallInfo *ci;
if (level < 0) return 0; /* invalid (negative) level */
lua_lock(L);
for (ci = L->ci; level > 0 && ci != &L->base_ci; ci = ci->previous)
level--;
if (level == 0 && ci != &L->base_ci) { /* level found? */
status = 1;
ar->i_ci = ci;
}
else status = 0; /* no such level */
lua_unlock(L);
return status;
}
static const char *upvalname (const Proto *p, int uv) {
TString *s = check_exp(uv < p->sizeupvalues, p->upvalues[uv].name);
if (s == NULL) return "?";
else return getstr(s);
}
static const char *findvararg (CallInfo *ci, int n, StkId *pos) {
if (clLvalue(s2v(ci->func.p))->p->is_vararg) {
int nextra = ci->u.l.nextraargs;
if (n >= -nextra) { /* 'n' is negative */
*pos = ci->func.p - nextra - (n + 1);
return "(vararg)"; /* generic name for any vararg */
}
}
return NULL; /* no such vararg */
}
const char *luaG_findlocal (lua_State *L, CallInfo *ci, int n, StkId *pos) {
StkId base = ci->func.p + 1;
const char *name = NULL;
if (isLua(ci)) {
if (n < 0) /* access to vararg values? */
return findvararg(ci, n, pos);
else
name = luaF_getlocalname(ci_func(ci)->p, n, currentpc(ci));
}
if (name == NULL) { /* no 'standard' name? */
StkId limit = (ci == L->ci) ? L->top.p : ci->next->func.p;
if (limit - base >= n && n > 0) { /* is 'n' inside 'ci' stack? */
/* generic name for any valid slot */
name = isLua(ci) ? "(temporary)" : "(C temporary)";
}
else
return NULL; /* no name */
}
if (pos)
*pos = base + (n - 1);
return name;
}
LUA_API const char *lua_getlocal (lua_State *L, const lua_Debug *ar, int n) {
const char *name;
lua_lock(L);
if (ar == NULL) { /* information about non-active function? */
if (!isLfunction(s2v(L->top.p - 1))) /* not a Lua function? */
name = NULL;
else /* consider live variables at function start (parameters) */
name = luaF_getlocalname(clLvalue(s2v(L->top.p - 1))->p, n, 0);
}
else { /* active function; get information through 'ar' */
StkId pos = NULL; /* to avoid warnings */
name = luaG_findlocal(L, ar->i_ci, n, &pos);
if (name) {
setobjs2s(L, L->top.p, pos);
api_incr_top(L);
}
}
lua_unlock(L);
return name;
}
LUA_API const char *lua_setlocal (lua_State *L, const lua_Debug *ar, int n) {
StkId pos = NULL; /* to avoid warnings */
const char *name;
lua_lock(L);
name = luaG_findlocal(L, ar->i_ci, n, &pos);
if (name) {
setobjs2s(L, pos, L->top.p - 1);
L->top.p--; /* pop value */
}
lua_unlock(L);
return name;
}
static void funcinfo (lua_Debug *ar, Closure *cl) {
if (!LuaClosure(cl)) {
ar->source = "=[C]";
ar->srclen = LL("=[C]");
ar->linedefined = -1;
ar->lastlinedefined = -1;
ar->what = "C";
}
else {
const Proto *p = cl->l.p;
if (p->source) {
ar->source = getstr(p->source);
ar->srclen = tsslen(p->source);
}
else {
ar->source = "=?";
ar->srclen = LL("=?");
}
ar->linedefined = p->linedefined;
ar->lastlinedefined = p->lastlinedefined;
ar->what = (ar->linedefined == 0) ? "main" : "Lua";
}
luaO_chunkid(ar->short_src, ar->source, ar->srclen);
}
static int nextline (const Proto *p, int currentline, int pc) {
if (p->lineinfo[pc] != ABSLINEINFO)
return currentline + p->lineinfo[pc];
else
return luaG_getfuncline(p, pc);
}
static void collectvalidlines (lua_State *L, Closure *f) {
if (!LuaClosure(f)) {
setnilvalue(s2v(L->top.p));
api_incr_top(L);
}
else {
const Proto *p = f->l.p;
int currentline = p->linedefined;
Table *t = luaH_new(L); /* new table to store active lines */
sethvalue2s(L, L->top.p, t); /* push it on stack */
api_incr_top(L);
if (p->lineinfo != NULL) { /* proto with debug information? */
int i;
TValue v;
setbtvalue(&v); /* boolean 'true' to be the value of all indices */
if (!p->is_vararg) /* regular function? */
i = 0; /* consider all instructions */
else { /* vararg function */
lua_assert(GET_OPCODE(p->code[0]) == OP_VARARGPREP);
currentline = nextline(p, currentline, 0);
i = 1; /* skip first instruction (OP_VARARGPREP) */
}
for (; i < p->sizelineinfo; i++) { /* for each instruction */
currentline = nextline(p, currentline, i); /* get its line */
luaH_setint(L, t, currentline, &v); /* table[line] = true */
}
}
}
}
static const char *getfuncname (lua_State *L, CallInfo *ci, const char **name) {
/* calling function is a known function? */
if (ci != NULL && !(ci->callstatus & CIST_TAIL))
return funcnamefromcall(L, ci->previous, name);
else return NULL; /* no way to find a name */
}
static int auxgetinfo (lua_State *L, const char *what, lua_Debug *ar,
Closure *f, CallInfo *ci) {
int status = 1;
for (; *what; what++) {
switch (*what) {
case 'S': {
funcinfo(ar, f);
break;
}
case 'l': {
ar->currentline = (ci && isLua(ci)) ? getcurrentline(ci) : -1;
break;
}
case 'u': {
ar->nups = (f == NULL) ? 0 : f->c.nupvalues;
if (!LuaClosure(f)) {
ar->isvararg = 1;
ar->nparams = 0;
}
else {
ar->isvararg = f->l.p->is_vararg;
ar->nparams = f->l.p->numparams;
}
break;
}
case 't': {
ar->istailcall = (ci) ? ci->callstatus & CIST_TAIL : 0;
break;
}
case 'n': {
ar->namewhat = getfuncname(L, ci, &ar->name);
if (ar->namewhat == NULL) {
ar->namewhat = ""; /* not found */
ar->name = NULL;
}
break;
}
case 'r': {
if (ci == NULL || !(ci->callstatus & CIST_TRAN))
ar->ftransfer = ar->ntransfer = 0;
else {
ar->ftransfer = ci->u2.transferinfo.ftransfer;
ar->ntransfer = ci->u2.transferinfo.ntransfer;
}
break;
}
case 'L':
case 'f': /* handled by lua_getinfo */
break;
default: status = 0; /* invalid option */
}
}
return status;
}
LUA_API int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar) {
int status;
Closure *cl;
CallInfo *ci;
TValue *func;
lua_lock(L);
if (*what == '>') {
ci = NULL;
func = s2v(L->top.p - 1);
api_check(L, ttisfunction(func), "function expected");
what++; /* skip the '>' */
L->top.p--; /* pop function */
}
else {
ci = ar->i_ci;
func = s2v(ci->func.p);
lua_assert(ttisfunction(func));
}
cl = ttisclosure(func) ? clvalue(func) : NULL;
status = auxgetinfo(L, what, ar, cl, ci);
if (strchr(what, 'f')) {
setobj2s(L, L->top.p, func);
api_incr_top(L);
}
if (strchr(what, 'L'))
collectvalidlines(L, cl);
lua_unlock(L);
return status;
}
/*
** {======================================================
** Symbolic Execution
** =======================================================
*/
static int filterpc (int pc, int jmptarget) {
if (pc < jmptarget) /* is code conditional (inside a jump)? */
return -1; /* cannot know who sets that register */
else return pc; /* current position sets that register */
}
/*
** Try to find last instruction before 'lastpc' that modified register 'reg'.
*/
static int findsetreg (const Proto *p, int lastpc, int reg) {
int pc;
int setreg = -1; /* keep last instruction that changed 'reg' */
int jmptarget = 0; /* any code before this address is conditional */
if (testMMMode(GET_OPCODE(p->code[lastpc])))
lastpc--; /* previous instruction was not actually executed */
for (pc = 0; pc < lastpc; pc++) {
Instruction i = p->code[pc];
OpCode op = GET_OPCODE(i);
int a = GETARG_A(i);
int change; /* true if current instruction changed 'reg' */
switch (op) {
case OP_LOADNIL: { /* set registers from 'a' to 'a+b' */
int b = GETARG_B(i);
change = (a <= reg && reg <= a + b);
break;
}
case OP_TFORCALL: { /* affect all regs above its base */
change = (reg >= a + 2);
break;
}
case OP_CALL:
case OP_TAILCALL: { /* affect all registers above base */
change = (reg >= a);
break;
}
case OP_JMP: { /* doesn't change registers, but changes 'jmptarget' */
int b = GETARG_sJ(i);
int dest = pc + 1 + b;
/* jump does not skip 'lastpc' and is larger than current one? */
if (dest <= lastpc && dest > jmptarget)
jmptarget = dest; /* update 'jmptarget' */
change = 0;
break;
}
default: /* any instruction that sets A */
change = (testAMode(op) && reg == a);
break;
}
if (change)
setreg = filterpc(pc, jmptarget);
}
return setreg;
}
/*
** Find a "name" for the constant 'c'.
*/
static const char *kname (const Proto *p, int index, const char **name) {
TValue *kvalue = &p->k[index];
if (ttisstring(kvalue)) {
*name = getstr(tsvalue(kvalue));
return "constant";
}
else {
*name = "?";
return NULL;
}
}
static const char *basicgetobjname (const Proto *p, int *ppc, int reg,
const char **name) {
int pc = *ppc;
*name = luaF_getlocalname(p, reg + 1, pc);
if (*name) /* is a local? */
return "local";
/* else try symbolic execution */
*ppc = pc = findsetreg(p, pc, reg);
if (pc != -1) { /* could find instruction? */
Instruction i = p->code[pc];
OpCode op = GET_OPCODE(i);
switch (op) {
case OP_MOVE: {
int b = GETARG_B(i); /* move from 'b' to 'a' */
if (b < GETARG_A(i))
return basicgetobjname(p, ppc, b, name); /* get name for 'b' */
break;
}
case OP_GETUPVAL: {
*name = upvalname(p, GETARG_B(i));
return "upvalue";
}
case OP_LOADK: return kname(p, GETARG_Bx(i), name);
case OP_LOADKX: return kname(p, GETARG_Ax(p->code[pc + 1]), name);
default: break;
}
}
return NULL; /* could not find reasonable name */
}
/*
** Find a "name" for the register 'c'.
*/
static void rname (const Proto *p, int pc, int c, const char **name) {
const char *what = basicgetobjname(p, &pc, c, name); /* search for 'c' */
if (!(what && *what == 'c')) /* did not find a constant name? */
*name = "?";
}
/*
** Find a "name" for a 'C' value in an RK instruction.
*/
static void rkname (const Proto *p, int pc, Instruction i, const char **name) {
int c = GETARG_C(i); /* key index */
if (GETARG_k(i)) /* is 'c' a constant? */
kname(p, c, name);
else /* 'c' is a register */
rname(p, pc, c, name);
}
/*
** Check whether table being indexed by instruction 'i' is the
** environment '_ENV'
*/
static const char *isEnv (const Proto *p, int pc, Instruction i, int isup) {
int t = GETARG_B(i); /* table index */
const char *name; /* name of indexed variable */
if (isup) /* is 't' an upvalue? */
name = upvalname(p, t);
else /* 't' is a register */
basicgetobjname(p, &pc, t, &name);
return (name && strcmp(name, LUA_ENV) == 0) ? "global" : "field";
}
/*
** Extend 'basicgetobjname' to handle table accesses
*/
static const char *getobjname (const Proto *p, int lastpc, int reg,
const char **name) {
const char *kind = basicgetobjname(p, &lastpc, reg, name);
if (kind != NULL)
return kind;
else if (lastpc != -1) { /* could find instruction? */
Instruction i = p->code[lastpc];
OpCode op = GET_OPCODE(i);
switch (op) {
case OP_GETTABUP: {
int k = GETARG_C(i); /* key index */
kname(p, k, name);
return isEnv(p, lastpc, i, 1);
}
case OP_GETTABLE: {
int k = GETARG_C(i); /* key index */
rname(p, lastpc, k, name);
return isEnv(p, lastpc, i, 0);
}
case OP_GETI: {
*name = "integer index";
return "field";
}
case OP_GETFIELD: {
int k = GETARG_C(i); /* key index */
kname(p, k, name);
return isEnv(p, lastpc, i, 0);
}
case OP_SELF: {
rkname(p, lastpc, i, name);
return "method";
}
default: break; /* go through to return NULL */
}
}
return NULL; /* could not find reasonable name */
}
/*
** Try to find a name for a function based on the code that called it.
** (Only works when function was called by a Lua function.)
** Returns what the name is (e.g., "for iterator", "method",
** "metamethod") and sets '*name' to point to the name.
*/
static const char *funcnamefromcode (lua_State *L, const Proto *p,
int pc, const char **name) {
TMS tm = (TMS)0; /* (initial value avoids warnings) */
Instruction i = p->code[pc]; /* calling instruction */
switch (GET_OPCODE(i)) {
case OP_CALL:
case OP_TAILCALL:
return getobjname(p, pc, GETARG_A(i), name); /* get function name */
case OP_TFORCALL: { /* for iterator */
*name = "for iterator";
return "for iterator";
}
/* other instructions can do calls through metamethods */
case OP_SELF: case OP_GETTABUP: case OP_GETTABLE:
case OP_GETI: case OP_GETFIELD:
tm = TM_INDEX;
break;
case OP_SETTABUP: case OP_SETTABLE: case OP_SETI: case OP_SETFIELD:
tm = TM_NEWINDEX;
break;
case OP_MMBIN: case OP_MMBINI: case OP_MMBINK: {
tm = cast(TMS, GETARG_C(i));
break;
}
case OP_UNM: tm = TM_UNM; break;
case OP_BNOT: tm = TM_BNOT; break;
case OP_LEN: tm = TM_LEN; break;
case OP_CONCAT: tm = TM_CONCAT; break;
case OP_EQ: tm = TM_EQ; break;
/* no cases for OP_EQI and OP_EQK, as they don't call metamethods */
case OP_LT: case OP_LTI: case OP_GTI: tm = TM_LT; break;
case OP_LE: case OP_LEI: case OP_GEI: tm = TM_LE; break;
case OP_CLOSE: case OP_RETURN: tm = TM_CLOSE; break;
default:
return NULL; /* cannot find a reasonable name */
}
*name = getshrstr(G(L)->tmname[tm]) + 2;
return "metamethod";
}
/*
** Try to find a name for a function based on how it was called.
*/
static const char *funcnamefromcall (lua_State *L, CallInfo *ci,
const char **name) {
if (ci->callstatus & CIST_HOOKED) { /* was it called inside a hook? */
*name = "?";
return "hook";
}
else if (ci->callstatus & CIST_FIN) { /* was it called as a finalizer? */
*name = "__gc";
return "metamethod"; /* report it as such */
}
else if (isLua(ci))
return funcnamefromcode(L, ci_func(ci)->p, currentpc(ci), name);
else
return NULL;
}
/* }====================================================== */
/*
** Check whether pointer 'o' points to some value in the stack frame of
** the current function and, if so, returns its index. Because 'o' may
** not point to a value in this stack, we cannot compare it with the
** region boundaries (undefined behavior in ISO C).
*/
static int instack (CallInfo *ci, const TValue *o) {
int pos;
StkId base = ci->func.p + 1;
for (pos = 0; base + pos < ci->top.p; pos++) {
if (o == s2v(base + pos))
return pos;
}
return -1; /* not found */
}
/*
** Checks whether value 'o' came from an upvalue. (That can only happen
** with instructions OP_GETTABUP/OP_SETTABUP, which operate directly on
** upvalues.)
*/
static const char *getupvalname (CallInfo *ci, const TValue *o,
const char **name) {
LClosure *c = ci_func(ci);
int i;
for (i = 0; i < c->nupvalues; i++) {
if (c->upvals[i]->v.p == o) {
*name = upvalname(c->p, i);
return "upvalue";
}
}
return NULL;
}
static const char *formatvarinfo (lua_State *L, const char *kind,
const char *name) {
if (kind == NULL)
return ""; /* no information */
else
return luaO_pushfstring(L, " (%s '%s')", kind, name);
}
/*
** Build a string with a "description" for the value 'o', such as
** "variable 'x'" or "upvalue 'y'".
*/
static const char *varinfo (lua_State *L, const TValue *o) {
CallInfo *ci = L->ci;
const char *name = NULL; /* to avoid warnings */
const char *kind = NULL;
if (isLua(ci)) {
kind = getupvalname(ci, o, &name); /* check whether 'o' is an upvalue */
if (!kind) { /* not an upvalue? */
int reg = instack(ci, o); /* try a register */
if (reg >= 0) /* is 'o' a register? */
kind = getobjname(ci_func(ci)->p, currentpc(ci), reg, &name);
}
}
return formatvarinfo(L, kind, name);
}
/*
** Raise a type error
*/
static l_noret typeerror (lua_State *L, const TValue *o, const char *op,
const char *extra) {
const char *t = luaT_objtypename(L, o);
luaG_runerror(L, "attempt to %s a %s value%s", op, t, extra);
}
/*
** Raise a type error with "standard" information about the faulty
** object 'o' (using 'varinfo').
*/
l_noret luaG_typeerror (lua_State *L, const TValue *o, const char *op) {
typeerror(L, o, op, varinfo(L, o));
}
/*
** Raise an error for calling a non-callable object. Try to find a name
** for the object based on how it was called ('funcnamefromcall'); if it
** cannot get a name there, try 'varinfo'.
*/
l_noret luaG_callerror (lua_State *L, const TValue *o) {
CallInfo *ci = L->ci;
const char *name = NULL; /* to avoid warnings */
const char *kind = funcnamefromcall(L, ci, &name);
const char *extra = kind ? formatvarinfo(L, kind, name) : varinfo(L, o);
typeerror(L, o, "call", extra);
}
l_noret luaG_forerror (lua_State *L, const TValue *o, const char *what) {
luaG_runerror(L, "bad 'for' %s (number expected, got %s)",
what, luaT_objtypename(L, o));
}
l_noret luaG_concaterror (lua_State *L, const TValue *p1, const TValue *p2) {
if (ttisstring(p1) || cvt2str(p1)) p1 = p2;
luaG_typeerror(L, p1, "concatenate");
}
l_noret luaG_opinterror (lua_State *L, const TValue *p1,
const TValue *p2, const char *msg) {
if (!ttisnumber(p1)) /* first operand is wrong? */
p2 = p1; /* now second is wrong */
luaG_typeerror(L, p2, msg);
}
/*
** Error when both values are convertible to numbers, but not to integers
*/
l_noret luaG_tointerror (lua_State *L, const TValue *p1, const TValue *p2) {
lua_Integer temp;
if (!luaV_tointegerns(p1, &temp, LUA_FLOORN2I))
p2 = p1;
luaG_runerror(L, "number%s has no integer representation", varinfo(L, p2));
}
l_noret luaG_ordererror (lua_State *L, const TValue *p1, const TValue *p2) {
const char *t1 = luaT_objtypename(L, p1);
const char *t2 = luaT_objtypename(L, p2);
if (strcmp(t1, t2) == 0)
luaG_runerror(L, "attempt to compare two %s values", t1);
else
luaG_runerror(L, "attempt to compare %s with %s", t1, t2);
}
/* add src:line information to 'msg' */
const char *luaG_addinfo (lua_State *L, const char *msg, TString *src,
int line) {
char buff[LUA_IDSIZE];
if (src)
luaO_chunkid(buff, getstr(src), tsslen(src));
else { /* no source available; use "?" instead */
buff[0] = '?'; buff[1] = '\0';
}
return luaO_pushfstring(L, "%s:%d: %s", buff, line, msg);
}
l_noret luaG_errormsg (lua_State *L) {
if (L->errfunc != 0) { /* is there an error handling function? */
StkId errfunc = restorestack(L, L->errfunc);
lua_assert(ttisfunction(s2v(errfunc)));
setobjs2s(L, L->top.p, L->top.p - 1); /* move argument */
setobjs2s(L, L->top.p - 1, errfunc); /* push function */
L->top.p++; /* assume EXTRA_STACK */
luaD_callnoyield(L, L->top.p - 2, 1); /* call it */
}
luaD_throw(L, LUA_ERRRUN);
}
l_noret luaG_runerror (lua_State *L, const char *fmt, ...) {
CallInfo *ci = L->ci;
const char *msg;
va_list argp;
luaC_checkGC(L); /* error message uses memory */
va_start(argp, fmt);
msg = luaO_pushvfstring(L, fmt, argp); /* format message */
va_end(argp);
if (isLua(ci)) { /* if Lua function, add source:line information */
luaG_addinfo(L, msg, ci_func(ci)->p->source, getcurrentline(ci));
setobjs2s(L, L->top.p - 2, L->top.p - 1); /* remove 'msg' */
L->top.p--;
}
luaG_errormsg(L);
}
/*
** Check whether new instruction 'newpc' is in a different line from
** previous instruction 'oldpc'. More often than not, 'newpc' is only
** one or a few instructions after 'oldpc' (it must be after, see
** caller), so try to avoid calling 'luaG_getfuncline'. If they are
** too far apart, there is a good chance of a ABSLINEINFO in the way,
** so it goes directly to 'luaG_getfuncline'.
*/
static int changedline (const Proto *p, int oldpc, int newpc) {
if (p->lineinfo == NULL) /* no debug information? */
return 0;
if (newpc - oldpc < MAXIWTHABS / 2) { /* not too far apart? */
int delta = 0; /* line difference */
int pc = oldpc;
for (;;) {
int lineinfo = p->lineinfo[++pc];
if (lineinfo == ABSLINEINFO)
break; /* cannot compute delta; fall through */
delta += lineinfo;
if (pc == newpc)
return (delta != 0); /* delta computed successfully */
}
}
/* either instructions are too far apart or there is an absolute line
info in the way; compute line difference explicitly */
return (luaG_getfuncline(p, oldpc) != luaG_getfuncline(p, newpc));
}
/*
** Traces Lua calls. If code is running the first instruction of a function,
** and function is not vararg, and it is not coming from an yield,
** calls 'luaD_hookcall'. (Vararg functions will call 'luaD_hookcall'
** after adjusting its variable arguments; otherwise, they could call
** a line/count hook before the call hook. Functions coming from
** an yield already called 'luaD_hookcall' before yielding.)
*/
int luaG_tracecall (lua_State *L) {
CallInfo *ci = L->ci;
Proto *p = ci_func(ci)->p;
ci->u.l.trap = 1; /* ensure hooks will be checked */
if (ci->u.l.savedpc == p->code) { /* first instruction (not resuming)? */
if (p->is_vararg)
return 0; /* hooks will start at VARARGPREP instruction */
else if (!(ci->callstatus & CIST_HOOKYIELD)) /* not yieded? */
luaD_hookcall(L, ci); /* check 'call' hook */
}
return 1; /* keep 'trap' on */
}
/*
** Traces the execution of a Lua function. Called before the execution
** of each opcode, when debug is on. 'L->oldpc' stores the last
** instruction traced, to detect line changes. When entering a new
** function, 'npci' will be zero and will test as a new line whatever
** the value of 'oldpc'. Some exceptional conditions may return to
** a function without setting 'oldpc'. In that case, 'oldpc' may be
** invalid; if so, use zero as a valid value. (A wrong but valid 'oldpc'
** at most causes an extra call to a line hook.)
** This function is not "Protected" when called, so it should correct
** 'L->top.p' before calling anything that can run the GC.
*/
int luaG_traceexec (lua_State *L, const Instruction *pc) {
CallInfo *ci = L->ci;
lu_byte mask = L->hookmask;
const Proto *p = ci_func(ci)->p;
int counthook;
if (!(mask & (LUA_MASKLINE | LUA_MASKCOUNT))) { /* no hooks? */
ci->u.l.trap = 0; /* don't need to stop again */
return 0; /* turn off 'trap' */
}
pc++; /* reference is always next instruction */
ci->u.l.savedpc = pc; /* save 'pc' */
counthook = (mask & LUA_MASKCOUNT) && (--L->hookcount == 0);
if (counthook)
resethookcount(L); /* reset count */
else if (!(mask & LUA_MASKLINE))
return 1; /* no line hook and count != 0; nothing to be done now */
if (ci->callstatus & CIST_HOOKYIELD) { /* hook yielded last time? */
ci->callstatus &= ~CIST_HOOKYIELD; /* erase mark */
return 1; /* do not call hook again (VM yielded, so it did not move) */
}
if (!isIT(*(ci->u.l.savedpc - 1))) /* top not being used? */
L->top.p = ci->top.p; /* correct top */
if (counthook)
luaD_hook(L, LUA_HOOKCOUNT, -1, 0, 0); /* call count hook */
if (mask & LUA_MASKLINE) {
/* 'L->oldpc' may be invalid; use zero in this case */
int oldpc = (L->oldpc < p->sizecode) ? L->oldpc : 0;
int npci = pcRel(pc, p);
if (npci <= oldpc || /* call hook when jump back (loop), */
changedline(p, oldpc, npci)) { /* or when enter new line */
int newline = luaG_getfuncline(p, npci);
luaD_hook(L, LUA_HOOKLINE, newline, 0, 0); /* call line hook */
}
L->oldpc = npci; /* 'pc' of last call to line hook */
}
if (L->status == LUA_YIELD) { /* did hook yield? */
if (counthook)
L->hookcount = 1; /* undo decrement to zero */
ci->callstatus |= CIST_HOOKYIELD; /* mark that it yielded */
luaD_throw(L, LUA_YIELD);
}
return 1; /* keep 'trap' on */
}
+64
View File
@@ -0,0 +1,64 @@
/*
** $Id: ldebug.h $
** Auxiliary functions from Debug Interface module
** See Copyright Notice in lua.h
*/
#ifndef ldebug_h
#define ldebug_h
#include "lstate.h"
#define pcRel(pc, p) (cast_int((pc) - (p)->code) - 1)
/* Active Lua function (given call info) */
#define ci_func(ci) (clLvalue(s2v((ci)->func.p)))
#define resethookcount(L) (L->hookcount = L->basehookcount)
/*
** mark for entries in 'lineinfo' array that has absolute information in
** 'abslineinfo' array
*/
#define ABSLINEINFO (-0x80)
/*
** MAXimum number of successive Instructions WiTHout ABSolute line
** information. (A power of two allows fast divisions.)
*/
#if !defined(MAXIWTHABS)
#define MAXIWTHABS 128
#endif
LUAI_FUNC int luaG_getfuncline (const Proto *f, int pc);
LUAI_FUNC const char *luaG_findlocal (lua_State *L, CallInfo *ci, int n,
StkId *pos);
LUAI_FUNC l_noret luaG_typeerror (lua_State *L, const TValue *o,
const char *opname);
LUAI_FUNC l_noret luaG_callerror (lua_State *L, const TValue *o);
LUAI_FUNC l_noret luaG_forerror (lua_State *L, const TValue *o,
const char *what);
LUAI_FUNC l_noret luaG_concaterror (lua_State *L, const TValue *p1,
const TValue *p2);
LUAI_FUNC l_noret luaG_opinterror (lua_State *L, const TValue *p1,
const TValue *p2,
const char *msg);
LUAI_FUNC l_noret luaG_tointerror (lua_State *L, const TValue *p1,
const TValue *p2);
LUAI_FUNC l_noret luaG_ordererror (lua_State *L, const TValue *p1,
const TValue *p2);
LUAI_FUNC l_noret luaG_runerror (lua_State *L, const char *fmt, ...);
LUAI_FUNC const char *luaG_addinfo (lua_State *L, const char *msg,
TString *src, int line);
LUAI_FUNC l_noret luaG_errormsg (lua_State *L);
LUAI_FUNC int luaG_traceexec (lua_State *L, const Instruction *pc);
LUAI_FUNC int luaG_tracecall (lua_State *L);
#endif
+1028
View File
File diff suppressed because it is too large Load Diff
+87
View File
@@ -0,0 +1,87 @@
/*
** $Id: ldo.h $
** Stack and Call structure of Lua
** See Copyright Notice in lua.h
*/
#ifndef ldo_h
#define ldo_h
#include "llimits.h"
#include "lobject.h"
#include "lstate.h"
#include "lzio.h"
/*
** Macro to check stack size and grow stack if needed. Parameters
** 'pre'/'pos' allow the macro to preserve a pointer into the
** stack across reallocations, doing the work only when needed.
** It also allows the running of one GC step when the stack is
** reallocated.
** 'condmovestack' is used in heavy tests to force a stack reallocation
** at every check.
*/
#define luaD_checkstackaux(L,n,pre,pos) \
if (l_unlikely(L->stack_last.p - L->top.p <= (n))) \
{ pre; luaD_growstack(L, n, 1); pos; } \
else { condmovestack(L,pre,pos); }
/* In general, 'pre'/'pos' are empty (nothing to save) */
#define luaD_checkstack(L,n) luaD_checkstackaux(L,n,(void)0,(void)0)
#define savestack(L,pt) (cast_charp(pt) - cast_charp(L->stack.p))
#define restorestack(L,n) cast(StkId, cast_charp(L->stack.p) + (n))
/* macro to check stack size, preserving 'p' */
#define checkstackp(L,n,p) \
luaD_checkstackaux(L, n, \
ptrdiff_t t__ = savestack(L, p), /* save 'p' */ \
p = restorestack(L, t__)) /* 'pos' part: restore 'p' */
/* macro to check stack size and GC, preserving 'p' */
#define checkstackGCp(L,n,p) \
luaD_checkstackaux(L, n, \
ptrdiff_t t__ = savestack(L, p); /* save 'p' */ \
luaC_checkGC(L), /* stack grow uses memory */ \
p = restorestack(L, t__)) /* 'pos' part: restore 'p' */
/* macro to check stack size and GC */
#define checkstackGC(L,fsize) \
luaD_checkstackaux(L, (fsize), luaC_checkGC(L), (void)0)
/* type of protected functions, to be ran by 'runprotected' */
typedef void (*Pfunc) (lua_State *L, void *ud);
LUAI_FUNC void luaD_seterrorobj (lua_State *L, int errcode, StkId oldtop);
LUAI_FUNC int luaD_protectedparser (lua_State *L, ZIO *z, const char *name,
const char *mode);
LUAI_FUNC void luaD_hook (lua_State *L, int event, int line,
int fTransfer, int nTransfer);
LUAI_FUNC void luaD_hookcall (lua_State *L, CallInfo *ci);
LUAI_FUNC int luaD_pretailcall (lua_State *L, CallInfo *ci, StkId func,
int narg1, int delta);
LUAI_FUNC CallInfo *luaD_precall (lua_State *L, StkId func, int nResults);
LUAI_FUNC void luaD_call (lua_State *L, StkId func, int nResults);
LUAI_FUNC void luaD_callnoyield (lua_State *L, StkId func, int nResults);
LUAI_FUNC int luaD_closeprotected (lua_State *L, ptrdiff_t level, int status);
LUAI_FUNC int luaD_pcall (lua_State *L, Pfunc func, void *u,
ptrdiff_t oldtop, ptrdiff_t ef);
LUAI_FUNC void luaD_poscall (lua_State *L, CallInfo *ci, int nres);
LUAI_FUNC int luaD_reallocstack (lua_State *L, int newsize, int raiseerror);
LUAI_FUNC int luaD_growstack (lua_State *L, int n, int raiseerror);
LUAI_FUNC void luaD_shrinkstack (lua_State *L);
LUAI_FUNC void luaD_inctop (lua_State *L);
LUAI_FUNC l_noret luaD_throw (lua_State *L, int errcode);
LUAI_FUNC int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud);
#endif

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