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