浏览代码

* Fix bug ID #29414

git-svn-id: trunk@32961 -
michael 9 年之前
父节点
当前提交
2658637a01
共有 4 个文件被更改,包括 252 次插入57 次删除
  1. 1 0
      .gitattributes
  2. 1 0
      packages/fcl-base/examples/README.txt
  3. 61 0
      packages/fcl-base/examples/testini.pp
  4. 189 57
      packages/fcl-base/src/inifiles.pp

+ 1 - 0
.gitattributes

@@ -1988,6 +1988,7 @@ packages/fcl-base/examples/testcont.pp svneol=native#text/plain
 packages/fcl-base/examples/testexprpars.pp svneol=native#text/plain
 packages/fcl-base/examples/testexprpars.pp svneol=native#text/plain
 packages/fcl-base/examples/testez.pp svneol=native#text/plain
 packages/fcl-base/examples/testez.pp svneol=native#text/plain
 packages/fcl-base/examples/testhres.pp svneol=native#text/plain
 packages/fcl-base/examples/testhres.pp svneol=native#text/plain
+packages/fcl-base/examples/testini.pp svneol=native#text/plain
 packages/fcl-base/examples/testipc_client.pp svneol=native#text/plain
 packages/fcl-base/examples/testipc_client.pp svneol=native#text/plain
 packages/fcl-base/examples/testipc_server.pp svneol=native#text/plain
 packages/fcl-base/examples/testipc_server.pp svneol=native#text/plain
 packages/fcl-base/examples/testmime.pp svneol=native#text/plain
 packages/fcl-base/examples/testmime.pp svneol=native#text/plain

+ 1 - 0
packages/fcl-base/examples/README.txt

@@ -73,3 +73,4 @@ poolmm2.pp   Test for pooledmm (nonfree) (VS)
 testweb.pp   Test for fpcgi (MVC)
 testweb.pp   Test for fpcgi (MVC)
 daemon.pp    Test for daemonapp (MVC)
 daemon.pp    Test for daemonapp (MVC)
 testtimer.pp Test for TFPTimer (MVC)
 testtimer.pp Test for TFPTimer (MVC)
+testini.pp   Test/Demo for inifiles, ReadSectionValues.

+ 61 - 0
packages/fcl-base/examples/testini.pp

@@ -0,0 +1,61 @@
+program testini;
+
+{$mode objfpc}{$H+}
+
+uses
+  inifiles, classes;
+
+var
+  i: Integer;
+  ini: TMemIniFile;
+  lines: TStrings;
+
+begin
+  lines:=TStringList.Create();
+  try
+    lines.Add('[main]');
+    lines.Add('key_a=1');
+    lines.Add(';comment');
+    lines.Add('key_b   =2');
+    lines.Add('not_valid');
+    lines.Add('key_c=   3');
+    lines.Add('key_d="3"');
+    WriteLn('ini file source:');
+    for i:=0 to lines.Count-1 do 
+      WriteLn('  ', lines[i]);
+    ini:=TMemIniFile.Create('');
+    try
+      ini.options:=ini.options+[ifoStripQuotes];
+      ini.SetStrings(lines);
+      lines.Clear();
+      ini.ReadSectionValues('main', lines,[]);
+      WriteLn('ReadSectionValues (no options):');
+      for i:=0 to lines.Count-1 do 
+        WriteLn('  ', lines[i]);
+      lines.Clear();
+      ini.ReadSectionValues('main', lines,[svoIncludeComments]);
+      WriteLn('ReadSectionValues (with comments, no invalid):');
+      for i:=0 to lines.Count-1 do
+        WriteLn('  ', lines[i]);
+      lines.Clear();
+      ini.ReadSectionValues('main', lines,[svoIncludeInvalid]);
+      WriteLn('ReadSectionValues (without comments, with invalid):');
+      for i:=0 to lines.Count-1 do
+        WriteLn('  ', lines[i]);
+      lines.Clear();
+      ini.ReadSectionValues('main', lines,[svoIncludeComments,svoIncludeInvalid]);
+      WriteLn('ReadSectionValues (with comments, with invalid):');
+      for i:=0 to lines.Count-1 do
+        WriteLn('  ', lines[i]);
+      Lines.Clear;
+      ini.ReadSectionValues('main', lines,[svoIncludeQuotes]);
+      WriteLn('ReadSectionValues (with quotes):');
+      for i:=0 to lines.Count-1 do
+        WriteLn('  ', lines[i]);
+    finally
+      ini.Free();
+    end;
+  finally
+    lines.Free();
+  end
+end.

