TL; DR :
Только samcv или какой-либо другой основной разработчик может дать достоверный ответ.Это мое понимание кода, комментариев и результатов, которые я вижу.
Если мое понимание правильное, необходимо разобраться с каким-то документом и / или кодом, чтобы воспроизвести этот SO спорный вопрос. 1
Задание аргумента $replacement
соответствует другому многопараметрическому методу P6, чем это невозможно.Давайте назовем его «путь кода замены».
Путь кода «замена» передает аргументы $replacement
и $strict
в путь кода в nqp, который, в свою очередь, передает их напуть кода в бэкэнде, который обрабатывает замены.
В бэкэнде MoarVM аргументы замены и строгого режима передаются в декодеры для кодировок windows1252, windows1251 и shiftjis , ноне для других кодировок . 2
по соответствующему пути кода
Ваш код вызывает этот код в Buf.pm6
:
multi method decode(Blob:D: $encoding,
Str :$replacement!,
Bool:D :$strict = False) {
nqp::p6box_s(
nqp::decoderepconf(
self,
Rakudo::Internals.NORMALIZE_ENCODING($encoding),
$replacement.defined ?? $replacement !! nqp::null_s(),
$strict ?? 0 !! 1))
}
Функция nqp::decoderepconf
напрямую отображается на соответствующую функцию в бэкенде.
В бэкэнде MoarVM это MVM_string_decode_from_buf_config
в ops.c
.
Это, в свою очередь, вызывает MVM_string_decode_config
в том же файле.
Из комментариев этой последней функции есть пара ключевых предложений, которые предположительно объясняютАктуальность замены и аргументы строгости:
Unlike MVM_string_decode
, он не будет проходить через кодовые точки, которые не имеют официального отображения.
На данный момент Windows-1252 и Windows-1251 - единственные, на которых есть разница.
Из-за написания кода и коммитов в репозитории последний комментарий немного устарел, потому что похоже, что он должен иметь значение и для shiftjis.
Также, чтобы было понятно, если указать $replacement
аргумент в P6, тогда аргумент $strict
в конечном итоге будет игнорироваться (и предполагается $strict = True
) при декодировании любой кодировки, кроме кодировок windows или shiftjis. 2
Что происходит с ascii и latin1, в частности
Текущий код для MVM_string_decode_config
не передает аргументы замены / строгости в функции MVM_string_ascii_decode
и MVM_string_latin1_decode
.
Таким образом, если вы используете кодировку «ascii», то двоичный объект должен содержать только значения от 0 до 127, а для «latin1» значения должны быть в диапазоне от 0 до 255.
say "þor".ords; # (254 111 114)
say "3€".ords; # (51 8364)
Первыйстрока (какBuf
) не удается декодировать, и вместо этого выдает сообщение об ошибке, потому что 254 больше 127 и код декодера ascii в MoarVM реагирует на недопустимое значение, выдавая исключение с «недопустимым ASCII»сообщение.
Второй заменяет €
на ¬
.Это связано с тем, что по умолчанию Buf
представляет собой 8-битный массив, поэтому значение выше 255 усекается до его младшего байта, что для €
совпадает с ¬
(как в latin1, так и в Unicode). 3
Но не лучше, если вы используете Buf
с большим размером элемента.Результат по-прежнему ¬
в сочетании с тофу .Я могу видеть, даже если я не могу C, так что для меня ясно, что функция MVM_string_latin1_decode
в MoarVM , которая декодирует latin1, не генерирует исключения.Таким образом, по-видимому, когда он встречает символьные значения вне диапазона 0-255, он превращает старшие байты в тофу.
Сноски
1 Конечно, JJ делает именно то, что делаетзаставил их опубликовать это ТАК, в первую очередь это исправление документа.Я добавил эту сноску, чтобы другие более поздние читатели поняли этот контекст и осознали, что этот SO ведет к изменениям в документе и может привести к изменениям в коде, что, по-видимому, сделает этот SO спорным из-за проделанной работы.
2 Было бы неплохо, если бы Multis отклонил использование аргумента $replacement
, если декодер для указанной кодировки ничего с этим не делает.
3 См. Комментарий timotimo ++ ниже.