public void SplitsEmptyStringsIntoNothing() { var value = string.Empty; var enumerator = new SpanSplitEnumerator(value); Assert.False(enumerator.MoveNext()); }
/// <summary> /// Searches the command tree for a command that matches the shape of the given command name string, and its /// named parameters. In this case, positional parameters are not supported; they are matched against their /// in-source names instead. /// </summary> /// <param name="commandNameString">The named command string.</param> /// <param name="namedParameters">The named parameters.</param> /// <param name="tokenizerOptions">The tokenizer options to use.</param> /// <param name="searchOptions">A set of search options.</param> /// <returns>The matching command nodes.</returns> public IEnumerable <BoundCommandNode> Search ( ReadOnlySpan <char> commandNameString, IReadOnlyDictionary <string, IReadOnlyList <string> > namedParameters, TokenizerOptions?tokenizerOptions = null, TreeSearchOptions?searchOptions = null ) { tokenizerOptions ??= new TokenizerOptions(); searchOptions ??= new TreeSearchOptions(); var splitEnumerator = new SpanSplitEnumerator(commandNameString, tokenizerOptions); var matchingNodes = Search(this.Root, splitEnumerator, searchOptions); var boundNodes = matchingNodes .Select ( c => ( IsSuccess: c.TryBind(namedParameters, out var boundCommandNode, searchOptions), BoundCommandNode: boundCommandNode ) ) .Where(kvp => kvp.IsSuccess) .Select(kvp => kvp.BoundCommandNode !); return(boundNodes); }
/// <summary> /// Creates a new pattern scan target given a string representation of a pattern. /// </summary> /// <param name="stringPattern"> /// The pattern to look for inside the given region. /// Example: "11 22 33 ?? 55". /// Key: ?? represents a byte that should be ignored, anything else if a hex byte. i.e. 11 represents 0x11, 1F represents 0x1F. /// </param> public SimplePatternScanData(string stringPattern) { #if SPAN_API var enumerator = new SpanSplitEnumerator <char>(stringPattern, ' '); #else var enumerator = new SpanSplitEnumerator <char>(new ReadOnlySpan <char>(stringPattern.ToCharArray()), ' '); #endif var questionMarkFlag = new ReadOnlySpan <char>(_maskIgnore); lock (_buildLock) { _maskBuilder.Clear(); _bytes.Clear(); while (enumerator.MoveNext()) { if (enumerator.Current.Equals(questionMarkFlag, StringComparison.Ordinal)) { _maskBuilder.Add(0x0); } else { #if SPAN_API _bytes.Add(byte.Parse(enumerator.Current, NumberStyles.AllowHexSpecifier)); #else _bytes.Add(byte.Parse(enumerator.Current.ToString(), NumberStyles.AllowHexSpecifier)); #endif _maskBuilder.Add(0x1); } } Mask = _maskBuilder.ToArray(); Bytes = _bytes.ToArray(); } }
public void StringSplitterEmpty() { string pattern = ""; var splitEnumerator = new SpanSplitEnumerator <char>(pattern.ToCharArray(), ' '); Assert.True(splitEnumerator.MoveNext()); Assert.Equal("", splitEnumerator.Current.ToString()); Assert.False(splitEnumerator.MoveNext()); }
public void SplitsSingleQuotedTermIntoSingleSegment() { var value = "\"one term\""; var enumerator = new SpanSplitEnumerator(value); Assert.True(enumerator.MoveNext()); Assert.Equal(value, enumerator.Current.ToString()); Assert.False(enumerator.MoveNext()); }
public void SplitsSingleWordIntoSingleSegment() { var value = "bunt"; var enumerator = new SpanSplitEnumerator(value); Assert.True(enumerator.MoveNext()); Assert.Equal(value, enumerator.Current.ToString()); Assert.False(enumerator.MoveNext()); }
/// <summary> /// Initializes a new instance of the <see cref="TokenizingEnumerator"/> struct. /// </summary> /// <param name="value">The value to tokenize.</param> /// <param name="tokenizerOptions">The tokenizer options.</param> public TokenizingEnumerator(ReadOnlySpan <char> value, TokenizerOptions?tokenizerOptions = null) { _tokenizerOptions = tokenizerOptions ?? new TokenizerOptions(); _isInCombinedShortNameSegment = default; _segment = default; _splitEnumerator = new SpanSplitEnumerator(value, _tokenizerOptions); _current = default; }
private static void AssertEqual <T>(T[][] items, ReadOnlySpan <T> orig, SpanSplitEnumerator <T> source) where T : IEquatable <T> { foreach (var item in items) { Assert.True(source.MoveNext()); var slice = orig[source.Current]; Assert.Equal(item, slice.ToArray()); } Assert.False(source.MoveNext()); }
public SpanSplitEnumerator <char> SpanSplit() { var enumerator = new SpanSplitEnumerator <char>(_pattern, ' '); while (enumerator.MoveNext()) { } return(enumerator); }
public void SplitsMultipleWordsIntoMultipleSegments() { var value = "a b c d e f g"; var enumerator = new SpanSplitEnumerator(value); for (var i = 0; i < 7; i++) { Assert.True(enumerator.MoveNext()); Assert.Equal(value[i * 2].ToString(), enumerator.Current.ToString()); } Assert.False(enumerator.MoveNext()); }
/// <summary> /// Performs a depth-first search of the given node. /// </summary> /// <param name="parentNode">The node.</param> /// <param name="enumerator">The splitting enumerator.</param> /// <param name="searchOptions">A set of search options.</param> /// <returns>The matching nodes.</returns> private IEnumerable <CommandNode> Search ( IParentNode parentNode, SpanSplitEnumerator enumerator, TreeSearchOptions searchOptions ) { var commandNodes = new List <CommandNode>(); foreach (var child in parentNode.Children) { if (!IsNodeMatch(child, enumerator, searchOptions)) { continue; } switch (child) { case CommandNode commandNode: { commandNodes.Add(commandNode); break; } case IParentNode groupNode: { // Consume the token if (!enumerator.MoveNext()) { // No more tokens, so we can't continue searching return(commandNodes); } var nestedResults = Search(groupNode, enumerator, searchOptions); commandNodes.AddRange(nestedResults); continue; } default: { throw new InvalidOperationException ( "Unknown node type encountered; tree is invalid and the search cannot continue." ); } } } return(commandNodes); }
public static int Last <T>(this SpanSplitEnumerator <T> enumerator, out ReadOnlySpan <T> last) where T : IEquatable <T> { int cnt = 0; last = null; while (enumerator.MoveNext()) { last = enumerator.Current; cnt++; } return(cnt); }
public static void DefaultSpanSplitEnumeratorBehavior() { var charSpanEnumerator = new SpanSplitEnumerator <string>(); Assert.Equal(new Range(0, 0), charSpanEnumerator.Current); Assert.False(charSpanEnumerator.MoveNext()); // Implicit DoesNotThrow assertion charSpanEnumerator.GetEnumerator(); var stringSpanEnumerator = new SpanSplitEnumerator <string>(); Assert.Equal(new Range(0, 0), stringSpanEnumerator.Current); Assert.False(stringSpanEnumerator.MoveNext()); stringSpanEnumerator.GetEnumerator(); }
public void StringSplitterNormal() { string pattern = "11 22 33 ?? 55"; string[] splitSegments = { "11", "22", "33", "??", "55" }; // Note: ToCharArray can be omitted in .NET Standard 2.1 and Core 3.0 var splitEnumerator = new SpanSplitEnumerator <char>(pattern.ToCharArray(), ' '); for (int x = 0; x < splitSegments.Length; x++) { Assert.True(splitEnumerator.MoveNext()); Assert.Equal(splitSegments[x], splitEnumerator.Current.ToString()); } Assert.False(splitEnumerator.MoveNext()); }
public static void ValidateArguments_OverloadWithROSSeparator() { // Default buffer ReadOnlySpan <char> buffer = default; SpanSplitEnumerator <char> enumerator = buffer.Split(default(char)); Assert.True(enumerator.MoveNext()); Assert.Equal(enumerator.Current, new Range(0, 0)); Assert.False(enumerator.MoveNext()); enumerator = buffer.Split(' '); Assert.True(enumerator.MoveNext()); Assert.Equal(enumerator.Current, new Range(0, 0)); Assert.False(enumerator.MoveNext()); // Empty buffer buffer = ""; enumerator = buffer.Split(default(char)); Assert.True(enumerator.MoveNext()); Assert.Equal(enumerator.Current, new Range(0, 0)); Assert.False(enumerator.MoveNext()); enumerator = buffer.Split(' '); Assert.True(enumerator.MoveNext()); Assert.Equal(enumerator.Current, new Range(0, 0)); Assert.False(enumerator.MoveNext()); // Single whitespace buffer buffer = " "; enumerator = buffer.Split(default(char)); Assert.True(enumerator.MoveNext()); Assert.False(enumerator.MoveNext()); enumerator = buffer.Split(' '); Assert.Equal(new Range(0, 0), enumerator.Current); Assert.True(enumerator.MoveNext()); Assert.Equal(new Range(0, 0), enumerator.Current); Assert.True(enumerator.MoveNext()); Assert.Equal(new Range(1, 1), enumerator.Current); Assert.False(enumerator.MoveNext()); }
/// <summary> /// Determines whether a node matches the current state of the enumerator. /// </summary> /// <param name="node">The node.</param> /// <param name="enumerator">The tokenizer.</param> /// <param name="searchOptions">A set of search options.</param> /// <returns>true if the node matches; otherwise, false.</returns> private bool IsNodeMatch(IChildNode node, SpanSplitEnumerator enumerator, TreeSearchOptions searchOptions) { if (!enumerator.MoveNext()) { return(false); } if (enumerator.Current.Equals(node.Key, searchOptions.KeyComparison)) { return(true); } foreach (var alias in node.Aliases) { if (enumerator.Current.Equals(alias, searchOptions.KeyComparison)) { return(true); } } return(false); }
public static void ValidateArguments_OverloadWithoutSeparator() { ReadOnlySpan <char> buffer = default; SpanSplitEnumerator <char> enumerator = buffer.Split(); Assert.True(enumerator.MoveNext()); Assert.Equal(new Range(0, 0), enumerator.Current); Assert.False(enumerator.MoveNext()); buffer = ""; enumerator = buffer.Split(); Assert.True(enumerator.MoveNext()); Assert.Equal(new Range(0, 0), enumerator.Current); Assert.False(enumerator.MoveNext()); buffer = " "; enumerator = buffer.Split(); Assert.True(enumerator.MoveNext()); Assert.Equal(new Range(0, 0), enumerator.Current); Assert.True(enumerator.MoveNext()); Assert.Equal(new Range(1, 1), enumerator.Current); Assert.False(enumerator.MoveNext()); }
public static void ValidateArguments_OverloadWithStringSeparator() { // Default buffer ReadOnlySpan <char> buffer = default; SpanSplitEnumerator <char> enumerator = buffer.Split(null); // null is treated as empty string Assert.True(enumerator.MoveNext()); Assert.Equal(enumerator.Current, new Range(0, 0)); Assert.False(enumerator.MoveNext()); enumerator = buffer.Split(""); Assert.True(enumerator.MoveNext()); Assert.Equal(enumerator.Current, new Range(0, 0)); Assert.False(enumerator.MoveNext()); enumerator = buffer.Split(" "); Assert.True(enumerator.MoveNext()); Assert.Equal(enumerator.Current, new Range(0, 0)); Assert.False(enumerator.MoveNext()); // Empty buffer buffer = ""; enumerator = buffer.Split(null); Assert.True(enumerator.MoveNext()); Assert.Equal(enumerator.Current, new Range(0, 0)); Assert.False(enumerator.MoveNext()); enumerator = buffer.Split(""); Assert.True(enumerator.MoveNext()); Assert.Equal(enumerator.Current, new Range(0, 0)); Assert.False(enumerator.MoveNext()); enumerator = buffer.Split(" "); Assert.True(enumerator.MoveNext()); Assert.Equal(enumerator.Current, new Range(0, 0)); Assert.False(enumerator.MoveNext()); // Single whitespace buffer buffer = " "; enumerator = buffer.Split(null); // null is treated as empty string Assert.True(enumerator.MoveNext()); Assert.Equal(enumerator.Current, new Range(0, 0)); Assert.True(enumerator.MoveNext()); Assert.Equal(enumerator.Current, new Range(1, 1)); Assert.False(enumerator.MoveNext()); enumerator = buffer.Split(""); Assert.True(enumerator.MoveNext()); Assert.Equal(enumerator.Current, new Range(0, 0)); Assert.True(enumerator.MoveNext()); Assert.Equal(enumerator.Current, new Range(1, 1)); Assert.False(enumerator.MoveNext()); enumerator = buffer.Split(" "); Assert.Equal(enumerator.Current, new Range(0, 0)); Assert.True(enumerator.MoveNext()); Assert.Equal(enumerator.Current, new Range(0, 0)); Assert.True(enumerator.MoveNext()); Assert.Equal(enumerator.Current, new Range(1, 1)); Assert.False(enumerator.MoveNext()); }