// ############################################################################################# // file IO // ############################################################################################# /** **************************************************************************************** * Clears all configuration data and reads the file. It might happen that lines are * ignored or otherwise marked as faulty. All numbers of such lines get collected in * field LinesWithReadErrors. * @return Returns the #Status of the operation. ******************************************************************************************/ public IniFile.Status ReadFile() { Reset(); LastStatus= Status.OK; // read all variables StreamReader file; try { file= new StreamReader( FileName.ToString() ); } catch( Exception ) { return LastStatus= Status.ERROR_OPENING_FILE; } String lineS; AString name= new AString(); AString value= new AString(); AString comments= new AString(); Section actSection= (IniFile.Section) Sections[0]; Substring line= new Substring(); int lineNo= 0; bool fileHeaderRead= false; char[] separatorCharacters= value._( "=" )._( CString.DefaultWhitespaces ) .ToString().ToCharArray(); LinesWithReadErrors.Clear(); while ( (lineS= file.ReadLine()) != null ) { lineNo++; bool isEmpty= line.Set( lineS ).Trim().IsEmpty(); bool isCommentLine= startsWithCommentSymbol( line ); if ( isCommentLine ) { if ( comments.IsNotEmpty() ) comments.NewLine(); comments._(line); continue; } // still processing file header? if ( !fileHeaderRead ) { fileHeaderRead= true; FileComments._()._( comments ); comments.Clear(); } // empty line? if ( isEmpty ) { if ( comments.IsNotEmpty() ) comments.NewLine(); continue; } // section line if ( line.Consume( '[' ) ) { fileHeaderRead= true; // we do not care if there is no closing bracket. But if there is one, we remove it. if( !line.ConsumeFromEnd(']') ) LinesWithReadErrors.Add( lineNo ); // search the section in our section list (if section existed already, new comments // are dropped) actSection= (IniFile.Section) SearchOrCreateSection( line, comments); comments.Clear(); continue; } // variable line? value.Clear(); int idx= line.IndexOfAny( separatorCharacters, Inclusion.Include ); if( idx < 0 ) { name._()._( line ); line.Clear(); } else { name._()._( line.Buf, line.Start, idx ); line.Consume( idx ); value._(line); } // read continues as long as lines end with '\' (must not be '\\') while ( line.CharAtEnd() == '\\' && line.CharAtEnd(1) != '\\' ) { value.NewLine(); if ( (lineS= file.ReadLine()) == null ) { // last line of the file ended with '\' ! line.Clear(); break; } line.Set( lineS ).TrimEnd(); value._( line ); } // insert entry with raw value { IniFile.Entry entry= (IniFile.Entry) actSection.GetEntry( name, true ); entry.Values .Clear(); entry.Comments._()._( comments ); entry.RawValue._()._( value ); // if there is just no raw value, we add an empty string to the entries' values if ( value.IsEmpty() ) entry.Values.Add( new AString() ); } comments.Clear(); } file.Close(); return LastStatus; }
/** **************************************************************************************** * Interprets given \p src as a value of enum type * \ref cs::aworx::lib::enums::Inclusion "enums.Inclusion". * If the case insensitive comparison of the first non-whitespace characters of the string * with values "i", "y", "t", "1" * matches, \b %Inclusion.Include is returned. * Otherwise, including the case that \p src is 'nulled', \b %Inclusion.Exclude is returned. * * @param src The string to 'parse'. * * @returns The \b %Inclusion value read. ******************************************************************************************/ public static Inclusion ReadInclusion( Substring src ) { int idx= src.IndexOfAny( CString.DefaultWhitespaces, Inclusion.Exclude ); if ( idx >= 0 ) { int c= Char.ToLower( src.CharAt(idx) ); foreach ( char v in trueValuesInclusion ) if ( c == v ) return Inclusion.Include; } return Inclusion.Exclude; }
/** **************************************************************************************** * Interprets given \p src as a value of enum type * \ref aworx.lib::enums::Case "enums.Case". * If the case insensitive comparison of the first non-whitespace characters of the string * with values "s", "y", "t", "1" * matches, \b %Case.Sensitive is returned. * Otherwise, including the case that \p src is 'nulled', \b %Case.Ignore is returned. * * @param src The string to 'parse'. * * @returns The \b %Case value read. ******************************************************************************************/ public static Case ReadCase( Substring src ) { int idx= src.IndexOfAny( CString.DefaultWhitespaces, Inclusion.Exclude ); if ( idx >= 0 ) { int c= Char.ToLower( src.CharAt(idx) ); foreach ( char v in trueValuesCase ) if ( c == v ) return Case.Sensitive; } return Case.Ignore; }
/** **************************************************************************************** * Interprets given \p src as a boolean value. * \ref cs::aworx::lib::enums::Inclusion "enums.Inclusion". * If the case insensitive comparison of the first non-whitespace characters of the string with * with values "t", "1", "y", "on", "ok" * matches, \c true is returned. * Otherwise, including the case that \p src is 'nulled', \c false is returned. * * @param src The string to 'parse'. * * @returns The \b %Case value read. ******************************************************************************************/ public static bool ReadBoolean( Substring src ) { int idx= src.IndexOfAny( CString.DefaultWhitespaces, Inclusion.Exclude ); if ( idx >= 0 ) { char c= Char.ToLower( src.CharAt(idx) ); foreach ( char v in trueValuesBoolean ) if ( c == v ) return true; char c2= Char.ToLower( src.CharAt( idx + 1 ) ); if ( c == 'o' && ( c2 == 'n' || c2 == 'k' ) ) return true; } return false; }
/** **************************************************************************************** * Interprets given \p src as a verbosity. * A case insensitive comparison of only the first (!) character of the start of the string * is performed (against 'v', 'i', 'w' and 'e'). * If no match is found, \e %Verbosity::Off is returned. * @param src The string to 'parse'. * @returns The verbosity read. ******************************************************************************************/ public static Verbosity ReadVerbosity( Substring src ) { int idx= src.IndexOfAny( CString.DefaultWhitespaces, Inclusion.Exclude ); if ( idx >= 0 ) { char c= Char.ToLower( src.CharAt(idx) ); if ( c == 'v' ) return Verbosity.Verbose; if ( c == 'i' ) return Verbosity.Info; if ( c == 'w' ) return Verbosity.Warning; if ( c == 'e' ) return Verbosity.Error; } return Verbosity.Off; }
public void IndexOf() { Substring subs; // indexOf() { subs= new Substring("ABCD"); UT_EQ( -1, subs.IndexOf('X') ); UT_EQ( 0, subs.IndexOf('A') ); UT_EQ( 1, subs.IndexOf('B') ); UT_EQ( 2, subs.IndexOf('C') ); UT_EQ( 3, subs.IndexOf('D') ); } // search characters subs.Set( "abc@" + "abcd abcd" + "abc@de", 4, 9 ); { UT_EQ( -1 , subs.IndexOf( '@', -5 ) ); UT_EQ( -1 , subs.IndexOf( '@' ) ); UT_EQ( -1 , subs.IndexOf( '@', 5 ) ); UT_EQ( -1 , subs.IndexOf( '@', 150 ) ); UT_EQ( 0 , subs.IndexOf( 'a' ) ); UT_EQ( 1 , subs.IndexOf( 'b' ) ); UT_EQ( 2 , subs.IndexOf( 'c' ) ); UT_EQ( 0 , subs.IndexOf( 'a', 0 ) ); UT_EQ( 1 , subs.IndexOf( 'b', 0 ) ); UT_EQ( 2 , subs.IndexOf( 'c', 0 ) ); UT_EQ( 5 , subs.IndexOf( 'a', 1 ) ); UT_EQ( 1 , subs.IndexOf( 'b', 1 ) ); UT_EQ( 2 , subs.IndexOf( 'c', 1 ) ); UT_EQ( 5 , subs.IndexOf( 'a', 2 ) ); UT_EQ( 6 , subs.IndexOf( 'b', 2 ) ); UT_EQ( 2 , subs.IndexOf( 'c', 2 ) ); UT_EQ( 5 , subs.IndexOf( 'a', 3 ) ); UT_EQ( 6 , subs.IndexOf( 'b', 3 ) ); UT_EQ( 7 , subs.IndexOf( 'c', 3 ) ); UT_EQ( 8 , subs.IndexOf( 'd', 7 ) ); UT_EQ( 8 , subs.IndexOf( 'd', 8 ) ); UT_EQ( -1 , subs.IndexOf( 'd', 9 ) ); } // search null, empty string subs.Set( "abc@" + "abcd abcd" + "abc@de", 4, 9 ); { UT_EQ( 0 , subs.IndexOf( (AString) null ) ); UT_EQ( 5 , subs.IndexOf( (AString) null, 5 ) ); UT_EQ( -1 , subs.IndexOf( (AString) null, 50 ) ); UT_EQ( 0 , subs.IndexOf( (AString) null, - 5 ) ); UT_EQ( 0 , subs.IndexOf( (String) null ) ); UT_EQ( 5 , subs.IndexOf( (String) null, 5 ) ); UT_EQ( -1 , subs.IndexOf( (String) null, 50 ) ); UT_EQ( 0 , subs.IndexOf( (String) null, - 5 ) ); UT_EQ( 0 , subs.IndexOf( "", - 5 ) ); UT_EQ( 0 , subs.IndexOf( "", 0 ) ); UT_EQ( 4 , subs.IndexOf( "", 4 ) ); UT_EQ( -1 , subs.IndexOf( "", 100 ) ); } // search subs.Set( "abc@" + "abcd abcd" + "abc@de", 4, 9 ); { UT_EQ( 0 , subs.IndexOf( "abcd" ) ); UT_EQ( 1 , subs.IndexOf( "b" ) ); UT_EQ( 4 , subs.IndexOf( " abcd" ) ); UT_EQ( 5 , subs.IndexOf( "abcd", 1 ) ); UT_EQ( 0 , subs.IndexOf( "abcd",- 1 ) ); UT_EQ( -1, subs.IndexOf( "xyz", -10 ) ); } // ignore case String t= "Hello A-Worx util"; subs.Set( "abc@" + t + "abc@de", 4, t.Length ); { UT_EQ( 6 , subs.IndexOf( "a-worx", 0 ,Case.Ignore ) ); UT_EQ( 6 , subs.IndexOf( "a-worx", 1 ,Case.Ignore ) ); UT_EQ( 6 , subs.IndexOf( "a-worx", -10 ,Case.Ignore ) ); UT_EQ( 6 , subs.IndexOf( "a-worx", 6 ,Case.Ignore ) ); UT_EQ( -1, subs.IndexOf( "a-worx", 7 ,Case.Ignore ) ); UT_EQ( -1, subs.IndexOf( "a-worx", 100 ,Case.Ignore ) ); UT_EQ( 0, subs.IndexOf( "hel", 0 ,Case.Ignore ) ); UT_EQ( -1, subs.IndexOf( "hel", 1 ,Case.Ignore ) ); UT_EQ( 13, subs.IndexOf( "util", 1 ,Case.Ignore ) ); UT_EQ( 13, subs.IndexOf( "UTIL", 5 ,Case.Ignore ) ); UT_EQ( 13, subs.IndexOf( "UTIL", 13 ,Case.Ignore ) ); UT_EQ( -1, subs.IndexOf( "UTIL", 14 ,Case.Ignore ) ); } // ------------------ search one of several characters ------------------ subs.Set( "abc@" + "abcd abcde" + "abc@de", 4, 10 ); { // search one of int l= subs.Length(); UT_EQ( 4, subs.IndexOfAny ( CString.DefaultWhitespaces,Inclusion.Include ) ); UT_EQ( -1, subs.IndexOfAny ( "x" .ToCharArray() ,Inclusion.Include ) ); UT_EQ( -1, subs.IndexOfAny ( "xy" .ToCharArray() ,Inclusion.Include ) ); UT_EQ( -1, subs.IndexOfAny ( "xyz" .ToCharArray() ,Inclusion.Include ) ); UT_EQ( 3, subs.IndexOfAny ( "xyd" .ToCharArray() ,Inclusion.Include ) ); UT_EQ( 3, subs.IndexOfAny ( "d" .ToCharArray() ,Inclusion.Include ) ); UT_EQ( 3, subs.IndexOfAny ( "xyd" .ToCharArray() ,Inclusion.Include, -2 ) ); UT_EQ( 8, subs.IndexOfAny ( "xyd" .ToCharArray() ,Inclusion.Include, 4 ) ); UT_EQ( -1, subs.IndexOfAny ( "xyd" .ToCharArray() ,Inclusion.Include, 20 ) ); UT_EQ( -1, subs.LastIndexOfAny( "" .ToCharArray() ,Inclusion.Include ) ); UT_EQ( -1, subs.LastIndexOfAny( "x" .ToCharArray() ,Inclusion.Include ) ); UT_EQ( -1, subs.LastIndexOfAny( "xy" .ToCharArray() ,Inclusion.Include ) ); UT_EQ( -1, subs.LastIndexOfAny( "xyz" .ToCharArray() ,Inclusion.Include ) ); UT_EQ( 8, subs.LastIndexOfAny( "xyd" .ToCharArray() ,Inclusion.Include ) ); UT_EQ( -1, subs.LastIndexOfAny( "xyd" .ToCharArray() ,Inclusion.Include, -2 ) ); UT_EQ( -1, subs.LastIndexOfAny( "xyd" .ToCharArray() ,Inclusion.Include, 2 ) ); UT_EQ( 3, subs.LastIndexOfAny( "xyd" .ToCharArray() ,Inclusion.Include, 4 ) ); UT_EQ( 0, subs.LastIndexOfAny( "a" .ToCharArray() ,Inclusion.Include, 4 ) ); UT_EQ( 1, subs.LastIndexOfAny( "b" .ToCharArray() ,Inclusion.Include, 4 ) ); UT_EQ( 1, subs.LastIndexOfAny( "ba" .ToCharArray() ,Inclusion.Include, 4 ) ); UT_EQ( 0, subs.LastIndexOfAny( "xa" .ToCharArray() ,Inclusion.Include, 4 ) ); UT_EQ( 8, subs.LastIndexOfAny( "xyd" .ToCharArray() ,Inclusion.Include, 20 ) ); UT_EQ( 8, subs.LastIndexOfAny( "d" .ToCharArray() ,Inclusion.Include, 20 ) ); UT_EQ( 9, subs.LastIndexOfAny( "e" .ToCharArray() ,Inclusion.Include, 20 ) ); // search NOT one of UT_EQ( 0, subs.IndexOfAny ( "" .ToCharArray() ,Inclusion.Exclude ) ); UT_EQ( 0, subs.IndexOfAny ( "x" .ToCharArray() ,Inclusion.Exclude ) ); UT_EQ( 0, subs.IndexOfAny ( "xy" .ToCharArray() ,Inclusion.Exclude ) ); UT_EQ( 0, subs.IndexOfAny ( "xyz" .ToCharArray() ,Inclusion.Exclude ) ); UT_EQ( 1, subs.IndexOfAny ( "a" .ToCharArray() ,Inclusion.Exclude ) ); UT_EQ( 2, subs.IndexOfAny ( "ba" .ToCharArray() ,Inclusion.Exclude ) ); UT_EQ( 3, subs.IndexOfAny ( "abc" .ToCharArray() ,Inclusion.Exclude ) ); UT_EQ( 3, subs.IndexOfAny ( "acb" .ToCharArray() ,Inclusion.Exclude ) ); UT_EQ( 3, subs.IndexOfAny ( "cba" .ToCharArray() ,Inclusion.Exclude ) ); UT_EQ( 3, subs.IndexOfAny ( "xcba" .ToCharArray() ,Inclusion.Exclude ) ); UT_EQ( l-1, subs.LastIndexOfAny( "" .ToCharArray() ,Inclusion.Exclude ) ); UT_EQ( l-1, subs.LastIndexOfAny( "x" .ToCharArray() ,Inclusion.Exclude ) ); UT_EQ( l-1, subs.LastIndexOfAny( "xy" .ToCharArray() ,Inclusion.Exclude ) ); UT_EQ( l-2, subs.LastIndexOfAny( "e" .ToCharArray() ,Inclusion.Exclude ) ); UT_EQ( l-3, subs.LastIndexOfAny( "de" .ToCharArray() ,Inclusion.Exclude ) ); UT_EQ( l-4, subs.LastIndexOfAny( "cde" .ToCharArray() ,Inclusion.Exclude ) ); UT_EQ( l-4, subs.LastIndexOfAny( "ced" .ToCharArray() ,Inclusion.Exclude ) ); UT_EQ( l-4, subs.LastIndexOfAny( "ecd" .ToCharArray() ,Inclusion.Exclude ) ); UT_EQ( 5, subs.LastIndexOfAny( "ecd" .ToCharArray() ,Inclusion.Exclude, 5 ) ); UT_EQ( 4, subs.LastIndexOfAny( "ecd" .ToCharArray() ,Inclusion.Exclude, 4 ) ); UT_EQ( 1, subs.LastIndexOfAny( "acd" .ToCharArray() ,Inclusion.Exclude, 3 ) ); UT_EQ( -1, subs.LastIndexOfAny( "abc" .ToCharArray() ,Inclusion.Exclude, 2 ) ); UT_EQ( 3, subs.LastIndexOfAny( "xay" .ToCharArray() ,Inclusion.Exclude, 3 ) ); UT_EQ( 2, subs.LastIndexOfAny( "d" .ToCharArray() ,Inclusion.Exclude, 3 ) ); UT_EQ( -1, subs.LastIndexOfAny( "a" .ToCharArray() ,Inclusion.Exclude, 0 ) ); } }