+ 189 - 57
packages/fcl-base/src/inifiles.pp

@@ -134,19 +134,31 @@ type
     property Items[Index: integer]: TIniFileSection read GetItem; default;
     property Items[Index: integer]: TIniFileSection read GetItem; default;
   end;
   end;
 
 
+  TIniFileOption = (ifoStripComments,    // Strip comments when reading file
+                    ifoStripInvalid,     // Strip invalid lines when reading file.
+                    ifoEscapeLineFeeds, // Escape linefeeds when reading file.
+                    ifoCaseSensitive,   // Use Case sensitive section/key names
+                    ifoStripQuotes,     // Strip quotes when reading string values.
+                    ifoFormatSettingsActive); // Use format settings when writing date/float etc.
+  TIniFileOptions = Set of TIniFileOption;
+
+  TSectionValuesOption = (svoIncludeComments,svoIncludeInvalid, svoIncludeQuotes);
+  TSectionValuesOptions = set of TSectionValuesOption;
+
   { TCustomIniFile }
   { TCustomIniFile }
 
 
   TCustomIniFile = class
   TCustomIniFile = class
   Private
   Private
     FFileName: string;
     FFileName: string;
+    FOptions: TIniFileOptions;
     FSectionList: TIniFileSectionList;
     FSectionList: TIniFileSectionList;
-    FEscapeLineFeeds: boolean;
-    FCaseSensitive : Boolean;
-    FStripQuotes : Boolean;
-    FFormatSettingsActive: Boolean;
+    function GetOption(AIndex: TIniFileOption): Boolean;
+    procedure SetOption(AIndex: TIniFileOption; AValue: Boolean);
+    procedure SetOptions(AValue: TIniFileOptions);
   public
   public
     FormatSettings: TFormatSettings;
     FormatSettings: TFormatSettings;
-    constructor Create(const AFileName: string; AEscapeLineFeeds : Boolean = False); virtual;
+    constructor Create(const AFileName: string; AOptions : TIniFileOptions = []); virtual;
+    constructor Create(const AFileName: string; AEscapeLineFeeds : Boolean); virtual;
     destructor Destroy; override;
     destructor Destroy; override;
     function SectionExists(const Section: string): Boolean; virtual;
     function SectionExists(const Section: string): Boolean; virtual;
     function ReadString(const Section, Ident, Default: string): string; virtual; abstract;
     function ReadString(const Section, Ident, Default: string): string; virtual; abstract;
@@ -169,16 +181,18 @@ type
     procedure WriteBinaryStream(const Section, Name: string; Value: TStream); virtual;
     procedure WriteBinaryStream(const Section, Name: string; Value: TStream); virtual;
     procedure ReadSection(const Section: string; Strings: TStrings); virtual; abstract;
     procedure ReadSection(const Section: string; Strings: TStrings); virtual; abstract;
     procedure ReadSections(Strings: TStrings); virtual; abstract;
     procedure ReadSections(Strings: TStrings); virtual; abstract;
-    procedure ReadSectionValues(const Section: string; Strings: TStrings); virtual; abstract;
+    procedure ReadSectionValues(const Section: string; Strings: TStrings; Options : TSectionValuesOptions); virtual;    overload;
+    procedure ReadSectionValues(const Section: string; Strings: TStrings); virtual;overload;
     procedure EraseSection(const Section: string); virtual; abstract;
     procedure EraseSection(const Section: string); virtual; abstract;
     procedure DeleteKey(const Section, Ident: String); virtual; abstract;
     procedure DeleteKey(const Section, Ident: String); virtual; abstract;
     procedure UpdateFile; virtual; abstract;
     procedure UpdateFile; virtual; abstract;
     function ValueExists(const Section, Ident: string): Boolean; virtual;
     function ValueExists(const Section, Ident: string): Boolean; virtual;
     property FileName: string read FFileName;
     property FileName: string read FFileName;
