+ my ($cat, $name) = split m{/}, $get{map}, 2 or die "invalid map\n";
+ if (!$name) {
+ ($cat, $name) = ('table', $cat);
+ }
+
+ my $row = $groupinfo->{$cat}->{$name}
+ or die "unknown character group $cat/$name\n";
+ my $query = $row->{query};
+
+ my @map;
+ for (map { split /[^\d-]/ } $query) {
+ my @range = split /-/, $_, 2;
+ m/^[0-9]+$/ or die "Invalid code point $_ in query $query\n" for @range;
+ push @map, $_ for $range[0] .. ($range[1] // $range[0]);
+ }
+ return \@map;
+ };
+ Abort($@, '404 invalid query') if $@;
+
+ require Unicode::UCD;
+
+ my $pagerows = 0x200;
+ my $pagecols = 32;
+ my $offset = eval {
+ local $_ = $get{q} || 0;
+ return $_ if /\A\d+\z/; # numeric
+ return hex $1 if /\A (?: 0?x | u\W* ) ([0-9a-f]+) \z/ix; # hexadecimal
+ return $_->[0]->[0] for Unicode::UCD::charblock(ucfirst) || (); # block
+ die "Unknown offset query '$_'\n";
+ };
+ Abort($@, '400 invalid offset') if $@;