;;;; z3.scm (module z3 (z3:decode-init z3:decode z3:encode-init z3:encode z3:handle? z3:open-compressed-input-file z3:open-compressed-output-file z3:file-handle? z3:file-handle-fileno z3:encode-buffer z3:decode-buffer z3:encode-buffer-to-blob z3:encode-file z3:write-encoded z3:decode-file z3:read-decoded) (import scheme) (import chicken) (import (except foreign foreign-declare)) (require-extension data-structures ports posix bind) #> #include #include "z3blib.c" #include "z3dlib.c" #include "z3flib.c" #define copy_dbuffer(ptr, buf, size) (C_memcpy(C_data_pointer(buf), C_c_pointer_nn(ptr), C_unfix(size)), C_SCHEME_UNDEFINED) #define free_dbuffer(ptr) (C_free(C_c_pointer_nn(ptr)), C_SCHEME_UNDEFINED) <# (bind-rename "z3err_none" "z3:error-none") (bind-rename/pattern "z3err_bd_(.+)" "z3:error-\\1") (bind #< given 0) (receiver (substring (z3:handle-buffer handle) index (+ index given))) ) taken) ((= err z3:error-none) #f) (else (z3:error 'z3:decode err "can not decode data") ) ) ) ) (define (z3:encode-init #!key (buffer (make-string 4096)) (buffer-size (string-length buffer)) (memsize (+ Z3DE_MEMSIZE_MIN 65402 Z3BE_MEMSIZE_EXTRA3)) ;??? (tellwhen Z3DE_SLICE_MIN) (thrmin 77) (thrmax 77) (initialgrant 13) preferlonger) (let ((zbuf (make-string memsize))) (unless (z3d_encode_init zbuf memsize tellwhen thrmin thrmax initialgrant preferlonger #t) (z3:error 'z3:encode-init z3:error-none "initialization failed")) (make-z3:handle zbuf buffer #t) ) ) (define (z3:encode handle receiver data #!optional (datasize (string-length data))) (assert (z3:handle-encode? handle) "not an encoding handle" handle) (let ((cbuf (z3:handle-decoded handle))) (let-values (((r taken given) (z3d_encode (z3:handle-buffer handle) data datasize cbuf (string-length cbuf)))) (when (fx> given 0) (receiver (substring cbuf 0 given)) ) (and r taken) ) ) ) (define strerror (foreign-lambda c-string "strerror" int)) (define -EAGAIN (foreign-value "-EAGAIN" int)) (define-record z3:file-handle z3 fileno) (define (z3:encode-file fd #!key (level 6) (filename #f) (comment #f) (ostype -1) (extra #f)) (define (err r) (error 'z3:encode-file (string-append "can not encode file - " (strerror (fxneg r))) fd) ) (let* ((z3 (make-string (foreign-value "sizeof(struct z3fe_handle)" int))) (xlen (if extra (string-length extra) 0)) (r (z3f_encode_init fd z3 level (current-seconds) ostype xlen extra filename comment)) ) (when (fx< r 0) (err r)) (let loop () (let ((r (z3f_encode_header z3 xlen extra filename comment))) (cond ((eq? -EAGAIN r) (loop)) ((fx< r 0) (err r)) (else (make-z3:file-handle z3 fd) ) ) ) ) ) ) (define (z3:write-encoded z3h data #!optional (len (and data (string-length data)))) (define (err r) (error 'z3:write-encoded (string-append "can not write encoded data - " (strerror (fxneg r)))) ) (let ((z3 (z3:file-handle-z3 z3h))) (if (not data) (let loop () (let ((r (z3f_encode_write z3 #f 0))) (cond ((eq? r -EAGAIN) (loop)) ((eq? r 0)) (else (err r)) ) ) ) (let loop ((len len) (data data) ) (when (fx> len 0) (let ((r (z3f_encode_write z3 data len))) (cond ((eq? r -EAGAIN) (loop len data)) ((fx<= r 0) (err r)) (else (loop (fx- len r) (substring data r))))))) ) ) ) (define (z3:decode-file fd) (let* ((z3 (make-string (foreign-value "sizeof(struct z3fd_handle)" int))) (r (z3f_decode_init fd z3)) ) (if (fx< r 0) (error 'z3:decode-file (string-append "can not decode file - " (strerror (fxneg r)))) (make-z3:file-handle z3 fd) ) ) ) (define-constant +read-block-size+ 4096) (define (z3:read-decoded z3 #!optional (len +read-block-size+)) (let ((buf (make-string len)) (z3 (z3:file-handle-z3 z3)) ) (let loop ((n len)) (let ((r (z3f_decode_read z3 buf n))) (cond ((eq? r -EAGAIN) (loop n)) ((fx< r 0) (error 'z3:read-decoded (string-append "can not read encoded data - " (strerror (fxneg r)))) ) ((eq? r 0) #!eof) ((eq? r n) buf) (else (substring buf 0 r)) ) ) ) ) ) (define (z3:open-compressed-input-file filename) (let* ((fd (file-open filename (bitwise-ior open/read open/binary))) (z3 (z3:decode-file fd)) (eof #f) (buf #f) (len 0) (pos 0) ) (define (read-next) (if eof #!eof (let ((b (z3:read-decoded z3))) (cond ((eof-object? b) (set! eof #t) b) (else (set! buf b) (set! len (string-length b)) ) ) ) ) ) (make-input-port (lambda () (cond ((fx>= pos len) (if (eof-object? (read-next)) #!eof (begin (set! pos 1) (string-ref buf 0) ) ) ) (else (let ((c (string-ref buf pos))) (set! pos (fx+ pos 1)) c) ) ) ) (lambda () (fx< pos len)) (lambda () (file-close fd)) ) ) ) (define (z3:open-compressed-output-file filename #!key (level 6) (comment #f) (astype -1) (extra #f)) (let* ((fd (file-open filename (bitwise-ior open/creat open/binary open/write))) (z3 (z3:encode-file fd level: level comment: comment filename: filename astype: astype extra: extra)) ) (make-output-port (lambda (s) (z3:write-encoded z3 s) ) (lambda () (z3:write-encoded z3 #f) (file-close fd)) ) ) ) (bind* #< dlen) { char *d2 = (char *)realloc(dest, dlen *= 2); if(d2 == NULL) { C_free(d2); return NULL; } else dest = d2; } if(given > 0) C_memcpy(dest + dcount, data, given); dcount += given; } } EOF ) (define (z3:decode-buffer str #!optional (start 0) (end (if (blob? str) (blob-size str) (string-length str)))) (let-values (((ptr err size) (decode_all (z3:handle-buffer (z3:decode-init)) str start end))) (cond ((= err z3:error-none) (if ptr (let ((buf (make-string size))) (##core#inline "copy_dbuffer" ptr buf size) (##core#inline "free_dbuffer" ptr) buf) (error 'z3:decode-buffer "out of memory - can not allocate decompression buffer")) ) (else (z3:error 'z3:decode-buffer err "can not decode data") ) ) ) ) )