1 (*
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
20 unit Thrift.Stream;
21
22 {$I Thrift.Defines.inc}
23
24 interface
25
26 uses
27 Classes,
28 SysUtils,
29 SysConst,
30 RTLConsts,
31 {$IFDEF OLD_UNIT_NAMES}
32 ActiveX,
33 {$ELSE}
34 Winapi.ActiveX,
35 {$ENDIF}
36 Thrift.Utils;
37
38 type
39 IThriftStream = interface
40 ['{3A61A8A6-3639-4B91-A260-EFCA23944F3A}']
41 procedure Write( const buffer: TBytes; offset: Integer; count: Integer); overload;
42 procedure Write( const pBuf : Pointer; offset: Integer; count: Integer); overload;
Readnull43 function Read( var buffer: TBytes; offset: Integer; count: Integer): Integer; overload;
Readnull44 function Read( const pBuf : Pointer; const buflen : Integer; offset: Integer; count: Integer): Integer; overload;
45 procedure Open;
46 procedure Close;
47 procedure Flush;
IsOpennull48 function IsOpen: Boolean;
ToArraynull49 function ToArray: TBytes;
Sizenull50 function Size : Int64;
Positionnull51 function Position : Int64;
52 end;
53
54
55 TThriftStreamImpl = class abstract( TInterfacedObject, IThriftStream)
56 strict private
57 procedure CheckSizeAndOffset( const pBuf : Pointer; const buflen : Integer; offset: Integer; count: Integer); overload;
58 strict protected
59 // IThriftStream
60 procedure Write( const buffer: TBytes; offset: Integer; count: Integer); overload; inline;
61 procedure Write( const pBuf : Pointer; offset: Integer; count: Integer); overload; virtual;
Readnull62 function Read( var buffer: TBytes; offset: Integer; count: Integer): Integer; overload; inline;
Readnull63 function Read( const pBuf : Pointer; const buflen : Integer; offset: Integer; count: Integer): Integer; overload; virtual;
64 procedure Open; virtual; abstract;
65 procedure Close; virtual; abstract;
66 procedure Flush; virtual; abstract;
IsOpennull67 function IsOpen: Boolean; virtual; abstract;
ToArraynull68 function ToArray: TBytes; virtual; abstract;
Sizenull69 function Size : Int64; virtual;
Positionnull70 function Position : Int64; virtual;
71 end;
72
73 TThriftStreamAdapterDelphi = class( TThriftStreamImpl)
74 strict private
75 FStream : TStream;
76 FOwnsStream : Boolean;
77 strict protected
78 // IThriftStream
79 procedure Write( const pBuf : Pointer; offset: Integer; count: Integer); override;
Readnull80 function Read( const pBuf : Pointer; const buflen : Integer; offset: Integer; count: Integer): Integer; override;
81 procedure Open; override;
82 procedure Close; override;
83 procedure Flush; override;
IsOpennull84 function IsOpen: Boolean; override;
ToArraynull85 function ToArray: TBytes; override;
Sizenull86 function Size : Int64; override;
Positionnull87 function Position : Int64; override;
88 public
89 constructor Create( const aStream: TStream; aOwnsStream : Boolean);
90 destructor Destroy; override;
91 end;
92
93 TThriftStreamAdapterCOM = class( TThriftStreamImpl)
94 strict private
95 FStream : IStream;
96 strict protected
97 // IThriftStream
98 procedure Write( const pBuf : Pointer; offset: Integer; count: Integer); override;
Readnull99 function Read( const pBuf : Pointer; const buflen : Integer; offset: Integer; count: Integer): Integer; override;
100 procedure Open; override;
101 procedure Close; override;
102 procedure Flush; override;
IsOpennull103 function IsOpen: Boolean; override;
ToArraynull104 function ToArray: TBytes; override;
Sizenull105 function Size : Int64; override;
Positionnull106 function Position : Int64; override;
107 public
108 constructor Create( const aStream: IStream);
109 end;
110
111 implementation
112
113 uses Thrift.Transport;
114
115 { TThriftStreamAdapterCOM }
116
117 procedure TThriftStreamAdapterCOM.Close;
118 begin
119 FStream := nil;
120 end;
121
122 constructor TThriftStreamAdapterCOM.Create( const aStream: IStream);
123 begin
124 inherited Create;
125 FStream := aStream;
126 end;
127
128 procedure TThriftStreamAdapterCOM.Flush;
129 begin
130 if IsOpen then begin
131 if FStream <> nil then begin
132 FStream.Commit( STGC_DEFAULT );
133 end;
134 end;
135 end;
136
Sizenull137 function TThriftStreamAdapterCOM.Size : Int64;
138 var statstg: TStatStg;
139 begin
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;
145 end;
146
TThriftStreamAdapterCOM.Positionnull147 function TThriftStreamAdapterCOM.Position : Int64;
148 var newpos : {$IF CompilerVersion >= 29.0} UInt64 {$ELSE} Int64 {$IFEND};
149 begin
150 if SUCCEEDED( FStream.Seek( 0, STREAM_SEEK_CUR, newpos))
151 then result := Int64(newpos)
152 else raise TTransportExceptionEndOfFile.Create('Seek() error');
153 end;
154
TThriftStreamAdapterCOM.IsOpennull155 function TThriftStreamAdapterCOM.IsOpen: Boolean;
156 begin
157 Result := FStream <> nil;
158 end;
159
160 procedure TThriftStreamAdapterCOM.Open;
161 begin
162 // nothing to do
163 end;
164
Readnull165 function TThriftStreamAdapterCOM.Read( const pBuf : Pointer; const buflen : Integer; offset: Integer; count: Integer): Integer;
166 var pTmp : PByte;
167 begin
168 inherited;
169
170 if count >= buflen-offset
171 then count := buflen-offset;
172
173 Result := 0;
174 if FStream <> nil then begin
175 if count > 0 then begin
176 pTmp := pBuf;
177 Inc( pTmp, offset);
178 FStream.Read( pTmp, count, @Result);
179 end;
180 end;
181 end;
182
ToArraynull183 function TThriftStreamAdapterCOM.ToArray: TBytes;
184 var
185 len : Int64;
186 NewPos : {$IF CompilerVersion >= 29.0} UInt64 {$ELSE} Int64 {$IFEND};
187 cbRead : Integer;
188 begin
189 len := Self.Size;
190 SetLength( Result, len );
191
192 if len > 0 then begin
193 if Succeeded( FStream.Seek( 0, STREAM_SEEK_SET, NewPos) ) then begin
194 FStream.Read( @Result[0], len, @cbRead);
195 end;
196 end;
197 end;
198
199 procedure TThriftStreamAdapterCOM.Write( const pBuf: Pointer; offset: Integer; count: Integer);
200 var nWritten : Integer;
201 pTmp : PByte;
202 begin
203 inherited;
204 if IsOpen then begin
205 if count > 0 then begin
206 pTmp := pBuf;
207 Inc( pTmp, offset);
208 FStream.Write( pTmp, count, @nWritten);
209 end;
210 end;
211 end;
212
213 { TThriftStreamImpl }
214
215 procedure TThriftStreamImpl.CheckSizeAndOffset( const pBuf : Pointer; const buflen : Integer; offset: Integer; count: Integer);
216 begin
217 if count > 0 then begin
218 if (offset < 0) or ( offset >= buflen) then begin
219 raise ERangeError.Create( SBitsIndexError );
220 end;
221 if count > buflen then begin
222 raise ERangeError.Create( SBitsIndexError );
223 end;
224 end;
225 end;
226
Readnull227 function TThriftStreamImpl.Read(var buffer: TBytes; offset, count: Integer): Integer;
228 begin
229 if Length(buffer) > 0
230 then Result := Read( @buffer[0], Length(buffer), offset, count)
231 else Result := 0;
232 end;
233
Readnull234 function TThriftStreamImpl.Read( const pBuf : Pointer; const buflen : Integer; offset: Integer; count: Integer): Integer;
235 begin
236 Result := 0;
237 CheckSizeAndOffset( pBuf, buflen, offset, count );
238 end;
239
240 procedure TThriftStreamImpl.Write(const buffer: TBytes; offset, count: Integer);
241 begin
242 if Length(buffer) > 0
243 then Write( @buffer[0], offset, count);
244 end;
245
246 procedure TThriftStreamImpl.Write( const pBuf : Pointer; offset: Integer; count: Integer);
247 begin
248 CheckSizeAndOffset( pBuf, offset+count, offset, count);
249 end;
250
Sizenull251 function TThriftStreamImpl.Size : Int64;
252 begin
253 ASSERT(FALSE);
254 raise ENotImplemented.Create(ClassName+'.Size');
255 end;
256
Positionnull257 function TThriftStreamImpl.Position : Int64;
258 begin
259 ASSERT(FALSE);
260 raise ENotImplemented.Create(ClassName+'.Position');
261 end;
262
263
264 { TThriftStreamAdapterDelphi }
265
266 constructor TThriftStreamAdapterDelphi.Create( const aStream: TStream; aOwnsStream: Boolean);
267 begin
268 inherited Create;
269 FStream := aStream;
270 FOwnsStream := aOwnsStream;
271 end;
272
273 destructor TThriftStreamAdapterDelphi.Destroy;
274 begin
275 if FOwnsStream
276 then Close;
277
278 inherited;
279 end;
280
281 procedure TThriftStreamAdapterDelphi.Close;
282 begin
283 FStream.Free;
284 FStream := nil;
285 FOwnsStream := False;
286 end;
287
288 procedure TThriftStreamAdapterDelphi.Flush;
289 begin
290 // nothing to do
291 end;
292
Sizenull293 function TThriftStreamAdapterDelphi.Size : Int64;
294 begin
295 result := FStream.Size;
296 end;
297
TThriftStreamAdapterDelphi.Positionnull298 function TThriftStreamAdapterDelphi.Position : Int64;
299 begin
300 result := FStream.Position;
301 end;
302
TThriftStreamAdapterDelphi.IsOpennull303 function TThriftStreamAdapterDelphi.IsOpen: Boolean;
304 begin
305 Result := FStream <> nil;
306 end;
307
308 procedure TThriftStreamAdapterDelphi.Open;
309 begin
310 // nothing to do
311 end;
312
Readnull313 function TThriftStreamAdapterDelphi.Read(const pBuf : Pointer; const buflen : Integer; offset, count: Integer): Integer;
314 var pTmp : PByte;
315 begin
316 inherited;
317
318 if count >= buflen-offset
319 then count := buflen-offset;
320
321 if count > 0 then begin
322 pTmp := pBuf;
323 Inc( pTmp, offset);
324 Result := FStream.Read( pTmp^, count)
325 end
326 else Result := 0;
327 end;
328
ToArraynull329 function TThriftStreamAdapterDelphi.ToArray: TBytes;
330 var
331 OrgPos : Integer;
332 len : Integer;
333 begin
334 if FStream <> nil
335 then len := FStream.Size
336 else len := 0;
337
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
350 end;
351
352 procedure TThriftStreamAdapterDelphi.Write(const pBuf : Pointer; offset, count: Integer);
353 var pTmp : PByte;
354 begin
355 inherited;
356 if count > 0 then begin
357 pTmp := pBuf;
358 Inc( pTmp, offset);
359 FStream.Write( pTmp^, count)
360 end;
361 end;
362
363 end.
364