mirror of
https://github.com/SabreTools/SabreTools.Matching.git
synced 2026-09-22 06:44:04 +00:00
Overhaul matching extensions
This commit is contained in:
@@ -17,37 +17,52 @@ namespace SabreTools.Matching
|
||||
/// <summary>
|
||||
/// Find all positions of one array in another, if possible, if possible
|
||||
/// </summary>
|
||||
public static List<int> FindAllPositions(this byte[] stack, byte[]? needle, int start = 0, int end = -1)
|
||||
/// <param name="stack">Byte array to search within</param>
|
||||
/// <param name="needle">Byte array representing the search value</param>
|
||||
/// <param name="start">Optional starting position in the stack, defaults to 0</param>
|
||||
/// <param name="end">Optional ending position in the stack, defaults to -1 (length of stack)</param>
|
||||
public static List<int> FindAllPositions(this byte[] stack, byte[] needle, int start = 0, int end = -1)
|
||||
{
|
||||
// Convert the needle to a nullable byte array
|
||||
byte?[]? nullableNeedle = null;
|
||||
if (needle != null)
|
||||
nullableNeedle = Array.ConvertAll(needle, b => (byte?)b);
|
||||
|
||||
byte?[] nullableNeedle = Array.ConvertAll(needle, b => (byte?)b);
|
||||
return FindAllPositions(stack, nullableNeedle, start, end);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Find all positions of one array in another, if possible, if possible
|
||||
/// </summary>
|
||||
public static List<int> FindAllPositions(this byte[] stack, byte?[]? needle, int start = 0, int end = -1)
|
||||
/// <param name="stack">Byte array to search within</param>
|
||||
/// <param name="needle">Byte array representing the search value</param>
|
||||
/// <param name="start">Optional starting position in the stack, defaults to 0</param>
|
||||
/// <param name="end">Optional ending position in the stack, defaults to -1 (length of stack)</param>
|
||||
public static List<int> FindAllPositions(this byte[] stack, byte?[] needle, int start = 0, int end = -1)
|
||||
{
|
||||
// Get the outgoing list
|
||||
List<int> positions = [];
|
||||
|
||||
// Initialize the loop variables
|
||||
int lastPosition = start;
|
||||
var matcher = new ContentMatch(needle, end: end);
|
||||
// Validate the start and end values
|
||||
if (start < 0 || start >= stack.Length)
|
||||
return positions;
|
||||
if (end < -1 || (end != -1 && end < start) || end > stack.Length)
|
||||
return positions;
|
||||
|
||||
// Loop over and get all positions
|
||||
while (true)
|
||||
// Normalize the end value, if necessary
|
||||
if (end == -1)
|
||||
end = stack.Length;
|
||||
|
||||
// Loop while there is data to check
|
||||
while (start < end)
|
||||
{
|
||||
matcher.Start = lastPosition;
|
||||
lastPosition = matcher.Match(stack, false);
|
||||
if (lastPosition < 0)
|
||||
// Create a new matcher for this segment
|
||||
var matcher = new ContentMatch(needle, start, end);
|
||||
|
||||
// Get the next matching position
|
||||
int position = matcher.Match(stack, reverse: false);
|
||||
if (position < 0)
|
||||
break;
|
||||
|
||||
positions.Add(lastPosition);
|
||||
// Append the position and reset the start index
|
||||
positions.Add(position);
|
||||
start = position;
|
||||
}
|
||||
|
||||
return positions;
|
||||
@@ -56,115 +71,111 @@ namespace SabreTools.Matching
|
||||
/// <summary>
|
||||
/// Find the first position of one array in another, if possible
|
||||
/// </summary>
|
||||
public static bool FirstPosition(this byte[] stack, byte[]? needle, out int position, int start = 0, int end = -1)
|
||||
/// <param name="stack">Byte array to search within</param>
|
||||
/// <param name="needle">Byte array representing the search value</param>
|
||||
/// <param name="start">Optional starting position in the stack, defaults to 0</param>
|
||||
/// <param name="end">Optional ending position in the stack, defaults to -1 (length of stack)</param>
|
||||
public static int FirstPosition(this byte[] stack, byte[] needle, int start = 0, int end = -1)
|
||||
{
|
||||
// Convert the needle to a nullable byte array
|
||||
byte?[]? nullableNeedle = null;
|
||||
if (needle != null)
|
||||
nullableNeedle = Array.ConvertAll(needle, b => (byte?)b);
|
||||
|
||||
return FirstPosition(stack, nullableNeedle, out position, start, end);
|
||||
byte?[] nullableNeedle = Array.ConvertAll(needle, b => (byte?)b);
|
||||
return FirstPosition(stack, nullableNeedle, start, end);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Find the first position of one array in another, if possible
|
||||
/// </summary>
|
||||
public static bool FirstPosition(this byte[] stack, byte?[]? needle, out int position, int start = 0, int end = -1)
|
||||
/// <param name="stack">Byte array to search within</param>
|
||||
/// <param name="needle">Byte array representing the search value</param>
|
||||
/// <param name="start">Optional starting position in the stack, defaults to 0</param>
|
||||
/// <param name="end">Optional ending position in the stack, defaults to -1 (length of stack)</param>
|
||||
public static int FirstPosition(this byte[] stack, byte?[] needle, int start = 0, int end = -1)
|
||||
{
|
||||
var matcher = new ContentMatch(needle, start, end);
|
||||
position = matcher.Match(stack, false);
|
||||
return position >= 0;
|
||||
return matcher.Match(stack, reverse: false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Find the last position of one array in another, if possible
|
||||
/// </summary>
|
||||
public static bool LastPosition(this byte[] stack, byte[]? needle, out int position, int start = 0, int end = -1)
|
||||
/// <param name="stack">Byte array to search within</param>
|
||||
/// <param name="needle">Byte array representing the search value</param>
|
||||
/// <param name="start">Optional starting position in the stack, defaults to 0</param>
|
||||
/// <param name="end">Optional ending position in the stack, defaults to -1 (length of stack)</param>
|
||||
public static int LastPosition(this byte[] stack, byte[] needle, int start = 0, int end = -1)
|
||||
{
|
||||
// Convert the needle to a nullable byte array
|
||||
byte?[]? nullableNeedle = null;
|
||||
if (needle != null)
|
||||
nullableNeedle = Array.ConvertAll(needle, b => (byte?)b);
|
||||
|
||||
return LastPosition(stack, nullableNeedle, out position, start, end);
|
||||
byte?[] nullableNeedle = Array.ConvertAll(needle, b => (byte?)b);
|
||||
return LastPosition(stack, nullableNeedle, start, end);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Find the last position of one array in another, if possible
|
||||
/// </summary>
|
||||
public static bool LastPosition(this byte[] stack, byte?[]? needle, out int position, int start = 0, int end = -1)
|
||||
/// <param name="stack">Byte array to search within</param>
|
||||
/// <param name="needle">Byte array representing the search value</param>
|
||||
/// <param name="start">Optional starting position in the stack, defaults to 0</param>
|
||||
/// <param name="end">Optional ending position in the stack, defaults to -1 (length of stack)</param>
|
||||
public static int LastPosition(this byte[] stack, byte?[] needle, int start = 0, int end = -1)
|
||||
{
|
||||
var matcher = new ContentMatch(needle, start, end);
|
||||
position = matcher.Match(stack, true);
|
||||
return position >= 0;
|
||||
return matcher.Match(stack, reverse: true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// See if a byte array starts with another
|
||||
/// Check if a byte array starts with another
|
||||
/// </summary>
|
||||
public static bool StartsWith(this byte[] stack, byte[]? needle, bool exact = false)
|
||||
/// <param name="stack">Byte array to search within</param>
|
||||
/// <param name="needle">Byte array representing the search value</param>
|
||||
public static bool StartsWith(this byte[] stack, byte[] needle)
|
||||
{
|
||||
// If we have any invalid inputs, we return false
|
||||
if (needle == null
|
||||
|| stack.Length == 0 || needle.Length == 0
|
||||
|| needle.Length > stack.Length
|
||||
|| (exact && stack.Length != needle.Length))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return FirstPosition(stack, needle, out int _, start: 0, end: 1);
|
||||
byte?[] nullableNeedle = Array.ConvertAll(needle, b => (byte?)b);
|
||||
return StartsWith(stack, nullableNeedle);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// See if a byte array starts with another
|
||||
/// Check if a byte array starts with another
|
||||
/// </summary>
|
||||
public static bool StartsWith(this byte[] stack, byte?[]? needle, bool exact = false)
|
||||
/// <param name="stack">Byte array to search within</param>
|
||||
/// <param name="needle">Byte array representing the search value</param>
|
||||
public static bool StartsWith(this byte[] stack, byte?[] needle)
|
||||
{
|
||||
// If we have any invalid inputs, we return false
|
||||
if (needle == null
|
||||
|| stack.Length == 0 || needle.Length == 0
|
||||
|| needle.Length > stack.Length
|
||||
|| (exact && stack.Length != needle.Length))
|
||||
{
|
||||
// If either the stack or needle are 0-length
|
||||
if (stack.Length == 0 || needle.Length == 0)
|
||||
return false;
|
||||
}
|
||||
|
||||
return FirstPosition(stack, needle, out int _, start: 0, end: 1);
|
||||
// If the needle is longer than the stack
|
||||
if (needle.Length > stack.Length)
|
||||
return false;
|
||||
|
||||
return FirstPosition(stack, needle, start: 0, end: 1) > -1;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// See if a byte array ends with another
|
||||
/// Check if a byte array ends with another
|
||||
/// </summary>
|
||||
public static bool EndsWith(this byte[] stack, byte[]? needle, bool exact = false)
|
||||
/// <param name="stack">Byte array to search within</param>
|
||||
/// <param name="needle">Byte array representing the search value</param>
|
||||
public static bool EndsWith(this byte[] stack, byte[] needle)
|
||||
{
|
||||
// If we have any invalid inputs, we return false
|
||||
if (needle == null
|
||||
|| stack.Length == 0 || needle.Length == 0
|
||||
|| needle.Length > stack.Length
|
||||
|| (exact && stack.Length != needle.Length))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return FirstPosition(stack, needle, out int _, start: stack.Length - needle.Length);
|
||||
byte?[] nullableNeedle = Array.ConvertAll(needle, b => (byte?)b);
|
||||
return EndsWith(stack, nullableNeedle);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// See if a byte array ends with another
|
||||
/// Check if a byte array ends with another
|
||||
/// </summary>
|
||||
public static bool EndsWith(this byte[] stack, byte?[]? needle, bool exact = false)
|
||||
/// <param name="stack">Byte array to search within</param>
|
||||
/// <param name="needle">Byte array representing the search value</param>
|
||||
public static bool EndsWith(this byte[] stack, byte?[] needle)
|
||||
{
|
||||
// If we have any invalid inputs, we return false
|
||||
if (needle == null
|
||||
|| stack.Length == 0 || needle.Length == 0
|
||||
|| needle.Length > stack.Length
|
||||
|| (exact && stack.Length != needle.Length))
|
||||
{
|
||||
// If either the stack or needle are 0-length
|
||||
if (stack.Length == 0 || needle.Length == 0)
|
||||
return false;
|
||||
}
|
||||
|
||||
return FirstPosition(stack, needle, out int _, start: stack.Length - needle.Length);
|
||||
// If the needle is longer than the stack
|
||||
if (needle.Length > stack.Length)
|
||||
return false;
|
||||
|
||||
return FirstPosition(stack, needle, start: stack.Length - needle.Length) > -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user