/
Ini.pas
147 lines (125 loc) · 3.85 KB
/
Ini.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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
namespace RemObjects.Train;
interface
uses
System.Collections.Generic,
System.Linq,
System.IO;
type
IniFile = public class
private
method WriteSection(ssw: TextWriter; aItem: IniSection);
method set_Keys(i : Int32; value: String);
fSections: List<Tuple<String, IniSection>> := new List<Tuple<String, IniSection>>;
public
property Count: Integer read fSections.Count;
property Keys[i: Integer]: String read fSections[i].Item1 write set_Keys;
property Item[s: String]: IniSection read fSections.FirstOrDefault(a-> String.Equals(a.Item1,s, StringComparison.InvariantCultureIgnoreCase)):Item2;
property Sections: List<Tuple<String, IniSection>> read fSections;
method AddSection(s: String): IniSection;
method RemoveAt(i: Integer);
method Remove(s: String): Boolean;
method SaveToStream(sr: TextWriter);
method ToString: String; override;
method SaveToFile(s: String);
method LoadFromStream(sr: TextReader);
method LoadFromFile(s: String);
end;
IniSection = public class(Dictionary<String, String>)
private
method get_Item(s : String): String;
method set_Item(s : String; value: String);
public
constructor;
property Item[s: String]: String read get_Item write set_Item; reintroduce;
end;
implementation
method IniSection.get_Item(s : String): String;
begin
TryGetValue(s, out result);
end;
method IniSection.set_Item(s : String; value: String);
begin
inherited Item[s] := value;
end;
constructor IniSection;
begin
inherited constructor(StringComparer.InvariantCultureIgnoreCase);
end;
method IniFile.set_Keys(i : Int32; value: String);
begin
fSections[i] := new Tuple<String, IniSection>(value, fSections[i].Item2);
end;
method IniFile.AddSection(s: String): IniSection;
begin
result := Item[s];
if result = nil then begin
result := new IniSection;
fSections.Add(new Tuple<String, IniSection>(s, result));
end;
end;
method IniFile.RemoveAt(i: Integer);
begin
fSections.RemoveAt(i);
end;
method IniFile.SaveToStream(sr: TextWriter);
begin
var lItem := Item[''];
if lItem <> nil then begin
WriteSection(sr, lItem);
end;
for each el in fSections do begin
if String.IsNullOrEmpty(el.Item1) then continue;
sr.WriteLine('[{0}]', el.Item1);
WriteSection(sr, el.Item2);
end;
end;
method IniFile.SaveToFile(s: String);
begin
using sr := new StreamWriter(s) do SaveToStream(sr);
end;
method IniFile.LoadFromStream(sr: TextReader);
begin
var lCurrentSection: IniSection;
loop begin
var s := sr.ReadLine():Trim();
if s = nil then break;
if s = '' then continue;
if s.StartsWith('#') then continue;
if s.StartsWith('[') then begin
s := s.Substring(1);
if s.EndsWith(']') then s := s.Substring(0, s.Length-1).Trim;
lCurrentSection := AddSection(s);
end else if s.IndexOf('=') >= 0 then begin
var lItem := s.Split(['='], 2, StringSplitOptions.RemoveEmptyEntries);
if length(lItem) = 2 then begin
if lCurrentSection = nil then lCurrentSection := AddSection('');
lCurrentSection[lItem[0]] := lItem[1];
end;
end;
end;
end;
method IniFile.LoadFromFile(s: String);
begin
using sr := new StreamReader(s) do
LoadFromStream(sr);
end;
method IniFile.WriteSection(ssw: TextWriter; aItem: IniSection);
begin
for each el in aItem do begin
ssw.WriteLine('{0}={1}', el.Key, el.Value);
end;
end;
method IniFile.ToString: String;
begin
var sr := new StringWriter();
SaveToStream(sr);
exit sr.GetStringBuilder().ToString;
end;
method IniFile.&Remove(s: String): Boolean;
begin
var n := fSections.FindIndex(a-> String.Equals(a.Item1, s, StringComparison.InvariantCultureIgnoreCase));
if n < 0 then exit false;
RemoveAt(n);
exit true;
end;
end.