# Copyright 2007-2008 Kevin Reid, under the terms of the MIT X license # found at http://www.opensource.org/licenses/mit-license.html ................ pragma.syntax("0.9") def dataBits :DeepFrozen := 7 def WholeNum :DeepFrozen := (int >= 0) /** http://www.waterken.com/dev/Doc/code/#ExtensionNumber */ # XXX is this the right name? should we call this ExtensionNumber instead? def wholeNumCoding implements DeepFrozen, ExitViaHere { # implements Binary to asType() { return WholeNum } to writingTo(out) { # , schedule # XXX consult stream's byte size return def writeWholeNum(n :WholeNum) { def count := n.bitLength().ceilDivide(dataBits) out.reserve().resolve(__makeList.fromValuesOf(def wnIter { to iterate(f) { var i := count * dataBits while ((i -= dataBits).atLeastZero()) { f(null, ((n >> i) & (2**dataBits-1)) | i.isZero().pick(0, 2**dataBits)) } } })) } } to takingFrom(ins, schedule) { # XXX consult stream's byte size return def takeWholeNum() :(schedule.result(WholeNum)) { # XXX this is O(n^2) in the size of the number; we could do better by buffering the 7-bytes and using an efficient "bignum-from-digit-array" primitive var acc := 0 return schedule.whenResolved( schedule.loop(fn { schedule.whenResolved(EIO.takeRange(1, 1, ins), fn chunk { def [byte] := chunk acc := (acc << dataBits) | (byte & (2**dataBits-1)) (byte & 2**dataBits).aboveZero() # continuation condition }) }), fn _ { acc }) } } }