diff --git a/lib/perl5i.pm b/lib/perl5i.pm index 77a61bb..6b3782c 100644 --- a/lib/perl5i.pm +++ b/lib/perl5i.pm @@ -367,6 +367,25 @@ Rounds the $number towards negative infinity. floor() is a synonyn for round_down(). +=head3 round_to_nearest + + my $new_number = $number->round_to_nearest($nearest); + +Rounds the $number to the closest $nearest. + + 13->round_to_nearest(5); # 15 + 1.23->round_to_nearest(.05); # 1.25 + +=head3 round_to_precision + + my $new_number = $number->round_to_precision($precision); + +Rounds $number to $precision digits past the decimal point. The value of +$precision is expected to be a positive integer, any other value will +result in an exception. + + 5.625512332->round_to_precision(3); # 5.626 + 5.5->round_to_precision(10); # 5.5 =head3 is_number diff --git a/lib/perl5i/2/SCALAR.pm b/lib/perl5i/2/SCALAR.pm index 940bfec..5eb116a 100644 --- a/lib/perl5i/2/SCALAR.pm +++ b/lib/perl5i/2/SCALAR.pm @@ -62,7 +62,6 @@ sub rtrim { sub trim { my $charset = $_[1]; - return rtrim(ltrim($_[0], $charset), $charset); } @@ -146,6 +145,20 @@ sub round { } } +sub round_to_nearest{ + my ($number,$nearest) = @_; + return ($number/$nearest)->round * $nearest; +} + +sub round_to_precision{ + my ($number,$precision) = @_; + my $used_precision = int(abs($precision)); + Carp::Fix::1_25::croak('round_to_precision does not support non-positive non-integer values.') + unless $used_precision == $precision; + my $pre = '1'. '0'x $used_precision; + return ($number*$pre)->round / $pre; +} + require Scalar::Util; *is_number = \&Scalar::Util::looks_like_number; sub is_positive { $_[0]->is_number && $_[0] > 0 } diff --git a/lib/perl5i/IO.pm b/lib/perl5i/IO.pm new file mode 100644 index 0000000..42eec51 --- /dev/null +++ b/lib/perl5i/IO.pm @@ -0,0 +1,82 @@ +package perl5i::IO; + +use strict; +use warnings; + +use IO::All; +use IO::All::LWP; + + +# This is IO::All->new but with most of the magic +# stripped out. +sub safer_io { + my $name = shift; + + # No name, return an empty io() object. + return io() unless defined $name; + + # Its an IO::All object, return it. + return $name if UNIVERSAL::isa($name, 'IO::All'); + + my $io = io(); + + # Its a filehandle + return $io->handle($name) + if UNIVERSAL::isa($name, 'GLOB') or ref(\ $name) eq 'GLOB'; + + # link is first because a link to a dir returns true for + # both -l and -d. + return $io->link($name) if -l $name; + return $io->file($name) if -f $name; + return $io->dir($name) if -d $name; + + # Maybe its a file they're going to write to later + $io->name($name); + return $io; +} + + +{ + package IO::All; + + use strict; + use warnings; + + sub url { + my $self = shift; + my $url = shift; + + my($method) = $url =~ /^([a-z]+):/; + $method ||= "http"; + $method = "file_url" if $method eq 'file'; + + # $self->can($scheme) or + # croak "url() does not know how to open scheme type $scheme"; + + return $self->$method($url); + } +} + + +{ + package IO::All::FILE_URL; + + # Convince IO::All that we exist + $INC{"IO/All/FILE_URL.pm"} = 1; + + use strict; + use warnings; + + use IO::All::LWP "-base"; + + const type => "file"; + + sub file_url { + my $self = shift; + + return $self->lwp_init(__PACKAGE__, @_); + } +} + + +1; diff --git a/t/io-url.t b/t/io-url.t new file mode 100644 index 0000000..b65fae0 --- /dev/null +++ b/t/io-url.t @@ -0,0 +1,29 @@ +#!/usr/bin/perl -w + +use perl5i; +use Test::More; +use Test::Exception; + +chdir 't'; + +# Test we can talk to a file URL +{ + "hello\nstuff\n" > io("io-url-test"); + ok -e "io-url-test"; + END { unlink "io-url-test" } + + is io->url("file://$CWD/io-url-test")->slurp, "hello\nstuff\n"; +} + + +# Test that we normally won't try to open a URL +{ + throws_ok { + io("http://www.google.com")->all; + } qr{^Can't open file 'http://www.google.com' for input}, + "io() won't open a URL as a URL"; +} + + +done_testing(); + diff --git a/t/io.t b/t/io.t new file mode 100644 index 0000000..d3601ce --- /dev/null +++ b/t/io.t @@ -0,0 +1,13 @@ +#!/usr/bin/perl -w + +use perl5i; +use Test::More; + +chdir 't'; + +"hello" > io("io-test"); +END { unlink "io-test" } + +is io("io-test")->slurp, "hello"; + +done_testing(); diff --git a/t/number.t b/t/number.t index d155b95..bc72ebb 100644 --- a/t/number.t +++ b/t/number.t @@ -23,6 +23,14 @@ is( (-3.51)->round, -4 ); is( (-3.5)->round, -4 ); is( (-3.49)->round, -3 ); +is( 13->round_to_nearest(5), 15); +is( 1.23->round_to_nearest(.05), 1.25); + +is( 5.625512332->round_to_precision(3), 5.626); +is( 5.5->round_to_precision(10), 5.5); +eval{5.5->round_to_precision(-10.3)}; +like( $@, qr/^round_to_precision does not support non-positive non-integer values/); + ok( 12->is_number ); ok(!'FF'->is_number );