############################################################################
#
# File: bitstr.icn
#
# Subject: Procedures for bits in Icon strings
#
# Author: Robert J. Alexander
#
# Date: August 14, 1996
#
############################################################################
#
# This file is in the public domain.
#
############################################################################
#
# Procedures for working with strings made up of numeric values
# represented by strings of an arbitrary number of bits, stored without
# regard to character boundaries.
#
# In conjunction with the "large integers" feature of Icon, this
# facility can deal with bitstring segments of arbitrary size. If
# "large integers" are not supported, bitstring segments (i.e. the
# nbits parameter of BitStringGet and BitStringPut) wider that the
# integer size of the platform are likely to produce incorrect results.
#
############################################################################
#
# Usage of BitStringPut, by example:
#
# record bit_value(value, nbits)
# ...
# bitString := BitString("")
# while value := get_new_value() do # loop to append to string
# BitStringPut(bitString, value.nbits, value.value)
# resultString := BitStringPut(bitString) # output any buffered bits
#
# Note the interesting effect that BitStringPut(bitString), as well as
# producing the complete string, pads the buffered string to an even
# character boundary. This can be dune during construction of a bit
# string if the effect is desired.
#
# The "value" argument defaults to zero.
#
############################################################################
#
# Usage of BitStringGet, by example:
#
# record bit_value(value, nbits)
# ...
# bitString := BitString(string_of_bits)
# while value := BitStringGet(bitString, nbits) do
# # do something with value
#
# BitStringGet fails when too few bits remain to satisfy a request.
# However, if bits remain in the string, subsequent calls with fewer
# bits requested may succeed. A negative "nbits" value gets the value
# of the entire remainder of the string, to the byte boundary at its
# end.
#
############################################################################
#
# See also: bitstrm.icn
#
############################################################################
record BitString(s, buffer, bufferBits)
procedure BitStringPut(bitString, nbits, value)
local outvalue
#
# Initialize.
#
/bitString.buffer := bitString.bufferBits := 0
#
# If this is "close" call ("nbits" is null), flush buffer,
# reinitialize, and return the bit string with the final character
# value zero padded on the right.
#
if /nbits then {
if bitString.bufferBits > 0 then
bitString.s ||:=
char(ishift(bitString.buffer, 8 - bitString.bufferBits))
bitString.buffer := bitString.bufferBits := 0
return bitString.s
}
#
# Merge new value into buffer.
#
/value := 0
bitString.buffer := ior(ishift(bitString.buffer, nbits), value)
bitString.bufferBits +:= nbits
#
# Output bits.
#
while bitString.bufferBits >= 8 do {
bitString.s ||:= char(outvalue :=
ishift(bitString.buffer, 8 - bitString.bufferBits))
bitString.buffer :=
ixor(bitString.buffer, ishift(outvalue, bitString.bufferBits - 8))
bitString.bufferBits -:= 8
}
return
end
procedure BitStringGet(bitString, nbits)
local value, save, i
#
# Initialize.
#
/bitString.buffer := bitString.bufferBits := 0
#
# Get more data if necessary.
#
save := copy(bitString)
while nbits < 0 | bitString.bufferBits < nbits do {
(bitString.buffer :=
ior(ishift(bitString.buffer, 8), ord(bitString.s[1]))) | {
#
# There aren't enough bits left in the file. Restore the
# BitString to its state before the call (in case he wants to
# try again), and fail.
#
if nbits >= 0 then {
every i := 1 to *bitString do
bitString[i] := save[i]
fail
}
else {
bitString.s := ""
bitString.bufferBits := value := 0
value :=: bitString.buffer
return value
}
}
bitString.s[1] := ""
bitString.bufferBits +:= 8
}
#
# Extract value from buffer and return.
#
value := ishift(bitString.buffer, nbits - bitString.bufferBits)
bitString.buffer :=
ixor(bitString.buffer, ishift(value, bitString.bufferBits - nbits))
bitString.bufferBits -:= nbits
return value
end
This page produced by UniDoc on 2021/04/15 @ 23:59:44.