Поиск Unicode-здравой функции для поиска текста в двоичных данных - PullRequest
0 голосов
/ 28 апреля 2019

Мне нужно найти текст Unicode внутри двоичных данных (файлов).

Я ищу любой код или библиотеку C или C ++ , которые можно использовать в macOS. Так как я думаю, что это также полезно для других платформ, поэтому я скорее делаю этот вопрос не специфичным для macOS.

В macOS функции NSString, отвечающие моим потребностям в юникоде, не могут быть использованы, поскольку они не работают с двоичными данными.

В качестве альтернативы я попробовал совместимые с POSIX regex функции, предоставляемые в macOS, но у них есть некоторые ограничения:

  • Они не разбираются в нормировке, т. Е. Если я ищу предварительно составленный (NFC) символ, он не найдет символ, если он встречается в разложенной (NFD) форме в целевых данных.
  • Поиск без учета регистра не работает для латинских символов NFC (поиск Ü не находит ü).

Пример кода, показывающий эти результаты ниже.

Какой код или библиотека существует для удовлетворения этих потребностей?

Мне не нужны возможности регулярных выражений, но если есть библиотека регулярных выражений, которая может удовлетворить эти требования, я тоже в порядке с этим.

В основном мне нужен текстовый поиск в Юникоде с этими опциями:

  • регистронезависимым
  • нормализация нечувствительные
  • диакритические-нечувствительные
  • работает с произвольными двоичными данными, находя совпадающие фрагменты текста UTF-8

Вот тестовый код, показывающий результаты использования реализации регулярных выражений TRE в macOS:

#include <stdio.h>
#include <regex.h>

void findIn (const char *what, const char *data, int whatPre, int dataPre) {
    regex_t re;
    regcomp (&re, what, REG_ICASE | REG_LITERAL);
    int found = regexec(&re, data, 0, NULL, 0) == 0;
    printf ("Found %s (%s) in %s (%s): %s\n", what, whatPre?"pre":"dec", data, dataPre?"pre":"dec", found?"yes":"no");
}

void findInBoth (const char *what, int whatPre) {
    char dataPre[] = { '<', 0xC3, 0xA4, '>', 0};        // precomposed
    char dataDec[] = { '<', 0x61, 0xCC, 0x88, '>', 0};  // decomposed
    findIn (what, dataPre, whatPre, 1);
    findIn (what, dataDec, whatPre, 0);
}

int main(int argc, const char * argv[]) {
    char a_pre[] = { 0xC3, 0xA4, 0};        // precomposed ä
    char a_dec[] = { 0x61, 0xCC, 0x88, 0};  // decomposed ä
    char A_pre[] = { 0xC3, 0x84, 0};        // precomposed Ä
    char A_dec[] = { 0x41, 0xCC, 0x88, 0};  // decomposed Ä

    findInBoth (a_pre, 1);
    findInBoth (a_dec, 0);
    findInBoth (A_pre, 1);
    findInBoth (A_dec, 0);

    return 0;
}

Вывод:

Found ä (pre) in <ä> (pre): yes
Found ä (pre) in <ä> (dec): no
Found ä (dec) in <ä> (pre): no
Found ä (dec) in <ä> (dec): yes
Found Ä (pre) in <ä> (pre): no
Found Ä (pre) in <ä> (dec): no
Found Ä (dec) in <ä> (pre): no
Found Ä (dec) in <ä> (dec): yes

Желаемый результат: все случаи должны давать «да»

1 Ответ

0 голосов
/ 28 апреля 2019

Я решил эту проблему, написав свой собственный препроцессор, сгенерировав регулярное выражение, объединяющее все чередования (регистр и нормализация, но не диакритические знаки), и передав его в функцию регулярного выражения.

Полное решение задокументировано здесь .

...