fpc/utils/makeini.pp
2000-09-01 21:37:30 +00:00

496 lines
13 KiB
ObjectPascal

{
$Id$
This file is part of the Free Component Library (FCL)
Copyright (c) 1999-2000 by Michael A. Hess
Old inifiles unit adapted for fpcmake
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
**********************************************************************}
unit MakeIni;
{$mode objfpc}
{$H+}
interface
uses Classes;
type
{ TIniFile class }
TIniFile = class(TObject)
private
FEscapeLineFeeds : Boolean;
FFileName : string;
FStream : TStream;
FFileBuffer : TStringList;
function GetName(const line : string) : string;
function GetValue(const line, name : string) : string;
function IsComment(const line : string) : boolean;
function IsSection(const line : string) : boolean;
function GetSectionIndex(const section : string) : integer;
protected
procedure SetFileName(const fn:string);
procedure SetStream(s:TStream);
procedure LoadFromFile;
procedure SaveToFile;
procedure LoadFromStream;
procedure SaveToStream;
public
constructor Create(const theFileName : string);
constructor Create(s:TStream);
destructor Destroy; override;
procedure DeleteKey(const section, ident : string);
procedure EraseSection(const section : string);
function ReadBool(const section, ident : string; defaultValue : boolean) : boolean;
function ReadInteger(const section, ident : string; defaultValue : longint) : longint;
procedure ReadSection(const section : string; strings : TStrings);
procedure ReadSections(strings : TStrings);
procedure ReadSectionValues(const section : string; strings : TStrings);
procedure ReadSectionRaw(const section : string; strings : TStrings);
function ReadString(const section, ident, defaultValue : string) : string;
procedure WriteBool(const section, ident : string; value : boolean);
procedure WriteInteger(const section, ident : string; value : longint);
procedure WriteString(const section, ident, value : string);
property FileName : String read FFileName;
property EscapeLineFeeds : Boolean Read FEscapeLineFeeds Write FEscapeLineFeeds default false;
end;
implementation
uses SysUtils;
const
brackets : array[0..1] of Char = ('[', ']');
separator : Char = '=';
comment : Char = ';';
{ TIniFile }
constructor TIniFile.Create(const theFileName : string);
begin
FFileName := theFileName;
FStream:=nil;
FEscapeLineFeeds:=False;
FFileBuffer := TStringList.Create;
if FileExists(fileName) then
LoadFromFile;
end;
constructor TIniFile.Create(s:TStream);
begin
FFileName := '';
FStream:=s;
FEscapeLineFeeds:=False;
FFileBuffer := TStringList.Create;
LoadFromStream;
end;
destructor TIniFile.Destroy;
begin
FFileBuffer.Free;
end;
function TIniFile.GetName(const line : string) : string;
var
index,index2 : integer;
begin
Result := '';
index := Pos(separator, line);
if index <> 0 then
begin
index2:=Pos(comment, line);
if (index2=0) or (index2>index) then
result := Trim(Copy(line, 1, index - 1));
end;
end;
function TIniFile.GetValue(const line, name : string) : string;
var
index1,index2,index3 : integer;
begin
result := '';
if (line <> '') and (name <> '') then
begin
index1 := Pos(name, line);
index2 := Pos(separator, line);
index3 := Pos(comment, line);
if index3=0 then
index3:=MaxInt;
if (index1 <> 0) and (index2 <> 0) and (index2 > index1) then
result := Trim(Copy(line, index2 + 1, index3));
end;
end;
function TIniFile.IsSection(const line : string) : boolean;
var
str : string;
begin
result := False;
if line <> '' then
begin
str := Trim(line);
if (str<>'') and (str[1] = brackets[0]) and (str[Length(str)] = brackets[1]) then
result := True;
end;
end;
function TIniFile.IsComment(const line : string) : boolean;
var
str : string;
begin
result := False;
if line <> '' then
begin
str := Trim(line);
result := (str<>'') and (str[1]=comment);
end;
end;
function TIniFile.GetSectionIndex(const section : string) : integer;
begin
result := FFileBuffer.IndexOf(brackets[0] + section + brackets[1]);
end;
{ Load/Save }
procedure TIniFile.SetFileName(const fn:string);
begin
FFileName:=fn;
end;
procedure TIniFile.SetStream(s:TStream);
begin
FStream:=s;
end;
procedure TIniFile.LoadFromFile;
begin
if FFileName<>'' then
FFileBuffer.LoadFromFile(FFileName);
end;
procedure TIniFile.SaveToFile;
begin
if FFileName<>'' then
FFileBuffer.SaveToFile(FFileName);
end;
procedure TIniFile.LoadFromStream;
begin
if assigned(FStream) then
FFileBuffer.LoadFromStream(FStream);
end;
procedure TIniFile.SaveToStream;
begin
if assigned(FStream) then
FFileBuffer.SaveToStream(FStream);
end;
{ Read all Names of one Section }
procedure TIniFile.ReadSection(const section : string; strings : TStrings);
var
index : integer;
name : string;
begin
strings.BeginUpdate;
try
strings.Clear;
if FFileBuffer.Count > 0 then
begin
index := GetSectionIndex(section);
if index <> -1 then
begin
Inc(index);
while (index < FFileBuffer.Count) and not IsSection(FFileBuffer[index]) do
begin
name := GetName(FFileBuffer[index]);
if name <> '' then
strings.Add(name);
Inc(index);
end;
end;
end;
finally
strings.EndUpdate;
end;
end;
{ Read all Sections of the Ini-File }
procedure TIniFile.ReadSections(strings : TStrings);
var
index : integer;
section : string;
begin
strings.BeginUpdate;
try
strings.Clear;
if FFileBuffer.Count > 0 then
begin
index := 0;
while (index < FFileBuffer.Count) do
begin
if IsSection(FFileBuffer[index]) then
begin
section := Trim(FFileBuffer[index]);
Delete(section, 1, 1);
Delete(section, Length(section), 1);
strings.Add(Trim(section));
end;
Inc(index);
end;
end;
finally
strings.EndUpdate;
end;
end;
{ Reads a String-Value of "ident" in one "section".
The result is "defaultValue" if
o section doesn't exists
o ident doesn't exists
o ident doesn't have any assigned value }
function TIniFile.ReadString(const section, ident, defaultValue : string) : string;
var
index : integer;
value : string;
begin
result := defaultValue;
if FFileBuffer.Count > 0 then
begin
index := GetSectionIndex(section);
if index <> -1 then
begin
Inc(index);
while (index < FFileBuffer.Count) and not IsSection(FFileBuffer[index]) do
begin
if CompareText(GetName(FFileBuffer[index]),ident)=0 then
begin
value := GetValue(FFileBuffer[index], ident);
if value <> '' then
begin
result := value;
if EscapeLineFeeds and (result[length(result)]='\') then
begin
inc(index);
while (index < FFileBuffer.Count) and (result[length(result)]='\') do
begin
result:=Copy(result,1,length(result)-1)+Trim(FFileBuffer[index]);
inc(index);
end;
end;
end;
break;
end;
Inc(index);
end;
end;
end;
end;
{ Reads an Integer-Value of Ident in one Section }
function TIniFile.ReadInteger(const section, ident : string; defaultValue : longint) : longint;
var
intStr : string;
begin
intStr := ReadString(section, ident, '');
{ convert a Hex-Value }
if (Length(intStr) > 2) and (intStr[1] = '0') and ((intStr[2] = 'X') or (intStr[2] = 'x')) then
intStr := '$' + Copy(intStr, 3, Maxint);
result := StrToIntDef(intStr, defaultValue);
end;
{ Reads a Bool-Value of Ident in one Section }
function TIniFile.ReadBool(const section, ident : string; defaultValue : boolean) : boolean;
begin
result := ReadInteger(section, ident, Ord(defaultValue)) <> 0;
end;
{ Reads all Names + Values of one Section }
procedure TIniFile.ReadSectionValues(const section : string; strings : TStrings);
var
name : string;
value : string;
index : integer;
begin
strings.BeginUpdate;
try
strings.Clear;
if FFileBuffer.Count > 0 then
begin
index := GetSectionIndex(section);
if index <> -1 then
begin
Inc(index);
while (index < FFileBuffer.Count) and not IsSection(FFileBuffer[index]) do
begin
name := GetName(FFileBuffer[index]);
if name <> '' then
begin
value := GetValue(FFileBuffer[index], name);
strings.Add(name + separator + value);
end;
Inc(index);
end;
end;
end;
finally
strings.EndUpdate;
end;
end;
procedure TIniFile.ReadSectionRaw(const section : string; strings : TStrings);
var
eols,index : integer;
begin
strings.BeginUpdate;
try
eols:=0;
strings.Clear;
if FFileBuffer.Count > 0 then
begin
index := GetSectionIndex(section);
if index <> -1 then
begin
Inc(index);
while (index < FFileBuffer.Count) and not IsSection(FFileBuffer[index]) do
begin
{ Skip empty lines at the end of the section }
if FFileBuffer[index]='' then
inc(eols)
else
begin
while eols>0 do
begin
Strings.Add('');
dec(eols);
end;
if not IsComment(FFileBuffer[index]) then
strings.Add(FFileBuffer[index]);
end;
Inc(index);
end;
end;
end;
finally
strings.EndUpdate;
end;
end;
{ Writes a String-Value for Ident in one Section.
Note: If Section and/or Ident don't exist, they will be placed in the Ini-File }
procedure TIniFile.WriteString(const section, ident, value : string);
var
index : integer;
begin
index := GetSectionIndex(section);
{ Section exists }
if index <> -1 then
begin
Inc(index);
while (index < FFileBuffer.Count) and not IsSection(FFileBuffer[index]) and
(GetName(FFileBuffer[index]) <> ident) do
Inc(index);
if (index >= FFileBuffer.Count) or IsSection(FFileBuffer[index]) then
begin { End of File or ident doesn't exists in the section }
if ident <> '' then
FFileBuffer.Insert(index, ident + separator + value);
end
else if ident <> '' then { Ident does exists in the section }
FFileBuffer[index] := ident + separator + value;
end
else { section doesn't exists, so add new [section] with ident=value }
begin
FFileBuffer.Add('');
FFileBuffer.Add(brackets[0] + section + brackets[1]);
if ident <> '' then
FFileBuffer.Add(ident + separator + value);
end;
SaveToFile;
end;
{ Writes an Integer-Value for Ident in one Section }
procedure TIniFile.WriteInteger(const section, ident : string; value : longint);
begin
WriteString(section, ident, IntToStr(value));
end;
{ Writes a Bool-Value for Ident in one Section }
procedure TIniFile.WriteBool(const section, ident : string; value : boolean);
const
values: array[boolean] of string = ('0', '1');
begin
WriteString(section, ident, values[Value]);
end;
{ Deletes the value of ident in one section.
Note: Only if section and ident exist, the value of ident will be set to NULL }
procedure TIniFile.DeleteKey(const section, ident : string);
var
index : integer;
begin
index := GetSectionIndex(section);
if index <> -1 then
begin
Inc(index);
while (index < FFileBuffer.Count) and not IsSection(FFileBuffer[index]) and
(GetName(FFileBuffer[index]) <> ident) do
Inc(index);
if not (index >= FFileBuffer.Count) and not IsSection(FFileBuffer[index]) then
begin { Ident does exists }
FFileBuffer.Delete(index);
SaveToFile;
end;
end;
end;
{ Erases the whole Section from an Ini-File }
procedure TIniFile.EraseSection(const section : string);
var
index : integer;
begin
index := GetSectionIndex(section);
if index <> -1 then
begin
FFileBuffer.Delete(index); { Delete Section-Header }
while (index < FFileBuffer.Count) and not IsSection(FFileBuffer[index]) do
FFileBuffer.Delete(index); { Delete Section-Items }
if index > 0 then FFileBuffer.Insert(index, '');
SaveToFile;
end;
end;
end.
{
$Log$
Revision 1.2 2000-09-01 21:37:30 peter
* targetdir support (merged)
Revision 1.1 2000/07/13 10:16:22 michael
+ Initial import
Revision 1.1 2000/05/11 17:59:12 peter
* makeini unit added as replacement for old inifiles unit
}