/[projects]/dao/DelphiScanner/Components/tpsystools_4.04/source/StIniStm.pas
ViewVC logotype

Annotation of /dao/DelphiScanner/Components/tpsystools_4.04/source/StIniStm.pas

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2671 - (hide annotations) (download)
Tue Aug 25 18:15:15 2015 UTC (8 years, 10 months ago) by torben
File size: 16205 byte(s)
Added tpsystools component
1 torben 2671 // Upgraded to Delphi 2009: Sebastian Zierer
2     // FIXME: TStAnsiTextStream
3    
4     (* ***** BEGIN LICENSE BLOCK *****
5     * Version: MPL 1.1
6     *
7     * The contents of this file are subject to the Mozilla Public License Version
8     * 1.1 (the "License"); you may not use this file except in compliance with
9     * the License. You may obtain a copy of the License at
10     * http://www.mozilla.org/MPL/
11     *
12     * Software distributed under the License is distributed on an "AS IS" basis,
13     * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
14     * for the specific language governing rights and limitations under the
15     * License.
16     *
17     * The Original Code is TurboPower SysTools
18     *
19     * The Initial Developer of the Original Code is
20     * TurboPower Software
21     *
22     * Portions created by the Initial Developer are Copyright (C) 1996-2002
23     * the Initial Developer. All Rights Reserved.
24     *
25     * Contributor(s):
26     *
27     * ***** END LICENSE BLOCK ***** *)
28    
29     {*********************************************************}
30     {* SysTools: StIniStm.pas 4.04 *}
31     {*********************************************************}
32     {* SysTools: .INI file-like stream class *}
33     {*********************************************************}
34    
35     {$include StDefine.inc}
36    
37     unit StIniStm;
38    
39    
40     interface
41    
42     uses
43     Windows, SysUtils, Classes, StStrms;
44    
45     type
46    
47     TStIniStream = class(TObject)
48     private
49     FAnsiStream : TStAnsiTextStream;
50     FSections : TStringList;
51     procedure GetSecStrings(Strs: TStrings);
52     protected
53     procedure GotoSection(const Section : String);
54     procedure UpdateSections;
55     procedure WriteSectionName(const Section : String);
56     procedure WriteValue(const Key, Value : String);
57     public
58     constructor Create(aStream : TStream);
59     destructor Destroy; override;
60    
61     function SectionExists(const Section : String): Boolean;
62     function ReadString(const Section, Ident, Default : String) : String;
63     procedure WriteString(const Section, Ident, Value : String);
64     procedure WriteSection(const Section : String; Strings: TStrings);
65     procedure ReadSection(const Section : String; Strings: TStrings);
66     procedure ReadSections(Strings: TStrings);
67     procedure ReadSectionValues(const Section : String; Strings: TStrings);
68     procedure EraseSection(const Section : String);
69     procedure DeleteKey(const Section, Ident : String);
70     function ValueExists(const Section, Ident : String): Boolean;
71     end;
72    
73     procedure SplitNameValue(const Line : string; var Name, Value : string); {!!.04}
74    
75     implementation
76    
77     {!!.04 - Added }
78     procedure SplitNameValue(const Line : string; var Name, Value : string);
79     var
80     P : Integer;
81     begin
82     P := Pos('=', Line);
83     if P < 1 then begin
84     Name := Line;
85     Value := '';
86     Exit;
87     end;
88    
89     Name := Copy(Line, 1, P-1);
90     Value := Copy(Line, P+1, Length(Line) - P);
91     end;
92     {!!.04 - Added End}
93    
94     function IsHeader(const AString : String) : Boolean;
95     { see if passed in text looks like an .INI header }
96     var
97     Temp : String;
98     begin
99     if AString = '' then begin
100     Result := False;
101     Exit;
102     end;
103    
104     Temp := Trim(AString);
105     Result := (Temp[1] = '[') and (Temp[Length(Temp)] = ']')
106     end;
107    
108    
109     { TStIniStream }
110    
111     constructor TStIniStream.Create(aStream: TStream);
112     begin
113     inherited Create;
114     FAnsiStream := TStAnsiTextStream.Create(aStream);
115     FSections := TStringList.Create;
116     FSections.Sorted := True;
117     FSections.Duplicates := dupIgnore;
118    
119     if aStream.Size > 0 then { not an empty stream }
120     UpdateSections;
121     end;
122    
123     destructor TStIniStream.Destroy;
124     begin
125     FSections.Free;
126     FAnsiStream.Free;
127     inherited Destroy;
128     end;
129    
130    
131     procedure TStIniStream.DeleteKey(const Section, Ident : String);
132     { delete specified item from Section }
133     var
134     SecStrs : TStringList;
135     SecIdx : Integer;
136     MS : TMemoryStream;
137     TS : TStAnsiTextStream;
138     i, Idx : Integer;
139     begin
140     SecStrs := TStringList.Create;
141     MS := TMemoryStream.Create;
142     TS := TStAnsiTextStream.Create(MS);
143    
144     try
145     { locate and read section }
146     GotoSection(Section);
147     GetSecStrings(SecStrs);
148     Idx := SecStrs.IndexOfName(Ident);
149    
150     if Idx > - 1 then begin
151     { remove desired key }
152     SecStrs.Delete(Idx);
153    
154     { locate subsequent section }
155     SecIdx := FSections.IndexOf(Section);
156     if SecIdx < Pred(FSections.Count) then begin
157     GotoSection(FSections[SecIdx+1]);
158    
159     { copy remaining sections }
160     while not FAnsiStream.AtEndOfStream do
161     TS.WriteLine(FAnsiStream.ReadLine);
162     end;
163     { else this is the last section }
164    
165     { seek back and truncate }
166     GotoSection(Section);
167     FAnsiStream.Size := FAnsiStream.Position;
168     // FAnsiStream.SetSize(FAnsiStream.Position);
169    
170     { write updated section }
171     WriteSectionName(Section);
172     for i := 0 to Pred(SecStrs.Count) do
173     FAnsiStream.WriteLine(SecStrs[i]);
174     FAnsiStream.Stream.Seek(0, soFromEnd);
175    
176     { append saved subsequent sections }
177     TS.SeekLine(0);
178     while not TS.AtEndOfStream do
179     FAnsiStream.WriteLine(TS.ReadLine);
180    
181     end; { if Ident > -1 }
182     { else the Ident doesn't exist so don't alter anything }
183    
184     finally
185     SecStrs.Free;
186     TS.Free;
187     MS.Free;
188     end;
189     end;
190    
191     procedure TStIniStream.EraseSection(const Section : String);
192     { erase specified section from Ini data }
193     var
194     SecIdx : Integer;
195     MS : TMemoryStream;
196     TS : TStAnsiTextStream;
197     begin
198     MS := TMemoryStream.Create;
199     TS := TStAnsiTextStream.Create(MS);
200    
201     { locate section }
202     SecIdx := FSections.IndexOf(Section);
203    
204     { if section found }
205     if SectionExists(Section) then begin
206     try
207     { if this is not the last section }
208     if (SecIdx < Pred(FSections.Count)) then begin
209     { locate subsequent section }
210     GotoSection(FSections[SecIdx+1]);
211    
212     { copy remaining sections to temporary stream}
213     while not FAnsiStream.AtEndOfStream do
214     TS.WriteLine(FAnsiStream.ReadLine);
215     end;
216     { else this is the last section }
217    
218     { locate section to delete and truncate }
219     GotoSection(Section);
220     FAnsiStream.Size := FAnsiStream.Position;
221     // FAnsiStream.SetSize(FAnsiStream.Position);
222    
223     { append saved subsequent sections }
224     TS.SeekLine(0);
225     while not TS.AtEndOfStream do
226     FAnsiStream.WriteLine(TS.ReadLine);
227    
228     finally
229     TS.Free;
230     MS.Free;
231     end;
232     UpdateSections;
233     end;
234     { else section doesn't exist, do nothing }
235     end;
236    
237     procedure TStIniStream.GetSecStrings(Strs : TStrings);
238     { read strings from a section, preserving comments and blanks }
239     var
240     LineVal : String;
241     begin
242     { assume we're at the start of a section }
243     FAnsiStream.ReadLine; { skip section header }
244    
245     LineVal := FAnsiStream.ReadLine;
246     while not (FAnsiStream.AtEndOfStream) and not (IsHeader(LineVal)) do begin
247     Strs.Add(LineVal); { add it to the list }
248     LineVal := FAnsiStream.ReadLine; { get next line }
249     end;
250     end;
251    
252     procedure TStIniStream.GotoSection(const Section: String);
253     { position stream to requested section header }
254     var
255     Idx : Integer;
256     begin
257     Idx := FSections.IndexOf(Section);
258     if Idx > -1 then
259     FAnsiStream.SeekLine(Integer(FSections.Objects[Idx]));
260     end;
261    
262     procedure TStIniStream.ReadSectionValues(const Section : String;
263     Strings: TStrings);
264     { return <Name>=<Value> pairs of requested Section in Strings }
265     var
266     Strs : TStringList;
267     LineVal : String;
268     i : Integer;
269     begin
270     if not Assigned(Strings) then Exit;
271    
272     Strs := TStringList.Create;
273     if SectionExists(Section) then begin { section exists }
274     Strings.Clear;
275     try
276     { locate section }
277     GotoSection(Section);
278    
279     { retrieve section contents, comments, blank lines and all }
280     GetSecStrings(Strs);
281    
282     { iterate section lines looking for entries }
283     for i := 0 to Pred(Strs.Count) do begin
284     LineVal := Strs[i];
285     if (Trim(LineVal) <> '') and (Trim(LineVal[1]) <> ';') and (Pos('=', LineVal) > 0) then {!!.02}
286     { not empty and not a comment and at least superficially resembles a
287     <Name>=<Value> pair }
288     Strings.Add(Trim(LineVal)); { add it to the list } {!!.02}
289     end;
290     finally
291     Strs.Free;
292     end;
293     end;
294     { else section doesn't exist, do nothing }
295     end;
296    
297     procedure TStIniStream.ReadSections(Strings: TStrings);
298     var
299     i : Integer;
300     begin
301     if not Assigned(Strings) then Exit;
302    
303     { omit the pseudo section }
304     for i := 1 to Pred(FSections.Count) do
305     Strings.Add(Trim(FSections[i])); {!!.02}
306     end;
307    
308     procedure TStIniStream.ReadSection(const Section : String;
309     Strings: TStrings);
310     { return Name strings for all entries in requested section }
311     var
312     SecStrs : TStringList;
313     i : Integer;
314     LineVal, Name : String;
315     begin
316     if not Assigned(Strings) then Exit;
317    
318     SecStrs := TStringList.Create;
319     try
320     // ReadSection(Section, SecStrs);
321     {!!.02 - Rewritten }
322     Strings.Clear;
323     { locate section }
324     GotoSection(Section);
325    
326     { retrieve section contents, comments, blank lines and all }
327     GetSecStrings(SecStrs);
328    
329     { iterate section lines looking for entries }
330     for i := 0 to Pred(SecStrs.Count) do begin
331     LineVal := SecStrs[i];
332     if (Trim(LineVal) <> '') and (Trim(LineVal[1]) <> ';') and (Pos('=', LineVal) > 0) then begin
333     { not empty and not a comment and at least superficially resembles a
334     <Name>=<Value> pair }
335     SplitNameValue(LineVal, Name, LineVal);
336     Strings.Add(Trim(Name));
337     end;
338     end;
339    
340     // for i := 0 to Pred(SecStrs.Count) do
341     // Strings.Add(SecStrs.Names[i]);
342     {!!.02 - Rewritten End }
343    
344    
345     finally
346     SecStrs.Free;
347     end;
348     end;
349    
350     function TStIniStream.ReadString(const Section, Ident,
351     Default : String) : String;
352     {
353     return a particular string selected by Ident from Section
354     if empty or doesn't exist, return Default
355     }
356     var
357     SecStrs : TStringList;
358     begin
359     SecStrs := TStringList.Create;
360     try
361     ReadSectionValues(Section, SecStrs); {!!.04}
362    
363     Result := SecStrs.Values[Ident];
364     if Result = '' then
365     Result := Default;
366    
367     finally
368     SecStrs.Free;
369     end;
370     end;
371    
372     function TStIniStream.SectionExists(const Section : String): Boolean;
373     { returns True if Section exists in section list, False otherwise }
374     begin
375     Result := FSections.IndexOf(Section) > -1;
376     end;
377    
378     procedure TStIniStream.UpdateSections;
379     { refresh Sections list }
380     var
381     i : Integer;
382     Line : String;
383     begin
384     i := 0;
385     FSections.Clear;
386     FAnsiStream.SeekLine(0);
387    
388     { pseudo section to account for any comments or whitespace prior to first
389     real section in data }
390     FSections.AddObject('[]', TObject(0));
391    
392     { iterate data looking for section headers: '[blah]' }
393     while not FAnsiStream.AtEndOfStream do begin
394     Line := Trim(FAnsiStream.ReadLine);
395     { if it looks like a header }
396     if IsHeader(Line) then
397     { add it to the list with a line index }
398     FSections.AddObject(Copy(Line, 2, Length(Line) - 2), TObject(i));
399     { go to next line }
400     Inc(i);
401     end;
402     end;
403    
404     function TStIniStream.ValueExists(const Section, Ident : String): Boolean;
405     {
406     see if requested section contains requested Ident
407     implies "<Ident>=" exists in section, not that there's necessarily any
408     explicit Value associated, i.e. Value may be blank
409     }
410     var
411     SecStrs : TStringList;
412     i : Integer;
413     begin
414     Result := False;
415     SecStrs := TStringList.Create;
416     try
417     { get section }
418     ReadSection(Section, SecStrs);
419    
420     { see if Ident exists in Names collection }
421     for i := 0 to Pred(SecStrs.Count) do
422     if SecStrs.Names[i] = Ident then begin
423     Result := True;
424     Break;
425     end;
426     finally
427     SecStrs.Free;
428     end;
429     end;
430    
431     procedure TStIniStream.WriteString(const Section, Ident, Value : String);
432     { write individual string value to IniStream }
433     var
434     SecStrs : TStringList;
435     SecIdx : Integer;
436     MS : TMemoryStream;
437     TS : TStAnsiTextStream;
438     i : Integer;
439     begin
440     if SectionExists(Section) then begin
441     SecStrs := TStringList.Create;
442     MS := TMemoryStream.Create;
443     TS := TStAnsiTextStream.Create(MS);
444    
445     try
446     { locate and read section }
447     GotoSection(Section);
448     GetSecStrings(SecStrs);
449    
450     { locate subsequent section }
451     SecIdx := FSections.IndexOf(Section);
452     if SecIdx < Pred(FSections.Count) then begin
453     GotoSection(FSections[SecIdx+1]);
454    
455     { copy remaining sections }
456     while not FAnsiStream.AtEndOfStream do
457     TS.WriteLine(FAnsiStream.ReadLine);
458     end;
459     { else this is the last section }
460    
461     { seek back and truncate }
462     GotoSection(Section);
463     FAnsiStream.Size := FAnsiStream.Position;
464    
465     // FAnsiStream.SetSize(FAnsiStream.Position);
466    
467     { insert new value }
468     SecStrs.Add(Ident + '=' + Value);
469    
470     { write updated section }
471     WriteSectionName(Section);
472     for i := 0 to Pred(SecStrs.Count) do
473     FAnsiStream.WriteLine(SecStrs[i]);
474     FAnsiStream.Stream.Seek(0, soFromEnd);
475    
476     { append saved subsequent sections }
477     TS.SeekLine(0);
478     while not TS.AtEndOfStream do
479     FAnsiStream.WriteLine(TS.ReadLine);
480    
481     finally
482     SecStrs.Free;
483     TS.Free;
484     MS.Free;
485     end;
486    
487     end
488     else begin { no such section exists, append new one }
489     FAnsiStream.Seek(0, soFromEnd);
490     WriteSectionName(Section);
491     WriteValue(Ident, Value);
492     UpdateSections;
493     end;
494    
495     end;
496    
497     procedure TStIniStream.WriteSectionName(const Section: String);
498     { write section header at current location }
499     begin
500     FAnsiStream.WriteLine('[' + Section + ']');
501     end;
502    
503     procedure TStIniStream.WriteValue(const Key, Value: String);
504     { write <Name>=<Value> pair at current location }
505     begin
506     FAnsiStream.WriteLine(Key + '=' + Value);
507     end;
508    
509     procedure TStIniStream.WriteSection(const Section: String;
510     Strings: TStrings);
511     { write entire section described by Strings }
512     var
513     SecStrs : TStringList;
514     SecIdx : Integer;
515     MS : TMemoryStream;
516     TS : TStAnsiTextStream;
517     i : Integer;
518     L : LongInt;
519     Name : String;
520     begin
521     if not Assigned(Strings) then Exit;
522    
523     if SectionExists(Section) then begin
524     SecStrs := TStringList.Create;
525     MS := TMemoryStream.Create;
526     TS := TStAnsiTextStream.Create(MS);
527    
528     try
529     { locate and read section }
530     GotoSection(Section);
531     GetSecStrings(SecStrs);
532    
533     { locate subsequent section }
534     SecIdx := FSections.IndexOf(Section);
535     if SecIdx < Pred(FSections.Count) then begin
536     GotoSection(FSections[SecIdx+1]);
537    
538     { copy remaining sections }
539     while not FAnsiStream.AtEndOfStream do
540     TS.WriteLine(FAnsiStream.ReadLine);
541     end;
542     { else this is the last section }
543    
544     { seek back and truncate }
545     GotoSection(Section);
546     FAnsiStream.Size := FAnsiStream.Position;
547     // FAnsiStream.SetSize(FAnsiStream.Position);
548    
549     { update section }
550     for i := 0 to Pred(Strings.Count) do begin
551     Name := Strings.Names[i];
552     if SecStrs.IndexOfName(Name) > -1 then { entry exists, change value }
553     SecStrs.Values[Name] := Strings.Values[Name]
554     else { new entry, just append it }
555     SecStrs.Add(Strings[i]);
556     end;
557    
558     { write updated section }
559     WriteSectionName(Section);
560     for i := 0 to Pred(SecStrs.Count) do
561     FAnsiStream.WriteLine(SecStrs[i]);
562     FAnsiStream.Stream.Seek(0, soFromEnd);
563    
564     { append saved subsequent sections }
565     TS.SeekLine(0);
566     while not TS.AtEndOfStream do
567     FAnsiStream.WriteLine(TS.ReadLine);
568    
569     finally
570     SecStrs.Free;
571     TS.Free;
572     MS.Free;
573     end;
574    
575     end
576     else begin { no such section exists, append new one }
577     L := FAnsiStream.LineCount;
578     FAnsiStream.Seek(0, soFromEnd);
579     WriteSectionName(Section);
580     FSections.AddObject(Section, TObject(L+1));
581     for i := 0 to Pred(Strings.Count) do
582     FAnsiStream.WriteLine(Strings[i]);
583     // UpdateSections;
584     end;
585     end;
586    
587     end.

  ViewVC Help
Powered by ViewVC 1.1.20