Если вы хотите сбросить циклы ЦП, вы можете подумать об этом - давайте предположим, что мы имеем дело с ASCII, а не с Unicode.
Создать статическую таблицу с 256 записями. Каждая запись в таблице - 256 бит.
Чтобы проверить, равны ли два символа, вы делаете что-то вроде этого:
if (BitLookup(table[char1], char2)) { /* match */ }
Чтобы построить таблицу, вы устанавливаете бит повсюду в таблице [char1], где вы считаете, что она соответствует char2. Таким образом, при построении таблицы вы должны установить биты в индексе для «а» и «А» в «а» записи (и «А» записи).
Теперь поиск по битам будет медленным (поиск по битам, скорее всего, будет сдвиг, маска и добавление), так что вы можете использовать вместо этого таблицу байтов, чтобы использовать 8 бит для представления 1 бита. Это займет 32 КБ - так что ура - вы нашли компромисс между временем и пространством! Возможно, мы захотим сделать таблицу более гибкой, поэтому допустим, что мы сделаем это вместо этого - вместо таблицы будет определена конгруэнция.
Два символа считаются конгруэнтными тогда и только тогда, когда есть функция, которая определяет их как эквивалентные. Таким образом, «А» и «А» являются конгруэнтными для нечувствительности к регистру. 'A', '& Agrave;', '& Aacute;' и 'В' соответствуют диакритической нечувствительности.
Таким образом, вы определяете битовые поля, которые соответствуют вашим конгруэнтности
#define kCongruentCase (1 << 0)
#define kCongruentDiacritical (1 << 1)
#define kCongruentVowel (1 << 2)
#define kCongruentConsonant (1 << 3)
Тогда ваш тест выглядит примерно так:
inline bool CharsAreCongruent(char c1, char c2, unsigned char congruency)
{
return (_congruencyTable[c1][c2] & congruency) != 0;
}
#define CaseInsensitiveCharEqual(c1, c2) CharsAreCongruent(c1, c2, kCongruentCase)
Этот тип немного возиться с огромными таблицами, к слову, является сердцем ctype.