source: trunk/Packages/CoolStreaming/StreamHelper.pas

Last change on this file was 323, checked in by chronos, 6 months ago
File size: 10.5 KB
Line 
1unit StreamHelper;
2
3interface
4
5uses
6 Classes, DateUtils, SysUtils;
7
8type
9 TEndianness = (enBig, enLittle);
10
11 { TStreamHelper }
12
13 TStreamHelper = class(TStream)
14 private
15 FOwnStream: Boolean;
16 FStream: TStream;
17 FEndianness: TEndianness;
18 SwapData: Boolean;
19 function GetItem(Index: Integer): Byte;
20 procedure SetEndianness(const AValue: TEndianness);
21 procedure SetItem(Index: Integer; const AValue: Byte);
22 procedure SetStream(AValue: TStream);
23 public
24 procedure Assign(Source: TStreamHelper);
25 procedure WriteByte(Data: Byte);
26 procedure WriteWord(Data: Word);
27 procedure WriteCardinal(Data: Cardinal);
28 procedure WriteInt64(Data: Int64);
29 procedure WriteString(Data: string);
30 procedure WriteShortString(Data: ShortString);
31 procedure WriteAnsiString(Data: string);
32 procedure WriteUnixTime(Data: TDateTime);
33 procedure WriteDouble(Value: Double);
34 procedure WriteSingle(Value: Single);
35 procedure WriteStream(AStream: TStream; Count: Integer);
36 procedure WriteStreamPart(AStream: TStream; Count: Integer);
37 function ReadByte: Byte;
38 function ReadWord: Word;
39 function ReadCardinal: Cardinal;
40 function ReadInt64: Int64;
41 function ReadString(Length: Integer): string;
42 function ReadShortString: string;
43 function ReadAnsiString: string;
44 function ReadStringTerminated(Terminator: string = #0): string;
45 function ReadUnixTime: TDateTime;
46 function ReadDouble: Double;
47 function ReadSingle: Single;
48 procedure ReadStream(AStream: TStream; Count: Integer);
49 procedure ReadStreamPart(AStream: TStream; Count: Integer);
50 function EqualTo(Source: TStream): Boolean;
51 function Sum: Byte;
52 procedure FillByte(Data: Byte; Count: Integer);
53 constructor Create; overload;
54 constructor Create(AStream: TStream); overload;
55 procedure Clear;
56 destructor Destroy; override;
57 function GetSize: Int64; override;
58 procedure SetSize(NewSize: Longint); override;
59 function Seek(Offset: Longint; Origin: Word): Longint; override;
60 function Read(var Buffer; Count: Longint): Longint; override;
61 function Write(const Buffer; Count: Longint): Longint; override;
62 property Endianness: TEndianness read FEndianness write SetEndianness;
63 property Stream: TStream read FStream write SetStream;
64 property Items[Index: Integer]: Byte read GetItem write SetItem; default;
65 property OwnStream: Boolean read FOwnStream write FOwnStream;
66 end;
67
68
69implementation
70
71{ TStreamHelper }
72
73function TStreamHelper.ReadAnsiString: string;
74var
75 StringLength: Longint;
76begin
77 StringLength := 0;
78 FStream.ReadBuffer(StringLength, SizeOf(StringLength));
79 Result := ReadString(StringLength);
80end;
81
82function TStreamHelper.ReadStringTerminated(Terminator: string = #0): string;
83var
84 Data: Char;
85 I: Integer;
86 OldPosition: Integer;
87begin
88 OldPosition := FStream.Position;
89 Result := '';
90 I := 1;
91 repeat
92 if FStream.Position >= FStream.Size then Break;
93 Data := Chr(ReadByte);
94 if Data <> Terminator[I] then begin
95 Result := Result + Data;
96 I := 1;
97 end else Inc(I);
98 until I > Length(Terminator);
99 if not (I > Length(Terminator)) then begin
100 Result := '';
101 FStream.Position := OldPosition;
102 end;
103end;
104
105function TStreamHelper.ReadByte: Byte;
106begin
107 Result := 0;
108 FStream.ReadBuffer(Result, SizeOf(Byte));
109end;
110
111function TStreamHelper.ReadCardinal: Cardinal;
112begin
113 Result := 0;
114 FStream.ReadBuffer(Result, SizeOf(Cardinal));
115 if SwapData then Result := SwapEndian(Result);
116end;
117
118function TStreamHelper.ReadInt64: Int64;
119begin
120 Result := 0;
121 FStream.ReadBuffer(Result, SizeOf(Int64));
122 if SwapData then Result := SwapEndian(Result);
123end;
124
125function TStreamHelper.ReadString(Length: Integer): string;
126begin
127 if Length > 0 then begin
128 SetLength(Result, Length);
129 FStream.Read(Result[1], Length);
130 end else Result := '';
131end;
132
133function TStreamHelper.ReadShortString: string;
134var
135 Count: Byte;
136begin
137 Count := 0;
138 FStream.ReadBuffer(Count, 1);
139 Result := ReadString(Count);
140end;
141
142procedure TStreamHelper.ReadStream(AStream: TStream; Count: Integer);
143//var
144// Buffer: array of Byte;
145begin
146 AStream.Position := 0;
147 AStream.CopyFrom(Self, Count);
148 (*if Count > 0 then begin
149 SetLength(Buffer, Count);
150 FStream.ReadBuffer(Buffer[0], Count);
151 AStream.Size := Count;
152 AStream.Position := 0;
153 AStream.Write(Buffer[0], Count);
154 end;*)
155end;
156
157procedure TStreamHelper.ReadStreamPart(AStream: TStream; Count: Integer);
158var
159 Buffer: array of Byte;
160begin
161 if Count > 0 then begin
162 SetLength(Buffer, Count);
163 FStream.ReadBuffer(Buffer[0], Count);
164 if AStream.Size < (AStream.Position + Count) then
165 AStream.Size := AStream.Position + Count;
166 AStream.Write(Buffer[0], Count);
167 end;
168end;
169
170function TStreamHelper.EqualTo(Source: TStream): Boolean;
171const
172 BlockSize = 4096;
173var
174 Buffer1: array[0..BlockSize - 1] of Byte;
175 Buffer2: array[0..BlockSize - 1] of Byte;
176 BufferLength: Integer;
177 OldPos1, OldPos2: Integer;
178begin
179 OldPos1 := Source.Position;
180 Source.Position := 0;
181 OldPos2 := Position;
182 Position := 0;
183 Result := True;
184 if Source.Size = Size then begin
185 while Source.Position < Source.Size do begin
186 BufferLength := Source.Read(Buffer1, BlockSize);
187 Read(Buffer2, BlockSize);
188 if not CompareMem(@Buffer1, @Buffer2, BufferLength) then begin
189 Result := False;
190 Break;
191 end;
192 end;
193 end else Result := False;
194 Source.Position := OldPos1;
195 Position := OldPos2;
196end;
197
198procedure TStreamHelper.WriteStreamPart(AStream: TStream; Count: Integer);
199var
200 Buffer: array of Byte;
201begin
202 if Count > AStream.Size then Count := AStream.Size; // Limit max. stream size
203 if Count > 0 then begin
204 SetLength(Buffer, Count);
205 AStream.Read(Buffer[0], Count);
206 FStream.Write(Buffer[0], Count);
207 end;
208end;
209
210constructor TStreamHelper.Create;
211begin
212 inherited;
213 Endianness := enLittle;
214 FStream := TMemoryStream.Create;
215 FOwnStream := True;
216end;
217
218constructor TStreamHelper.Create(AStream: TStream);
219begin
220 inherited Create;
221 Endianness := enLittle;
222 FStream := AStream;
223 FOwnStream := False;
224end;
225
226procedure TStreamHelper.Clear;
227begin
228 Stream.Size := 0;
229end;
230
231destructor TStreamHelper.Destroy;
232begin
233 if FOwnStream then FreeAndNil(FStream);
234 inherited;
235end;
236
237function TStreamHelper.GetSize: Int64;
238begin
239 Result := Stream.Size;
240end;
241
242procedure TStreamHelper.SetSize(NewSize: Longint);
243begin
244 Stream.Size := NewSize;
245end;
246
247function TStreamHelper.Seek(Offset: Longint; Origin: Word): Longint;
248begin
249 Result := Stream.Seek(Offset, Origin);
250end;
251
252function TStreamHelper.Read(var Buffer; Count: Longint): Longint;
253begin
254 Result := Stream.Read(Buffer, Count);
255end;
256
257function TStreamHelper.Write(const Buffer; Count: Longint): Longint;
258begin
259 Result := Stream.Write(Buffer, Count);
260end;
261
262function TStreamHelper.ReadUnixTime: TDateTime;
263begin
264 Result := UnixToDateTime(ReadCardinal);
265end;
266
267function TStreamHelper.ReadDouble: Double;
268begin
269 Result := 0;
270 FStream.ReadBuffer(Result, SizeOf(Double));
271end;
272
273function TStreamHelper.ReadSingle: Single;
274begin
275 Result := 0;
276 FStream.ReadBuffer(Result, SizeOf(Single));
277end;
278
279function TStreamHelper.Sum: Byte;
280begin
281 Result := 0;
282 FStream.Position := 0;
283 while FStream.Position < FStream.Size do
284 Result := (Result + FStream.ReadByte) and $ff;
285end;
286
287procedure TStreamHelper.FillByte(Data:Byte;Count:Integer);
288var
289 I: Integer;
290begin
291 for I := 0 to Count - 1 do
292 WriteByte(Data);
293end;
294
295function TStreamHelper.ReadWord: Word;
296begin
297 Result := 0;
298 FStream.ReadBuffer(Result, SizeOf(Word));
299 if SwapData then Result := SwapEndian(Result);
300end;
301
302procedure TStreamHelper.SetEndianness(const AValue: TEndianness);
303begin
304 FEndianness := AValue;
305 {$if defined(FPC_LITTLE_ENDIAN)}
306 SwapData := FEndianness = enBig;
307 {$elseif defined(FPC_BIG_ENDIAN)}
308 SwapData := FEndianness = enLittle;
309 {$endif}
310end;
311
312function TStreamHelper.GetItem(Index: Integer): Byte;
313begin
314 Position := Index;
315 Result := ReadByte;
316end;
317
318procedure TStreamHelper.SetItem(Index: Integer; const AValue: Byte);
319begin
320 Position := Index;
321 WriteByte(AValue);
322end;
323
324procedure TStreamHelper.SetStream(AValue: TStream);
325begin
326 if FStream = AValue then Exit;
327 if FOwnStream and Assigned(FStream) then FStream.Free;
328 FStream := AValue;
329 FOwnStream := False;
330end;
331
332procedure TStreamHelper.Assign(Source: TStreamHelper);
333var
334 OldPosition: Integer;
335begin
336 OldPosition := Source.Position;
337 Clear;
338 WriteStream(Source, Source.Size);
339 Source.Position := OldPosition;
340 Position := OldPosition;
341end;
342
343procedure TStreamHelper.WriteAnsiString(Data: string);
344var
345 StringLength: Longint;
346begin
347 StringLength := Length(Data);
348 Write(StringLength, SizeOf(StringLength));
349 Write(Data[1], StringLength);
350end;
351
352procedure TStreamHelper.WriteByte(Data: Byte);
353begin
354 FStream.Write(Data, SizeOf(Byte));
355end;
356
357procedure TStreamHelper.WriteCardinal(Data: Cardinal);
358begin
359 if SwapData then Data := SwapEndian(Data);
360 Write(Data, SizeOf(Cardinal));
361end;
362
363procedure TStreamHelper.WriteInt64(Data: Int64);
364begin
365 if SwapData then Data := SwapEndian(Data);
366 Write(Data, SizeOf(Int64));
367end;
368
369procedure TStreamHelper.WriteString(Data:string);
370begin
371 if Length(Data) > 0 then
372 Write(Data[1], Length(Data));
373end;
374
375procedure TStreamHelper.WriteShortString(Data: ShortString);
376begin
377 WriteByte(Length(Data));
378 Write(Data[1], Length(Data));
379end;
380
381procedure TStreamHelper.WriteStream(AStream: TStream; Count: Integer);
382//var
383// Buffer: array of Byte;
384begin
385 AStream.Position := 0;
386 CopyFrom(AStream, Count);
387 (*if Count > AStream.Size then Count := AStream.Size; // Limit max. stream size
388 AStream.Position := 0;
389 if Count > 0 then begin
390 SetLength(Buffer, Count);
391 AStream.Read(Buffer[0], Count);
392 FStream.Write(Buffer[0], Count);
393 end;*)
394end;
395
396procedure TStreamHelper.WriteDouble(Value: Double);
397begin
398 Write(Value, SizeOf(Double));
399end;
400
401procedure TStreamHelper.WriteSingle(Value: Single);
402begin
403 Write(Value, SizeOf(Single));
404end;
405
406procedure TStreamHelper.WriteUnixTime(Data: TDateTime);
407var
408 DataUnix: Int64;
409begin
410 DataUnix := DateTimeToUnix(Data);
411 WriteCardinal(DataUnix);
412end;
413
414procedure TStreamHelper.WriteWord(Data: Word);
415begin
416 if SwapData then Data := SwapEndian(Data);
417 Write(Data, SizeOf(Word));
418end;
419
420
421end.
Note: See TracBrowser for help on using the repository browser.