Releases: axuno/SmartFormat
v3.5.1
v3.5.0
What's Changed
Feature: Add interface IFormattingExtensionsToggle to skip formatting (#436)
- Added the
IFormattingExtensionsToggle
interface to allow skipping formatting byIFormatter
extensions. - This interface is primarily used by
ISource
extensions that receive it with theISelectorInfo
parameter. - By setting
IFormattingExtensionsToggle.DisableFormattingExtensions
totrue
, formatting can be skipped. This can be useful when theISource
found a value inISource.TryEvaluateSelector
where default formatting cannot reasonably be done.
Security: Update of System.Text.Json (#435)
- Bumped
System.Text.Json
to v8.0.4 - Fixed a vulnerability in .NET when calling the JsonSerializer.DeserializeAsyncEnumerable method against an untrusted input using System.Text.Json, which could result in Denial of Service.
Feature: Implement ISpanFormattable for DefaultFormatter (#434)
- Implemented
ISpanFormattable
forDefaultFormatter
ISpanFormattable
is 5% faster than IFormattable, with 24% less allocations// Performance test case Smart.FormatInto(output, null, _placeholder0005Format, 1234567.890123f, 1234567.890123f, 1234567.890123f, 1234567.890123f, 1234567.890123f);
BenchmarkDotNet v0.13.12, Windows 11 (10.0.22631.3737/23H2/2023Update/SunValley3) 13th Gen Intel Core i7-13700K, 1 CPU, 24 logical and 16 physical cores .NET SDK 8.0.302 [Host] : .NET 8.0.6 (8.0.624.26715), X64 RyuJIT AVX2 .NET 8.0 : .NET 8.0.6 (8.0.624.26715), X64 RyuJIT AVX2 Job=.NET 8.0 Runtime=.NET 8.0 | Method | N | Mean | Error | StdDev | Ratio | RatioSD | Gen0 | Allocated | Alloc Ratio | |------------------------- |------ |--------------:|------------:|------------:|------:|--------:|-----------:|-------------:|------------:| | ISpanFormattable | 100 | 74.502 us | 0.3693 us | 0.3273 us | 8.52 | 0.05 | 4.0283 | 62.5 KB | 2.76 | | IFormattable | 100 | 77.927 us | 0.5760 us | 0.5388 us | 8.91 | 0.07 | 5.2490 | 82.0 KB | 3.62 |
Feature: ReflectionSource (#426)
- Made
ReflectionSource.TypeCache
static
for better performance. - If the
static
cache has undesired effects on your code logic, consider to disable the cache (ReflectionSource.IsTypeCacheEnabled = false
). - Implemented a mechanism to control the size of
ReflectionSource.TypeCache
and remove the oldest item first.
Enhancement: DictionarySource (#426)
- Dynamics in
DictionarySource
now use case-sensitivity setting - Cache for
IReadOnlyDictionary
now has instance scope
Refactor: Split off classes Registry and Evaluator from SmartFormatter (#424)
SmartFormatter
- Separated members for handling
ISource
andIFormatter
extensions into internal classRegistry
- Separated members for evaluating formats into internal class
Evaluator
- Existing members of
SmartFormatter
remain unchanged and are not yet marked as obsolete
ZCharArray
- Added a lightweight, thread-safe container that rents a buffer from an
ArrayPool<char>
and returns it when disposed - Simplifies passing around the buffer without intermediate memory allocations
ZCharArray
contains most frequently used methods for writing data into the underlying buffer- Used in
FormattingInfo
methods (see below) for low memory allocation
FormattingInfo
Added methods useful in custom IFormatter
s:
- public ZCharArray FormattingInfo.FormatAsSpan(IFormatProvider, Format, object?): Works like SmartFormatter.Format(...) for the specified Format
- public ZCharArray FormattingInfo.FormatAsSpan(IFormatProvider, Placeholder, object?): Gets the value for the
Placeholder
and applies itsFormat
- public bool TryGetValue(Placeholder, out object?): Tries to get the value for a
Placeholder
Evaluator
- Internal class that supplies the methods for evaluating
Placeholder
andFormat
objects - Contains the methods that
FormattingInfo
uses to evaluatePlaceholder
andFormat
objects - Has other methods formerly included in
SmartFormatter
that are now moved toEvaluator
- Includes a partial class for handling events in all steps of the evaluation process
Registry
- Internal class that contains all methods for handling
ISource
andIFormatter
extensions that have been moved fromSmartFormatter
Feature: Format.HasNested checks for existing Placeholder in Items (#416)
- Added
Format.HasNested
property that checks Items for existing Placeholder
Test: Add unit test for nested scope (#404)
- Added unit test for nested scope
Enhancement: Ensure Format instances get returned to object pool (#402)
- Ensured that Format instances get returned to object pool
Refactor: Internal SmartFormat.Pooling
classes (#401)
- Simplified pooling classes and made methods and names more consistent
Chore: Remove unused performance test projects (#398)
- Removed unused performance test projects
Fix: Returning a StringBuilder exceeding default capacity to StringBuilderPool (#397)
- Fixed an issue where returning a
StringBuilder
exceeding the default capacity toStringBuilderPool
would throw an exception.
Refactor: Remove code duplications in SmartFormatter (#396)
- Removed code duplications in SmartFormatter
- Unified preprocessor directives
Chore: Remove redundant DependsOnTargets from SmartFormat.csproj (#394)
- Removed redundant DependsOnTargets from SmartFormat.csproj
Full Changelog: v3.4.0...v3.5.0
v3.4.0
What's Changed
.NET Framework 4.6.2
SmartFormat has transitioned to using .NET Framework 4.6.2 (net462)
as its target framework, replacing the now unsupported .NET Framework 4.6.1 (net461)
. The support for net461
ended in 2022, while net462
will continue to receive support until January 2027.
Switching to a different patch version of a target framework is generally not considered a breaking change. This is referred to as an in-place update by Microsoft. In the case of SmartFormat, we have not encountered any runtime issues with the existing API after this transition.
The same holds true for the new netstandard2.0
reference to ZString.
.NET 6.0 and .NET 8.0
SmartFormat has expanded its compatibility by adding .NET 6.0 (net60)
and .NET 8.0 (net80)
as additional target frameworks. You can find details about their end of support here.
All Target Frameworks
We have removed the SmartFormat.ZString
assembly and replaced it with a reference to the ZString package. This change does not affect the API.
Commits in detail
- Fix: Update nuget api key in #378
- Target Framework Updates in #389 (merged the version/3.4.0 branch)
Thanks to @thompson-tomo for his first contribution with #377
Full Changelog: v3.3.2...v3.4.0
v3.3.2
Reasoning for the Update
- Regression caused by #368
- If there are namespace collisions with Cysharp.Text using v3.3.1 please update to v3.2.2
What's Changed
- Change all public types in namespace Cysharp.Text to internal in #372
- Stop namespace collisions with Cysharp.ZString nuget package
- Affects: class, struct, interface, delegate, enum
- using https://github.com/zzzprojects/findandreplace on command line, so we can automate this step:
"fnr.exe" --cl --dir "SmartFormat.ZString\repo\src\ZString" --fileMask ".cs,.tt" --includeSubDirectories --caseSensitive --useRegEx --find "public (?=.*(class |struct |enum |interface |delegate ))" --replace "internal " - Add a unit test to get an alert when Cysharp.Text objects are public (e.g. after an update)
- Bump version to v3.3.2
Full Changelog: v3.3.1...v3.3.2
v3.3.1
Fix
PluralRule for DualFromZeroToTwo: Now a value of 2 is covered and will not throw. Frend is one of the affected languages. Closes #369 in #370
Enhancement
Dictionary<string, PluralRuleDelegate> PluralRule.IsoLangToDelegate
holds delegate
s with the pluralization rule per language. Changing a value of this dictionary will change the pluralization rules globally. This is not recommended, but possible. After a change calling PluralRules.RestoreDefault()
will restore the default rules.
Other Changes
- Unit tests: Convert NUnit Classic Assert to Constraint Model in #364
- Bump NUnit package reference to v4.0.1 in #367
- Linq optimizations in #366
- Update package Cysharp.ZString to v2.5.1 in #368
- Bump version to v3.3.1 in #371
Full Changelog: v3.3.0...v3.3.1
v3.3.0
What's Changed
- Add support for nested formats in
LocalizationFormatter
by @zacateras in #350. This is useful, if the string to localize contains a SmartFormat placeholder instead of a pure text. Example: If the format is"{:L:{ProductType}}"
, theProductType
placeholder will be replaced with the variable content "pen". "pen" will in turn be localiced to "bic" for theFR
locale. DictionarySource
has an option to evaluateIReadOnlyDictionary<TKey,TValue>
sources by @axunonb in #353. To enable, setDictionarySource.IsIReadOnlyDictionarySupported
totrue
(default isfalse
). This is for types that only implementIReadOnlyDictionary<TKey,TValue>
, but notIDictionary
.- Bump version to v3.3.0 in #356
New Contributors
- Thanks to @zacateras for the first contribution in #350
Full Changelog: v3.2.2...v3.3.0
v3.2.2
What's Changed
Fix
-
PluralLocalizationFormatter
does not treat a numeric string as valid argument (resolves #345, restore behavior of v3.1.0 and before) in #346 -
Bump version to v3.2.2
Meaning:
Smart.Format("{0:{}|is null or empty}", "1234");
will not implicitly invokePluralLocalizationFormatter
but insteadConditionalFormatter
. So the result is "1234" as to be expected. A string argument toPluralLocalizationFormatter
is never accepted, even if it could be converted to a number.
Chore
- Update appveyor and github CI scripts
- Update change log for v3.2.1 in #331
- Update NuGet API Key in #335
- Update link to pluralization rules we use as a reference in #338
- Add unit test for DateOnly and TimeOnly types (NET6.0+) in #341
Full Changelog: v3.2.1...v3.2.2
v3.2.1
What's Changed
PluralLocalizationFormatter
-
Fix: Auto-detection of PluralLocalizationFormatter does not throw for values not convertible to decimal by @axunonb in #330 Resolves #329 (Thanks to @BtbN)
-
Current behavior, introduced in v3.2.0:
WhenPluralLocalizationFormatter.CanAutoDetect == true
, values that are not convertible todecimal
will throw then trying toIConvertible.ToDecimal(...)
-
New behavior, equivalent to v3.1.0:
WhenPluralLocalizationFormatter.CanAutoDetect == true
, for values that are not convertible todecimal
,IFormatter.TryEvaluateFormat(...)
will returnfalse
-
Other Changes
- EditorConfig and appveyor.yml by @axunonb in #319
- Integrate Cysharp.ZString release v2.5.0 (26 Oct 2022) by @axunonb in #323
- Fix: PluralRules for Czech locale by @alexheb in #325
- Fixes for Demo App and NUnit TestAdapter by @axunonb in #328
New Contributors
Full Changelog: v3.2.0...v3.2.1
v3.2.0
Enhancements
- Remove usage of Linq for less GC
- Add
IConvertable
support forPluralLocalizationFormatter
andConditionalFormatter
ListFormatter
- ListFormatter handles selector name "Index" in
IEnumerable
s andIList
s: Inv1.6.1
a Selector was tested for having the name "index", even if data was not anIList
, and returned theCollectionIndex
. This is now implemented again in theListFormatter.TryEvaluateSelector(...)
- Set the
ParentPlaceholder
property for itemFormat
s - Use
PooledObject<T>
where possible, so objects will be returned toObjectPool
also in case of exceptions
- ListFormatter handles selector name "Index" in
Fixes
FormatItem.AsSpan()
returns the correct name- Remove potential namespace collisions: All public types in namespace
Cysharp.Text
are now internal
What's Changed
- Upgrade projects targeting NET5.0 to NET6.0 by @axunonb in #286
- Refactor suggestions by @karljj1 in #290
- Refactored unit tests for ReflectionSource and thread-safe mode by @axunonb in #291
- Convert solution to file-scoped namespacing by @axunonb in #292
- Use
is
instead of checking the type info. by @karljj1 in #293 - SonarCloud do not support analysis of forked PRs by @axunonb in #294
- Avoid using Linq as it generates GC each time. by @karljj1 in #296
- IConvertible support for plural and conditional formatters by @karljj1 in #300
- Fixed: FormatItem.AsSpan() by @axunonb in #304
- Refactor ListFormatter by @axunonb in #305
- Ignore bools in plurals formatter. by @karljj1 in #306
- Change all public types in namespace Cysharp.Text to internal by @axunonb in #309
- ListFormatter handles selector name "Index" in IEnumerable and IList by @axunonb in #314
- Bump version to v3.2.0 by @axunonb in #315
Full Changelog: v3.1.0...v3.2.0
v2.7.3
Fix: Newtonsoft.Json prior to version 13.0.1 is vulnerable
Newtonsoft.Json prior to version 13.0.1 is vulnerable to Insecure Defaults due to improper handling of expressions with high nesting level that lead to StackOverFlow exception or high CPU and RAM usage. Exploiting this vulnerability results in Denial Of Service (DoS).
Package reference updated to a minimum version 13.0.1