in reply to Re^7: Config files
in thread Config files

Hi Jenda,

Thanks for the response. Does that mean I need to hardcode the names of arrays that will be written in the config file to put them in the "qw()" ?

So, if my config file contains:

[one] size = 1,2,3,4 root = C:\test [two] colors = red,blue,green code = %root%\code1

Then, having:

use Config::IniHash qw(ReadINI); use Data::Dumper; $config = ReadINI('testiINI.ini', systemvars => 0, forValue => sub { my ($name, $value, $sectionname, $INIhashref) = @_; next if /^(#.*)?$/; $value =~ s{%(?:\[([^\]%]+)\])?([^%]*)%}{ print "for value: $value this is 1: $1 this is 2: $2 \n\n" +; if ($2 eq '') { '%' } elsif ($1 eq '') { $INIhashref->{$sectionname}{$2} } else { $INIhashref->{$1}{$2} } }ge; return $value; } ); foreach my $Section (values %$config) { foreach my $value ( qw( colors size ) ) { $Section->{$value} = [split /\s*,\s*/, $Section->{$value}]; } }

I am not sure if that is what you meant...but I am not too sure what you said should go into the qw(). How does the code determine what is the scalar variable and what is an array? Thank you.

Replies are listed 'Best First'.
Re^9: Config files
by Jenda (Abbot) on Dec 11, 2004 at 17:33 UTC

    You don't have to hardcode the names if you do not want to, but it's IMHO the best solution. There are basicaly three possible solutions.

    1. you can use the code above and specify what options allow multiple values. This way you know for sure that $config->{one}{root} is a string and $config->{one}{size} is an array. Which means you can safely write $path = $config->{one}{root} . "/processing.log"; and foreach my $size (@{$config->{one}{size}}) { ....
    2. You can split the values that contain the delimiters. This would allow the users to specify multiple values for any option in the INI file, the problem is that your script would have to be able to accept that. Otherwise you end up with $path (from the example in the previous solution) containing something like "ARRAY(0x14234234)/processing.log" which doesn't look too usefull to me. The same problem, just in the other direction would be with the "size" option, if the user did not specify several, the $config->{one}{size} would not be an array ref, but a string, so the foreach from the first solution would error out. I think this solution would complicate your script imensely.
    3. The last solution would be to split everything. Which means that $config->{sectionName}{optionName} would always be an array ref. And then if you had a use for just one value of an option you'd use $config->{sectionName}{optionName}[0] and if you wanted to do something with all of them you'd loop over @{$config->{sectionName}{optionName}}. The catch of this solution is that you might need to allow the delimiter in the value of some options. Or you would want to use a different delimiter for some options. Comma is fine if you are writing a list of color names, but is it so great for prices? What if the user enters prices=1,050? Did he/she mean two values, one and fifty or just one value, one thousand fifty?

    You can choose whichever solution you like best, but my choice would be 1) any day.

    Jenda
    We'd like to help you learn to help yourself
    Look around you, all you see are sympathetic eyes
    Stroll around the grounds until you feel at home
       -- P. Simon in Mrs. Robinson

      Hi Jenda,

      Thanks for the suggestion. I think other than option 1, as you have suggested, other options would complicate a lot of things...and hence I'll specify the options that allow multiple values.

      If the config file contains:

      [path] root = C:\test code = %root%\code1 [array] files = hello.txt,hi.txt,howdy.txt dirs = %code%, %root%, %code%

      Then, for the "dirs" array, how can I change the following regular expression to find and store all values between %%..since there can be more than one (as seen in the dirs array)...

      $value =~ s{%(?:\[([^\]%]+)\])?([^%]*)%}{ if ($2 eq '') { '%' } elsif ($1 eq '') { $INIhashref->{$sectionname}{$2} } else { $INIhashref->{$1}{$2} } }ge;

        It already does, thanks to the /g option.

        Jenda
        We'd like to help you learn to help yourself
        Look around you, all you see are sympathetic eyes
        Stroll around the grounds until you feel at home
           -- P. Simon in Mrs. Robinson