www.pudn.com > VCLSkin.4.81.rar > WinSkinIni.pas


unit WinSkinIni; 
 
{$B-} 
 
interface 
 
uses Classes,winconvert; 
 
type 
{ TQuickIni class } 
  TQuickIni = class(TObject) 
  private 
    FAuto : boolean; 
    FFileName: String; 
    FIniFile : TStrings; 
    function GetName(const Line: String): String; 
    function GetValue(const Line, Name: String): String; 
    function GetSectionIndex(const Section: String): Integer; 
    function IsSection(const Line: String): Boolean; 
    procedure SetFileName(Value: string); 
    procedure SetIniFile(Value: TStrings); 
  protected 
    FSections: TStrings; 
    procedure Compress(source,dest:TStream); 
    procedure Decompress(source,Dest:TStream); 
  public 
    constructor Create; 
    destructor Destroy; override; 
    procedure LoadFromFile(aname:string); 
    procedure SaveToFile(aname:string); 
    procedure LoadFromStream(Stream: TStream); 
    procedure SaveToStream(Stream:Tstream); 
    procedure LoadFromZip(aname:string); 
    procedure SavetoZip(aname:string); 
    procedure DeleteKey(const Section, Ident: String); 
    procedure EraseSection(const Section: String); 
    function ReadBool(const Section, Ident: String; Default: Boolean): Boolean; 
    function ReadInteger(const Section, Ident: String; Default: Longint): Longint; 
    procedure ReadSection(const Section: String; Strings: TStrings); 
    procedure ReadSections(Strings: TStrings); 
    procedure ReadSectionValues(const Section: String; Strings: TStrings); 
    function ReadString(const Section, Ident: String; Default: String): String; 
    procedure RebuildSections; 
    procedure WriteBool(const Section, Ident: String; Value: Boolean); 
    procedure WriteInteger(const Section, Ident: String; Value: Longint); 
    procedure WriteString(const Section, Ident: String; Value: String); 
    property FileName: String read FFileName write SetFileName; 
    property AutoSaveLoad: boolean read FAuto write FAuto; 
    property IniFile: TStrings read FIniFile write SetIniFile; 
    procedure Clear; 
  end; 
 
implementation 
 
uses SysUtils; 
 
const 
  SStringsUnassignedError = 'The parameter Strings is unassigned!'; 
  StartBracket = '['; 
  EndBracket   = ']'; 
  Separator    = '='; 
 
{ TQuickIni } 
 
constructor TQuickIni.Create; 
begin 
  FAuto := False; 
  FIniFile := TStringList.Create; 
  FSections := TStringList.Create; 
//  if FileExists(FileName) then 
//    LoadFromFile; 
end; 
 
destructor TQuickIni.Destroy; 
begin 
  FSections.Free; 
  FIniFile.Free; 
//  Finalize(FFileName); 
end; 
 
function TQuickIni.GetName(const Line: String): String; 
var 
  I: Integer; 
begin 
  I := Pos(Separator, Line); 
  if I <> 0 then 
    Result := Trim(Copy(Line, 1, I-1)) 
  else 
    Result := EmptyStr; 
  result:=lowercase(result); 
end; 
 
function TQuickIni.GetValue(const Line, Name: String): String; 
var 
  I: Integer; 
begin 
  Result := EmptyStr; 
  if (Line <> EmptyStr) and (Name <> EmptyStr) then 
  begin 
    I := Pos(Separator, Line); 
    if (Name = GetName(Line)) and (I <> 0) then 
      Result := Trim(System.Copy(Line, I+1, Maxint)); 
  end; 
end; 
 
function TQuickIni.IsSection(const Line: String): Boolean; 
var 
  S: String; 
begin 
  Result := False; 
  if Line <> EmptyStr then 
  begin 
    S := Trim(Line); 
    if (S[1] = StartBracket) and (S[System.Length(S)] = EndBracket) then 
      Result := True; 
  end; 
end; 
 
function TQuickIni.GetSectionIndex(const Section: String): Integer; 
 
begin 
  Result := FSections.IndexOf(StartBracket + Section + EndBracket); 
  if Result >= 0 then 
    Result := Integer(FSections.Objects[Result]) 
  else 
    Result := -1;   
