если кому интересно: по скорости допиленый libre9 примерно равен TRE (думаю, можно ещё ускорить, но лень). конечно, фич у TRE значительно больше, зато libre9 занимает ~36 килобайт в исходнике, одним файлом (хидер не считаю). в принципе, портабелен: я запихал там немного __attribute__, но их можно без потерь убрать.
фичи: * понимает как utf8, так и «просто байты»; * умеет non-capturing groups (?:…); * умеет нежадные повторения; * не бэктрекинговый, поэтому не улетает в космос, когда бэктрекер будет сто лет со строкой в двадцать символов трахаться; * потокобезопасный, как компилятор, так и исполнитель; * соответственно, после компиляции один регэксп можно использовать одновременно в куче потоков; * поскольку, опять таки, не бэктрекер, то без особого труда может быть адаптирован к работе в «поточном» режиме (ему нужно только три операции: «получить символ на текущей позиции», «продвинуть позицию вперёд», «проверить, не кончился ли поток»), он никогда не смотрит на символы строки, которые уже раз обработал и не накапливает строку в памяти.
антифичи: а никаких наворотов нет! * классов нет (типа \d, \s и так далее); * позикс-диапазонов нет ([[:alpha:]]); * числовых повторялок нет ({n,m} — это можно сделать, как в RE2 сделали: разворотом в «обычную» регулярку); * естественно, никаких backreferences, conditions и прочих бэктрекинговых радостей нет; * регистронезависимость делается ручками, в регэкспе (это вообще легко починить, но — только для ascii; для unicode только таблицы будут раз в десять жирнее, чем остальной код; это же справедливо и для диапазонов); * не умеет работать с не-asciiz (чинится элементарно, да и «внутре» умеет; лень); * точнее, не умеет компилировать регэкспы с '\0', а самому движку по барабану, ему можно передать начало и конец области памяти; * при невалидном UTF-8 может выскочить за строку (а валидируйте, ибо нехуй!); * жрёт больше памяти, чем ему реально надо (лееееень); * максимальное количество захватов — шестнадцать (чинится в исходнике правкой константы; чем больше захватов — тем больше жрёт памяти).
p.s. а впрочем… хуле нам дела? научил спецкоду \Z — символ с кодом ноль. концом строки не считается.
пока туда да сюда, наступил нечаянно на библиотеку для fuzzy regexp matching: libbitap. размеров маленьких, кода несложного, гигабайты не прожуёт, а так, если срочно надо и чтобы не стопицот строк из TRE — покатит. public domain к тому же.
прямую ссылку не даю, потому что офсайт дохлый. бог поисковик в помощь. шибко сильно не тестировал, с первого взгляда — работает, valgrind матом не выражается.
diff/patch на bitap, по идее, должен быть покруче привычных. потому как привычные только строками оперируют, а этот может и по буквам «вдарить». не то, чтобы «все выкидываем старьё», конечно: пусть оба будут. вплоть до комбинашки «сначала вломим по строкам, а потом разницу разъясним».
если я верно понял те куски, которые не поленился прочитать — оно реально шустрое. и да, libbitap сама занимается трюкачеством с длинными числами, чтобы не ограничиваться длиной машинного слова, так что берите-берите.