From a4658b1951f4555662afdc0983f294c8eed67a8c Mon Sep 17 00:00:00 2001 From: doyle Date: Sun, 25 Jun 2023 22:30:56 +1000 Subject: [PATCH] perfaware: Setup part2 --- .gitignore | 2 +- part1/_clang-format => _clang-format | 0 build.bat | 323 +++++++++++++ part1/build.bat | 307 ------------- part2/listing_0065_haversine_formula.cpp | 53 +++ part2/listing_0066_haversine_generator.cpp | 220 +++++++++ part2/listing_0067_simple_haversine.cpp | 165 +++++++ part2/listing_0068_buffer.cpp | 72 +++ part2/listing_0069_lookup_json_parser.cpp | 508 +++++++++++++++++++++ part2/main.c | 55 +++ part2/pap2_stdlib.c | 217 +++++++++ part2/pap2_stdlib.h | 61 +++ project.rdbg | Bin 4303 -> 4384 bytes 13 files changed, 1675 insertions(+), 308 deletions(-) rename part1/_clang-format => _clang-format (100%) create mode 100644 build.bat delete mode 100644 part1/build.bat create mode 100644 part2/listing_0065_haversine_formula.cpp create mode 100644 part2/listing_0066_haversine_generator.cpp create mode 100644 part2/listing_0067_simple_haversine.cpp create mode 100644 part2/listing_0068_buffer.cpp create mode 100644 part2/listing_0069_lookup_json_parser.cpp create mode 100644 part2/main.c create mode 100644 part2/pap2_stdlib.c create mode 100644 part2/pap2_stdlib.h diff --git a/.gitignore b/.gitignore index 5c644e1..b45a037 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1 @@ -*/build +Build diff --git a/part1/_clang-format b/_clang-format similarity index 100% rename from part1/_clang-format rename to _clang-format diff --git a/build.bat b/build.bat new file mode 100644 index 0000000..ff71a8c --- /dev/null +++ b/build.bat @@ -0,0 +1,323 @@ +@echo off + +REM Setup ========================================================================================== +set script_dir_backslash=%~dp0 +set script_dir=%script_dir_backslash:~0,-1% +set build_dir=%script_dir%\Build + +set part1_dir=%script_dir%\part1 +set part1_build_dir=%build_dir%\part1 +if not exist %part1_build_dir% mkdir %part1_build_dir% + +set part2_dir=%script_dir%\part2 +set part2_build_dir=%build_dir%\part2 +if not exist %part2_build_dir% mkdir %part2_build_dir% +goto :part2 + +REM Part 1 ========================================================================================= +REM Build ========================================================================================== +pushd %part1_build_dir% +cl %part1_dir%\sim8086.c /W4 /WX /Z7 /nologo || exit /b 1 +popd + +REM Tests ========================================================================================== +set listing_0037=listing_0037_single_register_mov +set part1_build_dir_listing_0037=%part1_build_dir%\%listing_0037% + +copy /Y %part1_dir%\%listing_0037% %part1_build_dir% 1>NUL + +%part1_build_dir%\sim8086.exe %part1_build_dir_listing_0037% > %part1_build_dir_listing_0037%_disassembled.asm +nasm %part1_build_dir_listing_0037%_disassembled.asm +fc /B %part1_build_dir_listing_0037% %part1_build_dir_listing_0037%_disassembled || exit /b 1 + +REM ================================================================================================ +set listing_0038=listing_0038_many_register_mov +set part1_build_dir_listing_0038=%part1_build_dir%\%listing_0038% + +copy /Y %part1_dir%\%listing_0038% %part1_build_dir% 1>NUL + +%part1_build_dir%\sim8086.exe %part1_build_dir_listing_0038% > %part1_build_dir_listing_0038%_disassembled.asm +nasm %part1_build_dir_listing_0038%_disassembled.asm +fc /B %part1_build_dir_listing_0038% %part1_build_dir_listing_0038%_disassembled || exit /b 1 + +REM ================================================================================================ +set listing_0039=listing_0039_more_movs +set part1_build_dir_listing_0039=%part1_build_dir%\%listing_0039% + +copy /Y %part1_dir%\%listing_0039% %part1_build_dir% 1>NUL + +%part1_build_dir%\sim8086.exe %part1_build_dir_listing_0039% > %part1_build_dir_listing_0039%_disassembled.asm +nasm %part1_build_dir_listing_0039%_disassembled.asm +fc /B %part1_build_dir_listing_0039% %part1_build_dir_listing_0039%_disassembled || exit /b 1 + +REM ================================================================================================ +set listing_0040=listing_0040_challenge_movs +set part1_build_dir_listing_0040=%part1_build_dir%\%listing_0040% + +copy /Y %part1_dir%\%listing_0040% %part1_build_dir% 1>NUL + +%part1_build_dir%\sim8086.exe %part1_build_dir_listing_0040% > %part1_build_dir_listing_0040%_disassembled.asm +nasm %part1_build_dir_listing_0040%_disassembled.asm +fc /B %part1_build_dir_listing_0040% %part1_build_dir_listing_0040%_disassembled || exit /b 1 + +REM ================================================================================================ +set listing_0041=listing_0041_add_sub_cmp_jnz +set part1_build_dir_listing_0041=%part1_build_dir%\%listing_0041% + +copy /Y %part1_dir%\%listing_0041% %part1_build_dir% 1>NUL + +%part1_build_dir%\sim8086.exe %part1_build_dir_listing_0041% > %part1_build_dir_listing_0041%_disassembled.asm +nasm %part1_build_dir_listing_0041%_disassembled.asm +fc /B %part1_build_dir_listing_0041% %part1_build_dir_listing_0041%_disassembled || exit /b 1 + +REM ================================================================================================ +set listing_0042=listing_0042_completionist_decode +set part1_build_dir_listing_0042=%part1_build_dir%\%listing_0042% + +copy /Y %part1_dir%\%listing_0042% %part1_build_dir% 1>NUL + +%part1_build_dir%\sim8086.exe %part1_build_dir_listing_0042% > %part1_build_dir_listing_0042%_disassembled.asm +nasm %part1_build_dir_listing_0042%_disassembled.asm +fc /B %part1_build_dir_listing_0042% %part1_build_dir_listing_0042%_disassembled || exit /b 1 + +REM ================================================================================================ +set listing_0043=listing_0043_immediate_movs +set part1_build_dir_listing_0043=%part1_build_dir%\%listing_0043% + +copy /Y %part1_dir%\%listing_0043% %part1_build_dir% 1>NUL +copy /Y %part1_dir%\%listing_0043%.txt %part1_build_dir% 1>NUL + +%part1_build_dir%\sim8086.exe %part1_build_dir_listing_0043% > %part1_build_dir_listing_0043%_disassembled.asm +%part1_build_dir%\sim8086.exe --exec %part1_build_dir_listing_0043% > %part1_build_dir_listing_0043%_disassembled.txt + +nasm %part1_build_dir_listing_0043%_disassembled.asm + +fc /B %part1_build_dir_listing_0043% %part1_build_dir_listing_0043%_disassembled || exit /b 1 +fc /N %part1_build_dir_listing_0043%.txt %part1_build_dir_listing_0043%_disassembled.txt || exit /b 1 + +REM ================================================================================================ +set listing_0044=listing_0044_register_movs +set part1_build_dir_listing_0044=%part1_build_dir%\%listing_0044% + +copy /Y %part1_dir%\%listing_0044% %part1_build_dir% 1>NUL +copy /Y %part1_dir%\%listing_0044%.txt %part1_build_dir% 1>NUL + +%part1_build_dir%\sim8086.exe --exec %part1_build_dir_listing_0044% > %part1_build_dir_listing_0044%_disassembled.txt +%part1_build_dir%\sim8086.exe %part1_build_dir_listing_0044% > %part1_build_dir_listing_0044%_disassembled.asm + +nasm %part1_build_dir_listing_0044%_disassembled.asm + +fc /B %part1_build_dir_listing_0044% %part1_build_dir_listing_0044%_disassembled || exit /b 1 +fc /N %part1_build_dir_listing_0044%.txt %part1_build_dir_listing_0044%_disassembled.txt || exit /b 1 + +REM ================================================================================================ +set listing_0045=listing_0045_challenge_register_movs +set part1_build_dir_listing_0045=%part1_build_dir%\%listing_0045% + +copy /Y %part1_dir%\%listing_0045% %part1_build_dir% 1>NUL +copy /Y %part1_dir%\%listing_0045%.txt %part1_build_dir% 1>NUL + +%part1_build_dir%\sim8086.exe --exec %part1_build_dir_listing_0045% > %part1_build_dir_listing_0045%_disassembled.txt +%part1_build_dir%\sim8086.exe %part1_build_dir_listing_0045% > %part1_build_dir_listing_0045%_disassembled.asm + +nasm %part1_build_dir_listing_0045%_disassembled.asm + +fc /B %part1_build_dir_listing_0045% %part1_build_dir_listing_0045%_disassembled || exit /b 1 +fc /N %part1_build_dir_listing_0045%.txt %part1_build_dir_listing_0045%_disassembled.txt || exit /b 1 + +REM ================================================================================================ +set listing_0046=listing_0046_add_sub_cmp +set part1_build_dir_listing_0046=%part1_build_dir%\%listing_0046% + +copy /Y %part1_dir%\%listing_0046% %part1_build_dir% 1>NUL +copy /Y %part1_dir%\%listing_0046%.txt %part1_build_dir% 1>NUL + +%part1_build_dir%\sim8086.exe --exec %part1_build_dir_listing_0046% > %part1_build_dir_listing_0046%_disassembled.txt +%part1_build_dir%\sim8086.exe %part1_build_dir_listing_0046% > %part1_build_dir_listing_0046%_disassembled.asm + +nasm %part1_build_dir_listing_0046%_disassembled.asm + +fc /B %part1_build_dir_listing_0046% %part1_build_dir_listing_0046%_disassembled || exit /b 1 +fc /N %part1_build_dir_listing_0046%.txt %part1_build_dir_listing_0046%_disassembled.txt || exit /b 1 + +REM ================================================================================================ +set listing_0047=listing_0047_challenge_flags +set part1_build_dir_listing_0047=%part1_build_dir%\%listing_0047% + +copy /Y %part1_dir%\%listing_0047% %part1_build_dir% 1>NUL +copy /Y %part1_dir%\%listing_0047%.txt %part1_build_dir% 1>NUL + +%part1_build_dir%\sim8086.exe --exec %part1_build_dir_listing_0047% > %part1_build_dir_listing_0047%_disassembled.txt +%part1_build_dir%\sim8086.exe %part1_build_dir_listing_0047% > %part1_build_dir_listing_0047%_disassembled.asm + +nasm %part1_build_dir_listing_0047%_disassembled.asm + +fc /B %part1_build_dir_listing_0047% %part1_build_dir_listing_0047%_disassembled || exit /b 1 +fc /N %part1_build_dir_listing_0047%.txt %part1_build_dir_listing_0047%_disassembled.txt || exit /b 1 + +REM ================================================================================================ +set listing_0048=listing_0048_ip_register +set part1_build_dir_listing_0048=%part1_build_dir%\%listing_0048% + +copy /Y %part1_dir%\%listing_0048% %part1_build_dir% 1>NUL +copy /Y %part1_dir%\%listing_0048%.txt %part1_build_dir% 1>NUL + +%part1_build_dir%\sim8086.exe --exec --log-instruction-ptr %part1_build_dir_listing_0048% > %part1_build_dir_listing_0048%_disassembled.txt +%part1_build_dir%\sim8086.exe %part1_build_dir_listing_0048% > %part1_build_dir_listing_0048%_disassembled.asm + +nasm %part1_build_dir_listing_0048%_disassembled.asm + +fc /B %part1_build_dir_listing_0048% %part1_build_dir_listing_0048%_disassembled || exit /b 1 +fc /N %part1_build_dir_listing_0048%.txt %part1_build_dir_listing_0048%_disassembled.txt || exit /b 1 + +REM ================================================================================================ +set listing_0049=listing_0049_conditional_jumps +set part1_build_dir_listing_0049=%part1_build_dir%\%listing_0049% + +copy /Y %part1_dir%\%listing_0049% %part1_build_dir% 1>NUL +copy /Y %part1_dir%\%listing_0049%.txt %part1_build_dir% 1>NUL + +%part1_build_dir%\sim8086.exe --exec --log-instruction-ptr %part1_build_dir_listing_0049% > %part1_build_dir_listing_0049%_disassembled.txt +%part1_build_dir%\sim8086.exe %part1_build_dir_listing_0049% > %part1_build_dir_listing_0049%_disassembled.asm + +nasm %part1_build_dir_listing_0049%_disassembled.asm + +fc /B %part1_build_dir_listing_0049% %part1_build_dir_listing_0049%_disassembled || exit /b 1 +fc /N %part1_build_dir_listing_0049%.txt %part1_build_dir_listing_0049%_disassembled.txt || exit /b 1 + +REM ================================================================================================ +set listing_0050=listing_0050_challenge_jumps +set part1_build_dir_listing_0050=%part1_build_dir%\%listing_0050% + +copy /Y %part1_dir%\%listing_0050% %part1_build_dir% 1>NUL +copy /Y %part1_dir%\%listing_0050%.txt %part1_build_dir% 1>NUL + +%part1_build_dir%\sim8086.exe --exec --log-instruction-ptr %part1_build_dir_listing_0050% > %part1_build_dir_listing_0050%_disassembled.txt +%part1_build_dir%\sim8086.exe %part1_build_dir_listing_0050% > %part1_build_dir_listing_0050%_disassembled.asm + +nasm %part1_build_dir_listing_0050%_disassembled.asm + +fc /B %part1_build_dir_listing_0050% %part1_build_dir_listing_0050%_disassembled || exit /b 1 +fc /N %part1_build_dir_listing_0050%.txt %part1_build_dir_listing_0050%_disassembled.txt || exit /b 1 + +REM ================================================================================================ +set listing_0051=listing_0051_memory_mov +set part1_build_dir_listing_0051=%part1_build_dir%\%listing_0051% + +copy /Y %part1_dir%\%listing_0051% %part1_build_dir% 1>NUL +copy /Y %part1_dir%\%listing_0051%.txt %part1_build_dir% 1>NUL + +%part1_build_dir%\sim8086.exe --exec --log-instruction-ptr %part1_build_dir_listing_0051% > %part1_build_dir_listing_0051%_disassembled.txt +%part1_build_dir%\sim8086.exe %part1_build_dir_listing_0051% > %part1_build_dir_listing_0051%_disassembled.asm + +nasm %part1_build_dir_listing_0051%_disassembled.asm + +fc /B %part1_build_dir_listing_0051% %part1_build_dir_listing_0051%_disassembled || exit /b 1 +fc /N %part1_build_dir_listing_0051%.txt %part1_build_dir_listing_0051%_disassembled.txt || exit /b 1 + +REM ================================================================================================ +set listing_0052=listing_0052_memory_add_loop +set part1_build_dir_listing_0052=%part1_build_dir%\%listing_0052% + +copy /Y %part1_dir%\%listing_0052% %part1_build_dir% 1>NUL +copy /Y %part1_dir%\%listing_0052%.txt %part1_build_dir% 1>NUL + +%part1_build_dir%\sim8086.exe --exec --log-instruction-ptr %part1_build_dir_listing_0052% > %part1_build_dir_listing_0052%_disassembled.txt +%part1_build_dir%\sim8086.exe %part1_build_dir_listing_0052% > %part1_build_dir_listing_0052%_disassembled.asm + +nasm %part1_build_dir_listing_0052%_disassembled.asm + +fc /B %part1_build_dir_listing_0052% %part1_build_dir_listing_0052%_disassembled || exit /b 1 +fc /N %part1_build_dir_listing_0052%.txt %part1_build_dir_listing_0052%_disassembled.txt || exit /b 1 + +REM ================================================================================================ +set listing_0053=listing_0053_add_loop_challenge +set part1_build_dir_listing_0053=%part1_build_dir%\%listing_0053% + +copy /Y %part1_dir%\%listing_0053% %part1_build_dir% 1>NUL +copy /Y %part1_dir%\%listing_0053%.txt %part1_build_dir% 1>NUL + +%part1_build_dir%\sim8086.exe --exec --log-instruction-ptr %part1_build_dir_listing_0053% > %part1_build_dir_listing_0053%_disassembled.txt +%part1_build_dir%\sim8086.exe %part1_build_dir_listing_0053% > %part1_build_dir_listing_0053%_disassembled.asm + +nasm %part1_build_dir_listing_0053%_disassembled.asm + +fc /B %part1_build_dir_listing_0053% %part1_build_dir_listing_0053%_disassembled || exit /b 1 +fc /N %part1_build_dir_listing_0053%.txt %part1_build_dir_listing_0053%_disassembled.txt || exit /b 1 + +REM ================================================================================================ +set listing_0054=listing_0054_draw_rectangle +set part1_build_dir_listing_0054=%part1_build_dir%\%listing_0054% + +copy /Y %part1_dir%\%listing_0054% %part1_build_dir% 1>NUL +copy /Y %part1_dir%\%listing_0054%.txt %part1_build_dir% 1>NUL + +pushd %part1_build_dir% +%part1_build_dir%\sim8086.exe --exec --log-instruction-ptr --dump %part1_build_dir_listing_0054% > %part1_build_dir_listing_0054%_disassembled.txt +%part1_build_dir%\sim8086.exe %part1_build_dir_listing_0054% > %part1_build_dir_listing_0054%_disassembled.asm +popd + +nasm %part1_build_dir_listing_0054%_disassembled.asm + +fc /B %part1_build_dir_listing_0054% %part1_build_dir_listing_0054%_disassembled || exit /b 1 +fc /N %part1_build_dir_listing_0054%.txt %part1_build_dir_listing_0054%_disassembled.txt || exit /b 1 + +REM ================================================================================================ +set listing_0055=listing_0055_challenge_rectangle +set part1_build_dir_listing_0055=%part1_build_dir%\%listing_0055% + +copy /Y %part1_dir%\%listing_0055% %part1_build_dir% 1>NUL +copy /Y %part1_dir%\%listing_0055%.txt %part1_build_dir% 1>NUL + +pushd %part1_build_dir% +%part1_build_dir%\sim8086.exe --exec --log-instruction-ptr --dump %part1_build_dir_listing_0055% > %part1_build_dir_listing_0055%_disassembled.txt +%part1_build_dir%\sim8086.exe %part1_build_dir_listing_0055% > %part1_build_dir_listing_0055%_disassembled.asm +popd + +nasm %part1_build_dir_listing_0055%_disassembled.asm + +fc /B %part1_build_dir_listing_0055% %part1_build_dir_listing_0055%_disassembled || exit /b 1 +fc /N %part1_build_dir_listing_0055%.txt %part1_build_dir_listing_0055%_disassembled.txt || exit /b 1 + +REM ================================================================================================ +set listing_0056=listing_0056_estimating_cycles +set part1_build_dir_listing_0056=%part1_build_dir%\%listing_0056% + +copy /Y %part1_dir%\%listing_0056% %part1_build_dir% 1>NUL +copy /Y %part1_dir%\%listing_0056%.txt %part1_build_dir% 1>NUL + +pushd %part1_build_dir% +%part1_build_dir%\sim8086.exe --exec --log-instruction-ptr --log-cycle-counts 8086 %part1_build_dir_listing_0056% > %part1_build_dir_listing_0056%_disassembled.txt +%part1_build_dir%\sim8086.exe %part1_build_dir_listing_0056% > %part1_build_dir_listing_0056%_disassembled.asm +%part1_build_dir%\sim8086.exe --exec --log-instruction-ptr --log-cycle-counts 8088 %part1_build_dir_listing_0056% >> %part1_build_dir_listing_0056%_disassembled.txt +popd + +nasm %part1_build_dir_listing_0056%_disassembled.asm + +fc /B %part1_build_dir_listing_0056% %part1_build_dir_listing_0056%_disassembled || exit /b 1 +fc /N %part1_build_dir_listing_0056%.txt %part1_build_dir_listing_0056%_disassembled.txt || exit /b 1 + +REM ================================================================================================ +set listing_0057=listing_0057_challenge_cycles +set part1_build_dir_listing_0057=%part1_build_dir%\%listing_0057% + +copy /Y %part1_dir%\%listing_0057% %part1_build_dir% 1>NUL +copy /Y %part1_dir%\%listing_0057%.txt %part1_build_dir% 1>NUL + +pushd %part1_build_dir% +%part1_build_dir%\sim8086.exe --exec --log-instruction-ptr --log-cycle-counts 8086 %part1_build_dir_listing_0057% > %part1_build_dir_listing_0057%_disassembled.txt +%part1_build_dir%\sim8086.exe %part1_build_dir_listing_0057% > %part1_build_dir_listing_0057%_disassembled.asm +%part1_build_dir%\sim8086.exe --exec --log-instruction-ptr --log-cycle-counts 8088 %part1_build_dir_listing_0057% >> %part1_build_dir_listing_0057%_disassembled.txt +popd + +nasm %part1_build_dir_listing_0057%_disassembled.asm + +fc /B %part1_build_dir_listing_0057% %part1_build_dir_listing_0057%_disassembled || exit /b 1 +fc /N %part1_build_dir_listing_0057%.txt %part1_build_dir_listing_0057%_disassembled.txt || exit /b 1 + +REM Part 2 ========================================================================================= +REM Build ========================================================================================== +:part2 +pushd %part2_build_dir% +cl %part2_dir%\main.c /W4 /WX /Z7 /nologo || exit /b 1 +popd diff --git a/part1/build.bat b/part1/build.bat deleted file mode 100644 index 897e461..0000000 --- a/part1/build.bat +++ /dev/null @@ -1,307 +0,0 @@ -@echo off - -REM Setup ========================================================================================== -set script_dir_backslash=%~dp0 -set script_dir=%script_dir_backslash:~0,-1% -set build_dir=%script_dir%\Build -if not exist %build_dir% mkdir %build_dir% - -REM Build ========================================================================================== -pushd %build_dir% -cl %script_dir%\sim8086.c /W4 /WX /Z7 /nologo || exit /b 1 -popd - -REM Tests ========================================================================================== -set listing_0037=listing_0037_single_register_mov -set build_dir_listing_0037=%build_dir%\%listing_0037% - -copy /Y %script_dir%\%listing_0037% %build_dir% 1>NUL - -%build_dir%\sim8086.exe %build_dir_listing_0037% > %build_dir_listing_0037%_disassembled.asm -nasm %build_dir_listing_0037%_disassembled.asm -fc /B %build_dir_listing_0037% %build_dir_listing_0037%_disassembled || exit /b 1 - -REM ================================================================================================ -set listing_0038=listing_0038_many_register_mov -set build_dir_listing_0038=%build_dir%\%listing_0038% - -copy /Y %script_dir%\%listing_0038% %build_dir% 1>NUL - -%build_dir%\sim8086.exe %build_dir_listing_0038% > %build_dir_listing_0038%_disassembled.asm -nasm %build_dir_listing_0038%_disassembled.asm -fc /B %build_dir_listing_0038% %build_dir_listing_0038%_disassembled || exit /b 1 - -REM ================================================================================================ -set listing_0039=listing_0039_more_movs -set build_dir_listing_0039=%build_dir%\%listing_0039% - -copy /Y %script_dir%\%listing_0039% %build_dir% 1>NUL - -%build_dir%\sim8086.exe %build_dir_listing_0039% > %build_dir_listing_0039%_disassembled.asm -nasm %build_dir_listing_0039%_disassembled.asm -fc /B %build_dir_listing_0039% %build_dir_listing_0039%_disassembled || exit /b 1 - -REM ================================================================================================ -set listing_0040=listing_0040_challenge_movs -set build_dir_listing_0040=%build_dir%\%listing_0040% - -copy /Y %script_dir%\%listing_0040% %build_dir% 1>NUL - -%build_dir%\sim8086.exe %build_dir_listing_0040% > %build_dir_listing_0040%_disassembled.asm -nasm %build_dir_listing_0040%_disassembled.asm -fc /B %build_dir_listing_0040% %build_dir_listing_0040%_disassembled || exit /b 1 - -REM ================================================================================================ -set listing_0041=listing_0041_add_sub_cmp_jnz -set build_dir_listing_0041=%build_dir%\%listing_0041% - -copy /Y %script_dir%\%listing_0041% %build_dir% 1>NUL - -%build_dir%\sim8086.exe %build_dir_listing_0041% > %build_dir_listing_0041%_disassembled.asm -nasm %build_dir_listing_0041%_disassembled.asm -fc /B %build_dir_listing_0041% %build_dir_listing_0041%_disassembled || exit /b 1 - -REM ================================================================================================ -set listing_0042=listing_0042_completionist_decode -set build_dir_listing_0042=%build_dir%\%listing_0042% - -copy /Y %script_dir%\%listing_0042% %build_dir% 1>NUL - -%build_dir%\sim8086.exe %build_dir_listing_0042% > %build_dir_listing_0042%_disassembled.asm -nasm %build_dir_listing_0042%_disassembled.asm -fc /B %build_dir_listing_0042% %build_dir_listing_0042%_disassembled || exit /b 1 - -REM ================================================================================================ -set listing_0043=listing_0043_immediate_movs -set build_dir_listing_0043=%build_dir%\%listing_0043% - -copy /Y %script_dir%\%listing_0043% %build_dir% 1>NUL -copy /Y %script_dir%\%listing_0043%.txt %build_dir% 1>NUL - -%build_dir%\sim8086.exe %build_dir_listing_0043% > %build_dir_listing_0043%_disassembled.asm -%build_dir%\sim8086.exe --exec %build_dir_listing_0043% > %build_dir_listing_0043%_disassembled.txt - -nasm %build_dir_listing_0043%_disassembled.asm - -fc /B %build_dir_listing_0043% %build_dir_listing_0043%_disassembled || exit /b 1 -fc /N %build_dir_listing_0043%.txt %build_dir_listing_0043%_disassembled.txt || exit /b 1 - -REM ================================================================================================ -set listing_0044=listing_0044_register_movs -set build_dir_listing_0044=%build_dir%\%listing_0044% - -copy /Y %script_dir%\%listing_0044% %build_dir% 1>NUL -copy /Y %script_dir%\%listing_0044%.txt %build_dir% 1>NUL - -%build_dir%\sim8086.exe --exec %build_dir_listing_0044% > %build_dir_listing_0044%_disassembled.txt -%build_dir%\sim8086.exe %build_dir_listing_0044% > %build_dir_listing_0044%_disassembled.asm - -nasm %build_dir_listing_0044%_disassembled.asm - -fc /B %build_dir_listing_0044% %build_dir_listing_0044%_disassembled || exit /b 1 -fc /N %build_dir_listing_0044%.txt %build_dir_listing_0044%_disassembled.txt || exit /b 1 - -REM ================================================================================================ -set listing_0045=listing_0045_challenge_register_movs -set build_dir_listing_0045=%build_dir%\%listing_0045% - -copy /Y %script_dir%\%listing_0045% %build_dir% 1>NUL -copy /Y %script_dir%\%listing_0045%.txt %build_dir% 1>NUL - -%build_dir%\sim8086.exe --exec %build_dir_listing_0045% > %build_dir_listing_0045%_disassembled.txt -%build_dir%\sim8086.exe %build_dir_listing_0045% > %build_dir_listing_0045%_disassembled.asm - -nasm %build_dir_listing_0045%_disassembled.asm - -fc /B %build_dir_listing_0045% %build_dir_listing_0045%_disassembled || exit /b 1 -fc /N %build_dir_listing_0045%.txt %build_dir_listing_0045%_disassembled.txt || exit /b 1 - -REM ================================================================================================ -set listing_0046=listing_0046_add_sub_cmp -set build_dir_listing_0046=%build_dir%\%listing_0046% - -copy /Y %script_dir%\%listing_0046% %build_dir% 1>NUL -copy /Y %script_dir%\%listing_0046%.txt %build_dir% 1>NUL - -%build_dir%\sim8086.exe --exec %build_dir_listing_0046% > %build_dir_listing_0046%_disassembled.txt -%build_dir%\sim8086.exe %build_dir_listing_0046% > %build_dir_listing_0046%_disassembled.asm - -nasm %build_dir_listing_0046%_disassembled.asm - -fc /B %build_dir_listing_0046% %build_dir_listing_0046%_disassembled || exit /b 1 -fc /N %build_dir_listing_0046%.txt %build_dir_listing_0046%_disassembled.txt || exit /b 1 - -REM ================================================================================================ -set listing_0047=listing_0047_challenge_flags -set build_dir_listing_0047=%build_dir%\%listing_0047% - -copy /Y %script_dir%\%listing_0047% %build_dir% 1>NUL -copy /Y %script_dir%\%listing_0047%.txt %build_dir% 1>NUL - -%build_dir%\sim8086.exe --exec %build_dir_listing_0047% > %build_dir_listing_0047%_disassembled.txt -%build_dir%\sim8086.exe %build_dir_listing_0047% > %build_dir_listing_0047%_disassembled.asm - -nasm %build_dir_listing_0047%_disassembled.asm - -fc /B %build_dir_listing_0047% %build_dir_listing_0047%_disassembled || exit /b 1 -fc /N %build_dir_listing_0047%.txt %build_dir_listing_0047%_disassembled.txt || exit /b 1 - -REM ================================================================================================ -set listing_0048=listing_0048_ip_register -set build_dir_listing_0048=%build_dir%\%listing_0048% - -copy /Y %script_dir%\%listing_0048% %build_dir% 1>NUL -copy /Y %script_dir%\%listing_0048%.txt %build_dir% 1>NUL - -%build_dir%\sim8086.exe --exec --log-instruction-ptr %build_dir_listing_0048% > %build_dir_listing_0048%_disassembled.txt -%build_dir%\sim8086.exe %build_dir_listing_0048% > %build_dir_listing_0048%_disassembled.asm - -nasm %build_dir_listing_0048%_disassembled.asm - -fc /B %build_dir_listing_0048% %build_dir_listing_0048%_disassembled || exit /b 1 -fc /N %build_dir_listing_0048%.txt %build_dir_listing_0048%_disassembled.txt || exit /b 1 - -REM ================================================================================================ -set listing_0049=listing_0049_conditional_jumps -set build_dir_listing_0049=%build_dir%\%listing_0049% - -copy /Y %script_dir%\%listing_0049% %build_dir% 1>NUL -copy /Y %script_dir%\%listing_0049%.txt %build_dir% 1>NUL - -%build_dir%\sim8086.exe --exec --log-instruction-ptr %build_dir_listing_0049% > %build_dir_listing_0049%_disassembled.txt -%build_dir%\sim8086.exe %build_dir_listing_0049% > %build_dir_listing_0049%_disassembled.asm - -nasm %build_dir_listing_0049%_disassembled.asm - -fc /B %build_dir_listing_0049% %build_dir_listing_0049%_disassembled || exit /b 1 -fc /N %build_dir_listing_0049%.txt %build_dir_listing_0049%_disassembled.txt || exit /b 1 - -REM ================================================================================================ -set listing_0050=listing_0050_challenge_jumps -set build_dir_listing_0050=%build_dir%\%listing_0050% - -copy /Y %script_dir%\%listing_0050% %build_dir% 1>NUL -copy /Y %script_dir%\%listing_0050%.txt %build_dir% 1>NUL - -%build_dir%\sim8086.exe --exec --log-instruction-ptr %build_dir_listing_0050% > %build_dir_listing_0050%_disassembled.txt -%build_dir%\sim8086.exe %build_dir_listing_0050% > %build_dir_listing_0050%_disassembled.asm - -nasm %build_dir_listing_0050%_disassembled.asm - -fc /B %build_dir_listing_0050% %build_dir_listing_0050%_disassembled || exit /b 1 -fc /N %build_dir_listing_0050%.txt %build_dir_listing_0050%_disassembled.txt || exit /b 1 - -REM ================================================================================================ -set listing_0051=listing_0051_memory_mov -set build_dir_listing_0051=%build_dir%\%listing_0051% - -copy /Y %script_dir%\%listing_0051% %build_dir% 1>NUL -copy /Y %script_dir%\%listing_0051%.txt %build_dir% 1>NUL - -%build_dir%\sim8086.exe --exec --log-instruction-ptr %build_dir_listing_0051% > %build_dir_listing_0051%_disassembled.txt -%build_dir%\sim8086.exe %build_dir_listing_0051% > %build_dir_listing_0051%_disassembled.asm - -nasm %build_dir_listing_0051%_disassembled.asm - -fc /B %build_dir_listing_0051% %build_dir_listing_0051%_disassembled || exit /b 1 -fc /N %build_dir_listing_0051%.txt %build_dir_listing_0051%_disassembled.txt || exit /b 1 - -REM ================================================================================================ -set listing_0052=listing_0052_memory_add_loop -set build_dir_listing_0052=%build_dir%\%listing_0052% - -copy /Y %script_dir%\%listing_0052% %build_dir% 1>NUL -copy /Y %script_dir%\%listing_0052%.txt %build_dir% 1>NUL - -%build_dir%\sim8086.exe --exec --log-instruction-ptr %build_dir_listing_0052% > %build_dir_listing_0052%_disassembled.txt -%build_dir%\sim8086.exe %build_dir_listing_0052% > %build_dir_listing_0052%_disassembled.asm - -nasm %build_dir_listing_0052%_disassembled.asm - -fc /B %build_dir_listing_0052% %build_dir_listing_0052%_disassembled || exit /b 1 -fc /N %build_dir_listing_0052%.txt %build_dir_listing_0052%_disassembled.txt || exit /b 1 - -REM ================================================================================================ -set listing_0053=listing_0053_add_loop_challenge -set build_dir_listing_0053=%build_dir%\%listing_0053% - -copy /Y %script_dir%\%listing_0053% %build_dir% 1>NUL -copy /Y %script_dir%\%listing_0053%.txt %build_dir% 1>NUL - -%build_dir%\sim8086.exe --exec --log-instruction-ptr %build_dir_listing_0053% > %build_dir_listing_0053%_disassembled.txt -%build_dir%\sim8086.exe %build_dir_listing_0053% > %build_dir_listing_0053%_disassembled.asm - -nasm %build_dir_listing_0053%_disassembled.asm - -fc /B %build_dir_listing_0053% %build_dir_listing_0053%_disassembled || exit /b 1 -fc /N %build_dir_listing_0053%.txt %build_dir_listing_0053%_disassembled.txt || exit /b 1 - -REM ================================================================================================ -set listing_0054=listing_0054_draw_rectangle -set build_dir_listing_0054=%build_dir%\%listing_0054% - -copy /Y %script_dir%\%listing_0054% %build_dir% 1>NUL -copy /Y %script_dir%\%listing_0054%.txt %build_dir% 1>NUL - -pushd %build_dir% -%build_dir%\sim8086.exe --exec --log-instruction-ptr --dump %build_dir_listing_0054% > %build_dir_listing_0054%_disassembled.txt -%build_dir%\sim8086.exe %build_dir_listing_0054% > %build_dir_listing_0054%_disassembled.asm -popd - -nasm %build_dir_listing_0054%_disassembled.asm - -fc /B %build_dir_listing_0054% %build_dir_listing_0054%_disassembled || exit /b 1 -fc /N %build_dir_listing_0054%.txt %build_dir_listing_0054%_disassembled.txt || exit /b 1 - -REM ================================================================================================ -set listing_0055=listing_0055_challenge_rectangle -set build_dir_listing_0055=%build_dir%\%listing_0055% - -copy /Y %script_dir%\%listing_0055% %build_dir% 1>NUL -copy /Y %script_dir%\%listing_0055%.txt %build_dir% 1>NUL - -pushd %build_dir% -%build_dir%\sim8086.exe --exec --log-instruction-ptr --dump %build_dir_listing_0055% > %build_dir_listing_0055%_disassembled.txt -%build_dir%\sim8086.exe %build_dir_listing_0055% > %build_dir_listing_0055%_disassembled.asm -popd - -nasm %build_dir_listing_0055%_disassembled.asm - -fc /B %build_dir_listing_0055% %build_dir_listing_0055%_disassembled || exit /b 1 -fc /N %build_dir_listing_0055%.txt %build_dir_listing_0055%_disassembled.txt || exit /b 1 - -REM ================================================================================================ -set listing_0056=listing_0056_estimating_cycles -set build_dir_listing_0056=%build_dir%\%listing_0056% - -copy /Y %script_dir%\%listing_0056% %build_dir% 1>NUL -copy /Y %script_dir%\%listing_0056%.txt %build_dir% 1>NUL - -pushd %build_dir% -%build_dir%\sim8086.exe --exec --log-instruction-ptr --log-cycle-counts 8086 %build_dir_listing_0056% > %build_dir_listing_0056%_disassembled.txt -%build_dir%\sim8086.exe %build_dir_listing_0056% > %build_dir_listing_0056%_disassembled.asm -%build_dir%\sim8086.exe --exec --log-instruction-ptr --log-cycle-counts 8088 %build_dir_listing_0056% >> %build_dir_listing_0056%_disassembled.txt -popd - -nasm %build_dir_listing_0056%_disassembled.asm - -fc /B %build_dir_listing_0056% %build_dir_listing_0056%_disassembled || exit /b 1 -fc /N %build_dir_listing_0056%.txt %build_dir_listing_0056%_disassembled.txt || exit /b 1 - -REM ================================================================================================ -set listing_0057=listing_0057_challenge_cycles -set build_dir_listing_0057=%build_dir%\%listing_0057% - -copy /Y %script_dir%\%listing_0057% %build_dir% 1>NUL -copy /Y %script_dir%\%listing_0057%.txt %build_dir% 1>NUL - -pushd %build_dir% -%build_dir%\sim8086.exe --exec --log-instruction-ptr --log-cycle-counts 8086 %build_dir_listing_0057% > %build_dir_listing_0057%_disassembled.txt -%build_dir%\sim8086.exe %build_dir_listing_0057% > %build_dir_listing_0057%_disassembled.asm -%build_dir%\sim8086.exe --exec --log-instruction-ptr --log-cycle-counts 8088 %build_dir_listing_0057% >> %build_dir_listing_0057%_disassembled.txt -popd - -nasm %build_dir_listing_0057%_disassembled.asm - -fc /B %build_dir_listing_0057% %build_dir_listing_0057%_disassembled || exit /b 1 -fc /N %build_dir_listing_0057%.txt %build_dir_listing_0057%_disassembled.txt || exit /b 1 diff --git a/part2/listing_0065_haversine_formula.cpp b/part2/listing_0065_haversine_formula.cpp new file mode 100644 index 0000000..680c88f --- /dev/null +++ b/part2/listing_0065_haversine_formula.cpp @@ -0,0 +1,53 @@ +/* ======================================================================== + + (C) Copyright 2023 by Molly Rocket, Inc., All Rights Reserved. + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Please see https://computerenhance.com for more information + + ======================================================================== */ + +/* ======================================================================== + LISTING 65 + ======================================================================== */ + +static f64 Square(f64 A) +{ + f64 Result = (A*A); + return Result; +} + +static f64 RadiansFromDegrees(f64 Degrees) +{ + f64 Result = 0.01745329251994329577 * Degrees; + return Result; +} + +// NOTE(casey): EarthRadius is generally expected to be 6372.8 +static f64 ReferenceHaversine(f64 X0, f64 Y0, f64 X1, f64 Y1, f64 EarthRadius) +{ + /* NOTE(casey): This is not meant to be a "good" way to calculate the Haversine distance. + Instead, it attempts to follow, as closely as possible, the formula used in the real-world + question on which these homework exercises are loosely based. + */ + + f64 lat1 = Y0; + f64 lat2 = Y1; + f64 lon1 = X0; + f64 lon2 = X1; + + f64 dLat = RadiansFromDegrees(lat2 - lat1); + f64 dLon = RadiansFromDegrees(lon2 - lon1); + lat1 = RadiansFromDegrees(lat1); + lat2 = RadiansFromDegrees(lat2); + + f64 a = Square(sin(dLat/2.0)) + cos(lat1)*cos(lat2)*Square(sin(dLon/2)); + f64 c = 2.0*asin(sqrt(a)); + + f64 Result = EarthRadius * c; + + return Result; +} diff --git a/part2/listing_0066_haversine_generator.cpp b/part2/listing_0066_haversine_generator.cpp new file mode 100644 index 0000000..fd3da1b --- /dev/null +++ b/part2/listing_0066_haversine_generator.cpp @@ -0,0 +1,220 @@ +/* ======================================================================== + + (C) Copyright 2023 by Molly Rocket, Inc., All Rights Reserved. + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Please see https://computerenhance.com for more information + + ======================================================================== */ + +/* ======================================================================== + LISTING 66 + ======================================================================== */ + +/* NOTE(casey): _CRT_SECURE_NO_WARNINGS is here because otherwise we cannot + call fopen(). If we replace fopen() with fopen_s() to avoid the warning, + then the code doesn't compile on Linux anymore, since fopen_s() does not + exist there. + + What exactly the CRT maintainers were thinking when they made this choice, + I have no idea. */ +#define _CRT_SECURE_NO_WARNINGS + +#include +#include +#include +#include +#include + +typedef uint32_t u32; +typedef uint64_t u64; +typedef double f64; +#define U64Max UINT64_MAX + +#include "listing_0065_haversine_formula.cpp" + +struct random_series +{ + u64 A, B, C, D; +}; + +static u64 RotateLeft(u64 V, int Shift) +{ + u64 Result = ((V << Shift) | (V >> (64-Shift))); + return Result; +} + +static u64 RandomU64(random_series *Series) +{ + u64 A = Series->A; + u64 B = Series->B; + u64 C = Series->C; + u64 D = Series->D; + + u64 E = A - RotateLeft(B, 27); + + A = (B ^ RotateLeft(C, 17)); + B = (C + D); + C = (D + E); + D = (E + A); + + Series->A = A; + Series->B = B; + Series->C = C; + Series->D = D; + + return D; +} + +static random_series Seed(u64 Value) +{ + random_series Series = {}; + + // NOTE(casey): This is the seed pattern for JSF generators, as per the original post + Series.A = 0xf1ea5eed; + Series.B = Value; + Series.C = Value; + Series.D = Value; + + u32 Count = 20; + while(Count--) + { + RandomU64(&Series); + } + + return Series; +} + +static f64 RandomInRange(random_series *Series, f64 Min, f64 Max) +{ + f64 t = (f64)RandomU64(Series) / (f64)U64Max; + f64 Result = (1.0 - t)*Min + t*Max; + + return Result; +} + +static FILE *Open(long long unsigned PairCount, char *Label, char *Extension) +{ + char Temp[256]; + sprintf(Temp, "data_%llu_%s.%s", PairCount, Label, Extension); + FILE *Result = fopen(Temp, "wb"); + if(!Result) + { + fprintf(stderr, "Unable to open \"%s\" for writing.\n", Temp); + } + + return Result; +} + +static f64 RandomDegree(random_series *Series, f64 Center, f64 Radius, f64 MaxAllowed) +{ + f64 MinVal = Center - Radius; + if(MinVal < -MaxAllowed) + { + MinVal = -MaxAllowed; + } + + f64 MaxVal = Center + Radius; + if(MaxVal > MaxAllowed) + { + MaxVal = MaxAllowed; + } + + f64 Result = RandomInRange(Series, MinVal, MaxVal); + return Result; +} + +int main(int ArgCount, char **Args) +{ + if(ArgCount == 4) + { + u64 ClusterCountLeft = U64Max; + f64 MaxAllowedX = 180; + f64 MaxAllowedY = 90; + + f64 XCenter = 0; + f64 YCenter = 0; + f64 XRadius = MaxAllowedX; + f64 YRadius = MaxAllowedY; + + char *MethodName = Args[1]; + if(strcmp(MethodName, "cluster") == 0) + { + ClusterCountLeft = 0; + } + else if(strcmp(MethodName, "uniform") != 0) + { + MethodName = "uniform"; + fprintf(stderr, "WARNING: Unrecognized method name. Using 'uniform'.\n"); + } + + u64 SeedValue = atoll(Args[2]); + random_series Series = Seed(SeedValue); + + u64 MaxPairCount = (1ULL << 34); + u64 PairCount = atoll(Args[3]); + if(PairCount < MaxPairCount) + { + u64 ClusterCountMax = 1 + (PairCount / 64); + + FILE *FlexJSON = Open(PairCount, "flex", "json"); + FILE *HaverAnswers = Open(PairCount, "haveranswer", "f64"); + if(FlexJSON && HaverAnswers) + { + fprintf(FlexJSON, "{\"pairs\":[\n"); + f64 Sum = 0; + f64 SumCoef = 1.0 / (f64)PairCount; + for(u64 PairIndex = 0; PairIndex < PairCount; ++PairIndex) + { + if(ClusterCountLeft-- == 0) + { + ClusterCountLeft = ClusterCountMax; + XCenter = RandomInRange(&Series, -MaxAllowedX, MaxAllowedX); + YCenter = RandomInRange(&Series, -MaxAllowedY, MaxAllowedY); + XRadius = RandomInRange(&Series, 0, MaxAllowedX); + YRadius = RandomInRange(&Series, 0, MaxAllowedY); + } + + f64 X0 = RandomDegree(&Series, XCenter, XRadius, MaxAllowedX); + f64 Y0 = RandomDegree(&Series, YCenter, YRadius, MaxAllowedY); + f64 X1 = RandomDegree(&Series, XCenter, XRadius, MaxAllowedX); + f64 Y1 = RandomDegree(&Series, YCenter, YRadius, MaxAllowedY); + + f64 EarthRadius = 6372.8; + f64 HaversineDistance = ReferenceHaversine(X0, Y0, X1, Y1, EarthRadius); + + Sum += SumCoef*HaversineDistance; + + char *JSONSep = (PairIndex == (PairCount - 1)) ? "\n" : ",\n"; + fprintf(FlexJSON, " {\"x0\":%.16f, \"y0\":%.16f, \"x1\":%.16f, \"y1\":%.16f}%s", X0, Y0, X1, Y1, JSONSep); + + fwrite(&HaversineDistance, sizeof(HaversineDistance), 1, HaverAnswers); + } + fprintf(FlexJSON, "]}\n"); + fwrite(&Sum, sizeof(Sum), 1, HaverAnswers); + + fprintf(stdout, "Method: %s\n", MethodName); + fprintf(stdout, "Random seed: %llu\n", SeedValue); + fprintf(stdout, "Pair count: %llu\n", PairCount); + fprintf(stdout, "Expected sum: %.16f\n", Sum); + } + + if(FlexJSON) fclose(FlexJSON); + if(HaverAnswers) fclose(HaverAnswers); + } + else + { + fprintf(stderr, "To avoid accidentally generating massive files, number of pairs must be less than %llu.\n", MaxPairCount); + } + } + else + { + fprintf(stderr, "Usage: %s [uniform/cluster] [random seed] [number of coordinate pairs to generate]\n", Args[0]); + } + + return 0; +} + \ No newline at end of file diff --git a/part2/listing_0067_simple_haversine.cpp b/part2/listing_0067_simple_haversine.cpp new file mode 100644 index 0000000..73fd61d --- /dev/null +++ b/part2/listing_0067_simple_haversine.cpp @@ -0,0 +1,165 @@ +/* ======================================================================== + + (C) Copyright 2023 by Molly Rocket, Inc., All Rights Reserved. + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Please see https://computerenhance.com for more information + + ======================================================================== */ + +/* ======================================================================== + LISTING 67 + ======================================================================== */ + +/* NOTE(casey): _CRT_SECURE_NO_WARNINGS is here because otherwise we cannot + call fopen(). If we replace fopen() with fopen_s() to avoid the warning, + then the code doesn't compile on Linux anymore, since fopen_s() does not + exist there. + + What exactly the CRT maintainers were thinking when they made this choice, + I have no idea. */ +#define _CRT_SECURE_NO_WARNINGS + +#include +#include +#include +#include +#include + +typedef uint8_t u8; +typedef uint32_t u32; +typedef uint64_t u64; + +typedef int32_t b32; + +typedef float f32; +typedef double f64; + +struct haversine_pair +{ + f64 X0, Y0; + f64 X1, Y1; +}; + +#include "listing_0065_haversine_formula.cpp" +#include "listing_0068_buffer.cpp" +#include "listing_0069_lookup_json_parser.cpp" + +static buffer ReadEntireFile(char *FileName) +{ + buffer Result = {}; + + FILE *File = fopen(FileName, "rb"); + if(File) + { +#if _WIN32 + struct __stat64 Stat; + _stat64(FileName, &Stat); +#else + struct stat Stat; + stat(FileName, &Stat); +#endif + + Result = AllocateBuffer(Stat.st_size); + if(Result.Data) + { + if(fread(Result.Data, Result.Count, 1, File) != 1) + { + fprintf(stderr, "ERROR: Unable to read \"%s\".\n", FileName); + FreeBuffer(&Result); + } + } + } + else + { + fprintf(stderr, "ERROR: Unable to open \"%s\".\n", FileName); + } + + return Result; +} + +static f64 SumHaversineDistances(u64 PairCount, haversine_pair *Pairs) +{ + f64 Sum = 0; + + f64 SumCoef = 1 / (f64)PairCount; + for(u64 PairIndex = 0; PairIndex < PairCount; ++PairIndex) + { + haversine_pair Pair = Pairs[PairIndex]; + f64 EarthRadius = 6372.8; + f64 Dist = ReferenceHaversine(Pair.X0, Pair.Y0, Pair.X1, Pair.Y1, EarthRadius); + Sum += SumCoef*Dist; + } + + return Sum; +} + +int main(int ArgCount, char **Args) +{ + int Result = 1; + + if((ArgCount == 2) || (ArgCount == 3)) + { + buffer InputJSON = ReadEntireFile(Args[1]); + + u32 MinimumJSONPairEncoding = 6*4; + u64 MaxPairCount = InputJSON.Count / MinimumJSONPairEncoding; + if(MaxPairCount) + { + buffer ParsedValues = AllocateBuffer(MaxPairCount * sizeof(haversine_pair)); + if(ParsedValues.Count) + { + haversine_pair *Pairs = (haversine_pair *)ParsedValues.Data; + u64 PairCount = ParseHaversinePairs(InputJSON, MaxPairCount, Pairs); + f64 Sum = SumHaversineDistances(PairCount, Pairs); + + fprintf(stdout, "Input size: %llu\n", InputJSON.Count); + fprintf(stdout, "Pair count: %llu\n", PairCount); + fprintf(stdout, "Haversine sum: %.16f\n", Sum); + + if(ArgCount == 3) + { + buffer AnswersF64 = ReadEntireFile(Args[2]); + if(AnswersF64.Count >= sizeof(f64)) + { + f64 *AnswerValues = (f64 *)AnswersF64.Data; + + fprintf(stdout, "\nValidation:\n"); + + u64 RefAnswerCount = (AnswersF64.Count - sizeof(f64)) / sizeof(f64); + if(PairCount != RefAnswerCount) + { + fprintf(stdout, "FAILED - pair count doesn't match %llu.\n", RefAnswerCount); + } + + f64 RefSum = AnswerValues[RefAnswerCount]; + fprintf(stdout, "Reference sum: %.16f\n", RefSum); + fprintf(stdout, "Difference: %.16f\n", Sum - RefSum); + + fprintf(stdout, "\n"); + } + } + } + + FreeBuffer(&ParsedValues); + } + else + { + fprintf(stderr, "ERROR: Malformed input JSON\n"); + } + + FreeBuffer(&InputJSON); + + Result = 0; + } + else + { + fprintf(stderr, "Usage: %s [haversine_input.json]\n", Args[0]); + fprintf(stderr, " %s [haversine_input.json] [answers.f64]\n", Args[0]); + } + + return Result; +} diff --git a/part2/listing_0068_buffer.cpp b/part2/listing_0068_buffer.cpp new file mode 100644 index 0000000..93f99fa --- /dev/null +++ b/part2/listing_0068_buffer.cpp @@ -0,0 +1,72 @@ +/* ======================================================================== + + (C) Copyright 2023 by Molly Rocket, Inc., All Rights Reserved. + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Please see https://computerenhance.com for more information + + ======================================================================== */ + +/* ======================================================================== + LISTING 68 + ======================================================================== */ + +struct buffer +{ + size_t Count; + u8 *Data; +}; + +#define CONSTANT_STRING(String) {sizeof(String) - 1, (u8 *)(String)} + +static b32 IsInBounds(buffer Source, u64 At) +{ + b32 Result = (At < Source.Count); + return Result; +} + +static b32 AreEqual(buffer A, buffer B) +{ + if(A.Count != B.Count) + { + return false; + } + + for(u64 Index = 0; Index < A.Count; ++Index) + { + if(A.Data[Index] != B.Data[Index]) + { + return false; + } + } + + return true; +} + +static buffer AllocateBuffer(size_t Count) +{ + buffer Result = {}; + Result.Data = (u8 *)malloc(Count); + if(Result.Data) + { + Result.Count = Count; + } + else + { + fprintf(stderr, "ERROR: Unable to allocate %llu bytes.\n", Count); + } + + return Result; +} + +static void FreeBuffer(buffer *Buffer) +{ + if(Buffer->Data) + { + free(Buffer->Data); + } + *Buffer = {}; +} \ No newline at end of file diff --git a/part2/listing_0069_lookup_json_parser.cpp b/part2/listing_0069_lookup_json_parser.cpp new file mode 100644 index 0000000..87c9ef2 --- /dev/null +++ b/part2/listing_0069_lookup_json_parser.cpp @@ -0,0 +1,508 @@ +/* ======================================================================== + + (C) Copyright 2023 by Molly Rocket, Inc., All Rights Reserved. + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Please see https://computerenhance.com for more information + + ======================================================================== */ + +/* ======================================================================== + LISTING 69 + ======================================================================== */ + +enum json_token_type +{ + Token_end_of_stream, + Token_error, + + Token_open_brace, + Token_open_bracket, + Token_close_brace, + Token_close_bracket, + Token_comma, + Token_colon, + Token_semi_colon, + Token_string_literal, + Token_number, + Token_true, + Token_false, + Token_null, + + Token_count, +}; + +struct json_token +{ + json_token_type Type; + buffer Value; +}; + +struct json_element +{ + buffer Label; + buffer Value; + json_element *FirstSubElement; + + json_element *NextSibling; +}; + +struct json_parser +{ + buffer Source; + u64 At; + b32 HadError; +}; + +static b32 IsJSONDigit(buffer Source, u64 At) +{ + b32 Result = false; + if(IsInBounds(Source, At)) + { + u8 Val = Source.Data[At]; + Result = ((Val >= '0') && (Val <= '9')); + } + + return Result; +} + +static b32 IsJSONWhitespace(buffer Source, u64 At) +{ + b32 Result = false; + if(IsInBounds(Source, At)) + { + u8 Val = Source.Data[At]; + Result = ((Val == ' ') || (Val == '\t') || (Val == '\n') || (Val == '\r')); + } + + return Result; +} + +static b32 IsParsing(json_parser *Parser) +{ + b32 Result = !Parser->HadError && IsInBounds(Parser->Source, Parser->At); + return Result; +} + +static void Error(json_parser *Parser, json_token Token, char const *Message) +{ + Parser->HadError = true; + fprintf(stderr, "ERROR: \"%.*s\" - %s\n", (u32)Token.Value.Count, (char *)Token.Value.Data, Message); +} + +static void ParseKeyword(buffer Source, u64 *At, buffer KeywordRemaining, json_token_type Type, json_token *Result) +{ + if((Source.Count - *At) >= KeywordRemaining.Count) + { + buffer Check = Source; + Check.Data += *At; + Check.Count = KeywordRemaining.Count; + if(AreEqual(Check, KeywordRemaining)) + { + Result->Type = Type; + Result->Value.Count += KeywordRemaining.Count; + *At += KeywordRemaining.Count; + } + } +} + +static json_token GetJSONToken(json_parser *Parser) +{ + json_token Result = {}; + + buffer Source = Parser->Source; + u64 At = Parser->At; + + while(IsJSONWhitespace(Source, At)) + { + ++At; + } + + if(IsInBounds(Source, At)) + { + Result.Type = Token_error; + Result.Value.Count = 1; + Result.Value.Data = Source.Data + At; + u8 Val = Source.Data[At++]; + switch(Val) + { + case '{': {Result.Type = Token_open_brace;} break; + case '[': {Result.Type = Token_open_bracket;} break; + case '}': {Result.Type = Token_close_brace;} break; + case ']': {Result.Type = Token_close_bracket;} break; + case ',': {Result.Type = Token_comma;} break; + case ':': {Result.Type = Token_colon;} break; + case ';': {Result.Type = Token_semi_colon;} break; + + case 'f': + { + ParseKeyword(Source, &At, CONSTANT_STRING("alse"), Token_false, &Result); + } break; + + case 'n': + { + ParseKeyword(Source, &At, CONSTANT_STRING("ull"), Token_null, &Result); + } break; + + case 't': + { + ParseKeyword(Source, &At, CONSTANT_STRING("rue"), Token_true, &Result); + } break; + + case '"': + { + Result.Type = Token_string_literal; + + u64 StringStart = At; + + while(IsInBounds(Source, At) && (Source.Data[At] != '"')) + { + if(IsInBounds(Source, (At + 1)) && + (Source.Data[At] == '\\') && + (Source.Data[At + 1] == '"')) + { + // NOTE(casey): Skip escaped quotation marks + ++At; + } + + ++At; + } + + Result.Value.Data = Source.Data + StringStart; + Result.Value.Count = At - StringStart; + if(IsInBounds(Source, At)) + { + ++At; + } + } break; + + case '-': + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + { + u64 Start = At - 1; + Result.Type = Token_number; + + // NOTE(casey): Move past a leading negative sign if one exists + if((Val == '-') && IsInBounds(Source, At)) + { + Val = Source.Data[At++]; + } + + // NOTE(casey): If the leading digit wasn't 0, parse any digits before the decimal point + if(Val != '0') + { + while(IsJSONDigit(Source, At)) + { + ++At; + } + } + + // NOTE(casey): If there is a decimal point, parse any digits after the decimal point + if(IsInBounds(Source, At) && (Source.Data[At] == '.')) + { + ++At; + while(IsJSONDigit(Source, At)) + { + ++At; + } + } + + // NOTE(casey): If it's in scientific notation, parse any digits after the "e" + if(IsInBounds(Source, At) && ((Source.Data[At] == 'e') || (Source.Data[At] == 'E'))) + { + ++At; + + if(IsInBounds(Source, At) && ((Source.Data[At] == '+') || (Source.Data[At] == '-'))) + { + ++At; + } + + while(IsJSONDigit(Source, At)) + { + ++At; + } + } + + Result.Value.Count = At - Start; + } break; + + default: + { + } break; + } + } + + Parser->At = At; + + return Result; +} + +static json_element *ParseJSONList(json_parser *Parser, json_token StartingToken, json_token_type EndType, b32 HasLabels); +static json_element *ParseJSONElement(json_parser *Parser, buffer Label, json_token Value) +{ + b32 Valid = true; + + json_element *SubElement = 0; + if(Value.Type == Token_open_bracket) + { + SubElement = ParseJSONList(Parser, Value, Token_close_bracket, false); + } + else if(Value.Type == Token_open_brace) + { + SubElement = ParseJSONList(Parser, Value, Token_close_brace, true); + } + else if((Value.Type == Token_string_literal) || + (Value.Type == Token_true) || + (Value.Type == Token_false) || + (Value.Type == Token_null) || + (Value.Type == Token_number)) + { + // NOTE(casey): Nothing to do here, since there is no additional data + } + else + { + Valid = false; + } + + json_element *Result = 0; + + if(Valid) + { + Result = (json_element *)malloc(sizeof(json_element)); + Result->Label = Label; + Result->Value = Value.Value; + Result->FirstSubElement = SubElement; + Result->NextSibling = 0; + } + + return Result; +} + +static json_element *ParseJSONList(json_parser *Parser, json_token StartingToken, json_token_type EndType, b32 HasLabels) +{ + json_element *FirstElement = {}; + json_element *LastElement = {}; + + while(IsParsing(Parser)) + { + buffer Label = {}; + json_token Value = GetJSONToken(Parser); + if(HasLabels) + { + if(Value.Type == Token_string_literal) + { + Label = Value.Value; + + json_token Colon = GetJSONToken(Parser); + if(Colon.Type == Token_colon) + { + Value = GetJSONToken(Parser); + } + else + { + Error(Parser, Colon, "Expected colon after field name"); + } + } + else if(Value.Type != EndType) + { + Error(Parser, Value, "Unexpected token in JSON"); + } + } + + json_element *Element = ParseJSONElement(Parser, Label, Value); + if(Element) + { + LastElement = (LastElement ? LastElement->NextSibling : FirstElement) = Element; + } + else if(Value.Type == EndType) + { + break; + } + else + { + Error(Parser, Value, "Unexpected token in JSON"); + } + + json_token Comma = GetJSONToken(Parser); + if(Comma.Type == EndType) + { + break; + } + else if(Comma.Type != Token_comma) + { + Error(Parser, Comma, "Unexpected token in JSON"); + } + } + + return FirstElement; +} + +static json_element *ParseJSON(buffer InputJSON) +{ + json_parser Parser = {}; + Parser.Source = InputJSON; + + json_element *Result = ParseJSONElement(&Parser, {}, GetJSONToken(&Parser)); + return Result; +} + +static void FreeJSON(json_element *Element) +{ + while(Element) + { + json_element *FreeElement = Element; + Element = Element->NextSibling; + + FreeJSON(FreeElement->FirstSubElement); + free(FreeElement); + } +} + +static json_element *LookupElement(json_element *Object, buffer ElementName) +{ + json_element *Result = 0; + + if(Object) + { + for(json_element *Search = Object->FirstSubElement; Search; Search = Search->NextSibling) + { + if(AreEqual(Search->Label, ElementName)) + { + Result = Search; + break; + } + } + } + + return Result; +} + +static f64 ConvertJSONSign(buffer Source, u64 *AtResult) +{ + u64 At = *AtResult; + + f64 Result = 1.0; + if(IsInBounds(Source, At) && (Source.Data[At] == '-')) + { + Result = -1.0; + ++At; + } + + *AtResult = At; + + return Result; +} + +static f64 ConvertJSONNumber(buffer Source, u64 *AtResult) +{ + u64 At = *AtResult; + + f64 Result = 0.0; + while(IsInBounds(Source, At)) + { + u8 Char = Source.Data[At] - (u8)'0'; + if(Char < 10) + { + Result = 10.0*Result + (f64)Char; + ++At; + } + else + { + break; + } + } + + *AtResult = At; + + return Result; +} + +static f64 ConvertElementToF64(json_element *Object, buffer ElementName) +{ + f64 Result = 0.0; + + json_element *Element = LookupElement(Object, ElementName); + if(Element) + { + buffer Source = Element->Value; + u64 At = 0; + + f64 Sign = ConvertJSONSign(Source, &At); + f64 Number = ConvertJSONNumber(Source, &At); + + if(IsInBounds(Source, At) && (Source.Data[At] == '.')) + { + ++At; + f64 C = 1.0 / 10.0; + while(IsInBounds(Source, At)) + { + u8 Char = Source.Data[At] - (u8)'0'; + if(Char < 10) + { + Number = Number + C*(f64)Char; + C *= 1.0 / 10.0; + ++At; + } + else + { + break; + } + } + } + + if(IsInBounds(Source, At) && ((Source.Data[At] == 'e') || (Source.Data[At] == 'E'))) + { + ++At; + if(IsInBounds(Source, At) && (Source.Data[At] == '+')) + { + ++At; + } + + f64 ExponentSign = ConvertJSONSign(Source, &At); + f64 Exponent = ExponentSign*ConvertJSONNumber(Source, &At); + Number *= pow(10.0, Exponent); + } + + Result = Sign*Number; + } + + return Result; +} + +static u64 ParseHaversinePairs(buffer InputJSON, u64 MaxPairCount, haversine_pair *Pairs) +{ + u64 PairCount = 0; + + json_element *JSON = ParseJSON(InputJSON); + json_element *PairsArray = LookupElement(JSON, CONSTANT_STRING("pairs")); + if(PairsArray) + { + for(json_element *Element = PairsArray->FirstSubElement; + Element && (PairCount < MaxPairCount); + Element = Element->NextSibling) + { + haversine_pair *Pair = Pairs + PairCount++; + + Pair->X0 = ConvertElementToF64(Element, CONSTANT_STRING("x0")); + Pair->Y0 = ConvertElementToF64(Element, CONSTANT_STRING("y0")); + Pair->X1 = ConvertElementToF64(Element, CONSTANT_STRING("x1")); + Pair->Y1 = ConvertElementToF64(Element, CONSTANT_STRING("y1")); + } + } + + FreeJSON(JSON); + + return PairCount; +} diff --git a/part2/main.c b/part2/main.c new file mode 100644 index 0000000..d5afed4 --- /dev/null +++ b/part2/main.c @@ -0,0 +1,55 @@ + +#include +#include +#include +#include +#include "pap2_stdlib.h" +#include "pap2_stdlib.c" +#include + +typedef double f64; + +static f64 Square(f64 A) +{ + f64 Result = (A*A); + return Result; +} + +static f64 RadiansFromDegrees(f64 Degrees) +{ + f64 Result = 0.01745329251994329577 * Degrees; + return Result; +} + +// NOTE(casey): EarthRadius is generally expected to be 6372.8 +static f64 ReferenceHaversine(f64 X0, f64 Y0, f64 X1, f64 Y1, f64 EarthRadius) +{ + /* NOTE(casey): This is not meant to be a "good" way to calculate the Haversine distance. + Instead, it attempts to follow, as closely as possible, the formula used in the real-world + question on which these homework exercises are loosely based. + */ + + f64 lat1 = Y0; + f64 lat2 = Y1; + f64 lon1 = X0; + f64 lon2 = X1; + + f64 dLat = RadiansFromDegrees(lat2 - lat1); + f64 dLon = RadiansFromDegrees(lon2 - lon1); + lat1 = RadiansFromDegrees(lat1); + lat2 = RadiansFromDegrees(lat2); + + f64 a = Square(sin(dLat/2.0)) + cos(lat1)*cos(lat2)*Square(sin(dLon/2)); + f64 c = 2.0*asin(sqrt(a)); + + f64 Result = EarthRadius * c; + + return Result; +} + +int main(int argc, char **argv) +{ + (void)argc; + (void)argv; + return 0; +} diff --git a/part2/pap2_stdlib.c b/part2/pap2_stdlib.c new file mode 100644 index 0000000..d3bc66f --- /dev/null +++ b/part2/pap2_stdlib.c @@ -0,0 +1,217 @@ +// NOTE: Implementation +// ============================================================================ +bool S86_Str8_Equals(S86_Str8 lhs, S86_Str8 rhs) +{ + bool result = lhs.size == rhs.size && memcmp(lhs.data, rhs.data, lhs.size) == 0; + return result; +} + +bool S86_BufferIsValid(S86_Buffer buffer) +{ + bool result = buffer.data && buffer.size; + return result; +} + +S86_BufferIterator S86_BufferIteratorInit(S86_Buffer buffer) +{ + S86_BufferIterator result = {0}; + result.buffer = buffer; + return result; +} + +bool S86_BufferIteratorHasMoreBytes(S86_BufferIterator it) +{ + bool result = S86_BufferIsValid(it.buffer) && it.index < it.buffer.size; + return result; +} + +uint8_t S86_BufferIteratorPeekByte(S86_BufferIterator *it) +{ + S86_ASSERT(it); + S86_ASSERT(S86_BufferIsValid(it->buffer)); + S86_ASSERT(it->index < it->buffer.size); + uint8_t result = it->buffer.data[it->index]; + return result; +} + +uint8_t S86_BufferIteratorNextByte(S86_BufferIterator *it) +{ + uint8_t result = S86_BufferIteratorPeekByte(it); + it->index++; + return result; +} + +S86_Buffer S86_FileRead(char const *file_path) +{ + S86_Buffer result = {0}; + + // NOTE: Determine file size + // ========================================================================= + WIN32_FILE_ATTRIBUTE_DATA file_attrib_data = {0}; + if (GetFileAttributesEx(file_path, GetFileExInfoStandard, &file_attrib_data) == 0) + return result; + + // NOTE: Open file + // ========================================================================= + HANDLE file_handle = CreateFile( + /*LPCSTR lpFileName*/ file_path, + /*DWORD dwDesiredAccess*/ GENERIC_READ, + /*DWORD dwShareMode*/ 0, + /*LPSECURITY_ATTRIBUTES lpSecurityAttributes*/ NULL, + /*DWORD dwCreationDisposition*/ OPEN_EXISTING, + /*DWORD dwFlagsAndAttributes*/ 0, + /*HANDLE hTemplateFile*/ NULL + ); + + if (file_handle == INVALID_HANDLE_VALUE) + return result; + + // NOTE: Allocate buffer + // ========================================================================= + uint64_t file_size = (uint64_t)file_attrib_data.nFileSizeHigh << 32 | (uint64_t)file_attrib_data.nFileSizeLow << 0; + S86_ASSERT(file_size < (DWORD)-1); + char *buffer = VirtualAlloc( + /*LPVOID lpAddress*/ NULL, + /*SIZE_T dwSize*/ file_size, + /*DWORD flAllocationType*/ MEM_COMMIT | MEM_RESERVE, + /*DWORD flProtect*/ PAGE_READWRITE + ); + + if (!buffer) + goto end; + + // NOTE: Read file to buffer + // ========================================================================= + DWORD bytes_read = 0; + BOOL read_file_result = ReadFile( + /*HANDLE hFile*/ file_handle, + /*LPVOID lpBuffer*/ buffer, + /*DWORD nNumberOfBytesToRead*/ S86_CAST(DWORD)file_size, + /*LPDWORD lpNumberOfBytesRead*/ &bytes_read, + /*LPOVERLAPPED lpOverlapped*/ NULL + ); + + // NOTE: Handle read result + // ========================================================================= + if (read_file_result == 0) { + VirtualFree(buffer, 0, MEM_RELEASE); + } else { + result.data = buffer; + result.size = file_size; + } + +end: + CloseHandle(file_handle); + return result; +}; + +void S86_FileFree(S86_Buffer buffer) +{ + if (S86_BufferIsValid(buffer)) + VirtualFree(buffer.data, 0, MEM_RELEASE); +} + +bool S86_FileWrite(char const *file_path, void const *buffer, size_t buffer_size) +{ + bool result = false; + + // NOTE: Open file + // ========================================================================= + HANDLE file_handle = CreateFile( + /*LPCSTR lpFileName*/ file_path, + /*DWORD dwDesiredAccess*/ GENERIC_WRITE, + /*DWORD dwShareMode*/ 0, + /*LPSECURITY_ATTRIBUTES lpSecurityAttributes*/ NULL, + /*DWORD dwCreationDisposition*/ CREATE_ALWAYS, + /*DWORD dwFlagsAndAttributes*/ 0, + /*HANDLE hTemplateFile*/ NULL + ); + + if (file_handle == INVALID_HANDLE_VALUE) + return result; + + // NOTE: Write file to disk + // ========================================================================= + DWORD bytes_written = 0; + BOOL write_file_result = WriteFile( + /*HANDLE hFile*/ file_handle, + /*LPVOID lpBuffer*/ buffer, + /*DWORD nNumberOfBytesToWrite*/ S86_CAST(DWORD)buffer_size, + /*LPDWORD lpNumberOfBytesWrite*/ &bytes_written, + /*LPOVERLAPPED lpOverlapped*/ NULL + ); + + S86_ASSERT(bytes_written == buffer_size); + result = write_file_result && bytes_written == buffer_size; + CloseHandle(file_handle); + return result; +}; + +void S86_Print(S86_Str8 string) +{ + if (s86_globals.stdout_handle == NULL) { + s86_globals.stdout_handle = GetStdHandle(STD_OUTPUT_HANDLE); + DWORD mode = 0; + BOOL get_console_mode_result = GetConsoleMode( + /*HANDLE hConsoleHandle*/ s86_globals.stdout_handle, + /*LPDWORD lpMode*/ &mode + ); + s86_globals.write_to_console = get_console_mode_result != 0; + } + + + S86_ASSERT(string.size < S86_CAST(DWORD)-1); + if (s86_globals.write_to_console) { + DWORD chars_written = 0; + WriteConsoleA(s86_globals.stdout_handle, string.data, (DWORD)string.size, &chars_written, NULL); + } else { + DWORD bytes_written = 0; + WriteFile(s86_globals.stdout_handle, string.data, (DWORD)string.size, &bytes_written, NULL); + } +} + +void S86_PrintFmt(char const *fmt, ...) +{ + va_list args, args_copy; + va_start(args, fmt); + + va_copy(args_copy, args); + int string_size = vsnprintf(NULL, 0, fmt, args_copy); + va_end(args_copy); + + char buffer[8192]; + S86_ASSERT(string_size >= 0 && string_size < S86_ARRAY_UCOUNT(buffer)); + if (string_size) { + vsnprintf(buffer, sizeof(buffer), fmt, args); + S86_Str8 string = {.data = buffer, .size = string_size}; + S86_Print(string); + } + + va_end(args); +} + +void S86_PrintLn(S86_Str8 string) +{ + S86_Print(string); + S86_Print(S86_STR8("\n")); +} + +void S86_PrintLnFmt(char const *fmt, ...) +{ + va_list args, args_copy; + va_start(args, fmt); + + va_copy(args_copy, args); + int string_size = vsnprintf(NULL, 0, fmt, args_copy); + va_end(args_copy); + + char buffer[8192]; + S86_ASSERT(string_size >= 0 && string_size < S86_ARRAY_UCOUNT(buffer)); + if (string_size) { + vsnprintf(buffer, sizeof(buffer), fmt, args); + S86_Str8 string = {.data = buffer, .size = string_size}; + S86_PrintLn(string); + } + + va_end(args); +} diff --git a/part2/pap2_stdlib.h b/part2/pap2_stdlib.h new file mode 100644 index 0000000..6c88eed --- /dev/null +++ b/part2/pap2_stdlib.h @@ -0,0 +1,61 @@ +// NOTE: Macros +// ============================================================================ +#define S86_STRINGIFY2(token) #token +#define S86_STRINGIFY(token) S86_STRINGIFY2(token) +#define S86_ASSERT(expr) \ + if (!(expr)) { \ + S86_PrintLnFmt("Assertion triggered [file=\"" __FILE__ ":" S86_STRINGIFY(__LINE__) "\", expr=\"" #expr "\"]"); \ + __debugbreak(); \ + } \ + +#define S86_ARRAY_UCOUNT(array) sizeof((array)) / sizeof((array)[0]) +#define S86_CAST(Type) (Type) + +// NOTE: Globals +// ============================================================================ +typedef struct S86_Globals { + HANDLE stdout_handle; + bool write_to_console; +} S86_Globals; + +S86_Globals s86_globals; + +// NOTE: Strings +// ============================================================================ +typedef struct S86_Str8 { + char *data; + size_t size; +} S86_Str8; + +#define S86_STR8(string) (S86_Str8){.data = (string), .size = S86_ARRAY_UCOUNT(string) - 1 } +#define S86_STR8_FMT(string) (int)((string).size), (string).data + +bool S86_Str8_Equals(S86_Str8 lhs, S86_Str8 rhs); + +// NOTE: Buffer +// ============================================================================ +typedef struct S86_Buffer { + char *data; + size_t size; +} S86_Buffer; + +typedef struct S86_BufferIterator { + S86_Buffer buffer; + size_t index; +} S86_BufferIterator; + +bool S86_BufferIsValid(S86_Buffer buffer); +S86_BufferIterator S86_BufferIteratorInit(S86_Buffer buffer); +bool S86_BufferIteratorHasMoreBytes(S86_BufferIterator it); +uint8_t S86_BufferIteratorNextByte(S86_BufferIterator *it); + +// NOTE: File +// ============================================================================ +S86_Buffer S86_FileRead(char const *file_path); +void S86_FileFree(S86_Buffer buffer); +bool S86_FileWrite(char const *file_path, void const *buffer, size_t buffer_size); + +// NOTE: Print +// ============================================================================ +void S86_PrintLn(S86_Str8 string); +void S86_PrintLnFmt(char const *fmt, ...); diff --git a/project.rdbg b/project.rdbg index 9d77ee46d031e4aa068a85ccbee3049fdeb152be..1cac5d5f7db3afc538bcd2576fc89d1a55eb9f90 100644 GIT binary patch delta 94 zcmX@FxIk$`G$SM1<`~9ZjI0bmz&Nqcp2>-AvIujYEE|x|#{KgM2#XZHUkSo>vktwN jE`9QsZL%Pr!shMF&RqOpWgx9!z%{v$&waB$Ujq{W5}O(o delta 81 zcmZ3WbY5{oG$SMH<`~9ZjFaP-b0k?A7#P^Ne;xs0k;3;YLAY+#q4%tl6ZvE&FW_U@ a%*|rY#RpOb!i*rmHTfW)`{o6F4NL$u&==DH