end; 
 
procedure TQuickIni.Decompress(source,Dest:TStream); 
var 
   LZH: TLZH; 
   Size, Bytes: Longint; 
begin 
    // Decompress in memory blob. 
    LZH := TLZH.Create; 
    try 
       LZH.StreamIn:= source; 
       LZH.StreamOut:=dest; 
       LZH.StreamIn.Position := 0; 
       LZH.StreamOut.Position := 0; 
 
       // Uncompressed file size 
       LZH.StreamIn.Read(size, sizeof(Longint)); 
       Bytes := Size; 
 
       // Decompress rest of stream. 
       LZH.LZHUnpack(Bytes, LZH.GetBlockStream, LZH.PutBlockStream); 
    finally 
       LZH.Free; 
    end; 
end; 
 
procedure TQuickIni.compress(source,dest:TStream); 
var 
   LZH: TLZH; 
   Size, Bytes: Longint; 
begin 
    // Decompress in memory blob. 
    LZH := TLZH.Create; 
    try 
        LZH.StreamIn := Source; 
        LZH.StreamOut := dest; 
        LZH.StreamIn.Position := 0; 
        LZH.StreamOut.Position := 0; 
 
        //write uncompressed size 
        Size := LZH.StreamIn.Size; 
        LZH.StreamOut.Write(Size, sizeof(Longint)); 
 
        // Compress stream. 
        LZH.LZHPack(Bytes, LZH.GetBlockStream, LZH.PutBlockStream); 
    finally 
       LZH.Free; 
    end; 
end; 
 
procedure TQuickIni.LoadFromZip(aname:string); 
var 
  r,r2: TMemoryStream; 
begin 
    r:=Tmemorystream.create; 
    r2:=Tmemorystream.create; 
    try 
       r2.loadfromfile(aname); 
       Decompress(r2,r); 
       r.Seek(0,soFromBeginning); 
       loadfromstream(r); 
    finally 
       r.free; 
       r2.free; 
    end; 
end; 
 
procedure TQuickIni.SavetoZip(aname:string); 
var 
  m,m2: TMemoryStream; 
begin 
   m:=Tmemorystream.create; 
   m2:=Tmemorystream.create; 
   try 
     savetostream(m); 
     compress(m,m2); 
     m2.savetofile(aname); 
   finally 
     m.free; 
     m2.free; 
   end; 
end; 
 
procedure TQuickIni.LoadFromFile(aname:string); 
var 
  Stream: TStream; 
  Ptr, Start: PChar; 
  StmStr,Str: string; 
  Size : integer; 
  I : integer; 
begin 
  Stream := TFileStream.Create(aname, fmOpenRead or fmShareDenyWrite); 
  LoadFromStream(Stream); 
  Stream.Free; 
end; 
 
procedure TQuickIni.LoadFromStream(Stream: TStream); 
var 
  Ptr, Start: PChar; 
  StmStr,Str: string; 
  Size : integer; 
  I : integer; 
