forked from thargor6/mb3d
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathBitStream.pas
151 lines (122 loc) · 3.67 KB
/
BitStream.pas
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
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
////////////////////////////////////////////////////////////////////////////////
//
// BitStream.pas - Bit stream unit
// -------------------------------
// Changed: 2001-02-10
// Maintain: Michael Vinther | mv@logicnet·dk
//
// Contains:
// (TBaseStream)
// (TFilterStream)
// TBitStream
//
unit BitStream;
interface
uses Windows, Streams, SysUtils;
resourcestring
rsWriteDenied = 'Stream not open for write';
type
TBitStream = class(TFilterStream)
public
destructor Destroy; override;
// function Write(var Buf; Count: Integer): Integer; override;
// function Read(var Buf; Count: Integer): Integer; override;
procedure WriteBits(Str: DWord; Count: Integer);
function ReadBits(var Str; Count: Integer): Integer;
function ReadBit: Byte;
// Write data in look-ahead and reset 1-byte read/write buffer
procedure Flush; override;
// Return value is >0 if there is available data
function Available: Integer; override;
protected
WBitPos, RBitPos : Integer;
Buffer : Byte;
end;
implementation
uses MemUtils;
//=======================================================================================================
// TBitStream
//=======================================================================================================
//-----------------------------------------------------------------------------------
// Flush and free memory
destructor TBitStream.Destroy;
begin
Flush;
inherited;
end;
procedure TBitStream.WriteBits(Str: DWord; Count: Integer);
var
OutBits : Integer;
DataByte : Byte;
begin
Assert(Count<=32);
while Count>0 do // Write data one byte at a time
begin
OutBits:=Count;
if OutBits>8 then OutBits:=8;
DataByte:=Str and ((1 shl OutBits)-1); // Make sure only bits to be written can be set
Buffer:=Buffer or (DataByte shl WBitPos); // Put first part of byte in buffer
if WBitPos+OutBits>=8 then // Byte overlap
begin
Next.Write(Buffer,1);
Buffer:=DataByte shr (8-WBitPos); // Put first part of byte in buffer
Dec(WBitPos,8);
end;
Inc(WBitPos,OutBits);
Str:=Str shr 8;
Dec(Count,OutBits);
end;
end;
function TBitStream.ReadBits(var Str; Count: Integer): Integer;
var
InBits, Got : Integer;
DataByte : Byte;
StrPtr : ^Byte;
begin
StrPtr:=@Str;
Result:=0;
while Count>0 do // Read data one byte at a time
begin
InBits:=Count;
if InBits>8 then InBits:=8;
if (RBitPos=0) and (Next.Read(Buffer,1)<>1) then Exit;
DataByte:=Buffer shr RBitPos; // Read first part of byte
if RBitPos+InBits>8 then // Byte overlap
begin
if Next.Read(Buffer,1)<>1 then Exit;
Got:=8-RBitPos;
DataByte:=(DataByte and ((1 shl Got)-1)) or (Buffer shl Got); // Read last part of byte
Dec(RBitPos,8);
end;
StrPtr^:=DataByte and ((1 shl InBits)-1); // Make sure only bits to be read can be set
Inc(StrPtr);
Inc(RBitPos,InBits);
Inc(Result,InBits);
Dec(Count,InBits);
end;
end;
function TBitStream.ReadBit: Byte;
begin
if (RBitPos=0) or (RBitPos=8) then
begin
Next.Read(Buffer,1);
RBitPos:=0;
end;
Result:=(Buffer shr RBitPos) and 1;
Inc(RBitPos);
end;
//-----------------------------------------------------------------------------------
// Write data in look-ahead and reset 1-byte read/write buffer
procedure TBitStream.Flush;
begin
if WBitPos>0 then Next.Write(Buffer,1);
WBitPos:=0; RBitPos:=0;
Buffer:=0;
end;
//-----------------------------------------------------------------------------------
// Return value is >0 if there is available data
function TBitStream.Available;
begin
Available:=Next.Available+RBitPos;
end;
end.