This project is read-only.
1
Vote

Ini documents with comments are not read correctly

description

When reading ini documents that contains comment lines (a line starting with a semi colon) the parser doesn't handle the cr+lf characters at the end of the line correctly.
 
The result is that the sections and properties after the comment are not parsed correctly. It can also result in the following exception:
System.ArgumentNullException : Key cannot be null.
Parameter name: key
at System.Collections.Hashtable.get_Item(Object key)
at ComLib.ConfigSectionUtils.Add(IDictionary dictionary, String key, Object val, Boolean overWrite)
at ComLib.ConfigSection.AddMulti(String key, Object val, Boolean overWrite)
at ComLib.IO.IniDocument.<Load>b__2(IniSection s)
at System.Collections.Generic.List1.ForEach(Action1 action)
at ComLib.IO.IniDocument.Load()
at ComLib.IO.IniDocument.Init(String name, String iniContentOrFilePath, Boolean isFilePath, Boolean isCaseSensitive)
at ComLib.IO.IniDocument..ctor(String name, String iniContentOrFilePath, Boolean isFilePath, Boolean isCaseSensitive)
at ComLib.IO.IniDocument..ctor(String iniContentOrFilePath, Boolean isFilePath)
 
I've added the following unit-test that shows the incorrect behavior:
 
[Test]
public void CanParseComments()
{
string iniContent = "; Global application settings" + Environment.NewLine
                    + "" + Environment.NewLine
                    + "[globalSettings]" + Environment.NewLine
                    + "time: all" + Environment.NewLine
                    + "; define the categories" + Environment.NewLine
                    + "category: Art,Drawing";
 
IniDocument document = new IniDocument(iniContent, false);
 
Assert.IsTrue(document.Contains("globalSettings"));
Assert.AreEqual(document["globalSettings", "time"], "all");
Assert.AreEqual(document["globalSettings", "category"], "Art,Drawing");
}
 
I've made a patch in the IniDocument.Process() method. It fixes the problem but I'm not entirely sure if it is the best solution.
 
Note: I've added "readNextChar = false;" after the line with "string comment = _reader.ReadToEol();"
 
private void Process()
{
// Move to first char.
_reader.ReadChar();
 
// Consume End Of Line.
_reader.ConsumeNewLines();
bool readNextChar = true;
// While not end of content.
while ( !_reader.IsEnded() )
{
    // Get the current char.
    char currentChar = _reader.CurrentChar;
 
    if (currentChar == '[')
    {
        StoreGroup();
        readNextChar = false;
    }
    else if (currentChar == ';' )
    {
        string comment = _reader.ReadToEol();
        readNextChar = false;
    }
    else if (_reader.IsEol())
    {
        _reader.ConsumeNewLines();
        readNextChar = false;
    }
    else
    {
        StoreKeyValue();
        _reader.ConsumeNewLines();
        readNextChar = false;
    }
 
    // Read the next char.
    if(readNextChar) _reader.ReadChar();
}
 
// Add the last section.
// Handle null/emtpy sections.
if(_currentSection.Count > 0 && !string.IsNullOrEmpty(_currentSection.Name))
    _sections.Add(_currentSection);
}

comments

RemkoJansen wrote Aug 30, 2012 at 2:57 PM

Correction to the above patch.
The patch is not for the method IniDocument.Process() but for IniParser.Process(), located in the same source file: trunk\src\Lib\CommonLibrary.NET\IO\IniDocument.cs

wrote Feb 22, 2013 at 1:03 AM