blob: b6e0cbfe9453986a3141771539e8230df7e14c62 [file] [log] [blame]
Jens Geyerd5436f52014-10-03 19:50:38 +02001(*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 *)
19
20unit Thrift.Stream;
21
Jens Geyer9f7f11e2016-04-14 21:37:11 +020022{$I Thrift.Defines.inc}
Nick4f5229e2016-04-14 16:43:22 +030023
Jens Geyerd5436f52014-10-03 19:50:38 +020024interface
25
26uses
27 Classes,
28 SysUtils,
29 SysConst,
30 RTLConsts,
Jens Geyer9f7f11e2016-04-14 21:37:11 +020031 {$IFDEF OLD_UNIT_NAMES}
32 ActiveX,
Nick4f5229e2016-04-14 16:43:22 +030033 {$ELSE}
Jens Geyer9f7f11e2016-04-14 21:37:11 +020034 Winapi.ActiveX,
35 {$ENDIF}
Nick4f5229e2016-04-14 16:43:22 +030036 Thrift.Utils;
Jens Geyerd5436f52014-10-03 19:50:38 +020037
38type
39
40 IThriftStream = interface
Jens Geyer17c3ad92017-09-05 20:31:27 +020041 ['{2A77D916-7446-46C1-8545-0AEC0008DBCA}']
42 procedure Write( const buffer: TBytes; offset: Integer; count: Integer); overload;
43 procedure Write( const pBuf : Pointer; offset: Integer; count: Integer); overload;
44 function Read( var buffer: TBytes; offset: Integer; count: Integer): Integer; overload;
45 function Read( const pBuf : Pointer; const buflen : Integer; offset: Integer; count: Integer): Integer; overload;
Jens Geyerd5436f52014-10-03 19:50:38 +020046 procedure Open;
47 procedure Close;
48 procedure Flush;
49 function IsOpen: Boolean;
50 function ToArray: TBytes;
51 end;
52
53 TThriftStreamImpl = class( TInterfacedObject, IThriftStream)
54 private
Jens Geyer17c3ad92017-09-05 20:31:27 +020055 procedure CheckSizeAndOffset( const pBuf : Pointer; const buflen : Integer; offset: Integer; count: Integer); overload;
Jens Geyerd5436f52014-10-03 19:50:38 +020056 protected
Jens Geyer17c3ad92017-09-05 20:31:27 +020057 procedure Write( const buffer: TBytes; offset: Integer; count: Integer); overload; inline;
58 procedure Write( const pBuf : Pointer; offset: Integer; count: Integer); overload; virtual;
59 function Read( var buffer: TBytes; offset: Integer; count: Integer): Integer; overload; inline;
60 function Read( const pBuf : Pointer; const buflen : Integer; offset: Integer; count: Integer): Integer; overload; virtual;
Jens Geyerd5436f52014-10-03 19:50:38 +020061 procedure Open; virtual; abstract;
62 procedure Close; virtual; abstract;
63 procedure Flush; virtual; abstract;
64 function IsOpen: Boolean; virtual; abstract;
65 function ToArray: TBytes; virtual; abstract;
66 end;
67
68 TThriftStreamAdapterDelphi = class( TThriftStreamImpl )
69 private
70 FStream : TStream;
71 FOwnsStream : Boolean;
72 protected
Jens Geyer17c3ad92017-09-05 20:31:27 +020073 procedure Write( const pBuf : Pointer; offset: Integer; count: Integer); override;
74 function Read( const pBuf : Pointer; const buflen : Integer; offset: Integer; count: Integer): Integer; override;
Jens Geyerd5436f52014-10-03 19:50:38 +020075 procedure Open; override;
76 procedure Close; override;
77 procedure Flush; override;
78 function IsOpen: Boolean; override;
79 function ToArray: TBytes; override;
80 public
81 constructor Create( const AStream: TStream; AOwnsStream : Boolean);
82 destructor Destroy; override;
83 end;
84
85 TThriftStreamAdapterCOM = class( TThriftStreamImpl)
86 private
87 FStream : IStream;
88 protected
Jens Geyer17c3ad92017-09-05 20:31:27 +020089 procedure Write( const pBuf : Pointer; offset: Integer; count: Integer); override;
90 function Read( const pBuf : Pointer; const buflen : Integer; offset: Integer; count: Integer): Integer; override;
Jens Geyerd5436f52014-10-03 19:50:38 +020091 procedure Open; override;
92 procedure Close; override;
93 procedure Flush; override;
94 function IsOpen: Boolean; override;
95 function ToArray: TBytes; override;
96 public
97 constructor Create( const AStream: IStream);
98 end;
99
100implementation
101
102{ TThriftStreamAdapterCOM }
103
104procedure TThriftStreamAdapterCOM.Close;
105begin
106 FStream := nil;
107end;
108
109constructor TThriftStreamAdapterCOM.Create( const AStream: IStream);
110begin
111 inherited Create;
112 FStream := AStream;
113end;
114
115procedure TThriftStreamAdapterCOM.Flush;
116begin
Jens Geyer9f7f11e2016-04-14 21:37:11 +0200117 if IsOpen then begin
118 if FStream <> nil then begin
Jens Geyerd5436f52014-10-03 19:50:38 +0200119 FStream.Commit( STGC_DEFAULT );
120 end;
121 end;
122end;
123
124function TThriftStreamAdapterCOM.IsOpen: Boolean;
125begin
126 Result := FStream <> nil;
127end;
128
129procedure TThriftStreamAdapterCOM.Open;
130begin
Jens Geyer9f7f11e2016-04-14 21:37:11 +0200131 // nothing to do
Jens Geyerd5436f52014-10-03 19:50:38 +0200132end;
133
Jens Geyer17c3ad92017-09-05 20:31:27 +0200134function TThriftStreamAdapterCOM.Read( const pBuf : Pointer; const buflen : Integer; offset: Integer; count: Integer): Integer;
Jens Geyerd5436f52014-10-03 19:50:38 +0200135begin
136 inherited;
Jens Geyer17c3ad92017-09-05 20:31:27 +0200137
138 if count >= buflen-offset
139 then count := buflen-offset;
140
Jens Geyerd5436f52014-10-03 19:50:38 +0200141 Result := 0;
Jens Geyer9f7f11e2016-04-14 21:37:11 +0200142 if FStream <> nil then begin
143 if count > 0 then begin
Jens Geyer17c3ad92017-09-05 20:31:27 +0200144 FStream.Read( @(PByteArray(pBuf)^[offset]), count, @Result);
Jens Geyerd5436f52014-10-03 19:50:38 +0200145 end;
146 end;
147end;
148
149function TThriftStreamAdapterCOM.ToArray: TBytes;
150var
151 statstg: TStatStg;
152 len : Integer;
Nick4f5229e2016-04-14 16:43:22 +0300153 NewPos : {$IF CompilerVersion >= 29.0} UInt64 {$ELSE} Int64 {$IFEND};
Jens Geyerd5436f52014-10-03 19:50:38 +0200154 cbRead : Integer;
155begin
156 FillChar( statstg, SizeOf( statstg), 0);
157 len := 0;
Jens Geyer9f7f11e2016-04-14 21:37:11 +0200158 if IsOpen then begin
159 if Succeeded( FStream.Stat( statstg, STATFLAG_NONAME )) then begin
Jens Geyerd5436f52014-10-03 19:50:38 +0200160 len := statstg.cbSize;
161 end;
162 end;
163
164 SetLength( Result, len );
165
Jens Geyer9f7f11e2016-04-14 21:37:11 +0200166 if len > 0 then begin
167 if Succeeded( FStream.Seek( 0, STREAM_SEEK_SET, NewPos) ) then begin
Jens Geyerd5436f52014-10-03 19:50:38 +0200168 FStream.Read( @Result[0], len, @cbRead);
169 end;
170 end;
171end;
172
Jens Geyer17c3ad92017-09-05 20:31:27 +0200173procedure TThriftStreamAdapterCOM.Write( const pBuf: Pointer; offset: Integer; count: Integer);
Jens Geyer9f7f11e2016-04-14 21:37:11 +0200174var nWritten : Integer;
Jens Geyerd5436f52014-10-03 19:50:38 +0200175begin
176 inherited;
Jens Geyer9f7f11e2016-04-14 21:37:11 +0200177 if IsOpen then begin
178 if count > 0 then begin
Jens Geyer17c3ad92017-09-05 20:31:27 +0200179 FStream.Write( @(PByteArray(pBuf)^[offset]), count, @nWritten);
Jens Geyerd5436f52014-10-03 19:50:38 +0200180 end;
181 end;
182end;
183
184{ TThriftStreamImpl }
185
Jens Geyer17c3ad92017-09-05 20:31:27 +0200186procedure TThriftStreamImpl.CheckSizeAndOffset( const pBuf : Pointer; const buflen : Integer; offset: Integer; count: Integer);
Jens Geyerd5436f52014-10-03 19:50:38 +0200187begin
Jens Geyer9f7f11e2016-04-14 21:37:11 +0200188 if count > 0 then begin
Jens Geyer17c3ad92017-09-05 20:31:27 +0200189 if (offset < 0) or ( offset >= buflen) then begin
Jens Geyerd5436f52014-10-03 19:50:38 +0200190 raise ERangeError.Create( SBitsIndexError );
191 end;
Jens Geyer17c3ad92017-09-05 20:31:27 +0200192 if count > buflen then begin
Jens Geyerd5436f52014-10-03 19:50:38 +0200193 raise ERangeError.Create( SBitsIndexError );
194 end;
195 end;
196end;
197
Jens Geyer9f7f11e2016-04-14 21:37:11 +0200198function TThriftStreamImpl.Read(var buffer: TBytes; offset, count: Integer): Integer;
Jens Geyerd5436f52014-10-03 19:50:38 +0200199begin
Jens Geyera76e6c72017-09-08 21:03:30 +0200200 if Length(buffer) > 0
201 then Result := Read( @buffer[0], Length(buffer), offset, count)
202 else Result := 0;
Jens Geyer17c3ad92017-09-05 20:31:27 +0200203end;
204
205function TThriftStreamImpl.Read( const pBuf : Pointer; const buflen : Integer; offset: Integer; count: Integer): Integer;
206begin
Jens Geyerd5436f52014-10-03 19:50:38 +0200207 Result := 0;
Jens Geyer17c3ad92017-09-05 20:31:27 +0200208 CheckSizeAndOffset( pBuf, buflen, offset, count );
Jens Geyerd5436f52014-10-03 19:50:38 +0200209end;
210
211procedure TThriftStreamImpl.Write(const buffer: TBytes; offset, count: Integer);
212begin
Jens Geyera76e6c72017-09-08 21:03:30 +0200213 if Length(buffer) > 0
214 then Write( @buffer[0], offset, count);
Jens Geyer17c3ad92017-09-05 20:31:27 +0200215end;
216
217procedure TThriftStreamImpl.Write( const pBuf : Pointer; offset: Integer; count: Integer);
218begin
219 CheckSizeAndOffset( pBuf, offset+count, offset, count);
Jens Geyerd5436f52014-10-03 19:50:38 +0200220end;
221
222{ TThriftStreamAdapterDelphi }
223
224procedure TThriftStreamAdapterDelphi.Close;
225begin
226 FStream.Free;
227 FStream := nil;
228 FOwnsStream := False;
229end;
230
231constructor TThriftStreamAdapterDelphi.Create( const AStream: TStream; AOwnsStream: Boolean);
232begin
233 inherited Create;
234 FStream := AStream;
235 FOwnsStream := AOwnsStream;
236end;
237
238destructor TThriftStreamAdapterDelphi.Destroy;
239begin
Jens Geyer9f7f11e2016-04-14 21:37:11 +0200240 if FOwnsStream
241 then Close;
242
Jens Geyerd5436f52014-10-03 19:50:38 +0200243 inherited;
244end;
245
246procedure TThriftStreamAdapterDelphi.Flush;
247begin
Jens Geyer9f7f11e2016-04-14 21:37:11 +0200248 // nothing to do
Jens Geyerd5436f52014-10-03 19:50:38 +0200249end;
250
251function TThriftStreamAdapterDelphi.IsOpen: Boolean;
252begin
253 Result := FStream <> nil;
254end;
255
256procedure TThriftStreamAdapterDelphi.Open;
257begin
Jens Geyer9f7f11e2016-04-14 21:37:11 +0200258 // nothing to do
Jens Geyerd5436f52014-10-03 19:50:38 +0200259end;
260
Jens Geyer17c3ad92017-09-05 20:31:27 +0200261function TThriftStreamAdapterDelphi.Read(const pBuf : Pointer; const buflen : Integer; offset, count: Integer): Integer;
Jens Geyerd5436f52014-10-03 19:50:38 +0200262begin
263 inherited;
Jens Geyer17c3ad92017-09-05 20:31:27 +0200264
265 if count >= buflen-offset
266 then count := buflen-offset;
267
268 if count > 0
269 then Result := FStream.Read( PByteArray(pBuf)^[offset], count)
270 else Result := 0;
Jens Geyerd5436f52014-10-03 19:50:38 +0200271end;
272
273function TThriftStreamAdapterDelphi.ToArray: TBytes;
274var
275 OrgPos : Integer;
276 len : Integer;
277begin
278 len := 0;
279 if FStream <> nil then
280 begin
281 len := FStream.Size;
282 end;
283
284 SetLength( Result, len );
285
286 if len > 0 then
287 begin
288 OrgPos := FStream.Position;
289 try
290 FStream.Position := 0;
291 FStream.ReadBuffer( Pointer(@Result[0])^, len );
292 finally
293 FStream.Position := OrgPos;
294 end;
295 end
296end;
297
Jens Geyer17c3ad92017-09-05 20:31:27 +0200298procedure TThriftStreamAdapterDelphi.Write(const pBuf : Pointer; offset, count: Integer);
Jens Geyerd5436f52014-10-03 19:50:38 +0200299begin
300 inherited;
Jens Geyer9f7f11e2016-04-14 21:37:11 +0200301 if count > 0 then begin
Jens Geyer17c3ad92017-09-05 20:31:27 +0200302 FStream.Write( PByteArray(pBuf)^[offset], count)
Jens Geyerd5436f52014-10-03 19:50:38 +0200303 end;
304end;
305
306end.