-    property EscapeLineFeeds: boolean read FEscapeLineFeeds;
-    Property CaseSensitive : Boolean Read FCaseSensitive Write FCaseSensitive;
-    Property StripQuotes : Boolean Read FStripQuotes Write FStripQuotes;
-    Property FormatSettingsActive: Boolean Read FFormatSettingsActive write FFormatSettingsActive;
+    Property Options : TIniFileOptions Read FOptions Write SetOptions;
+    property EscapeLineFeeds: boolean index ifoEscapeLineFeeds Read GetOption ;deprecated 'Use options instead';
+    Property CaseSensitive : Boolean index ifoCaseSensitive Read GetOption Write SetOption; deprecated  'Use options instead';
+    Property StripQuotes : Boolean index ifoStripQuotes Read GetOption Write SetOption; deprecated 'Use options instead';
+    Property FormatSettingsActive : Boolean index ifoFormatSettingsActive Read GetOption Write SetOption;deprecated  'Use options instead';
   end;
   end;
 
 
   { TIniFile }
   { TIniFile }
@@ -197,15 +211,16 @@ type
     procedure MaybeUpdateFile;
     procedure MaybeUpdateFile;
     property Dirty : Boolean Read FDirty;
     property Dirty : Boolean Read FDirty;
   public
   public
-    constructor Create(const AFileName: string; AEscapeLineFeeds : Boolean = False); overload; override;
-    constructor Create(AStream: TStream; AEscapeLineFeeds : Boolean = False); overload;
+    constructor Create(const AFileName: string; AOptions : TIniFileoptions = []); overload; override;
+    constructor Create(AStream: TStream; AOptions : TIniFileoptions = []); overload;
+    constructor Create(AStream: TStream; AEscapeLineFeeds : Boolean); overload; deprecated 'Use Options argument instead';
     destructor Destroy; override;
     destructor Destroy; override;
     function ReadString(const Section, Ident, Default: string): string; override;
     function ReadString(const Section, Ident, Default: string): string; override;
     procedure WriteString(const Section, Ident, Value: String); override;
     procedure WriteString(const Section, Ident, Value: String); override;
     procedure ReadSection(const Section: string; Strings: TStrings); override;
     procedure ReadSection(const Section: string; Strings: TStrings); override;
     procedure ReadSectionRaw(const Section: string; Strings: TStrings);
     procedure ReadSectionRaw(const Section: string; Strings: TStrings);
     procedure ReadSections(Strings: TStrings); override;
     procedure ReadSections(Strings: TStrings); override;
-    procedure ReadSectionValues(const Section: string; Strings: TStrings); override;
+    procedure ReadSectionValues(const Section: string; Strings: TStrings; AOptions : TSectionValuesOptions = []); overload; override;
     procedure EraseSection(const Section: string); override;
     procedure EraseSection(const Section: string); override;
     procedure DeleteKey(const Section, Ident: String); override;
     procedure DeleteKey(const Section, Ident: String); override;
     procedure UpdateFile; override;
     procedure UpdateFile; override;
@@ -510,11 +525,34 @@ end;
 
 
 { TCustomIniFile }
 { TCustomIniFile }
 
 
-constructor TCustomIniFile.Create(const AFileName: string; AEscapeLineFeeds : Boolean = False);
+
+function TCustomIniFile.GetOption(AIndex: TIniFileOption): Boolean;
+begin
+  Result:=AIndex in FOptions;
+end;
+
+
+procedure TCustomIniFile.SetOption(AIndex: TIniFileOption; AValue: Boolean);
+begin
+  if AIndex in [ifoStripComments,ifoStripInvalid] then
+    Raise Exception.Create('Flags ifoStripComments or ifoStripInvalid must be set/unset in the constructor');
+  if AValue then
+    Include(FOptions,AIndex)
+  else
+    Exclude(FOptions,AIndex)
+end;
+
+procedure TCustomIniFile.SetOptions(AValue: TIniFileOptions);
+begin
+  if FOptions=AValue then Exit;
+  FOptions:=AValue;
+end;
+
+constructor TCustomIniFile.Create(const AFileName: string; AOptions : TIniFileOptions = []);
 begin
 begin
   FFileName := AFileName;
   FFileName := AFileName;
   FSectionList := TIniFileSectionList.Create;
   FSectionList := TIniFileSectionList.Create;
