{$ifdef read_interface} type PIniFile = ^TIniFile; { TIniFile } TIniFile = object( TObj ) private procedure SetMode(const AValue: TIniFileMode); protected fMode: TIniFileMode; fFileName: KOLString; fSection: KOLString; fData: PStrList; protected function FindSection(var First, Last: Integer): Boolean; function FindKey(Key: String; First, Last: Integer; var Value: String): Integer; public destructor Destroy; virtual; property Mode: TIniFileMode read fMode write SetMode; property FileName: KOLString read fFileName; property Section: KOLString read fSection write fSection; function ValueInteger( const Key: KOLString; Value: Integer ): Integer; function ValueString( const Key: KOLString; const Value: KOLString ): KOLString; function ValueBoolean( const Key: KOLString; Value: Boolean ): Boolean; function ValueData( const Key: KOLString; Value: Pointer; Count: Integer ): Boolean; procedure ClearAll; procedure ClearSection; procedure ClearKey( const Key: KOLString ); procedure GetSectionNames(Names: {$IFNDEF UNICODE_CTRLS}PStrList{$ELSE}PWStrList{$ENDIF}); procedure SectionData(Names: {$IFNDEF UNICODE_CTRLS}PStrList{$ELSE}PWStrList{$ENDIF}); procedure UpdateFile; end; {$endif read_interface} {$ifdef read_implementation} function OpenIniFile( const FileName: KOLString ): PIniFile; begin New(Result, Create); Result.fFileName := FileName; Result.fData:= NewStrList; Result.fMode:= ifmRead; Result.fData.LoadFromFile(FileName); end; function GetSection(var S: String): Boolean; var L: Integer; begin S:= Trim(S); L:= Length(S); Result:= (L > 2) and (S[1] = '[') and (S[L] = ']'); if Result then begin Delete(S, L, 1); Delete(S, 1, 1); S:= Trim(S); // Result:= (S <> ''); end; end; procedure TIniFile.ClearAll; begin fData.Clear; fData.SaveToFile(fFileName); end; procedure TIniFile.ClearKey(const Key: KOLString); var k, F, L: Integer; S: String; begin if FindSection(F, L) then begin k:= FindKey(Key, F, L, S); if k >= 0 then fData.Delete(k); fData.SaveToFile(fFileName); end; end; procedure TIniFile.ClearSection; var i, F, L: Integer; begin if FindSection(F, L) then begin for i := L downto F do begin fData.Delete(i); end; fData.SaveToFile(fFileName); end; end; destructor TIniFile.Destroy; begin if fMode = ifmWrite then fData.SaveToFile(fFileName); fData.Free; fFileName := ''; fSection := ''; inherited; end; procedure TIniFile.GetSectionNames(Names: {$IFNDEF UNICODE_CTRLS}PStrList{$ELSE}PWStrList{$ENDIF}); var i: Integer; S: String; begin for i:= 0 to fData.Count-1 do begin S:= fData.Items[i]; if GetSection(S) then Names.Add(S) end; end; procedure TIniFile.SectionData(Names: {$IFNDEF UNICODE_CTRLS}PStrList{$ELSE}PWStrList{$ENDIF}); var i, F, L: Integer; S: String; begin if fMode = ifmRead then begin if FindSection(F, L) then for i := F+1 to L do begin S:= Trim(fData.Items[i]); if S <> '' then Names.Add(S); end; end else begin ClearSection; fData.Add('[' + fSection + ']'); for i:= 0 to Names.Count-1 do begin S:= Trim(Names.Items[i]); if S <> '' then fData.Add(S); end; end; end; procedure TIniFile.UpdateFile; begin if fMode = ifmRead then fData.LoadFromFile(fFileName) else fData.SaveToFile(fFileName); end; function TIniFile.ValueBoolean(const Key: KOLString; Value: Boolean): Boolean; begin Result:= ValueInteger(Key, Ord(Value)) <> 0; end; function TIniFile.ValueData(const Key: KOLString; Value: Pointer; Count: Integer): Boolean; var i: Integer; S: String; begin if fMode = ifmRead then begin S:= ValueString(Key, ''); for i:= 0 to Min(Length(S) div 2, Count) - 1 do begin PByte(Value)^:= Hex2Int(Copy(S, 1+i*2, 2)); cardinal(Value):= cardinal(Value) + 1; Result:= True; end; end else begin S:= ''; for i:= 0 to Count - 1 do begin S:= S + Int2Hex(PByte(Value)^, 2); cardinal(Value):= cardinal(Value) + 1; Result:= True; end; ValueString(Key, S); end; end; function TIniFile.ValueInteger(const Key: KOLString; Value: Integer): Integer; begin Result:= Str2Int(ValueString(Key, Int2Str(Value))); end; function TIniFile.ValueString( const Key: KOLString; const Value: KOLString ): KOLString; var k, F, L: Integer; S: String; fSect: Boolean; begin fSect:= FindSection(F, L); if fSect then k:= FindKey(Key, F, L, S) else k:= -1; if fMode = ifmRead then begin if fSect and (k > 0) then Result:= S else Result := Value; end else begin if not fSect then begin fData.Add('[' + fSection + ']'); fData.Add(''); k:= fData.Count-1; end; if k < 0 then begin k:= L+1; fData.Insert(k, ''); end; fData.Items[k]:= Key+'='+Value; end; end; procedure TIniFile.SetMode(const AValue: TIniFileMode); begin if fMode = AValue then Exit; if fMode = ifmWrite then fData.SaveToFile(fFileName) else fData.LoadFromFile(fFileName); fMode:= AValue; end; function TIniFile.FindSection(var First, Last: Integer): Boolean; var i: Integer; Sec, S: String; begin Result:= False; Sec := Trim(fSection); for i:= 0 to fData.Count-1 do begin S:= fData.Items[i]; if GetSection(S) and (AnsiCompareStrNoCase(S, Sec) = 0) then begin First:= i; Result:= True; Break; end; end; if Result then begin for i:= First+1 to fData.Count-1 do begin S:= fData.Items[i]; if GetSection(S) then begin Last:= i-1; Exit; end; end; Last:= fData.Count-1; end; end; function TIniFile.FindKey(Key: String; First, Last: Integer; var Value: String): Integer; var i, k: Integer; S: String; begin Result:= -1; Key:= Trim(Key); for i:= First to Last do begin S:= fData.Items[i]; k:= Pos('=', S); if k > 0 then begin if AnsiCompareStrNoCase(Key, Trim(Copy(S, 1, k-1))) = 0 then Result:= i; if Result >= 0 then begin Delete(S, 1, k); Value:= Trim(S); k:= Length(Value); if (k > 0) and (Value[1] = '"') and (Value[k] = '"') then begin Delete(Value, k, 1); Delete(Value, 1, 1); end; Exit; end; end; end; end; {$endif read_implementation}