// ############################################################################################# // 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; }
/** **************************************************************************************** * Searches in the values of this variable for the pattern * <c>attrName = result</c> and * sets parameter \p result to the string following this pattern. * * @param attrName The name of the attribute searched. * @param[out] result A substring with the result. * @param attrDelim The delimiter to search for. Defaults to '='. * @return \c true if the attribute was found, \c false otherwise. ******************************************************************************************/ public bool GetAttribute( String attrName, Substring result, char attrDelim= '=' ) { for ( int i= 0; i< Size(); i++ ) { result.Set( GetString(i ) ); if ( result.Consume( attrName, Case.Ignore, Whitespaces.Trim ) && result.Consume( attrDelim, Case.Ignore, Whitespaces.Trim ) ) { result.Trim(); return true; } } return false; }
/** ******************************************************************************************** * Processes the next command found in the format string, by writing formatted information * into the given buffer. * The given Substring holds the next command. When method returns, the command is cut * from the front. * * @param logger The logger that we are embedded in. * @param domain The <em>Log Domain</em>. * @param verbosity The verbosity. This has been checked to be active already on this * stage and is provided to be able to be logged out only. * @param scope Information about the scope of the <em>Log Statement</em>.. * @param dest The buffer to write meta information into. * @param variable The variable to read (may have more characters appended) * * @return The number of tab sequences that were written (by adding ESC::TAB to the buffer). **********************************************************************************************/ protected virtual int processVariable( TextLogger logger, Domain domain, Verbosity verbosity, ScopeInfo scope, AString dest, Substring variable ) { // process commands char c2; switch ( variable.Consume() ) { // scope info case 'S': { // read sub command AString val; switch( c2= variable.Consume() ) { case 'P': // SP: full path { int length; String path= scope.GetFullPath( out length ); if ( length > 0 ) { dest._( path, 0, length ); return 0; } val= NoSourceFileInfo; } break; case 'p': // Sp: trimmed path { val= scope.GetTrimmedPath(); if ( val.IsEmpty() ) val= NoSourceFileInfo; } break; case 'F': // file name { val= scope.GetFileName(); if ( val.IsEmpty() ) val= NoSourceFileInfo; } break; case 'f': // file name without extension { val= scope.GetFileNameWithoutExtension(); if ( val.IsEmpty() ) val= NoSourceFileInfo; } break; case 'M': // method name { String method= scope.GetMethod(); if ( method.Length == 0 ) dest._( NoMethodInfo ); else dest._( method ); return 0; } case 'L': // line number { dest._( scope.GetLineNumber() ); return 0; } default: { if( !warnedOnce ) { warnedOnce= true; ALIB.WARNING( "Unknown format variable '%S" + c2 + "\' (only one warning)" ); } dest._( "%ERROR" ); return 0; } } dest._( val ); return 0; } // %Tx: Time case 'T': { // read sub command c2= variable.Consume(); // %TD: Date if ( c2 == 'D' ) { // get time stamp as DateTime once if ( callerDateTime == null ) callerDateTime= scope.GetTimeStamp().InDotNetDateTime(); // avoid the allocation of a) a StringBuilder (yes, a string builder is allocated inside StringBuilder.AppendFormat!) // and b) a DateTime object, if the format is the unchanged standard. And it is faster anyhow. if ( DateFormat.Equals( "yyyy-MM-dd" ) ) { dest ._( callerDateTime.Value.Year, 4 )._( '-' ) ._( callerDateTime.Value.Month, 2 )._( '-' ) ._( callerDateTime.Value.Day, 2 ); } // support user defined standards else { // detect changes of format string since last log if ( detectDateFormatChanges != DateFormat ) { detectDateFormatChanges= DateFormat; dateFormatString= "{0:" + DateFormat + "}"; } // get date string from system and append to log buffer formatSB.Clear(); formatSB.AppendFormat( CultureInfo.InvariantCulture, dateFormatString, callerDateTime ); dest._( formatSB ); } } // %TT: Time of Day else if ( c2 == 'T' ) { // get time stamp as DateTime once if ( callerDateTime == null ) callerDateTime= scope.GetTimeStamp().InDotNetDateTime(); // avoid the allocation of a) a StringBuilder (yes, a string builder is allocated inside StringBuilder.AppendFormat!) // and b) a DateTime object, if the format is the unchanged standard. And it is faster anyhow. if ( TimeOfDayFormat.Equals( "HH:mm:ss" ) ) { dest ._( callerDateTime.Value.Hour, 2 )._( ':' ) ._( callerDateTime.Value.Minute, 2 )._( ':' ) ._( callerDateTime.Value.Second, 2 ); } // support user defined standards else { // detect changes of format string since last log if ( detectTimeOfDayFormatChanges != TimeOfDayFormat ) { detectTimeOfDayFormatChanges= TimeOfDayFormat; timeOfDayFormatString= "{0:" + TimeOfDayFormat + "}"; } // get time string from system and append to log buffer formatSB.Clear(); formatSB.AppendFormat( CultureInfo.InvariantCulture, timeOfDayFormatString, callerDateTime); dest ._( formatSB ); } } // %TC: Time elapsed since created else if ( c2 == 'C' ) { elapsedTime.Set( scope.GetTimeStamp() ); elapsedTime.Sub( logger.TimeOfCreation ); if( MaxElapsedTime.Raw() < elapsedTime.Raw() ) MaxElapsedTime.Set( elapsedTime ); long maxElapsedSecs= MaxElapsedTime.InSeconds(); TimeSpan elapsed= new TimeSpan( elapsedTime.Raw() ); if ( maxElapsedSecs >= 60*60*24 ) dest._( elapsed.Days )._NC( TimeElapsedDays ); if ( maxElapsedSecs >= 60*60 ) dest._( elapsed.Hours , maxElapsedSecs >= 60*60*10 ? 2 : 1 )._( ':' ); if ( maxElapsedSecs >= 60 ) dest._( elapsed.Minutes, maxElapsedSecs >= 10*60 ? 2 : 1 )._( ':' ); dest._( elapsed.Seconds, maxElapsedSecs > 9 ? 2 : 1 )._NC( '.' ); dest._( elapsed.Milliseconds, 3 ); } // %TL: Time elapsed since last log call else if ( c2 == 'L' ) writeTimeDiff( dest, scope.GetTimeStamp().Since(logger.TimeOfLastLog).InNanos() ); else { if( !warnedOnce ) { warnedOnce= true; ALIB.WARNING( "Unknown format variable '%T" + c2 + "\' (only one warning)" ); } dest._( "%ERROR" ); } return 0; } // thread name / ID case 't': { c2= variable.Consume(); if ( c2 == 'N' ) { dest.Field() ._( scope.GetThreadName() ) .Field( logger.AutoSizes.Next( scope.GetThreadName().Length(), 0 ), Alignment.Center ); } else if ( c2 == 'I' ) { tmpAString._()._( scope.GetThreadID() ); dest.Field() ._( tmpAString ) .Field( logger.AutoSizes.Next( tmpAString .Length(), 0 ), Alignment.Center ); } else { if( !warnedOnce ) { warnedOnce= true; ALIB.WARNING( "Unknown format variable '%t" + c2 + "\' (only one warning)" ); } dest._( "%ERROR" ); } return 0; } case 'L': { c2= variable.Consume(); if ( c2 == 'G' ) dest._NC( logger.GetName() ); else if ( c2 == 'X' ) dest._NC( scope.GetLoxName() ); else { if( !warnedOnce ) { warnedOnce= true; ALIB.WARNING( "Unknown format variable '%L" + c2 + "\' (only one warning)" ); } dest._( "%ERROR" ); return 0; } return 0; } case 'P': { dest._NC( Util.GetProcessName() ); return 0; } case 'V': dest._ ( verbosity == Verbosity.Error ? VerbosityError : verbosity == Verbosity.Warning ? VerbosityWarning : verbosity == Verbosity.Info ? VerbosityInfo : VerbosityVerbose ); return 0; case 'D': { dest.Field()._( domain.FullPath ).Field( logger.AutoSizes.Next( domain.FullPath.Length(), 0 ), Alignment.Left ); return 0; } case '#': dest._( logger.CntLogs, LogNumberMinDigits ); return 0; // A: Auto tab case 'A': { // read extra space from format string int oldStart= variable.Start; int extraSpace; variable.ConsumeInteger( out extraSpace ); if ( oldStart == variable.Start ) extraSpace= 1; // insert ESC code to jump to next tab level extraSpace= Math.Min( extraSpace, 10 + ('Z'-'A') ); char escNo= extraSpace < 10 ? (char) ( '0' + extraSpace ) : (char) ( 'A' + extraSpace ); dest._( "\x1Bt" )._( escNo ); return 1; } default: { if( !warnedOnce ) { warnedOnce= true; ALIB.WARNING( "Unknown format variable \'" + variable.Buf[variable.Start - 1] + "\'" ); } dest._( "%ERROR" ); } return 0; } }
bool Load( Variable variable, bool searchOnly= false ) { if ( args == null ) return false; int optionLength= variable.Fullname.Length(); Substring actVar= new Substring(); for ( int i= 0; i < args.Length ; i++ ) { // remove whitespaces (if somebody would work with quotation marks...) // and request '-' and allow a second '-' if ( !actVar.Set( args[i] ).Trim().Consume('-') ) continue; actVar.Consume( '-' ); if ( variable.Fullname.CompareTo( args[i], Case.Ignore, actVar.Start, optionLength, 0, optionLength ) == 0) { //again, lets trim before searching the = sign (really almost unnecessary) actVar.Start+= optionLength; if ( actVar.IsEmpty() ) { if ( !searchOnly ) variable.AddString(); return true; } if ( actVar.Consume( '=', Case.Sensitive, Whitespaces.Trim ) ) { if ( !searchOnly ) { actVar.Trim(); StringConverter.LoadFromString( variable, actVar ); } return true; } } } return false; }
// ############################################################################################# // Internals // ############################################################################################# /** **************************************************************************************** * Internal, recursive helper of #Find. * * @param domainPath Path to search. * @param sensitivity Denotes if domain name search is treated case sensitive or not. * @param maxCreate The maximum number of sub domains that are created if not * found at the end of the path. * @param[out] wasCreated Output parameter that is set \c true if domain was not found * and hence created. * @return The domain found or created. ******************************************************************************************/ protected Domain findRecursive( Substring domainPath, Case sensitivity, int maxCreate, ref bool wasCreated ) { //--- get act sub-name and rest of path domainPath.Consume( Separator ); int endSubName= domainPath.IndexOf( Separator ); ALIB.ASSERT_ERROR( endSubName != 0, "Internal Error" ); // find end of actual domain name and save rest Substring restOfDomainPath= tSubstring2; restOfDomainPath.SetNull(); if ( endSubName > 0 ) domainPath.Split( endSubName, restOfDomainPath, 1 ); // search sub-domain Domain subDomain= null; // "." if( domainPath.Equals( "." ) ) subDomain= this; // ".." else if( domainPath.Equals( ".." ) ) subDomain= Parent != null ? Parent : this; // search in sub-domain else { int i; bool fixedOnce= false; for(;;) { for( i= 0; i< SubDomains.Count; i++ ) { int comparison= SubDomains[i].Name.CompareTo( domainPath, sensitivity ); if( comparison >= 0 ) { if ( comparison == 0 ) subDomain= SubDomains[i]; break; } } // domain found? if ( subDomain != null ) break; // try and fix name if( !fixedOnce ) { fixedOnce= true; bool illegalCharacterFound= false; for( int cp= 0; cp< domainPath.Length() ; ++cp ) { char c= domainPath.CharAt(cp); if ( c < '-' || c > 'z' || c == '<' || c == '>' || c == '[' || c == ']' || c == '=' || c == '?' || c == ';' || c == ':' || c == '\\'|| c == '\''|| c == '.' || c == ',' ) { illegalCharacterFound= true; domainPath.Buf[domainPath.Start + cp]= '#'; } } if ( illegalCharacterFound ) continue; } // create if ( maxCreate == 0 ) return null; wasCreated= true; SubDomains.Insert( i, subDomain= new Domain( this, new AString( domainPath ) ) ); maxCreate--; if ( maxCreate == 0 ) return subDomain; break; } } // recursion? if ( restOfDomainPath.IsNotEmpty() ) { domainPath.Set( restOfDomainPath ); return subDomain.findRecursive( domainPath, sensitivity, maxCreate, ref wasCreated ); } // that's it return subDomain; }
public void _() { // append char[] { AString ms= new AString(); char[] csNull= null; char[] csEmpty= "".ToCharArray(); ms._( csNull ); UT_EQ ( ms.Length(), 0 ); UT_TRUE( ms.IsNull() ); ms._( csEmpty); UT_EQ ( ms.Length(), 0 ); UT_TRUE( ms.IsNotNull() ); ms.SetNull(); UT_EQ ( ms.Length(), 0 ); UT_TRUE( ms.IsNull() ); ms._("1234567".ToCharArray()); UT_EQ ( ms.Capacity(), 16 ); UT_EQ( "1234567", ms ); ms._("89" .ToCharArray()); UT_TRUE( ms.Length()> 7 ); UT_EQ( "123456789", ms ); char[] t= "0123456789".ToCharArray(); ms.Clear()._ ( t, 5); UT_EQ( ms, "56789" ); ms.Clear()._ ( t, 5, 100); UT_EQ( ms, "56789" ); ms.Clear()._ ( t, -5); UT_EQ( ms, "0123456789" ); ms.Clear()._ ( t, -5, 3); UT_EQ( ms, "" ); ms.Clear()._ ( t, 50, 3); UT_EQ( ms, "" ); ms.Clear()._ ( t, 10, 3); UT_EQ( ms, "" ); ms.Clear()._ ( t, -5, 10); UT_EQ( ms, "01234" ); ms.Clear()._ ( t, -5, 100); UT_EQ( ms, "0123456789" ); // _NC ms.SetNull(); UT_EQ ( ms.Length(), 0 ); UT_TRUE( ms.IsNull() ); ms._NC( csEmpty,0,0); UT_EQ ( ms.Length(), 0 ); UT_TRUE( ms.IsNull() ); ms.Clear()._NC( t, 5,3); UT_EQ( ms, "567" ); } // append AString { AString ms= new AString(); AString asNull= null; AString asEmpty= new AString(""); AString t= new AString( "012" ); ms._( asNull ); UT_EQ ( ms.Length(), 0 ); UT_TRUE( ms.IsNull() ); ms._( asEmpty); UT_EQ ( ms.Length(), 0 ); UT_TRUE( ms.IsNotNull() ); ms.SetNull(); UT_EQ ( ms.Length(), 0 ); UT_TRUE( ms.IsNull() ); ms._( t ); UT_EQ ( ms.Capacity(), 16 ); UT_EQ( "012" , ms ); ms._( t ); UT_TRUE( ms.Length()> 3 ); UT_EQ( "012012", ms ); t.Clear()._( "0123456789" ); ms.Clear()._ ( t, 5); UT_EQ( ms, "56789" ); ms.Clear()._ ( t, 5, 100); UT_EQ( ms, "56789" ); ms.Clear()._ ( t, -5); UT_EQ( ms, "0123456789" ); ms.Clear()._ ( t, -5, 3); UT_EQ( ms, "" ); ms.Clear()._ ( t, 50, 3); UT_EQ( ms, "" ); ms.Clear()._ ( t, 10, 3); UT_EQ( ms, "" ); ms.Clear()._ ( t, -5, 10); UT_EQ( ms, "01234" ); ms.Clear()._ ( t, -5, 100); UT_EQ( ms, "0123456789" ); ms.Clear()._NC( t ); UT_EQ( ms, "0123456789" ); ms.Clear()._NC( t, 1, 9 ); UT_EQ( ms, "123456789" ); ms.Clear()._NC( t, 1, 2 ); UT_EQ( ms, "12" ); ms.Clear()._NC( t, 1, 8 ); UT_EQ( ms, "12345678" ); ms.Clear()._NC( t, 1, 9 ); UT_EQ( ms, "123456789" ); ms.Clear()._NC( t, 5, 5 ); UT_EQ( ms, "56789" ); // _NC ms.SetNull(); UT_EQ ( ms.Length(), 0 ); UT_TRUE( ms.IsNull() ); ms._NC( asEmpty); UT_EQ ( ms.Length(), 0 ); UT_TRUE( ms.IsNull() ); ms.Clear()._NC( t, 5, 3); UT_EQ( ms, "567" ); } // append Substring { AString ms= new AString(); Substring ssNull= null; Substring ssEmpty= new Substring( "" ); Substring t= new Substring( "01234" ); ms._( ssNull ); UT_EQ ( ms.Length(), 0 ); UT_TRUE( ms.IsNull() ); ms._( ssEmpty); UT_EQ ( ms.Length(), 0 ); UT_TRUE( ms.IsNotNull() ); ms.SetNull(); UT_EQ ( ms.Length(), 0 ); UT_TRUE( ms.IsNull() ); ms._( t ); UT_EQ ( ms.Capacity(), 16 ); UT_EQ( "01234" , ms ); ms._( t ); UT_TRUE( ms.Length()> 5 ); UT_EQ( "0123401234", ms ); t.Consume(); ms.Clear()._( t ); UT_EQ( ms, "1234" ); t.Consume(); ms.Clear()._( t ); UT_EQ( ms, "234" ); t.ConsumeFromEnd(); ms.Clear()._( t ); UT_EQ( ms, "23" ); // _NC ms.SetNull(); UT_EQ ( ms.Length(), 0 ); UT_TRUE( ms.IsNull() ); ms._NC( ssEmpty ); UT_EQ ( ms.Length(), 0 ); UT_TRUE( ms.IsNull() ); ms.Clear()._NC( t); UT_EQ( ms, "23" ); } // append String { AString ms= new AString(); String sEmpty= ""; String t= "012"; ms._( sEmpty); UT_EQ ( ms.Length(), 0 ); UT_TRUE( ms.IsNotNull() ); ms.SetNull(); UT_EQ ( ms.Length(), 0 ); UT_TRUE( ms.IsNull() ); ms._( t ); UT_EQ ( ms.Capacity(), 16 ); UT_EQ( "012" , ms ); ms._( t ); UT_TRUE( ms.Length()> 3 ); UT_EQ( "012012", ms ); t= "0123456789"; ms.Clear()._( t, 5); UT_EQ( ms, "56789" ); ms.Clear()._( t, 5, 100); UT_EQ( ms, "56789" ); ms.Clear()._( t, -5); UT_EQ( ms, "0123456789" ); ms.Clear()._( t, -5, 3); UT_EQ( ms, "" ); ms.Clear()._( t, 50, 3); UT_EQ( ms, "" ); ms.Clear()._( t, 10, 3); UT_EQ( ms, "" ); ms.Clear()._( t, -5, 10); UT_EQ( ms, "01234" ); ms.Clear()._( t, -5, 100); UT_EQ( ms, "0123456789" ); // _NC ms.SetNull(); UT_EQ ( ms.Length(), 0 ); UT_TRUE( ms.IsNull() ); ms._NC( sEmpty ); UT_EQ ( ms.Length(), 0 ); UT_TRUE( ms.IsNull() ); ms.Clear()._NC( t); UT_EQ( ms, "0123456789" ); ms.Clear()._NC( t ,2,3); UT_EQ( ms, "234" ); } // append String Builders { AString ms= new AString(); StringBuilder t= new StringBuilder( "012"); ms._( t ); UT_EQ ( ms.Capacity(), 16 ); UT_EQ( "012" , ms ); ms._( t ); UT_TRUE( ms.Length()> 3 ); UT_EQ( "012012", ms ); t.Clear().Append("0123456789"); ms.Clear()._( t, 5); UT_EQ( ms, "56789" ); ms.Clear()._( t, 5, 100); UT_EQ( ms, "56789" ); ms.Clear()._( t, -5); UT_EQ( ms, "0123456789" ); ms.Clear()._( t, -5, 3); UT_EQ( ms, "" ); ms.Clear()._( t, 50, 3); UT_EQ( ms, "" ); ms.Clear()._( t, 10, 3); UT_EQ( ms, "" ); ms.Clear()._( t, -5, 10); UT_EQ( ms, "01234" ); ms.Clear()._( t, -5, 100); UT_EQ( ms, "0123456789" ); } }
void InternalizeValue( Substring src, AString dest ) { src.Trim(); bool inUnquoted= true; bool inQuote= false; bool lastWasSlash= false; while( src.IsNotEmpty() ) { char c= src.Consume(); if( lastWasSlash ) { lastWasSlash= false; char escChr= c == '\\' ? '\\' : c == 'n' ? '\n' : c == 'r' ? '\r' : c == 't' ? '\t' : c == '"' ? '"' : c; dest._(escChr); continue; } if( c== '\\' ) { lastWasSlash= true; continue; } if( c== '"' ) { inQuote= !inQuote; inUnquoted= false; continue; } if( inQuote || inUnquoted ) { dest._(c); continue; } if( CString.IndexOf( CString.DefaultWhitespaces, c) >= 0 ) continue; inUnquoted= true; dest._(c); } }
public void Consume() { // null substring { Substring s= new Substring(); Substring r= new Substring("oldval"); UT_EQ( '\0', s.Consume ( ) ); UT_EQ( 0, s.Consume ( 0 , r) ); UT_TRUE(r.IsNull()); UT_EQ( 0, s.Consume ( 5 , r) ); UT_TRUE(r.IsNull()); UT_EQ( false, s.Consume ( 'a' ) ); UT_EQ( false, s.Consume ( "word" ) ); UT_EQ( '\0', s.ConsumeFromEnd( ) ); UT_EQ( 0, s.ConsumeFromEnd( 0 ) ); UT_EQ( 0, s.ConsumeFromEnd( 5 ) ); UT_EQ( false, s.ConsumeFromEnd( 'a' ) ); UT_EQ( false, s.ConsumeFromEnd( "word" ) ); } // empty substring { Substring s= new Substring("aaaaaaaaaaaa"); Substring r= new Substring("oldval"); s.Start= 5; s.End= 4; UT_EQ( '\0', s.Consume ( ) ); UT_EQ( 0, s.Consume ( 0 ,r ) ); UT_TRUE( r.IsNotNull()); UT_TRUE(r.IsEmpty()); UT_EQ( 0, s.Consume ( 5 ,r ) ); UT_TRUE( r.IsNotNull()); UT_TRUE(r.IsEmpty()); UT_EQ( false, s.Consume ( 'a' ) ); UT_EQ( false, s.Consume ( "word" ) ); UT_EQ( '\0', s.ConsumeFromEnd( ) ); UT_EQ( 0, s.ConsumeFromEnd( 0 ) ); UT_EQ( 0, s.ConsumeFromEnd( 5 ) ); UT_EQ( false, s.ConsumeFromEnd( 'a' ) ); UT_EQ( false, s.ConsumeFromEnd( "word" ) ); } // substring of length 1 { Substring s= new Substring("aaaaaaaaaaaa"); Substring r= new Substring("oldval"); s.Start= s.End= 5; UT_EQ( 'a', s.Consume ( ) ); UT_EQ( 0, s.Length() ); s.Start= s.End= 5; UT_EQ( 1, s.Consume ( 0 ) ); UT_EQ( 1, s.Length() ); s.Start= s.End= 5; UT_EQ( 0, s.Consume ( 1 , r ) ); UT_EQ( 0, s.Length() ); UT_TRUE(r.Equals("a")); s.Start= s.End= 5; UT_EQ( 0, s.Consume ( 5 , r ) ); UT_EQ( 0, s.Length() ); UT_TRUE(r.Equals("a")); s.Start= s.End= 5; UT_EQ( true, s.Consume ( 'a' ) ); UT_EQ( 0, s.Length() ); s.Start= s.End= 5; UT_EQ( false, s.Consume ( 'b' ) ); UT_EQ( 1, s.Length() ); s.Start= s.End= 5; UT_EQ( false, s.Consume ( "word" ) ); UT_EQ( 1, s.Length() ); s.Start= s.End= 5; UT_EQ( 'a', s.ConsumeFromEnd( ) ); UT_EQ( 0, s.Length() ); s.Start= s.End= 5; UT_EQ( 1, s.ConsumeFromEnd( 0 ) ); UT_EQ( 1, s.Length() ); s.Start= s.End= 5; UT_EQ( 0, s.ConsumeFromEnd( 1 ) ); UT_EQ( 0, s.Length() ); s.Start= s.End= 5; UT_EQ( 0, s.ConsumeFromEnd( 5 ) ); UT_EQ( 0, s.Length() ); s.Start= s.End= 5; UT_EQ( true, s.ConsumeFromEnd( 'a' ) ); UT_EQ( 0, s.Length() ); s.Start= s.End= 5; UT_EQ( false, s.ConsumeFromEnd( 'b' ) ); UT_EQ( 1, s.Length() ); s.Start= s.End= 5; UT_EQ( false, s.ConsumeFromEnd( "word" ) ); UT_EQ( 1, s.Length() ); } // substring of length 2 { Substring s= new Substring("12ab3456"); Substring r= new Substring("oldval"); s.Start= 2; s.End= 3; UT_EQ( 'a', s.Consume ( ) ); UT_EQ( 1, s.Length() ); UT_EQ( 'b', s.Consume ( ) ); UT_EQ( 0, s.Length() ); s.Start= 2; s.End= 3; UT_EQ( 'b', s.ConsumeFromEnd( ) ); UT_EQ( 1, s.Length() ); UT_EQ( 'a', s.ConsumeFromEnd( ) ); UT_EQ( 0, s.Length() ); s.Start= 2; s.End= 3; UT_EQ( 2, s.Consume ( 0 , r ) ); UT_EQ( 2, s.Length() ); UT_TRUE(r.IsNotNull()); UT_TRUE(r.IsEmpty()); s.Start= 2; s.End= 3; UT_EQ( 1, s.Consume ( 1 , r ) ); UT_EQ( 1, s.Length() ); UT_TRUE(r.Equals("a")); s.Start= 2; s.End= 3; UT_EQ( 0, s.Consume ( 2 , r ) ); UT_EQ( 0, s.Length() ); UT_TRUE(r.Equals("ab")); s.Start= 2; s.End= 3; UT_EQ( 0, s.Consume ( 3 , r ) ); UT_EQ( 0, s.Length() ); UT_TRUE(r.Equals("ab")); s.Start= 2; s.End= 3; UT_EQ( 2, s.ConsumeFromEnd( 0 , r ) ); UT_EQ( 2, s.Length() ); UT_TRUE(r.IsNotNull()); UT_TRUE(r.IsEmpty()); s.Start= 2; s.End= 3; UT_EQ( 1, s.ConsumeFromEnd( 1 , r ) ); UT_EQ( 1, s.Length() ); UT_TRUE(r.Equals("b")); s.Start= 2; s.End= 3; UT_EQ( 0, s.ConsumeFromEnd( 2 , r ) ); UT_EQ( 0, s.Length() ); UT_TRUE(r.Equals("ab")); s.Start= 2; s.End= 3; UT_EQ( 0, s.ConsumeFromEnd( 3 , r ) ); UT_EQ( 0, s.Length() ); UT_TRUE(r.Equals("ab")); s.Start= 2; s.End= 3; UT_EQ( false, s.Consume ( 'b' ) ); UT_EQ( 2, s.Length() ); UT_EQ( true, s.Consume ( 'a' ) ); UT_EQ( 1, s.Length() ); UT_EQ( true, s.Consume ( 'b' ) ); UT_EQ( 0, s.Length() ); UT_EQ( false, s.Consume ( 'a' ) ); UT_EQ( 0, s.Length() ); UT_EQ( false, s.Consume ( 'b' ) ); UT_EQ( 0, s.Length() ); s.Start= 2; s.End= 3; UT_EQ( false, s.ConsumeFromEnd( 'a' ) ); UT_EQ( 2, s.Length() ); UT_EQ( true, s.ConsumeFromEnd( 'b' ) ); UT_EQ( 1, s.Length() ); UT_EQ( true, s.ConsumeFromEnd( 'a' ) ); UT_EQ( 0, s.Length() ); UT_EQ( false, s.ConsumeFromEnd( 'b' ) ); UT_EQ( 0, s.Length() ); UT_EQ( false, s.ConsumeFromEnd( 'a' ) ); UT_EQ( 0, s.Length() ); s.Start= 2; s.End= 3; UT_EQ( false, s.Consume ( "word" ) ); UT_EQ( 2, s.Length() ); s.Start= 2; s.End= 3; UT_EQ( false, s.Consume ( "AB" ) ); UT_EQ( 2, s.Length() ); s.Start= 2; s.End= 3; UT_EQ( true, s.Consume ( "ab" ) ); UT_EQ( 0, s.Length() ); s.Start= 2; s.End= 3; UT_EQ( false, s.ConsumeFromEnd( "word" ) ); UT_EQ( 2, s.Length() ); s.Start= 2; s.End= 3; UT_EQ( false, s.ConsumeFromEnd( "AB" ) ); UT_EQ( 2, s.Length() ); s.Start= 2; s.End= 3; UT_EQ( true, s.ConsumeFromEnd( "ab" ) ); UT_EQ( 0, s.Length() ); } // 3 words { Substring s= new Substring("word1 word2 word3"); UT_EQ( 'w', s.Consume ( ) ); UT_EQ( 'o', s.Consume ( ) ); UT_EQ( 'r', s.Consume ( ) ); UT_EQ( 'd', s.Consume ( ) ); UT_EQ( '1', s.Consume ( ) ); UT_EQ( false , s.Consume ('w' ) ); UT_EQ( true , s.Consume ('w' , Case.Sensitive, Whitespaces.Trim ) ); UT_EQ( true , s.Consume ('o' , Case.Sensitive, Whitespaces.Trim ) ); UT_EQ( false , s.Consume ('o' , Case.Sensitive, Whitespaces.Trim ) ); UT_EQ( true , s.Consume ('r' , Case.Sensitive, Whitespaces.Trim ) ); UT_EQ( false , s.Consume ("D2" , Case.Sensitive, Whitespaces.Trim ) ); UT_EQ( false , s.Consume ("D2" ) ); UT_EQ( true , s.Consume ("d2" ) ); UT_EQ( 2 , s.Consume ( 4 ) ); UT_EQ( "d3" , s.ToString() ); s= new Substring("word1 word2 word3"); UT_EQ( '3', s.ConsumeFromEnd( ) ); UT_EQ( 'd', s.ConsumeFromEnd( ) ); UT_EQ( 'r', s.ConsumeFromEnd( ) ); UT_EQ( 'o', s.ConsumeFromEnd( ) ); UT_EQ( 'w', s.ConsumeFromEnd( ) ); UT_EQ( false , s.ConsumeFromEnd('2' ) ); UT_EQ( true , s.ConsumeFromEnd('2' , Case.Sensitive, Whitespaces.Trim ) ); UT_EQ( true , s.ConsumeFromEnd('d' , Case.Sensitive, Whitespaces.Trim ) ); UT_EQ( false , s.ConsumeFromEnd('d' , Case.Sensitive, Whitespaces.Trim ) ); UT_EQ( true , s.ConsumeFromEnd('r' , Case.Sensitive, Whitespaces.Trim ) ); UT_EQ( false , s.ConsumeFromEnd("WO" , Case.Sensitive, Whitespaces.Trim ) ); UT_EQ( false , s.ConsumeFromEnd("WO" ) ); UT_EQ( true , s.ConsumeFromEnd("wo" ) ); UT_EQ( 2 , s.ConsumeFromEnd( 4 ) ); UT_EQ( "wo" , s.ToString() ); } // consume AString, Substring { Substring s= new Substring("word1 word2 word3 word4"); Substring sConsume= new Substring( "1234word12", 4, 4 ); AString aConsume= new AString ( "word" ); UT_EQ( true, s.Consume ( sConsume ) ); UT_EQ( false, s.Consume ( sConsume ) ); UT_EQ( '1', s.Consume ( ) ); UT_EQ( false, s.Consume ( sConsume ) ); UT_EQ( true, s.Consume ( sConsume, Case.Sensitive, Whitespaces.Trim ) ); UT_EQ( '2', s.Consume ( ) ); UT_EQ( ' ', s.Consume ( ) ); UT_EQ( true, s.Consume ( aConsume ) ); UT_EQ( false, s.Consume ( aConsume ) ); UT_EQ( '3', s.Consume ( ) ); UT_EQ( false, s.Consume ( aConsume ) ); UT_EQ( true, s.Consume ( aConsume, Case.Sensitive, Whitespaces.Trim ) ); s.Set("1word 2word 3word 4word"); UT_EQ( true, s.ConsumeFromEnd( sConsume ) ); UT_EQ( false, s.ConsumeFromEnd( sConsume ) ); UT_EQ( '4', s.ConsumeFromEnd( ) ); UT_EQ( false, s.ConsumeFromEnd( sConsume ) ); UT_EQ( true, s.ConsumeFromEnd( sConsume, Case.Sensitive, Whitespaces.Trim ) ); UT_EQ( '3', s.ConsumeFromEnd( ) ); UT_EQ( ' ', s.ConsumeFromEnd( ) ); UT_EQ( true, s.ConsumeFromEnd( aConsume ) ); UT_EQ( false, s.ConsumeFromEnd( aConsume ) ); UT_EQ( '2', s.ConsumeFromEnd( ) ); UT_EQ( false, s.ConsumeFromEnd( aConsume ) ); UT_EQ( true, s.ConsumeFromEnd( aConsume, Case.Sensitive, Whitespaces.Trim ) ); } }
/** **************************************************************************************** * Implements functionality for configuration variable \c LOXNAME_DUMP_STATE_ON_EXIT. * Is called when a logger is removed. ******************************************************************************************/ protected void dumpStateOnLoggerRemoval() { if( !loggerAddedSinceLastDebugState ) return; loggerAddedSinceLastDebugState= false; Variable variable= new Variable( ALox.DUMP_STATE_ON_EXIT, GetName() ); variable.Load(); String domain= null; Verbosity verbosity= Verbosity.Info; Substring tok= new Substring(); int flags= 0; for( int tokNo= 0; tokNo< variable.Size(); tokNo++ ) { tok.Set( variable.GetString( tokNo ) ); if( tok.IsEmpty() ) continue; // state flags if( tok.Equals( "NONE" , Case.Ignore ) ) { flags= 0; break; } else if( tok.Equals( "Basic" , Case.Ignore ) ) flags|= (int) Lox.StateInfo.Basic ; else if( tok.Equals( "Version" , Case.Ignore ) ) flags|= (int) Lox.StateInfo.Version ; else if( tok.Equals( "Loggers" , Case.Ignore ) ) flags|= (int) Lox.StateInfo.Loggers ; else if( tok.Equals( "Domains" , Case.Ignore ) ) flags|= (int) Lox.StateInfo.Domains ; else if( tok.Equals( "InternalDomains" , Case.Ignore ) ) flags|= (int) Lox.StateInfo.InternalDomains ; else if( tok.Equals( "ScopeDomains" , Case.Ignore ) ) flags|= (int) Lox.StateInfo.ScopeDomains ; else if( tok.Equals( "DSR" , Case.Ignore ) ) flags|= (int) Lox.StateInfo.DSR ; else if( tok.Equals( "PrefixLogables" , Case.Ignore ) ) flags|= (int) Lox.StateInfo.PrefixLogables ; else if( tok.Equals( "Once" , Case.Ignore ) ) flags|= (int) Lox.StateInfo.Once ; else if( tok.Equals( "LogData" , Case.Ignore ) ) flags|= (int) Lox.StateInfo.LogData ; else if( tok.Equals( "ThreadMappings" , Case.Ignore ) ) flags|= (int) Lox.StateInfo.ThreadMappings ; else if( tok.Equals( "SPTR" , Case.Ignore ) ) flags|= (int) Lox.StateInfo.SPTR ; else if( tok.Equals( "All" , Case.Ignore ) ) flags|= (int) Lox.StateInfo.All ; // domain and verbosity else if( tok.Consume( "domain", Case.Ignore, Whitespaces.Trim ) ) { if( tok.Consume( '=', Case.Sensitive, Whitespaces.Trim ) ) domain= tok.Trim().ToString(); } else if( tok.Consume( "verbosity", Case.Ignore, Whitespaces.Trim ) ) { if( tok.Consume( '=', Case.Sensitive, Whitespaces.Trim ) ) verbosity= ALox.ReadVerbosity( tok.Trim() ); } // unknown argument else { logInternal( Verbosity.Error, "VAR", intMsg._() ._( "Unknown argument '" )._(tok) ._( "' in variable " )._(variable.Fullname)._( " = \"")._(variable.GetString())._('\"') ); } } if ( flags != 0 ) { State( domain, verbosity, "Auto dump state on exit requested: ", (Lox.StateInfo) flags ); } }
/** **************************************************************************************** * Implements functionality for configuration variable \c LOXNAME_LOGGERNAME_VERBOSITY. * Is called when a logger is removed. * @param logger The logger to write the verbosity for. ******************************************************************************************/ protected void writeVerbositiesOnLoggerRemoval( Logger logger ) { // When writing back we will use this priority as the maximum to write. This way, if this was // an automatic default value, we will not write back into the user's variable store. // As always, only if the app fetches new variables on termination, this is entry is copied. Variable variable= new Variable( ALox.VERBOSITY, GetName(), logger.GetName() ); variable.Load(); // first token is "writeback" ? if ( variable.Size() == 0 ) return; Substring firstArg= new Substring( variable.GetString() ); if ( !firstArg.Consume( "writeback", Case.Ignore, Whitespaces.Trim ) ) return; // optionally read a destination variable name Substring destVarCategory = new Substring(); Substring destVarName = new Substring(); if( firstArg.Trim().IsNotEmpty() ) { // separate category from variable name int catSeparatorIdx= firstArg.IndexOf( '_' ); if (catSeparatorIdx >= 0 ) { destVarCategory.Set( firstArg, 0 , catSeparatorIdx ); destVarName .Set( firstArg, catSeparatorIdx + 1); } else destVarName.Set( firstArg ); if ( destVarName.IsEmpty() ) { logInternal( Verbosity.Error, "VAR", intMsg._() ._( "Argument 'writeback' in variable " ) ._( variable.Fullname) ._( "\n Error: Wrong destination variable name format\"" ) ._( firstArg )._( "\"" ) ); return; } } // either write directly into LOX_LOGGER_VERBOSITY variable... Variable destVar= null; if( destVarName.IsEmpty() ) { variable.ClearValues( 1 ); destVar= variable; } // ...or into a new given variable else { destVar= new Variable( destVarCategory, destVarName, ALox.VERBOSITY.Delim ); destVar.FormatHints= variable.FormatHints; destVar.FormatAttrAlignment= variable.FormatAttrAlignment; destVar.Comments._("Created at runtime through config option 'writeback' in variable \"")._( variable.Fullname )._("\"."); } // collect verbosities { int loggerNoMainDom= domains .GetLoggerNo( logger ); int loggerNoIntDom= internalDomains.GetLoggerNo( logger ); if ( loggerNoMainDom >= 0 ) verbositySettingToVariable( domains , loggerNoMainDom, destVar ); if ( loggerNoIntDom >= 0 ) verbositySettingToVariable( internalDomains, loggerNoIntDom , destVar ); } // now store using the same plug-in as original variable has destVar.Priority= variable.Priority; destVar.Store(); // internal logging intMsg._()._( "Argument 'writeback' in variable " )._( variable.Fullname ) ._( ":\n Verbosities for logger \"" ) ._( logger.GetName() ) ._( "\" written " ); if( destVarName.IsEmpty() ) intMsg._( "(to source variable)." ); else intMsg._( "to variable \"" ) ._( destVar.Fullname ) ._("\".") ; logInternal( Verbosity.Info, "VAR", intMsg._( destVarName )._( "\"." ) ); // verbose logging of the value written intMsg._()._(" Value:"); for( int i= 0; i< destVar.Size() ; i++ ) intMsg._( "\n " )._( destVar.GetString(i) ); logInternal( Verbosity.Verbose, "VAR", intMsg ); }
/** **************************************************************************************** * Reads a prefix string from the ALib configuration system. * This internal method is used when a new domain is created, * * @param dom The domain to set the verbosity for. ******************************************************************************************/ protected void getDomainPrefixFromConfig( Domain dom ) { Variable variable= new Variable( ALox.PREFIXES, GetName() ); if( 0 == variable.Load() ) return; Tokenizer prefixTok= new Tokenizer(); Tokenizer prefixTokInner= new Tokenizer(); Substring domainStr= new Substring(); AString domainStrBuf= new AString(); Substring prefixStr= new Substring(); for( int varNo= 0; varNo< variable.Size(); varNo++ ) { prefixTok.Set( variable.GetString( varNo ), '=' ); domainStr.Set( prefixTok.Next() ); if ( domainStr.StartsWith( "INTERNAL_DOMAINS", DomainSensitivity ) ) { domainStrBuf._()._( domainStr.Buf, domainStr.Start + 16, domainStr.Length() -16 ); while ( domainStrBuf.CharAtStart() == '/' ) domainStrBuf.DeleteStart( 1 ); domainStrBuf.InsertAt( ALox.InternalDomains, 0 ); domainStr.Set( domainStrBuf ); } prefixTokInner.Set( prefixTok.Next(), ',' ); prefixStr.Set( prefixTokInner.Next() ); if ( prefixStr.IsEmpty() ) continue; if ( prefixStr.Consume( '\"' ) ) prefixStr.ConsumeFromEnd( '\"' ); Inclusion otherPLs= Inclusion.Include; prefixTokInner.Next(); if ( prefixTokInner.Actual.IsNotEmpty() ) otherPLs= ALIB.ReadInclusion( prefixTokInner.Actual ); int searchMode= 0; if ( domainStr.Consume ( '*' ) ) searchMode+= 2; if ( domainStr.ConsumeFromEnd( '*' ) ) searchMode+= 1; if( ( searchMode == 0 && dom.FullPath.Equals ( domainStr, DomainSensitivity ) ) || ( searchMode == 1 && dom.FullPath.StartsWith ( domainStr, DomainSensitivity ) ) || ( searchMode == 2 && dom.FullPath.EndsWith ( domainStr, DomainSensitivity ) ) || ( searchMode == 3 && dom.FullPath.IndexOf ( domainStr, 0, DomainSensitivity ) >=0 ) ) { dom.PrefixLogables.Add( new Domain.PL( new AString( prefixStr ), otherPLs ) ); // log info on this intMsg._()._NC( "String \"" )._NC( prefixStr )._NC ( "\" added as prefix logable for domain \'" ) ._NC( dom.FullPath ) ._NC( "\'. (Retrieved from variable" ) ._NC( variable.Fullname )._( ".)" ); logInternal( Verbosity.Info, "PFX", intMsg ); } } }
/** **************************************************************************************** * Reads the verbosity for the given logger and domain from the ALib configuration system. * This internal method is used in two occasions: * - when a new logger is added: recursively for all existing domains (\p configStr is * given) * - when a new domain is created on the fly(\p configStr is not given) * * @param logger The logger to set the verbosity for. * @param dom The domain to set the verbosity for. * @param variable The (already read) variable to set verbosities from. ******************************************************************************************/ protected void getVerbosityFromConfig( Logger logger, Domain dom, Variable variable ) { // get logger number. It may happen that the logger is not existent in this domain tree. int loggerNo= dom.GetLoggerNo( logger ) ; if ( loggerNo < 0 ) return; Tokenizer verbosityTknzr= new Tokenizer(); Substring domainStr= new Substring(); AString domainStrBuf= new AString(); for( int varNo= 0; varNo< variable.Size(); varNo++ ) { verbosityTknzr.Set( variable.GetString( varNo ), '=' ); domainStr.Set( verbosityTknzr.Next() ); if ( domainStr.StartsWith( "INTERNAL_DOMAINS", DomainSensitivity ) ) { domainStrBuf._()._( domainStr.Buf, domainStr.Start + 16, domainStr.Length() -16 ); while ( domainStrBuf.CharAtStart() == '/' ) domainStrBuf.DeleteStart( 1 ); domainStrBuf.InsertAt( ALox.InternalDomains, 0 ); domainStr.Set( domainStrBuf ); } Substring verbosityStr= verbosityTknzr.Next(); if ( verbosityStr.IsEmpty() ) continue; int searchMode= 0; if ( domainStr.Consume ( '*' ) ) searchMode+= 2; if ( domainStr.ConsumeFromEnd( '*' ) ) searchMode+= 1; if( ( searchMode == 0 && dom.FullPath.Equals ( domainStr, DomainSensitivity ) ) || ( searchMode == 1 && dom.FullPath.StartsWith ( domainStr, DomainSensitivity ) ) || ( searchMode == 2 && dom.FullPath.EndsWith ( domainStr, DomainSensitivity ) ) || ( searchMode == 3 && dom.FullPath.IndexOf ( domainStr, 0, DomainSensitivity ) >=0 ) ) { Verbosity verbosity= ALox.ReadVerbosity( verbosityStr); dom.SetVerbosity( loggerNo, verbosity, variable.Priority ); // log info on this intMsg._()._NC( "Logger \"" )._NC( logger.GetName() ) ._NC( "\":" ).Tab(11 + maxLoggerNameLength) ._( '\'' )._NC( dom.FullPath ) ._( '\'' ).InsertChars(' ', maxDomainPathLength - dom.FullPath.Length() + 1 ) ._("= Verbosity." ); ALox.ToString( verbosity, dom.GetPriority(loggerNo), intMsg ).TrimEnd() ._('.'); logInternal( Verbosity.Info, "LGR", intMsg ); } } }