-  FEscapeLineFeeds := AEscapeLineFeeds;
+  FOptions:=AOptions;
   FormatSettings := DefaultFormatSettings;
   FormatSettings := DefaultFormatSettings;
   with FormatSettings do begin
   with FormatSettings do begin
     DecimalSeparator := '.';
     DecimalSeparator := '.';
@@ -528,6 +566,15 @@ begin
   end;
   end;
 end;
 end;
 
 
+constructor TCustomIniFile.Create(const AFileName: string;
+  AEscapeLineFeeds: Boolean);
+begin
+  if AEscapeLineFeeds then
+    Create(AFileName,[ifoEscapeLineFeeds])
+  else
+    Create(AFileName,[])
+end;
+
 destructor TCustomIniFile.Destroy;
 destructor TCustomIniFile.Destroy;
 begin
 begin
   FSectionList.Free;
   FSectionList.Free;
@@ -584,7 +631,7 @@ end;
 function TCustomIniFile.ReadDate(const Section, Ident: string; Default: TDateTime): TDateTime;
 function TCustomIniFile.ReadDate(const Section, Ident: string; Default: TDateTime): TDateTime;
 
 
 begin
 begin
-  if FFormatSettingsActive then begin
+  if FormatSettingsActive then begin
     if not TryStrToDate(ReadString(Section, Ident, ''), Result, FormatSettings) then
     if not TryStrToDate(ReadString(Section, Ident, ''), Result, FormatSettings) then
       Result := Default;
       Result := Default;
   end else
   end else
@@ -594,7 +641,7 @@ end;
 function TCustomIniFile.ReadDateTime(const Section, Ident: string; Default: TDateTime): TDateTime;
 function TCustomIniFile.ReadDateTime(const Section, Ident: string; Default: TDateTime): TDateTime;
 
 
 begin
 begin
-  if FFormatSettingsActive then begin
+  if FormatSettingsActive then begin
     if not TryStrToDateTime(ReadString(Section, Ident, ''), Result, FormatSettings) then
     if not TryStrToDateTime(ReadString(Section, Ident, ''), Result, FormatSettings) then
       Result := Default;
       Result := Default;
   end else
   end else
@@ -604,7 +651,7 @@ end;
 function TCustomIniFile.ReadFloat(const Section, Ident: string; Default: Double): Double;
 function TCustomIniFile.ReadFloat(const Section, Ident: string; Default: Double): Double;
 
 
 begin
 begin
-  if FFormatSettingsActive then
+  if FormatSettingsActive then
     Result:=StrToFloatDef(ReadString(Section, Ident, ''),Default, FormatSettings)
     Result:=StrToFloatDef(ReadString(Section, Ident, ''),Default, FormatSettings)
   else
   else
     Result:=StrToFloatDef(ReadString(Section, Ident, ''),Default);
     Result:=StrToFloatDef(ReadString(Section, Ident, ''),Default);
@@ -613,7 +660,7 @@ end;
 function TCustomIniFile.ReadTime(const Section, Ident: string; Default: TDateTime): TDateTime;
 function TCustomIniFile.ReadTime(const Section, Ident: string; Default: TDateTime): TDateTime;
 
 
 begin
 begin
-  if FFormatSettingsActive then
+  if FormatSettingsActive then
     Result := StrToTimeDef(ReadString(Section, Ident, ''),Default, FormatSettings.TimeSeparator)
     Result := StrToTimeDef(ReadString(Section, Ident, ''),Default, FormatSettings.TimeSeparator)
   else
   else
     Result := StrToTimeDef(ReadString(Section, Ident, ''),Default);
     Result := StrToTimeDef(ReadString(Section, Ident, ''),Default);
@@ -621,7 +668,7 @@ end;
 
 
 procedure TCustomIniFile.WriteDate(const Section, Ident: string; Value: TDateTime);
 procedure TCustomIniFile.WriteDate(const Section, Ident: string; Value: TDateTime);
 begin
 begin
