DMS-Parser
view release on metacpan or search on metacpan
lib/DMS/Parser.pm view on Meta::CPAN
sub _utf8_die {
my ($s, $i) = @_;
my $prefix = substr($s, 0, $i);
my $line = 1 + ($prefix =~ tr/\n//);
my $last_nl = rindex($prefix, "\n");
my $col = $i - ($last_nl + 1) + 1;
die "$line:$col: input is not valid UTF-8\n";
}
# Shared input-normalization for every public decode entry point.
# SPEC §"UTF-8 only, NFC-normalized": reject BOM at offset 0, reject
# malformed UTF-8 bytes (5/6-byte forms, > U+10FFFF, lone continuation
# bytes, overlongs, surrogates), reject U+0000 anywhere, then NFC the
# source. Returns the (possibly NFC'd) Perl-internal-encoded string.
sub _normalize_source {
my ($src) = @_;
# SPEC §"UTF-8 only, NFC-normalized": DMS source is plain UTF-8 with
# no byte-order mark. A leading U+FEFF is not silently consumed â
# reject it explicitly so encoding mistakes surface loudly. (BOMs
# *inside* string/heredoc bodies are fine; this only fires at offset 0.)
# We check for the raw UTF-8 BOM bytes (EF BB BF) before any decoding,
# so the rejection is independent of how the caller passed `$src`.
if (!utf8::is_utf8($src) && length($src) >= 3
&& substr($src, 0, 3) eq "\xEF\xBB\xBF") {
die "1:1: BOM (U+FEFF) at file start is not allowed; DMS source is plain UTF-8\n";
}
# SPEC §"UTF-8 only": reject malformed UTF-8 bytes (codepoints
# > U+10FFFF, lone continuation bytes, overlongs, surrogates encoded
# as bytes). Perl's `utf8::decode` is permissive about 5/6-byte
# forms and codepoints above U+10FFFF, so we additionally walk the
# raw bytes to confirm strict UTF-8 conformance.
if (!utf8::is_utf8($src)) {
_validate_strict_utf8($src);
my $copy = $src;
if (!utf8::decode($copy)) {
die "1:1: input is not valid UTF-8\n";
}
$src = $copy;
}
if (length($src) >= 1 && substr($src, 0, 1) eq "\x{FEFF}") {
die "1:1: BOM (U+FEFF) at file start is not allowed; DMS source is plain UTF-8\n";
}
# U+0000 is not allowed anywhere in DMS source (see SPEC §Strings).
if ((my $nul = index($src, "\0")) >= 0) {
my $prefix = substr($src, 0, $nul);
my $line = 1 + ($prefix =~ tr/\n//);
my $last_nl = rindex($prefix, "\n");
my $col = $nul - ($last_nl + 1) + 1;
die "$line:$col: U+0000 (NUL) is not allowed in DMS source\n";
}
# SPEC §Unicode normalization: NFC the source before tokenization.
( run in 0.511 second using v1.01-cache-2.11-cpan-9581c071862 )