public void InOrderAtLeastAdditionalItemAtStartAndEndPassesTest() { AssertPasses( Items("zero", "one", "two", "three", "four"), AList.InOrder().WithAtLeast(AString.EqualToValues("one", "two", "three")) ); }
// ############################################################################################# // Public interface // ############################################################################################# /** ******************************************************************************************** * Constructor for domain. * @param parent The parent domain. For root domains, this is null. * @param name The name of the domain. For root domains, this is null. **********************************************************************************************/ public Domain(Domain parent, AString name) { // store parameters this.Name = name; this.Parent = parent; // create fields SubDomains = new List <Domain>(3); Data = new List <LoggerData>(parent == null ? 2 : parent.Data.Count); // if we have a parent, we inherit all logger's verbosities if (parent != null) { foreach (LoggerData ldParent in parent.Data) { LoggerData ld = new LoggerData(ldParent.Logger); ld.LoggerVerbosity = ldParent.LoggerVerbosity; ld.Priority = ldParent.Priority; Data.Add(ld); } } FullPath = new AString(); Domain dom = this; do { if (dom != this || dom.Parent == null) { FullPath.InsertAt("/", 0); } FullPath.InsertAt(dom.Name, 0); dom = dom.Parent; }while(dom != null); }
public void InAnyOrderAtLeastOutOfOrderItemsPassesTest() { AssertPasses( Items("two", "one", "three"), AList.InAnyOrder().WithAtLeast(AString.EqualToValues("one", "two", "three")) ); }
public void InAnyOrderAtLeastAdditionalItemPassesTest() { AssertPasses( Items("four", "three", "one", "two"), AList.InAnyOrder().WithAtLeast(AString.EqualToValues("one", "two", "three")) ); }
public void ReportIsCorrectlyGeneratedTest() { PerformanceMetricsWriter metricsWriter; PerformanceReport report; Scenario() .Given(metricsWriter = PerformanceMetricsWriter.With().TestName("ReportIsCorrectlyGeneratedTest")) .When(PerformanceSuite.With() .NumRuns(2) .PerRunTimeout(20).Seconds() .LoadRunner(ContentionLoadRunner.With() .Tests(new MyPerfTest()) .RunTimeout(15).Seconds()) .Listener(metricsWriter) .Build()) .When(report = metricsWriter.BuildReport()) .When(report.PrintToConsole) .Then( Expect(report.GetMetricSummaryNamed("metric1").ValueMean), Is(ADouble.EqualTo(4.75))) .Then( Expect(report.GetMetricSummaryNamed("metric1").ValueMedian), Is(ADouble.EqualTo(5))) .Then( Expect(report.GetMetricSummaryNamed("metric1").ValueMax), Is(ADouble.EqualTo(10))) .Then( Expect(report.GetMetricSummaryNamed("metric1").ValueMin), Is(ADouble.EqualTo(0))) .Then( Expect(report.GetMetricSummaryNamed("metric1").MetricName), Is(AString.EqualTo("metric1"))); }
/** **************************************************************************************** * Writes a string representation of the \e Verbosity and priority into the given * AString. * * @param verbosity The enum value to retrieve a string representation for. * @param priority The priority of the \p verbosity setting. * @param target The target to write into. * @returns \p target to allow concatenated calls. ******************************************************************************************/ public static AString ToString(Verbosity verbosity, int priority, AString target) { target.Field()._(verbosity.ToString()).Field(8, Alignment.Left) ._('('); if (priority == Lox.PrioSource) { target._("Source) "); } else if (priority == Lox.PrioProtected) { target._("Protected)"); } else if (priority == Configuration.PrioCmdLine) { target._("CmdLine) "); } else if (priority == Configuration.PrioEnvVars) { target._("EnvVars) "); } else if (priority == Configuration.PrioIniFile) { target._("IniFile) "); } else { target._(priority)._(')'); } return(target); }
public void InAnyOrderWithMissingItemFailsTest() { AssertFails( Items("one", "two"), AList.InAnyOrder().WithOnly(AString.EqualToValues("one", "two", "three")) ); }
public void trim(String source, String expected) { AString x = new AString(source); x.trim(); Assert.Equal(expected, x.ToString()); }
/** **************************************************************************************** * Invokes grand-parent's method and in addition, de-registers with * \ref cs::aworx::lib::ALIB::StdOutputStreamsLock "ALIB.StdOutputStreamsLock" * @param acquirer The acquirer to remove. * @return The new number of \e acquirers set. ******************************************************************************************/ public override int RemoveAcquirer(ThreadLock acquirer) { // d-register with ALIB lockers (if not done yet) if (usesStdStreams) { ALIB.Lock.Acquire(); int stdStreamLockRegistrationCounter = --this.stdStreamLockRegistrationCounter; ALIB.Lock.Release(); if (stdStreamLockRegistrationCounter == 0) { ALIB.StdOutputStreamsLock.RemoveAcquirer(this); } } // export autosizes to configuration { AString autoSizes = new AString(); AString variableName = new AString(name); variableName._("_AUTO_SIZES"); AutoSizes.Export(autoSizes); ALIB.Config.Save(ALox.ConfigCategoryName, variableName, autoSizes, "Auto size values of last run"); } // call parents' implementation return(base.RemoveAcquirer(acquirer)); }
/** **************************************************************************************** * This is for debugging purposes. E.g. this enables the \e Monodevelop IDE to display * object descriptions in the debugger. * @returns A human readable string representation of this object. ******************************************************************************************/ public override String ToString() { AString target = new AString(); Export(target); return(target.ToString()); }
public void EqualToWithKeyAndValueMatcher() { AssertPasses(Pair("key", "val"), AKeyValuePair.EqualTo(AString.Containing("key"), AString.Containing("val"))); AssertFails(Pair("key", "val"), AKeyValuePair.EqualTo(AString.Containing("key"), AString.Containing("not_val"))); AssertFails(Pair("key", "val"), AKeyValuePair.EqualTo(AString.Containing("not_key"), AString.Containing("val"))); }
/** **************************************************************************************** * Converts variable value data. Replaces certain characters by escape sequences. * @param os The output stream to write to. * @param value The value to write * @param temp A temporary AString needed internally. * @return The difference of length written and given value length. ******************************************************************************************/ protected int addEscapeSequences(TextWriter os, Substring value, AString temp) { int sizeDiff = 0; temp.Clear(); if (char.IsWhiteSpace(value.CharAtStart()) || char.IsWhiteSpace(value.CharAtEnd())) { temp._('\"')._(value)._('\"'); sizeDiff = 2; } else { temp._(value); } for (int i = 0; i < EscapeSequences.Count;) { String replacement = EscapeSequences[i++]; String needle = EscapeSequences[i++]; sizeDiff += temp.SearchAndReplace(needle, replacement, 0) * (replacement.Length - needle.Length); } os.Write(temp.Buffer(), 0, temp.Length()); return(sizeDiff); }
public void InOrderAtLeastDuplicateItemAtStartPassesTest() { AssertPasses( Items("one", "one", "two", "three", "three"), AList.InOrder().WithAtLeast(AString.EqualToValues("one", "two", "three")) ); }
/** ******************************************************************************************** * Searches a domain. If not found, the domain is (or path of domains are) created in * the domain tree. * If the path string starts with the character defined in #PathSeparator, then * the search (and creation) is done starting from the root domain of this domain and not * from this domain. * * @param domainPathAS Path and domain 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. **********************************************************************************************/ public Domain Find(AString domainPathAS, Case sensitivity, int maxCreate, ref bool wasCreated) { Substring domainPath = tSubstring; domainPath.Set(domainPathAS); // set optional output parameter as default to false wasCreated = false; int lenBeforeTrim = domainPath.Length(); // if string is empty (resp. contains only separator characters), return ourselves while (domainPath.Consume(PathSeparator)) { ; } if (domainPath.IsEmpty()) { return(this); } // Trailing domain separator found: call find on root domain Domain startDomain = this; if (lenBeforeTrim > domainPath.Length()) { while (startDomain.Parent != null) { startDomain = startDomain.Parent; } } // call find return(startDomain.findRecursive(domainPath, sensitivity, maxCreate, ref wasCreated)); }
public void InOrderAtLeastMissingItemAtStartFailsTest() { AssertFails( Items("two", "three"), AList.InOrder().WithAtLeast(AString.EqualToValues("one", "two", "three")) ); }
public string Get(MisIdiomas lang) { string r = ""; AString.TryGetValue(lang, out r); return(r); }
//-------------------------------------------------------------------------------------------------- //--- Test Constructors //-------------------------------------------------------------------------------------------------- void constructorTest( String inputString, AString result, bool trim ) { Substring tok= new Substring( inputString ); if ( trim ) tok.Trim(); tok.CopyTo( result ); }
/** ************************************************************************************ * Logs the header and invokes instRecursive() * @param o The object to be logged. * @param maxRecursion The maximum depth of recursion for logging nested object. * @param headLine The headline to log. **************************************************************************************/ protected static void instMain(Object o, int maxRecursion, String headLine) { // prepare fields if (toolBuf == null) { toolBuf = new AString(1024); } else { toolBuf.Clear(); } if (tempBuf == null) { tempBuf = new AString(64); } instLineNumber = 0; instLineBeginIdx = 0; instObject2LineNumber = new Dictionary <Object, UInt32>(); // log headline if answer exception if (headLine != null) { toolBuf._(headLine)._(' '); } // dump the object instRecursive(o, maxRecursion, headLine != null ? 1 : 0); // dispose the dictionary instObject2LineNumber = null; }
public static void XML(String domain, Verbosity verbosity, XElement xElement, String headLine = null, Lox lox = null, [CallerLineNumber] int cln = 0, [CallerFilePath] String csf = "", [CallerMemberName] String cmn = "") { #if ALOX_DBG_LOG || ALOX_REL_LOG try { Lock.Acquire(); // create/clear toolBuf if (toolBuf == null) { toolBuf = new AString(1024); } else { toolBuf.Clear(); } // dump exception to the Buffer xmlElement(xElement, headLine, 0); // if no lox given, use static Log.LOX or, if debug logging is not active, return if (lox == null) #if ALOX_DBG_LOG { lox = Log.LOX; } #else { return; } #endif // log it using the static Log interface lox.Entry(domain, verbosity, toolBuf, cln, csf, cmn); } finally { Lock.Release(); } #endif }
public void AMockFailsVerifyAllTest() { Scenario("AMockTest") .Given(AMock <ISpeaker>() .WhereMethod(t => t.Says()) .Returns("DoDah") .Instance) .WhenNothing() .Then(() => { /*Scenario passes but verify should fail*/ }); MockException thrown = null; try { //force scenario completion and assertions AfterTest(); } catch (Exception e) { thrown = e.InnerException as MockException; } AnException.With() .Type("Moq.MockVerificationException") .Message(AString.Containing("ISpeaker t => t.Says()")) .AssertMatch(thrown); }
public void removeDuplicates(String source, String expected) { AString x = new AString(source); x.removeDuplicates(' '); Assert.Equal(expected, x.ToString()); }
public void InOrderExactPassesTest() { AssertPasses( Items("one", "two", "three"), AList.InOrder().WithOnly(AString.EqualToValues("one", "two", "three")) ); }
// ############################################################################################# // Reimplementing interface of grand-parent class SmartLock // ############################################################################################# /** **************************************************************************************** * Invokes grand-parent's method and in addition, if field #usesStdStreams is set, * registers with * \ref cs::aworx::lib::ALIB::StdOutputStreamsLock "ALIB.StdOutputStreamsLock", respectively * * @param newAcquirer The acquirer to add. * @return The new number of \e acquirers set. ******************************************************************************************/ public override int AddAcquirer(ThreadLock newAcquirer) { // register with ALIB lockers (if not done yet) if (usesStdStreams) { ALIB.Lock.Acquire(); int stdStreamLockRegistrationCounter = this.stdStreamLockRegistrationCounter++; ALIB.Lock.Release(); if (stdStreamLockRegistrationCounter == 0) { ALIB.StdOutputStreamsLock.AddAcquirer(this); } } // get auto sizes from last session { AString autoSizes = new AString(); AString variableName = new AString(name); variableName._("_AUTO_SIZES"); if (ALIB.Config.Get(ALox.ConfigCategoryName, variableName, autoSizes) != 0) { AutoSizes.Import(autoSizes); } } // call parents' implementation return(base.AddAcquirer(newAcquirer)); }
void PerformanceTestRL() { // create a lox for release logging Lox lox = new Lox("ReleaseLox"); TextLogger relLogger = Lox.CreateConsoleLogger(); MemoryLogger ml = new MemoryLogger(); lox.SetVerbosity(relLogger, Verbosity.Verbose, "/CON"); lox.SetVerbosity(ml, Verbosity.Verbose, "/MEM"); lox.Info("/CON", "Logging simple info lines into a memory logger"); AString msgBuf = new AString( ); long fastest = long.MaxValue; Ticks timer = new Ticks(); int qtyLines = 1000; int qtyLoops = 2000; //1000 if (System.Diagnostics.Debugger.IsAttached) { qtyLines = qtyLoops = 10; } for (int i = 0; i < qtyLoops; i++) { #if ALOX_DBG_LOG || ALOX_REL_LOG ml.MemoryLog.Clear(); #endif timer.Set(); for (int ii = 0; ii < qtyLines; ii++) { lox.Info("/MEM", "Test Line"); if (i == 0 && ii == 0) { Console.WriteLine(ml.MemoryLog.ToString()); } } long t = timer.Age().Raw(); if (fastest > t) { fastest = t; lox.Info("/CON", msgBuf.Clear()._("Pass ")._(i, 3)._(" is new fastest: ") ._((int)(new Ticks(fastest)).InMicros(), 0) ._(" micros per ")._(qtyLines)._(" logs.")); } } double microsPerLog = ((double)(new Ticks(fastest)).InMicros()) / qtyLines; int logsPerSecond = (int)(1000000.0 / microsPerLog); lox.Info("/CON", msgBuf._()._(" ")._(ESC.MAGENTA)._("Fastest Release Logging: ") ._(microsPerLog)._(" micros per log (resp ") ._(logsPerSecond)._(" logs per second) ")); lox.RemoveLogger(ml); lox.RemoveLogger(relLogger); }
void SampleALibReport() { Console.WriteLine("Sample: ALib Report via using ALox"); Log.AddDebugLogger(); Log.SetDomain("/SAMPLE", Scope.Filename); Log.SetVerbosity(Log.DebugLogger, Verbosity.Info, ""); Log.Info("Method \"Log.AddDebugLogger()\" by default creates a replacement for ALibs'\n" + "error/warning reporter. If this is a debug compiliation, let's have a try and\n" + "create 3 Messages:"); Report.GetDefault().PushHaltFlags(false, false); ALIB.ERROR("This is an error report!"); ALIB.WARNING("And this is a warning!"); AString illegalAccess = new AString(10); illegalAccess._("1234"); illegalAccess.SetCharAt_NC(5, '5'); Report.GetDefault().PopHaltFlags(); Log.SetVerbosity(Log.DebugLogger, Verbosity.Verbose, ALox.InternalDomains); ALIB.REPORT(2, "This is an ALib Report. Types other than '0' and '1' are user defined.\n" + "Verbosity of ALox.InternalDomains has to be increased to see them when using" + " ALoxReportWriter."); Log.Info("Note the domain prefix '" + ALox.InternalDomains.ToString() + "'. This addresses " + "the tree of internal domains\nof the Lox, which the report writer is just " + "using for ALib reports."); Log.RemoveDebugLogger(); }
public void SubsequentFailAfterPassThenFailsTest() { var whenStep = new Scenario().Given(DoNothingAction()).When(DoNothingAction()); AssertFails(() => whenStep .Then(() => "ok", AString.EqualTo("ok")) .Then(() => "", AString.EqualTo("fail"))); }
public void EqualsToNullTest() { string nil = null; AssertPasses(nil, AString.EqualTo(nil)); AssertFails("one", AString.EqualTo(nil)); AssertFails("", AString.EqualTo(nil)); }
public void EqualsToIgnoreCaseTest() { AssertPasses("One", AString.EqualToIgnoringCase("One")); AssertPasses("ONE", AString.EqualToIgnoringCase("One")); AssertFails("", AString.EqualToIgnoringCase("One")); AssertFails((string)null, AString.EqualToIgnoringCase("One")); }
public void setStringIndex(int index, String expected) { AString x = new AString("eric"); AString y = new AString(" "); y.setString(x, index); Assert.Equal(expected, y.ToString()); }
public void EqualsToTest() { AssertPasses("One", AString.EqualTo("One")); AssertFails("one", AString.EqualTo("One")); AssertFails("", AString.EqualTo("One")); AssertFails((string)null, AString.EqualTo("One")); }
public void UT_EQ(AString exp, AString s, [CallerFilePath] String csf = "", [CallerLineNumber] int cln = 0, [CallerMemberName] String cmn = "") { if (!exp.Equals(s)) { ASM(csf, cln, cmn, ASS.Clear()._("\"")._(exp)._("\", Given: \"")._(s)._("\".")); } Assert.AreEqual(exp.ToString(), s.ToString()); }
/** ******************************************************************************************** * The conversion method. * @param o The object to convert. * @param target An AString that takes the result. * @return \c true, if the object was converted successfully, \c false otherwise. **********************************************************************************************/ public override bool ConvertObject( Object o, AString target ) { // copy the string into our internal Buffer (or reassign if AString given) if ( o == null ) target._( FmtNullObject ); // <null> else target._( o ) ; // let AString do the conversion // we always return true return true; }
protected bool logSubstring( AString buffer, int start, int length ) { #if !(ALOX_WP71 || ALOX_WP8) Console.Write( buffer.Buffer(), start, length ); #else Console.Write( buffer.ToString( 0, start, length ); #endif return true; }
/** **************************************************************************************** * Writes a string representation of the priority value into the given AString. * * @param priority The priority of the \p verbosity setting. * @param target The target to write into. * @returns \p target to allow concatenated calls. ******************************************************************************************/ public static AString ToStringPriority( int priority, AString target ) { if ( priority == Configuration.PrioDefault ) return target._( "Default " ); if ( priority == Configuration.PrioProtected ) return target._( "Protected" ); if ( priority == Configuration.PrioCmdLine ) return target._( "CmdLine " ); if ( priority == Configuration.PrioEnvironment ) return target._( "EnvVars " ); if ( priority == Configuration.PrioIniFile ) return target._( "IniFile " ); return target.Field()._( priority ).Field( 9, Alignment.Left ); }
public void SubstringConstructor() { AString astr= new AString(); AString res= new AString(); constructorTest( "a" , res, false ); UT_EQ( "a", res ); constructorTest( " a" , res, false ); UT_EQ( " a", res ); constructorTest( "a " , res, false ); UT_EQ( "a ", res ); constructorTest( "a b" , res, false ); UT_EQ( "a b", res ); constructorTest( " a b" , res, false ); UT_EQ( " a b", res ); constructorTest( "a b " , res, false ); UT_EQ( "a b ", res ); constructorTest( "a" , res, true ); UT_EQ( "a", res ); constructorTest( " a" , res, true ); UT_EQ( "a", res ); constructorTest( "a " , res, true ); UT_EQ( "a", res ); constructorTest( "a b" , res, true ); UT_EQ( "a b", res ); constructorTest( " a b" , res, true ); UT_EQ( "a b", res ); constructorTest( "a b " , res, true ); UT_EQ( "a b", res ); // changing whitespaces { { astr.Clear()._( "xy xz abc xy" ); Substring subs= new Substring(); subs.Set(astr).Trim("xy ".ToCharArray()).CopyTo( res ); UT_EQ( "z abc", res ); } { Substring subs= new Substring( "xy xz abc xy" ); subs.TrimStart("xy ".ToCharArray()); subs.TrimEnd("xy ".ToCharArray()); subs.CopyTo( res ); UT_EQ( "z abc", res ); } } // test other constructors { astr.Clear()._( " astring "); UT_TRUE ( (new Substring()).IsEmpty() ); UT_TRUE ( (new Substring()).IsNull() ); UT_EQ( "astring", (new Substring( astr)).Trim() .ToString() ); UT_EQ( "str", (new Substring( astr, 2, 3 )).ToString() ); UT_EQ( "", (new Substring( astr, 20, 3 )).ToString() ); UT_TRUE ( (new Substring( astr, 20, 3 )).IsEmpty() ); UT_FALSE( (new Substring( astr, 20, 3 )).IsNull() ); Substring s2= new Substring( astr); UT_EQ( "astring", new Substring( s2.Trim().ToString() ).ToString() ); UT_EQ( "str", (new Substring( (new Substring( astr, 2,3 )))).ToString() ); } }
/** * Simple constructor copying values * @param categoryFallback Value for field #CategoryFallback (treated as reference, value not copied) * @param category Value for field #Category * @param name Value for field #Name * @param defaultValue Value for field #DefaultValue * @param delim Value for field #Delim * @param formatAttrAlignment Value for field #FormatAttrAlignment * @param formatHints Value for field #FormatHints * @param comments Value for field #Comments */ public VariableDefinition( AString categoryFallback, String category, String name, String defaultValue, char delim, String formatAttrAlignment, Variable.FormatHint formatHints, String comments ) { this.CategoryFallback= categoryFallback; this.Category= category; this.Name= name; this.DefaultValue= defaultValue; this.Delim= delim; this.FormatAttrAlignment= formatAttrAlignment; this.FormatHints= formatHints; this.Comments= comments; }
// ############################################################################################# // static helpers // ############################################################################################# /** **************************************************************************************** * Provides a string representation of the Scope enums. * * @param scope The enum value to retrieve a string representation for. * @param pathLevel The path level. * @param target The target string. * @returns A string representation of the provided Scope value. ******************************************************************************************/ public static AString ToString( Scope scope, int pathLevel, AString target ) { target._( "Scope." ); switch( scope ) { case Scope.Global: { target._("Global"); break; } case Scope.ThreadOuter: { target._("ThreadOuter");break; } case Scope.Path: { target._("Path")._("(L" )._( pathLevel )._( ")" ); break; } case Scope.Filename: { target._("Filename"); break; } case Scope.Method: { target._("Method"); break; } case Scope.ThreadInner: { target._("ThreadInner");break; } } return target; }
public override bool ConvertObject( Object o, AString result ) { if ( o == null ) { result._( "MyObjectConverter: null" ); return true; } if ( o.GetType() == typeof(MyType) ) { result._( "my type" ); return true; } return false; }
//################################################################################################## // SAMPLE code of class documentation //################################################################################################## void documentationSampleTokenizer() { UTSampleWriter utsw= new UTSampleWriter("DOC_SAMPLES_ALIB_LIB_STRING_TOKEN.txt"); //! [DOC_SAMPLES_ALIB_LIB_STRING_TOKEN] // data string to tokenize AString data= new AString( "test; abc ; 1,2 , 3 ; xyz ; including;separator" ); // create tokenizer on data with ';' as delimiter Tokenizer tknzr= new Tokenizer( data, ';' ); // read tokens System.Console.WriteLine( tknzr.Next() ); // will print "test" System.Console.WriteLine( tknzr.Next() ); // will print "abc" System.Console.WriteLine( tknzr.Next() ); // will print "1,2 , 3" // tokenize actual (third) token (nested tokenizer) Tokenizer subTknzr= new Tokenizer( tknzr.Actual, ','); System.Console.Write( subTknzr.Next().ToString() ); while( subTknzr.HasNext() ) System.Console.Write( "~" + subTknzr.Next().ToString() ); System.Console.WriteLine(); // continue with the main tokenizer System.Console.WriteLine( tknzr.Next().ToString() ); // will print "xyz" // grab the rest, as we know that the last token might include our separator character System.Console.WriteLine( tknzr.GetRest().ToString() ); // will print "including;separator" //! [DOC_SAMPLES_ALIB_LIB_STRING_TOKEN] utsw.FlushAndResetConsole(); }
/** **************************************************************************************** * Writes a list of comments to the file. Comment lines are started with '#'. * @param os The output stream to write to. * @param comments The comment lines for the section. * @param tknzr A temporary tokenizer needed internally. ******************************************************************************************/ protected void writeComments( TextWriter os, AString comments, Tokenizer tknzr ) { // is empty when trimmed? (we are lenting tokeinizers field 'actual' to test) if ( tknzr.Actual.Set( comments ).Trim().IsEmpty() ) return; // tokenize by NEWLINE character tknzr.Set( comments, '\n' ); char[] oldWhiteSpaces= tknzr.Whitespaces; tknzr.Whitespaces= " \r\t".ToCharArray(); // \n is not a whitespace while( tknzr.Next(Whitespaces.Keep).IsNotNull() ) { if ( !startsWithCommentSymbol( tknzr.Actual ) ) os.Write( DefaultCommentPrefix ); os.WriteLine( tknzr.Actual.Buf, tknzr.Actual.Start, tknzr.Actual.Length() ); } tknzr.Whitespaces= oldWhiteSpaces; }
/** **************************************************************************************** * Searches the \ref cs::aworx::lib::config::InMemoryPlugin::Section "Section" with the given name. * If the section was not found, it is created. * If the section is found and has no comments, then the provided comments are appended. * @param name The name of the section to be retrieved. * @param comments The comment lines for the section, in the case the section is not * found. If this is null, no section is created. * @return Returns the section if it was found or created. \c null otherwise. ******************************************************************************************/ public Section SearchOrCreateSection( Object name, AString comments ) { Section s= SearchSection( name ); if ( s == null ) Sections.Add( s= createSection( name ) ); if ( s.Comments.IsEmpty() ) s.Comments._( comments ); return s; }
/** **************************************************************************************** * Helper method for formatting attributes * @param value The value to check * @param alignmentSeparator The string defining the separator. * @return Returns the position of the first '=' or ':' character ******************************************************************************************/ protected static int getAssignmentPos( AString value, String alignmentSeparator ) { int idx= value.IndexOf( alignmentSeparator ); if( idx > 0 ) { int idxQuote= value.IndexOf( '"' ); if ( idxQuote < 0 || idxQuote > idx ) return idx; } return -1; }
/** **************************************************************************************** * Write all configuration data into the file. * @return Returns the #Status of the operation. ******************************************************************************************/ public IniFile.Status WriteFile() { LastStatus= Status.OK; // open file StreamWriter file; try { file= new StreamWriter( FileName.ToString() ); } catch( Exception ) { return LastStatus= Status.ERROR_OPENING_FILE; } Tokenizer tknzr= new Tokenizer(); AString externalizedValue= new AString(); // write file header if ( FileComments.IsNotEmpty() ) { writeComments( file, FileComments, tknzr ); file.WriteLine(); } // loop over all sections int cntVars= 0; foreach ( Section section in Sections ) { if ( cntVars > 0 ) file.WriteLine(); // write section comments and name writeComments( file, section.Comments, tknzr ); if ( section.Name.IsNotEmpty() ) { file.Write('['); file.Write( section.Name.Buffer(), 0, section.Name.Length() ); file.WriteLine(']'); } // variables int maxVarLength= 0; foreach ( Entry entry in section.Entries ) maxVarLength= Math.Max( maxVarLength, entry.Name.Length() ); bool previousVarHasComments= true; foreach ( Entry entry in section.Entries ) { cntVars++; // write comments if( entry.Comments.IsNotEmpty() ) { // we make an extra empty line if previous var had no comments if( !previousVarHasComments) file.WriteLine(); writeComments( file, entry.Comments, tknzr ); } // write name = file.Write( entry.Name.Buffer(), 0, entry.Name.Length() ); // either write raw value (if it was not used by the application) IniFile.Entry ifEntry= (IniFile.Entry) entry; if ( ifEntry.RawValue.IsNotEmpty() ) { file.Write( ifEntry.RawValue.Buffer(), 0, ifEntry.RawValue.Length() ); } // or write the values parsed by the software else { file.Write( '=' ); Util.WriteSpaces( file, maxVarLength - entry.Name.Length() + 1 ); bool isFirst= true; //-------- write as single-line ---------- if ( 0 == ( entry.FormatHints & Variable.FormatHint.MultLine ) ) { bool delimSpaces= (0 == ( entry.FormatHints & Variable.FormatHint.NoDelimSpaces ) ); foreach( AString value in entry.Values ) { // write delim and backslash of previous line, newline and then spaces of actual line if ( !isFirst ) { ALIB.ASSERT_ERROR( entry.Delim != 0, "No delimiter given for multi-value variable \"" + entry.Name + "\"." ); if( delimSpaces && FormatSpaceBeforeDelim) file.Write( ' ' ); file.Write( entry.Delim ); if( delimSpaces && FormatSpaceAfterDelim) file.Write( ' ' ); } // externalize value externalizedValue._(); StringConverter.ExternalizeValue( value, externalizedValue, entry.Delim ); file.Write( externalizedValue.Buffer(), 0, externalizedValue.Length() ); isFirst= false; } } // ---------- write as multi-line ---------- else { int backSlashPos= 0; int lastLineLen= 0; // Get maximum position of attribute assignment char '=' or ':' (if exists) int maxAttributeAssignPos= 0; bool allAttrHavePrecedingBlanks= true; if (entry.FormatAttrAlignment != null ) { foreach( AString value in entry.Values ) { int attributeAssignPos= getAssignmentPos( value, entry.FormatAttrAlignment ); if ( attributeAssignPos > 0 ) { if ( maxAttributeAssignPos < attributeAssignPos ) maxAttributeAssignPos= attributeAssignPos; allAttrHavePrecedingBlanks&= value.CharAt( attributeAssignPos - 1 ) == ' '; } } if ( !allAttrHavePrecedingBlanks ) maxAttributeAssignPos += 1; } // loop over values of entry foreach( AString value in entry.Values ) { // write delim and backslash of previous line, newline and then spaces of actual line if ( !isFirst ) { ALIB.ASSERT_ERROR( entry.Delim != 0, "No delimiter given for multi-value variable \"" + entry.Name + "\"." ); file.Write( entry.Delim ); if ( backSlashPos < lastLineLen + 1 ) backSlashPos= lastLineLen + 4; Util.WriteSpaces( file, backSlashPos - lastLineLen ); file.WriteLine( '\\' ); Util.WriteSpaces( file, maxVarLength + 2 ); // 2 for "= " } // externalize value externalizedValue._(); StringConverter.ExternalizeValue( value, externalizedValue, entry.Delim ); // if first character is a INI comment char, then escape it char firstChar= externalizedValue.CharAt(0); if( !isFirst && (firstChar == '#' || firstChar == ';' ) ) externalizedValue.InsertAt("\\", 0 ); // if assignment, insert spaces to align assignments if (entry.FormatAttrAlignment != null ) { int attributeAssignPos= getAssignmentPos( externalizedValue, entry.FormatAttrAlignment ); if ( attributeAssignPos > 0 && attributeAssignPos < maxAttributeAssignPos ) externalizedValue.InsertChars( ' ', maxAttributeAssignPos-attributeAssignPos, attributeAssignPos + (FormatIncludeDelimInAttrAlignment ? 0 : entry.FormatAttrAlignment.Length ) ); } file.Write( externalizedValue.Buffer(), 0, externalizedValue.Length() ); lastLineLen= maxVarLength + 2 + externalizedValue.Length(); isFirst= false; } } } file.WriteLine(); // add an empty line if we have comments if( (previousVarHasComments= entry.Comments.IsNotEmpty() ) == true ) file.WriteLine(); } } // close file file.Close(); return LastStatus; }
/** * Overrides default method. If we have not parsed the INI file text value, yet, * we do this now. * * @param parent The plug-in we belong to. * @param variable The variable to fill with our values. */ public override void ToVariable( InMemoryPlugin parent, Variable variable ) { // if we are still raw, then parse the INI file content if ( Values.Count == 0 ) { ALIB.ASSERT( Delim == '\0' ); Delim= variable.Delim; variable.Comments._()._( Comments ); //----- remove INI-File specific from raw value ----- AString raw= new AString(); raw._( RawValue ); // remove '=' raw.TrimStart(); if ( raw.CharAtStart() != '=' ) { ALIB.WARNING( "No equal sign in variable \"" + variable.Fullname + "\" of INI file." ); } else raw.DeleteStart(1).TrimStart(); // remove "\\n" int startIdx= 0; while ( (startIdx= raw.IndexOf( '\n', startIdx )) >= 0 ) { // find \\n and trim around this location int delLen= 2; if ( raw.CharAt( --startIdx) == '\r' ) { delLen= 3; --startIdx; } ALIB.ASSERT( raw.CharAt(startIdx) == '\\' ); raw.Delete( startIdx, delLen ); startIdx= raw.TrimAt( startIdx ); // if now the next value is starting with a comment symbol, we remove to the next \n for(;;) { char c= raw.CharAt( startIdx ); if ( c != '#' && c != ';' && ( c != '/' || raw.CharAt( startIdx + 1 ) != '/' ) ) break; int idx= raw.IndexOf( '\n' ); if (idx < 0 ) idx= raw.Length(); raw.Delete( startIdx, idx - startIdx + 1 ); if( startIdx >= raw.Length() ) break; startIdx= raw.TrimAt( startIdx ); } } // now convert parent.StringConverter.LoadFromString( variable, raw ); // copy the parsed values back to our entry and store the delimiter for( int i= 0; i < variable.Size() ; i++ ) Values.Add( new AString( variable.GetString( i ) ) ); } // otherwise, use base method else base.ToVariable( parent, variable ); }
// ############################################################################################# // 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; }
void SaveTutorialOutput( string fileName, AString log ) { if ( outputPath.Length == 0 ) return; #if !WINDOWS_PHONE System.IO.File.WriteAllText( outputPath + fileName, log.ToString() ); #endif }
public void MeasureIncreasingDoublingLoop() { UT_INIT(); Log.SetVerbosity( new ConsoleLogger(), Verbosity.Verbose, "/" ); Log.MapThreadName( "UnitTest" ); Log.SetDomain( "TickWatch", Scope.Method ); Log.Info( "This test shows quite nicely, how the just in time compiler steps in when we are looping heavily!" ); String testString= "-------------------------------------------------------------------------------------------#"; AString testAString= new AString( testString ); TickWatch ttString= new TickWatch(); TickWatch ttAString= new TickWatch(); for (int run= 4; run < 20; run++ ) { int qtyLoops= (run == 0) ? 0 : (1 << (run -1)); // use String.IndexOf() ttString.Reset(); int nonOptimizableUsedResultValue= 0; for (int i= 0; i < qtyLoops; i++ ) nonOptimizableUsedResultValue+= testString.IndexOf( '#' ); Ticks sSample= ttString.Sample(); // use AString.IndexOf() ttAString.Reset(); for (int i= 0; i < qtyLoops; i++ ) nonOptimizableUsedResultValue+= testAString.IndexOf( '#' ); Ticks aSample= ttAString.Sample(); if ( nonOptimizableUsedResultValue > -1 ) // this is always true, just for the sake that the compiler does not optimize the whole code! Log.Info( Log.Buf()._( "Search loops " ) .Field()._( qtyLoops.ToString() ) .Field( 6 ) ._( ": time needed: " ) .Field()._( (int) sSample.InNanos() ).Field( 8 ) ._( " / " ) .Field()._( (int) aSample.InNanos() ).Field( 8 ) ._( " Ratio String/AString: " ) ._( ((double) sSample.Raw()) / ((double) aSample.Raw()) ) ); } }
Variable Define( VariableDefinition definition, params Object[] replacements ) { clear(); Delim= definition.Delim; FormatHints= definition.FormatHints; FormatAttrAlignment= definition.FormatAttrAlignment; // set Category, Name, Comment if( definition.Category != null ) Category._( definition.Category ); else Category._( definition.CategoryFallback ); Name ._( definition.Name ); Comments._( definition.Comments ); if ( definition.DefaultValue != null ) DefaultValue._()._( definition.DefaultValue ); else DefaultValue.SetNull(); // replace strings if ( replacements != null && replacements.Length > 0 ) { AString search= Fullname; // just an alias name AString repl= new AString(); values.Add(repl); // reuse this string later for( int i= 0; i < replacements.Length; i++ ) { search._()._("%")._(i + 1); repl ._()._( replacements[i] ); Category .SearchAndReplace( search, repl ); Name .SearchAndReplace( search, repl ); Comments .SearchAndReplace( search, repl ); DefaultValue.SearchAndReplace( search, repl ); } search._(); } // set full name if( Category.IsNotEmpty() ) Fullname._( Category )._( '_' ); Fullname._( Name ); ALIB.ASSERT_WARNING( Name.IsNotEmpty(), "Empty variable name given" ); return this; }
public static readonly String EOMETA = "\x001BA0"; ///< End of meta information in log string /** ************************************************************************************************ * Replaces ESC codes in a string reversely to "ESC.XXX". * @param target The string to replace in. * @param startIdx The index to start searching for ESC codes. **************************************************************************************************/ public static void ReplaceToReadable( AString target, int startIdx ) { while( (startIdx= target.IndexOf( '\x001B', startIdx ) ) >= 0 ) { String val= "{ESC."; char c= target.CharAt( startIdx + 1 ); char c2= target.CharAt( startIdx + 2 ); String code= "ERROR"; // colors if( c == 'c' || c == 'C' ) { if ( c == 'C' ) val+= "BG_" ; switch( c2 - '0' ) { case 0: code= "RED" ; break; case 1: code= "GREEN" ; break; case 2: code= "YELLOW" ; break; case 3: code= "BLUE" ; break; case 4: code= "MAGENTA" ; break; case 5: code= "CYAN" ; break; case 6: code= "BLACK" ; break; case 7: code= "WHITE" ; break; case 8: code= "GRAY" ; break; case 9: code= "RESET" ; break; default: code= "COL_ERR"; break; } } // styles else if( c == 's' ) { switch( c2 ) { case 'B': code= "BOLD" ; break; case 'I': code= "ITALICS" ; break; case 'r': code= "STYLE_RESET" ; break; case 'a': code= "RESET" ; break; default: code= "STYLE_ERR" ; break; } } // styles else if( c == 'l' ) { switch( c2 ) { case 'S': code= "URL_START" ; break; case 'E': code= "URL_END" ; break; default: code= "URL_ERR" ; break; } } // others else if( c == 'l' && c2 == '0' ) code= "TAB"; else if( c == 'A' && c2 == '0' ) code= "EOMETA"; // Replace val+= code + '}'; target.ReplaceSubstring( val, startIdx, 3 ); startIdx+= 3; } }
/** ******************************************************************************************** * Searches a domain. If not found, the domain is (or path of domains are) created in * the domain tree. * If the path string starts with the character defined in #Separator, then * the search (and creation) is done starting from the root domain of this domain and not * from this domain. * * @param domainPathAS Path and domain 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. **********************************************************************************************/ public Domain Find( AString domainPathAS, Case sensitivity, int maxCreate, ref bool wasCreated ) { Substring domainPath= tSubstring; domainPath.Set( domainPathAS ); // set optional output parameter as default to false wasCreated= false; int lenBeforeTrim= domainPath.Length(); // if string is empty (resp. contains only separator characters), return ourselves while ( domainPath.Consume( Separator ) ) ; if( domainPath.IsEmpty() ) { return this; } // Trailing domain separator found: call find on root domain Domain startDomain= this; if ( lenBeforeTrim > domainPath.Length() ) { while (startDomain.Parent != null ) startDomain= startDomain.Parent; } // call find return startDomain.findRecursive( domainPath, sensitivity, maxCreate, ref wasCreated ); }
public static void GetState( AString buf, Lox.StateInfo flags, [CallerLineNumber] int cln= 0,[CallerFilePath] String csf="",[CallerMemberName] String cmn="" ) { #if ALOX_DBG_LOG LOX.GetState( buf, flags, cln,csf,cmn ); #endif }
/** ******************************************************************************************** * * Helper function that logs a time given difference into the given buffer in a human readable * format. Works from micro seconds to days. * * @param buf The buffer to write the time difference representation into. * @param diffNanos The time difference to write in nanoseconds. **********************************************************************************************/ protected virtual void writeTimeDiff( AString buf, long diffNanos ) { // unmeasurable? if ( diffNanos < TimeDiffMinimum ) { buf._( TimeDiffNone ); return; } if ( diffNanos < 1000 ) { buf._( (int) diffNanos, 3 )._( TimeDiffNanos ); return; } // we continue with micros long diffMicros= diffNanos / 1000L; // below 1000 microseconds? if ( diffMicros < 1000 ) { buf._( (int) diffMicros, 3 )._( TimeDiffMicros ); return; } // below 1000 ms? if ( diffMicros < 1000000 ) { buf._( (int) (diffMicros / 1000), 3 )._( TimeDiffMillis ); return; } // below 10 secs (rounded) ? if ( diffMicros < 9995000 ) { // convert to hundredth of secs long hundredthSecs= ((diffMicros / 1000) + 5) / 10; // print two digits after dot x.xx buf._( (int) (hundredthSecs / 100), 1 ) ._( '.' ) ._( (int) (hundredthSecs % 100), 2 ) ._( TimeDiffSecs ); return; } // convert to tenth of secs long tenthSecs= ((diffMicros / 10000) + 5) / 10 ; // below 100 secs ? if ( tenthSecs < 1000 ) { // print one digits after dot xx.x (round value by adding 5 hundredth) buf._( (int) ( tenthSecs / 10 ), 2 ) ._( '.' ) ._( (int) ( tenthSecs % 10 ), 1 ) ._( TimeDiffSecs ); return; } // below 10 minutes ? if ( tenthSecs < 6000 ) { // convert to hundredth of minutes long hundredthMins= tenthSecs / 6; // print two digits after dot x.xx buf._( (int) (hundredthMins / 100), 1 ) ._( '.' ) ._( (int) (hundredthMins % 100), 2 ) ._( TimeDiffMins ); return; } // convert to tenth of minutes long tenthMins= tenthSecs / 60; // below 100 minutes ? if ( tenthMins < 1000 ) { // print one digits after dot xx.x (round value by adding 5 hundredth) buf._( (int) (tenthMins / 10), 2 ) ._( '.' ) ._( (int) (tenthMins % 10), 1 ) ._( TimeDiffMins ); return; } // below ten hours? if ( tenthMins < 6000 ) { // convert to hundredth of hours long hundredthHours= tenthMins / 6; // print two digits after dot x.xx buf._( (int) (hundredthHours / 100), 1 ) ._( '.' ) ._( (int) (hundredthHours % 100), 2 ) ._( TimeDiffHours ); return; } // convert to tenth of minutes long tenthHours= tenthMins / 60; // below 10 hours ? if ( tenthHours < 1000 ) { // print two digits after dot x.xx buf._( (int) (tenthHours / 10), 2 ) ._( '.' ) ._( (int) (tenthHours % 10), 1 ) ._( TimeDiffHours ); return; } // below 100 hours ? if ( tenthHours < 1000 ) { // print one digits after dot xx.x (round value by adding 5 hundredth) buf._( (int) (tenthHours / 10), 2 ) ._( '.' ) ._( (int) ((tenthHours / 10) % 10), 1 ) ._( TimeDiffHours ); return; } // convert to hundredth of days long hundredthDays= tenthHours * 10 / 24; // below 10 days ? if ( hundredthDays < 1000 ) { // print two digits after dot x.xx buf._( (int) (hundredthDays / 100), 1 ) ._( '.' ) ._( (int) (hundredthDays % 100), 2 ) ._( TimeDiffDays ); return; } // 10 days or more (print days plus one digit after the comma) // print one digits after dot xx.x (round value by adding 5 hundredth) buf ._( (int) (hundredthDays / 100), 2 ) ._( '.' ) ._( (int) ((hundredthDays / 10) % 10), 1 ) ._( TimeDiffDays ); }
/** ******************************************************************************************** * 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; } }
/** ******************************************************************************************** * Parses the #Format string and logs meta information into the log buffer. For each * variable found, method #processVariable is invoked. Hence, to add new variables, * the latter method can be overwritten by descendants. Overwriting this method is * recommended for formatter classes that do not rely on format strings. * @param logger The logger that we are embedded in. * @param buffer The buffer to write meta information into. * @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>.. * * @return The number of tab sequences that were written (by adding ESC::TAB to the buffer). **********************************************************************************************/ public virtual int Write( TextLogger logger, AString buffer, Domain domain, Verbosity verbosity, ScopeInfo scope ) { int qtyTabStops= 0; // check if ( Format == null || Format.IsEmpty() ) return 0; // clear DateTime singleton callerDateTime= null ; // loop/switch over content specified in configuration array tTok.Set( Format, '%' ); while ( true ) { // get next and log substring between commands if ( tTok.Next(Whitespaces.Keep).IsNotEmpty() ) buffer._( tTok.Actual ); // previous next did not find a delimiter if ( !tTok.HasNext() ) break; // process the found variable qtyTabStops+= processVariable( logger, domain, verbosity, scope, buffer, tTok.Rest ); } return qtyTabStops; }
// ############################################################################################# // Constructor // ############################################################################################# /** **************************************************************************************** * Creates an AnsiLogger. * @param textWriter The TextWriter object to write into. * @param usesStdStreams Denotes whether this logger writes to the * <em>standard output streams</em>. * @param name The name of the \e Logger, defaults to what is provided with * parameter \p typeName. * @param typeName The type of the \e Logger, defaults to "ANSI". ******************************************************************************************/ public AnsiLogger( System.IO.TextWriter textWriter, bool usesStdStreams, String name= null, String typeName= "ANSI" ) : base( name, typeName, usesStdStreams ) { this.textWriter= textWriter; // evaluate environment variable "ALOX_CONSOLE_HAS_LIGHT_BACKGROUND" Variable variable= new Variable( ALox.CONSOLE_HAS_LIGHT_BACKGROUND ); variable.Load(); if ( variable.Size() > 0 ) IsBackgroundLight= variable.IsTrue(); else { // on ANSI terminals we can only guess. Our guess is: console windows have dark background IsBackgroundLight= false; } // remove verbosity information and colorize the whole line MetaInfo.Format.SearchAndReplace( "]%V[", "][" ); if ( IsBackgroundLight ) { MsgPrefixError = ANSI_RED; MsgPrefixWarning = ANSI_BLUE; MsgPrefixVerbose = ANSI_GRAY; } else { MsgPrefixError = ANSI_LIGHT_RED; MsgPrefixWarning = ANSI_LIGHT_BLUE; MsgPrefixVerbose = ANSI_LIGHT_GRAY; } // set source file background to gray AString ansiBGGray= new AString( ESC.BG_GRAY ); ansiBGGray._( "%SF(%SL):" )._( ANSI_BG_STD_COL ); MetaInfo.Format.SearchAndReplace( "%SF(%SL):", ansiBGGray.ToString() ); }
/** **************************************************************************************** * Provides a string representation of a this object. * @param target The target AString. * @returns The \p target, with string representation of the provided Scope value * appended ******************************************************************************************/ public AString ToString( AString target ) { target._( '[' ); target._( '\"' )._( StringValue )._( "\"," ); target._( IntegerValue ); if ( ObjectValue != null ) target._NC( ",<object>" ); target._( ']' ); return target; }
public static void PerformanceTestRL() { // create a lox for release logging Lox lox= new Lox( "ReleaseLox" ); TextLogger relLogger= Lox.CreateConsoleLogger(); MemoryLogger ml = new MemoryLogger(); lox.SetVerbosity( relLogger, Verbosity.Verbose, "/CON" ); lox.SetVerbosity( ml , Verbosity.Verbose, "/MEM" ); lox.Info( "/CON", "Logging simple info lines into a memory logger" ); AString msgBuf= new AString( ); long fastest= long.MaxValue; Ticks timer= new Ticks(); int qtyLines= 100; int qtyLoops= 1000; if( System.Diagnostics.Debugger.IsAttached ) qtyLines= qtyLoops= 10; for ( int i= 0 ; i < qtyLoops ; i++ ) { #if ALOX_DBG_LOG || ALOX_REL_LOG ml.MemoryLog.Clear(); #endif timer.Set(); for ( int ii= 0 ; ii < qtyLines ; ii++ ) { lox.Info( "/MEM", "Test Line" ); if( i== 0 && ii == 0) Console.WriteLine( ml.MemoryLog.ToString() ); } long t= timer.Age().Raw(); if ( fastest > t ) { fastest= t; lox.Info( "/CON", msgBuf.Clear()._( "Pass " )._( i, 3)._( " is new fastest: ") ._( (int) (new Ticks( fastest)).InMicros(), 0) ._( " micros per ")._(qtyLines)._(" logs.") ); } } double microsPerLog= ( (double) (new Ticks(fastest)).InMicros() ) / qtyLines; int logsPerSecond= (int)( 1000000.0 / microsPerLog); lox.Info( "/CON", msgBuf._()._( " " )._( ESC.MAGENTA )._( "Fastest Release Logging: " ) ._( microsPerLog )._( " micros per log (resp " ) ._( logsPerSecond )._( " logs per second) " ) ); lox.RemoveLogger( ml ); lox.RemoveLogger( relLogger ); }
public static void SampleALibReport() { Console.WriteLine( "Sample: ALib Report via using ALox" ); Log.AddDebugLogger(); Log.SetDomain( "/SAMPLE", Scope.Filename); Log.SetVerbosity( Log.DebugLogger, Verbosity.Info, "" ); Log.Info( "Method \"Log.AddDebugLogger()\" by default creates a replacement for the\n" + "standard ALib report writer. If this is a debug compiliation, let's have a try and\n" + "create 3 Messages:" ); Report.GetDefault().PushHaltFlags( false, false ); ALIB.ERROR( "This is an error report!" ); ALIB.WARNING( "And this is a warning!" ); AString illegalAccess= new AString(10); illegalAccess._("1234"); illegalAccess.SetCharAt_NC(5, '5'); Report.GetDefault().PopHaltFlags(); Log.SetVerbosity( Log.DebugLogger, Verbosity.Verbose, ALox.InternalDomains ); ALIB.REPORT( 2, "This is an ALib Report. Types other than '0' and '1' are user defined.\n" + "Verbosity of ALox.InternalDomains has to be increased to see them when using" + " ALoxReportWriter." ); Log.Info( "Note the domain prefix '" + ALox.InternalDomains.ToString() + "'. This addresses " + "the tree of internal domains\nof the Lox, which the report writer is just " + "using for ALib reports." ); Log.RemoveDebugLogger(); }
// ############################################################################################# // logText // ############################################################################################# /** ******************************************************************************************** * * The implementation of the abstract method of parent class TextLogger. Logs messages to the * application console and/or the VStudio output window. * * @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 msg The log message * @param scope Information about the scope of the <em>Log Statement</em>.. * @param lineNumber The line number of a multi-line message, starting with 0. For * single line messages this is -1. **********************************************************************************************/ override protected void logText( Domain domain, Verbosity verbosity, AString msg, ScopeInfo scope, int lineNumber) { // loop over message, print the parts between the escape sequences Tokenizer msgParts= new Tokenizer( msg, '\x001B' ); Substring actual= msgParts.Actual; Substring rest= msgParts.Rest; int column= 0; for(;;) { msgParts.Next( Whitespaces.Keep ); // check if this is an ANSI sequence already if ( rest.CharAtStart() == '[' ) { // read the 'm' int idx= rest.IndexOf( 'm' ); if ( idx < 0 ) // unknown ANSI Code { ALIB.WARNING( "Unknown ANSI ESC Code " ); textWriter.Write( actual.Buf, actual.Start, actual.Length() ); continue; } column+= actual.Length(); actual.End= rest.Start + idx ; rest.Start+= idx + 1; textWriter.Write( actual.Buf, actual.Start, actual.Length() ); continue; } if ( actual.IsNotEmpty() ) { textWriter.Write( actual.Buf, actual.Start, actual.Length() ); column+= actual.Length(); } // end of loop? if ( !msgParts.HasNext() ) break; // found an ESC sequence char c= rest.Consume(); // Colors bool isForeGround= true; if( c == 'C' || c == 'c' ) { isForeGround= c== 'c'; c= rest.Consume(); int colNo= c - '0'; ALIB.ASSERT_WARNING( colNo >=0 && colNo <=9, "Unknown ESC-c code" ); // add bg colNo+= isForeGround ? 0 : 10; // add light colNo+= (isForeGround ? !IsBackgroundLight : IsBackgroundLight ) ? 20 : 0; textWriter.Write( ansiCols[ colNo ] ); } // Styles else if ( c == 's' ) { // bold/italics style not supported in Windows console // reset all if ( rest.Consume() == 'a' ) { textWriter.Write( ANSI_RESET ); } } // auto tab / end of meta else if ( c == 't' || c == 'A') { bool endOfMeta= c == 'A'; c= rest.Consume(); int extraSpace= c >= '0' && c <= '9' ? (int) ( c - '0' ) : (int) ( c - 'A' ) + 10; int tabStop= AutoSizes.Next( column, extraSpace ); Util.WriteSpaces( textWriter, tabStop - column ); column= tabStop; if ( endOfMeta ) { String msgPrefix; switch ( verbosity ) { case lox.Verbosity.Verbose: msgPrefix= MsgPrefixVerbose; break; case lox.Verbosity.Info: msgPrefix= MsgPrefixInfo; break; case lox.Verbosity.Warning: msgPrefix= MsgPrefixWarning; break; case lox.Verbosity.Error: msgPrefix= MsgPrefixError; break; default: msgPrefix= ""; break; } textWriter.Write( msgPrefix ); } } // Link (we just colorize links here) else if ( c == 'l' ) { textWriter.Write( rest.Consume() == 'S' ? ( IsBackgroundLight ? ANSI_LIGHT_BLUE : ANSI_LIGHT_BLUE ) : ANSI_STD_COL ); } else { ALIB.WARNING( "Unknown ESC code" ); } } // write loop textWriter.WriteLine( MsgSuffix ); }
/** **************************************************************************************** * Adds a value to the end of the list of values. * @return A reference to the string which can be manipulated to set the value. ******************************************************************************************/ public AString AddString() { int actIdx= qtyValues; qtyValues++; if( actIdx < values.Count ) return values[actIdx].Clear(); AString newVal= new AString(); values.Add( newVal ); return newVal; }