using System.Diagnostics;
public static (string NewFilter, string ErrorMessage) FilterBuilder(string filter1, string Operator = "&&", string filter2 = "")
ReadOnlySpan<char> Filter1Span = filter1.AsSpan();
ReadOnlySpan<char> Filter2Span = filter2.AsSpan();
ReadOnlySpan<char> OperatorSpan = Operator.AsSpan();
ReadOnlySpan<char> In = "in".AsSpan();
if (Filter2Span.Length != 0 && Filter1Span.Length != 0)
filter = OperatorBuilder(SeparateMultipleStatements(Filter1Span), OperatorSpan, SeparateMultipleStatements(Filter2Span)).ToString();
if(Filter1Span.Length == 0)
if(Filter2Span.Length == 0)
Error = "Both filters cannot be empty";
filter = SeparateMultipleStatements(Filter2Span).ToString();
else if(Filter2Span.Length == 0)
filter = SeparateMultipleStatements(Filter1Span).ToString();
public static ReadOnlySpan<char> SeparateMultipleStatements(ReadOnlySpan<char> filter)
if (MemoryExtensions.Contains(filter, ",".AsSpan(), StringComparison.Ordinal) && !MemoryExtensions.Contains(filter, "in".AsSpan(), StringComparison.Ordinal) &&
!(MemoryExtensions.Contains(filter, "(".AsSpan(), StringComparison.Ordinal) && MemoryExtensions.Contains(filter, ")".AsSpan(), StringComparison.Ordinal)))
int index = filter.IndexOf(',');
var filter1 = ConvertToNewSyntax(filter.Slice(0, index));
var Operator = " && ".AsSpan();
var filter2 = ConvertToNewSyntax(filter.Slice(index+1));
char[] buffer = new char[filter1.Length + Operator.Length + filter2.Length];
Span<char> span = new Span<char>(buffer);
int indexConcatenate = 0;
filter1.CopyTo(span.Slice(indexConcatenate, filter1.Length));
indexConcatenate += filter1.Length;
Operator.CopyTo(span.Slice(indexConcatenate, Operator.Length));
indexConcatenate += Operator.Length;
filter2.CopyTo(span.Slice(indexConcatenate, filter2.Length));
filter = ConvertToNewSyntax(filter);
public static ReadOnlySpan<char> ConvertToNewSyntax(ReadOnlySpan<char> filter)
if (MemoryExtensions.Contains(filter, "=".AsSpan(), StringComparison.Ordinal))
else if (MemoryExtensions.Contains(filter, ":".AsSpan(), StringComparison.Ordinal))
int index = filter.IndexOf(character);
bool isDate = IsDateTime(filter.Slice(index+1));
var part1 = filter.Slice(0, index);
var part2 = filter.Slice(index+1);
var Character = character.ToString().AsSpan();
var Quote = "\"".AsSpan();
char[] buffer = new char[part1.Length + part2.Length + Character.Length + Quote.Length * 2];
Span<char> span = new Span<char>(buffer);
int indexConcatenate = 0;
part1.CopyTo(span.Slice(indexConcatenate, part1.Length));
indexConcatenate += part1.Length;
Character.CopyTo(span.Slice(indexConcatenate, Character.Length));
indexConcatenate += Character.Length;
Quote.CopyTo(span.Slice(indexConcatenate, Quote.Length));
indexConcatenate += Quote.Length;
part2.CopyTo(span.Slice(indexConcatenate, part2.Length));
indexConcatenate += part2.Length;
Quote.CopyTo(span.Slice(indexConcatenate, Quote.Length));
foreach (char c in filter)
var part1 = filter.Slice(0, index);
var part2 = filter.Slice(index+1);
var Character = character.ToString().AsSpan();
var Equal = "=".AsSpan();
char[] buffer = new char[part1.Length + part2.Length + Character.Length + Equal.Length];
Span<char> span = new Span<char>(buffer);
int indexConcatenate = 0;
part1.CopyTo(span.Slice(indexConcatenate, part1.Length));
indexConcatenate += part1.Length;
Character.CopyTo(span.Slice(indexConcatenate, Character.Length));
indexConcatenate += Character.Length;
Equal.CopyTo(span.Slice(indexConcatenate, Equal.Length));
indexConcatenate += Equal.Length;
part2.CopyTo(span.Slice(indexConcatenate, part2.Length));
else if (character == ':')
var part1 = filter.Slice(0, index);
var part2 = filter.Slice(index+1);
var string1 = "==\"".AsSpan();
var string2 = "*\"".AsSpan();
char[] buffer = new char[part1.Length + part2.Length + string1.Length + string2.Length];
Span<char> span = new Span<char>(buffer);
int indexConcatenate = 0;
part1.CopyTo(span.Slice(indexConcatenate, part1.Length));
indexConcatenate += part1.Length;
string1.CopyTo(span.Slice(indexConcatenate, string1.Length));
indexConcatenate += string1.Length;
part2.CopyTo(span.Slice(indexConcatenate, part2.Length));
indexConcatenate += part2.Length;
string2.CopyTo(span.Slice(indexConcatenate, string2.Length));
public static ReadOnlySpan<char> OperatorBuilder(ReadOnlySpan<char> filter1, ReadOnlySpan<char> Operator, ReadOnlySpan<char> filter2)
ReadOnlySpan<char> filter;
var OpenningBracket = "(".AsSpan();
var ClosingBracket = ")".AsSpan();
var Space = " ".AsSpan();
int indexConcatenate = 0;
if(Operator == "()&&" || Operator == "()!!" || Operator.ToString().Contains("in"))
Operator = MemoryExtensions.TrimStart(Operator, "()");
char[] buffer = new char[filter1.Length + filter2.Length + OpenningBracket.Length + ClosingBracket.Length + Space.Length * 2 + Operator.Length];
Span<char> span = new Span<char>(buffer);
OpenningBracket.CopyTo(span.Slice(indexConcatenate, OpenningBracket.Length));
indexConcatenate += OpenningBracket.Length;
filter1.CopyTo(span.Slice(indexConcatenate, filter1.Length));
indexConcatenate += filter1.Length;
ClosingBracket.CopyTo(span.Slice(indexConcatenate, ClosingBracket.Length));
indexConcatenate += ClosingBracket.Length;
Space.CopyTo(span.Slice(indexConcatenate, Space.Length));
indexConcatenate += Space.Length;
Operator.CopyTo(span.Slice(indexConcatenate, Operator.Length));
indexConcatenate += Operator.Length;
Space.CopyTo(span.Slice(indexConcatenate, Space.Length));
indexConcatenate += Space.Length;
filter2.CopyTo(span.Slice(indexConcatenate, filter2.Length));
else if (Operator == "&&()" || Operator == "!!()")
Operator = MemoryExtensions.TrimEnd(Operator, "()");
char[] buffer = new char[filter1.Length + filter2.Length + OpenningBracket.Length + ClosingBracket.Length + Space.Length * 2 + Operator.Length];
Span<char> span = new Span<char>(buffer);
filter1.CopyTo(span.Slice(indexConcatenate, filter1.Length));
indexConcatenate += filter1.Length;
Space.CopyTo(span.Slice(indexConcatenate, Space.Length));
indexConcatenate += Space.Length;
Operator.CopyTo(span.Slice(indexConcatenate, Operator.Length));
indexConcatenate += Operator.Length;
Space.CopyTo(span.Slice(indexConcatenate, Space.Length));
indexConcatenate += Space.Length;
OpenningBracket.CopyTo(span.Slice(indexConcatenate, OpenningBracket.Length));
indexConcatenate += OpenningBracket.Length;
filter2.CopyTo(span.Slice(indexConcatenate, filter2.Length));
indexConcatenate += filter2.Length;
ClosingBracket.CopyTo(span.Slice(indexConcatenate, ClosingBracket.Length));
else if (Operator == "()&&()" || Operator =="()!!()")
Operator = MemoryExtensions.TrimStart(Operator, "()");
Operator = MemoryExtensions.TrimEnd(Operator, "()");
char[] buffer = new char[filter1.Length + filter2.Length + OpenningBracket.Length * 2 + ClosingBracket.Length * 2 + Space.Length * 2 + Operator.Length];
Span<char> span = new Span<char>(buffer);
OpenningBracket.CopyTo(span.Slice(indexConcatenate, OpenningBracket.Length));
indexConcatenate += OpenningBracket.Length;
filter1.CopyTo(span.Slice(indexConcatenate, filter1.Length));
indexConcatenate += filter1.Length;
ClosingBracket.CopyTo(span.Slice(indexConcatenate, ClosingBracket.Length));
indexConcatenate += ClosingBracket.Length;
Space.CopyTo(span.Slice(indexConcatenate, Space.Length));
indexConcatenate += Space.Length;
Operator.CopyTo(span.Slice(indexConcatenate, Operator.Length));
indexConcatenate += Operator.Length;
Space.CopyTo(span.Slice(indexConcatenate, Space.Length));
indexConcatenate += Space.Length;
OpenningBracket.CopyTo(span.Slice(indexConcatenate, OpenningBracket.Length));
indexConcatenate += OpenningBracket.Length;
filter2.CopyTo(span.Slice(indexConcatenate, filter2.Length));
indexConcatenate += filter2.Length;
ClosingBracket.CopyTo(span.Slice(indexConcatenate, ClosingBracket.Length));
char[] buffer = new char[filter1.Length + filter2.Length + Space.Length * 2 + Operator.Length];
Span<char> span = new Span<char>(buffer);
filter1.CopyTo(span.Slice(indexConcatenate, filter1.Length));
indexConcatenate += filter1.Length;
Space.CopyTo(span.Slice(indexConcatenate, Space.Length));
indexConcatenate += Space.Length;
Operator.CopyTo(span.Slice(indexConcatenate, Operator.Length));
indexConcatenate += Operator.Length;
Space.CopyTo(span.Slice(indexConcatenate, Space.Length));
indexConcatenate += Space.Length;
filter2.CopyTo(span.Slice(indexConcatenate, filter2.Length));
public static bool IsDateTime(ReadOnlySpan<char> text)
isDateTime = DateTime.TryParse(text, out dateTime);
public static void Main()
Stopwatch s = Stopwatch.StartNew();
Console.WriteLine(FilterBuilder(""));
Console.WriteLine(FilterBuilder("", "&&", ""));
Console.WriteLine(FilterBuilder("NAME:D,SEX=\"M\""));
Console.WriteLine(FilterBuilder("SEX==\"M\",ST:D"));
Console.WriteLine(FilterBuilder("ST==2" , "&&" , "NAME:D,SEX=\"M\""));
Console.WriteLine(FilterBuilder("ST<2" , "&&" , ""));
Console.WriteLine(FilterBuilder("" , "&&" , "ST<2"));
Console.WriteLine(FilterBuilder("ST==9" , "&&()" , "ST<2"));
var (M, E) = FilterBuilder( "ST<2", "&&", "" );
Console.WriteLine(FilterBuilder( M, "&&()", "DATE=2012.03.12" ));
var (N, E2) = FilterBuilder( "$ARCH:C", "()!!", "exists(1)" );
Console.WriteLine(FilterBuilder( N, "&&", "ST in (2, 4, 9)"));
string filter1 = "TEXT:AB";
string filter2 = "(1, 3)";
var (F,E3) = FilterBuilder( filter1 );
(F,E3) = FilterBuilder( F, "&&", "ST == 4" );
Console.WriteLine(FilterBuilder( F, "()!! TCODE in", filter2 ));
Console.WriteLine("Time elapsed (ns): {0}", s.Elapsed.TotalMilliseconds * 1000000);