blob: 16680591c9f80102ab4f8bdf3b0cd6377ed17612 [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
Jens Geyerd5436f52014-10-03 19:50:38 +020039 IThriftStream = interface
Jens Geyera019cda2019-11-09 23:24:52 +010040 ['{3A61A8A6-3639-4B91-A260-EFCA23944F3A}']
Jens Geyer17c3ad92017-09-05 20:31:27 +020041 procedure Write( const buffer: TBytes; offset: Integer; count: Integer); overload;
42 procedure Write( const pBuf : Pointer; offset: Integer; count: Integer); overload;
43 function Read( var buffer: TBytes; offset: Integer; count: Integer): Integer; overload;
44 function Read( const pBuf : Pointer; const buflen : Integer; offset: Integer; count: Integer): Integer; overload;
Jens Geyerd5436f52014-10-03 19:50:38 +020045 procedure Open;
46 procedure Close;
47 procedure Flush;
48 function IsOpen: Boolean;
49 function ToArray: TBytes;
Jens Geyer41f47af2019-11-09 23:24:52 +010050 function Size : Int64;
51 function Position : Int64;
52 end;
53
54
55 TThriftStreamImpl = class abstract( TInterfacedObject, IThriftStream)
Jens Geyerfad7fd32019-11-09 23:24:52 +010056 strict private
Jens Geyer17c3ad92017-09-05 20:31:27 +020057 procedure CheckSizeAndOffset( const pBuf : Pointer; const buflen : Integer; offset: Integer; count: Integer); overload;
Jens Geyerfad7fd32019-11-09 23:24:52 +010058 strict protected
Jens Geyer41f47af2019-11-09 23:24:52 +010059 // IThriftStream
Jens Geyer17c3ad92017-09-05 20:31:27 +020060 procedure Write( const buffer: TBytes; offset: Integer; count: Integer); overload; inline;
61 procedure Write( const pBuf : Pointer; offset: Integer; count: Integer); overload; virtual;
62 function Read( var buffer: TBytes; offset: Integer; count: Integer): Integer; overload; inline;
63 function Read( const pBuf : Pointer; const buflen : Integer; offset: Integer; count: Integer): Integer; overload; virtual;
Jens Geyerd5436f52014-10-03 19:50:38 +020064 procedure Open; virtual; abstract;
65 procedure Close; virtual; abstract;
66 procedure Flush; virtual; abstract;
67 function IsOpen: Boolean; virtual; abstract;
68 function ToArray: TBytes; virtual; abstract;
Jens Geyera019cda2019-11-09 23:24:52 +010069 function Size : Int64; virtual;
70 function Position : Int64; virtual;
Jens Geyerd5436f52014-10-03 19:50:38 +020071 end;
72
Jens Geyera019cda2019-11-09 23:24:52 +010073 TThriftStreamAdapterDelphi = class( TThriftStreamImpl)
Jens Geyerfad7fd32019-11-09 23:24:52 +010074 strict private
Jens Geyerd5436f52014-10-03 19:50:38 +020075 FStream : TStream;
76 FOwnsStream : Boolean;
Jens Geyerfad7fd32019-11-09 23:24:52 +010077 strict protected
Jens Geyer41f47af2019-11-09 23:24:52 +010078 // IThriftStream
Jens Geyer17c3ad92017-09-05 20:31:27 +020079 procedure Write( const pBuf : Pointer; offset: Integer; count: Integer); override;
80 function Read( const pBuf : Pointer; const buflen : Integer; offset: Integer; count: Integer): Integer; override;
Jens Geyerd5436f52014-10-03 19:50:38 +020081 procedure Open; override;
82 procedure Close; override;
83 procedure Flush; override;
84 function IsOpen: Boolean; override;
85 function ToArray: TBytes; override;
Jens Geyera019cda2019-11-09 23:24:52 +010086 function Size : Int64; override;
87 function Position : Int64; override;
Jens Geyerd5436f52014-10-03 19:50:38 +020088 public
Jens Geyer41f47af2019-11-09 23:24:52 +010089 constructor Create( const aStream: TStream; aOwnsStream : Boolean);
Jens Geyerd5436f52014-10-03 19:50:38 +020090 destructor Destroy; override;
91 end;
92
Jens Geyera019cda2019-11-09 23:24:52 +010093 TThriftStreamAdapterCOM = class( TThriftStreamImpl)
Jens Geyerfad7fd32019-11-09 23:24:52 +010094 strict private
Jens Geyerd5436f52014-10-03 19:50:38 +020095 FStream : IStream;
Jens Geyerfad7fd32019-11-09 23:24:52 +010096 strict protected
Jens Geyer41f47af2019-11-09 23:24:52 +010097 // IThriftStream
Jens Geyer17c3ad92017-09-05 20:31:27 +020098 procedure Write( const pBuf : Pointer; offset: Integer; count: Integer); override;
99 function Read( const pBuf : Pointer; const buflen : Integer; offset: Integer; count: Integer): Integer; override;
Jens Geyerd5436f52014-10-03 19:50:38 +0200100 procedure Open; override;
101 procedure Close; override;
102 procedure Flush; override;
103 function IsOpen: Boolean; override;
104 function ToArray: TBytes; override;
Jens Geyera019cda2019-11-09 23:24:52 +0100105 function Size : Int64; override;
106 function Position : Int64; override;
Jens Geyerd5436f52014-10-03 19:50:38 +0200107 public
Jens Geyer41f47af2019-11-09 23:24:52 +0100108 constructor Create( const aStream: IStream);
Jens Geyerd5436f52014-10-03 19:50:38 +0200109 end;
110
111implementation
112
Jens Geyer41f47af2019-11-09 23:24:52 +0100113uses Thrift.Transport;
114
Jens Geyerd5436f52014-10-03 19:50:38 +0200115{ TThriftStreamAdapterCOM }
116
117procedure TThriftStreamAdapterCOM.Close;
118begin
119 FStream := nil;
120end;
121
Jens Geyer41f47af2019-11-09 23:24:52 +0100122constructor TThriftStreamAdapterCOM.Create( const aStream: IStream);
Jens Geyerd5436f52014-10-03 19:50:38 +0200123begin
124 inherited Create;
Jens Geyer41f47af2019-11-09 23:24:52 +0100125 FStream := aStream;
Jens Geyerd5436f52014-10-03 19:50:38 +0200126end;
127
128procedure TThriftStreamAdapterCOM.Flush;
129begin
Jens Geyer9f7f11e2016-04-14 21:37:11 +0200130 if IsOpen then begin
131 if FStream <> nil then begin
Jens Geyerd5436f52014-10-03 19:50:38 +0200132 FStream.Commit( STGC_DEFAULT );
133 end;
134 end;
135end;
136
Jens Geyer41f47af2019-11-09 23:24:52 +0100137function TThriftStreamAdapterCOM.Size : Int64;
138var statstg: TStatStg;
139begin
140 FillChar( statstg, SizeOf( statstg), 0);
141 if IsOpen
142 and Succeeded( FStream.Stat( statstg, STATFLAG_NONAME ))
143 then result := statstg.cbSize
144 else result := 0;
145end;
146
147function TThriftStreamAdapterCOM.Position : Int64;
148var newpos : {$IF CompilerVersion >= 29.0} UInt64 {$ELSE} Int64 {$IFEND};
149begin
150 if SUCCEEDED( FStream.Seek( 0, STREAM_SEEK_CUR, newpos))
151 then result := Int64(newpos)
152 else raise TTransportExceptionEndOfFile.Create('Seek() error');
153end;
154
Jens Geyerd5436f52014-10-03 19:50:38 +0200155function TThriftStreamAdapterCOM.IsOpen: Boolean;
156begin
157 Result := FStream <> nil;
158end;
159
160procedure TThriftStreamAdapterCOM.Open;
161begin
Jens Geyer9f7f11e2016-04-14 21:37:11 +0200162 // nothing to do
Jens Geyerd5436f52014-10-03 19:50:38 +0200163end;
164
Jens Geyer17c3ad92017-09-05 20:31:27 +0200165function TThriftStreamAdapterCOM.Read( const pBuf : Pointer; const buflen : Integer; offset: Integer; count: Integer): Integer;
Jens Geyer5089b0a2018-02-01 22:37:18 +0100166var pTmp : PByte;
Jens Geyerd5436f52014-10-03 19:50:38 +0200167begin
168 inherited;
Jens Geyer17c3ad92017-09-05 20:31:27 +0200169
170 if count >= buflen-offset
171 then count := buflen-offset;
172
Jens Geyerd5436f52014-10-03 19:50:38 +0200173 Result := 0;
Jens Geyer9f7f11e2016-04-14 21:37:11 +0200174 if FStream <> nil then begin
175 if count > 0 then begin
Jens Geyer5089b0a2018-02-01 22:37:18 +0100176 pTmp := pBuf;
177 Inc( pTmp, offset);
178 FStream.Read( pTmp, count, @Result);
Jens Geyerd5436f52014-10-03 19:50:38 +0200179 end;
180 end;
181end;
182
183function TThriftStreamAdapterCOM.ToArray: TBytes;
184var
Jens Geyer41f47af2019-11-09 23:24:52 +0100185 len : Int64;
Nick4f5229e2016-04-14 16:43:22 +0300186 NewPos : {$IF CompilerVersion >= 29.0} UInt64 {$ELSE} Int64 {$IFEND};
Jens Geyerd5436f52014-10-03 19:50:38 +0200187 cbRead : Integer;
188begin
Jens Geyer41f47af2019-11-09 23:24:52 +0100189 len := Self.Size;
Jens Geyerd5436f52014-10-03 19:50:38 +0200190 SetLength( Result, len );
191
Jens Geyer9f7f11e2016-04-14 21:37:11 +0200192 if len > 0 then begin
193 if Succeeded( FStream.Seek( 0, STREAM_SEEK_SET, NewPos) ) then begin
Jens Geyerd5436f52014-10-03 19:50:38 +0200194 FStream.Read( @Result[0], len, @cbRead);
195 end;
196 end;
197end;
198
Jens Geyer17c3ad92017-09-05 20:31:27 +0200199procedure TThriftStreamAdapterCOM.Write( const pBuf: Pointer; offset: Integer; count: Integer);
Jens Geyer9f7f11e2016-04-14 21:37:11 +0200200var nWritten : Integer;
Jens Geyer5089b0a2018-02-01 22:37:18 +0100201 pTmp : PByte;
Jens Geyerd5436f52014-10-03 19:50:38 +0200202begin
203 inherited;
Jens Geyer9f7f11e2016-04-14 21:37:11 +0200204 if IsOpen then begin
205 if count > 0 then begin
Jens Geyer5089b0a2018-02-01 22:37:18 +0100206 pTmp := pBuf;
207 Inc( pTmp, offset);
208 FStream.Write( pTmp, count, @nWritten);
Jens Geyerd5436f52014-10-03 19:50:38 +0200209 end;
210 end;
211end;
212
213{ TThriftStreamImpl }
214
Jens Geyer17c3ad92017-09-05 20:31:27 +0200215procedure TThriftStreamImpl.CheckSizeAndOffset( const pBuf : Pointer; const buflen : Integer; offset: Integer; count: Integer);
Jens Geyerd5436f52014-10-03 19:50:38 +0200216begin
Jens Geyer9f7f11e2016-04-14 21:37:11 +0200217 if count > 0 then begin
Jens Geyer17c3ad92017-09-05 20:31:27 +0200218 if (offset < 0) or ( offset >= buflen) then begin
Jens Geyerd5436f52014-10-03 19:50:38 +0200219 raise ERangeError.Create( SBitsIndexError );
220 end;
Jens Geyer17c3ad92017-09-05 20:31:27 +0200221 if count > buflen then begin
Jens Geyerd5436f52014-10-03 19:50:38 +0200222 raise ERangeError.Create( SBitsIndexError );
223 end;
224 end;
225end;
226
Jens Geyer9f7f11e2016-04-14 21:37:11 +0200227function TThriftStreamImpl.Read(var buffer: TBytes; offset, count: Integer): Integer;
Jens Geyerd5436f52014-10-03 19:50:38 +0200228begin
Jens Geyera76e6c72017-09-08 21:03:30 +0200229 if Length(buffer) > 0
230 then Result := Read( @buffer[0], Length(buffer), offset, count)
231 else Result := 0;
Jens Geyer17c3ad92017-09-05 20:31:27 +0200232end;
233
234function TThriftStreamImpl.Read( const pBuf : Pointer; const buflen : Integer; offset: Integer; count: Integer): Integer;
235begin
Jens Geyerd5436f52014-10-03 19:50:38 +0200236 Result := 0;
Jens Geyer17c3ad92017-09-05 20:31:27 +0200237 CheckSizeAndOffset( pBuf, buflen, offset, count );
Jens Geyerd5436f52014-10-03 19:50:38 +0200238end;
239
240procedure TThriftStreamImpl.Write(const buffer: TBytes; offset, count: Integer);
241begin
Jens Geyera76e6c72017-09-08 21:03:30 +0200242 if Length(buffer) > 0
243 then Write( @buffer[0], offset, count);
Jens Geyer17c3ad92017-09-05 20:31:27 +0200244end;
245
246procedure TThriftStreamImpl.Write( const pBuf : Pointer; offset: Integer; count: Integer);
247begin
248 CheckSizeAndOffset( pBuf, offset+count, offset, count);
Jens Geyerd5436f52014-10-03 19:50:38 +0200249end;
250
Jens Geyera019cda2019-11-09 23:24:52 +0100251function TThriftStreamImpl.Size : Int64;
252begin
253 ASSERT(FALSE);
254 raise ENotImplemented.Create(ClassName+'.Size');
255end;
256
257function TThriftStreamImpl.Position : Int64;
258begin
259 ASSERT(FALSE);
260 raise ENotImplemented.Create(ClassName+'.Position');
261end;
262
263
Jens Geyerd5436f52014-10-03 19:50:38 +0200264{ TThriftStreamAdapterDelphi }
265
Jens Geyer41f47af2019-11-09 23:24:52 +0100266constructor TThriftStreamAdapterDelphi.Create( const aStream: TStream; aOwnsStream: Boolean);
267begin
268 inherited Create;
269 FStream := aStream;
270 FOwnsStream := aOwnsStream;
271end;
272
273destructor TThriftStreamAdapterDelphi.Destroy;
274begin
275 if FOwnsStream
276 then Close;
277
278 inherited;
279end;
280
Jens Geyerd5436f52014-10-03 19:50:38 +0200281procedure TThriftStreamAdapterDelphi.Close;
282begin
283 FStream.Free;
284 FStream := nil;
285 FOwnsStream := False;
286end;
287
Jens Geyerd5436f52014-10-03 19:50:38 +0200288procedure TThriftStreamAdapterDelphi.Flush;
289begin
Jens Geyer9f7f11e2016-04-14 21:37:11 +0200290 // nothing to do
Jens Geyerd5436f52014-10-03 19:50:38 +0200291end;
292
Jens Geyer41f47af2019-11-09 23:24:52 +0100293function TThriftStreamAdapterDelphi.Size : Int64;
294begin
295 result := FStream.Size;
296end;
297
298function TThriftStreamAdapterDelphi.Position : Int64;
299begin
300 result := FStream.Position;
301end;
302
Jens Geyerd5436f52014-10-03 19:50:38 +0200303function TThriftStreamAdapterDelphi.IsOpen: Boolean;
304begin
305 Result := FStream <> nil;
306end;
307
308procedure TThriftStreamAdapterDelphi.Open;
309begin
Jens Geyer9f7f11e2016-04-14 21:37:11 +0200310 // nothing to do
Jens Geyerd5436f52014-10-03 19:50:38 +0200311end;
312
Jens Geyer17c3ad92017-09-05 20:31:27 +0200313function TThriftStreamAdapterDelphi.Read(const pBuf : Pointer; const buflen : Integer; offset, count: Integer): Integer;
Jens Geyer5089b0a2018-02-01 22:37:18 +0100314var pTmp : PByte;
Jens Geyerd5436f52014-10-03 19:50:38 +0200315begin
316 inherited;
Jens Geyer17c3ad92017-09-05 20:31:27 +0200317
318 if count >= buflen-offset
319 then count := buflen-offset;
320
Jens Geyer5089b0a2018-02-01 22:37:18 +0100321 if count > 0 then begin
322 pTmp := pBuf;
323 Inc( pTmp, offset);
324 Result := FStream.Read( pTmp^, count)
325 end
Jens Geyer17c3ad92017-09-05 20:31:27 +0200326 else Result := 0;
Jens Geyerd5436f52014-10-03 19:50:38 +0200327end;
328
329function TThriftStreamAdapterDelphi.ToArray: TBytes;
330var
331 OrgPos : Integer;
332 len : Integer;
333begin
Jens Geyer41f47af2019-11-09 23:24:52 +0100334 if FStream <> nil
335 then len := FStream.Size
336 else len := 0;
Jens Geyerd5436f52014-10-03 19:50:38 +0200337
338 SetLength( Result, len );
339
340 if len > 0 then
341 begin
342 OrgPos := FStream.Position;
343 try
344 FStream.Position := 0;
345 FStream.ReadBuffer( Pointer(@Result[0])^, len );
346 finally
347 FStream.Position := OrgPos;
348 end;
349 end
350end;
351
Jens Geyer17c3ad92017-09-05 20:31:27 +0200352procedure TThriftStreamAdapterDelphi.Write(const pBuf : Pointer; offset, count: Integer);
Jens Geyer5089b0a2018-02-01 22:37:18 +0100353var pTmp : PByte;
Jens Geyerd5436f52014-10-03 19:50:38 +0200354begin
355 inherited;
Jens Geyer9f7f11e2016-04-14 21:37:11 +0200356 if count > 0 then begin
Jens Geyer5089b0a2018-02-01 22:37:18 +0100357 pTmp := pBuf;
358 Inc( pTmp, offset);
359 FStream.Write( pTmp^, count)
Jens Geyerd5436f52014-10-03 19:50:38 +0200360 end;
361end;
362
363end.