source: trunk/Demo/Packages/CoolWeb/Common/UMemoryStreamEx.pas

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