home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 October
/
usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso
/
misc
/
volume44
/
ibpag2
/
part02
/
outbits.icn
< prev
Wrap
Text File
|
1994-09-25
|
3KB
|
101 lines
############################################################################
#
# Name: outbits.icn
#
# Title: output variable-length characters in byte-size chunks
#
# Author: Richard L. Goerwitz
#
# $Revision: 1.5 $
#
############################################################################
#
# In any number of instances (e.g. when outputting variable-length
# characters or fixed-length encoded strings), the programmer must
# fit variable and/or non-byte-sized blocks into standard 8-bit
# bytes. Outbits() performs this task.
#
# 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
# a null i argument. Note that len gives the number of bits there
# are in i (or at least the number of bits you want preserved; those
# that are discarded are the most significant ones).
#
# 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.
#
############################################################################
#
# Links: none
# See also: inbits.icn
#
############################################################################
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 {
if old_len > 0 then {
old_i := old_len := 0
return char(old_part)
} else {
old_i := old_len := 0
fail
}
} else {
new_part := ishift(i, window-len)
len -:= (len >= window) | {
old_len +:= len
old_i := ior(ishift(old_part, len-window), i)
fail
}
# For debugging purposes.
# write("old_byte_mask = ", old_byte_mask)
# write("window = ", image(window))
# write("old_part = ", image(old_part))
# write("new_part = ", image(new_part))
# write("outputting ", image(ior(old_part, new_part)))
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