public static bool TryBuild()

in Arriba/Arriba/Model/Expressions/RangeToScan.cs [32:148]


        public static bool TryBuild(Operator op, int firstSortedIndexWithValue, int lastSortedIndexWithValue, int count, ref RangeToScan r)
        {
            r.Clear();
            r.Count = count;
            r.ScanWithinRange = true;

            // If source is empty, range is always empty
            if (count == 0)
            {
                r.Start = -1;
                r.End = -1;
                r.ScanWithinRange = true;
                r.NegateResult = false;
                return true;
            }

            // Set range and negate based on the operator
            if (op == Operator.Equals || op == Operator.NotEquals || op == Operator.Matches || op == Operator.MatchesExact)
            {
                // NOTE: Treat "Matches", "MatchesExact" like "Equals" if an IndexedColumn doesn't pick them up.
                // NOTE: "StartsWith" must be mapped to "Equals" by a caller which also knows to use StartsWith to find the first and last indicies.

                // Scan the item subset containing the value
                r.Start = firstSortedIndexWithValue;
                r.End = lastSortedIndexWithValue;

                // Include the opposite for not equals
                r.NegateResult = (op == Operator.NotEquals);
            }
            else if (op == Operator.LessThan || op == Operator.GreaterThanOrEqual)
            {
                r.Start = 0;

                if (firstSortedIndexWithValue < 0)
                {
                    // If not in array, scan up to (including) where it would've been inserted
                    r.End = ~firstSortedIndexWithValue - 1;
                }
                else
                {
                    // Scan below the first item with the value
                    r.End = firstSortedIndexWithValue - 1;
                }

                // Include the opposite for >=
                r.NegateResult = (op == Operator.GreaterThanOrEqual);
            }
            else if (op == Operator.GreaterThan || op == Operator.LessThanOrEqual)
            {
                r.End = count - 1;

                if (lastSortedIndexWithValue < 0)
                {
                    // If not in array, scan from where it would've been inserted
                    r.Start = ~lastSortedIndexWithValue;
                }
                else
                {
                    // Scan above the last item with the value
                    r.Start = lastSortedIndexWithValue + 1;
                }

                // Include the opposite for <=
                r.NegateResult = (op == Operator.LessThanOrEqual);
            }
            else
            {
                return false;
            }

            // Canonicalize
            if (r.End < 0 || r.Start > r.End)
            {
                // Canonicalize: If the range is empty (Start > End), always report as -1, -1 (leave negate according to operator)
                r.End = -1;
                r.Start = -1;
            }
            else if (r.Start == 0 && r.End == count - 1)
            {
                // Canonicalize: If the range is all items, convert to an empty range and negate it
                r.End = -1;
                r.Start = -1;
                r.ScanWithinRange = false;
                r.NegateResult = !r.NegateResult;
            }

            // Optimize
            if (r.Start >= 0)
            {
                // Optimize: If the range to scan is non-empty and more than half the set, scan the inverse and negate
                int rangeSize = r.End - r.Start + 1;
                if (rangeSize > count / 2)
                {
                    r.ScanWithinRange = false;
                    r.NegateResult = !r.NegateResult;
                }

                if (!r.ScanWithinRange && r.Start < r.End)
                {
                    // Optimize: If we want outside the range and one end is the end, convert to a single range
                    if (r.Start == 0)
                    {
                        r.Start = r.End + 1;
                        r.End = count - 1;
                        r.ScanWithinRange = true;
                    }
                    else if (r.End == count - 1)
                    {
                        r.End = r.Start - 1;
                        r.Start = 0;
                        r.ScanWithinRange = true;
                    }
                }
            }

            return true;
        }