вторник, 14 сентября 2021 г.

Об unicode в Perl

В очередной раз задумался о том, какие строки оптимальней использовать в основном коде: characters или octets.

Обычно мне очень редко приходиться работать непосредственно с unicode. Когда нужно, я преобразовываю octets в characters, а затем обратно.

Но HTML::Parser требует на вход unicode, и JSON::XS корректно работает только с unicode. Поэтому хоть непосредственно я сам не использую characters, приходиться перекодировать при помощи модуля Encode.

Кроме этих модулей, обычно все работают с octets.

А вот при работе над магазинчиком вышивки бисером и нитками Embroidery Kits выяснилось, что остальные используемый модули могут работать как с octets, так и с characters (кроме Digest::SHA).

HTML::Parser и JSON::XS перетянули одеяло на себя. Задумался.

P.S.
Utf8 флаг в сложных структурах данных расставляю, сбрасываю при помощи нижеприведенного кода.

use Encode;
use Scalar::Util qw(looks_like_number);


sub data_walk($$);
sub data_walk($$) {
  my ($d,$s) = @_;
  if (ref $d eq "ARRAY") {
    $d = [ map { data_walk($_, $s) } @$d ];
  } elsif (ref $d eq "HASH") {
    $d = { map { $s->($_) => data_walk($$d{$_}, $s) } keys %$d };
  } elsif (not ref $d) {
    $d = $s->($d)
  }
  return $d;
}


sub data_encode_utf8 { data_walk(shift,
    sub {
      my $data = shift;
      if ($data and not looks_like_number($data)) {
        $data = Encode::encode_utf8($data) if Encode::is_utf8($data);
      }
      return $data;
    }
  )
}


sub data_decode_utf8 { data_walk(shift,
    sub {
      my $data = shift;
      if ($data and not looks_like_number($data)) {
        $data = Encode::decode_utf8($data, Encode::FB_QUIET) unless Encode::is_utf8($data);
        $data ||= "ERROR: FOR SOME REASON, TEXT CONVERSION TO UTF8 FAILED";
      }
      return $data;
    }
  )
}

Комментариев нет: