|
|
|
(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 "<stdio.h>" "<stdlib.h>" "<fcntl.h>" "<unistd.h>"
|
|
|
|
"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")))
|