goer@ellis.uchicago.edu (Richard L. Goerwitz) (04/04/91)
Perhaps I'm opening a can of worms, like I did with the last such
posting ("terrible code"). Anyway, I just wrote a section of code
for some compression work I'm doing, and I just don't like the
looks of it. Is there a clearer and/or more efficient way of do-
ing this sort of thing in Icon??
-Richard
(what sort of thing I'm talking about will shortly become clear;
behold the code -)
#
# outbits() & inbits()
#
# Pass to outbits(i, len) an integer i, and a length parameter (len),
# and outbits will suspend byte-sized chunks of i converted to
# characters (most significant bits first) until there is not enough
# left of i to fill up an 8-bit character. The remaining portion is
# stored in a buffer until outbits() is called again, at which point
# the buffer is combined with the new i and then output in the same
# manner as before. The buffer is flushed by calling outbits() with
# no i argument.
#
# A trivial example of how outbits() might be used:
#
# outtext := open("some.file.name","w")
# l := [1,2,3,4]
# every writes(outtext, outbits(!l,3))
# writes(outtext, outbits(&null,3)) # flush buffer
#
# List l may be reconstructed with inbits() (see inbits.icn):
#
# intext := open("some.file.name")
# l := []
# while put(l, inbits(intext, 3))
#
# Note that outbits() is a generator, while inbits() is not.
#
procedure outbits(i, len)
local old_part, new_part, window, old_byte_mask
static old_i, old_len, byte_length, byte_mask
initial {
old_i := old_len := 0
byte_length := 8
byte_mask := (2^byte_length)-1
}
old_byte_mask := (0 < 2^old_len - 1) | 0
window := byte_length - old_len
old_part := ishift(iand(old_i, old_byte_mask), window)
# If we have a no-arg invocation, then flush buffer (old_i).
if /i then {
old_i := old_len := 0
return char(old_part)
} else {
new_part := ishift(i, window-len)
len -:= (len >= window) | {
old_len +:= len
old_i := ior(ishift(old_part, len-window), i)
fail
}
suspend char(ior(old_part, new_part))
}
until len < byte_length do {
suspend char(iand(ishift(i, byte_length-len), byte_mask))
len -:= byte_length
}
old_len := len
old_i := i
fail
end
procedure inbits(f, len)
local i, byte, old_byte_mask
static old_byte, old_len, byte_length
initial {
old_byte := old_len := 0
byte_length := 8
}
old_byte_mask := (0 < 2^old_len - 1) | 0
old_byte := iand(old_byte, old_byte_mask)
i := ishift(old_byte, len-old_len)
len -:= (len > old_len) | {
old_len -:= len
return i
}
while byte := ord(reads(f)) do {
i := ior(i, ishift(byte, len-byte_length))
len -:= (len > byte_length) | {
old_len := byte_length-len
old_byte := byte
return i
}
}
end
--
-Richard L. Goerwitz goer%sophist@uchicago.bitnet
goer@sophist.uchicago.edu rutgers!oddjob!gide!sophist!goer