写点什么

通过解析库探究函数式抽象代价 ( ini 解析示例补充)

作者:八苦-瞿昙
  • 2024-02-28
    美国
  • 本文字数:3498 字

    阅读完需:约 11 分钟

上一篇 用 HexColor 作为示例,可能过于简单


这里再补充一个 ini 解析的示例


由于实在写不动用其他库解析 ini 了, 春节都要过完了,累了,写不动了,


所以随意找了一份解析 ini 的库, 仅供参考,对比不准确,毕竟完整库包含了更多功能

先看看结果


BenchmarkDotNet v0.13.12, Windows 11 (10.0.22631.3085/23H2/2023Update/SunValley3)Intel Core i7-9750H CPU 2.60GHz, 1 CPU, 12 logical and 6 physical cores.NET SDK 8.0.200 [Host] : .NET 8.0.2 (8.0.224.6711), X64 RyuJIT AVX2 DefaultJob : .NET 8.0.2 (8.0.224.6711), X64 RyuJIT AVX2

复制代码



// * Legends *  Mean      : Arithmetic mean of all measurements  Error     : Half of 99.9% confidence interval  StdDev    : Standard deviation of all measurements  Gen0      : GC Generation 0 collects per 1000 operations  Gen1      : GC Generation 1 collects per 1000 operations  Allocated : Allocated memory per single operation (managed only, inclusive, 1KB = 1024B)  1 ns      : 1 Nanosecond (0.000000001 sec)
复制代码

先看来自 dotnet Microsoft.Extensions.Configuration 中解析 ini 的代码

public static IDictionary<string, string?> Read(string content){    var data = new Dictionary<string, string?>(StringComparer.OrdinalIgnoreCase);    using (var reader = new StringReader(content))    {        string sectionPrefix = string.Empty;
while (reader.Peek() != -1) { string rawLine = reader.ReadLine()!; // Since Peak didn't return -1, stream hasn't ended. string line = rawLine.Trim();
// Ignore blank lines if (string.IsNullOrWhiteSpace(line)) { continue; } // Ignore comments if (line[0] is ';' or '#' or '/') { continue; } // [Section:header] if (line[0] == '[' && line[line.Length - 1] == ']') { // remove the brackets sectionPrefix = string.Concat(line.AsSpan(1, line.Length - 2).Trim(), ConfigurationPath.KeyDelimiter); continue; }
// key = value OR "value" int separator = line.IndexOf('='); if (separator < 0) { throw new FormatException(rawLine); }
string key = sectionPrefix + line.Substring(0, separator).Trim(); string value = line.Substring(separator + 1).Trim();
// Remove quotes if (value.Length > 1 && value[0] == '"' && value[value.Length - 1] == '"') { value = value.Substring(1, value.Length - 2); }
if (data.ContainsKey(key)) { throw new FormatException(key); }
data[key] = value; } } return data;}
复制代码

再来看看部分函数语义优化的代码

public class Ini{    private static Ini instance = new Ini();
public Func<IPeeker<char>, bool> WhiteSpace = Chars.IngoreWhiteSpace.Map(i => i > 0);
public Func<IPeeker<char>, bool> Comment = Chars.In(";#/").Delimited(Chars.NotCRLF.ToSlice().Opt(), Chars.IsCRLF, "Comment not right").Map((c, x, y, z) => c);
public Func<IPeeker<char>, string> SectionName = Chars.Is('[').Delimited(Chars.Not(']').ToSlice().Once("Section name is required."), Chars.Is(']'), "Section name must end with ']'").Map((c, x, y, z) => y?.ToString());
public Func<IPeeker<char>, string> Key = Chars.Not('=').ToSlice().Once("key is required.").Map(i => i.ToString()); public Func<IPeeker<char>, char> Separater = Chars.Is('=').Once("Section name is required.");
public Func<IPeeker<char>, string> Value = Chars.NotCRLF.ToSlice().Once("value is required.").Map(i => { var v = i.ToString().Trim(); return v.StartsWith('"') ? v[1..^1] : v; });
public IDictionary<string, string> ParseString(string content) { var input = Input.From(content); var dict = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase); while (input.TryPeek(out var v)) { if (!(WhiteSpace(input) || Comment(input) || Section(input, dict))) { throw new NotSupportedException(v.ToString()); } } return dict; }
public bool SectionContentEnd(IPeeker<char> input) { return !input.TryPeek(out var v) || v is '['; }
public bool Section(StringPeeker input, Dictionary<string, string> dict) { var name = SectionName(input); if (name == null) return false; while (!SectionContentEnd(input)) { if (WhiteSpace(input) || Comment(input)) { continue; } SectionKV(input, dict, name); } return true; }
public void SectionKV(StringPeeker input, Dictionary<string, string> dict, string name) { var k = Key(input); Separater(input); var v = Value(input); k = $"{name}:{k.Trim()}"; dict.Add(k, v.Trim()); }
public static IDictionary<string, string> Parse(string content) { return instance.ParseString(content); }}
复制代码

最后截取 部分 ini 解析库的代码 仅供参考

public IniData Parse(string iniDataString){    IniData iniData = (Configuration.CaseInsensitive ? new IniDataCaseInsensitive() : new IniData());    iniData.Configuration = Configuration.Clone();    if (string.IsNullOrEmpty(iniDataString))    {        return iniData;    }
_errorExceptions.Clear(); _currentCommentListTemp.Clear(); _currentSectionNameTemp = null; try { string[] array = iniDataString.Split(new string[2] { "\n", "\r\n" }, StringSplitOptions.None); for (int i = 0; i < array.Length; i++) { string text = array[i]; if (text.Trim() == string.Empty) { continue; }
try { ProcessLine(text, iniData); } catch (Exception ex) { ParsingException ex2 = new ParsingException(ex.Message, i + 1, text, ex); if (Configuration.ThrowExceptionsOnError) { throw ex2; }
_errorExceptions.Add(ex2); } }
if (_currentCommentListTemp.Count > 0) { if (iniData.Sections.Count > 0) { iniData.Sections.GetSectionData(_currentSectionNameTemp).TrailingComments.AddRange(_currentCommentListTemp); } else if (iniData.Global.Count > 0) { iniData.Global.GetLast().Comments.AddRange(_currentCommentListTemp); }
_currentCommentListTemp.Clear(); } } catch (Exception item) { _errorExceptions.Add(item); if (Configuration.ThrowExceptionsOnError) { throw; } }
if (HasError) { return null; }
return (IniData)iniData.Clone();}
复制代码


发布于: 4 小时前阅读数: 6
用户头像

八苦-瞿昙

关注

一个假和尚,不懂人情世故。 2018-11-23 加入

会点点技术,能写些代码,只爱静静。 g hub: https://github.com/fs7744 黑历史:https://www.cnblogs.com/fs7744

评论

发布
暂无评论
通过解析库探究函数式抽象代价 ( ini 解析示例补充)_C#_八苦-瞿昙_InfoQ写作社区