Bitwise IO: Difference between revisions
Content added Content deleted
m (Imlementation in Red programming language) |
Thundergnat (talk | contribs) (Rename Perl 6 -> Raku, alphabetize, minor clean-up) |
||
Line 559: | Line 559: | ||
return 0; |
return 0; |
||
}</lang> |
|||
=={{header|C sharp|C#}}== |
|||
<lang csharp>using System; |
|||
using System.IO; |
|||
public class BitReader |
|||
{ |
|||
uint readData = 0; |
|||
int startPosition = 0; |
|||
int endPosition = 0; |
|||
public int InBuffer |
|||
{ |
|||
get { return endPosition - startPosition; } |
|||
} |
|||
private Stream stream; |
|||
public Stream BaseStream |
|||
{ |
|||
get { return stream; } |
|||
} |
|||
public BitReader(Stream stream) |
|||
{ |
|||
this.stream = stream; |
|||
} |
|||
void EnsureData(int bitCount) |
|||
{ |
|||
int readBits = bitCount - InBuffer; |
|||
while (readBits > 0) |
|||
{ |
|||
int b = BaseStream.ReadByte(); |
|||
if (b < 0) throw new InvalidOperationException("Unexpected end of stream"); |
|||
readData |= checked((uint)b << endPosition); |
|||
endPosition += 8; |
|||
readBits -= 8; |
|||
} |
|||
} |
|||
public bool ReadBit() |
|||
{ |
|||
return Read(1) > 0; |
|||
} |
|||
public int Read(int bitCount) |
|||
{ |
|||
EnsureData(bitCount); |
|||
int result = (int)(readData >> startPosition) & ((1 << bitCount) - 1); |
|||
startPosition += bitCount; |
|||
if (endPosition == startPosition) |
|||
{ |
|||
endPosition = startPosition = 0; |
|||
readData = 0; |
|||
} |
|||
else if (startPosition >= 8) |
|||
{ |
|||
readData >>= startPosition; |
|||
endPosition -= startPosition; |
|||
startPosition = 0; |
|||
} |
|||
return result; |
|||
} |
|||
public void Align() |
|||
{ |
|||
endPosition = startPosition = 0; |
|||
readData = 0; |
|||
} |
|||
} |
|||
public class BitWriter |
|||
{ |
|||
uint data = 0; |
|||
int dataLength = 0; |
|||
Stream stream; |
|||
public Stream BaseStream |
|||
{ |
|||
get { return stream; } |
|||
} |
|||
public int BitsToAligment |
|||
{ |
|||
get { return (32 - dataLength) % 8; } |
|||
} |
|||
public BitWriter(Stream stream) |
|||
{ |
|||
this.stream = stream; |
|||
} |
|||
public void WriteBit(bool value) |
|||
{ |
|||
Write(value ? 1 : 0, 1); |
|||
} |
|||
public void Write(int value, int length) |
|||
{ |
|||
uint currentData = data | checked((uint)value << dataLength); |
|||
int currentLength = dataLength + length; |
|||
while (currentLength >= 8) |
|||
{ |
|||
BaseStream.WriteByte((byte)currentData); |
|||
currentData >>= 8; |
|||
currentLength -= 8; |
|||
} |
|||
data = currentData; |
|||
dataLength = currentLength; |
|||
} |
|||
public void Align() |
|||
{ |
|||
if (dataLength > 0) |
|||
{ |
|||
BaseStream.WriteByte((byte)data); |
|||
data = 0; |
|||
dataLength = 0; |
|||
} |
|||
} |
|||
} |
|||
class Program |
|||
{ |
|||
static void Main(string[] args) |
|||
{ |
|||
MemoryStream ms = new MemoryStream(); |
|||
BitWriter writer = new BitWriter(ms); |
|||
writer.WriteBit(true); |
|||
writer.Write(5, 3); |
|||
writer.Write(0x0155, 11); |
|||
writer.Align(); |
|||
ms.Position = 0; |
|||
BitReader reader = new BitReader(ms); |
|||
Console.WriteLine(reader.ReadBit()); |
|||
Console.WriteLine(reader.Read(3)); |
|||
Console.WriteLine(reader.Read(11).ToString("x4")); |
|||
reader.Align(); |
|||
} |
|||
}</lang> |
}</lang> |
||
Line 737: | Line 884: | ||
⇒ ABORT |
⇒ ABORT |
||
</lang> |
</lang> |
||
=={{header|C sharp|C#}}== |
|||
<lang csharp>using System; |
|||
using System.IO; |
|||
public class BitReader |
|||
{ |
|||
uint readData = 0; |
|||
int startPosition = 0; |
|||
int endPosition = 0; |
|||
public int InBuffer |
|||
{ |
|||
get { return endPosition - startPosition; } |
|||
} |
|||
private Stream stream; |
|||
public Stream BaseStream |
|||
{ |
|||
get { return stream; } |
|||
} |
|||
public BitReader(Stream stream) |
|||
{ |
|||
this.stream = stream; |
|||
} |
|||
void EnsureData(int bitCount) |
|||
{ |
|||
int readBits = bitCount - InBuffer; |
|||
while (readBits > 0) |
|||
{ |
|||
int b = BaseStream.ReadByte(); |
|||
if (b < 0) throw new InvalidOperationException("Unexpected end of stream"); |
|||
readData |= checked((uint)b << endPosition); |
|||
endPosition += 8; |
|||
readBits -= 8; |
|||
} |
|||
} |
|||
public bool ReadBit() |
|||
{ |
|||
return Read(1) > 0; |
|||
} |
|||
public int Read(int bitCount) |
|||
{ |
|||
EnsureData(bitCount); |
|||
int result = (int)(readData >> startPosition) & ((1 << bitCount) - 1); |
|||
startPosition += bitCount; |
|||
if (endPosition == startPosition) |
|||
{ |
|||
endPosition = startPosition = 0; |
|||
readData = 0; |
|||
} |
|||
else if (startPosition >= 8) |
|||
{ |
|||
readData >>= startPosition; |
|||
endPosition -= startPosition; |
|||
startPosition = 0; |
|||
} |
|||
return result; |
|||
} |
|||
public void Align() |
|||
{ |
|||
endPosition = startPosition = 0; |
|||
readData = 0; |
|||
} |
|||
} |
|||
public class BitWriter |
|||
{ |
|||
uint data = 0; |
|||
int dataLength = 0; |
|||
Stream stream; |
|||
public Stream BaseStream |
|||
{ |
|||
get { return stream; } |
|||
} |
|||
public int BitsToAligment |
|||
{ |
|||
get { return (32 - dataLength) % 8; } |
|||
} |
|||
public BitWriter(Stream stream) |
|||
{ |
|||
this.stream = stream; |
|||
} |
|||
public void WriteBit(bool value) |
|||
{ |
|||
Write(value ? 1 : 0, 1); |
|||
} |
|||
public void Write(int value, int length) |
|||
{ |
|||
uint currentData = data | checked((uint)value << dataLength); |
|||
int currentLength = dataLength + length; |
|||
while (currentLength >= 8) |
|||
{ |
|||
BaseStream.WriteByte((byte)currentData); |
|||
currentData >>= 8; |
|||
currentLength -= 8; |
|||
} |
|||
data = currentData; |
|||
dataLength = currentLength; |
|||
} |
|||
public void Align() |
|||
{ |
|||
if (dataLength > 0) |
|||
{ |
|||
BaseStream.WriteByte((byte)data); |
|||
data = 0; |
|||
dataLength = 0; |
|||
} |
|||
} |
|||
} |
|||
class Program |
|||
{ |
|||
static void Main(string[] args) |
|||
{ |
|||
MemoryStream ms = new MemoryStream(); |
|||
BitWriter writer = new BitWriter(ms); |
|||
writer.WriteBit(true); |
|||
writer.Write(5, 3); |
|||
writer.Write(0x0155, 11); |
|||
writer.Align(); |
|||
ms.Position = 0; |
|||
BitReader reader = new BitReader(ms); |
|||
Console.WriteLine(reader.ReadBit()); |
|||
Console.WriteLine(reader.Read(3)); |
|||
Console.WriteLine(reader.Read(11).ToString("x4")); |
|||
reader.Align(); |
|||
} |
|||
}</lang> |
|||
=={{header|D}}== |
=={{header|D}}== |
||
Line 1,451: | Line 1,451: | ||
69</lang> |
69</lang> |
||
Note: this implementation writes the bytes to the session (which is to say, it just gets displayed like any other result. Also, the compressed result is represented as bits - like 1 0 1 0 1... You'll of course need other code when you want to do other things.) |
Note: this implementation writes the bytes to the session (which is to say, it just gets displayed like any other result. Also, the compressed result is represented as bits - like 1 0 1 0 1... You'll of course need other code when you want to do other things.) |
||
=={{header|Julia}}== |
=={{header|Julia}}== |
||
Line 1,901: | Line 1,900: | ||
print pack("C1", $v); |
print pack("C1", $v); |
||
}</lang> |
}</lang> |
||
=={{header|Perl 6}}== |
|||
<lang perl6>sub encode-ascii(Str $s) { |
|||
my @b = flat $s.ords».fmt("%07b")».comb; |
|||
@b.push(0) until @b %% 8; # padding |
|||
Buf.new: gather while @b { take reduce * *2+*, (@b.pop for ^8) } |
|||
} |
|||
sub decode-ascii(Buf $b) { |
|||
my @b = flat $b.list».fmt("%08b")».comb; |
|||
@b.shift until @b %% 7; # remove padding |
|||
@b = gather while @b { take reduce * *2+*, (@b.pop for ^7) } |
|||
return [~] @b».chr; |
|||
} |
|||
say my $encode = encode-ascii 'STRING'; |
|||
say decode-ascii $encode;</lang> |
|||
{{out}} |
|||
<pre>Buf:0x<03 8b 99 29 4a e5> |
|||
STRING</pre> |
|||
=={{header|Phix}}== |
=={{header|Phix}}== |
||
Line 2,037: | Line 2,017: | ||
simply ignore retrieved zero bytes, but that could fairly obviously create problems for some forms of binary data. A better solution |
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. |
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|PicoLisp}}== |
|||
<lang PicoLisp>(de write7bitwise (Lst) |
|||
(let (Bits 0 Byte) |
|||
(for N Lst |
|||
(if (=0 Bits) |
|||
(setq Bits 7 Byte (* 2 N)) |
|||
(wr (| Byte (>> (dec 'Bits) N))) |
|||
(setq Byte (>> (- Bits 8) N)) ) ) |
|||
(unless (=0 Bits) |
|||
(wr Byte) ) ) ) |
|||
(de read7bitwise () |
|||
(make |
|||
(let (Bits 0 Byte) |
|||
(while (rd 1) |
|||
(let N @ |
|||
(link |
|||
(if (=0 Bits) |
|||
(>> (one Bits) N) |
|||
(| Byte (>> (inc 'Bits) N)) ) ) |
|||
(setq Byte (& 127 (>> (- Bits 7) N))) ) ) |
|||
(when (= 7 Bits) |
|||
(link Byte) ) ) ) )</lang> |
|||
<lang PicoLisp>(out 'a (write7bitwise (127 0 127 0 127 0 127 0 127))) |
|||
(hd 'a) |
|||
(in 'a (println (read7bitwise))) |
|||
(out 'a (write7bitwise (0 127 0 127 0 127 0 127 0))) |
|||
(hd 'a) |
|||
(in 'a (println (read7bitwise))) |
|||
(out 'a (write7bitwise (mapcar char (chop "STRING")))) |
|||
(hd 'a) |
|||
(println (mapcar char (in 'a (read7bitwise))))</lang> |
|||
{{out}} |
|||
<pre>00000000 FE 03 F8 0F E0 3F 80 FE .....?.. |
|||
(127 0 127 0 127 0 127 0) |
|||
00000000 01 FC 07 F0 1F C0 7F 00 ....... |
|||
(0 127 0 127 0 127 0 127) |
|||
00000000 A7 52 94 99 D1 C0 .R.... |
|||
("S" "T" "R" "I" "N" "G")</pre> |
|||
=={{header|PL/I}}== |
=={{header|PL/I}}== |
||
Line 2,081: | Line 2,103: | ||
1010011101010010100101001001100111010001111010011000110100010100000000 |
1010011101010010100101001001100111010001111010011000110100010100000000 |
||
</pre> |
</pre> |
||
=={{header|PicoLisp}}== |
|||
<lang PicoLisp>(de write7bitwise (Lst) |
|||
(let (Bits 0 Byte) |
|||
(for N Lst |
|||
(if (=0 Bits) |
|||
(setq Bits 7 Byte (* 2 N)) |
|||
(wr (| Byte (>> (dec 'Bits) N))) |
|||
(setq Byte (>> (- Bits 8) N)) ) ) |
|||
(unless (=0 Bits) |
|||
(wr Byte) ) ) ) |
|||
(de read7bitwise () |
|||
(make |
|||
(let (Bits 0 Byte) |
|||
(while (rd 1) |
|||
(let N @ |
|||
(link |
|||
(if (=0 Bits) |
|||
(>> (one Bits) N) |
|||
(| Byte (>> (inc 'Bits) N)) ) ) |
|||
(setq Byte (& 127 (>> (- Bits 7) N))) ) ) |
|||
(when (= 7 Bits) |
|||
(link Byte) ) ) ) )</lang> |
|||
<lang PicoLisp>(out 'a (write7bitwise (127 0 127 0 127 0 127 0 127))) |
|||
(hd 'a) |
|||
(in 'a (println (read7bitwise))) |
|||
(out 'a (write7bitwise (0 127 0 127 0 127 0 127 0))) |
|||
(hd 'a) |
|||
(in 'a (println (read7bitwise))) |
|||
(out 'a (write7bitwise (mapcar char (chop "STRING")))) |
|||
(hd 'a) |
|||
(println (mapcar char (in 'a (read7bitwise))))</lang> |
|||
{{out}} |
|||
<pre>00000000 FE 03 F8 0F E0 3F 80 FE .....?.. |
|||
(127 0 127 0 127 0 127 0) |
|||
00000000 01 FC 07 F0 1F C0 7F 00 ....... |
|||
(0 127 0 127 0 127 0 127) |
|||
00000000 A7 52 94 99 D1 C0 .R.... |
|||
("S" "T" "R" "I" "N" "G")</pre> |
|||
=={{header|PureBasic}}== |
=={{header|PureBasic}}== |
||
Line 2,436: | Line 2,416: | ||
Decrunched string equal to original. |
Decrunched string equal to original. |
||
</pre> |
</pre> |
||
=={{header|Raku}}== |
|||
(formerly Perl 6) |
|||
<lang perl6>sub encode-ascii(Str $s) { |
|||
my @b = flat $s.ords».fmt("%07b")».comb; |
|||
@b.push(0) until @b %% 8; # padding |
|||
Buf.new: gather while @b { take reduce * *2+*, (@b.pop for ^8) } |
|||
} |
|||
sub decode-ascii(Buf $b) { |
|||
my @b = flat $b.list».fmt("%08b")».comb; |
|||
@b.shift until @b %% 7; # remove padding |
|||
@b = gather while @b { take reduce * *2+*, (@b.pop for ^7) } |
|||
return [~] @b».chr; |
|||
} |
|||
say my $encode = encode-ascii 'STRING'; |
|||
say decode-ascii $encode;</lang> |
|||
{{out}} |
|||
<pre>Buf:0x<03 8b 99 29 4a e5> |
|||
STRING</pre> |
|||
=={{header|Red}}== |
=={{header|Red}}== |