;;;; message-digest-update-item.scm ;;;; Kon Lovett, Jan '06 (message-digest.scm) ;;;; Kon Lovett, May '10 (message-digest.scm) ;;;; Kon Lovett, Apr '12 ;;;; Kon Lovett, Aug '17 ;; Issues (module message-digest-update-item (;export message-digest-update-object message-digest-update-procedure message-digest-update-port message-digest-update-file) (import scheme chicken) (use (only lolevel number-of-bytes pointer?) (only posix file-open file-close open/rdonly directory?) (only miscmacros while*) message-digest-primitive message-digest-type message-digest-chunk message-digest-support type-checks type-errors typed-define) ;;; Support ;; (include "message-digest-types") ;; (define-type converted-chunk (or blob string message-digest-raw-chunk)) ;; ;=> #f or converted-chunk (define: (chunk-convert (obj *)) -> converted-chunk (and-let* ( (cnv (message-digest-chunk-converter)) ) (cnv obj) ) ) (define: (get-port-chunk-reader (port input-port)) -> procedure ((message-digest-chunk-port-read-maker) port) ) (define: (get-fileno-chunk-reader (fd fixnum)) -> procedure ((message-digest-chunk-fileno-read-maker) fd) ) (define: (get-update (md message-digest)) -> procedure (message-digest-primitive-update (message-digest-algorithm md)) ) (define: (get-raw-update (md message-digest)) -> procedure (message-digest-primitive-raw-update (message-digest-algorithm md)) ) ;; (define: (do-object-update (loc symbol) (md message-digest) (src *) (start fixnum) (end (or boolean fixnum))) (cond ((input-port? src) (do-port-update loc md src start end) ) ((procedure? src) (do-procedure-update loc md src start end) ) (else (do-bytes-update loc md src start end) ) ) ) (define: (do-port-update (loc symbol) (md message-digest) (port input-port) (start fixnum) (end (or boolean fixnum))) (do-procedure-update loc md (get-port-chunk-reader port) start end) ) (define: (do-procedure-update (loc symbol) (md message-digest) (proc procedure) (start fixnum) (end (or boolean fixnum))) (let ( (src-updt (get-update md)) (raw-updt (get-raw-update md)) (ctx (message-digest-context md)) ) ;note the 'src' object (return of proc) may or may not be unique (while* (proc) (do-byte-source-update loc ctx it src-updt raw-updt start end) ) ) ) (define: (do-bytes-update (loc symbol) (md message-digest) (src *) (start fixnum) (end (or boolean fixnum))) (do-byte-source-update loc (message-digest-context md) src (get-update md) (get-raw-update md) start end) ) (define: (do-byte-source-update (loc symbol) (ctx *) (src *) (src-updt procedure) (raw-updt procedure) (start fixnum) (end (or boolean fixnum))) (cond ;simple bytes ((blob? src) (let ( (blb (blob/slice src start end)) ) (src-updt ctx blb (blob-size blb)) ) ) ((string? src) (let ( (str (string/slice src start end)) ) (src-updt ctx str (string-length str)) ) ) ((message-digest-raw-chunk? src) (let* ( (obj (message-digest-raw-chunk-object src)) (updator (if (pointer? obj) raw-updt src-updt)) ) (unless updator (error loc "primitive does not support raw-update") ) ;FIXME xtra arg (message-digest-raw-chunk-start src) (updator ctx obj (message-digest-raw-chunk-size src)) ) ) ;more complicated bytes ((object->bytevector-like src) => (cut do-byte-source-update loc ctx <> src-updt raw-updt start end) ) ;too complicated bytes (else (signal-type-error loc "indigestible object" src start end) ) ) ) (define: (object->bytevector-like (obj *)) -> converted-chunk (or (packed-vector->blob/shared obj) (chunk-convert obj)) ) ;;; Update Operation ;; (define: (message-digest-update-object (md message-digest) (obj *) . (opts list)) (let-optionals* opts ( (start 0) (end #f) ) (do-object-update 'message-digest-update-object (check-message-digest 'message-digest-update-object md) obj start end) ) ) ;; (define: (message-digest-update-procedure (md message-digest) (proc procedure)) (do-procedure-update 'message-digest-update-procedure (check-message-digest 'message-digest-update-procedure md) (check-procedure 'message-digest-update-procedure proc) 0 #f) ) ;; (define: (message-digest-update-port (md message-digest) (port input-port)) (do-port-update 'message-digest-update-port (check-message-digest 'message-digest-update-port md) (check-input-port 'message-digest-update-port port) 0 #f) ) ;; (define: (message-digest-update-file (md message-digest) (flnm pathname)) ; (unless (file-exists? (check-string 'message-digest-update-file flnm)) (error 'message-digest-update-file "no such file" flnm) ) ; #; ;can't open a directory? (when (directory? flnm) (error 'message-digest-update-file "file is a directory" flnm) ) ; (if (get-raw-update (check-message-digest 'message-digest-update-file md)) (*message-digest-update-file/fileno 'message-digest-update-file md flnm) (*message-digest-update-file/port 'message-digest-update-file md flnm) ) ) (define: (*message-digest-update-file/fileno (loc symbol) (md message-digest) (flnm pathname)) (let ( (fd (file-open flnm open/rdonly)) ) (handle-exceptions exn (begin (file-close fd) (abort exn) ) (do-procedure-update loc md (get-fileno-chunk-reader fd) 0 #f) ) (file-close fd) ) ) (define: (*message-digest-update-file/port (loc symbol) (md message-digest) (flnm pathname)) (let ( (in (open-input-file flnm)) ) (handle-exceptions exn (begin (close-input-port in) (abort exn) ) (do-port-update loc md in 0 #f) ) (close-input-port in) ) ) #; ;book implementation (define: (message-digest-update-file (md message-digest) (flnm pathname)) (let ((in #f)) (dynamic-wind (lambda () (set! in (open-input-file flnm)) ) (lambda () (do-port-update 'message-digest-update-file md in) ) (lambda () (close-input-port in) ) ) ) ) ) ;module message-digest-update-item