From 6feda0e69d3ca43f66792e49ba41ed7493909620 Mon Sep 17 00:00:00 2001 From: Matt Nadareski Date: Wed, 4 Dec 2024 20:22:47 -0500 Subject: [PATCH] Split Input type into typed classes --- CHANGELIST.md | 1 + MPF.ExecutionContexts.Test/InputTests.cs | 483 +++++-------- MPF.ExecutionContexts/Data/BooleanInput.cs | 61 ++ MPF.ExecutionContexts/Data/FlagInput.cs | 47 ++ MPF.ExecutionContexts/Data/Input.cs | 208 ++++++ MPF.ExecutionContexts/Data/Int16Input.cs | 83 +++ MPF.ExecutionContexts/Data/Int32Input.cs | 83 +++ MPF.ExecutionContexts/Data/Int64Input.cs | 83 +++ MPF.ExecutionContexts/Data/Int8Input.cs | 83 +++ MPF.ExecutionContexts/Data/StringInput.cs | 55 ++ MPF.ExecutionContexts/Data/UInt16Input.cs | 83 +++ MPF.ExecutionContexts/Data/UInt32Input.cs | 83 +++ MPF.ExecutionContexts/Data/UInt64Input.cs | 83 +++ MPF.ExecutionContexts/Data/UInt8Input.cs | 83 +++ MPF.ExecutionContexts/Input.cs | 753 --------------------- 15 files changed, 1223 insertions(+), 1049 deletions(-) create mode 100644 MPF.ExecutionContexts/Data/BooleanInput.cs create mode 100644 MPF.ExecutionContexts/Data/FlagInput.cs create mode 100644 MPF.ExecutionContexts/Data/Input.cs create mode 100644 MPF.ExecutionContexts/Data/Int16Input.cs create mode 100644 MPF.ExecutionContexts/Data/Int32Input.cs create mode 100644 MPF.ExecutionContexts/Data/Int64Input.cs create mode 100644 MPF.ExecutionContexts/Data/Int8Input.cs create mode 100644 MPF.ExecutionContexts/Data/StringInput.cs create mode 100644 MPF.ExecutionContexts/Data/UInt16Input.cs create mode 100644 MPF.ExecutionContexts/Data/UInt32Input.cs create mode 100644 MPF.ExecutionContexts/Data/UInt64Input.cs create mode 100644 MPF.ExecutionContexts/Data/UInt8Input.cs delete mode 100644 MPF.ExecutionContexts/Input.cs diff --git a/CHANGELIST.md b/CHANGELIST.md index 0c1d18d3..457bedf7 100644 --- a/CHANGELIST.md +++ b/CHANGELIST.md @@ -25,6 +25,7 @@ - Add tests around ProcessingTool - Add BaseExecutionContext tests - Add currently unused Input type +- Split Input type into typed classes ### 3.2.4 (2024-11-24) diff --git a/MPF.ExecutionContexts.Test/InputTests.cs b/MPF.ExecutionContexts.Test/InputTests.cs index 6838ec1a..cd722e16 100644 --- a/MPF.ExecutionContexts.Test/InputTests.cs +++ b/MPF.ExecutionContexts.Test/InputTests.cs @@ -1,441 +1,332 @@ +using MPF.ExecutionContexts.Data; using Xunit; namespace MPF.ExecutionContexts.Test { public class InputTests { - #region ProcessAsFlag + #region FlagInput [Theory] - // Invalid type - [InlineData(InputType.None, "flag", new string[] { "flag" }, 0, false)] - [InlineData(InputType.Boolean, "flag", new string[] { "flag" }, 0, false)] - [InlineData(InputType.Int8, "flag", new string[] { "flag" }, 0, false)] - [InlineData(InputType.UInt8, "flag", new string[] { "flag" }, 0, false)] - [InlineData(InputType.Int16, "flag", new string[] { "flag" }, 0, false)] - [InlineData(InputType.UInt16, "flag", new string[] { "flag" }, 0, false)] - [InlineData(InputType.Int32, "flag", new string[] { "flag" }, 0, false)] - [InlineData(InputType.UInt32, "flag", new string[] { "flag" }, 0, false)] - [InlineData(InputType.Int64, "flag", new string[] { "flag" }, 0, false)] - [InlineData(InputType.UInt64, "flag", new string[] { "flag" }, 0, false)] - [InlineData(InputType.String, "flag", new string[] { "flag" }, 0, false)] // Invalid parts - [InlineData(InputType.Flag, "flag", new string[0], 0, false)] + [InlineData("flag", new string[0], 0, false, false)] // Invalid index - [InlineData(InputType.Flag, "flag", new string[] { "flag" }, -1, false)] - [InlineData(InputType.Flag, "flag", new string[] { "flag" }, 1, false)] + [InlineData("flag", new string[] { "flag" }, -1, false, false)] + [InlineData("flag", new string[] { "flag" }, 1, false, false)] // Invalid name - [InlineData(InputType.Flag, "flag", new string[] { "" }, 0, false)] - [InlineData(InputType.Flag, "flag", new string[] { "flag2" }, 0, false)] + [InlineData("flag", new string[] { "" }, 0, false, false)] + [InlineData("flag", new string[] { "flag2" }, 0, false, false)] // Valid - [InlineData(InputType.Flag, "flag", new string[] { "flag" }, 0, true)] - public void ProcessAsFlagTest(InputType type, string name, string[] parts, int index, bool expected) + [InlineData("flag", new string[] { "flag" }, 0, true, true)] + public void FlagInputTest(string name, string[] parts, int index, bool success, bool expected) { - Input input = new Input(type, name); - bool actual = input.ProcessAsFlag(parts, ref index); - Assert.Equal(expected, actual); + FlagInput input = new FlagInput(name); + bool actual = input.Process(parts, ref index); + + Assert.Equal(success, actual); + Assert.Equal(expected, input.Value); } #endregion - #region ProcessAsBoolean + #region BooleanInput [Theory] - // Invalid type - [InlineData(InputType.None, "flag", true, new string[] { "flag" }, 0, null)] - [InlineData(InputType.Flag, "flag", true, new string[] { "flag" }, 0, null)] - [InlineData(InputType.Int8, "flag", true, new string[] { "flag" }, 0, null)] - [InlineData(InputType.UInt8, "flag", true, new string[] { "flag" }, 0, null)] - [InlineData(InputType.Int16, "flag", true, new string[] { "flag" }, 0, null)] - [InlineData(InputType.UInt16, "flag", true, new string[] { "flag" }, 0, null)] - [InlineData(InputType.Int32, "flag", true, new string[] { "flag" }, 0, null)] - [InlineData(InputType.UInt32, "flag", true, new string[] { "flag" }, 0, null)] - [InlineData(InputType.Int64, "flag", true, new string[] { "flag" }, 0, null)] - [InlineData(InputType.UInt64, "flag", true, new string[] { "flag" }, 0, null)] - [InlineData(InputType.String, "flag", true, new string[] { "flag" }, 0, null)] // Invalid parts - [InlineData(InputType.Boolean, "flag", true, new string[0], 0, null)] + [InlineData("flag", true, new string[0], 0, false, null)] // Invalid index - [InlineData(InputType.Boolean, "flag", true, new string[] { "flag" }, -1, null)] - [InlineData(InputType.Boolean, "flag", true, new string[] { "flag" }, 1, null)] + [InlineData("flag", true, new string[] { "flag" }, -1, false, null)] + [InlineData("flag", true, new string[] { "flag" }, 1, false, null)] // Invalid name - [InlineData(InputType.Boolean, "flag", true, new string[] { "" }, 0, null)] - [InlineData(InputType.Boolean, "flag", true, new string[] { "flag2" }, 0, null)] + [InlineData("flag", true, new string[] { "" }, 0, false, null)] + [InlineData("flag", true, new string[] { "flag2" }, 0, false, null)] // Valid name, no following - [InlineData(InputType.Boolean, "flag", true, new string[] { "flag" }, 0, null)] - [InlineData(InputType.Boolean, "flag", false, new string[] { "flag" }, 0, true)] + [InlineData("flag", true, new string[] { "flag" }, 0, false, null)] + [InlineData("flag", false, new string[] { "flag" }, 0, true, true)] // Valid name, invalid following - [InlineData(InputType.Boolean, "flag", true, new string[] { "flag", "invalid" }, 0, null)] - [InlineData(InputType.Boolean, "flag", false, new string[] { "flag", "invalid" }, 0, true)] + [InlineData("flag", true, new string[] { "flag", "invalid" }, 0, false, null)] + [InlineData("flag", false, new string[] { "flag", "invalid" }, 0, true, true)] // Valid name, valid following - [InlineData(InputType.Boolean, "flag", true, new string[] { "flag", "true" }, 0, true)] - [InlineData(InputType.Boolean, "flag", true, new string[] { "flag", "false" }, 0, false)] - public void ProcessAsBooleanTest(InputType type, string name, bool required, string[] parts, int index, bool? expected) + [InlineData("flag", true, new string[] { "flag", "true" }, 0, true, true)] + [InlineData("flag", true, new string[] { "flag", "false" }, 0, true, false)] + public void BooleanInputTest(string name, bool required, string[] parts, int index, bool success, bool? expected) { - Input input = new Input(type, name, required); - bool? actual = input.ProcessAsBoolean(parts, ref index); - Assert.Equal(expected, actual); + BooleanInput input = new BooleanInput(name, required); + bool actual = input.Process(parts, ref index); + + Assert.Equal(success, actual); + Assert.Equal(expected, input.Value); } #endregion - #region ProcessAsInt8 + #region Int8Input [Theory] - // Invalid type - [InlineData(InputType.None, "flag", true, new string[] { "flag" }, 0, null)] - [InlineData(InputType.Flag, "flag", true, new string[] { "flag" }, 0, null)] - [InlineData(InputType.Boolean, "flag", true, new string[] { "flag" }, 0, null)] - [InlineData(InputType.UInt8, "flag", true, new string[] { "flag" }, 0, null)] - [InlineData(InputType.Int16, "flag", true, new string[] { "flag" }, 0, null)] - [InlineData(InputType.UInt16, "flag", true, new string[] { "flag" }, 0, null)] - [InlineData(InputType.Int32, "flag", true, new string[] { "flag" }, 0, null)] - [InlineData(InputType.UInt32, "flag", true, new string[] { "flag" }, 0, null)] - [InlineData(InputType.Int64, "flag", true, new string[] { "flag" }, 0, null)] - [InlineData(InputType.UInt64, "flag", true, new string[] { "flag" }, 0, null)] - [InlineData(InputType.String, "flag", true, new string[] { "flag" }, 0, null)] // Invalid parts - [InlineData(InputType.Int8, "flag", true, new string[0], 0, null)] + [InlineData("flag", true, new string[0], 0, false, null)] // Invalid index - [InlineData(InputType.Int8, "flag", true, new string[] { "flag" }, -1, null)] - [InlineData(InputType.Int8, "flag", true, new string[] { "flag" }, 1, null)] + [InlineData("flag", true, new string[] { "flag" }, -1, false, null)] + [InlineData("flag", true, new string[] { "flag" }, 1, false, null)] // Invalid name - [InlineData(InputType.Int8, "flag", true, new string[] { "" }, 0, null)] - [InlineData(InputType.Int8, "flag", true, new string[] { "flag2" }, 0, null)] + [InlineData("flag", true, new string[] { "" }, 0, false, null)] + [InlineData("flag", true, new string[] { "flag2" }, 0, false, null)] // Valid name, no following - [InlineData(InputType.Int8, "flag", true, new string[] { "flag" }, 0, null)] - [InlineData(InputType.Int8, "flag", false, new string[] { "flag" }, 0, sbyte.MinValue)] + [InlineData("flag", true, new string[] { "flag" }, 0, false, null)] + [InlineData("flag", false, new string[] { "flag" }, 0, true, sbyte.MinValue)] // Valid name, invalid following - [InlineData(InputType.Int8, "flag", true, new string[] { "flag", "invalid" }, 0, null)] - [InlineData(InputType.Int8, "flag", false, new string[] { "flag", "invalid" }, 0, sbyte.MinValue)] + [InlineData("flag", true, new string[] { "flag", "invalid" }, 0, false, null)] + [InlineData("flag", false, new string[] { "flag", "invalid" }, 0, true, sbyte.MinValue)] // Valid name, valid following - [InlineData(InputType.Int8, "flag", true, new string[] { "flag", "1" }, 0, (sbyte)1)] - [InlineData(InputType.Int8, "flag", true, new string[] { "flag", "-1" }, 0, (sbyte)-1)] - public void ProcessAsInt8Test(InputType type, string name, bool required, string[] parts, int index, sbyte? expected) + [InlineData("flag", true, new string[] { "flag", "1" }, 0, true, (sbyte)1)] + [InlineData("flag", true, new string[] { "flag", "-1" }, 0, true, (sbyte)-1)] + public void Int8InputTest(string name, bool required, string[] parts, int index, bool success, sbyte? expected) { - Input input = new Input(type, name, required); - sbyte? actual = input.ProcessAsInt8(parts, ref index); - Assert.Equal(expected, actual); + Int8Input input = new Int8Input(name, required); + bool actual = input.Process(parts, ref index); + + Assert.Equal(success, actual); + Assert.Equal(expected, input.Value); } #endregion - #region ProcessAsUInt8 + #region UInt8Input [Theory] - // Invalid type - [InlineData(InputType.None, "flag", true, new string[] { "flag" }, 0, null)] - [InlineData(InputType.Flag, "flag", true, new string[] { "flag" }, 0, null)] - [InlineData(InputType.Boolean, "flag", true, new string[] { "flag" }, 0, null)] - [InlineData(InputType.Int8, "flag", true, new string[] { "flag" }, 0, null)] - [InlineData(InputType.Int16, "flag", true, new string[] { "flag" }, 0, null)] - [InlineData(InputType.UInt16, "flag", true, new string[] { "flag" }, 0, null)] - [InlineData(InputType.Int32, "flag", true, new string[] { "flag" }, 0, null)] - [InlineData(InputType.UInt32, "flag", true, new string[] { "flag" }, 0, null)] - [InlineData(InputType.Int64, "flag", true, new string[] { "flag" }, 0, null)] - [InlineData(InputType.UInt64, "flag", true, new string[] { "flag" }, 0, null)] - [InlineData(InputType.String, "flag", true, new string[] { "flag" }, 0, null)] // Invalid parts - [InlineData(InputType.UInt8, "flag", true, new string[0], 0, null)] + [InlineData("flag", true, new string[0], 0, false, null)] // Invalid index - [InlineData(InputType.UInt8, "flag", true, new string[] { "flag" }, -1, null)] - [InlineData(InputType.UInt8, "flag", true, new string[] { "flag" }, 1, null)] + [InlineData("flag", true, new string[] { "flag" }, -1, false, null)] + [InlineData("flag", true, new string[] { "flag" }, 1, false, null)] // Invalid name - [InlineData(InputType.UInt8, "flag", true, new string[] { "" }, 0, null)] - [InlineData(InputType.UInt8, "flag", true, new string[] { "flag2" }, 0, null)] + [InlineData("flag", true, new string[] { "" }, 0, false, null)] + [InlineData("flag", true, new string[] { "flag2" }, 0, false, null)] // Valid name, no following - [InlineData(InputType.UInt8, "flag", true, new string[] { "flag" }, 0, null)] - [InlineData(InputType.UInt8, "flag", false, new string[] { "flag" }, 0, byte.MinValue)] + [InlineData("flag", true, new string[] { "flag" }, 0, false, null)] + [InlineData("flag", false, new string[] { "flag" }, 0, true, byte.MinValue)] // Valid name, invalid following - [InlineData(InputType.UInt8, "flag", true, new string[] { "flag", "invalid" }, 0, null)] - [InlineData(InputType.UInt8, "flag", false, new string[] { "flag", "invalid" }, 0, byte.MinValue)] + [InlineData("flag", true, new string[] { "flag", "invalid" }, 0, false, null)] + [InlineData("flag", false, new string[] { "flag", "invalid" }, 0, true, byte.MinValue)] // Valid name, valid following - [InlineData(InputType.UInt8, "flag", true, new string[] { "flag", "1" }, 0, (byte)1)] - public void ProcessAsUInt8Test(InputType type, string name, bool required, string[] parts, int index, byte? expected) + [InlineData("flag", true, new string[] { "flag", "1" }, 0, true, (byte)1)] + public void UInt8InputTest(string name, bool required, string[] parts, int index, bool success, byte? expected) { - Input input = new Input(type, name, required); - byte? actual = input.ProcessAsUInt8(parts, ref index); - Assert.Equal(expected, actual); + UInt8Input input = new UInt8Input(name, required); + bool actual = input.Process(parts, ref index); + + Assert.Equal(success, actual); + Assert.Equal(expected, input.Value); } #endregion - #region ProcessAsInt16 + #region Int16Input [Theory] - // Invalid type - [InlineData(InputType.None, "flag", true, new string[] { "flag" }, 0, null)] - [InlineData(InputType.Flag, "flag", true, new string[] { "flag" }, 0, null)] - [InlineData(InputType.Boolean, "flag", true, new string[] { "flag" }, 0, null)] - [InlineData(InputType.Int8, "flag", true, new string[] { "flag" }, 0, null)] - [InlineData(InputType.UInt8, "flag", true, new string[] { "flag" }, 0, null)] - [InlineData(InputType.UInt16, "flag", true, new string[] { "flag" }, 0, null)] - [InlineData(InputType.Int32, "flag", true, new string[] { "flag" }, 0, null)] - [InlineData(InputType.UInt32, "flag", true, new string[] { "flag" }, 0, null)] - [InlineData(InputType.Int64, "flag", true, new string[] { "flag" }, 0, null)] - [InlineData(InputType.UInt64, "flag", true, new string[] { "flag" }, 0, null)] - [InlineData(InputType.String, "flag", true, new string[] { "flag" }, 0, null)] // Invalid parts - [InlineData(InputType.Int16, "flag", true, new string[0], 0, null)] + [InlineData("flag", true, new string[0], 0, false, null)] // Invalid index - [InlineData(InputType.Int16, "flag", true, new string[] { "flag" }, -1, null)] - [InlineData(InputType.Int16, "flag", true, new string[] { "flag" }, 1, null)] + [InlineData("flag", true, new string[] { "flag" }, -1, false, null)] + [InlineData("flag", true, new string[] { "flag" }, 1, false, null)] // Invalid name - [InlineData(InputType.Int16, "flag", true, new string[] { "" }, 0, null)] - [InlineData(InputType.Int16, "flag", true, new string[] { "flag2" }, 0, null)] + [InlineData("flag", true, new string[] { "" }, 0, false, null)] + [InlineData("flag", true, new string[] { "flag2" }, 0, false, null)] // Valid name, no following - [InlineData(InputType.Int16, "flag", true, new string[] { "flag" }, 0, null)] - [InlineData(InputType.Int16, "flag", false, new string[] { "flag" }, 0, short.MinValue)] + [InlineData("flag", true, new string[] { "flag" }, 0, false, null)] + [InlineData("flag", false, new string[] { "flag" }, 0, true, short.MinValue)] // Valid name, invalid following - [InlineData(InputType.Int16, "flag", true, new string[] { "flag", "invalid" }, 0, null)] - [InlineData(InputType.Int16, "flag", false, new string[] { "flag", "invalid" }, 0, short.MinValue)] + [InlineData("flag", true, new string[] { "flag", "invalid" }, 0, false, null)] + [InlineData("flag", false, new string[] { "flag", "invalid" }, 0, true, short.MinValue)] // Valid name, valid following - [InlineData(InputType.Int16, "flag", true, new string[] { "flag", "1" }, 0, (short)1)] - [InlineData(InputType.Int16, "flag", true, new string[] { "flag", "-1" }, 0, (short)-1)] - public void ProcessAsInt16Test(InputType type, string name, bool required, string[] parts, int index, short? expected) + [InlineData("flag", true, new string[] { "flag", "1" }, 0, true, (short)1)] + [InlineData("flag", true, new string[] { "flag", "-1" }, 0, true, (short)-1)] + public void Int16InputTest(string name, bool required, string[] parts, int index, bool success, short? expected) { - Input input = new Input(type, name, required); - short? actual = input.ProcessAsInt16(parts, ref index); - Assert.Equal(expected, actual); + Int16Input input = new Int16Input(name, required); + bool actual = input.Process(parts, ref index); + + Assert.Equal(success, actual); + Assert.Equal(expected, input.Value); } #endregion - #region ProcessAsUInt16 + #region UInt16Input [Theory] - // Invalid type - [InlineData(InputType.None, "flag", true, new string[] { "flag" }, 0, null)] - [InlineData(InputType.Flag, "flag", true, new string[] { "flag" }, 0, null)] - [InlineData(InputType.Boolean, "flag", true, new string[] { "flag" }, 0, null)] - [InlineData(InputType.Int8, "flag", true, new string[] { "flag" }, 0, null)] - [InlineData(InputType.UInt8, "flag", true, new string[] { "flag" }, 0, null)] - [InlineData(InputType.Int16, "flag", true, new string[] { "flag" }, 0, null)] - [InlineData(InputType.Int32, "flag", true, new string[] { "flag" }, 0, null)] - [InlineData(InputType.UInt32, "flag", true, new string[] { "flag" }, 0, null)] - [InlineData(InputType.Int64, "flag", true, new string[] { "flag" }, 0, null)] - [InlineData(InputType.UInt64, "flag", true, new string[] { "flag" }, 0, null)] - [InlineData(InputType.String, "flag", true, new string[] { "flag" }, 0, null)] // Invalid parts - [InlineData(InputType.UInt16, "flag", true, new string[0], 0, null)] + [InlineData("flag", true, new string[0], 0, false, null)] // Invalid index - [InlineData(InputType.UInt16, "flag", true, new string[] { "flag" }, -1, null)] - [InlineData(InputType.UInt16, "flag", true, new string[] { "flag" }, 1, null)] + [InlineData("flag", true, new string[] { "flag" }, -1, false, null)] + [InlineData("flag", true, new string[] { "flag" }, 1, false, null)] // Invalid name - [InlineData(InputType.UInt16, "flag", true, new string[] { "" }, 0, null)] - [InlineData(InputType.UInt16, "flag", true, new string[] { "flag2" }, 0, null)] + [InlineData("flag", true, new string[] { "" }, 0, false, null)] + [InlineData("flag", true, new string[] { "flag2" }, 0, false, null)] // Valid name, no following - [InlineData(InputType.UInt16, "flag", true, new string[] { "flag" }, 0, null)] - [InlineData(InputType.UInt16, "flag", false, new string[] { "flag" }, 0, ushort.MinValue)] + [InlineData("flag", true, new string[] { "flag" }, 0, false, null)] + [InlineData("flag", false, new string[] { "flag" }, 0, true, ushort.MinValue)] // Valid name, invalid following - [InlineData(InputType.UInt16, "flag", true, new string[] { "flag", "invalid" }, 0, null)] - [InlineData(InputType.UInt16, "flag", false, new string[] { "flag", "invalid" }, 0, ushort.MinValue)] + [InlineData("flag", true, new string[] { "flag", "invalid" }, 0, false, null)] + [InlineData("flag", false, new string[] { "flag", "invalid" }, 0, true, ushort.MinValue)] // Valid name, valid following - [InlineData(InputType.UInt16, "flag", true, new string[] { "flag", "1" }, 0, (ushort)1)] - public void ProcessAsUInt16Test(InputType type, string name, bool required, string[] parts, int index, ushort? expected) + [InlineData("flag", true, new string[] { "flag", "1" }, 0, true, (ushort)1)] + public void UInt16InputTest(string name, bool required, string[] parts, int index, bool success, ushort? expected) { - Input input = new Input(type, name, required); - ushort? actual = input.ProcessAsUInt16(parts, ref index); - Assert.Equal(expected, actual); + UInt16Input input = new UInt16Input(name, required); + bool actual = input.Process(parts, ref index); + + Assert.Equal(success, actual); + Assert.Equal(expected, input.Value); } #endregion - #region ProcessAsInt32 + #region Int32Input [Theory] - // Invalid type - [InlineData(InputType.None, "flag", true, new string[] { "flag" }, 0, null)] - [InlineData(InputType.Flag, "flag", true, new string[] { "flag" }, 0, null)] - [InlineData(InputType.Boolean, "flag", true, new string[] { "flag" }, 0, null)] - [InlineData(InputType.Int8, "flag", true, new string[] { "flag" }, 0, null)] - [InlineData(InputType.UInt8, "flag", true, new string[] { "flag" }, 0, null)] - [InlineData(InputType.Int16, "flag", true, new string[] { "flag" }, 0, null)] - [InlineData(InputType.UInt16, "flag", true, new string[] { "flag" }, 0, null)] - [InlineData(InputType.UInt32, "flag", true, new string[] { "flag" }, 0, null)] - [InlineData(InputType.Int64, "flag", true, new string[] { "flag" }, 0, null)] - [InlineData(InputType.UInt64, "flag", true, new string[] { "flag" }, 0, null)] - [InlineData(InputType.String, "flag", true, new string[] { "flag" }, 0, null)] // Invalid parts - [InlineData(InputType.Int32, "flag", true, new string[0], 0, null)] + [InlineData("flag", true, new string[0], 0, false, null)] // Invalid index - [InlineData(InputType.Int32, "flag", true, new string[] { "flag" }, -1, null)] - [InlineData(InputType.Int32, "flag", true, new string[] { "flag" }, 1, null)] + [InlineData("flag", true, new string[] { "flag" }, -1, false, null)] + [InlineData("flag", true, new string[] { "flag" }, 1, false, null)] // Invalid name - [InlineData(InputType.Int32, "flag", true, new string[] { "" }, 0, null)] - [InlineData(InputType.Int32, "flag", true, new string[] { "flag2" }, 0, null)] + [InlineData("flag", true, new string[] { "" }, 0, false, null)] + [InlineData("flag", true, new string[] { "flag2" }, 0, false, null)] // Valid name, no following - [InlineData(InputType.Int32, "flag", true, new string[] { "flag" }, 0, null)] - [InlineData(InputType.Int32, "flag", false, new string[] { "flag" }, 0, int.MinValue)] + [InlineData("flag", true, new string[] { "flag" }, 0, false, null)] + [InlineData("flag", false, new string[] { "flag" }, 0, true, int.MinValue)] // Valid name, invalid following - [InlineData(InputType.Int32, "flag", true, new string[] { "flag", "invalid" }, 0, null)] - [InlineData(InputType.Int32, "flag", false, new string[] { "flag", "invalid" }, 0, int.MinValue)] + [InlineData("flag", true, new string[] { "flag", "invalid" }, 0, false, null)] + [InlineData("flag", false, new string[] { "flag", "invalid" }, 0, true, int.MinValue)] // Valid name, valid following - [InlineData(InputType.Int32, "flag", true, new string[] { "flag", "1" }, 0, (int)1)] - [InlineData(InputType.Int32, "flag", true, new string[] { "flag", "-1" }, 0, (int)-1)] - public void ProcessAsInt32Test(InputType type, string name, bool required, string[] parts, int index, int? expected) + [InlineData("flag", true, new string[] { "flag", "1" }, 0, true, (int)1)] + [InlineData("flag", true, new string[] { "flag", "-1" }, 0, true, (int)-1)] + public void Int32InputTest(string name, bool required, string[] parts, int index, bool success, int? expected) { - Input input = new Input(type, name, required); - int? actual = input.ProcessAsInt32(parts, ref index); - Assert.Equal(expected, actual); + Int32Input input = new Int32Input(name, required); + bool actual = input.Process(parts, ref index); + + Assert.Equal(success, actual); + Assert.Equal(expected, input.Value); } #endregion - #region ProcessAsUInt32 + #region UInt32Input [Theory] - // Invalid type - [InlineData(InputType.None, "flag", true, new string[] { "flag" }, 0, null)] - [InlineData(InputType.Flag, "flag", true, new string[] { "flag" }, 0, null)] - [InlineData(InputType.Boolean, "flag", true, new string[] { "flag" }, 0, null)] - [InlineData(InputType.Int8, "flag", true, new string[] { "flag" }, 0, null)] - [InlineData(InputType.UInt8, "flag", true, new string[] { "flag" }, 0, null)] - [InlineData(InputType.Int16, "flag", true, new string[] { "flag" }, 0, null)] - [InlineData(InputType.UInt16, "flag", true, new string[] { "flag" }, 0, null)] - [InlineData(InputType.Int32, "flag", true, new string[] { "flag" }, 0, null)] - [InlineData(InputType.Int64, "flag", true, new string[] { "flag" }, 0, null)] - [InlineData(InputType.UInt64, "flag", true, new string[] { "flag" }, 0, null)] - [InlineData(InputType.String, "flag", true, new string[] { "flag" }, 0, null)] // Invalid parts - [InlineData(InputType.UInt32, "flag", true, new string[0], 0, null)] + [InlineData("flag", true, new string[0], 0, false, null)] // Invalid index - [InlineData(InputType.UInt32, "flag", true, new string[] { "flag" }, -1, null)] - [InlineData(InputType.UInt32, "flag", true, new string[] { "flag" }, 1, null)] + [InlineData("flag", true, new string[] { "flag" }, -1, false, null)] + [InlineData("flag", true, new string[] { "flag" }, 1, false, null)] // Invalid name - [InlineData(InputType.UInt32, "flag", true, new string[] { "" }, 0, null)] - [InlineData(InputType.UInt32, "flag", true, new string[] { "flag2" }, 0, null)] + [InlineData("flag", true, new string[] { "" }, 0, false, null)] + [InlineData("flag", true, new string[] { "flag2" }, 0, false, null)] // Valid name, no following - [InlineData(InputType.UInt32, "flag", true, new string[] { "flag" }, 0, null)] - [InlineData(InputType.UInt32, "flag", false, new string[] { "flag" }, 0, uint.MinValue)] + [InlineData("flag", true, new string[] { "flag" }, 0, false, null)] + [InlineData("flag", false, new string[] { "flag" }, 0, true, uint.MinValue)] // Valid name, invalid following - [InlineData(InputType.UInt32, "flag", true, new string[] { "flag", "invalid" }, 0, null)] - [InlineData(InputType.UInt32, "flag", false, new string[] { "flag", "invalid" }, 0, uint.MinValue)] + [InlineData("flag", true, new string[] { "flag", "invalid" }, 0, false, null)] + [InlineData("flag", false, new string[] { "flag", "invalid" }, 0, true, uint.MinValue)] // Valid name, valid following - [InlineData(InputType.UInt32, "flag", true, new string[] { "flag", "1" }, 0, (uint)1)] - public void ProcessAsUInt32Test(InputType type, string name, bool required, string[] parts, int index, uint? expected) + [InlineData("flag", true, new string[] { "flag", "1" }, 0, true, (uint)1)] + public void UInt32InputTest(string name, bool required, string[] parts, int index, bool success, uint? expected) { - Input input = new Input(type, name, required); - uint? actual = input.ProcessAsUInt32(parts, ref index); - Assert.Equal(expected, actual); + UInt32Input input = new UInt32Input(name, required); + bool actual = input.Process(parts, ref index); + + Assert.Equal(success, actual); + Assert.Equal(expected, input.Value); } #endregion - #region ProcessAsInt64 + #region Int64Input [Theory] - // Invalid type - [InlineData(InputType.None, "flag", true, new string[] { "flag" }, 0, null)] - [InlineData(InputType.Flag, "flag", true, new string[] { "flag" }, 0, null)] - [InlineData(InputType.Boolean, "flag", true, new string[] { "flag" }, 0, null)] - [InlineData(InputType.Int8, "flag", true, new string[] { "flag" }, 0, null)] - [InlineData(InputType.UInt8, "flag", true, new string[] { "flag" }, 0, null)] - [InlineData(InputType.Int16, "flag", true, new string[] { "flag" }, 0, null)] - [InlineData(InputType.UInt16, "flag", true, new string[] { "flag" }, 0, null)] - [InlineData(InputType.Int32, "flag", true, new string[] { "flag" }, 0, null)] - [InlineData(InputType.UInt32, "flag", true, new string[] { "flag" }, 0, null)] - [InlineData(InputType.UInt64, "flag", true, new string[] { "flag" }, 0, null)] - [InlineData(InputType.String, "flag", true, new string[] { "flag" }, 0, null)] // Invalid parts - [InlineData(InputType.Int64, "flag", true, new string[0], 0, null)] + [InlineData("flag", true, new string[0], 0, false, null)] // Invalid index - [InlineData(InputType.Int64, "flag", true, new string[] { "flag" }, -1, null)] - [InlineData(InputType.Int64, "flag", true, new string[] { "flag" }, 1, null)] + [InlineData("flag", true, new string[] { "flag" }, -1, false, null)] + [InlineData("flag", true, new string[] { "flag" }, 1, false, null)] // Invalid name - [InlineData(InputType.Int64, "flag", true, new string[] { "" }, 0, null)] - [InlineData(InputType.Int64, "flag", true, new string[] { "flag2" }, 0, null)] + [InlineData("flag", true, new string[] { "" }, 0, false, null)] + [InlineData("flag", true, new string[] { "flag2" }, 0, false, null)] // Valid name, no following - [InlineData(InputType.Int64, "flag", true, new string[] { "flag" }, 0, null)] - [InlineData(InputType.Int64, "flag", false, new string[] { "flag" }, 0, long.MinValue)] + [InlineData("flag", true, new string[] { "flag" }, 0, false, null)] + [InlineData("flag", false, new string[] { "flag" }, 0, true, long.MinValue)] // Valid name, invalid following - [InlineData(InputType.Int64, "flag", true, new string[] { "flag", "invalid" }, 0, null)] - [InlineData(InputType.Int64, "flag", false, new string[] { "flag", "invalid" }, 0, long.MinValue)] + [InlineData("flag", true, new string[] { "flag", "invalid" }, 0, false, null)] + [InlineData("flag", false, new string[] { "flag", "invalid" }, 0, true, long.MinValue)] // Valid name, valid following - [InlineData(InputType.Int64, "flag", true, new string[] { "flag", "1" }, 0, (long)1)] - [InlineData(InputType.Int64, "flag", true, new string[] { "flag", "-1" }, 0, (long)-1)] - public void ProcessAsInt64Test(InputType type, string name, bool required, string[] parts, int index, long? expected) + [InlineData("flag", true, new string[] { "flag", "1" }, 0, true, (long)1)] + [InlineData("flag", true, new string[] { "flag", "-1" }, 0, true, (long)-1)] + public void Int64InputTest(string name, bool required, string[] parts, int index, bool success, long? expected) { - Input input = new Input(type, name, required); - long? actual = input.ProcessAsInt64(parts, ref index); - Assert.Equal(expected, actual); + Int64Input input = new Int64Input(name, required); + bool actual = input.Process(parts, ref index); + + Assert.Equal(success, actual); + Assert.Equal(expected, input.Value); } #endregion - #region ProcessAsUInt64 + #region UInt64Input [Theory] - // Invalid type - [InlineData(InputType.None, "flag", true, new string[] { "flag" }, 0, null)] - [InlineData(InputType.Flag, "flag", true, new string[] { "flag" }, 0, null)] - [InlineData(InputType.Boolean, "flag", true, new string[] { "flag" }, 0, null)] - [InlineData(InputType.Int8, "flag", true, new string[] { "flag" }, 0, null)] - [InlineData(InputType.UInt8, "flag", true, new string[] { "flag" }, 0, null)] - [InlineData(InputType.Int16, "flag", true, new string[] { "flag" }, 0, null)] - [InlineData(InputType.UInt16, "flag", true, new string[] { "flag" }, 0, null)] - [InlineData(InputType.Int32, "flag", true, new string[] { "flag" }, 0, null)] - [InlineData(InputType.UInt32, "flag", true, new string[] { "flag" }, 0, null)] - [InlineData(InputType.Int64, "flag", true, new string[] { "flag" }, 0, null)] - [InlineData(InputType.String, "flag", true, new string[] { "flag" }, 0, null)] // Invalid parts - [InlineData(InputType.UInt64, "flag", true, new string[0], 0, null)] + [InlineData("flag", true, new string[0], 0, false, null)] // Invalid index - [InlineData(InputType.UInt64, "flag", true, new string[] { "flag" }, -1, null)] - [InlineData(InputType.UInt64, "flag", true, new string[] { "flag" }, 1, null)] + [InlineData("flag", true, new string[] { "flag" }, -1, false, null)] + [InlineData("flag", true, new string[] { "flag" }, 1, false, null)] // Invalid name - [InlineData(InputType.UInt64, "flag", true, new string[] { "" }, 0, null)] - [InlineData(InputType.UInt64, "flag", true, new string[] { "flag2" }, 0, null)] + [InlineData("flag", true, new string[] { "" }, 0, false, null)] + [InlineData("flag", true, new string[] { "flag2" }, 0, false, null)] // Valid name, no following - [InlineData(InputType.UInt64, "flag", true, new string[] { "flag" }, 0, null)] - [InlineData(InputType.UInt64, "flag", false, new string[] { "flag" }, 0, ulong.MinValue)] + [InlineData("flag", true, new string[] { "flag" }, 0, false, null)] + [InlineData("flag", false, new string[] { "flag" }, 0, true, ulong.MinValue)] // Valid name, invalid following - [InlineData(InputType.UInt64, "flag", true, new string[] { "flag", "invalid" }, 0, null)] - [InlineData(InputType.UInt64, "flag", false, new string[] { "flag", "invalid" }, 0, ulong.MinValue)] + [InlineData("flag", true, new string[] { "flag", "invalid" }, 0, false, null)] + [InlineData("flag", false, new string[] { "flag", "invalid" }, 0, true, ulong.MinValue)] // Valid name, valid following - [InlineData(InputType.UInt64, "flag", true, new string[] { "flag", "1" }, 0, (ulong)1)] - public void ProcessAsUInt64Test(InputType type, string name, bool required, string[] parts, int index, ulong? expected) + [InlineData("flag", true, new string[] { "flag", "1" }, 0, true, (ulong)1)] + public void UInt64InputTest(string name, bool required, string[] parts, int index, bool success, ulong? expected) { - Input input = new Input(type, name, required); - ulong? actual = input.ProcessAsUInt64(parts, ref index); - Assert.Equal(expected, actual); + UInt64Input input = new UInt64Input(name, required); + bool actual = input.Process(parts, ref index); + + Assert.Equal(success, actual); + Assert.Equal(expected, input.Value); } #endregion - #region ProcessAsString + #region StringInput [Theory] - // Invalid type - [InlineData(InputType.None, "flag", true, new string[] { "flag" }, 0, null)] - [InlineData(InputType.Flag, "flag", true, new string[] { "flag" }, 0, null)] - [InlineData(InputType.Boolean, "flag", true, new string[] { "flag" }, 0, null)] - [InlineData(InputType.Int8, "flag", true, new string[] { "flag" }, 0, null)] - [InlineData(InputType.UInt8, "flag", true, new string[] { "flag" }, 0, null)] - [InlineData(InputType.Int16, "flag", true, new string[] { "flag" }, 0, null)] - [InlineData(InputType.UInt16, "flag", true, new string[] { "flag" }, 0, null)] - [InlineData(InputType.Int32, "flag", true, new string[] { "flag" }, 0, null)] - [InlineData(InputType.UInt32, "flag", true, new string[] { "flag" }, 0, null)] - [InlineData(InputType.Int64, "flag", true, new string[] { "flag" }, 0, null)] - [InlineData(InputType.UInt64, "flag", true, new string[] { "flag" }, 0, null)] // Invalid parts - [InlineData(InputType.String, "flag", true, new string[0], 0, null)] + [InlineData("flag", true, new string[0], 0, false, null)] // Invalid index - [InlineData(InputType.String, "flag", true, new string[] { "flag" }, -1, null)] - [InlineData(InputType.String, "flag", true, new string[] { "flag" }, 1, null)] + [InlineData("flag", true, new string[] { "flag" }, -1, false, null)] + [InlineData("flag", true, new string[] { "flag" }, 1, false, null)] // Invalid name - [InlineData(InputType.String, "flag", true, new string[] { "" }, 0, null)] - [InlineData(InputType.String, "flag", true, new string[] { "flag2" }, 0, null)] + [InlineData("flag", true, new string[] { "" }, 0, false, null)] + [InlineData("flag", true, new string[] { "flag2" }, 0, false, null)] // Valid name, no following - [InlineData(InputType.String, "flag", true, new string[] { "flag" }, 0, null)] - [InlineData(InputType.String, "flag", false, new string[] { "flag" }, 0, "")] + [InlineData("flag", true, new string[] { "flag" }, 0, false, null)] + [InlineData("flag", false, new string[] { "flag" }, 0, true, "")] // Valid name, following - [InlineData(InputType.String, "flag", true, new string[] { "flag", "value" }, 0, "value")] - public void ProcessAsString(InputType type, string name, bool required, string[] parts, int index, string? expected) + [InlineData("flag", true, new string[] { "flag", "value" }, 0, true, "value")] + public void StringInputTest(string name, bool required, string[] parts, int index, bool success, string? expected) { - Input input = new Input(type, name, required); - string? actual = input.ProcessAsString(parts, ref index); - Assert.Equal(expected, actual); + StringInput input = new StringInput(name, required); + bool actual = input.Process(parts, ref index); + + Assert.Equal(success, actual); + Assert.Equal(expected, input.Value); } #endregion diff --git a/MPF.ExecutionContexts/Data/BooleanInput.cs b/MPF.ExecutionContexts/Data/BooleanInput.cs new file mode 100644 index 00000000..a78e7a94 --- /dev/null +++ b/MPF.ExecutionContexts/Data/BooleanInput.cs @@ -0,0 +1,61 @@ +namespace MPF.ExecutionContexts.Data +{ + /// + /// Represents a boolean flag with an optional trailing value + /// + public class BooleanInput : Input + { + #region Constructors + + /// + public BooleanInput(string name) + : base(name) { } + + /// + public BooleanInput(string name, bool required) + : base(name, required) { } + + /// + public BooleanInput(string shortName, string longName) + : base(shortName, longName) { } + + /// + public BooleanInput(string shortName, string longName, bool required) + : base(shortName, longName, required) { } + + #endregion + + /// + public override bool Process(string[] parts, ref int index) + { + // Check the parts array + if (parts.Length == 0) + return false; + + // Check the index + if (index < 0 || index >= parts.Length) + return false; + + // Check the name + if (parts[index] != Name && (_longName != null && parts[index] != _longName)) + return false; + + // Ensure the value exists + if (!DoesExist(parts, index + 1)) + { + Value = _required ? null : true; + return !_required; + } + + // If the next value is valid + if (!bool.TryParse(parts[index + 1], out bool value)) + { + Value = _required ? null : true; + return !_required; + } + + index++; + return value; + } + } +} \ No newline at end of file diff --git a/MPF.ExecutionContexts/Data/FlagInput.cs b/MPF.ExecutionContexts/Data/FlagInput.cs new file mode 100644 index 00000000..664b5627 --- /dev/null +++ b/MPF.ExecutionContexts/Data/FlagInput.cs @@ -0,0 +1,47 @@ +namespace MPF.ExecutionContexts.Data +{ + /// + /// Represents a boolean flag without a trailing value + /// + public class FlagInput : Input + { + #region Constructors + + /// + public FlagInput(string name) + : base(name) { } + + /// + public FlagInput(string name, bool required) + : base(name, required) { } + + /// + public FlagInput(string shortName, string longName) + : base(shortName, longName) { } + + /// + public FlagInput(string shortName, string longName, bool required) + : base(shortName, longName, required) { } + + #endregion + + /// + public override bool Process(string[] parts, ref int index) + { + // Check the parts array + if (parts.Length == 0) + return false; + + // Check the index + if (index < 0 || index >= parts.Length) + return false; + + // Check the name + if (parts[index] != Name && (_longName != null && parts[index] != _longName)) + return false; + + Value = true; + return true; + } + } +} \ No newline at end of file diff --git a/MPF.ExecutionContexts/Data/Input.cs b/MPF.ExecutionContexts/Data/Input.cs new file mode 100644 index 00000000..7b6c3af9 --- /dev/null +++ b/MPF.ExecutionContexts/Data/Input.cs @@ -0,0 +1,208 @@ +using System; + +namespace MPF.ExecutionContexts.Data +{ + /// + /// Represents a single input for an execution context + /// + public abstract class Input + { + #region Properties + + /// + /// Primary name for the input + /// + public readonly string Name; + + /// + /// Verbose name for the input + /// + protected readonly string? _longName; + + /// + /// Indicates if the value following is required or not + /// + protected readonly bool _required; + + #endregion + + #region Constructors + + /// Flag name / value + public Input(string name) + { + Name = name; + _longName = null; + _required = true; + } + + /// Flag name / value + /// Indicates if a following value is required + public Input(string name, bool required) + { + Name = name; + _longName = null; + _required = required; + } + + /// Flag name / value + /// Verbose flag name / value + public Input(string shortName, string longName) + { + Name = shortName; + _longName = longName; + _required = true; + } + + /// Flag name / value + /// Verbose flag name / value + /// Indicates if a following value is required + public Input(string shortName, string longName, bool required) + { + Name = shortName; + _longName = longName; + _required = required; + } + + #endregion + + #region Helpers + + /// + /// Returns whether or not the selected item exists + /// + /// Parts array to be referenced + /// Current index + /// True if the next item exists, false otherwise + internal static bool DoesExist(string[] parts, int index) + => index >= 0 && index < parts.Length; + + /// + /// Get the trimmed value and multiplication factor from a value + /// + /// String value to treat as suffixed number + /// Trimmed value and multiplication factor + internal static string ExtractFactorFromValue(string value, out long factor) + { + value = value.Trim('"'); + factor = 1; + + // Characters + if (value.EndsWith("c", StringComparison.Ordinal)) + { + factor = 1; + value = value.TrimEnd('c'); + } + + // Words + else if (value.EndsWith("w", StringComparison.Ordinal)) + { + factor = 2; + value = value.TrimEnd('w'); + } + + // Double Words + else if (value.EndsWith("d", StringComparison.Ordinal)) + { + factor = 4; + value = value.TrimEnd('d'); + } + + // Quad Words + else if (value.EndsWith("q", StringComparison.Ordinal)) + { + factor = 8; + value = value.TrimEnd('q'); + } + + // Kilobytes + else if (value.EndsWith("k", StringComparison.Ordinal)) + { + factor = 1024; + value = value.TrimEnd('k'); + } + + // Megabytes + else if (value.EndsWith("M", StringComparison.Ordinal)) + { + factor = 1024 * 1024; + value = value.TrimEnd('M'); + } + + // Gigabytes + else if (value.EndsWith("G", StringComparison.Ordinal)) + { + factor = 1024 * 1024 * 1024; + value = value.TrimEnd('G'); + } + + return value; + } + + /// + /// Removes a leading 0x if it exists, case insensitive + /// + /// String with removed leading 0x + /// + internal static string RemoveHexIdentifier(string value) + { + if (value.Length <= 2) + return value; + if (value[0] != '0') + return value; + if (value[1] != 'x' && value[1] != 'X') + return value; + + return value.Substring(2); + } + + #endregion + } + + /// + /// Represents a single input for an execution context + /// + public abstract class Input : Input + { + #region Properties + + /// + /// Represents the last value stored + /// + public T? Value { get; protected set; } + + #endregion + + #region Constructors + + /// + public Input(string name) + : base(name) { } + + /// + public Input(string name, bool required) + : base(name, required) { } + + /// + public Input(string shortName, string longName) + : base(shortName, longName) { } + + /// + public Input(string shortName, string longName, bool required) + : base(shortName, longName, required) { } + + #endregion + + #region Processors + + /// + /// Process the current index, if possible + /// + /// Parts array to be referenced + /// Reference to the position in the parts + /// True if a value could be determined, false otherwise + public abstract bool Process(string[] parts, ref int index); + + #endregion + } +} \ No newline at end of file diff --git a/MPF.ExecutionContexts/Data/Int16Input.cs b/MPF.ExecutionContexts/Data/Int16Input.cs new file mode 100644 index 00000000..601407ab --- /dev/null +++ b/MPF.ExecutionContexts/Data/Int16Input.cs @@ -0,0 +1,83 @@ +using System.Globalization; + +namespace MPF.ExecutionContexts.Data +{ + /// + /// Represents an Int16 flag with an optional trailing value + /// + public class Int16Input : Input + { + #region Constructors + + /// + public Int16Input(string name) + : base(name) { } + + /// + public Int16Input(string name, bool required) + : base(name, required) { } + + /// + public Int16Input(string shortName, string longName) + : base(shortName, longName) { } + + /// + public Int16Input(string shortName, string longName, bool required) + : base(shortName, longName, required) { } + + #endregion + + /// + public override bool Process(string[] parts, ref int index) + { + // Check the parts array + if (parts.Length == 0) + return false; + + // Check the index + if (index < 0 || index >= parts.Length) + return false; + + // Check the name + if (parts[index] != Name && (_longName != null && parts[index] != _longName)) + return false; + + // Ensure the value exists + if (!DoesExist(parts, index + 1)) + { + Value = _required ? null : short.MinValue; + return !_required; + } + + // If the next value is valid + if (short.TryParse(parts[index + 1], out short value)) + { + index++; + Value = value; + return true; + } + + // Try to process as a formatted string + string baseVal = ExtractFactorFromValue(parts[index + 1], out long factor); + if (short.TryParse(baseVal, out value)) + { + index++; + Value = (short)(value * factor); + return true; + } + + // Try to process as a hex string + string hexValue = RemoveHexIdentifier(baseVal); + if (short.TryParse(hexValue, NumberStyles.AllowHexSpecifier, CultureInfo.InvariantCulture, out value)) + { + index++; + Value = (short)(value * factor); + return true; + } + + // Return value based on required flag + Value = _required ? null : short.MinValue; + return !_required; + } + } +} \ No newline at end of file diff --git a/MPF.ExecutionContexts/Data/Int32Input.cs b/MPF.ExecutionContexts/Data/Int32Input.cs new file mode 100644 index 00000000..7ff2b96e --- /dev/null +++ b/MPF.ExecutionContexts/Data/Int32Input.cs @@ -0,0 +1,83 @@ +using System.Globalization; + +namespace MPF.ExecutionContexts.Data +{ + /// + /// Represents an Int32 flag with an optional trailing value + /// + public class Int32Input : Input + { + #region Constructors + + /// + public Int32Input(string name) + : base(name) { } + + /// + public Int32Input(string name, bool required) + : base(name, required) { } + + /// + public Int32Input(string shortName, string longName) + : base(shortName, longName) { } + + /// + public Int32Input(string shortName, string longName, bool required) + : base(shortName, longName, required) { } + + #endregion + + /// + public override bool Process(string[] parts, ref int index) + { + // Check the parts array + if (parts.Length == 0) + return false; + + // Check the index + if (index < 0 || index >= parts.Length) + return false; + + // Check the name + if (parts[index] != Name && (_longName != null && parts[index] != _longName)) + return false; + + // Ensure the value exists + if (!DoesExist(parts, index + 1)) + { + Value = _required ? null : int.MinValue; + return !_required; + } + + // If the next value is valid + if (int.TryParse(parts[index + 1], out int value)) + { + index++; + Value = value; + return true; + } + + // Try to process as a formatted string + string baseVal = ExtractFactorFromValue(parts[index + 1], out long factor); + if (int.TryParse(baseVal, out value)) + { + index++; + Value = (int)(value * factor); + return true; + } + + // Try to process as a hex string + string hexValue = RemoveHexIdentifier(baseVal); + if (int.TryParse(hexValue, NumberStyles.AllowHexSpecifier, CultureInfo.InvariantCulture, out value)) + { + index++; + Value = (int)(value * factor); + return true; + } + + // Return value based on required flag + Value = _required ? null : int.MinValue; + return !_required; + } + } +} \ No newline at end of file diff --git a/MPF.ExecutionContexts/Data/Int64Input.cs b/MPF.ExecutionContexts/Data/Int64Input.cs new file mode 100644 index 00000000..3d0baf59 --- /dev/null +++ b/MPF.ExecutionContexts/Data/Int64Input.cs @@ -0,0 +1,83 @@ +using System.Globalization; + +namespace MPF.ExecutionContexts.Data +{ + /// + /// Represents an Int64 flag with an optional trailing value + /// + public class Int64Input : Input + { + #region Constructors + + /// + public Int64Input(string name) + : base(name) { } + + /// + public Int64Input(string name, bool required) + : base(name, required) { } + + /// + public Int64Input(string shortName, string longName) + : base(shortName, longName) { } + + /// + public Int64Input(string shortName, string longName, bool required) + : base(shortName, longName, required) { } + + #endregion + + /// + public override bool Process(string[] parts, ref int index) + { + // Check the parts array + if (parts.Length == 0) + return false; + + // Check the index + if (index < 0 || index >= parts.Length) + return false; + + // Check the name + if (parts[index] != Name && (_longName != null && parts[index] != _longName)) + return false; + + // Ensure the value exists + if (!DoesExist(parts, index + 1)) + { + Value = _required ? null : long.MinValue; + return !_required; + } + + // If the next value is valid + if (long.TryParse(parts[index + 1], out long value)) + { + index++; + Value = value; + return true; + } + + // Try to process as a formatted string + string baseVal = ExtractFactorFromValue(parts[index + 1], out long factor); + if (long.TryParse(baseVal, out value)) + { + index++; + Value = (long)(value * factor); + return true; + } + + // Try to process as a hex string + string hexValue = RemoveHexIdentifier(baseVal); + if (long.TryParse(hexValue, NumberStyles.AllowHexSpecifier, CultureInfo.InvariantCulture, out value)) + { + index++; + Value = (long)(value * factor); + return true; + } + + // Return value based on required flag + Value = _required ? null : long.MinValue; + return !_required; + } + } +} \ No newline at end of file diff --git a/MPF.ExecutionContexts/Data/Int8Input.cs b/MPF.ExecutionContexts/Data/Int8Input.cs new file mode 100644 index 00000000..2c3c18bf --- /dev/null +++ b/MPF.ExecutionContexts/Data/Int8Input.cs @@ -0,0 +1,83 @@ +using System.Globalization; + +namespace MPF.ExecutionContexts.Data +{ + /// + /// Represents an Int8 flag with an optional trailing value + /// + public class Int8Input : Input + { + #region Constructors + + /// + public Int8Input(string name) + : base(name) { } + + /// + public Int8Input(string name, bool required) + : base(name, required) { } + + /// + public Int8Input(string shortName, string longName) + : base(shortName, longName) { } + + /// + public Int8Input(string shortName, string longName, bool required) + : base(shortName, longName, required) { } + + #endregion + + /// + public override bool Process(string[] parts, ref int index) + { + // Check the parts array + if (parts.Length == 0) + return false; + + // Check the index + if (index < 0 || index >= parts.Length) + return false; + + // Check the name + if (parts[index] != Name && (_longName != null && parts[index] != _longName)) + return false; + + // Ensure the value exists + if (!DoesExist(parts, index + 1)) + { + Value = _required ? null : sbyte.MinValue; + return !_required; + } + + // If the next value is valid + if (sbyte.TryParse(parts[index + 1], out sbyte value)) + { + index++; + Value = value; + return true; + } + + // Try to process as a formatted string + string baseVal = ExtractFactorFromValue(parts[index + 1], out long factor); + if (sbyte.TryParse(baseVal, out value)) + { + index++; + Value = (sbyte)(value * factor); + return true; + } + + // Try to process as a hex string + string hexValue = RemoveHexIdentifier(baseVal); + if (sbyte.TryParse(hexValue, NumberStyles.AllowHexSpecifier, CultureInfo.InvariantCulture, out value)) + { + index++; + Value = (sbyte)(value * factor); + return true; + } + + // Return value based on required flag + Value = _required ? null : sbyte.MinValue; + return !_required; + } + } +} \ No newline at end of file diff --git a/MPF.ExecutionContexts/Data/StringInput.cs b/MPF.ExecutionContexts/Data/StringInput.cs new file mode 100644 index 00000000..bfd6585f --- /dev/null +++ b/MPF.ExecutionContexts/Data/StringInput.cs @@ -0,0 +1,55 @@ +namespace MPF.ExecutionContexts.Data +{ + /// + /// Represents a string flag with an optional trailing value + /// + public class StringInput : Input + { + #region Constructors + + /// + public StringInput(string name) + : base(name) { } + + /// + public StringInput(string name, bool required) + : base(name, required) { } + + /// + public StringInput(string shortName, string longName) + : base(shortName, longName) { } + + /// + public StringInput(string shortName, string longName, bool required) + : base(shortName, longName, required) { } + + #endregion + + /// + public override bool Process(string[] parts, ref int index) + { + // Check the parts array + if (parts.Length == 0) + return false; + + // Check the index + if (index < 0 || index >= parts.Length) + return false; + + // Check the name + if (parts[index] != Name && (_longName != null && parts[index] != _longName)) + return false; + + // Ensure the value exists + if (!DoesExist(parts, index + 1)) + { + Value = _required ? null : string.Empty; + return !_required; + } + + index++; + Value = parts[index]; + return true; + } + } +} \ No newline at end of file diff --git a/MPF.ExecutionContexts/Data/UInt16Input.cs b/MPF.ExecutionContexts/Data/UInt16Input.cs new file mode 100644 index 00000000..8f05988e --- /dev/null +++ b/MPF.ExecutionContexts/Data/UInt16Input.cs @@ -0,0 +1,83 @@ +using System.Globalization; + +namespace MPF.ExecutionContexts.Data +{ + /// + /// Represents an UInt16 flag with an optional trailing value + /// + public class UInt16Input : Input + { + #region Constructors + + /// + public UInt16Input(string name) + : base(name) { } + + /// + public UInt16Input(string name, bool required) + : base(name, required) { } + + /// + public UInt16Input(string shortName, string longName) + : base(shortName, longName) { } + + /// + public UInt16Input(string shortName, string longName, bool required) + : base(shortName, longName, required) { } + + #endregion + + /// + public override bool Process(string[] parts, ref int index) + { + // Check the parts array + if (parts.Length == 0) + return false; + + // Check the index + if (index < 0 || index >= parts.Length) + return false; + + // Check the name + if (parts[index] != Name && (_longName != null && parts[index] != _longName)) + return false; + + // Ensure the value exists + if (!DoesExist(parts, index + 1)) + { + Value = _required ? null : ushort.MinValue; + return !_required; + } + + // If the next value is valid + if (ushort.TryParse(parts[index + 1], out ushort value)) + { + index++; + Value = value; + return true; + } + + // Try to process as a formatted string + string baseVal = ExtractFactorFromValue(parts[index + 1], out long factor); + if (ushort.TryParse(baseVal, out value)) + { + index++; + Value = (ushort)(value * factor); + return true; + } + + // Try to process as a hex string + string hexValue = RemoveHexIdentifier(baseVal); + if (ushort.TryParse(hexValue, NumberStyles.AllowHexSpecifier, CultureInfo.InvariantCulture, out value)) + { + index++; + Value = (ushort)(value * factor); + return true; + } + + // Return value based on required flag + Value = _required ? null : ushort.MinValue; + return !_required; + } + } +} \ No newline at end of file diff --git a/MPF.ExecutionContexts/Data/UInt32Input.cs b/MPF.ExecutionContexts/Data/UInt32Input.cs new file mode 100644 index 00000000..c6afb746 --- /dev/null +++ b/MPF.ExecutionContexts/Data/UInt32Input.cs @@ -0,0 +1,83 @@ +using System.Globalization; + +namespace MPF.ExecutionContexts.Data +{ + /// + /// Represents an UInt32 flag with an optional trailing value + /// + public class UInt32Input : Input + { + #region Constructors + + /// + public UInt32Input(string name) + : base(name) { } + + /// + public UInt32Input(string name, bool required) + : base(name, required) { } + + /// + public UInt32Input(string shortName, string longName) + : base(shortName, longName) { } + + /// + public UInt32Input(string shortName, string longName, bool required) + : base(shortName, longName, required) { } + + #endregion + + /// + public override bool Process(string[] parts, ref int index) + { + // Check the parts array + if (parts.Length == 0) + return false; + + // Check the index + if (index < 0 || index >= parts.Length) + return false; + + // Check the name + if (parts[index] != Name && (_longName != null && parts[index] != _longName)) + return false; + + // Ensure the value exists + if (!DoesExist(parts, index + 1)) + { + Value = _required ? null : uint.MinValue; + return !_required; + } + + // If the next value is valid + if (uint.TryParse(parts[index + 1], out uint value)) + { + index++; + Value = value; + return true; + } + + // Try to process as a formatted string + string baseVal = ExtractFactorFromValue(parts[index + 1], out long factor); + if (uint.TryParse(baseVal, out value)) + { + index++; + Value = (uint)(value * factor); + return true; + } + + // Try to process as a hex string + string hexValue = RemoveHexIdentifier(baseVal); + if (uint.TryParse(hexValue, NumberStyles.AllowHexSpecifier, CultureInfo.InvariantCulture, out value)) + { + index++; + Value = (uint)(value * factor); + return true; + } + + // Return value based on required flag + Value = _required ? null : uint.MinValue; + return !_required; + } + } +} \ No newline at end of file diff --git a/MPF.ExecutionContexts/Data/UInt64Input.cs b/MPF.ExecutionContexts/Data/UInt64Input.cs new file mode 100644 index 00000000..7cfb8801 --- /dev/null +++ b/MPF.ExecutionContexts/Data/UInt64Input.cs @@ -0,0 +1,83 @@ +using System.Globalization; + +namespace MPF.ExecutionContexts.Data +{ + /// + /// Represents an UInt64 flag with an optional trailing value + /// + public class UInt64Input : Input + { + #region Constructors + + /// + public UInt64Input(string name) + : base(name) { } + + /// + public UInt64Input(string name, bool required) + : base(name, required) { } + + /// + public UInt64Input(string shortName, string longName) + : base(shortName, longName) { } + + /// + public UInt64Input(string shortName, string longName, bool required) + : base(shortName, longName, required) { } + + #endregion + + /// + public override bool Process(string[] parts, ref int index) + { + // Check the parts array + if (parts.Length == 0) + return false; + + // Check the index + if (index < 0 || index >= parts.Length) + return false; + + // Check the name + if (parts[index] != Name && (_longName != null && parts[index] != _longName)) + return false; + + // Ensure the value exists + if (!DoesExist(parts, index + 1)) + { + Value = _required ? null : ulong.MinValue; + return !_required; + } + + // If the next value is valid + if (ulong.TryParse(parts[index + 1], out ulong value)) + { + index++; + Value = value; + return true; + } + + // Try to process as a formatted string + string baseVal = ExtractFactorFromValue(parts[index + 1], out long factor); + if (ulong.TryParse(baseVal, out value)) + { + index++; + Value = (ulong)(value * factor); + return true; + } + + // Try to process as a hex string + string hexValue = RemoveHexIdentifier(baseVal); + if (ulong.TryParse(hexValue, NumberStyles.AllowHexSpecifier, CultureInfo.InvariantCulture, out value)) + { + index++; + Value = (ulong)(value * factor); + return true; + } + + // Return value based on required flag + Value = _required ? null : ulong.MinValue; + return !_required; + } + } +} \ No newline at end of file diff --git a/MPF.ExecutionContexts/Data/UInt8Input.cs b/MPF.ExecutionContexts/Data/UInt8Input.cs new file mode 100644 index 00000000..eb847466 --- /dev/null +++ b/MPF.ExecutionContexts/Data/UInt8Input.cs @@ -0,0 +1,83 @@ +using System.Globalization; + +namespace MPF.ExecutionContexts.Data +{ + /// + /// Represents an UInt8 flag with an optional trailing value + /// + public class UInt8Input : Input + { + #region Constructors + + /// + public UInt8Input(string name) + : base(name) { } + + /// + public UInt8Input(string name, bool required) + : base(name, required) { } + + /// + public UInt8Input(string shortName, string longName) + : base(shortName, longName) { } + + /// + public UInt8Input(string shortName, string longName, bool required) + : base(shortName, longName, required) { } + + #endregion + + /// + public override bool Process(string[] parts, ref int index) + { + // Check the parts array + if (parts.Length == 0) + return false; + + // Check the index + if (index < 0 || index >= parts.Length) + return false; + + // Check the name + if (parts[index] != Name && (_longName != null && parts[index] != _longName)) + return false; + + // Ensure the value exists + if (!DoesExist(parts, index + 1)) + { + Value = _required ? null : byte.MinValue; + return !_required; + } + + // If the next value is valid + if (byte.TryParse(parts[index + 1], out byte value)) + { + index++; + Value = value; + return true; + } + + // Try to process as a formatted string + string baseVal = ExtractFactorFromValue(parts[index + 1], out long factor); + if (byte.TryParse(baseVal, out value)) + { + index++; + Value = (byte)(value * factor); + return true; + } + + // Try to process as a hex string + string hexValue = RemoveHexIdentifier(baseVal); + if (byte.TryParse(hexValue, NumberStyles.AllowHexSpecifier, CultureInfo.InvariantCulture, out value)) + { + index++; + Value = (byte)(value * factor); + return true; + } + + // Return value based on required flag + Value = _required ? null : byte.MinValue; + return !_required; + } + } +} \ No newline at end of file diff --git a/MPF.ExecutionContexts/Input.cs b/MPF.ExecutionContexts/Input.cs deleted file mode 100644 index 818c67b6..00000000 --- a/MPF.ExecutionContexts/Input.cs +++ /dev/null @@ -1,753 +0,0 @@ -using System; -using System.Globalization; - -namespace MPF.ExecutionContexts -{ - /// - /// Indicates the input type - /// - public enum InputType - { - None, - Flag, - Boolean, - Int8, - UInt8, - Int16, - UInt16, - Int32, - UInt32, - Int64, - UInt64, - String, - } - - /// - /// Represents a single input for an execution context - /// - public class Input - { - #region Properties - - /// - /// Input type for parsing - /// - public readonly InputType InputType; - - /// - /// Primary name for the input - /// - public readonly string Name; - - /// - /// Verbose name for the input - /// - private readonly string? _longName; - - /// - /// Indicates if the value following is required or not - /// - private readonly bool _required; - - #endregion - - #region Constructors - - /// Type of input for parsing - /// Flag name / value - public Input(InputType type, string name) - { - InputType = type; - Name = name; - _longName = null; - _required = true; - } - - /// Type of input for parsing - /// Flag name / value - /// Indicates if a following value is required - public Input(InputType type, string name, bool required) - { - InputType = type; - Name = name; - _longName = null; - _required = required; - } - - /// Type of input for parsing - /// Flag name / value - /// Verbose flag name / value - public Input(InputType type, string shortName, string longName) - { - InputType = type; - Name = shortName; - _longName = longName; - _required = true; - } - - /// Type of input for parsing - /// Flag name / value - /// Verbose flag name / value - /// Indicates if a following value is required - public Input(InputType type, string shortName, string longName, bool required) - { - InputType = type; - Name = shortName; - _longName = longName; - _required = required; - } - - #endregion - - #region Processors - - /// - /// Process the input as a flag - /// - /// Parts array to be referenced - /// Reference to the position in the parts - /// True if the flag was set, false otherwise - public bool ProcessAsFlag(string[] parts, ref int index) - { - // Check the input type - if (InputType != InputType.Flag) - return false; - - // Check the parts array - if (parts.Length == 0) - return false; - - // Check the index - if (index < 0 || index >= parts.Length) - return false; - - // Check the name - if (parts[index] == Name || (_longName != null && parts[index] == _longName)) - return true; - - return false; - } - - /// - /// Process the input as a boolean - /// - /// Parts array to be referenced - /// Reference to the position in the parts - /// Boolean value if set, null otherwise - public bool? ProcessAsBoolean(string[] parts, ref int index) - { - // Check the input type - if (InputType != InputType.Boolean) - return null; - - // Check the parts array - if (parts == null || parts.Length == 0) - return null; - - // Check the index - if (index < 0 || index >= parts.Length) - return null; - - // Check the name - if (parts[index] == Name || (_longName != null && parts[index] == _longName)) - { - // Ensure the value exists - if (!DoesExist(parts, index + 1)) - return _required ? null : true; - - // If the next value is valid - if (!bool.TryParse(parts[index + 1], out bool value)) - return _required ? null : true; - - index++; - return value; - } - - return null; - } - - /// - /// Process the input as an Int8 - /// - /// Parts array to be referenced - /// Reference to the position in the parts - /// Int8 value if set, minimum value if not required and missing, null otherwise - public sbyte? ProcessAsInt8(string[] parts, ref int index) - { - // Check the input type - if (InputType != InputType.Int8) - return null; - - // Check the parts array - if (parts == null || parts.Length == 0) - return null; - - // Check the index - if (index < 0 || index >= parts.Length) - return null; - - // Check the name - if (parts[index] == Name || (_longName != null && parts[index] == _longName)) - { - // Ensure the value exists - if (!DoesExist(parts, index + 1)) - return _required ? null : sbyte.MinValue; - - // If the next value is valid - if (sbyte.TryParse(parts[index + 1], out sbyte value)) - { - index++; - return value; - } - - // Try to process as a formatted string - string baseVal = ExtractFactorFromValue(parts[index + 1], out long factor); - if (sbyte.TryParse(baseVal, out value)) - { - index++; - return (sbyte)(value * factor); - } - - // Try to process as a hex string - string hexValue = RemoveHexIdentifier(baseVal); - if (sbyte.TryParse(hexValue, NumberStyles.AllowHexSpecifier, CultureInfo.InvariantCulture, out value)) - { - index++; - return (sbyte)(value * factor); - } - - // Return value based on required flag - return _required ? null : sbyte.MinValue; - } - - return null; - } - - /// - /// Process the input as a UInt8 - /// - /// Parts array to be referenced - /// Reference to the position in the parts - /// UInt8 value if set, minimum value if not required and missing, null otherwise - public byte? ProcessAsUInt8(string[] parts, ref int index) - { - // Check the input type - if (InputType != InputType.UInt8) - return null; - - // Check the parts array - if (parts == null || parts.Length == 0) - return null; - - // Check the index - if (index < 0 || index >= parts.Length) - return null; - - // Check the name - if (parts[index] == Name || (_longName != null && parts[index] == _longName)) - { - // Ensure the value exists - if (!DoesExist(parts, index + 1)) - return _required ? null : byte.MinValue; - - // If the next value is valid - if (byte.TryParse(parts[index + 1], out byte value)) - { - index++; - return value; - } - - // Try to process as a formatted string - string baseVal = ExtractFactorFromValue(parts[index + 1], out long factor); - if (byte.TryParse(baseVal, out value)) - { - index++; - return (byte)(value * factor); - } - - // Try to process as a hex string - string hexValue = RemoveHexIdentifier(baseVal); - if (byte.TryParse(hexValue, NumberStyles.AllowHexSpecifier, CultureInfo.InvariantCulture, out value)) - { - index++; - return (byte)(value * factor); - } - - // Return value based on required flag - return _required ? null : byte.MinValue; - } - - return null; - } - - /// - /// Process the input as an Int16 - /// - /// Parts array to be referenced - /// Reference to the position in the parts - /// Int16 value if set, minimum value if not required and missing, null otherwise - public short? ProcessAsInt16(string[] parts, ref int index) - { - // Check the input type - if (InputType != InputType.Int16) - return null; - - // Check the parts array - if (parts == null || parts.Length == 0) - return null; - - // Check the index - if (index < 0 || index >= parts.Length) - return null; - - // Check the name - if (parts[index] == Name || (_longName != null && parts[index] == _longName)) - { - // Ensure the value exists - if (!DoesExist(parts, index + 1)) - return _required ? null : short.MinValue; - - // If the next value is valid - if (short.TryParse(parts[index + 1], out short value)) - { - index++; - return value; - } - - // Try to process as a formatted string - string baseVal = ExtractFactorFromValue(parts[index + 1], out long factor); - if (short.TryParse(baseVal, out value)) - { - index++; - return (short)(value * factor); - } - - // Try to process as a hex string - string hexValue = RemoveHexIdentifier(baseVal); - if (short.TryParse(hexValue, NumberStyles.AllowHexSpecifier, CultureInfo.InvariantCulture, out value)) - { - index++; - return (short)(value * factor); - } - - // Return value based on required flag - return _required ? null : short.MinValue; - } - - return null; - } - - /// - /// Process the input as a UInt16 - /// - /// Parts array to be referenced - /// Reference to the position in the parts - /// UInt16 value if set, minimum value if not required and missing, null otherwise - public ushort? ProcessAsUInt16(string[] parts, ref int index) - { - // Check the input type - if (InputType != InputType.UInt16) - return null; - - // Check the parts array - if (parts == null || parts.Length == 0) - return null; - - // Check the index - if (index < 0 || index >= parts.Length) - return null; - - // Check the name - if (parts[index] == Name || (_longName != null && parts[index] == _longName)) - { - // Ensure the value exists - if (!DoesExist(parts, index + 1)) - return _required ? null : ushort.MinValue; - - // If the next value is valid - if (ushort.TryParse(parts[index + 1], out ushort value)) - { - index++; - return value; - } - - // Try to process as a formatted string - string baseVal = ExtractFactorFromValue(parts[index + 1], out long factor); - if (ushort.TryParse(baseVal, out value)) - { - index++; - return (ushort)(value * factor); - } - - // Try to process as a hex string - string hexValue = RemoveHexIdentifier(baseVal); - if (ushort.TryParse(hexValue, NumberStyles.AllowHexSpecifier, CultureInfo.InvariantCulture, out value)) - { - index++; - return (ushort)(value * factor); - } - - // Return value based on required flag - return _required ? null : ushort.MinValue; - } - - return null; - } - - /// - /// Process the input as an Int32 - /// - /// Parts array to be referenced - /// Reference to the position in the parts - /// Int32 value if set, minimum value if not required and missing, null otherwise - public int? ProcessAsInt32(string[] parts, ref int index) - { - // Check the input type - if (InputType != InputType.Int32) - return null; - - // Check the parts array - if (parts == null || parts.Length == 0) - return null; - - // Check the index - if (index < 0 || index >= parts.Length) - return null; - - // Check the name - if (parts[index] == Name || (_longName != null && parts[index] == _longName)) - { - // Ensure the value exists - if (!DoesExist(parts, index + 1)) - return _required ? null : int.MinValue; - - // If the next value is valid - if (int.TryParse(parts[index + 1], out int value)) - { - index++; - return value; - } - - // Try to process as a formatted string - string baseVal = ExtractFactorFromValue(parts[index + 1], out long factor); - if (int.TryParse(baseVal, out value)) - { - index++; - return (int)(value * factor); - } - - // Try to process as a hex string - string hexValue = RemoveHexIdentifier(baseVal); - if (int.TryParse(hexValue, NumberStyles.AllowHexSpecifier, CultureInfo.InvariantCulture, out value)) - { - index++; - return (int)(value * factor); - } - - // Return value based on required flag - return _required ? null : int.MinValue; - } - - return null; - } - - /// - /// Process the input as a UInt32 - /// - /// Parts array to be referenced - /// Reference to the position in the parts - /// UInt32 value if set, minimum value if not required and missing, null otherwise - public uint? ProcessAsUInt32(string[] parts, ref int index) - { - // Check the input type - if (InputType != InputType.UInt32) - return null; - - // Check the parts array - if (parts == null || parts.Length == 0) - return null; - - // Check the index - if (index < 0 || index >= parts.Length) - return null; - - // Check the name - if (parts[index] == Name || (_longName != null && parts[index] == _longName)) - { - // Ensure the value exists - if (!DoesExist(parts, index + 1)) - return _required ? null : uint.MinValue; - - // If the next value is valid - if (uint.TryParse(parts[index + 1], out uint value)) - { - index++; - return value; - } - - // Try to process as a formatted string - string baseVal = ExtractFactorFromValue(parts[index + 1], out long factor); - if (uint.TryParse(baseVal, out value)) - { - index++; - return (uint)(value * factor); - } - - // Try to process as a hex string - string hexValue = RemoveHexIdentifier(baseVal); - if (uint.TryParse(hexValue, NumberStyles.AllowHexSpecifier, CultureInfo.InvariantCulture, out value)) - { - index++; - return (uint)(value * factor); - } - - // Return value based on required flag - return _required ? null : uint.MinValue; - } - - return null; - } - - /// - /// Process the input as an Int64 - /// - /// Parts array to be referenced - /// Reference to the position in the parts - /// Int64 value if set, minimum value if not required and missing, null otherwise - public long? ProcessAsInt64(string[] parts, ref int index) - { - // Check the input type - if (InputType != InputType.Int64) - return null; - - // Check the parts array - if (parts == null || parts.Length == 0) - return null; - - // Check the index - if (index < 0 || index >= parts.Length) - return null; - - // Check the name - if (parts[index] == Name || (_longName != null && parts[index] == _longName)) - { - // Ensure the value exists - if (!DoesExist(parts, index + 1)) - return _required ? null : long.MinValue; - - // If the next value is valid - if (long.TryParse(parts[index + 1], out long value)) - { - index++; - return value; - } - - // Try to process as a formatted string - string baseVal = ExtractFactorFromValue(parts[index + 1], out long factor); - if (long.TryParse(baseVal, out value)) - { - index++; - return (long)(value * factor); - } - - // Try to process as a hex string - string hexValue = RemoveHexIdentifier(baseVal); - if (long.TryParse(hexValue, NumberStyles.AllowHexSpecifier, CultureInfo.InvariantCulture, out value)) - { - index++; - return (long)(value * factor); - } - - // Return value based on required flag - return _required ? null : long.MinValue; - } - - return null; - } - - /// - /// Process the input as a UInt64 - /// - /// Parts array to be referenced - /// Reference to the position in the parts - /// UInt64 value if set, minimum value if not required and missing, null otherwise - public ulong? ProcessAsUInt64(string[] parts, ref int index) - { - // Check the input type - if (InputType != InputType.UInt64) - return null; - - // Check the parts array - if (parts == null || parts.Length == 0) - return null; - - // Check the index - if (index < 0 || index >= parts.Length) - return null; - - // Check the name - if (parts[index] == Name || (_longName != null && parts[index] == _longName)) - { - // Ensure the value exists - if (!DoesExist(parts, index + 1)) - return _required ? null : ulong.MinValue; - - // If the next value is valid - if (ulong.TryParse(parts[index + 1], out ulong value)) - { - index++; - return value; - } - - // Try to process as a formatted string - string baseVal = ExtractFactorFromValue(parts[index + 1], out long factor); - if (ulong.TryParse(baseVal, out value)) - { - index++; - return (ulong)(value * (ulong)factor); - } - - // Try to process as a hex string - string hexValue = RemoveHexIdentifier(baseVal); - if (ulong.TryParse(hexValue, NumberStyles.AllowHexSpecifier, CultureInfo.InvariantCulture, out value)) - { - index++; - return (ulong)(value * (ulong)factor); - } - - // Return value based on required flag - return _required ? null : ulong.MinValue; - } - - return null; - } - - /// - /// Process the input as a UInt64 - /// - /// Parts array to be referenced - /// Reference to the position in the parts - /// String value if set, empty value if not required and missing, null otherwise - public string? ProcessAsString(string[] parts, ref int index) - { - // Check the input type - if (InputType != InputType.String) - return null; - - // Check the parts array - if (parts == null || parts.Length == 0) - return null; - - // Check the index - if (index < 0 || index >= parts.Length) - return null; - - // Check the name - if (parts[index] == Name || (_longName != null && parts[index] == _longName)) - { - // Ensure the value exists - if (!DoesExist(parts, index + 1)) - return _required ? null : string.Empty; - - index++; - return parts[index]; - } - - return null; - } - - #endregion - - #region Helpers - - /// - /// Returns whether or not the selected item exists - /// - /// Parts array to be referenced - /// Current index - /// True if the next item exists, false otherwise - internal static bool DoesExist(string[] parts, int index) - => index >= 0 && index < parts.Length; - - /// - /// Get the trimmed value and multiplication factor from a value - /// - /// String value to treat as suffixed number - /// Trimmed value and multiplication factor - internal static string ExtractFactorFromValue(string value, out long factor) - { - value = value.Trim('"'); - factor = 1; - - // Characters - if (value.EndsWith("c", StringComparison.Ordinal)) - { - factor = 1; - value = value.TrimEnd('c'); - } - - // Words - else if (value.EndsWith("w", StringComparison.Ordinal)) - { - factor = 2; - value = value.TrimEnd('w'); - } - - // Double Words - else if (value.EndsWith("d", StringComparison.Ordinal)) - { - factor = 4; - value = value.TrimEnd('d'); - } - - // Quad Words - else if (value.EndsWith("q", StringComparison.Ordinal)) - { - factor = 8; - value = value.TrimEnd('q'); - } - - // Kilobytes - else if (value.EndsWith("k", StringComparison.Ordinal)) - { - factor = 1024; - value = value.TrimEnd('k'); - } - - // Megabytes - else if (value.EndsWith("M", StringComparison.Ordinal)) - { - factor = 1024 * 1024; - value = value.TrimEnd('M'); - } - - // Gigabytes - else if (value.EndsWith("G", StringComparison.Ordinal)) - { - factor = 1024 * 1024 * 1024; - value = value.TrimEnd('G'); - } - - return value; - } - - /// - /// Removes a leading 0x if it exists, case insensitive - /// - /// String with removed leading 0x - /// - internal static string RemoveHexIdentifier(string value) - { - if (value.Length <= 2) - return value; - if (value[0] != '0') - return value; - if (value[1] != 'x' && value[1] != 'X') - return value; - - return value.Substring(2); - } - - #endregion - } -} \ No newline at end of file