begin 
  if not assigned(Stream) then exit; 
 
  FIniFile.BeginUpdate; 
  FSections.BeginUpdate; 
  try 
    Size := Stream.Size - Stream.Position; 
    SetString(StmStr, nil, Size); 
    Stream.Read(Pointer(StmStr)^, Size); 
    FIniFile.Clear; 
    FSections.Clear; 
    Ptr := Pointer(StmStr); 
    I := 0; 
    if Ptr <> nil then 
      while Ptr^ <> #0 do 
      begin 
        Start := Ptr; 
        while not (Ptr^ in [#0, #10, #13]) do 
          Inc(Ptr); 
        SetString(Str, Start, Ptr - Start); 
        Str := Trim(Str); 
        if (Str <> '') and (Str[1] <> ';') then 
        begin 
          FIniFile.Add(Str); 
          if (Str[1] = '[') and (Str[Length(Str)] = ']') then 
          begin 
            FSections.AddObject(Trim(Str),TObject(I)); 
          end; 
          inc(I); 
        end; 
        if Ptr^ = #13 then Inc(Ptr); 
        if Ptr^ = #10 then Inc(Ptr); 
      end; 
  finally 
    FSections.EndUpdate; 
    FIniFile.EndUpdate; 
  end; 
end; 
 
procedure TQuickIni.SaveToFile(aname:string); 
begin 
//  if AutoSaveLoad then 
    FIniFile.SaveToFile(aname); 
end; 
 
procedure TQuickIni.SaveToStream(Stream:Tstream); 
begin 
//  if AutoSaveLoad then 
    if assigned(stream) then 
    FIniFile.SaveTostream(stream); 
end; 
 
{ Read all Names of one Section } 
 
procedure TQuickIni.ReadSection(const Section: String; Strings: TStrings); 
var 
  I: Integer; 
  N: String; 
begin 
  Assert(Assigned(Strings), SStringsUnassignedError); 
  Strings.BeginUpdate; 
  try 
    Strings.Clear; 
    if FIniFile.Count > 0 then 
    begin 
      I := GetSectionIndex(Section); 
      if I <> -1 then 
      begin 
        Inc(I); 
        while (I < FIniFile.Count) and not IsSection(FIniFile[I]) do 
        begin 
          N := GetName(FIniFile[I]); 
          if N <> EmptyStr then Strings.Add(N); 
          Inc(I); 
        end; 
      end; 
    end; 
  finally 
    Strings.EndUpdate; 
  end; 
end; 
 
{ Read all Sections of the Ini-File } 
 
procedure TQuickIni.ReadSections(Strings: TStrings); 
var 
  I: Integer; 
  Section: String; 
begin 
  Assert(Assigned(Strings), SStringsUnassignedError); 
  Strings.Assign(FSections); 
  I := 0; 
  while I < Strings.Count do 
  begin 
    Strings.Objects[I] := Nil; 
    Section := Trim(Strings.Strings[I]); 
    System.Delete(Section, 1, 1); 
    System.Delete(Section, System.Length(Section), 1); 
    Strings.Strings[I] := Trim(Section); 
    Inc(I); 
  end; 
end; 
 
{ Reads a String-Value of Ident in one Section. 
  The result is Default if 
  o Section doesn't exists 
  o Ident doesn't exists 
  o Ident doesn't have any assigned value } 
 
function TQuickIni.ReadString(const Section, Ident: String; Default: String): String; 
var 
  I: Integer; 
  V,s: String; 
begin 
  Result := Default; 
  s:=lowercase(ident); 
  if FIniFile.Count > 0 then 
  begin 
    I := GetSectionIndex(Section); 
    if I <> -1 then 
    begin 
      Inc(I); 
      while (I < FIniFile.Count) and not IsSection(FIniFile[I]) do 
      begin 
        if GetName(FIniFile[I]) = s then 
        begin 
          V := GetValue(FIniFile[I], s); 
          if V <> EmptyStr then 
            Result := V; 
          break; 
        end; 
        Inc(I); 
      end; 
    end; 
  end; 
end; 
 
{ Reads an Integer-Value of Ident in one Section } 
 
function TQuickIni.ReadInteger(const Section, Ident: String; Default: 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 := '$' + System.Copy(IntStr, 3, Maxint); 
  Result := StrToIntDef(IntStr, Default); 
end; 
 
{ Reads a Bool-Value of Ident in one Section } 
 
function TQuickIni.ReadBool(const Section, Ident: String; Default: Boolean): Boolean; 
begin 
  Result := ReadInteger(Section, Ident, Ord(Default)) <> 0; 
end; 
 
{ Reads all Names + Values of one Section } 
 
procedure TQuickIni.ReadSectionValues(const Section: String; Strings: TStrings); 
var 
  I: Integer; 
begin 
  Assert(Assigned(Strings), SStringsUnassignedError); 
  Strings.BeginUpdate; 
  try 
    Strings.Clear; 
    if FIniFile.Count > 0 then 
    begin 
      I := GetSectionIndex(Section); 
      if I <> -1 then 
      begin 
        Inc(I); 
        while (I < FIniFile.Count) and not IsSection(FIniFile[I]) do 
        begin 
          if (FIniFile[I] <> '') then 
            Strings.Add(FIniFile[I]); 
          Inc(I); 
        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 TQuickIni.WriteString(const Section, Ident: String; Value: String); 
var 
  I: Integer; 
  Q : integer; 
  s:string; 
begin 
  I := GetSectionIndex(Section); 
  s:=lowercase(ident); 
  // Section exists 
  if I >= 0 then 
  begin 
    Inc(I); 
    while (I < FIniFile.Count) and not IsSection(FIniFile[I]) 
      and (GetName(FIniFile[I]) <> s) do 
    begin 
      Inc(I); 
    end; 
    // End of File or Ident doesn't exists in the Section 
    if (I >= FIniFile.Count) then 
    begin 
      if Ident <> EmptyStr then 
      begin 
        FIniFile.Add(Ident + Separator + Value); 
      end 
    end 
    else if (I < FIniFile.Count) and IsSection(FIniFile[I]) then 
    begin 
      if Ident <> EmptyStr then 
      begin 
        FIniFile.Insert(I,Ident + Separator + Value); 
        Inc(I); 
        Q := FSections.IndexOf(FIniFile[I]); 
        FSections.Objects[Q] := TObject(I+1); 
      end 
    end 
    // Ident does exists in the section 
    else if Ident <> EmptyStr then 
    begin 
      FIniFile[I] := Ident + Separator + Value; 
    end; 
  end 
  // Section doesn't exists, so add new [Section] with Ident=Value 
  else 
  begin 
    I := FIniFile.Add(StartBracket + Section + EndBracket); 
    FSections.AddObject(StartBracket + Section + EndBracket,TObject(I)); 
    if Ident <> EmptyStr then 
    begin 
      FIniFile.Add(Ident + Separator + Value); 
    end; 
  end; 
//  SaveToFile; 
end; 
 
{ Writes an Integer-Value for Ident in one Section } 
 
procedure TQuickIni.WriteInteger(const Section, Ident: String; Value: Longint); 
begin 
  WriteString(Section, Ident, IntToStr(Value)); 
end; 
 
{ Writes a Bool-Value for Ident in one Section } 
 
procedure TQuickIni.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 TQuickIni.DeleteKey(const Section, Ident: String); 
var 
  I: Integer; 
begin 
  I := GetSectionIndex(Section); 
  if I <> -1 then 
  begin 
    Inc(I); 
    while (I < FIniFile.Count) and not IsSection(FIniFile[I]) and 
      (GetName(FIniFile[I]) <> Ident) do Inc(I); 
    // Ident does exists   
    if not (I >= FIniFile.Count) and not IsSection(FIniFile[I]) then 
    begin 
      FIniFile.Delete(I); 
//      SaveToFile; 
    end;   
  end; 
end; 
 
procedure TQuickIni.EraseSection(const Section: String); 
var 
  I: Integer; 
begin 
  I := GetSectionIndex(Section); 
  if I <> -1 then 
  begin 
    // Delete Section-Header 
    FIniFile.Delete(I); 
    // Delete Section-Items 
    while (I < FIniFile.Count) and not IsSection(FIniFile[I]) do 
      FIniFile.Delete(I); 
    if I > 0 then FIniFile.Insert(I, EmptyStr);   
//    SaveToFile; 
  end; 
end; 
 
procedure TQuickIni.SetFileName(Value: string); 
begin 
  if Value <> FFileName then 
  begin 
    FFileName := Value; 
//    if FileExists(Value) and FAuto then 
//      LoadFromFile; 
  end; 
end; 
 
procedure TQuickIni.SetIniFile(Value: TStrings); 
begin 
  FIniFile.Assign(Value); 
  RebuildSections; 
end; 
 
procedure TQuickIni.RebuildSections; 
Var 
  I : integer; 
  Count : integer; 
begin 
  FSections.Clear; 
  I := 0; 
  Count := FIniFile.Count; 
  while I < Count do 
  begin 
    if (FIniFile[I] <> '') and (FIniFile[I][1] = '[') and (FIniFile[I][Length(FIniFile[I])] = ']') then 
    begin 
      if assigned(FSections) then 
        FSections.AddObject(Trim(FIniFile[I]),TObject(I)); 
    end; 
    inc(I); 
  end; 
end; 
 
procedure TQuickIni.Clear; 
begin 
  FIniFile.Clear; 
  FSections.Clear; 
end; 
 
end.