Хабр Курсы для всех
РЕКЛАМА
Практикум, Хекслет, SkyPro, авторские курсы — собрали всех и попросили скидки. Осталось выбрать!
Строка «аа» во внутреннем представлении перла без флага выглядит так: \x{d0}\x{b0}\x{d0}\x{b0}
а с флагом вот так: \x{430}\x{430}
И функция utf8::is_utf8() на оба варианта вернёт истину.
my $s1 = "x{d0}\x{b0}\x{d0}\x{b0}";
print "s1:", utf8::is_utf8($s1), "\n";
my $s2 = "\x{430}\x{430}";
print "s2:", utf8::is_utf8($s2), "\n";
s1: s2:1
utf8::upgrade( $a ); # перевели во внутреннее представление только чтобы показать что оно отличается от флаговой стоки
use Data::Dumper;
use Modern::Perl;
my $a = "аа";
print length($a);
Функция utf8::is_utf8() к сожалению показывает не наличие флага у строки, а внутреннее это представление или нет.
В документации прямо и пишут «the internal representation»
Это некорректное присвоение, т.е. Вы не то присвоили, это Dumper так выводит стоки.
Надо было
my $s1 = 'аа';
utf8::upgrade($a);
Строка в utf8 с флагом — это именно символы, а без флага — байты, это тоже можно проверить regexp-ом
строка с флагом по умолчанию понимают что мы работаем с символами, а без флага — с байтами.
> Дальше этот пример не изучал.
Я изучал
PS чтобы использовать Encode::encode, Encode::decode не обязательно подключать модуль Encode,
проще использовать utf8::decode() и utf8::encode() чтобы не засорять namespace модуля/скрипта
Note that this function does not handle arbitrary encodings. Therefore Encode is recommended for the general purposes; see also Encode.
Строка «аа» во внутреннем представлении перла без флага выглядит так: \x{d0}\x{b0}\x{d0}\x{b0}
И функция utf8::is_utf8() на оба варианта вернёт истину.
{"utf8::is_utf8", XS_utf8_is_utf8, NULL},
XS(XS_utf8_is_utf8)
{
dVAR;
dXSARGS;
if (items != 1)
croak_xs_usage(cv, "sv");
else {
SV * const sv = ST(0);
SvGETMAGIC(sv);
if (SvUTF8(sv))
XSRETURN_YES;
else
XSRETURN_NO;
}
XSRETURN_EMPTY;
}
if (RETVAL &&
check &&
!is_utf8_string((U8*)SvPVX(sv), SvCUR(sv)))
RETVAL = FALSE;
#define SvUTF8(sv) (SvFLAGS(sv) & SVf_UTF8)
#define SVf_UTF8 0x20000000 /* SvPV is UTF-8 encoded
#define SvFLAGS(sv) (sv)->sv_flags
#define SvUTF8_on(sv) (SvFLAGS(sv) |= (SVf_UTF8))
В Encode.pm описание is_utf8 — "...Tests whether the UTF8 flag is turned on in the string. If check is true also checks
Думаю Encode::is_utf8 с флагом check эквивалентно utf8::valid().— получается не так. В Encode::is_utf8 с флагом check выполняется
RETVAL = SvUTF8(sv) ? TRUE : FALSE;
if (RETVAL &&
check &&
!is_utf8_string((U8*)SvPVX(sv), SvCUR(sv)))
RETVAL = FALSE;
{"utf8::valid", XS_utf8_valid, NULL},
XS(XS_utf8_valid)
{
dVAR;
dXSARGS;
if (items != 1)
croak_xs_usage(cv, "sv");
else {
SV * const sv = ST(0);
STRLEN len;
const char * const s = SvPV_const(sv,len);
if (!SvUTF8(sv) || is_utf8_string((const U8*)s,len))
XSRETURN_YES;
else
XSRETURN_NO;
}
XSRETURN_EMPTY;
}
Получается, что TRUE если есть установленный флаг и не выполняется условие ниже
Если флаг не установлен – возвращаем ОК без проверки.
Will return true if it is well-formed UTF-8 and has the UTF-8 flag on or if STRING is held as bytes (both these states are 'consistent').
Т.е. перекодировка туда-обратно не меняет данные (это ожидаемо), но устанавливает UTF-8 флаг.
(впрочем, такое поведение decode() противоречит его собственной документации, которая, в свою очередь, противоречит идее, что никакой документации и гарантий относительно utf-8 флага в ASCII данных быть не должно)
use strict;
use warnings;
use Devel::Peek;
my $str = "Hello";
print Dump ($str);
use strict;
use warnings;
#use utf8;
use Devel::Peek;
my $str = "Привет";
print Dump ($str);
use strict;
use warnings;
use encoding('windows-1251');
use Devel::Peek;
my $str = "Привет";
print Dump ($str);
use strict;
use warnings;
use utf8;
use Devel::Peek;
my $str = "Hello";
print Dump ($str);
Вся правда о UTF-8 флаге