mirror of https://github.com/ppy/osu
Expose and document query parser and helpers
This commit is contained in:
parent
f9148eec20
commit
f733d1ec1f
|
@ -31,6 +31,17 @@ public interface IRulesetFilterCriteria
|
|||
/// {key}{op}{value}
|
||||
/// </code>
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// For adding optional string criteria, <see cref="FilterCriteria.OptionalTextFilter"/> can be used for matching,
|
||||
/// along with <see cref="FilterQueryParser.TryUpdateCriteriaText"/> for parsing.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// For adding numerical-type range criteria, <see cref="FilterCriteria.OptionalRange{T}"/> can be used for matching,
|
||||
/// along with <see cref="FilterQueryParser.TryUpdateCriteriaRange{T}(ref osu.Game.Screens.Select.FilterCriteria.OptionalRange{T},osu.Game.Screens.Select.Filter.Operator,string,FilterQueryParser.TryParseFunction{T})"/>
|
||||
/// and <see cref="float"/>- and <see cref="double"/>-typed overloads for parsing.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
/// <param name="key">The key (name) of the criterion.</param>
|
||||
/// <param name="op">The operator in the criterion.</param>
|
||||
/// <param name="value">The value of the criterion.</param>
|
||||
|
|
|
@ -9,7 +9,10 @@
|
|||
|
||||
namespace osu.Game.Screens.Select
|
||||
{
|
||||
internal static class FilterQueryParser
|
||||
/// <summary>
|
||||
/// Utility class used for parsing song select filter queries entered via the search box.
|
||||
/// </summary>
|
||||
public static class FilterQueryParser
|
||||
{
|
||||
private static readonly Regex query_syntax_regex = new Regex(
|
||||
@"\b(?<key>\w+)(?<op>(:|=|(>|<)(:|=)?))(?<value>("".*"")|(\S*))",
|
||||
|
@ -35,36 +38,36 @@ private static bool tryParseKeywordCriteria(FilterCriteria criteria, string key,
|
|||
switch (key)
|
||||
{
|
||||
case "stars":
|
||||
return tryUpdateCriteriaRange(ref criteria.StarDifficulty, op, value, 0.01d / 2);
|
||||
return TryUpdateCriteriaRange(ref criteria.StarDifficulty, op, value, 0.01d / 2);
|
||||
|
||||
case "ar":
|
||||
return tryUpdateCriteriaRange(ref criteria.ApproachRate, op, value);
|
||||
return TryUpdateCriteriaRange(ref criteria.ApproachRate, op, value);
|
||||
|
||||
case "dr":
|
||||
case "hp":
|
||||
return tryUpdateCriteriaRange(ref criteria.DrainRate, op, value);
|
||||
return TryUpdateCriteriaRange(ref criteria.DrainRate, op, value);
|
||||
|
||||
case "cs":
|
||||
return tryUpdateCriteriaRange(ref criteria.CircleSize, op, value);
|
||||
return TryUpdateCriteriaRange(ref criteria.CircleSize, op, value);
|
||||
|
||||
case "bpm":
|
||||
return tryUpdateCriteriaRange(ref criteria.BPM, op, value, 0.01d / 2);
|
||||
return TryUpdateCriteriaRange(ref criteria.BPM, op, value, 0.01d / 2);
|
||||
|
||||
case "length":
|
||||
return tryUpdateLengthRange(criteria, op, value);
|
||||
|
||||
case "divisor":
|
||||
return tryUpdateCriteriaRange(ref criteria.BeatDivisor, op, value, tryParseInt);
|
||||
return TryUpdateCriteriaRange(ref criteria.BeatDivisor, op, value, tryParseInt);
|
||||
|
||||
case "status":
|
||||
return tryUpdateCriteriaRange(ref criteria.OnlineStatus, op, value,
|
||||
return TryUpdateCriteriaRange(ref criteria.OnlineStatus, op, value,
|
||||
(string s, out BeatmapSetOnlineStatus val) => Enum.TryParse(value, true, out val));
|
||||
|
||||
case "creator":
|
||||
return tryUpdateCriteriaText(ref criteria.Creator, op, value);
|
||||
return TryUpdateCriteriaText(ref criteria.Creator, op, value);
|
||||
|
||||
case "artist":
|
||||
return tryUpdateCriteriaText(ref criteria.Artist, op, value);
|
||||
return TryUpdateCriteriaText(ref criteria.Artist, op, value);
|
||||
|
||||
default:
|
||||
return criteria.RulesetCriteria?.TryParseCustomKeywordCriteria(key, op, value) ?? false;
|
||||
|
@ -113,7 +116,18 @@ private static bool tryParseDoubleWithPoint(string value, out double result) =>
|
|||
private static bool tryParseInt(string value, out int result) =>
|
||||
int.TryParse(value, NumberStyles.None, CultureInfo.InvariantCulture, out result);
|
||||
|
||||
private static bool tryUpdateCriteriaText(ref FilterCriteria.OptionalTextFilter textFilter, Operator op, string value)
|
||||
/// <summary>
|
||||
/// Attempts to parse a keyword filter with the specified <paramref name="op"/> and textual <paramref name="value"/>.
|
||||
/// If the value indicates a valid textual filter, the function returns <c>true</c> and the resulting data is stored into
|
||||
/// <paramref name="textFilter"/>.
|
||||
/// </summary>
|
||||
/// <param name="textFilter">The <see cref="FilterCriteria.OptionalTextFilter"/> to store the parsed data into, if successful.</param>
|
||||
/// <param name="op">
|
||||
/// The operator for the keyword filter.
|
||||
/// Only <see cref="Operator.Equal"/> is valid for textual filters.
|
||||
/// </param>
|
||||
/// <param name="value">The value of the keyword filter.</param>
|
||||
public static bool TryUpdateCriteriaText(ref FilterCriteria.OptionalTextFilter textFilter, Operator op, string value)
|
||||
{
|
||||
switch (op)
|
||||
{
|
||||
|
@ -126,7 +140,20 @@ private static bool tryUpdateCriteriaText(ref FilterCriteria.OptionalTextFilter
|
|||
}
|
||||
}
|
||||
|
||||
private static bool tryUpdateCriteriaRange(ref FilterCriteria.OptionalRange<float> range, Operator op, string val, float tolerance = 0.05f)
|
||||
/// <summary>
|
||||
/// Attempts to parse a keyword filter of type <see cref="float"/>
|
||||
/// from the specified <paramref name="op"/> and <paramref name="val"/>.
|
||||
/// If <paramref name="val"/> can be parsed as a <see cref="float"/>, the function returns <c>true</c>
|
||||
/// and the resulting range constraint is stored into <paramref name="range"/>.
|
||||
/// </summary>
|
||||
/// <param name="range">
|
||||
/// The <see cref="float"/>-typed <see cref="FilterCriteria.OptionalRange{T}"/>
|
||||
/// to store the parsed data into, if successful.
|
||||
/// </param>
|
||||
/// <param name="op">The operator for the keyword filter.</param>
|
||||
/// <param name="val">The value of the keyword filter.</param>
|
||||
/// <param name="tolerance">Allowed tolerance of the parsed range boundary value.</param>
|
||||
public static bool TryUpdateCriteriaRange(ref FilterCriteria.OptionalRange<float> range, Operator op, string val, float tolerance = 0.05f)
|
||||
=> tryParseFloatWithPoint(val, out float value) && tryUpdateCriteriaRange(ref range, op, value, tolerance);
|
||||
|
||||
private static bool tryUpdateCriteriaRange(ref FilterCriteria.OptionalRange<float> range, Operator op, float value, float tolerance = 0.05f)
|
||||
|
@ -161,7 +188,20 @@ private static bool tryUpdateCriteriaRange(ref FilterCriteria.OptionalRange<floa
|
|||
return true;
|
||||
}
|
||||
|
||||
private static bool tryUpdateCriteriaRange(ref FilterCriteria.OptionalRange<double> range, Operator op, string val, double tolerance = 0.05)
|
||||
/// <summary>
|
||||
/// Attempts to parse a keyword filter of type <see cref="double"/>
|
||||
/// from the specified <paramref name="op"/> and <paramref name="val"/>.
|
||||
/// If <paramref name="val"/> can be parsed as a <see cref="double"/>, the function returns <c>true</c>
|
||||
/// and the resulting range constraint is stored into <paramref name="range"/>.
|
||||
/// </summary>
|
||||
/// <param name="range">
|
||||
/// The <see cref="double"/>-typed <see cref="FilterCriteria.OptionalRange{T}"/>
|
||||
/// to store the parsed data into, if successful.
|
||||
/// </param>
|
||||
/// <param name="op">The operator for the keyword filter.</param>
|
||||
/// <param name="val">The value of the keyword filter.</param>
|
||||
/// <param name="tolerance">Allowed tolerance of the parsed range boundary value.</param>
|
||||
public static bool TryUpdateCriteriaRange(ref FilterCriteria.OptionalRange<double> range, Operator op, string val, double tolerance = 0.05)
|
||||
=> tryParseDoubleWithPoint(val, out double value) && tryUpdateCriteriaRange(ref range, op, value, tolerance);
|
||||
|
||||
private static bool tryUpdateCriteriaRange(ref FilterCriteria.OptionalRange<double> range, Operator op, double value, double tolerance = 0.05)
|
||||
|
@ -196,11 +236,28 @@ private static bool tryUpdateCriteriaRange(ref FilterCriteria.OptionalRange<doub
|
|||
return true;
|
||||
}
|
||||
|
||||
private delegate bool TryParseFunction<T>(string val, out T value);
|
||||
/// <summary>
|
||||
/// Used to determine whether the string value <paramref name="val"/> can be converted to type <typeparamref name="T"/>.
|
||||
/// If conversion can be performed, the delegate returns <c>true</c>
|
||||
/// and the conversion result is returned in the <c>out</c> parameter <paramref name="parsed"/>.
|
||||
/// </summary>
|
||||
/// <param name="val">The string value to attempt parsing for.</param>
|
||||
/// <param name="parsed">The parsed value, if conversion is possible.</param>
|
||||
public delegate bool TryParseFunction<T>(string val, out T parsed);
|
||||
|
||||
private static bool tryUpdateCriteriaRange<T>(ref FilterCriteria.OptionalRange<T> range, Operator op, string value, TryParseFunction<T> conversionFunc)
|
||||
/// <summary>
|
||||
/// Attempts to parse a keyword filter of type <typeparamref name="T"/>,
|
||||
/// from the specified <paramref name="op"/> and <paramref name="val"/>.
|
||||
/// If <paramref name="val"/> can be parsed into <typeparamref name="T"/> using <paramref name="parseFunction"/>, the function returns <c>true</c>
|
||||
/// and the resulting range constraint is stored into <paramref name="range"/>.
|
||||
/// </summary>
|
||||
/// <param name="range">The <see cref="FilterCriteria.OptionalRange{T}"/> to store the parsed data into, if successful.</param>
|
||||
/// <param name="op">The operator for the keyword filter.</param>
|
||||
/// <param name="val">The value of the keyword filter.</param>
|
||||
/// <param name="parseFunction">Function used to determine if <paramref name="val"/> can be converted to type <typeparamref name="T"/>.</param>
|
||||
public static bool TryUpdateCriteriaRange<T>(ref FilterCriteria.OptionalRange<T> range, Operator op, string val, TryParseFunction<T> parseFunction)
|
||||
where T : struct
|
||||
=> conversionFunc.Invoke(value, out var converted) && tryUpdateCriteriaRange(ref range, op, converted);
|
||||
=> parseFunction.Invoke(val, out var converted) && tryUpdateCriteriaRange(ref range, op, converted);
|
||||
|
||||
private static bool tryUpdateCriteriaRange<T>(ref FilterCriteria.OptionalRange<T> range, Operator op, T value)
|
||||
where T : struct
|
||||
|
|
Loading…
Reference in New Issue