Определение UTF-8 на чистом Perl

У нас сейчас смена админов: отдел переходит из ведомства одних админов к другим. Соотвественно, все задачи выполняются сильно медленее. Задача по установке модуля к Perl висит уже несколько дней. Вот и пришлось мне написать на чистом Perl функцию, определяющую UTF-8 это или нет.

На Perl'e не писал уже очень давно, так что было интересно что я помню. Функцию, в итоге, сохраню здесь, мало ли — понадобится кому.
sub detect_utf8($) {
    my $str = shift;
    my %exclude = map { $_ => undef } (0..191, 194..244);  # RFC 3629

    for (my $i = 0, $l, $len = length $str; $i < $len; $i++) {
        $code = ord substr($str, $i, 1);

        return 0 unless exists $exclude{$code};

        for ($l = 0; $code & 128; $l++, $code = 0xFF & ($code << 1)) {}

        $i += $l - 1 if $l;

        return 0 if $i > $len or $l > 4; # broken
    }

    1;
}
Что можно улучшить: проверять, чтобы дополнительные байты имели старшие биты «10».
14 апреля 2009 17:20

david-m.livejournal.com (david-m.livejournal.com)
15 апреля 2009, 00:03

В принципе, это одним регекспом делается. Искать, правда, отчаянно лень, в последний раз эта задача передо мной вставала лет пять назад:)

david-m.livejournal.com (david-m.livejournal.com)
15 апреля 2009, 00:20

Хотя, собственно, чего лениться…
[\x00-\x7f]|[\xc0-\xdf][\x80-\xbf]|[\xe0-\xef][\x80-\xbf][\x80-\xbf]|[\xf0-\xf7][\x80-\xbf][\x80-\xbf][\x80-\xbf]
Если матчится — значит, UTF-8.

bolk (bolknote.ru)
15 апреля 2009, 09:36, ответ предназначен david-m.livejournal.com:

О, спасибо! Вот что значит — коллективный разум. Причём, я уверен, что когда-то этот регэксп видел :)

Для тех, кто будет использовать: описан один символ, нужно поставить ^(?: и )+$ по краям.

david-m.livejournal.com (david-m.livejournal.com)
15 апреля 2009, 15:52

Собственно, это дословный перевод спецификации UTF-8 на язык регекспов. Да, это один символ, конечно.

bolk (bolknote.ru)
15 апреля 2009, 17:55, ответ предназначен david-m.livejournal.com:

Ага, так и есть :) Очень простая идея, да :)

Ваше имя или адрес блога (можно OpenID):

Текст вашего комментария, не HTML:

Кому бы вы хотели ответить (или кликните на его аватару)