-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathnodeio.pas
120 lines (100 loc) · 2.7 KB
/
nodeio.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
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
unit nodeio;
{$mode ObjFPC}{$H+}
interface
uses
Classes, SysUtils, nodetree, ZStream;
type
generic TNodeIO<PNodeType> = class sealed
type
{$PUSH}{$PACKENUM 1}
TNodeStreamType = (Child, Sibling, Last);
{$POP}
private
fs, cs, ds: TStream;
procedure LoadNodeInternal(node: PNodeType);
procedure SaveNodeInternal(node: PNodeType; NodeStreamType: TNodeStreamType);
public
constructor Create(FileName: String; const FileExt: String; Compression: Boolean = True);
destructor Destroy; override;
procedure LoadNode(node: PNodeType);
procedure SaveNode(node: PNodeType);
end;
implementation
constructor TNodeIO.Create(FileName: String; const FileExt: String; Compression: Boolean = True);
begin
inherited Create;
if FileName='' then FileName:=FormatDateTime('yyyymmddHHMMSS', Now) + FileExt;
if FileExists(FileName) then
fs := TFileStream.Create(FileName, fmOpenReadWrite)
else
fs := TFileStream.Create(FileName, fmCreate);
if Compression then
begin
cs := TCompressionStream.Create(clfastest, fs);
ds := TDecompressionStream.create(fs);
end else
begin
cs := fs;
ds := fs;
end;
end;
destructor TNodeIO.Destroy;
begin
if ds<>cs then
begin
ds.Free;
cs.Free;
end;
fs.Free;
inherited Destroy;
end;
procedure TNodeIO.LoadNodeInternal(node: PNodeType);
var
NodeStreamType: TNodeStreamType;
begin
while (ds.Read(NodeStreamType, SizeOf(NodeStreamType))<>0) do
begin
case NodeStreamType of
TNodeStreamType.Child:
begin
ds.Read(node^.AddChild^.NodeData, SizeOf(node^.NodeData));
LoadNodeInternal(node^.Child);
end;
TNodeStreamType.Sibling:
begin
node:=node^.AddSibling;
ds.Read(node^.NodeData, SizeOf(node^.NodeData));
end;
else
begin
Exit;
end;
end;
end;
end;
procedure TNodeIO.LoadNode(node: PNodeType);
var
NodeStreamType: TNodeStreamType;
begin
if ds.Read(NodeStreamType, SizeOf(NodeStreamType))=0 then Exit;
if ds.Read(node^.NodeData, SizeOf(node^.NodeData))=0 then Exit;
LoadNodeInternal(node);
end;
procedure TNodeIO.SaveNodeInternal(node: PNodeType; NodeStreamType: TNodeStreamType);
begin
while Assigned(node) do
begin
cs.Write(NodeStreamType, SizeOf(NodeStreamType));
cs.Write(node^.NodeData, SizeOf(node^.NodeData));
if Assigned(node^.Child) then SaveNodeInternal(node^.Child, TNodeStreamType.Child);
node:=node^.Sibling;
NodeStreamType:=TNodeStreamType.Sibling;
end;
NodeStreamType:=TNodeStreamType.Last;
cs.Write(NodeStreamType, SizeOf(NodeStreamType));
end;
procedure TNodeIO.SaveNode(node: PNodeType);
begin
SaveNodeInternal(node, TNodeStreamType.Child);
end;
end.