Bitwise IO: Difference between revisions

3,979 bytes added ,  4 years ago
(Added Seed7 example)
Line 1,920:
<pre>Buf:0x<03 8b 99 29 4a e5>
STRING</pre>
 
=={{header|Phix}}==
<lang Phix>enum FN, V, BITS -- fields of a bitwiseioreader/writer
 
function new_bitwiseio(string filename, mode)
integer fn = open(filename,mode)
return {fn,0,0} -- ie {FN,V=0,BITS=0}
end function
 
function new_bitwiseiowriter(string filename)
return new_bitwiseio(filename,"wb")
end function
 
function new_bitwiseioreader(string filename)
return new_bitwiseio(filename,"rb")
end function
 
function write_bits(sequence writer, integer v, bits)
integer {fn,wv,wb} = writer,
p2 = power(2,bits), ch
if v!=and_bits(v,p2*2-1) then ?9/0 end if
wv = wv*p2+v
wb += bits
while wb>=8 do
wb -= 8
p2 = power(2,wb)
ch = floor(wv/p2)
puts(fn,ch)
wv -= ch*p2
end while
if wv>=#100 then ?9/0 end if
if wb>=8 then ?9/0 end if
writer[V]= wv
writer[BITS]= wb
return writer
end function
 
function close_bitwiseiowriter(sequence writer)
integer {fn,wv,wb} = writer
if wb then
if wb>=8 then ?9/0 end if -- sanity check
writer = write_bits(writer,0,8-wb)
end if
if writer[V]!=0 then ?9/0 end if
if writer[BITS]!=0 then ?9/0 end if
close(fn)
writer[FN]=-1
return writer
end function
 
function read_bits(sequence reader, integer bits)
integer {fn,rv,rb} = reader, ch, p2
while bits>rb do
ch = getc(fn)
if ch=-1 then return {-1,reader} end if
rv = rv*#100+ch
rb += 8
end while
rb -= bits
p2 = power(2,rb)
ch = floor(rv/p2)
rv -= ch*p2
reader[V]= rv
reader[BITS]= rb
return {ch,reader}
end function
 
function as_hexb(string s, fmt="%02x ")
-- helper funtion, returns hex string, or binary if fmt="%08b "
string res = ""
for i=1 to length(s) do
res &= sprintf(fmt,s[i])
end for
return trim(res)
end function
 
constant test = "This is a test."
--constant test = "This is a test"
--constant test = "abcdefghijk"
--constant test = "STRING"
--constant test = "This is an ascii string that will be crunched, written, read and expanded."
printf(1,"\"%s\" as bytes: %s (length %d)\n",{test,as_hexb(test),length(test)})
printf(1," original bits: %s\n",{as_hexb(test,"%08b ")})
 
sequence writer = new_bitwiseiowriter("test.bin")
for i=1 to length(test) do
writer = write_bits(writer,test[i],7)
end for
writer = close_bitwiseiowriter(writer)
 
integer fn = open("test.bin","rb")
string bytes = get_text(fn,GT_WHOLE_FILE)
printf(1,"Written bitstream: %s\n",{as_hexb(bytes,"%08b ")})
printf(1,"Written bytes: %s (length %d)\n",{as_hexb(bytes),length(bytes)})
close(fn)
 
sequence reader = new_bitwiseioreader("test.bin")
bytes = ""
integer ch
while true do
{ch,reader} = read_bits(reader,7)
if ch=-1 then exit end if
bytes &= ch
end while
printf(1,"\"%s\" as bytes: %s (length %d)\n",{bytes,as_hexb(bytes),length(bytes)})</lang>
{{out}}
<pre>
"This is a test." as bytes: 54 68 69 73 20 69 73 20 61 20 74 65 73 74 2E (length 15)
original bits: 01010100 01101000 01101001 01110011 00100000 01101001 01110011 00100000 01100001 00100000 01110100 01100101 01110011 01110100 00101110
Written bitstream: 10101001 10100011 01001111 00110100 00011010 01111001 10100000 11000010 10000011 10100110 01011110 01111101 00010111 00000000
Written bytes: A9 A3 4F 34 1A 79 A0 C2 83 A6 5E 7D 17 00 (length 14)
"This is a test. " as bytes: 54 68 69 73 20 69 73 20 61 20 74 65 73 74 2E 00 (length 16)
</pre>
Note that the 105(=15*7) bits written out are rounded up/padded to 112(=14*8), reading them back in makes for 16 whole 7-bit values,
which, since 16*7==112, cannot be distinguished from deliberately writing a trailing 7 zero bits. You could, as per the Go example,
simply ignore retrieved zero bytes, but that could fairly obviously create problems for some forms of binary data. A better solution
might be for the data to embed or prefix it's own length. The other four (commented-out) test values do not exhibit this problem.
 
=={{header|PL/I}}==
7,804

edits