App-Music-ChordPro
view release on metacpan or search on metacpan
lib/ChordPro/Utils.pm view on Meta::CPAN
use Text::ParseWords qw(quotewords);
my @words = quotewords( '\s+', 1, @lines );
parse_kv( \@words );
}
push( @EXPORT, 'parse_kvm' );
# Odd/even.
sub is_odd( $arg ) {
( $arg % 2 ) != 0;
}
sub is_even( $arg ) {
( $arg % 2 ) == 0;
}
push( @EXPORT, qw( is_odd is_even ) );
# Map true/false etc to true / false.
sub is_true ( $arg ) {
return 0 if !defined($arg) || $arg eq '';
return 0 if $arg =~ /^(false|null|no|none|off|\s+|0)$/i;
return !!$arg;
}
push( @EXPORT, 'is_true' );
# Stricter form of true.
sub is_ttrue ( $arg ) {
return 0 if !defined($arg);
$arg =~ /^(on|true|1)$/i;
}
push( @EXPORT, 'is_ttrue' );
# Fix apos -> quote.
sub fq ( $arg ) {
$arg =~ s/'/\x{2019}/g;
$arg;
}
push( @EXPORT, 'fq' );
# Quote a string if needed unless forced.
sub qquote ( $arg, $force = 0 ) {
for ( $arg ) {
s/([\\\"])/\\$1/g;
s/([[:^print:]])/sprintf("\\u%04x", ord($1))/ge;
return $_ unless /[\\\s]/ || $force;
return qq("$_");
}
}
push( @EXPORT, 'qquote' );
# Safely print values.
use Scalar::Util qw(looks_like_number);
# We want overload:
# sub pv( $val )
# sub pv( $label, $val )
sub pv {
my $val = pop;
my $label = pop // "";
my $suppressundef;
if ( $label =~ /\?$/ ) {
$suppressundef++;
$label = $';
}
if ( defined $val ) {
if ( looks_like_number($val) ) {
$val = sprintf("%.3f", $val);
$val =~ s/0+$//;
$val =~ s/\.$//;
}
else {
$val = qquote( $val, 1 );
}
}
else {
return "" if $suppressundef;
$val = "<undef>"
}
defined wantarray ? $label.$val : warn($label.$val."\n");
}
push( @EXPORT, 'pv' );
# Processing JSON.
my $_json_xs;
my $_json_rr;
our $json_last;
sub json_load( $json, $source = "<builtin>" ) {
# We have two JSON parsers: Relaxed and XS.
# Relaxed accepts a lot of relaxing extensions, but XS is much
# much faster. So fast, in fact, that trying XS first will be a
# win in many cases, and a neglectable overhead in the other
# cases.
state $jx = JSON::XS->new;
$jx->relaxed;
# Glue lines, so we have at lease some relaxation.
$json =~ s/"\s*\\\r?\n\s*"//g;
my $data;
$json_last = "xs";
eval { $data = $jx->decode($json."\n"); $_json_xs++ };
return $data if defined $data;
require JSON::Relaxed;
state $jr = JSON::Relaxed::Parser->new( croak_on_error => 0,
strict => 0,
prp => 1 );
$_json_rr++;
$json_last = "rr";
$data = $jr->decode($json."\n");
return $data unless $jr->is_error;
$source .= ": " if $source;
die("${source}JSON error: " . $jr->err_msg . "\n");
}
sub json_stats( $reset = 0 ) {
my $res = { xs => $_json_xs//0, rr => $_json_rr//0 };
if ( $reset ) {
$_json_xs = $_json_rr = 0;
}
return $res;
( run in 2.847 seconds using v1.01-cache-2.11-cpan-437f7b0c052 )