Using OOP to load a config file

P

Prab_kar

Hi all,
I'm fairly new to OOP in Perl and trying my hand to load a config file
(in a 'key=value' format)using OOP. I've got stuck at a point and
wonder if anyone of you could give me some pointers.

Config file: Foo.conf
Perl module: CfgLoader.pm
Perl script: useOOP.pl

For a given config file, Foo.conf with content along the lines,
Key1=Value1, I'd like to access the keys and values from my Perl
script, useOOP.pl, as, $obj->value("key1") ; which would give me
"value1".

In the following .pl/.pm below, I was able to load the config file and
split the key/values, but dont know how to transfer that 'hash' back to
the main program, useOOP.pl.
I'll have to define another method/function, 'value', but dont know how
to transfer the hash from the 'loadCfg' method to the new method or to
return values from the new method to the calling script. Could any of
you give some pointers, please? Thanks for your time,

------------------useOOP.pl:-----------------------------

#!/usr/local/bin/perl

use strict ;
use warnings ;

use CfgLoader ;

my $obj = new CfgLoader() ;
$obj->loadCfg("Foo.conf") ;

--------------------------------------------------------------

------------------CfgLoader.pm-----------------------------
package CfgLoader ;

sub new ()
{
$class = shift ;
$self = {} ;
bless ($self,$class) ;
}

sub loadCfg()
{
my ($self,$file) = @_ ;
print "Loading configuration: $file\n" ;

open(IN,"$file") or die "Cant open $file: $!\n" ;
while(<IN>)
{
chomp ;
next if ( /^(#|$)/ ) ;
($key,$value) = split(/\=/,$_) ;
print "Key: $key Value: $value\n" ;
$hash{$key} = $value ;
}
close(IN) or die "Cant close file: $!\n" ;
}

# Required to retun 1
1 ;
 
J

jl_post

For a given config file, Foo.conf with content along the lines,
Key1=Value1, I'd like to access the keys and values from my Perl
script, useOOP.pl, as, $obj->value("key1") ; which would give me
"value1".

------------------CfgLoader.pm-----------------------------
 
A

Anno Siegel

Dear Prabh,

I noticed that you used "use strict;" and "use warnings;" in the
file "useOOP.pl". Good for you! However, it's also good to include
them in CfgLoader.pm, as they will point out (at least) one error to
you.

Right off the bat, I see that you are populating %hash inside
loadCfg() when it is never declared. Instead of:

$hash{$key} = $value;

I think you mean to say:

$self->{$key} = $value;

that way you can use $obj->{key1} to retrieve "value1".

I agree that the key/value pairs should probably go into the object and
not in some class-global hash (though that is a valid alternative too).

However, $obj->{key1} is no way to access an object. An object
encapsulates its implementation, but $obj->{key1} exposes the
implementation as a hash.

Instead there should be accessor methods for each key expected in the
config file to access the corresponding value (untested)

sub get_key1 { $_[ 0]->{ key1} }

etc.

For this approach you need to know beforehand which keys can possibly
appear in a config file. If you expect keys that aren't known until
run time, a general accessor can be used:

sub get_any_key {
my ( $conf, $key) = @_;
$conf->{ $key};
}

In that case, individual accessors can be derived from the general one

sub get_key1 { shift()->get_any_key( key1) }

Anno
 
A

Anno Siegel

Dear Prabh,

I noticed that you used "use strict;" and "use warnings;" in the
file "useOOP.pl". Good for you! However, it's also good to include
them in CfgLoader.pm, as they will point out (at least) one error to
you.

Right off the bat, I see that you are populating %hash inside
loadCfg() when it is never declared. Instead of:

$hash{$key} = $value;

I think you mean to say:

$self->{$key} = $value;

that way you can use $obj->{key1} to retrieve "value1".

I agree that the key/value pairs should probably go into the object and
not in some class-global hash (though that is a valid alternative too).

However, $obj->{key1} is no way to access an object. An object
encapsulates its implementation, but $obj->{key1} exposes the
implementation as a hash.

Instead there should be accessor methods for each key expected in the
config file to access the corresponding value (untested)

sub get_key1 { $_[ 0]->{ key1} }

etc.

For this approach you need to know beforehand which keys can possibly
appear in a config file. If you expect keys that aren't known until
run time, a general accessor can be used:

sub get_any_key {
my ( $conf, $key) = @_;
$conf->{ $key};
}

In that case, individual accessors can be derived from the general one

sub get_key1 { shift()->get_any_key( 'key1') }

Anno
 
J

jl_post

Anno said:
I agree that the key/value pairs should probably go into the object and
not in some class-global hash (though that is a valid alternative too).

However, $obj->{key1} is no way to access an object. An object
encapsulates its implementation, but $obj->{key1} exposes the
implementation as a hash.

If you expect keys that aren't known until
run time, a general accessor can be used:

sub get_any_key {
my ( $conf, $key) = @_;
$conf->{ $key};
}


I figure you could also make use of the AUTOLOAD function, like
this:

# Untested:
sub AUTOLOAD
{
my $key = our $AUTOLOAD;
$key =~ s/.*:://; # trim package name
return $_->{$key} if exists $$_{$key};

use Carp;
croak "Undefined subroutine $AUTOLOAD called";
}

That way, he can retrieve a value with a call like:

my $install_path = $configObject->install_path();

to retrieve a value in his config file that defined like:

install_path /home/user1/temp

Of course, this AUTOLOAD function assumes that every config entry
you'd ever want to retrieve has been specified in the config file. If
it isn't, then it will assume that the code was trying to call an
undefined function.

I suppose that this little problem could be fixed by using the
"fields" pragma to define the existing fields ahead of time by the
programmer. However, the "use fields" approach wouldn't work very well
if he/she wanted an arbitrary number of fields, but if he wants to
hard-code what to retrieve in his code anyway, he should already know
what fields to specify.

-- Jean-Luc
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,767
Messages
2,569,570
Members
45,045
Latest member
DRCM

Latest Threads

Top