! Copyright (C) 2006, 2008 Doug Coleman.
! See http://factorcode.org/license.txt for BSD license.
-USING: accessors byte-arrays byte-vectors checksums grouping io
-io.backend io.binary io.encodings.binary io.files kernel make
-math sequences ;
+USING: accessors byte-arrays byte-vectors checksums endian
+grouping kernel make math sequences ;
IN: checksums.common
: calculate-pad-length ( length -- length' )
INSTANCE: block-checksum checksum
-TUPLE: checksum-state
-{ bytes-read integer }
-{ block-size integer }
-{ bytes byte-vector } ;
-
-: new-checksum-state ( class -- checksum-state )
- new
- BV{ } clone >>bytes ; inline
-
-M: checksum-state clone
- call-next-method
- [ clone ] change-bytes ;
-
-GENERIC: initialize-checksum-state ( checksum -- checksum-state )
+TUPLE: block-checksum-state < checksum-state
+ { bytes-read integer }
+ { block-size integer } ;
GENERIC: checksum-block ( bytes checksum-state -- )
-GENERIC: get-checksum ( checksum-state -- value )
+! Update the bytes-read before calculating checksum in case
+! checksum uses this in the calculation.
+M:: block-checksum-state add-checksum-bytes ( state data -- state )
+ state block-size>> :> block-size
+ state bytes>> length :> initial-len
+ initial-len data length + block-size /mod :> ( n extra )
+ data state bytes>> [ push-all ] keep :> all-bytes
+ all-bytes block-size <groups>
+ extra zero? [ f ] [ unclip-last-slice ] if :> ( blocks remain )
-: add-checksum-bytes ( checksum-state data -- checksum-state' )
- [
- over bytes>> [ push-all ] keep
- [ dup length pick block-size>> >= ]
- [
- over block-size>> cut-slice [
- over checksum-block
- [ block-size>> ] keep [ + ] change-bytes-read
- ] dip
- ] while
- >byte-vector >>bytes
- ] keep
- length [ + ] curry change-bytes-read ;
+ state [ initial-len - ] change-bytes-read drop
-: add-checksum-stream ( checksum-state stream -- checksum-state )
- [ [ add-checksum-bytes ] each-block ] with-input-stream ;
+ blocks [
+ state [ block-size + ] change-bytes-read
+ checksum-block
+ ] each
-: add-checksum-file ( checksum-state path -- checksum-state )
- binary <file-reader> add-checksum-stream ;
+ state [ extra + ] change-bytes-read
+ remain [ >byte-vector ] [ BV{ } clone ] if* >>bytes ;
M: block-checksum checksum-bytes
- initialize-checksum-state
- swap add-checksum-bytes get-checksum ;
+ [ swap add-checksum-bytes get-checksum ] with-checksum-state ;
M: block-checksum checksum-stream
- initialize-checksum-state
- swap add-checksum-stream get-checksum ;
+ [ swap add-checksum-stream get-checksum ] with-checksum-state ;