Config-Properties
view release on metacpan or search on metacpan
lib/Config/Properties.pm view on Meta::CPAN
# escape_key(string), escape_value(string), unescape(string) -
# subroutines to convert escaped characters to their
# real counterparts back and forward.
my %esc = ( "\n" => 'n',
"\r" => 'r',
"\t" => 't' );
my %unesc = reverse %esc;
sub escape_key {
$_[0]=~s{([\t\n\r\\"' =:])}{
"\\".($esc{$1}||$1) }ge;
$_[0]=~s{([^\x20-\x7e])}{sprintf "\\u%04x", ord $1}ge;
$_[0]=~s/^ /\\ /;
$_[0]=~s/^([#!])/\\$1/;
$_[0]=~s/(?<!\\)((?:\\\\)*) $/$1\\ /;
}
sub escape_value {
$_[0]=~s{([\t\n\r\\])}{
"\\".($esc{$1}||$1) }ge;
$_[0]=~s{([^\x20-\x7e])}{sprintf "\\u%04x", ord $1}ge;
$_[0]=~s/^ /\\ /;
}
sub unescape {
$_[0]=~s/\\([tnr\\"' =:#!])|\\u([\da-fA-F]{4})/
defined $1 ? $unesc{$1}||$1 : chr hex $2 /ge;
}
sub read_line {
my ($self, $file) = @_;
my $bin = \$self->{buffer_in};
my $line_re = $self->{line_re};
while (1) {
if ($$bin =~ s/$line_re//) {
$self->{last_line_number}++;
return $1;
}
else {
my $bytes = read($file, $$bin, 8192, length $$bin);
last unless $bytes or (not defined $bytes and
($! == Errno::EGAIN() or
$! == Errno::EWOULDBLOCK() or
$! == Errno::EINTR()));
}
}
if (length $$bin) {
$self->{last_line_number}++;
my $line = $$bin;
$$bin = '';
return $line
}
undef;
}
# process_line() - read and parse a line from the properties file.
# this is to workaround a bug in perl 5.6.0 related to unicode
my $bomre = eval(q< qr/^\\x{FEFF}/ >) || qr//;
sub process_line {
my ($self, $file) = @_;
my $line = $self->read_line($file);
defined $line or return undef;
# remove utf8 byte order mark
my $ln = $self->{last_line_number};
$line =~ s/$bomre// if $ln < 2;
# ignore comments
$line =~ /^\s*(\#|\!|$)/ and return 1;
# handle continuation lines
my @lines;
while ($line =~ /(\\+)$/ and length($1) & 1) {
$line =~ s/\\$//;
push @lines, $line;
$line = $self->read_line($file);
$line = '' unless defined $line;
$line =~ s/^\s+//;
}
$line = join('', @lines, $line) if @lines;
my ($key, $value) = $line =~ /^
\s*
((?:[^\s:=\\]|\\.)+)
\s*
[:=\s]
\s*
(.*)
$
/x
or $self->fail("invalid property line '$line'");
unescape $key;
unescape $value;
$self->validate($key, $value);
$self->{property_line_numbers}{$key} = $ln;
$self->{properties}{$key} = $value;
return 1;
}
sub validate {
my $self=shift;
my $validator = $self->{validator};
if (defined $validator) {
&{$validator}(@_, $self) or $self->fail("invalid value '$_[1]' for '$_[0]'");
}
}
# line_number() - number for the last line read from the configuration file
sub line_number { shift->{last_line_number} }
( run in 0.672 second using v1.01-cache-2.11-cpan-39bf76dae61 )