Write functions to compute various sizes of Fletcher's checksum.
$ cat fc.scm (use-modules ((rnrs io ports) #:renamer (symbol-prefix-proc 'bio:)) (rnrs bytevectors) (ice-9 match)) (include-from-path "srfi-78/srfi-78.scm")
Return a function accepting a file descriptor and returning the n-byte integer read from the file descriptor, or various status values.
(define (make-reader n) (lambda (f) (let ((bytes (bio:get-bytevector-n f n))) (cond ((eof-object? bytes) '(eof . #f)) ((< (bytevector-length bytes) n) '(err . #f)) (#t (cons 'num (bytevector-uint-ref bytes 0 (endianness big) n))))))) (define reader1 (make-reader 1)) (check (reader1 (bio:open-bytevector-input-port #vu8())) => '(eof . #f)) (let ((f (bio:open-bytevector-input-port #vu8(1)))) (check (reader1 f) => '(num . 1)) (check (reader1 f) => '(eof . #f))) (let ((f (bio:open-bytevector-input-port #vu8(0 1 255)))) (check (reader1 f) => '(num . 0)) (check (reader1 f) => '(num . 1)) (check (reader1 f) => '(num . 255)) (check (reader1 f) => '(eof . #f))) (define reader2 (make-reader 2)) (let ((f (bio:open-bytevector-input-port #vu8(0 1)))) (check (reader2 f) => '(num . 1)) (check (reader2 f) => '(eof . #f))) (let ((f (bio:open-bytevector-input-port #vu8(0 0 0 1 0 255 255 255)))) (check (reader2 f) => '(num . 0)) (check (reader2 f) => '(num . 1)) (check (reader2 f) => '(num . 255)) (check (reader2 f) => '(num . #xffff)) (check (reader2 f) => '(eof . #f))) (define reader4 (make-reader 4)) (let ((f (bio:open-bytevector-input-port #vu8(0 0 0 1)))) (check (reader4 f) => '(num . 1)) (check (reader4 f) => '(eof . #f))) (let ((f (bio:open-bytevector-input-port #vu8(0 0 0 0 0 0 0 1 0 0 0 255 255 255 255 255)))) (check (reader4 f) => '(num . 0)) (check (reader4 f) => '(num . 1)) (check (reader4 f) => '(num . 255)) (check (reader4 f) => '(num . #xffffffff)) (check (reader4 f) => '(eof . #f)))
Return a function accepting a file descriptor f and returning the 2n-byte Fletcher's checksum of the data read from f. The number of bytes read from f should be evenly divisible by n.
(define (make-fcs n) (let* ((reader (make-reader n)) (bits (* n 8)) (little-mask (logxor -1 (ash -1 bits))) (big-mask (logior (ash little-mask bits) little-mask))) (lambda (f) (let loop ((in (reader f)) (cs1 0) (cs2 0)) (match (car in) ('eof (logand (+ (ash cs2 bits) (logand cs1 little-mask)) big-mask)) ('err (error "unexpected eof")) ('num (let ((cs1' (+ cs1 (cdr in)))) (loop (reader f) cs1' (+ cs2 cs1'))))))))) (define fcs1 (make-fcs 1)) (check (fcs1 (bio:open-bytevector-input-port #vu8())) => 0) (check (fcs1 (bio:open-bytevector-input-port #vu8(1))) => #x0101) (check (fcs1 (bio:open-bytevector-input-port #vu8(255 1))) => #x0ff00) (check (fcs1 (bio:open-bytevector-input-port #vu8(1 255))) => #x0100) (define fcs2 (make-fcs 2)) (check (fcs2 (bio:open-bytevector-input-port #vu8())) => 0) (check (fcs2 (bio:open-bytevector-input-port #vu8(0 1))) => #x00010001) (check (fcs2 (bio:open-bytevector-input-port #vu8(0 255 0 1))) => #x01ff0100) (check (fcs2 (bio:open-bytevector-input-port #vu8(0 1 0 255))) => #x01010100) (define fcs4 (make-fcs 4)) (check (fcs4 (bio:open-bytevector-input-port #vu8())) => 0) (check (fcs4 (bio:open-bytevector-input-port #vu8(0 0 0 1))) => #x0000000100000001) (check (fcs4 (bio:open-bytevector-input-port #vu8(0 0 0 255 0 0 0 1))) => #x000001ff00000100) (check (fcs4 (bio:open-bytevector-input-port #vu8(0 0 0 1 0 0 0 255))) => #x000010100000100) $ guile fc.scm (reader1 (bio:open-bytevector-input-port #vu8())) => (eof . #f) ; correct (reader1 f) => (num . 1) ; correct (reader1 f) => (eof . #f) ; correct (reader1 f) => (num . 0) ; correct (reader1 f) => (num . 1) ; correct (reader1 f) => (num . 255) ; correct (reader1 f) => (eof . #f) ; correct (reader2 f) => (num . 1) ; correct (reader2 f) => (eof . #f) ; correct (reader2 f) => (num . 0) ; correct (reader2 f) => (num . 1) ; correct (reader2 f) => (num . 255) ; correct (reader2 f) => (num . 65535) ; correct (reader2 f) => (eof . #f) ; correct (reader4 f) => (num . 1) ; correct (reader4 f) => (eof . #f) ; correct (reader4 f) => (num . 0) ; correct (reader4 f) => (num . 1) ; correct (reader4 f) => (num . 255) ; correct (reader4 f) => (num . 4294967295) ; correct (reader4 f) => (eof . #f) ; correct (fcs1 (bio:open-bytevector-input-port #vu8())) => 0 ; correct (fcs1 (bio:open-bytevector-input-port #vu8(1))) => 257 ; correct (fcs1 (bio:open-bytevector-input-port #vu8(255 1))) => 65280 ; correct (fcs1 (bio:open-bytevector-input-port #vu8(1 255))) => 256 ; correct (fcs2 (bio:open-bytevector-input-port #vu8())) => 0 ; correct (fcs2 (bio:open-bytevector-input-port #vu8(0 1))) => 65537 ; correct (fcs2 (bio:open-bytevector-input-port #vu8(0 255 0 1))) => 33489152 ; correct (fcs2 (bio:open-bytevector-input-port #vu8(0 1 0 255))) => 16843008 ; correct (fcs4 (bio:open-bytevector-input-port #vu8())) => 0 ; correct (fcs4 (bio:open-bytevector-input-port #vu8(0 0 0 1))) => 4294967297 ; correct (fcs4 (bio:open-bytevector-input-port #vu8(0 0 0 255 0 0 0 1))) => 2194728288512 ; correct (fcs4 (bio:open-bytevector-input-port #vu8(0 0 0 1 0 0 0 255))) => 1103806595328 ; correct $