-
Notifications
You must be signed in to change notification settings - Fork 48
/
Copy pathChunkedFileStream.pas
96 lines (80 loc) · 2.44 KB
/
ChunkedFileStream.pas
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
unit ChunkedFileStream;
interface
uses System.Classes, System.SysUtils;
type
TChunkedFileStream = class(TStream)
private
FStartPos, FSize: Int64;
FileStream: TBufferedFileStream;
protected
function GetSize(): Int64; override;
public
property Size: Int64 read GetSize;
constructor Create(const AFileName: string; Mode: Word; ChunkStart, ChunkSize: Int64);
destructor Destroy; override;
function Read(var Buffer; Count: Longint): Longint; override;
function Write(const Buffer; Count: Longint): Longint; override;
function Seek(const Offset: Int64; Origin: TSeekOrigin): Int64; override;
end;
implementation
{TChunkedFileStream}
constructor TChunkedFileStream.Create(const AFileName: string; Mode: Word; ChunkStart, ChunkSize: Int64);
var
FileSize: Int64;
begin
inherited Create;
self.FileStream := TBufferedFileStream.Create(AFileName, Mode);
FileSize := FileStream.Size;
if (ChunkSize < 0) or (ChunkSize > FileSize) or (ChunkStart < 0) or (ChunkStart > FileSize) or (FileStream.Seek(ChunkStart, soBeginning) <> ChunkStart) then
raise EReadError.Create('Can''t read from ' + AFileName + ' ' + ChunkSize.ToString + ' bytes at ' + ChunkStart.ToString);
self.FStartPos := ChunkStart;
if ChunkSize = 0 then
self.FSize := FileSize - ChunkStart
else
self.FSize := ChunkSize;
end;
destructor TChunkedFileStream.Destroy;
begin
FileStream.Free;
inherited Destroy;
end;
function TChunkedFileStream.GetSize: Int64;
begin
result := FSize;
end;
function TChunkedFileStream.Read(var Buffer; Count: Longint): Longint;
begin
if FileStream.Position + Count > self.FStartPos + self.FSize then
Count := self.FStartPos + self.FSize - FileStream.Position;
if Count > 0 then
result := FileStream.Read(Buffer, Count)
else
result := 0;
end;
function TChunkedFileStream.Seek(const Offset: Int64; Origin: TSeekOrigin): Int64;
var
NewPos: Int64;
begin
case Origin of
soBeginning:
result := FileStream.Seek(FStartPos + Offset, soBeginning) - FStartPos;
soCurrent:
begin
NewPos := FileStream.Position + Offset - FStartPos;
if NewPos < 0 then
NewPos := 0;
if NewPos > FSize then
NewPos := FSize;
result := FileStream.Seek(FStartPos + NewPos, soBeginning) - FStartPos;
end;
soEnd:
result := FileStream.Seek(FStartPos + FSize + Offset, soBeginning) - FStartPos;
else
result := -1;
end;
end;
function TChunkedFileStream.Write(const Buffer; Count: Longint): Longint;
begin
result := 0; //too lazy to implement
end;
end.