String-Smart
view release on metacpan or search on metacpan
lib/String/Smart.pm view on Meta::CPAN
add_rep reversed => sub { reverse $_[0] }, sub { reverse $_[0] };
my $this = "Hello";
my $that = reversed "Hello";
print as reversed => $this, "\n";
# prints "olleH"
print as reversed => $that, "\n";
# also prints "olleH"
A representation consists of a name and two subroutine references. The
first subroutine applies the encoding, the second reverses it. If either
subroutine is undefined a boilerplate subroutine that throws a
descriptive error will be used in its place.
=cut
sub add_rep($$$) {
my ( $name, $to, $from ) = @_;
croak "$name contains an underscore"
if $name =~ /_/;
my %spec = ( from => $from, to => $to );
for my $dir ( keys %spec ) {
unless ( defined $spec{$dir} ) {
$spec{$dir} = sub {
croak "Don't know how to convert $dir $name";
};
}
}
$rep_map{$name} = \%spec;
}
=head2 C<< as >>
Coerce a string into the specified encoding.
my $representation = as html => $some_string;
Optionally multiple encodings my be supplied either like this:
my $rep = as html_nl2br => $some_string;
Or like this:
my $rep = as ['html', 'nl2br'], $some_string;
The returned object (actually a hash blessed to C<String::Smart>)
will have the specified encoding irrespective of it's current
encoding. For example the sequence:
my $html1 = as html => $some_string;
my $html2 = as html => $html1;
Does I<not> result in double encoding. The encodings you request are
'absolute'. A path of transformations that will convert the string from
whatever its current encoding is will be computed and applied.
=cut
sub as($$) {
my ( $desired, $str ) = @_;
my @desired
= map { split /_/ } 'ARRAY' eq ref $desired ? @$desired : $desired;
unless ( blessed $str && $str->isa( __PACKAGE__ ) ) {
$str = bless { val => $str, rep => [] };
}
my @got_rep = $str->rep;
my @want_rep = @desired;
# Prune common reps
while ( @got_rep && @want_rep && $got_rep[0] eq $want_rep[0] ) {
shift @got_rep;
shift @want_rep;
}
$str = $str->{val};
for my $spec ( [ 'from', reverse @got_rep ], [ 'to', @want_rep ] ) {
my $dir = shift @$spec;
for my $rep ( @$spec ) {
my $handler = $rep_map{$rep} || croak "Don't know about $rep";
$str = $handler->{$dir}->( $str );
}
}
return bless {
val => $str,
rep => \@desired,
};
}
=head2 C<< already >>
Declare that a string is already encoded in a particular way. For example:
my $html = already html => '<p>This is a paragraph</p>';
my $text = 'This is just << some text >>';
print literal html => $html;
# already HTML encoded
# prints
# <p>This is a paragraph</p>
print literal html => $text;
# applies HTML encoding
# prints
# This is just << some text >>
=cut
sub already($$) {
return bless {
val => $_[1],
rep => [ map { split /_/ } 'ARRAY' eq ref $_[0] ? @$_[0] : $_[0] ]
};
}
( run in 1.031 second using v1.01-cache-2.11-cpan-524268b4103 )