-  if FFormatSettingsActive then
+  if FormatSettingsActive then
     WriteString(Section, Ident, DateToStr(Value, FormatSettings))
     WriteString(Section, Ident, DateToStr(Value, FormatSettings))
   else
   else
     WriteString(Section, Ident, DateToStr(Value));
     WriteString(Section, Ident, DateToStr(Value));
@@ -629,7 +676,7 @@ end;
 
 
 procedure TCustomIniFile.WriteDateTime(const Section, Ident: string; Value: TDateTime);
 procedure TCustomIniFile.WriteDateTime(const Section, Ident: string; Value: TDateTime);
 begin
 begin
-  if FFormatSettingsActive then
+  if FormatSettingsActive then
     WriteString(Section, Ident, DateTimeToStr(Value, FormatSettings))
     WriteString(Section, Ident, DateTimeToStr(Value, FormatSettings))
   else
   else
     WriteString(Section, Ident, DateTimeToStr(Value));
     WriteString(Section, Ident, DateTimeToStr(Value));
@@ -637,7 +684,7 @@ end;
 
 
 procedure TCustomIniFile.WriteFloat(const Section, Ident: string; Value: Double);
 procedure TCustomIniFile.WriteFloat(const Section, Ident: string; Value: Double);
 begin
 begin
-  if FFormatSettingsActive then
+  if FormatSettingsActive then
     WriteString(Section, Ident, FloatToStr(Value, FormatSettings))
     WriteString(Section, Ident, FloatToStr(Value, FormatSettings))
   else
   else
     WriteString(Section, Ident, FloatToStr(Value));
     WriteString(Section, Ident, FloatToStr(Value));
@@ -645,7 +692,7 @@ end;
 
 
 procedure TCustomIniFile.WriteTime(const Section, Ident: string; Value: TDateTime);
 procedure TCustomIniFile.WriteTime(const Section, Ident: string; Value: TDateTime);
 begin
 begin
-  if FFormatSettingsActive then
+  if FormatSettingsActive then
     WriteString(Section, Ident, TimeToStr(Value, FormatSettings))
     WriteString(Section, Ident, TimeToStr(Value, FormatSettings))
   else
   else
     WriteString(Section, Ident, TimeToStr(Value));
     WriteString(Section, Ident, TimeToStr(Value));
@@ -698,7 +745,8 @@ begin
     end;
     end;
 end;
 end;
 
 
-procedure TCustomInifile.WriteBinaryStream(const Section, Name: string; Value: TStream);
+procedure TCustomIniFile.WriteBinaryStream(const Section, Name: string;
+  Value: TStream);
 
 
 
 
 Var
 Var
@@ -733,16 +781,54 @@ begin
   end;
   end;
 end;
 end;
 
 
+procedure TCustomIniFile.ReadSectionValues(const Section: string; Strings: TStrings; Options: TSectionValuesOptions);
+
+type
+  TOldSectionValues = Procedure (const Section: string; Strings: TStrings) of object;
+
+var
+  CurrSV,
+  TCustomSV: TOldSectionValues;
+  CurrClass   : TClass;
+
+begin
+  if (Options<>[]) then
+    Raise Exception.Create('Options not supported, options must be empty');
+  // Redirect calls to old implementation, if it is overridden.
+  CurrSV:=nil;
+  CurrClass:=Classtype;
+  while (CurrClass<>nil) and (CurrClass<>TCustomIniFile) do
+   CurrClass:=CurrClass.Classparent;
+  if CurrClass<>nil then
+    begin
+    CurrSV:[email protected];
+    TCustomSV:=@TCustomIniFile(@CurrClass).ReadSectionValues;
+    if TMethod(TCustomSV).Code=TMethod(CurrSV).Code then
+      CurrSV:=nil;
+   end;
+  if Assigned(CurrSV) then
+    ReadSectionValues(Section,Strings)
+  else
+    Raise Exception.Create('ReadSectionValues not overridden');
+end;
+
+procedure TCustomIniFile.ReadSectionValues(const Section: string;
+  Strings: TStrings);
+begin
+  ReadSectionValues(Section,Strings,[]);
+end;
+
 { TIniFile }
 { TIniFile }
 
 
