summaryrefslogtreecommitdiff
path: root/ipl/procs/bitstrm.icn
blob: 44b46f5276309a6f000aaf30434ef38bf5dc419e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
############################################################################
#
#	File:     bitstrm.icn
#
#	Subject:  Procedures to read and write strings of bits in files
#
#	Author:   Robert J. Alexander
#
#	Date:     August 14, 1996
#
############################################################################
#
#   This file is in the public domain.
#
############################################################################
#
#  Procedures for reading and writing integer values made up of an
#  arbitrary number of bits, stored without regard to character
#  boundaries.
#
############################################################################
#
#  Usage of BitStreamWrite, by example:
#
#       record bit_value(value, nbits)
#       ...
#       BitStreamWrite()                        #initialize
#       while value := get_new_value() do       # loop to output values
#               BitStreamWrite(outfile, value.nbits, value.value)
#       BitStreamWrite(outfile)                 # output any buffered bits
#
#  Note the interesting effect that BitStreamWrite(outproc), as well as
#  outputting the complete string, pads the output 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 BitStreamRead, by example:
#
#       BitStreamRead()
#       while value := BitStreamRead(infile, nbits) do
#               # do something with value
#
#  BitStringRead fails when too few bits remain to satisfy a request.
#
############################################################################
#
#  See also: bitstr.icn
#
############################################################################

procedure BitStreamWrite(outfile,bits,value,outproc)
    local outvalue
    static buffer,bufferbits
    #
    #  Initialize.
    #
    initial {
	 buffer := bufferbits := 0
	    }
    /outproc := writes
    #
    #  If this is "close" call, flush buffer and reinitialize.
    #
    if /value then {
	 outvalue := &null
	 if bufferbits > 0 then
		  outproc(outfile,char(outvalue := ishift(buffer,8 - bufferbits)))
	 buffer := bufferbits := 0
	 return outvalue
	    }
    #
    #  Merge new value into buffer.
    #
    buffer := ior(ishift(buffer,bits),value)
    bufferbits +:= bits
    #
    #  Output bits.
    #
    while bufferbits >= 8 do {
	 outproc(outfile,char(outvalue := ishift(buffer,8 - bufferbits)))
	 buffer := ixor(buffer,ishift(outvalue,bufferbits - 8))
	 bufferbits -:= 8
	    }
    return outvalue
end


procedure BitStreamRead(infile,bits,inproc)
    local value
    static buffer,bufferbits
    #
    #  Initialize.
    #
    initial {
	 buffer := bufferbits := 0
	    }
    #
    #  Reinitialize if called with no arguments.
    #
    if /infile then {
	 buffer := bufferbits := 0
	 return
	    }
    #
    #  Read in more data if necessary.
    #
    /inproc := reads
    while bufferbits < bits do {
	 buffer := ior(ishift(buffer,8),ord(inproc(infile))) | fail
	 bufferbits +:= 8
	    }
    #
    #  Extract value from buffer and return.
    #
    value := ishift(buffer,bits - bufferbits)
    buffer := ixor(buffer,ishift(value,bufferbits - bits))
    bufferbits -:= bits
    return value
end