1
- //
1
+ //
2
2
// Copyright SmartFormat Project maintainers and contributors.
3
3
// Licensed under the MIT license.
4
4
@@ -255,7 +255,7 @@ public string Format(string format, params object?[] args)
255
255
{
256
256
return Format ( null , format , ( IList < object ? > ) args ) ;
257
257
}
258
-
258
+
259
259
/// <summary>
260
260
/// Replaces one or more format items in as specified string with the string representation of a specific object.
261
261
/// </summary>
@@ -289,20 +289,9 @@ public string Format(IFormatProvider? provider, string format, params object?[]
289
289
public string Format ( IFormatProvider ? provider , string format , IList < object ? > args )
290
290
{
291
291
var formatParsed = Parser . ParseFormat ( format ) ; // The parser gets the Format from the pool
292
-
293
- // Note: Making ZStringOutput a class instance variable has no advantage for speed,
294
- // but brings 10% less Gen 0 GC. Then, SmartFormatter would have to be IDisposable (dispose ZStringOutput)
295
- using var zsOutput = new ZStringOutput ( ZStringBuilderUtilities . CalcCapacity ( formatParsed ) ) ;
296
-
297
- var current = args . Count > 0 ? args [ 0 ] : args ; // The first item is the default.
298
-
299
- var formatDetails = FormatDetailsPool . Instance . Get ( ) . Initialize ( this , formatParsed , args , provider , zsOutput ) ;
300
- Format ( formatDetails , formatParsed , current ) ;
301
-
302
- FormatDetailsPool . Instance . Return ( formatDetails ) ;
303
- FormatPool . Instance . Return ( formatParsed ) ;
304
-
305
- return zsOutput . ToString ( ) ;
292
+ var result = Format ( provider , formatParsed , args ) ;
293
+ FormatPool . Instance . Return ( formatParsed ) ;
294
+ return result ;
306
295
}
307
296
308
297
#region ** Format overloads with cached Format **
@@ -353,15 +342,12 @@ public string Format(IFormatProvider? provider, Format formatParsed, IList<objec
353
342
// Note: Making ZStringOutput a class instance variable has no advantage for speed,
354
343
// but brings 10% less Gen 0 GC. Then, SmartFormatter would have to be IDisposable (to dispose ZStringOutput)
355
344
using var zsOutput = new ZStringOutput ( ZStringBuilderUtilities . CalcCapacity ( formatParsed ) ) ;
356
- var current = args . Count > 0 ? args [ 0 ] : args ; // The first item is the default.
357
- var formatDetails = FormatDetailsPool . Instance . Get ( ) . Initialize ( this , formatParsed , args , provider , zsOutput ) ;
358
- Format ( formatDetails , formatParsed , current ) ;
359
- FormatDetailsPool . Instance . Return ( formatDetails ) ;
345
+ FormatInto ( zsOutput , provider , formatParsed , args ) ;
360
346
return zsOutput . ToString ( ) ;
361
347
}
362
348
363
349
#endregion
364
-
350
+
365
351
/// <summary>
366
352
/// Format the <see cref="FormattingInfo" /> argument.
367
353
/// </summary>
@@ -407,7 +393,7 @@ public void Format(FormattingInfo formattingInfo)
407
393
}
408
394
}
409
395
}
410
-
396
+
411
397
private void Format ( FormatDetails formatDetails , Format format , object ? current )
412
398
{
413
399
var formattingInfo = FormattingInfoPool . Instance . Get ( ) . Initialize ( formatDetails , format , current ) ;
@@ -488,11 +474,11 @@ public void FormatInto(IOutput output, IFormatProvider? provider, Format formatP
488
474
#endregion
489
475
490
476
#endregion
491
-
477
+
492
478
#region: Private methods :
493
479
494
- private void FormatError ( FormatItem errorItem , Exception innerException , int startIndex ,
495
- FormattingInfo formattingInfo )
480
+ internal void FormatError ( FormatItem errorItem , Exception innerException , int startIndex ,
481
+ IFormattingInfo formattingInfo )
496
482
{
497
483
OnFormattingFailure ? . Invoke ( this ,
498
484
new FormattingErrorEventArgs ( errorItem . RawText , startIndex ,
@@ -537,24 +523,26 @@ private void CheckForExtensions()
537
523
/// Example: "{ChildOne.ChildTwo.ChildThree: {Four}}" where "{Four}" is a child placeholder.
538
524
/// </remarks>
539
525
/// <param name="formattingInfo"></param>
526
+ /// <exception cref="FormattingException"></exception>
540
527
private void EvaluateSelectors ( FormattingInfo formattingInfo )
541
528
{
542
529
if ( formattingInfo . Placeholder is null ) return ;
543
-
530
+
544
531
var firstSelector = true ;
545
532
foreach ( var selector in formattingInfo . Placeholder . Selectors )
546
533
{
547
534
// Don't evaluate empty selectors
548
535
// (used e.g. for Settings.Parser.NullableOperator and Settings.Parser.ListIndexEndChar final operators)
549
- if ( selector . Length == 0 ) continue ;
550
-
536
+ if ( selector . Length == 0 ) continue ;
537
+
538
+ // Ensure ISelectorInfo implementation returns the current selector values
551
539
formattingInfo . Selector = selector ;
552
540
// Do not evaluate alignment-only selectors
553
541
if ( formattingInfo . SelectorOperator . Length > 0 &&
554
542
formattingInfo . SelectorOperator [ 0 ] == Settings . Parser . AlignmentOperator ) continue ;
555
-
543
+
556
544
formattingInfo . Result = null ;
557
-
545
+
558
546
var handled = InvokeSourceExtensions ( formattingInfo ) ;
559
547
if ( handled ) formattingInfo . CurrentValue = formattingInfo . Result ;
560
548
@@ -567,6 +555,7 @@ private void EvaluateSelectors(FormattingInfo formattingInfo)
567
555
while ( ! handled && parentFormattingInfo . Parent != null )
568
556
{
569
557
parentFormattingInfo = parentFormattingInfo . Parent ;
558
+ // Ensure ISelectorInfo implementation returns the current selector values
570
559
parentFormattingInfo . Selector = selector ;
571
560
parentFormattingInfo . Result = null ;
572
561
handled = InvokeSourceExtensions ( parentFormattingInfo ) ;
@@ -580,12 +569,12 @@ private void EvaluateSelectors(FormattingInfo formattingInfo)
580
569
}
581
570
}
582
571
583
- private bool InvokeSourceExtensions ( FormattingInfo formattingInfo )
572
+ private bool InvokeSourceExtensions ( ISelectorInfo selectorInfo )
584
573
{
585
574
// less GC than using Linq
586
575
foreach ( var sourceExtension in _sourceExtensions )
587
576
{
588
- var handled = sourceExtension . TryEvaluateSelector ( formattingInfo ) ;
577
+ var handled = sourceExtension . TryEvaluateSelector ( selectorInfo ) ;
589
578
if ( handled ) return true ;
590
579
}
591
580
@@ -623,7 +612,7 @@ private bool InvokeFormatterExtensions(FormattingInfo formattingInfo)
623
612
// Compatibility mode does not support formatter extensions except this one:
624
613
if ( Settings . StringFormatCompatibility )
625
614
{
626
- return
615
+ return
627
616
_formatterExtensions . First ( fe => fe is DefaultFormatter )
628
617
. TryEvaluateFormat ( formattingInfo ) ;
629
618
}
@@ -636,18 +625,18 @@ private bool InvokeFormatterExtensions(FormattingInfo formattingInfo)
636
625
foreach ( var fe in _formatterExtensions )
637
626
{
638
627
if ( ! fe . Name . Equals ( formatterName , comparison ) ) continue ;
639
-
628
+
640
629
formatterExtension = fe ;
641
630
break ;
642
631
}
643
-
632
+
644
633
if ( formatterExtension is null )
645
634
throw formattingInfo . FormattingException ( $ "No formatter with name '{ formatterName } ' found",
646
635
formattingInfo . Format , formattingInfo . Selector ? . SelectorIndex ?? - 1 ) ;
647
636
648
637
return formatterExtension . TryEvaluateFormat ( formattingInfo ) ;
649
638
}
650
-
639
+
651
640
// Go through all (implicit) formatters which contain an empty name
652
641
// much higher performance and less GC than using Linq
653
642
foreach ( var fe in _formatterExtensions )
0 commit comments