using System;
using System.Collections.Generic;
using SabreTools.Logging;
namespace SabreTools.Filtering
{
///
/// Represents the filtering operations that need to be performed on a set of items, usually a DAT
///
public abstract class Filter
{
#region Logging
///
/// Logging object
///
protected Logger logger;
#endregion
#region Constructors
///
/// Constructor
///
public Filter()
{
logger = new Logger(this);
}
#endregion
#region Filter Population
///
/// Split the parts of a filter statement
///
/// key:value where ~key/!key is negated
protected (string field, string value, bool negate) ProcessFilterPair(string filter)
{
// If we don't even have a possible filter pair
if (!filter.Contains(":"))
{
logger.Warning($"'{filter}` is not a valid filter string. Valid filter strings are of the form 'key:value'. Please refer to README.1ST or the help feature for more details.");
return (null, null, false);
}
string filterTrimmed = filter.Trim('"', ' ', '\t');
bool negate = filterTrimmed.StartsWith("!")
|| filterTrimmed.StartsWith("~")
|| filterTrimmed.StartsWith("not-");
filterTrimmed = filterTrimmed.TrimStart('!', '~');
filterTrimmed = filterTrimmed.StartsWith("not-") ? filterTrimmed[4..] : filterTrimmed;
string filterFieldString = filterTrimmed.Split(':')[0].ToLowerInvariant().Trim('"', ' ', '\t');
string filterValue = filterTrimmed[(filterFieldString.Length + 1)..].Trim('"', ' ', '\t');
return (filterFieldString, filterValue, negate);
}
///
/// Set a bool? filter
///
/// FilterItem to populate
/// String value to add
/// True to set negative filter, false otherwise
protected void SetBooleanFilter(FilterItem filterItem, string value, bool negate)
{
if (negate || value.Equals("false", StringComparison.OrdinalIgnoreCase))
filterItem.Neutral = false;
else
filterItem.Neutral = true;
}
///
/// Set a long? filter
///
/// FilterItem to populate
/// String value to add
/// True to set negative filter, false otherwise
protected void SetDoubleFilter(FilterItem filterItem, string value, bool negate)
{
bool? operation = null;
if (value.StartsWith(">"))
operation = true;
else if (value.StartsWith("<"))
operation = false;
else if (value.StartsWith("="))
operation = null;
string valueString = value.TrimStart('>', '<', '=');
if (!Double.TryParse(valueString, out double valueDouble))
return;
// Equal
if (operation == null && !negate)
{
filterItem.Neutral = valueDouble;
}
// Not Equal
else if (operation == null && negate)
{
filterItem.Negative = valueDouble - 1;
filterItem.Positive = valueDouble + 1;
}
// Greater Than or Equal
else if (operation == true && !negate)
{
filterItem.Positive = valueDouble;
}
// Strictly Less Than
else if (operation == true && negate)
{
filterItem.Negative = valueDouble - 1;
}
// Less Than or Equal
else if (operation == false && !negate)
{
filterItem.Negative = valueDouble;
}
// Strictly Greater Than
else if (operation == false && negate)
{
filterItem.Positive = valueDouble + 1;
}
}
///
/// Set a long? filter
///
/// FilterItem to populate
/// String value to add
/// True to set negative filter, false otherwise
protected void SetLongFilter(FilterItem filterItem, string value, bool negate)
{
bool? operation = null;
if (value.StartsWith(">"))
operation = true;
else if (value.StartsWith("<"))
operation = false;
else if (value.StartsWith("="))
operation = null;
string valueString = value.TrimStart('>', '<', '=');
if (!Int64.TryParse(valueString, out long valueLong))
return;
// Equal
if (operation == null && !negate)
{
filterItem.Neutral = valueLong;
}
// Not Equal
else if (operation == null && negate)
{
filterItem.Negative = valueLong - 1;
filterItem.Positive = valueLong + 1;
}
// Greater Than or Equal
else if (operation == true && !negate)
{
filterItem.Positive = valueLong;
}
// Strictly Less Than
else if (operation == true && negate)
{
filterItem.Negative = valueLong - 1;
}
// Less Than or Equal
else if (operation == false && !negate)
{
filterItem.Negative = valueLong;
}
// Strictly Greater Than
else if (operation == false && negate)
{
filterItem.Positive = valueLong + 1;
}
}
///
/// Set a string filter
///
/// FilterItem to populate
/// String value to add
/// True to set negative filter, false otherwise
protected void SetStringFilter(FilterItem filterItem, string value, bool negate)
{
if (negate)
filterItem.NegativeSet.Add(value);
else
filterItem.PositiveSet.Add(value);
}
#endregion
#region Filter Running
///
/// Determines if a value passes a bool? filter
///
/// Filter item to check
/// Value to check
/// True if the value passes, false otherwise
public static bool PassBoolFilter(FilterItem filterItem, bool? value)
{
if (filterItem.MatchesNeutral(null, value) == false)
return false;
return true;
}
///
/// Determines if a value passes a double? filter
///
/// Filter item to check
/// Value to check
/// True if the value passes, false otherwise
public static bool PassDoubleFilter(FilterItem filterItem, double? value)
{
if (filterItem.MatchesNeutral(null, value) == false)
return false;
else if (filterItem.MatchesPositive(null, value) == false)
return false;
else if (filterItem.MatchesNegative(null, value) == false)
return false;
return true;
}
///
/// Determines if a value passes a long? filter
///
/// Filter item to check
/// Value to check
/// True if the value passes, false otherwise
public static bool PassLongFilter(FilterItem filterItem, long? value)
{
if (filterItem.MatchesNeutral(null, value) == false)
return false;
else if (filterItem.MatchesPositive(null, value) == false)
return false;
else if (filterItem.MatchesNegative(null, value) == false)
return false;
return true;
}
///
/// Determines if a value passes a string filter
///
/// Filter item to check
/// Value to check
/// True if the value passes, false otherwise
public static bool PassStringFilter(FilterItem filterItem, string value)
{
if (filterItem.MatchesPositiveSet(value) == false)
return false;
if (filterItem.MatchesNegativeSet(value) == true)
return false;
return true;
}
#endregion
}
}