这段代码:
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)
根本不起作用,用¬代替€。
确实,这些方法没有经过测试,但是语法正确吗?
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
当前代码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)
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 ++注释。