perfaware: Setup part2
This commit is contained in:
parent
9db292f616
commit
a4658b1951
2
.gitignore
vendored
2
.gitignore
vendored
@ -1 +1 @@
|
|||||||
*/build
|
Build
|
||||||
|
323
build.bat
Normal file
323
build.bat
Normal file
@ -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
|
307
part1/build.bat
307
part1/build.bat
@ -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
|
|
53
part2/listing_0065_haversine_formula.cpp
Normal file
53
part2/listing_0065_haversine_formula.cpp
Normal file
@ -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;
|
||||||
|
}
|
220
part2/listing_0066_haversine_generator.cpp
Normal file
220
part2/listing_0066_haversine_generator.cpp
Normal file
@ -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 <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <math.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
165
part2/listing_0067_simple_haversine.cpp
Normal file
165
part2/listing_0067_simple_haversine.cpp
Normal file
@ -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 <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <math.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
72
part2/listing_0068_buffer.cpp
Normal file
72
part2/listing_0068_buffer.cpp
Normal file
@ -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 = {};
|
||||||
|
}
|
508
part2/listing_0069_lookup_json_parser.cpp
Normal file
508
part2/listing_0069_lookup_json_parser.cpp
Normal file
@ -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;
|
||||||
|
}
|
55
part2/main.c
Normal file
55
part2/main.c
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <Windows.h>
|
||||||
|
#include "pap2_stdlib.h"
|
||||||
|
#include "pap2_stdlib.c"
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
217
part2/pap2_stdlib.c
Normal file
217
part2/pap2_stdlib.c
Normal file
@ -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);
|
||||||
|
}
|
61
part2/pap2_stdlib.h
Normal file
61
part2/pap2_stdlib.h
Normal file
@ -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, ...);
|
BIN
project.rdbg
BIN
project.rdbg
Binary file not shown.
Loading…
Reference in New Issue
Block a user