这段代码:
my $þor-blob = Blob.new("þor".ords);
$þor-blob.decode( "ascii", :replacement("0"), :strict(False) ).say
失败:
Will not decode invalid ASCII (code point > 127 found)
还有这个:
my $euro = Blob.new("3€".ords);
$euro.decode( "latin1", :replacement("euro") ).say
似乎没有用,取代¬。
这是真的,those methods are not tested,但语法是正确的?
TL; DR:
$replacement
参数匹配不同的P6核心多方法而不是不这样做。我们称之为“替代者”代码路径。$replacement
和$strict
参数传递到nqp中的代码路径,然后将它们传递到处理替换的后端的代码路径中。你的代码调用this code in 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
in ops.c
。
这反过来在同一个文件中调用MVM_string_decode_config
。
从后一个函数的评论中,有几个关键句子可能解释了替换和严格性论点的相关性:
与
MVM_string_decode
不同,它不会通过没有官方映射的代码点。现在,windows-1252和windows-1251是唯一有所作为的。
对代码进行处理并在回购中提交建议后一条评论稍微过时,因为看起来它应该对shiftjis产生影响。
另外,要清楚的是,如果在P6中指定了$replacement
参数,那么如果解码除windows或shiftjis编码之外的任何编码,$strict
参数将最终被忽略(并且$strict = True
假设)。
MVM_string_decode_config
的当前代码不传递MVM_string_ascii_decode
和MVM_string_latin1_decode
函数的替换/严格性参数。
因此,如果使用编码“ascii”,则blob必须仅包含0到127之间的值,对于“latin1”,值必须介于0到255之间。
say "þor".ords; # (254 111 114)
say "3€".ords; # (51 8364)
第一个字符串(作为Buf
)无法解码,而是产生错误消息,因为254大于127并且the ascii decoder code in MoarVM通过使用“invalid ASCII”消息抛出异常来对无效值做出反应。
第二个用€
替换¬
。这是因为默认情况下,Buf
是一个8位数组,因此高于255的值会被截断为低字节,€
与¬
相同(在latin1和Unicode中).3
但是,如果你使用更大元素尺寸的Buf
,那就不错了。结果仍然是¬
,加上tofu。我可以看到,即使我不能C,所以我很清楚解释latin1的the MVM_string_latin1_decode
function in MoarVM不会抛出异常。因此,当它遇到0-255范围之外的字符值时,它会将更高的字节变成豆腐。
1当然,JJ正在做的事情导致他们首先发布这个SO正在修复文档。我添加了这个脚注,以便其他后来的读者能够理解上下文,并意识到这个SO正在导致文档中的更改,并且可能导致代码的更改,这可能会因为完成的工作而导致这样的SO。
2如果指定编码的解码器没有对它做任何事情,那么如果有multis拒绝使用$replacement
参数,那将是很好的。
3请参阅下面的timotimo ++的评论。