带有替换的Blob.decode似乎不起作用

jjm*_*elo 8 encoding perl6

这段代码:

my $þor-blob = Blob.new("þor".ords);
$þor-blob.decode( "ascii", :replacement("0"), :strict(False) ).say
Run Code Online (Sandbox Code Playgroud)

失败:

Will not decode invalid ASCII (code point > 127 found)?
Run Code Online (Sandbox Code Playgroud)

还有这个:

my $euro = Blob.new("3€".ords);
$euro.decode( "latin1", :replacement("euro") ).say
Run Code Online (Sandbox Code Playgroud)

根本不起作用,用¬代替€。

确实,这些方法没有经过测试,但是语法正确吗?

rai*_*iph 7

TL; DR

  • 只有samcv或其他核心开发人员才能提供权威的答案。这是我对所看到的代码,注释和结果的理解。

  • 如果我的理解是正确的,则需要整理一些文档和/或代码来表达这种想法。1个

  • 指定$replacement参数与不匹配的P6核心多重方法不同。我们称其为“替换”代码路径。

  • “替换器”代码路径将$replacement$strict参数传递到nqp中的代码路径,后者又将它们传递到后端中处理替换的代码路径中。

  • 在MoarVM后端,对于Windows1252,Windows1251和shiftjis编码,将replace和strict参数传递到解码器,但对于其他编码,则不传递。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))
}
Run Code Online (Sandbox Code Playgroud)

nqp::decoderepconf函数直接映射到后端中的相应函数。

在MoarVM后端,它MVM_string_decode_from_buf_config位于中ops.c

依次调用MVM_string_decode_config同一文件。

从后一个函数的注释中,有几个关键的句子大概可以解释替换和严格性参数的相关性:

与不同MVM_string_decode,它不会通过没有正式映射的代码点。

目前,只有Windows-1252和Windows-1251可以有所作为。

对代码进行拼写并提交到存储库中,表明后者的注释有点过时了,因为它似乎也应该对shiftjis有所帮助。

同样,要明确的是,如果$replacement在P6中指定了自变量,则如果解码除窗口或shiftjis编码以外的任何其他编码,则该自$strict变量最终将被忽略(并$strict = True假定)。2

特别是ascii和latin1会发生什么

当前代码MVM_string_decode_config传递更换/严格参数给MVM_string_ascii_decodeMVM_string_latin1_decode功能。

因此,如果您使用编码“ ascii”,那么blob只能包含0到127之间的值,而对于“ latin1”,该值必须介于0到255之间。

say "þor".ords; # (254 111 114)
say "3€".ords;  # (51 8364)
Run Code Online (Sandbox Code Playgroud)

第一个字符串(作为a Buf)无法解码,而是产生一条错误消息,因为254大于127,并且MoarVM中的ascii解码器代码通过抛出带有“无效ASCII”消息的异常来对无效值做出反应。

第二个替换¬。这是因为默认情况下,a Buf是一个8位数组,因此大于255的值将被截断为其低字节,for ¬(在latin1和Unicode中)相同。3

但是,如果您使用Buf具有更大元素大小的,这并没有更好。结果还是¬,再加上豆腐。我可以看到,即使我可以不是C所以很明显,我认为MVM_string_latin1_decode在MoarVM功能解码Latin1则不抛出异常。因此,大概当它遇到0-255范围以外的字符值时,会将较高的字节转换为豆腐。

脚注

1当然,JJ所做的正是使他们首先发布此SO的事情是修复了文档。我添加了此脚注,以便其他以后的读者理解该上下文,并意识到此SO导致文档中的更改,并且可能导致代码更改,这可能由于完成的工作而使SO毫无意义。

2如果$replacement指定编码的解码器对参数不执行任何操作,那么如果有多个拒绝使用该参数,那就太好了。

3请参阅下面的timotimo ++注释。

  • 这个问题的latin1部分的更精确答案是,默认情况下,`Blob.new`是`Blob [uint8] .new`,它将截断传递给8位的值。这就是为什么您会得到一个“¬”的原因,因为它是由“ 0xac”编码的 (2认同)
  • @jjmerelo“`$ replacement`没有区别。” 根据我对MoarVM代码和注释的阅读,它适用于两种Windows编码和shiftjis编码,但不适用于其他编码(例如ascii和latin1)。我已经编辑了问题,以使我的回答尽可能清楚。 (2认同)