private static List <EquivalenceClass> ComputeIgnoreCaseEquivalenceClasses(CharSetSolver solver, CultureInfo culture)
        {
            var ignoreCase = new Dictionary <char, EquivalenceClass>();
            var sets       = new List <EquivalenceClass>();

            for (uint i = 65; i <= 0xFFFF; i++)
            {
                char C = (char)i;
                char c = char.ToLower(C, culture);

                if (c == C)
                {
                    continue;
                }

                EquivalenceClass?ec;
                if (!ignoreCase.TryGetValue(c, out ec))
                {
                    ec            = new EquivalenceClass(solver.CharConstraint(c));
                    ignoreCase[c] = ec;
                    sets.Add(ec);
                }
                ec._set = solver.Or(ec._set, solver.CharConstraint(C));
            }
            return(sets);
        }
Example #2
0
        /// <summary>
        /// Get the set of CI-equivalent characters to c.
        /// This operation depends on culture for i, I, '\u0130', and '\u0131';
        /// culture="" means InvariantCulture while culture=null means to use the current culture.
        /// </summary>
        public BDD Apply(char c, string?culture = null)
        {
            if (Volatile.Read(ref _cultureIndependentChars[c]) is BDD bdd)
            {
                return(bdd);
            }

            culture ??= CultureInfo.CurrentCulture.Name;
            switch (c)
            {
            // Do not cache in _cultureIndependentChars values that are culture-dependent

            case 'i':
                return
                    (culture == string.Empty ? _i_Invariant :
                     IsTurkishAlphabet(culture) ? _i_Turkish :
                     _i_Default);   // for all other cultures, case-sensitivity is the same as for en-US

            case 'I':
                return
                    (culture == string.Empty ? _i_Invariant :
                     IsTurkishAlphabet(culture) ? _I_Turkish :    // different from 'i' above
                     _i_Default);

            case Turkish_I_WithDot:
                return
                    (culture == string.Empty ? _solver.CharConstraint(Turkish_I_WithDot) :
                     IsTurkishAlphabet(culture) ? _i_Turkish :
                     _i_Default);

            case Turkish_i_WithoutDot:
                return
                    (IsTurkishAlphabet(culture) ? _I_Turkish :
                     _solver.CharConstraint(Turkish_i_WithoutDot));

            case 'k':
            case 'K':
            case KelvinSign:
                Volatile.Write(ref _cultureIndependentChars[c], _solver.Or(_solver.Or(_solver.CharConstraint('k'), _solver.CharConstraint('K')), _solver.CharConstraint(KelvinSign)));
                return(_cultureIndependentChars[c] !);

            // Cache in _cultureIndependentChars entries that are culture-independent.
            // BDDs are idempotent, so while we use volatile to ensure proper adherence
            // to ECMA's memory model, we don't need Interlocked.CompareExchange.

            case <= '\x7F':
                // For ASCII range other than letters i, I, k, and K, the case-conversion is independent of culture and does
                // not include case-insensitive-equivalent non-ASCII.
                Volatile.Write(ref _cultureIndependentChars[c], _solver.Or(_solver.CharConstraint(char.ToLower(c)), _solver.CharConstraint(char.ToUpper(c))));
                return(_cultureIndependentChars[c] !);

            default:
                // Bring in the full transfomation relation, but here it does not actually depend on culture
                // so it is safe to store the result for c.
                Volatile.Write(ref _cultureIndependentChars[c], Apply(_solver.CharConstraint(c)));
                return(_cultureIndependentChars[c] !);
            }
        }
Example #3
0
 public IgnoreCaseTransformer(CharSetSolver solver)
 {
     _solver      = solver;
     _i_Invariant = solver.Or(_solver.CharConstraint('i'), solver.CharConstraint('I'));
     _i_Default   = solver.Or(_i_Invariant, solver.CharConstraint(Turkish_I_WithDot));
     _i_Turkish   = solver.Or(solver.CharConstraint('i'), solver.CharConstraint(Turkish_I_WithDot));
     _I_Turkish   = solver.Or(solver.CharConstraint('I'), solver.CharConstraint(Turkish_i_WithoutDot));
 }