to 255 (inclusive) are by default not encoded in UTF-8 Unicode for
backward compatibility reasons (but see L<encoding>).
+Negative values give the Unicode replacement character (chr(0xfffd)),
+except under the L</bytes> pragma, where low eight bits of the value
+(truncated to an integer) are used.
+
If NUMBER is omitted, uses C<$_>.
For the reverse, use L</ord>.
{
dSP; dTARGET;
char *tmps;
- UV value = POPu;
+ UV value;
+
+ if (((SvIOK_notUV(TOPs) && SvIV(TOPs) < 0)
+ ||
+ (SvNOK(TOPs) && SvNV(TOPs) < 0.0))) {
+ if (IN_BYTES) {
+ value = POPu; /* chr(-1) eq chr(0xff), etc. */
+ } else {
+ (void) POPs; /* Ignore the argument value. */
+ value = UNICODE_REPLACEMENT;
+ }
+ } else {
+ value = POPu;
+ }
SvUPGRADE(TARG,SVt_PV);
require "test.pl";
}
-plan tests => 26;
+plan tests => 34;
# Note that t/op/ord.t already tests for chr() <-> ord() rountripping.
is(chr(128), "\x80");
is(chr(255), "\xFF");
-# is(chr(-1), undef); # Shouldn't it be?
+is(chr(-0.1), "\x{FFFD}"); # The U+FFFD Unicode replacement character.
+is(chr(-1 ), "\x{FFFD}");
+is(chr(-2 ), "\x{FFFD}");
+is(chr(-3.0), "\x{FFFD}");
+{
+ use bytes; # Backward compatibility.
+ is(chr(-0.1), "\x00");
+ is(chr(-1 ), "\xFF");
+ is(chr(-2 ), "\xFE");
+ is(chr(-3.0), "\xFD");
+}
# Check UTF-8.
-sub hexes { join(" ",map{sprintf"%02x",$_}unpack("C*",chr($_[0]))) }
+sub hexes {
+ no warnings 'utf8'; # avoid surrogate and beyond Unicode warnings
+ join(" ",map{sprintf"%02x",$_}unpack("C*",chr($_[0])));
+}
# The following code points are some interesting steps in UTF-8.
is(hexes( 0x100), "c4 80");