Nemesis.TextParsers
0.11.41
See the version list below for details.
dotnet add package Nemesis.TextParsers --version 0.11.41
NuGet\Install-Package Nemesis.TextParsers -Version 0.11.41
<PackageReference Include="Nemesis.TextParsers" Version="0.11.41" />
<PackageVersion Include="Nemesis.TextParsers" Version="0.11.41" />
<PackageReference Include="Nemesis.TextParsers" />
paket add Nemesis.TextParsers --version 0.11.41
#r "nuget: Nemesis.TextParsers, 0.11.41"
#:package Nemesis.TextParsers@0.11.41
#addin nuget:?package=Nemesis.TextParsers&version=0.11.41
#tool nuget:?package=Nemesis.TextParsers&version=0.11.41
Nemesis.TextParsers
When stucked with a task of parsing various items form strings we ofter opt for TypeConverter (https://docs.microsoft.com/en-us/dotnet/api/system.componentmodel.typeconverter) ?
We tend to create methods like:
public static T FromString<T>(string text) =>
(T)TypeDescriptor.GetConverter(typeof(T))
.ConvertFromInvariantString(text);
or even create similar constructs to be in line with object oriented design:
public abstract class TextTypeConverter : TypeConverter
{
public sealed override bool CanConvertFrom(ITypeDescriptorContextcontext, Type sourceType) =>
sourceType == typeof(string) || base.CanConvertFrom(context, ourceType);
public sealed override bool CanConvertTo(ITypeDescriptorContext ontext, Type destinationType) =>
destinationType == typeof(string) || base.CanConvertTocontext, destinationType);
}
public abstract class BaseTextConverter<TValue> : TextTypeConverter
{
public sealed override object ConvertFrom(ITypeDescriptorContext ontext, CultureInfo culture, object value) =>
value is string text ? ParseString(text) : default;
public abstract TValue ParseString(string text);
public sealed override object ConvertTo(ITypeDescriptorContext ontext, CultureInfo culture, object value, Type estinationType) =>
destinationType == typeof(string) ?
FormatToString((TValue)value) :
base.ConvertTo(context, culture, value, destinationType);
public abstract string FormatToString(TValue value);
}
What is wrong with that? Well, nothing... except of performance.
TypeConverter was designed 15+ years ago when processing power tended to double every now and then and (in my opinion) it was more suited for creating GUI-like editors where performance usually is not an issue. But imagine a service application like exchange trading suite that has to perform multiple operations per second and in such cases processor has more important thing to do than parsing strings.
Parser/formatter features
- as concise as possible - both JSON or XML exist but thay are not ready to be created from hand by human support
- works in various architectures supporting .Net Core and .Net Standard and is culture independent
- support for basic system types (C#-like type names):
- string
- bool
- byte/sbyte
- short/ushort
- int/uint
- long/ulong
- float/double
- decimal
- BigInteger
- TimeSpan
- DateTime/DateTimeOffset
- Guid
- supports pattern based parsing/formatting via ToString/FromText methods placed inside type or static/instance factory
- supports compound types:
- KeyValuePair<,> and ValueTuple of arity 2-5 (1 is not a tuple, more than 5 warrants a dedicated type)
- Enums (with number underlying types)
- Nullables
- Dictionaries (built-in i.e. SortedDictionary/SortedList and custom ones)
- Arrays (including jagged arrays)
- Standard collections and collection contracts (List vs IList vs IEnumerable)
- User defined collections
- everything mentioned above but combined with inner elements properly escaped in final string i.e. SortedDictionary<char?, IList<float[][]>>
- ability to fallback to TypeConverter if no parsing/formatting strategy was found
- parsing is fast to while allocating as little memory as possible upon parsing. The follwing benchmark illustrates this speed via parsing 1000 element array
| Method | Mean | Ratio | Gen 0 | Gen 1 | Allocated | Remarks |
|---|---|---|---|---|---|---|
| RegEx parsing | 4,528.99 us | 44.98 | 492.1875 | - | 2089896 B | Regular expression with escaping support |
| StringSplitTest_KnownType | 93.41 us | 0.92 | 9.5215 | 0.1221 | 40032 B | string.Split(..).Select(text=>int.Parse(text)) |
| StringSplitTest_DynamicType | 474.73 us | 4.69 | 24.4141 | - | 104032 B | string.Split + TypeDescriptor.GetConverter |
| SpanSplitTest_NoAlloc | 101.00 us | 1.00 | - | - | - | "1|2|3".AsSpan().Tokenize() |
| SpanSplitTest_Alloc | 101.38 us | 1.00 | 0.8545 | - | 4024 B | "1|2|3".AsSpan().Tokenize(); var array = new int[1000]; |
- provides basic building blocks for parser's callers to be able to create their own transformers/factories
- LeanCollection that can store 1,2,3 or more elements
- string.Split equivalent is provided to accept faster representaion of string - ReadOnlySpan<char>. Supports both standard and custom escaping sequences
- access to every implemented parser/formatter
- basic LINQ support
var avg = SpanCollectionSerializer.DefaultInstance.ParseStream<double>("1|2|3".AsSpan()).Average();
- basic support for GUI editors for compound types like collections/dictionaries
- lean/frugal implementation of StringBuilder - ValueSequenceBuilder
Span<char> initialBuffer = stackalloc char[32];
var accumulator = new ValueSequenceBuilder<char>initialBuffer);
using (var enumerator = coll.GetEnumerator())
while (enumerator.MoveNext())
FormatElement(formatter, enumerator.Current, ref ccumulator);
var text = accumulator.AsSpanTo(accumulator.Length > 0 ? ccumulator.Length - 1 : 0).ToString();
accumulator.Dispose();
Continuous Integration
| Branch | Status |
|---|---|
| master build | |
| Tests | |
| Code size | |
| Issues | |
| GitHub stars | |
| GitHub commit activity |
Nuget package
Todo / road map
- context based transformer creation with settings for:
- DictionaryBehaviour
- Enum casing+other customizations
- empty string meaing (empty, default, null?))
- custom TextParser factory/customizations
- ability to format to buffer
- become DI friendly adding support for cross cutting concerns i.e. logging
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net5.0 was computed. net5.0-windows was computed. net6.0 was computed. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 was computed. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
| .NET Core | netcoreapp2.0 was computed. netcoreapp2.1 was computed. netcoreapp2.2 is compatible. netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
| .NET Standard | netstandard2.0 is compatible. netstandard2.1 was computed. |
| .NET Framework | net461 was computed. net462 was computed. net463 was computed. net47 was computed. net471 was computed. net472 was computed. net48 was computed. net481 was computed. |
| MonoAndroid | monoandroid was computed. |
| MonoMac | monomac was computed. |
| MonoTouch | monotouch was computed. |
| Tizen | tizen40 was computed. tizen60 was computed. |
| Xamarin.iOS | xamarinios was computed. |
| Xamarin.Mac | xamarinmac was computed. |
| Xamarin.TVOS | xamarintvos was computed. |
| Xamarin.WatchOS | xamarinwatchos was computed. |
-
.NETCoreApp 2.2
- Nemesis.Essentials.TypeMeta.Sources (>= 1.0.17)
- System.Runtime.CompilerServices.Unsafe (>= 4.5.2)
-
.NETStandard 2.0
- Nemesis.Essentials.TypeMeta.Sources (>= 1.0.17)
- System.Memory (>= 4.5.3)
- System.Runtime.CompilerServices.Unsafe (>= 4.5.2)
- System.ValueTuple (>= 4.5.0)
NuGet packages (1)
Showing the top 1 NuGet packages that depend on Nemesis.TextParsers:
| Package | Downloads |
|---|---|
|
Nemesis.TextParsers.DependencyInjection
Contains helper methods useful to setup DependencyInjection using Microsoft.Extensions.DependencyInjection This package was built from the source at https://github.com/nemesissoft/Nemesis.TextParsers/tree/b6854dd729d170756762cad27fc9acfa79115931 |
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 2.10.0 | 275 | 1/9/2025 |
| 2.9.15 | 333 | 8/9/2024 |
| 2.9.6 | 250 | 8/8/2024 |
| 2.9.2 | 320 | 1/3/2024 |
| 2.9.1 | 198 | 1/1/2024 |
| 2.8.2 | 235 | 12/19/2023 |
| 2.7.2 | 505 | 7/16/2023 |
| 2.7.1 | 255 | 7/14/2023 |
| 2.7.0 | 241 | 7/14/2023 |
| 2.6.3 | 632 | 5/30/2022 |
| 2.6.2 | 586 | 3/1/2021 |
| 2.6.1 | 527 | 2/25/2021 |
| 2.6.0 | 521 | 2/25/2021 |
| 2.5.0 | 544 | 12/31/2020 |
| 2.4.0 | 591 | 11/30/2020 |
| 2.3.0 | 591 | 11/16/2020 |
| 2.2.1 | 680 | 5/15/2020 |
| 2.2.0 | 608 | 5/14/2020 |
| 2.1.2 | 619 | 5/12/2020 |
| 2.1.1 | 673 | 5/1/2020 |
| 2.1.0 | 628 | 4/28/2020 |
| 2.0.4 | 646 | 4/26/2020 |
| 2.0.2 | 659 | 4/21/2020 |
| 2.0.1 | 667 | 4/17/2020 |
| 2.0.0-alpha | 526 | 4/15/2020 |
| 1.5.1 | 641 | 3/29/2020 |
| 1.5.0 | 675 | 3/28/2020 |
| 1.4.1 | 694 | 3/23/2020 |
| 1.3.2 | 661 | 3/19/2020 |
| 1.3.0 | 665 | 3/16/2020 |
| 1.2.0 | 719 | 3/15/2020 |
| 1.1.3 | 744 | 3/14/2020 |
| 1.1.2 | 717 | 2/27/2020 |
| 1.1.1 | 639 | 2/26/2020 |
| 1.1.0 | 723 | 2/26/2020 |
| 1.0.6 | 731 | 2/25/2020 |
| 1.0.4 | 615 | 2/25/2020 |
| 1.0.3 | 739 | 2/18/2020 |
| 1.0.2 | 728 | 11/8/2019 |
| 1.0.1 | 680 | 11/6/2019 |
| 1.0.0 | 673 | 9/25/2019 |
| 0.11.50 | 685 | 9/25/2019 |
| 0.11.47 | 679 | 9/25/2019 |
| 0.11.46 | 675 | 9/23/2019 |
| 0.11.42 | 735 | 9/18/2019 |
| 0.11.41 | 697 | 9/18/2019 |
| 0.11.40 | 678 | 9/18/2019 |
| 0.11.39 | 752 | 9/18/2019 |
| 0.11.38 | 708 | 9/18/2019 |
| 0.11.37 | 690 | 9/18/2019 |
| 0.11.36 | 707 | 9/17/2019 |
| 0.11.35 | 712 | 9/17/2019 |
| 0.11.34 | 715 | 9/17/2019 |
| 0.11.33 | 711 | 9/17/2019 |
| 0.9.32 | 718 | 9/17/2019 |
| 0.9.31 | 702 | 9/11/2019 |
| 0.9.30 | 709 | 9/9/2019 |
| 0.9.29 | 671 | 9/6/2019 |
| 0.9.28 | 709 | 8/3/2019 |
| 0.9.27 | 733 | 8/3/2019 |
| 0.9.26 | 690 | 8/1/2019 |
| 0.9.25 | 736 | 7/21/2019 |
| 0.9.24 | 705 | 7/19/2019 |
| 0.9.22 | 735 | 6/14/2019 |
| 0.9.21 | 684 | 6/13/2019 |
| 0.9.20 | 753 | 6/9/2019 |
| 0.9.19 | 785 | 6/7/2019 |
| 0.9.18 | 742 | 6/5/2019 |
| 0.9.15 | 711 | 5/29/2019 |
| 0.9.14 | 762 | 5/29/2019 |
| 0.9.13 | 740 | 5/28/2019 |
| 0.9.12 | 754 | 5/27/2019 |
| 0.9.10 | 754 | 5/21/2019 |
| 0.9.8 | 747 | 5/7/2019 |
| 0.9.7 | 772 | 5/5/2019 |
| 0.9.6 | 736 | 5/5/2019 |
| 0.9.5 | 734 | 5/5/2019 |
| 0.0.0-alpha.0.335 | 108 | 1/1/2024 |