forked from thalber/Atmo
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathArgSet.cs
133 lines (122 loc) · 3.52 KB
/
ArgSet.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
using System.Collections;
using Atmo.Body;
namespace Atmo.Data;
/// <summary>
/// A set of <see cref="Arg"/>s. Implements IList, so can be indexed by position (<see cref="this[int]"/>), as well as <see cref="Arg"/>'s name <see cref="this[string[]]"/>.
/// <para>
/// ArgSets can be created from string arrays, explicitly (<see cref="ArgSet(string[], bool)"/>)
/// or implicitly (a cast that invokes the same constructor). When instantiating, ArgSet creates
/// a dictionary-based index of named args. All args are created with linkage.
/// </para>
/// <para>
/// This class is typically used by delegates in <see cref="Atmo.API"/>,
/// although nothing stops a user from applying it in an unrelated context.
/// Use of ArgSet over simple string arrays was enforced to ensure
/// consistent argument syntax in various <see cref="Happen"/> actions.
/// </para>
/// </summary>
public sealed class ArgSet : IList<Arg>
{
/// <summary>
/// Creates the instance from a given array of raw string arguments.
/// </summary>
/// <param name="rawargs"></param>
/// <param name="linkage">Whether to parse argument names and variable links on instantiation. On by default.</param>
public ArgSet(string[] rawargs, bool linkage = true)
{
for (int i = 0; i < rawargs.Length; i++)
{
Arg newarg = new(
rawargs[i] ?? string.Empty,
linkage);
_args.Add(newarg);
if (newarg.Name is not null) { _named.Add(newarg.Name, newarg); }
}
}
private readonly List<Arg> _args = new();
private readonly Dictionary<string, Arg> _named = new();
/// <summary>
/// Checks given names and returns first matching named argument, if any.
/// <para>
/// This indexer can be used to easily fetch an argument that may have variant names, for example:
/// <code>
/// ArgSet set = myStringArray;
/// Arg
/// cooldown = set["cd", "cooldown"] ?? 80,
/// power = set["pow", "power"] ?? 0.3f;
/// </code>
/// </para>
/// </summary>
/// <param name="names">Names to check</param>
/// <returns>An <see cref="Arg"/> if one is found, null otherwise.</returns>
public Arg? this[params string[] names]
{
get
{
foreach (string? name in names) if (_named.TryGetValue(name, out Arg val)) return val;
return null;
}
}
#pragma warning disable CS1591
#region interface
/// <summary>
/// Simple order-based indexing. For non-throwing alternative, you can use <see cref="Utils.AtOr{T}(IList{T}, int, T)"/>.
/// </summary>
/// <param name="index"></param>
/// <returns></returns>
public Arg this[int index] { get => _args[index]; set => _args[index] = value; }
public int Count
=> _args.Count;
public bool IsReadOnly
=> false;
public void Add(Arg item)
{
_args.Add(item);
}
public void Clear()
{
_args.Clear();
}
public bool Contains(Arg item)
{
return _args.Contains(item);
}
public void CopyTo(Arg[] array, int arrayIndex)
{
_args.CopyTo(array, arrayIndex);
}
public IEnumerator<Arg> GetEnumerator()
{
return _args.GetEnumerator();
}
public int IndexOf(Arg item)
{
return _args.IndexOf(item);
}
public void Insert(int index, Arg item)
{
_args.Insert(index, item);
}
public bool Remove(Arg item)
{
return _args.Remove(item);
}
public void RemoveAt(int index)
{
_args.RemoveAt(index);
}
IEnumerator IEnumerable.GetEnumerator()
{
return _args.GetEnumerator();
}
#endregion interface;
#pragma warning restore
/// <summary>
/// Creates a new ArgSet from a specified string array.
/// </summary>
/// <param name="raw"></param>
public static implicit operator ArgSet(string[] raw)
{
return new(raw);
}
}