-constructor TIniFile.Create(const AFileName: string; AEscapeLineFeeds : Boolean = False);
+
+constructor TIniFile.Create(const AFileName: string; AOptions : TIniFileOptions = []);
 var
 var
   slLines: TStringList;
   slLines: TStringList;
 begin
 begin
   FBOM := '';
   FBOM := '';
   If Not (self is TMemIniFile) then
   If Not (self is TMemIniFile) then
     StripQuotes:=True;
     StripQuotes:=True;
-  inherited Create(AFileName,AEscapeLineFeeds);
+  inherited Create(AFileName,AOptions);
   FStream := nil;
   FStream := nil;
   slLines := TStringList.Create;
   slLines := TStringList.Create;
   try
   try
@@ -757,12 +843,23 @@ begin
   end;
   end;
 end;
 end;
 
 
-constructor TIniFile.Create(AStream: TStream; AEscapeLineFeeds : Boolean = False);
+constructor TIniFile.Create(AStream: TStream; AEscapeLineFeeds : Boolean);
+
+begin
+  if AEscapeLineFeeds then
+    Create(AStream,[ifoEscapeLineFeeds])
+  else
+    Create(AStream,[]);
+end;
+
+constructor TIniFile.Create(AStream: TStream; AOptions : TIniFileOptions = []);
+
 var
 var
   slLines: TStringList;
   slLines: TStringList;
+
 begin
 begin
   FBOM := '';
   FBOM := '';
-  inherited Create('',AEscapeLineFeeds);
+  inherited Create('',AOptions);
   FStream := AStream;
   FStream := AStream;
   slLines := TStringList.Create;
   slLines := TStringList.Create;
   try
   try
@@ -818,10 +915,13 @@ var
     end;
     end;
   end;
   end;
 
 
+Var
+  addKey : Boolean;
+
 begin
 begin
   oSection := nil;
   oSection := nil;
   FSectionList.Clear;
   FSectionList.Clear;
-  if FEscapeLineFeeds then
+  if EscapeLineFeeds then
     RemoveBackslashes;
     RemoveBackslashes;
   if (AStrings.Count > 0) and (copy(AStrings.Strings[0],1,Length(Utf8Bom)) = Utf8Bom) then
   if (AStrings.Count > 0) and (copy(AStrings.Strings[0],1,Length(Utf8Bom)) = Utf8Bom) then
   begin
   begin
@@ -832,37 +932,51 @@ begin
     sLine := Trim(AStrings[i]);
     sLine := Trim(AStrings[i]);
     if sLine > '' then
     if sLine > '' then
       begin
       begin
-      if IsComment(sLine) and (oSection = nil) then begin
+      if IsComment(sLine) and (oSection = nil) then
+        begin
         // comment at the beginning of the ini file
         // comment at the beginning of the ini file
-        oSection := TIniFileSection.Create(sLine);
-        FSectionList.Add(oSection);
+        if Not (ifoStripComments in Options) then
+          begin
+          oSection := TIniFileSection.Create(sLine);
+          FSectionList.Add(oSection);
+          end;
         continue;
         continue;
-      end;
-      if (Copy(sLine, 1, 1) = Brackets[0]) and (Copy(sLine, length(sLine), 1) = Brackets[1]) then begin
+        end;
+      if (Copy(sLine, 1, 1) = Brackets[0]) and (Copy(sLine, length(sLine), 1) = Brackets[1]) then
+        begin
         // regular section
         // regular section
         oSection := TIniFileSection.Create(Copy(sLine, 2, Length(sLine) - 2));
         oSection := TIniFileSection.Create(Copy(sLine, 2, Length(sLine) - 2));
         FSectionList.Add(oSection);
         FSectionList.Add(oSection);
-      end else if oSection <> nil then begin
-        if IsComment(sLine) then begin
+        end
+      else if oSection <> nil then
+        begin
+        if IsComment(sLine) then
+          begin
+          AddKey:=Not (ifoStripComments in Options);
           // comment within a section
           // comment within a section
           sIdent := sLine;
           sIdent := sLine;
           sValue := '';
           sValue := '';
