Better INI backend for Config::Model

Current ini_file backend built into Config::Model works pretty well, but not for all files. Config::Tiny module (used for reading INI files) makes assumption that a variable name cannot be repeated in one section. This statement is true only for about 99% of INI files. Look at the following fragment of valid Kismet config file:

# Sources are defined as:
# source=sourcetype,interface,name[,initialchannel]
source = ipw2100,eth1,intel
source = madwifi,ath0,atheros

As you can see, source variable is repeated – in this case, backend based on Config::Tiny will report only one occurrence of it.

New backend

I decided to write a new backend. Patching Config::Tiny is not a good idea in my humble opinion – modifying this module could break applications dependent on it. Dominique suggested that repeated variables should be handled as lists. I had some trouble with Config::Model docs, but with his help I managed to create a fully working backend today.

Reading file

    my $data = {};
    my $section;
    foreach ($args{io_handle}->getlines) {
	next if /^[;#]/ ;
	chomp ;
	next if/^\s*$/;
	#Update section name
	if(/\[(.*)\]/)
	{
		$section = $1;
		next;
	}
	my ($name,$val) = split(/\s*=\s*/);
	#Get the 'right' ref
	my $r = $data;
	if (defined $section)
	{
		$data->{$section} = {} if not defined $data->{$section};
		$r = $data->{$section}
	}
	if (defined $r->{$name})
	{
		$r->{$name} = [$r->{$name}] if ref($r->{$name}) ne 'ARRAY';
		push @{$r->{$name}}, $val;
	}
	else
	{
		$r->{$name} = $val;
	}
    }
    $self->node->load_data($data);

This simple loop goes through all of the lines of a config file and builds a Perl data structure of it. All values are initially stored as strings. When a variable name appears for the second time, it’s converted to an array of values. Finally, data is loaded into a model using load_data method.

Problems

This approach solves only one problem of Config::Tiny – comments in the file are still lost. However, this can be easily solved – all I need to do is store comments separately (like in ShellVar backend). Some basic file validation would be good too.

Files

New backend
Modified Kismet model (source parameter as list)
P.S.
I promised to post some notes about Config::Model docs, but I’ll do it after some more investigation.

One thought on “Better INI backend for Config::Model

  1. Comments extracted from the configuration file can be extracted by the read backend and stored in the new annotation feature provided by Config::Model 1.202. Then they can be written back by the write backend.
    Hope this helps

Dodaj komentarz

Twój adres email nie zostanie opublikowany. Wymagane pola są oznaczone *