Skip to content

Instantly share code, notes, and snippets.

@VBAndCs
Last active January 31, 2022 01:12
Show Gist options
  • Save VBAndCs/4c4dfd6025ce5fb5e4c7b4d0d9eeb37b to your computer and use it in GitHub Desktop.
Save VBAndCs/4c4dfd6025ce5fb5e4c7b4d0d9eeb37b to your computer and use it in GitHub Desktop.
Safe/Managed Interpolated Parseing
using System.Runtime.CompilerServices;

string input = "My Name: Andrew Smith  ; Age: 31 years; City: London.";

Placeholder<string> name = new();
Placeholder<int> age = new();
Placeholder<string> city = new();

input.TryParse($"Name: {name} Age: {age} City: {city}");
Console.WriteLine($"{name}, {age}, {city}");


public static class ParsingExtensions
{
    public static bool TryParse(this string input, [InterpolatedStringHandlerArgument("input")] TryParseHandler handler)
    {
        return handler.Result;
    }
}

public class Placeholder<T>
{
    T value;

    public T Value
    {
        get => value;
        set
        {
            Found = true;
            this.value = value;
        }
    }

    public bool Found = false;

    public override string ToString()
    {
        if (Found)
            return value?.ToString();

        return "Not Found";
    }
}



[InterpolatedStringHandler]
public class TryParseHandler
{
    string input;
    int strLength;
    int index = 0;

    public bool Result = true;

    public TryParseHandler(int literalLength, int formattedCount, string input)
    {
        this.input = input;
        strLength = input.Length;
    }

    private bool Failed()
    {
        Result = false;
        return false;
    }

    public bool AppendLiteral(string literal)
    {
        literal= literal.Trim();
        var i = input.IndexOf(literal, index);
        if (i < 0)
            return Failed();

        index = i + literal.Length;
        return true;
    }

    public bool AppendFormatted(Placeholder<string> placeholder)
    {
        if (index >= strLength)
            placeholder.Value = "";
        else
        {
            int start = index;
            while (index < strLength && (char.IsLetterOrDigit(input[index]) || input[index] == '_' || input[index] == ' '))
                index++;

            placeholder.Value = input.Substring(start, index - start).Trim();
        }

        return true;
    }

    public bool AppendFormatted(Placeholder<int> placeholder)
    {
        int start = index;
        while (start < strLength && input[start] == ' ')
            start++;

        if (start >= strLength)
            return Failed();

        index = start + 1;
        while (index < strLength && char.IsDigit(input[index]))
            index++;

        if (index - start == 0)
            return Failed();

        placeholder.Value = Convert.ToInt32(input.Substring(start, index - start));
        return true;
    }

}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment