diff --git a/src/Archetype.cs b/src/Archetype.cs index 6ae03a2..3ffb9c6 100644 --- a/src/Archetype.cs +++ b/src/Archetype.cs @@ -328,35 +328,7 @@ private bool IsSuperset(ReadOnlySpan other) internal int FindMatch(ReadOnlySpan searching) { - var currents = Components.AsSpan(); - var i = 0; - var j = 0; - - while (i < currents.Length && j < searching.Length) - { - ref readonly var current = ref currents[i]; - ref readonly var search = ref searching[j]; - - if (_comparer.Compare(current.ID.Value, search.ID.Value) == 0) - { - if (search.Op == TermOp.Without) - return -1; - - ++j; - } - else if (current.ID > search.ID && search.Op != TermOp.With) - { - ++j; - continue; - } - - ++i; - } - - while (j < searching.Length && searching[j].Op != TermOp.With) - ++j; - - return j == searching.Length ? 0 : 1; + return Match.Validate(_comparer, Components.AsSpan(), searching); } public void Print() diff --git a/src/Match.cs b/src/Match.cs new file mode 100644 index 0000000..386f293 --- /dev/null +++ b/src/Match.cs @@ -0,0 +1,56 @@ +namespace TinyEcs; + +static class Match +{ + public static int Validate(IComparer comparer, ReadOnlySpan ids, ReadOnlySpan terms) + { + int idIndex = 0; + int termIndex = 0; + + while (idIndex < ids.Length && termIndex < terms.Length) + { + var id = ids[idIndex].ID; + ref readonly var term = ref terms[termIndex]; + + if (comparer.Compare(id.Value, term.ID.Value) == 0) + { + switch (term.Op) + { + case TermOp.With: + termIndex++; + break; + case TermOp.Without: + return -1; // Forbidden ID found + case TermOp.Optional: + termIndex++; + break; + } + idIndex++; + } + else if (id < term.ID) + { + idIndex++; + } + else if (id > term.ID) + { + if (term.Op == TermOp.With) + { + return 1; // Required ID not found + } + termIndex++; + } + } + + // Check any remaining required terms + while (termIndex < terms.Length) + { + if (terms[termIndex].Op == TermOp.With) + { + return 1; // Required ID not found + } + termIndex++; + } + + return 0; + } +} diff --git a/src/World.cs b/src/World.cs index a8f5ae9..55844d6 100644 --- a/src/World.cs +++ b/src/World.cs @@ -606,7 +606,9 @@ static void ParseType(SortedSet terms) where T : struct EcsAssert.Panic(false, $"Type {type} is not registered. Register {type} using world.Entity() or assign it to an entity."); } - internal static class Query where TQuery : struct where TFilter : struct + internal static class Query + where TQuery : struct + where TFilter : struct { public static readonly ImmutableArray Terms; public static readonly ImmutableArray Columns;