| 1 | unit BitStream;
|
|---|
| 2 |
|
|---|
| 3 | // Date: 2010-08-17
|
|---|
| 4 |
|
|---|
| 5 | interface
|
|---|
| 6 |
|
|---|
| 7 | uses
|
|---|
| 8 | Classes, SysUtils, RtlConsts, Math, Memory;
|
|---|
| 9 |
|
|---|
| 10 | type
|
|---|
| 11 | TBytes = array[0..MaxInt - 1] of Byte;
|
|---|
| 12 |
|
|---|
| 13 | { TBitStream }
|
|---|
| 14 |
|
|---|
| 15 | TBitStream = class
|
|---|
| 16 | private
|
|---|
| 17 | function GetBit(Index: Integer):Boolean; virtual;
|
|---|
| 18 | function GetPosition: LongInt; virtual;
|
|---|
| 19 | function GetSize: LongInt; virtual;
|
|---|
| 20 | procedure SetBit(Index: Integer;const AValue: Boolean); virtual;
|
|---|
| 21 | procedure SetPosition(const AValue: LongInt); virtual;
|
|---|
| 22 | procedure SetSize(const AValue: LongInt); virtual;
|
|---|
| 23 | public
|
|---|
| 24 | function Seek(Offset: LongInt; Origin: TSeekOrigin): LongInt; virtual;
|
|---|
| 25 | function Read(var Buffer; Count: Longint): Longint; virtual;
|
|---|
| 26 | function CopyFrom(Source: TBitStream; Count: LongInt): LongInt;
|
|---|
| 27 | function Write(const Buffer; Count: Longint): Longint; virtual;
|
|---|
| 28 | function EqualTo(Source: TBitStream): Boolean;
|
|---|
| 29 | function GetString: string;
|
|---|
| 30 | procedure SetString(const AValue: string);
|
|---|
| 31 | procedure ReadBuffer(var Buffer; Count: Longint);
|
|---|
| 32 | procedure WriteBuffer(const Buffer; Count: Longint);
|
|---|
| 33 | function ReadBit: Boolean;
|
|---|
| 34 | procedure WriteBit(AValue: Boolean);
|
|---|
| 35 | function ReadNumber(Count: Byte): QWord;
|
|---|
| 36 | procedure WriteNumber(AValue: QWord; Count: Byte);
|
|---|
| 37 | property Position: LongInt read GetPosition write SetPosition;
|
|---|
| 38 | property Size: LongInt read GetSize write SetSize;
|
|---|
| 39 | property Bit[Index: Integer]: Boolean read GetBit write SetBit;
|
|---|
| 40 | property AsString: string read GetString write SetString;
|
|---|
| 41 | end;
|
|---|
| 42 |
|
|---|
| 43 | { TMemoryBitStream }
|
|---|
| 44 |
|
|---|
| 45 | TMemoryBitStream = class(TBitStream)
|
|---|
| 46 | private
|
|---|
| 47 | FMemory: TPositionMemory;
|
|---|
| 48 | FPosition: LongInt;
|
|---|
| 49 | FSize: LongInt;
|
|---|
| 50 | function GetPosition: LongInt; override;
|
|---|
| 51 | function GetSize: LongInt; override;
|
|---|
| 52 | procedure SetPosition(const AValue: LongInt); override;
|
|---|
| 53 | procedure SetSize(const AValue: LongInt); override;
|
|---|
| 54 | function WriteToByte(var Data: Byte; NewData, Pos, Count: Byte): Byte;
|
|---|
| 55 | public
|
|---|
| 56 | function Read(var Buffer; Count: Longint): Longint; override;
|
|---|
| 57 | function Write(const Buffer; Count: Longint): Longint; override;
|
|---|
| 58 | function Seek(Offset: LongInt; Origin: TSeekOrigin): LongInt; override;
|
|---|
| 59 | constructor Create;
|
|---|
| 60 | destructor Destroy; override;
|
|---|
| 61 | property Memory: TPositionMemory read FMemory;
|
|---|
| 62 | end;
|
|---|
| 63 |
|
|---|
| 64 |
|
|---|
| 65 | implementation
|
|---|
| 66 |
|
|---|
| 67 | { TBitStream }
|
|---|
| 68 |
|
|---|
| 69 | function TBitStream.GetBit(Index: Integer):Boolean;
|
|---|
| 70 | begin
|
|---|
| 71 | Seek(Index, soBeginning);
|
|---|
| 72 | Read(Result, 1);
|
|---|
| 73 | end;
|
|---|
| 74 |
|
|---|
| 75 | function TBitStream.GetPosition:LongInt;
|
|---|
| 76 | begin
|
|---|
| 77 | Result := Seek(0, soCurrent);
|
|---|
| 78 | end;
|
|---|
| 79 |
|
|---|
| 80 | function TBitStream.GetSize: LongInt;
|
|---|
| 81 | var
|
|---|
| 82 | P: LongInt;
|
|---|
| 83 | begin
|
|---|
| 84 | P := Seek(0, soCurrent);
|
|---|
| 85 | GetSize := Seek(0, soEnd);
|
|---|
| 86 | Seek(P, soBeginning);
|
|---|
| 87 | end;
|
|---|
| 88 |
|
|---|
| 89 | procedure TBitStream.SetBit(Index: Integer;const AValue: Boolean);
|
|---|
| 90 | begin
|
|---|
| 91 | Seek(Index, soBeginning);
|
|---|
| 92 | Write(AValue, 1);
|
|---|
| 93 | end;
|
|---|
| 94 |
|
|---|
| 95 | procedure TBitStream.SetPosition(const AValue:LongInt);
|
|---|
| 96 | begin
|
|---|
| 97 | Seek(AValue, soBeginning);
|
|---|
| 98 | end;
|
|---|
| 99 |
|
|---|
| 100 | procedure TBitStream.SetSize(const AValue:LongInt);
|
|---|
| 101 | begin
|
|---|
| 102 | end;
|
|---|
| 103 |
|
|---|
| 104 | function TBitStream.Seek(Offset:LongInt;Origin:TSeekOrigin):LongInt;
|
|---|
| 105 | begin
|
|---|
| 106 | Result := 0;
|
|---|
| 107 | end;
|
|---|
| 108 |
|
|---|
| 109 | function TBitStream.Read(var Buffer; Count:Longint):Longint;
|
|---|
| 110 | begin
|
|---|
| 111 | Result := 0;
|
|---|
| 112 | end;
|
|---|
| 113 |
|
|---|
| 114 | function TBitStream.CopyFrom(Source: TBitStream; Count: LongInt): LongInt;
|
|---|
| 115 | var
|
|---|
| 116 | BlockSize: LongInt;
|
|---|
| 117 | Buffer: array[0..1023] of Byte;
|
|---|
| 118 | begin
|
|---|
| 119 | Result := 0;
|
|---|
| 120 | while Count > 0 do begin
|
|---|
| 121 | if Count > (SizeOf(Buffer) * 8) then BlockSize := SizeOf(Buffer) * 8
|
|---|
| 122 | else BlockSize := Count;
|
|---|
| 123 | BlockSize := Source.Read(Buffer, BlockSize);
|
|---|
| 124 | BlockSize := Write(Buffer, BlockSize);
|
|---|
| 125 | if BlockSize = 0 then Break;
|
|---|
| 126 | Dec(Count, BlockSize);
|
|---|
| 127 | Result := Result + BlockSize;
|
|---|
| 128 | end;
|
|---|
| 129 | end;
|
|---|
| 130 |
|
|---|
| 131 | function TBitStream.Write(const Buffer; Count:Longint):Longint;
|
|---|
| 132 | begin
|
|---|
| 133 | Result := 0;
|
|---|
| 134 | end;
|
|---|
| 135 |
|
|---|
| 136 | function TBitStream.EqualTo(Source: TBitStream): Boolean;
|
|---|
| 137 | var
|
|---|
| 138 | I: Integer;
|
|---|
| 139 | begin
|
|---|
| 140 | if Size = Source.Size then begin
|
|---|
| 141 | I := 0;
|
|---|
| 142 | Result := True;
|
|---|
| 143 | Position := 0;
|
|---|
| 144 | Source.Position := 0;
|
|---|
| 145 | while (I < Size) and (ReadBit = Source.ReadBit) do Inc(I);
|
|---|
| 146 | if I < Size then Result := False;
|
|---|
| 147 | end else Result := False;
|
|---|
| 148 | end;
|
|---|
| 149 |
|
|---|
| 150 | procedure TBitStream.ReadBuffer(var Buffer; Count:Longint);
|
|---|
| 151 | begin
|
|---|
| 152 | if Read(Buffer, Count) < Count then
|
|---|
| 153 | raise EReadError.Create(SReadError);
|
|---|
| 154 | end;
|
|---|
| 155 |
|
|---|
| 156 | procedure TBitStream.WriteBuffer(const Buffer; Count:Longint);
|
|---|
| 157 | begin
|
|---|
| 158 | if Write(Buffer, Count) < Count then
|
|---|
| 159 | raise EWriteError.Create(SWriteError);
|
|---|
| 160 | end;
|
|---|
| 161 |
|
|---|
| 162 | function TBitStream.ReadBit:Boolean;
|
|---|
| 163 | begin
|
|---|
| 164 | Read(Result, 1);
|
|---|
| 165 | Result := Boolean(Integer(Result) and 1);
|
|---|
| 166 | end;
|
|---|
| 167 |
|
|---|
| 168 | procedure TBitStream.WriteBit(AValue:Boolean);
|
|---|
| 169 | begin
|
|---|
| 170 | Write(AValue, 1);
|
|---|
| 171 | end;
|
|---|
| 172 |
|
|---|
| 173 | function TBitStream.ReadNumber(Count: Byte): QWord;
|
|---|
| 174 | begin
|
|---|
| 175 | Result := 0;
|
|---|
| 176 | Read(Result, Count);
|
|---|
| 177 | Result := Result and ((QWord(1) shl Count) - 1);
|
|---|
| 178 | end;
|
|---|
| 179 |
|
|---|
| 180 | procedure TBitStream.WriteNumber(AValue: QWord; Count: Byte);
|
|---|
| 181 | begin
|
|---|
| 182 | Write(AValue, Count);
|
|---|
| 183 | end;
|
|---|
| 184 |
|
|---|
| 185 | function TBitStream.GetString: string;
|
|---|
| 186 | var
|
|---|
| 187 | I: Integer;
|
|---|
| 188 | begin
|
|---|
| 189 | Result := '';
|
|---|
| 190 | Position := 0;
|
|---|
| 191 | for I := 0 to Size - 1 do
|
|---|
| 192 | Result := Result + IntToStr(Integer(ReadBit));
|
|---|
| 193 | end;
|
|---|
| 194 |
|
|---|
| 195 | procedure TBitStream.SetString(const AValue: string);
|
|---|
| 196 | var
|
|---|
| 197 | I: Integer;
|
|---|
| 198 | begin
|
|---|
| 199 | Size := 0;
|
|---|
| 200 | for I := 1 to Length(AValue) do
|
|---|
| 201 | WriteBit(Boolean(StrToInt(AValue[I])));
|
|---|
| 202 | Position := 0;
|
|---|
| 203 | end;
|
|---|
| 204 |
|
|---|
| 205 | { TMemoryBitStream }
|
|---|
| 206 |
|
|---|
| 207 | function TMemoryBitStream.GetPosition:LongInt;
|
|---|
| 208 | begin
|
|---|
| 209 | Result := FPosition;
|
|---|
| 210 | end;
|
|---|
| 211 |
|
|---|
| 212 | function TMemoryBitStream.GetSize:LongInt;
|
|---|
| 213 | begin
|
|---|
| 214 | Result := FSize;
|
|---|
| 215 | end;
|
|---|
| 216 |
|
|---|
| 217 | procedure TMemoryBitStream.SetPosition(const AValue:LongInt);
|
|---|
| 218 | begin
|
|---|
| 219 | Seek(AValue, soBeginning);
|
|---|
| 220 | end;
|
|---|
| 221 |
|
|---|
| 222 | procedure TMemoryBitStream.SetSize(const AValue: LongInt);
|
|---|
| 223 | begin
|
|---|
| 224 | FSize := AValue;
|
|---|
| 225 | FMemory.Size := Ceil(AValue / 8);
|
|---|
| 226 | if FPosition > FSize then FPosition := FSize;
|
|---|
| 227 | end;
|
|---|
| 228 |
|
|---|
| 229 | function TMemoryBitStream.WriteToByte(var Data: Byte; NewData, Pos, Count: Byte) :Byte;
|
|---|
| 230 | begin
|
|---|
| 231 | Data := Byte(Data and not (((1 shl Count) - 1) shl Pos) // Make zero space for new data
|
|---|
| 232 | or ((NewData and ((1 shl Count) - 1)) shl Pos)); // Write new data
|
|---|
| 233 | Result := Count;
|
|---|
| 234 | if Result > (8 - Pos) then Result := 8 - Pos;
|
|---|
| 235 | end;
|
|---|
| 236 |
|
|---|
| 237 | function TMemoryBitStream.Read(var Buffer;Count:Longint):Longint;
|
|---|
| 238 | var
|
|---|
| 239 | ByteCount: LongInt;
|
|---|
| 240 | I: LongInt;
|
|---|
| 241 | PosInByte: Byte;
|
|---|
| 242 | Data: Byte;
|
|---|
| 243 | begin
|
|---|
| 244 | if (Count < 0) or (Count > (Size - Position)) then
|
|---|
| 245 | raise EReadError.Create(SReadError);
|
|---|
| 246 |
|
|---|
| 247 | Result := 0;
|
|---|
| 248 | if (FSize > 0) and (FPosition < FSize) and (FPosition >= 0) then begin
|
|---|
| 249 | if (FPosition + Count) > FSize then Count := FSize - FPosition;
|
|---|
| 250 | ByteCount := Ceil(Count / 8);
|
|---|
| 251 | PosInByte := FPosition mod 8;
|
|---|
| 252 | FMemory.Position := Trunc(FPosition / 8);
|
|---|
| 253 | Data := FMemory.ReadByte; // Read first byte
|
|---|
| 254 | for I := 0 to ByteCount - 1 do begin
|
|---|
| 255 | TBytes(Buffer)[I] := (Data shr PosInByte) and ((1 shl (8 - PosInByte)) - 1);
|
|---|
| 256 | if (I < ByteCount) and (FMemory.Position < FMemory.Size) then begin
|
|---|
| 257 | Data := FMemory.ReadByte;
|
|---|
| 258 | end else Data := 0;
|
|---|
| 259 | if PosInByte > 0 then
|
|---|
| 260 | TBytes(Buffer)[I] := TBytes(Buffer)[I] or
|
|---|
| 261 | ((Integer(Data) and ((1 shl PosInByte) - 1)) shl (8 - PosInByte));
|
|---|
| 262 | if (I = (ByteCount - 1)) then
|
|---|
| 263 | TBytes(Buffer)[I] := TBytes(Buffer)[I] and ((1 shl (Count - 8 * (ByteCount - 1))) - 1);
|
|---|
| 264 | end;
|
|---|
| 265 | Inc(FPosition, Count);
|
|---|
| 266 | Result := Count;
|
|---|
| 267 | end;
|
|---|
| 268 | end;
|
|---|
| 269 |
|
|---|
| 270 | function TMemoryBitStream.Write(const Buffer; Count: Longint): Longint;
|
|---|
| 271 | var
|
|---|
| 272 | ByteCount: LongInt;
|
|---|
| 273 | BitCount: LongInt;
|
|---|
| 274 | WriteBitCount: Integer;
|
|---|
| 275 | RestBitCount: Integer;
|
|---|
| 276 | NextRestBitCount: Integer;
|
|---|
| 277 | I: LongInt;
|
|---|
| 278 | BytePos: Byte;
|
|---|
| 279 | Data: Byte;
|
|---|
| 280 |
|
|---|
| 281 | function Min(Value1, Value2: Integer): Integer;
|
|---|
| 282 | begin
|
|---|
| 283 | if Value1 < Value2 then Result := Value1
|
|---|
| 284 | else Result := Value2;
|
|---|
| 285 | end;
|
|---|
| 286 |
|
|---|
| 287 | begin
|
|---|
| 288 | if Count < 0 then
|
|---|
| 289 | raise EWriteError.Create(SWriteError);
|
|---|
| 290 |
|
|---|
| 291 | RestBitCount := 0;
|
|---|
| 292 | NextRestBitCount := 0;
|
|---|
| 293 | BitCount := Count;
|
|---|
| 294 | ByteCount := Ceil(Count / 8);
|
|---|
| 295 | FMemory.Position := Trunc(FPosition / 8);
|
|---|
| 296 | BytePos := FPosition mod 8;
|
|---|
| 297 | I := 0;
|
|---|
| 298 | while (I < ByteCount) or (RestBitCount > 0) do begin
|
|---|
| 299 | WriteBitCount := Min(8 - BytePos, BitCount);
|
|---|
| 300 | if (FMemory.Position < FMemory.Size) and (WriteBitCount < 8) then begin
|
|---|
| 301 | Data := FMemory.ReadByte;
|
|---|
| 302 | FMemory.Position := FMemory.Position - 1;
|
|---|
| 303 | end else Data := 0;
|
|---|
| 304 |
|
|---|
| 305 | // Write rest of previous source byte to target
|
|---|
| 306 | if RestBitCount > 0 then begin
|
|---|
| 307 | Dec(BitCount, WriteToByte(Data, TBytes(Buffer)[I - 1] shr (8 - BytePos), 0, RestBitCount));
|
|---|
| 308 | WriteBitCount := Min(8 - BytePos, BitCount);
|
|---|
| 309 | end;
|
|---|
| 310 |
|
|---|
| 311 | // Write part up to one byte from source to target
|
|---|
| 312 | Dec(BitCount, WriteToByte(Data, TBytes(Buffer)[I], BytePos, WriteBitCount));
|
|---|
| 313 | FMemory.WriteByte(Data);
|
|---|
| 314 |
|
|---|
| 315 | RestBitCount := Min(8 - WriteBitCount, BitCount);
|
|---|
| 316 | Inc(I);
|
|---|
| 317 | end;
|
|---|
| 318 | Inc(FPosition, Count);
|
|---|
| 319 | if FSize < FPosition then FSize := FPosition;
|
|---|
| 320 | Result := Count;
|
|---|
| 321 | end;
|
|---|
| 322 |
|
|---|
| 323 | function TMemoryBitStream.Seek(Offset:LongInt;Origin:TSeekOrigin):LongInt;
|
|---|
| 324 | begin
|
|---|
| 325 | case Origin of
|
|---|
| 326 | soBeginning: FPosition := Offset;
|
|---|
| 327 | soEnd: FPosition := FSize + Offset;
|
|---|
| 328 | soCurrent: FPosition := FPosition + Offset;
|
|---|
| 329 | end;
|
|---|
| 330 | //if FPosition > FSize then FPosition := FSize;
|
|---|
| 331 | Result := FPosition;
|
|---|
| 332 | end;
|
|---|
| 333 |
|
|---|
| 334 | constructor TMemoryBitStream.Create;
|
|---|
| 335 | begin
|
|---|
| 336 | FMemory := TPositionMemory.Create;
|
|---|
| 337 | FPosition := 0;
|
|---|
| 338 | FSize := 0;
|
|---|
| 339 | end;
|
|---|
| 340 |
|
|---|
| 341 | destructor TMemoryBitStream.Destroy;
|
|---|
| 342 | begin
|
|---|
| 343 | FreeAndNil(FMemory);
|
|---|
| 344 | inherited;
|
|---|
| 345 | end;
|
|---|
| 346 |
|
|---|
| 347 | end.
|
|---|
| 348 |
|
|---|