Int32
CIniParser::FindIndexOfNonQuotedEquals( const CString& testString )
{GUCEF_TRACE;

    Int32 equalsIndex = testString.HasChar( '=', 0, true );
    if ( equalsIndex > -1 )
    {
        Int32 dummy = 0;
        if ( IsCharIndexWithinQuotes( testString  ,
                                      equalsIndex ,
                                      dummy       ,
                                      dummy       ) )
        {
            // this is not the equals we want, it is quoted
            // lets try again
            // we will allow:
            //     " my key with a = string " = " my value "
            // where there is whitespace after the quoted section
            equalsIndex = testString.HasChar( '=', equalsIndex+1, true );
            if ( equalsIndex > -1 )
            {
                if ( !IsCharIndexWithinQuotes( testString  ,
                                               equalsIndex ,
                                               dummy       ,
                                               dummy       ) )
                {
                    return equalsIndex;
                }
                // else:
                // this is not valid, the quoted section should have been followed by a
                // non quoted equals
            }
        }
        else
        {
            // There are no quotes surrounding this equals so we are done
            return equalsIndex;
        }
    }
    return -1;
}
bool
CIniParser::LoadFrom( CIOAccess& fileAccess )
{GUCEF_TRACE;

    // @TODO: take escape sequences into account
    if ( fileAccess.IsValid() )
    {
        bool isNewSection = true;
        CString sectionName;
        while ( !fileAccess.Eof() )
        {
            // Get the current line from the file, trimming white space on both ends
            CString line = fileAccess.ReadLine().Trim( true ).Trim( false );
            if( line.Length() > 0 )
            {
                // Get rid of any trailing commentary on this line
                Int32 commentaryIndex = line.HasChar( ';', false );
                if ( commentaryIndex > -1 )
                {
                    Int32 dummy = 0;
                    if ( !IsCharIndexWithinQuotes( line, commentaryIndex, dummy, dummy ) )
                    {
                        // we found a semicolon which is not contained within a quotation
                        // thus this is a commentary section which we should remove
                        line = line.CutChars( line.Length()-commentaryIndex, false ).Trim( false );
                    }
                }

                if( line.Length() > 0 )
                {
                    // Check if this is a section tag line
                    if ( ( line[ 0 ] == '[' ) && ( line[ line.Length()-1 ] == ']' ) )
                    {
                        sectionName = line.SubstrFromRange( 1, line.Length()-1 );
                        isNewSection = true;
                    }
                    else
                    {
                        Int32 equalsIndex = FindIndexOfNonQuotedEquals( line );
                        if ( equalsIndex > -1 )
                        {
                            // get the key and value strings
                            CString sectionBeforeEquals = StripQuotation( line.SubstrFromRange( 0, equalsIndex ) );
                            CString sectionAfterEquals = StripQuotation( line.SubstrFromRange( equalsIndex+1, line.Length() ) );

                            if ( ( sectionBeforeEquals.Length() > 0 ) &&
                                 ( sectionAfterEquals.Length() > 0 )   )
                            {
                                if ( isNewSection )
                                {
                                    TIniSection dummySection;
                                    m_iniData.push_back( dummySection );
                                    TIniSection& newSection = (*m_iniData.rbegin());
                                    newSection.sectionName = sectionName;
                                    newSection.sectionData.SetAllowDuplicates( true );
                                    newSection.sectionData.SetAllowMultipleValues( true );

                                    isNewSection = false;
                                }

                                TIniSection& newSection = (*m_iniData.rbegin());
                                newSection.sectionData.Set( sectionBeforeEquals, sectionAfterEquals );
                            }
                        }
                        // else:
                        // Line with junk on it we do not support
                        // we will try and be robust and ignore this line
                    }
                }
            }
        }
        return true;
    }
    return false;
}