(comptime-define-symbol 'Unix) (set-cakelisp-option cakelisp-src-dir "Dependencies/cakelisp/src") (add-cakelisp-search-directory "test/src" "Dependencies/cakelisp/runtime") (import &comptime-only "Macros.cake") (add-c-search-directory-module "../../src") ;; Building from Dependencies/gamelib (c-import "" "" "" "" "bunzip.h") (add-c-build-dependency "bunzip-4.1.c") ;; LGPLv2 (var g-known-num-puzzles (const int) 2577412) ;; This controls how many should be exported! (var g-num-puzzles-to-read (const int) 50000) (var-global g-bunzip-debug bool false) (def-function-signature-global bunzip-decompress-callback (buffer (* char) num-bytes-this-read int user-data (* void) &return bool)) (defun bunzip-decompress (bz2-file (* (const char)) receive-data-callback bunzip-decompress-callback user-data (* void) &return bool) (var file-descriptor int (open bz2-file O_RDONLY)) (when (= -1 file-descriptor) (printf "Failed to load file %s\n" bz2-file) (return false)) ;; Prints all of it, which is a lot! ;; (unless (= 0 (uncompressStream file-descriptor 1)) ;; (return false)) (var header-data (* bunzip_data) null) (var error-code int 0) (set error-code (start_bunzip (addr header-data) file-descriptor null 0)) ;; Unused: Input buffer (when error-code (printf "Bunzip error %d\n" error-code) (free header-data) (close file-descriptor) (return false)) ;; Add room for null terminator. Not necessary for binary data (var output ([] 4097 char) (array 0)) (var num-bytes-read int 0) (while true (var return-code int (read_bunzip header-data output (- (array-size output) 1))) (when (< return-code RETVAL_LAST_BLOCK) ;; On success, return code = num bytes written (printf "Bunzip error %d\n" return-code) (free header-data) (close file-descriptor) (return false)) (var num-bytes-this-read int 0) (when (> return-code 0) (set num-bytes-this-read return-code) ;; Set null terminator (set (at num-bytes-this-read output) 0) (set num-bytes-read (+ num-bytes-read num-bytes-this-read))) (when receive-data-callback (unless (receive-data-callback output num-bytes-this-read user-data) (free header-data) (close file-descriptor) (return false))) ;; (printf "Output: %d bytes\n%s[end]\n" return-code output) (when (= return-code RETVAL_LAST_BLOCK) (when g-bunzip-debug (printf "Last Output: %s[end]\n" output)) (break))) (when g-bunzip-debug (printf "Output: %d bytes\n" num-bytes-read)) (free header-data) (close file-descriptor) (return true)) (comptime-cond ('Kitty-Main) (true ;; Generate puzzles.txt ;; Note that this doesn't change the distribution of puzzles (var g-puzzle-skip-count (const int) (/ g-known-num-puzzles g-num-puzzles-to-read)) (defstruct-local puzzle-line-buffer buffer (* char) buffer-size int buffer-write (* char) num-puzzles-read int file-out (* FILE)) (defun-local process-puzzle-data (buffer (* char) num-bytes-this-read int user-data (* void) &return bool) (var work-in-progress-line (* puzzle-line-buffer) (type-cast user-data (* puzzle-line-buffer))) (var current-char (* char) buffer) (while (< (- current-char buffer) num-bytes-this-read) (cond ((= '\n' (deref current-char)) ;; Found puzzle delimiter (set (deref (path work-in-progress-line > buffer-write)) 0) ;; Output puzzle (when (= 0 (mod (path work-in-progress-line > num-puzzles-read) g-puzzle-skip-count)) (printf "%s\n" (path work-in-progress-line > buffer)) (when (path work-in-progress-line > file-out) (fprintf (path work-in-progress-line > file-out) "%s\n" (path work-in-progress-line > buffer)))) (set (path work-in-progress-line > buffer-write) (path work-in-progress-line > buffer)) (incr (path work-in-progress-line > num-puzzles-read))) (true ;; Reading a puzzle in (set (deref (path work-in-progress-line > buffer-write)) (deref current-char)) (incr (path work-in-progress-line > buffer-write)) (when (>= (- (path work-in-progress-line > buffer-write) (path work-in-progress-line > buffer)) (- (path work-in-progress-line > buffer-size) 1)) (printf "Error: didn't encounter newline before end of buffer\n") (return false)))) (incr current-char)) (return true)) (defun main (&return int) (var bz2-file (* (const char)) "assets/rush.txt.bz2") (var file-out (* FILE) (fopen "data/puzzles.txt" "w")) (unless file-out (printf "Could not open output file\n") (return 1)) (fprintf file-out "%d\n" g-num-puzzles-to-read) ;; For when the read buffer straddles a single puzzle ;; 46 chars max per puzzle, plus newline, plus room for null terminator for easy printing (var work-in-progress-buffer ([] 48 char) (array 0)) (var work-in-progress-line puzzle-line-buffer (array work-in-progress-buffer (array-size work-in-progress-buffer) work-in-progress-buffer 0 file-out)) (unless (bunzip-decompress bz2-file process-puzzle-data (addr work-in-progress-line)) (fclose file-out) (return 1)) (fclose file-out) (return 0)) (set-cakelisp-option executable-output "../../decompression-test")))