package Data::Hive::Store::Param; use strict; use warnings; =head1 NAME Data::Hive::Store::Param =head1 DESCRIPTION CGI-like param() store for Data::Hive. =head1 METHODS =head2 new # use default method name 'param' my $store = Data::Hive::Store::Param->new($obj); # use different method name 'info' my $store = Data::Hive::Store::Param->new($obj, { method => 'info' }); # escape certain characters in keys my $store = Data::Hive::Store::Param->new($obj, { escape => './!' }); Return a new param() store. Several interesting arguments can be passed in a hashref after the first (mandatory) object argument. =over =item * method Use a different method name on the object (default is 'param'). =item * escape List of characters to escape (prepend '\' to) in keys. Defaults to the C<< separator >>. =item * separator String to join path segments together with; defaults to either the first character of the C<< escape >> option (if given) or '.'. =item * exists Coderef that describes how to see if a given parameter name (C<< separator >>-joined path) exists. The default is to treat the object like a hashref and look inside it. =item * delete Coderef that describes how to delete a given parameter name. The default is to treat the object like a hashref and call C on it. =back =cut sub _escape { my ($self, $str) = @_; my $escape = $self->{escape} or return $str; $str =~ s/([\Q$escape\E%])/sprintf("%%%x", ord($1))/ge; return $str; } sub _path { my ($self, $path) = @_; return join $self->{separator}, map { $self->_escape($_) } @$path; } =head2 new my $store = Data::Hive::Store::Param->new($obj, \%arg); =cut sub new { my ($class, $obj, $arg) = @_; $arg ||= {}; $arg->{escape} ||= $arg->{separator} || '.'; $arg->{separator} ||= substr($arg->{escape}, 0, 1); $arg->{method} ||= 'param'; $arg->{exists} ||= sub { exists $obj->{shift()} }; $arg->{delete} ||= sub { delete $obj->{shift()} }; $arg->{obj} = $obj; return bless { %$arg } => $class; } sub _param { my $self = shift; my $meth = $self->{method}; my $path = $self->_path(shift); return $self->{obj}->$meth($path, @_); } =head2 get Join the path together with the C<< separator >> and get it from the object. =cut sub get { my ($self, $path) = @_; return $self->_param($path); } =head2 set See L. =cut sub set { my ($self, $path, $val) = @_; return $self->_param($path => $val); } =head2 name Join path together with C<< separator >> and return it. =cut sub name { my ($self, $path) = @_; return $self->_path($path); } =head2 exists Return true if the C<< name >> of this hive is a parameter. =cut sub exists { my ($self, $path) = @_; my $code = $self->{exists}; my $key = $self->_path($path); return ref($code) ? $code->($key) : $self->{obj}->$code($key); } =head2 delete Delete the entry for the C<< name >> of this hive and return its old value. =cut sub delete { my ($self, $path) = @_; my $code = $self->{delete}; my $key = $self->_path($path); return ref($code) ? $code->($key) : $self->{obj}->$code($key); } 1;