| line | stmt | bran | cond | sub | pod | time | code | 
| 1 |  |  |  |  |  |  | #----------------------------------------------------------------- | 
| 2 |  |  |  |  |  |  | # Proc::Async::Config | 
| 3 |  |  |  |  |  |  | # Author: Martin Senger | 
| 4 |  |  |  |  |  |  | # For copyright and disclaimer se below. | 
| 5 |  |  |  |  |  |  | # | 
| 6 |  |  |  |  |  |  | # ABSTRACT: Configuration helper | 
| 7 |  |  |  |  |  |  | # PODNAME: Proc::Async::Config | 
| 8 |  |  |  |  |  |  | #----------------------------------------------------------------- | 
| 9 |  |  |  |  |  |  |  | 
| 10 | 18 |  |  | 18 |  | 20877 | use warnings; | 
|  | 18 |  |  |  |  | 51 |  | 
|  | 18 |  |  |  |  | 737 |  | 
| 11 | 18 |  |  | 18 |  | 80 | use strict; | 
|  | 18 |  |  |  |  | 36 |  | 
|  | 18 |  |  |  |  | 648 |  | 
| 12 |  |  |  |  |  |  | package Proc::Async::Config; | 
| 13 |  |  |  |  |  |  |  | 
| 14 | 18 |  |  | 18 |  | 76 | use Carp; | 
|  | 18 |  |  |  |  | 23 |  | 
|  | 18 |  |  |  |  | 15919 |  | 
| 15 |  |  |  |  |  |  |  | 
| 16 |  |  |  |  |  |  | our $VERSION = '0.2.0'; # VERSION | 
| 17 |  |  |  |  |  |  |  | 
| 18 |  |  |  |  |  |  | #----------------------------------------------------------------- | 
| 19 |  |  |  |  |  |  | # Constructor. It reads a given configuration file (but does not | 
| 20 |  |  |  |  |  |  | # complain if the file does not exist yet). | 
| 21 |  |  |  |  |  |  | # | 
| 22 |  |  |  |  |  |  | # Arguments: | 
| 23 |  |  |  |  |  |  | #   config-file-name | 
| 24 |  |  |  |  |  |  | #   name/value pairs (at the moment, not used) | 
| 25 |  |  |  |  |  |  | # ----------------------------------------------------------------- | 
| 26 |  |  |  |  |  |  | sub new { | 
| 27 | 117 |  |  | 117 | 0 | 10800 | my ($class, @args) = @_; | 
| 28 |  |  |  |  |  |  |  | 
| 29 |  |  |  |  |  |  | # create an object | 
| 30 | 117 |  | 33 |  |  | 1076 | my $self = bless {}, ref ($class) || $class; | 
| 31 |  |  |  |  |  |  |  | 
| 32 |  |  |  |  |  |  | # a config file name is mandatory | 
| 33 | 117 | 100 |  |  |  | 625 | croak ("Missing config file name in the Proc::Async::Config constructor.\n") | 
| 34 |  |  |  |  |  |  | unless @args > 0; | 
| 35 | 116 |  |  |  |  | 497 | $self->{cfgfile} = shift @args; | 
| 36 |  |  |  |  |  |  |  | 
| 37 |  |  |  |  |  |  | # ...and the rest are optional name/value pairs | 
| 38 | 116 |  |  |  |  | 354 | my (%args) = @args; | 
| 39 | 116 |  |  |  |  | 628 | foreach my $key (keys %args) { | 
| 40 | 2 |  |  |  |  | 6 | $self->{$key} = $args {$key}; | 
| 41 |  |  |  |  |  |  | } | 
| 42 |  |  |  |  |  |  |  | 
| 43 | 116 |  |  |  |  | 472 | $self->clean();  # empty storage for the configuration properties | 
| 44 |  |  |  |  |  |  |  | 
| 45 |  |  |  |  |  |  | # load the configuration (if exists) | 
| 46 | 116 | 100 |  |  |  | 5662 | $self->load() | 
| 47 |  |  |  |  |  |  | if -e $self->{cfgfile}; | 
| 48 |  |  |  |  |  |  |  | 
| 49 |  |  |  |  |  |  | # done | 
| 50 | 116 |  |  |  |  | 519 | return $self; | 
| 51 |  |  |  |  |  |  | } | 
| 52 |  |  |  |  |  |  |  | 
| 53 |  |  |  |  |  |  | #----------------------------------------------------------------- | 
| 54 |  |  |  |  |  |  | # Remove all properties from all so far loaded configuration files (it | 
| 55 |  |  |  |  |  |  | # does it in memory, the files remain untouched). | 
| 56 |  |  |  |  |  |  | # ----------------------------------------------------------------- | 
| 57 |  |  |  |  |  |  | sub clean { | 
| 58 | 117 |  |  | 117 | 0 | 236 | my $self = shift; | 
| 59 | 117 |  |  |  |  | 406 | $self->{data} = {}; | 
| 60 |  |  |  |  |  |  | } | 
| 61 |  |  |  |  |  |  |  | 
| 62 |  |  |  |  |  |  | #-------------------------------------------------------------------- | 
| 63 |  |  |  |  |  |  | # Add properties from the given configuration files (or from the file | 
| 64 |  |  |  |  |  |  | # given in the constructor). | 
| 65 |  |  |  |  |  |  | # ----------------------------------------------------------------- | 
| 66 |  |  |  |  |  |  | sub load { | 
| 67 | 81 |  |  | 81 | 0 | 257 | my ($self, $cfgfile) = @_; | 
| 68 | 81 | 50 |  |  |  | 286 | $cfgfile = $self->{cfgfile} unless $cfgfile; | 
| 69 | 81 | 50 |  |  |  | 6330 | open (my $cfg, '<', $cfgfile) | 
| 70 |  |  |  |  |  |  | or croak ("Cannot open configuration file '$cfgfile': $!\n"); | 
| 71 | 81 |  |  |  |  | 482 | my $count = 0; | 
| 72 | 81 |  |  |  |  | 2261 | while (my $line = <$cfg>) { | 
| 73 | 1035 |  |  |  |  | 1426 | $count++; | 
| 74 |  |  |  |  |  |  |  | 
| 75 |  |  |  |  |  |  | # skipping comments and empty lines: | 
| 76 | 1035 | 50 |  |  |  | 2967 | $line =~ /^(\n|\#)/  and next; | 
| 77 | 1035 | 50 |  |  |  | 3278 | $line =~ /\S/        or  next; | 
| 78 | 1035 |  |  |  |  | 1954 | chomp $line; | 
| 79 | 1035 |  |  |  |  | 1867 | $line =~ s/^\s+//g; | 
| 80 | 1035 |  |  |  |  | 2424 | $line =~ s/\s+$//g; | 
| 81 |  |  |  |  |  |  |  | 
| 82 |  |  |  |  |  |  | # parsing key/value pairs | 
| 83 | 1035 |  |  |  |  | 4521 | my ($key, $value) = split (m{\s*=\s*}, $line, 2); | 
| 84 | 1035 | 50 | 33 |  |  | 4958 | if (not defined $key or $key eq '') { | 
| 85 |  |  |  |  |  |  | # unusable key | 
| 86 | 0 |  |  |  |  | 0 | carp "Missing key in the configuration file '$cfgfile' in line $count: '$line'. Ignored.\n"; | 
| 87 | 0 |  |  |  |  | 0 | next; | 
| 88 |  |  |  |  |  |  | } | 
| 89 | 1035 | 50 | 33 |  |  | 4956 | if (not defined $value or $value eq '') { | 
| 90 | 0 |  |  |  |  | 0 | $value = 1;   # an existing property must be an important property | 
| 91 |  |  |  |  |  |  | } | 
| 92 | 1035 |  |  |  |  | 2140 | $self->param ($key, $value); | 
| 93 |  |  |  |  |  |  | } | 
| 94 | 81 |  |  |  |  | 2003 | close $cfg; | 
| 95 |  |  |  |  |  |  | } | 
| 96 |  |  |  |  |  |  |  | 
| 97 |  |  |  |  |  |  | #----------------------------------------------------------------- | 
| 98 |  |  |  |  |  |  | # Return the value of the given configuration property, or undef if | 
| 99 |  |  |  |  |  |  | # the property does not exist. Depending on the context, it returns | 
| 100 |  |  |  |  |  |  | # the value as a scalar (and if there are more values for the given | 
| 101 |  |  |  |  |  |  | # property then it returns the first value only), or an array. | 
| 102 |  |  |  |  |  |  | # | 
| 103 |  |  |  |  |  |  | # Set the given property first if there is a second argument with the | 
| 104 |  |  |  |  |  |  | # property value. | 
| 105 |  |  |  |  |  |  | # | 
| 106 |  |  |  |  |  |  | # Return a sorted list of all property names if no argument given (the | 
| 107 |  |  |  |  |  |  | # list may be empty). | 
| 108 |  |  |  |  |  |  | # ----------------------------------------------------------------- | 
| 109 |  |  |  |  |  |  | sub param { | 
| 110 | 1515 |  |  | 1515 | 0 | 5119 | my ($self, $name, $value) = @_; | 
| 111 | 1515 | 100 |  |  |  | 3130 | unless (defined $name) { | 
| 112 | 6 |  |  |  |  | 14 | my @names = sort keys %{ $self->{data} }; | 
|  | 6 |  |  |  |  | 27 |  | 
| 113 | 6 | 100 |  |  |  | 49 | return (@names ? @names : ()); | 
| 114 |  |  |  |  |  |  | } | 
| 115 | 1509 | 100 |  |  |  | 2531 | if (defined $value) { | 
| 116 | 1309 | 100 |  |  |  | 5216 | $self->{data}->{$name} = [] | 
| 117 |  |  |  |  |  |  | unless exists $self->{data}->{$name}; | 
| 118 | 1309 |  |  |  |  | 1651 | push (@{ $self->{data}->{$name} }, $value); | 
|  | 1309 |  |  |  |  | 3746 |  | 
| 119 |  |  |  |  |  |  | } else { | 
| 120 |  |  |  |  |  |  | return | 
| 121 | 200 | 100 |  |  |  | 775 | unless exists $self->{data}->{$name}; | 
| 122 |  |  |  |  |  |  | } | 
| 123 | 1473 | 100 |  |  |  | 6587 | return unless defined wantarray; # don't bother doing more | 
| 124 | 166 | 100 |  |  |  | 1070 | return wantarray ? @{ $self->{data}->{$name} } : $self->{data}->{$name}->[0]; | 
|  | 42 |  |  |  |  | 345 |  | 
| 125 |  |  |  |  |  |  | } | 
| 126 |  |  |  |  |  |  |  | 
| 127 |  |  |  |  |  |  | sub remove { | 
| 128 | 16 |  |  | 16 | 0 | 102 | my ($self, $name) = @_; | 
| 129 | 16 |  |  |  |  | 181 | return delete $self->{data}->{$name}; | 
| 130 |  |  |  |  |  |  | } | 
| 131 |  |  |  |  |  |  |  | 
| 132 |  |  |  |  |  |  | #----------------------------------------------------------------- | 
| 133 |  |  |  |  |  |  | # Create a configuration file (overwrite if exists). The name is | 
| 134 |  |  |  |  |  |  | # either given here or the one given in the constructor. | 
| 135 |  |  |  |  |  |  | # ----------------------------------------------------------------- | 
| 136 |  |  |  |  |  |  | sub save { | 
| 137 | 43 |  |  | 43 | 0 | 823 | my ($self, $cfgfile) = @_; | 
| 138 | 43 | 50 |  |  |  | 160 | $cfgfile = $self->{cfgfile} unless defined $cfgfile; | 
| 139 | 43 | 100 |  |  |  | 579839 | open (my $cfg, '>', $cfgfile) | 
| 140 |  |  |  |  |  |  | or croak ("Cannot create configuration file '$cfgfile': $!\n"); | 
| 141 | 42 |  |  |  |  | 269 | foreach my $key (sort keys %{ $self->{data} }) { | 
|  | 42 |  |  |  |  | 610 |  | 
| 142 | 157 |  |  |  |  | 326 | my $values = $self->{data}->{$key}; | 
| 143 | 157 |  |  |  |  | 296 | foreach my $value (@$values) { | 
| 144 | 310 |  |  |  |  | 1642 | print $cfg "$key = $value\n"; | 
| 145 |  |  |  |  |  |  | } | 
| 146 |  |  |  |  |  |  | } | 
| 147 | 42 |  |  |  |  | 3440 | close $cfg; | 
| 148 |  |  |  |  |  |  | } | 
| 149 |  |  |  |  |  |  |  | 
| 150 |  |  |  |  |  |  | 1; | 
| 151 |  |  |  |  |  |  |  | 
| 152 |  |  |  |  |  |  | __END__ |