blob: 7cb9219b677fa8ea521ecc55cfc8ff9686bc4b2d [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 Geyer17c3ad92017-09-05 20:31:27 +020040 ['{2A77D916-7446-46C1-8545-0AEC0008DBCA}']
41 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;
50 end;
51
52 TThriftStreamImpl = class( TInterfacedObject, IThriftStream)
Jens Geyerfad7fd32019-11-09 23:24:52 +010053 strict private
Jens Geyer17c3ad92017-09-05 20:31:27 +020054 procedure CheckSizeAndOffset( const pBuf : Pointer; const buflen : Integer; offset: Integer; count: Integer); overload;
Jens Geyerfad7fd32019-11-09 23:24:52 +010055 strict protected
Jens Geyer17c3ad92017-09-05 20:31:27 +020056 procedure Write( const buffer: TBytes; offset: Integer; count: Integer); overload; inline;
57 procedure Write( const pBuf : Pointer; offset: Integer; count: Integer); overload; virtual;
58 function Read( var buffer: TBytes; offset: Integer; count: Integer): Integer; overload; inline;
59 function Read( const pBuf : Pointer; const buflen : Integer; offset: Integer; count: Integer): Integer; overload; virtual;
Jens Geyerd5436f52014-10-03 19:50:38 +020060 procedure Open; virtual; abstract;
61 procedure Close; virtual; abstract;
62 procedure Flush; virtual; abstract;
63 function IsOpen: Boolean; virtual; abstract;
64 function ToArray: TBytes; virtual; abstract;
65 end;
66
67 TThriftStreamAdapterDelphi = class( TThriftStreamImpl )
Jens Geyerfad7fd32019-11-09 23:24:52 +010068 strict private
Jens Geyerd5436f52014-10-03 19:50:38 +020069 FStream : TStream;
70 FOwnsStream : Boolean;
Jens Geyerfad7fd32019-11-09 23:24:52 +010071 strict protected
Jens Geyer17c3ad92017-09-05 20:31:27 +020072 procedure Write( const pBuf : Pointer; offset: Integer; count: Integer); override;
73 function Read( const pBuf : Pointer; const buflen : Integer; offset: Integer; count: Integer): Integer; override;
Jens Geyerd5436f52014-10-03 19:50:38 +020074 procedure Open; override;
75 procedure Close; override;
76 procedure Flush; override;
77 function IsOpen: Boolean; override;
78 function ToArray: TBytes; override;
79 public
80 constructor Create( const AStream: TStream; AOwnsStream : Boolean);
81 destructor Destroy; override;
82 end;
83
84 TThriftStreamAdapterCOM = class( TThriftStreamImpl)
Jens Geyerfad7fd32019-11-09 23:24:52 +010085 strict private
Jens Geyerd5436f52014-10-03 19:50:38 +020086 FStream : IStream;
Jens Geyerfad7fd32019-11-09 23:24:52 +010087 strict protected
Jens Geyer17c3ad92017-09-05 20:31:27 +020088 procedure Write( const pBuf : Pointer; offset: Integer; count: Integer); override;
89 function Read( const pBuf : Pointer; const buflen : Integer; offset: Integer; count: Integer): Integer; override;
Jens Geyerd5436f52014-10-03 19:50:38 +020090 procedure Open; override;
91 procedure Close; override;
92 procedure Flush; override;
93 function IsOpen: Boolean; override;
94 function ToArray: TBytes; override;
95 public
96 constructor Create( const AStream: IStream);
97 end;
98
99implementation
100
101{ TThriftStreamAdapterCOM }
102
103procedure TThriftStreamAdapterCOM.Close;
104begin
105 FStream := nil;
106end;
107
108constructor TThriftStreamAdapterCOM.Create( const AStream: IStream);
109begin
110 inherited Create;
111 FStream := AStream;
112end;
113
114procedure TThriftStreamAdapterCOM.Flush;
115begin
Jens Geyer9f7f11e2016-04-14 21:37:11 +0200116 if IsOpen then begin
117 if FStream <> nil then begin
Jens Geyerd5436f52014-10-03 19:50:38 +0200118 FStream.Commit( STGC_DEFAULT );
119 end;
120 end;
121end;
122
123function TThriftStreamAdapterCOM.IsOpen: Boolean;
124begin
125 Result := FStream <> nil;
126end;
127
128procedure TThriftStreamAdapterCOM.Open;
129begin
Jens Geyer9f7f11e2016-04-14 21:37:11 +0200130 // nothing to do
Jens Geyerd5436f52014-10-03 19:50:38 +0200131end;
132
Jens Geyer17c3ad92017-09-05 20:31:27 +0200133function TThriftStreamAdapterCOM.Read( const pBuf : Pointer; const buflen : Integer; offset: Integer; count: Integer): Integer;
Jens Geyer5089b0a2018-02-01 22:37:18 +0100134var pTmp : PByte;
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 Geyer5089b0a2018-02-01 22:37:18 +0100144 pTmp := pBuf;
145 Inc( pTmp, offset);
146 FStream.Read( pTmp, count, @Result);
Jens Geyerd5436f52014-10-03 19:50:38 +0200147 end;
148 end;
149end;
150
151function TThriftStreamAdapterCOM.ToArray: TBytes;
152var
153 statstg: TStatStg;
154 len : Integer;
Nick4f5229e2016-04-14 16:43:22 +0300155 NewPos : {$IF CompilerVersion >= 29.0} UInt64 {$ELSE} Int64 {$IFEND};
Jens Geyerd5436f52014-10-03 19:50:38 +0200156 cbRead : Integer;
157begin
158 FillChar( statstg, SizeOf( statstg), 0);
159 len := 0;
Jens Geyer9f7f11e2016-04-14 21:37:11 +0200160 if IsOpen then begin
161 if Succeeded( FStream.Stat( statstg, STATFLAG_NONAME )) then begin
Jens Geyerd5436f52014-10-03 19:50:38 +0200162 len := statstg.cbSize;
163 end;
164 end;
165
166 SetLength( Result, len );
167
Jens Geyer9f7f11e2016-04-14 21:37:11 +0200168 if len > 0 then begin
169 if Succeeded( FStream.Seek( 0, STREAM_SEEK_SET, NewPos) ) then begin
Jens Geyerd5436f52014-10-03 19:50:38 +0200170 FStream.Read( @Result[0], len, @cbRead);
171 end;
172 end;
173end;
174
Jens Geyer17c3ad92017-09-05 20:31:27 +0200175procedure TThriftStreamAdapterCOM.Write( const pBuf: Pointer; offset: Integer; count: Integer);
Jens Geyer9f7f11e2016-04-14 21:37:11 +0200176var nWritten : Integer;
Jens Geyer5089b0a2018-02-01 22:37:18 +0100177 pTmp : PByte;
Jens Geyerd5436f52014-10-03 19:50:38 +0200178begin
179 inherited;
Jens Geyer9f7f11e2016-04-14 21:37:11 +0200180 if IsOpen then begin
181 if count > 0 then begin
Jens Geyer5089b0a2018-02-01 22:37:18 +0100182 pTmp := pBuf;
183 Inc( pTmp, offset);
184 FStream.Write( pTmp, count, @nWritten);
Jens Geyerd5436f52014-10-03 19:50:38 +0200185 end;
186 end;
187end;
188
189{ TThriftStreamImpl }
190
Jens Geyer17c3ad92017-09-05 20:31:27 +0200191procedure TThriftStreamImpl.CheckSizeAndOffset( const pBuf : Pointer; const buflen : Integer; offset: Integer; count: Integer);
Jens Geyerd5436f52014-10-03 19:50:38 +0200192begin
Jens Geyer9f7f11e2016-04-14 21:37:11 +0200193 if count > 0 then begin
Jens Geyer17c3ad92017-09-05 20:31:27 +0200194 if (offset < 0) or ( offset >= buflen) then begin
Jens Geyerd5436f52014-10-03 19:50:38 +0200195 raise ERangeError.Create( SBitsIndexError );
196 end;
Jens Geyer17c3ad92017-09-05 20:31:27 +0200197 if count > buflen then begin
Jens Geyerd5436f52014-10-03 19:50:38 +0200198 raise ERangeError.Create( SBitsIndexError );
199 end;
200 end;
201end;
202
Jens Geyer9f7f11e2016-04-14 21:37:11 +0200203function TThriftStreamImpl.Read(var buffer: TBytes; offset, count: Integer): Integer;
Jens Geyerd5436f52014-10-03 19:50:38 +0200204begin
Jens Geyera76e6c72017-09-08 21:03:30 +0200205 if Length(buffer) > 0
206 then Result := Read( @buffer[0], Length(buffer), offset, count)
207 else Result := 0;
Jens Geyer17c3ad92017-09-05 20:31:27 +0200208end;
209
210function TThriftStreamImpl.Read( const pBuf : Pointer; const buflen : Integer; offset: Integer; count: Integer): Integer;
211begin
Jens Geyerd5436f52014-10-03 19:50:38 +0200212 Result := 0;
Jens Geyer17c3ad92017-09-05 20:31:27 +0200213 CheckSizeAndOffset( pBuf, buflen, offset, count );
Jens Geyerd5436f52014-10-03 19:50:38 +0200214end;
215
216procedure TThriftStreamImpl.Write(const buffer: TBytes; offset, count: Integer);
217begin
Jens Geyera76e6c72017-09-08 21:03:30 +0200218 if Length(buffer) > 0
219 then Write( @buffer[0], offset, count);
Jens Geyer17c3ad92017-09-05 20:31:27 +0200220end;
221
222procedure TThriftStreamImpl.Write( const pBuf : Pointer; offset: Integer; count: Integer);
223begin
224 CheckSizeAndOffset( pBuf, offset+count, offset, count);
Jens Geyerd5436f52014-10-03 19:50:38 +0200225end;
226
227{ TThriftStreamAdapterDelphi }
228
229procedure TThriftStreamAdapterDelphi.Close;
230begin
231 FStream.Free;
232 FStream := nil;
233 FOwnsStream := False;
234end;
235
236constructor TThriftStreamAdapterDelphi.Create( const AStream: TStream; AOwnsStream: Boolean);
237begin
238 inherited Create;
239 FStream := AStream;
240 FOwnsStream := AOwnsStream;
241end;
242
243destructor TThriftStreamAdapterDelphi.Destroy;
244begin
Jens Geyer9f7f11e2016-04-14 21:37:11 +0200245 if FOwnsStream
246 then Close;
247
Jens Geyerd5436f52014-10-03 19:50:38 +0200248 inherited;
249end;
250
251procedure TThriftStreamAdapterDelphi.Flush;
252begin
Jens Geyer9f7f11e2016-04-14 21:37:11 +0200253 // nothing to do
Jens Geyerd5436f52014-10-03 19:50:38 +0200254end;
255
256function TThriftStreamAdapterDelphi.IsOpen: Boolean;
257begin
258 Result := FStream <> nil;
259end;
260
261procedure TThriftStreamAdapterDelphi.Open;
262begin
Jens Geyer9f7f11e2016-04-14 21:37:11 +0200263 // nothing to do
Jens Geyerd5436f52014-10-03 19:50:38 +0200264end;
265
Jens Geyer17c3ad92017-09-05 20:31:27 +0200266function TThriftStreamAdapterDelphi.Read(const pBuf : Pointer; const buflen : Integer; offset, count: Integer): Integer;
Jens Geyer5089b0a2018-02-01 22:37:18 +0100267var pTmp : PByte;
Jens Geyerd5436f52014-10-03 19:50:38 +0200268begin
269 inherited;
Jens Geyer17c3ad92017-09-05 20:31:27 +0200270
271 if count >= buflen-offset
272 then count := buflen-offset;
273
Jens Geyer5089b0a2018-02-01 22:37:18 +0100274 if count > 0 then begin
275 pTmp := pBuf;
276 Inc( pTmp, offset);
277 Result := FStream.Read( pTmp^, count)
278 end
Jens Geyer17c3ad92017-09-05 20:31:27 +0200279 else Result := 0;
Jens Geyerd5436f52014-10-03 19:50:38 +0200280end;
281
282function TThriftStreamAdapterDelphi.ToArray: TBytes;
283var
284 OrgPos : Integer;
285 len : Integer;
286begin
287 len := 0;
288 if FStream <> nil then
289 begin
290 len := FStream.Size;
291 end;
292
293 SetLength( Result, len );
294
295 if len > 0 then
296 begin
297 OrgPos := FStream.Position;
298 try
299 FStream.Position := 0;
300 FStream.ReadBuffer( Pointer(@Result[0])^, len );
301 finally
302 FStream.Position := OrgPos;
303 end;
304 end
305end;
306
Jens Geyer17c3ad92017-09-05 20:31:27 +0200307procedure TThriftStreamAdapterDelphi.Write(const pBuf : Pointer; offset, count: Integer);
Jens Geyer5089b0a2018-02-01 22:37:18 +0100308var pTmp : PByte;
Jens Geyerd5436f52014-10-03 19:50:38 +0200309begin
310 inherited;
Jens Geyer9f7f11e2016-04-14 21:37:11 +0200311 if count > 0 then begin
Jens Geyer5089b0a2018-02-01 22:37:18 +0100312 pTmp := pBuf;
313 Inc( pTmp, offset);
314 FStream.Write( pTmp^, count)
Jens Geyerd5436f52014-10-03 19:50:38 +0200315 end;
316end;
317
318end.