-        end else begin
+          end
+        else
+          begin
           // regular key
           // regular key
           j:=Pos(Separator, sLine);
           j:=Pos(Separator, sLine);
           if j=0 then
           if j=0 then
            begin
            begin
-             sIdent:='';
-             sValue:=sLine
+           AddKey:=Not (ifoStripInvalid in Options);
+           sIdent:='';
+           sValue:=sLine
            end
            end
           else
           else
            begin
            begin
-             sIdent:=Trim(Copy(sLine, 1,  j - 1));
-             sValue:=Trim(Copy(sLine, j + 1, Length(sLine) - j));
+           AddKey:=True;
+           sIdent:=Trim(Copy(sLine, 1,  j - 1));
+           sValue:=Trim(Copy(sLine, j + 1, Length(sLine) - j));
            end;
            end;
         end;
         end;
-        oSection.KeyList.Add(TIniFileKey.Create(sIdent, sValue));
-      end;
+        if AddKey then
+          oSection.KeyList.Add(TIniFileKey.Create(sIdent, sValue));
+        end;
       end;
       end;
   end;
   end;
 end;
 end;
@@ -982,31 +1096,49 @@ begin
   end;
   end;
 end;
 end;
 
 
-procedure TIniFile.ReadSectionValues(const Section: string; Strings: TStrings);
+procedure TIniFile.ReadSectionValues(const Section: string; Strings: TStrings; AOptions : TSectionValuesOptions = []);
 var
 var
   oSection: TIniFileSection;
   oSection: TIniFileSection;
   s: string;
   s: string;
   i,J: integer;
   i,J: integer;
+  KeyIsComment,IncludeComments,IncludeInvalid,DoStripQuotes : boolean;
+  K : TIniFileKey;
+
 begin
 begin
+  IncludeComments:=(svoIncludeComments in AOptions) Or (ifoStripComments in Options);
+  IncludeInvalid:=(svoIncludeInvalid in AOptions) Or (ifoStripInvalid in Options);
+  DoStripQuotes:=StripQuotes and Not (svoIncludeQuotes in AOptions);
   Strings.BeginUpdate;
   Strings.BeginUpdate;
   try
   try
     Strings.Clear;
     Strings.Clear;
     oSection := FSectionList.SectionByName(Section,CaseSensitive);
     oSection := FSectionList.SectionByName(Section,CaseSensitive);
-    if oSection <> nil then with oSection.KeyList do
-      for i := 0 to Count-1 do begin
-        s := Items[i].Value;
-      If StripQuotes then
+    if oSection = nil then
+      Exit;
+    for i := 0 to oSection.KeyList.Count-1 do
+      begin
+      K:=oSection.KeyList.Items[i];
+      if IncludeInvalid or (K.Ident<>'') then
         begin
         begin
-          J:=Length(s);
-          // Joost, 2-jan-2007: The check (J>1) is there for the case that
-          // the value consist of a single double-quote character. (see
-          // mantis bug 6555)
-          If (J>1) and ((s[1] in ['"','''']) and (s[J]=s[1])) then
-             s:=Copy(s,2,J-2);
+        s := K.Value;
+        KeyIsComment:=IsComment(K.Ident);
+        if IncludeComments Or Not KeyIsComment then
+          begin
+          If DoStripQuotes then
+            begin
+            J:=Length(s);
+            // Joost, 2-jan-2007: The check (J>1) is there for the case that
+            // the value consist of a single double-quote character. (see
+            // mantis bug 6555)
+            If (J>1) and ((s[1] in ['"','''']) and (s[J]=s[1])) then
+               s:=Copy(s,2,J-2);
+            end;
+          if KeyIsComment then
+            S:=K.Ident
+          else if k.ident<>'' then
+            s:=K.Ident+Separator+s;
+          Strings.Add(s);
+          end;
         end;
         end;
-        if Items[i].Ident<>'' then
-          s:=Items[i].Ident+Separator+s;
-        Strings.Add(s);
       end;
       end;
   finally
   finally
     Strings.EndUpdate;
     Strings.EndUpdate;