source: trunk/Packages/CoolWeb/Common/MemoryStreamEx.pas

Last change on this file was 151, checked in by chronos, 8 months ago
File size: 7.4 KB
Line 
1unit MemoryStreamEx;
2
3interface
4
5uses
6 Classes, DateUtils, syncobjs;
7
8type
9 TEndianness = (enBig, enLittle);
10
11 { TMemoryStreamEx }
12
13 TMemoryStreamEx = class(TMemoryStream)
14 private
15 FEndianness: TEndianness;
16 SwapData: Boolean;
17 procedure SetEndianness(const AValue: TEndianness);
18 public
19 procedure WriteByte(Data: Byte);
20 procedure WriteWord(Data: Word);
21 procedure WriteCardinal(Data: Cardinal);
22 procedure WriteInt64(Data: Int64);
23 procedure WriteString(Data: string);
24 procedure WriteShortString(Data: ShortString);
25 procedure WriteAnsiString(const Data: string); override;
26 procedure WriteUnixTime(Data: TDateTime);
27 procedure WriteDouble(Value: Double);
28 procedure WriteSingle(Value: Single);
29 procedure WriteStream(Stream: TStream; Count: Integer);
30 procedure WriteStreamPart(Stream: TStream; Count: Integer);
31 function ReadByte: Byte;
32 function ReadWord: Word;
33 function ReadCardinal: Cardinal;
34 function ReadInt64: Int64;
35 function ReadString: string;
36 function ReadShortString: string;
37 function ReadAnsiString: string;
38 function ReadStringTerminated(Terminator: string = #0): string;
39 function ReadUnixTime: TDateTime;
40 function ReadDouble: Double;
41 function ReadSingle: Single;
42 procedure ReadStream(Stream: TStream; Count: Integer);
43 procedure ReadStreamPart(Stream: TStream; Count: Integer);
44 function Sum: Byte;
45 procedure FillByte(Data: Byte; Count: Integer);
46 procedure Assign(Source: TMemoryStreamEx);
47 constructor Create;
48 property Endianness: TEndianness read FEndianness write SetEndianness;
49 end;
50
51 { TThreadMemoryStreamEx }
52
53 TThreadMemoryStreamEx = class(TMemoryStreamEx)
54 Lock: TCriticalSection;
55 constructor Create;
56 destructor Destroy; override;
57 end;
58
59
60implementation
61
62{ TMemoryStreamEx }
63
64function TMemoryStreamEx.ReadAnsiString: string;
65var
66 StringLength: Longint;
67begin
68 ReadBuffer(StringLength, SizeOf(StringLength));
69 SetLength(Result, StringLength);
70 if StringLength > 0 then begin
71 ReadBuffer(Result[1], StringLength);
72 end;
73end;
74
75function TMemoryStreamEx.ReadStringTerminated(Terminator: string = #0): string;
76var
77 Data: Char;
78 I: Integer;
79 OldPosition: Integer;
80begin
81 OldPosition := Position;
82 Result := '';
83 I := 1;
84 repeat
85 if Position >= Size then Break;
86 Data := Chr(ReadByte);
87 if Data <> Terminator[I] then begin
88 Result := Result + Data;
89 I := 1;
90 end else Inc(I);
91 until I > Length(Terminator);
92 if not (I > Length(Terminator)) then begin
93 Result := '';
94 Position := OldPosition;
95 end;
96end;
97
98function TMemoryStreamEx.ReadByte: Byte;
99begin
100 ReadBuffer(Result, SizeOf(Byte));
101end;
102
103function TMemoryStreamEx.ReadCardinal: Cardinal;
104begin
105 ReadBuffer(Result, SizeOf(Cardinal));
106 if SwapData then Result := Swap(Result);
107end;
108
109function TMemoryStreamEx.ReadInt64: Int64;
110begin
111 ReadBuffer(Result, SizeOf(Int64));
112 if SwapData then Result := Swap(Result);
113end;
114
115function TMemoryStreamEx.ReadString:string;
116begin
117 SetLength(Result, Size - Position);
118 if (Size - Position) > 0 then
119 Read(Result[1], Size - Position)
120 else Result := '';
121end;
122
123function TMemoryStreamEx.ReadShortString: string;
124var
125 Count: Byte;
126begin
127 ReadBuffer(Count, 1);
128 SetLength(Result, Count);
129 ReadBuffer(Result[1], Count);
130end;
131
132procedure TMemoryStreamEx.ReadStream(Stream: TStream; Count: Integer);
133var
134 Buffer: array of Byte;
135begin
136 if Count > 0 then begin
137 SetLength(Buffer, Count);
138 ReadBuffer(Buffer[0], Count);
139 Stream.Size := Count;
140 Stream.Position := 0;
141 Stream.Write(Buffer[0], Count);
142 end;
143end;
144
145procedure TMemoryStreamEx.ReadStreamPart(Stream:TStream;Count:Integer);
146var
147 Buffer: array of Byte;
148begin
149 if Count > 0 then begin
150 SetLength(Buffer, Count);
151 ReadBuffer(Buffer[0], Count);
152 if Stream.Size < (Stream.Position + Count) then
153 Stream.Size := Stream.Position + Count;
154 Stream.Write(Buffer[0], Count);
155 end;
156end;
157
158procedure TMemoryStreamEx.WriteStreamPart(Stream:TStream;Count:Integer);
159var
160 Buffer: array of Byte;
161begin
162 if Count > Stream.Size then Count := Stream.Size; // Limit max. stream size
163 if Count > 0 then begin
164 SetLength(Buffer, Count);
165 Stream.Read(Buffer[0], Count);
166 Write(Buffer[0], Count);
167 end;
168end;
169
170constructor TMemoryStreamEx.Create;
171begin
172 Endianness := enLittle;
173end;
174
175function TMemoryStreamEx.ReadUnixTime: TDateTime;
176begin
177 Result := UnixToDateTime(ReadCardinal);
178end;
179
180function TMemoryStreamEx.ReadDouble: Double;
181begin
182 ReadBuffer(Result, SizeOf(Double));
183end;
184
185function TMemoryStreamEx.ReadSingle: Single;
186begin
187 ReadBuffer(Result, SizeOf(Single));
188end;
189
190function TMemoryStreamEx.Sum: Byte;
191begin
192 Result := 0;
193 Position := 0;
194 while Position < Size do
195 Result := (Result + ReadByte) and $ff;
196end;
197
198procedure TMemoryStreamEx.FillByte(Data:Byte;Count:Integer);
199var
200 I: Integer;
201begin
202 for I := 0 to Count - 1 do
203 WriteByte(Data);
204end;
205
206procedure TMemoryStreamEx.Assign(Source: TMemoryStreamEx);
207var
208 OldPosition: Int64;
209begin
210 FEndianness := Source.FEndianness;
211 SwapData := Source.SwapData;
212 OldPosition := Source.Position;
213 Clear;
214 Source.Position := 0;
215 CopyFrom(Source, Source.Size);
216 Position := OldPosition;
217 Source.Position := OldPosition;
218end;
219
220function TMemoryStreamEx.ReadWord: Word;
221begin
222 ReadBuffer(Result, SizeOf(Word));
223 if SwapData then Result := Swap(Result);
224end;
225
226procedure TMemoryStreamEx.SetEndianness(const AValue: TEndianness);
227begin
228 FEndianness := AValue;
229 {$if defined(FPC_LITTLE_ENDIAN)}
230 SwapData := FEndianness = enBig;
231 {$elseif defined(FPC_BIG_ENDIAN)}
232 SwapData := FEndianness = enLittle;
233 {$endif}
234end;
235
236procedure TMemoryStreamEx.WriteAnsiString(const Data: string);
237var
238 StringLength: Longint;
239begin
240 StringLength := Length(Data);
241 Write(StringLength, SizeOf(StringLength));
242 Write(Data[1], StringLength);
243end;
244
245procedure TMemoryStreamEx.WriteByte(Data: Byte);
246begin
247 Write(Data, SizeOf(Byte));
248end;
249
250procedure TMemoryStreamEx.WriteCardinal(Data: Cardinal);
251begin
252 if SwapData then Data := Swap(Data);
253 Write(Data, SizeOf(Cardinal));
254end;
255
256procedure TMemoryStreamEx.WriteInt64(Data: Int64);
257begin
258 if SwapData then Data := Swap(Data);
259 Write(Data, SizeOf(Int64));
260end;
261
262procedure TMemoryStreamEx.WriteString(Data: string);
263begin
264 if Length(Data) > 0 then
265 Write(Data[1], Length(Data));
266end;
267
268procedure TMemoryStreamEx.WriteShortString(Data: ShortString);
269begin
270 WriteByte(Length(Data));
271 Write(Data[1], Length(Data));
272end;
273
274procedure TMemoryStreamEx.WriteStream(Stream: TStream; Count: Integer);
275var
276 Buffer: array of Byte;
277begin
278 if Count > Stream.Size then Count := Stream.Size; // Limit max. stream size
279 Stream.Position := 0;
280 if Count > 0 then begin
281 SetLength(Buffer, Count);
282 Stream.Read(Buffer[0], Count);
283 Write(Buffer[0], Count);
284 end;
285end;
286
287procedure TMemoryStreamEx.WriteDouble(Value: Double);
288begin
289 Write(Value, SizeOf(Double));
290end;
291
292procedure TMemoryStreamEx.WriteSingle(Value: Single);
293begin
294 Write(Value, SizeOf(Single));
295end;
296
297procedure TMemoryStreamEx.WriteUnixTime(Data: TDateTime);
298var
299 DataUnix: Int64;
300begin
301 DataUnix := DateTimeToUnix(Data);
302 WriteCardinal(DataUnix);
303end;
304
305procedure TMemoryStreamEx.WriteWord(Data: Word);
306begin
307 if SwapData then Data := Swap(Data);
308 Write(Data, SizeOf(Word));
309end;
310
311{ TThreadMemoryStreamEx }
312
313constructor TThreadMemoryStreamEx.Create;
314begin
315 inherited;
316 Lock := TCriticalSection.Create;
317end;
318
319destructor TThreadMemoryStreamEx.Destroy;
320begin
321 Lock.Free;
322 inherited;
323end;
324
325end.
326
Note: See TracBrowser for help on using the repository browser.