Repository: microsoft/garnet
File: libs/server/GlobUtils.cs (C#)

Code before:
﻿// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

namespace Garnet.server
{
    /// <summary>
    /// Glob utils
    /// </summary>
    public static class GlobUtils
    {
        /// <summary>
        /// Glob-style ASCII pattern matching
        /// </summary>
        /// <returns>Whether match was found</returns>
        public static unsafe bool Match(byte* pattern, int patternLen, byte* key, int stringLen, bool ignoreCase = false)
        {
            static byte ToLowerAscii(byte value) => (byte)(value | 0x20);

            while (patternLen > 0 && stringLen > 0)
            {
                switch (pattern[0])
                {
                    case (byte)'*':
                        while (patternLen > 0 && pattern[1] == '*')
                        {
                            pattern++;
                            patternLen--;
                        }
                        if (patternLen == 1)
                            return true; /* match */
                        while (stringLen > 0)
                        {
                            if (Match(pattern + 1, patternLen - 1, key, stringLen, ignoreCase))
                                return true; /* match */
                            key++;
                            stringLen--;
                        }
                        return false; /* no match */

                    case (byte)'?':
                        key++;
                        stringLen--;

Review comment (suggestion):
This code considers @=`, and ^=~ (all other relevant special characters are already handled below). IMO, this behavior is absolutely fine for our use case, but it might be worth adding this limitation to the doc comment for Match().

Code after:
﻿// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

namespace Garnet.server
{
    /// <summary>
    /// Glob utils
    /// </summary>
    public static class GlobUtils
    {
        /// <summary>
        /// Glob-style ASCII pattern matching
        /// </summary>
        /// <returns>Whether match was found</returns>
        public static unsafe bool Match(byte* pattern, int patternLen, byte* key, int stringLen, bool ignoreCase = false)
        {
            static byte ToLowerAscii(byte value)
            {
                if ((uint)(value - 'A') <= (uint)('Z' - 'A')) // Is in [A-Z]
                    value = (byte)(value | 0x20);
                return value;
            }

            while (patternLen > 0 && stringLen > 0)
            {
                switch (pattern[0])
                {
                    case (byte)'*':
                        while (patternLen > 0 && pattern[1] == '*')
                        {
                            pattern++;
                            patternLen--;
                        }
                        if (patternLen == 1)
                            return true; /* match */
                        while (stringLen > 0)
                        {
                            if (Match(pattern + 1, patternLen - 1, key, stringLen, ignoreCase))
                                return true; /* match */
                            key++;
                            stringLen--;
                        }