#lang scheme/base
(require
"list.ss"
"seq-tools.ss"
"grabbag.ss"
"binary.ss"
(lib "match.ss"))
(provide (all-defined-out))
(require (lib "78.ss" "srfi"))
(check-set-mode! 'report-failed)
(define (number/false? x)
(and x (number? x)))
(define (binchunk? x)
(fail/false
(and (= 2 (length x))
(number? (car x))
(pair? (cadr x)) (andmap number/false? (cadr x)))))
(define (bin? x)
(fail/false
(andmap binchunk? x)))
(define binchunk-address car)
(define binchunk-code cadr)
(define (binchunk-split chunk left right) (match chunk
((addr things)
`(,(<<< addr 1)
,(split-nibble-list things left right)))))
(check (binchunk-split '(0 (#x0102 #x0304)) 0 8)
=> '(0 (#x02 #x01 #x04 #x03)))
(define (in-binchunk chunk)
(in-parallel
(in-naturals (binchunk-address chunk))
(in-list (binchunk-code chunk))))
(define (in-bin bin)
(apply in-append (map in-binchunk bin)))
(define (bin-flatten dirty-bin)
(let ((bin (filter binchunk? dirty-bin))) (if (null? bin) '()
(let-values
(((sos _)
(for/fold ((sos (make-sos 2))
(expected (binchunk-address (car bin))))
(((address codeword) (in-bin bin)))
(values
(sos-push
(if (= address expected)
sos
(begin
(sos-collapse sos 1)))
(list address codeword))
(+ 1 address)))))
(map address/code->binchunk
(sos->list sos))))))
(define (address/code->binchunk acl)
(list (caar acl)
(map cadr acl)))
(define (in-binchunk/pad-align chunk bits [filler #f])
(in-acor
(lambda (yield end)
(define addr (binchunk-address chunk))
(define endx (+ addr (length (binchunk-code chunk))))
(define _addr (bit-floor addr bits))
(define _endx (bit-ceil endx bits))
(for ((a (in-range _addr addr))) (yield a filler))
(for (((a c) (in-binchunk chunk))) (yield a c))
(for ((a (in-range endx _endx))) (yield a filler)))))
(check (for/list (((a c) (in-binchunk/pad-align '(3 (1 2 3)) 3 #f)))
(list a c))
=> '((0 #f)
(1 #f)
(2 #f)
(3 1)
(4 2)
(5 3)
(6 #f)
(7 #f)))
(define (in-binchunk-sequence/lines seq bits)
(in-acor
(lambda (yield)
(let ((mask (bitmask bits)))
(for/fold ((line '()))
(((a c) seq))
(let ((line+ (cons c line)))
(if (= mask (band a mask))
(begin
(yield (- a mask)
(reverse line+))
'())
line+)))))))
(define (in-binchunk/lines chunk bits [filler #f])
(in-binchunk-sequence/lines
(in-binchunk/pad-align chunk bits filler)
bits))
(define (chunks->list/0 chunks size pad)
(define mem (make-vector size pad))
(define top -1)
(for ((c chunks))
(for (((addr byte) (in-binchunk c)))
(when (< addr size)
(set! top (max top addr))
(vector-set! mem addr byte))))
(for/list ((i (in-range (add1 top)))) (vector-ref mem i)))