I know I should not be pushing my own posts but as it is a little difficult to find using search or Super Search here it is: Re: Persistence for options?, a quick comparison between 14 (!) different ways to store configuration info in Perl.
| [reply] |
| [reply] |
Sounds like ConfigReader::Simple or one of many other modules on CPAN. You need to do some serious research before introducing a new module into such a crowded field. If the only difference is that yours reads __DATA__ sections, you might be better off just adding that feature to an existing one. | [reply] |
Thanks for the comments. I knew there were modules already, so I know I don't want to add another one for no good reason. Most of the other modules weren't quite what I was looking for.
However, I've looked at ConfigReader::Simple (again) and it's very similar to what I want. It's probably better to contribute to that.
The other feature my module has is the ability to write configs back out, something ConfigReader::Simple can't.
As I said, the module was also a learning exersise, something to do for the sake of it.
Anyhow, for your amusment here is the very simple and probably not very good souce of my module:
# --------------------------------------------------
#
# Config::SimpleConf
# Version 0.06
# September 2001
# Copyright iredale Consulting, all rights reserved
# http://www.iredale.net/
#
# --------------------------------------------------
# --------------------------------------------------
# Module starts here...
# --------------------------------------------------
package Config::SimpleConf;
use 5.6.0;
use strict;
use warnings;
use Carp;
use subs qw(_process_line _clean_string read_config
write_config _set_modes);
require Exporter;
our @ISA = qw(Exporter);
our $VERSION = '0.06'; # Module ver
+sion
our %settings = (); # This is t
+he hash we export back
our $_strict; # Set this to
+ 1 to force Strict operation
our $_verbose; # Set this t
+o 1 to force Verbose operation
our $_read_self; # Set this to
+1 to switch on Read-Self mode
our $_over; # Set this
+to 1 to switch on Over-writing mode
our ($_package, $_file) = caller; # Find out wh
+o called the module
our @EXPORT_OK = qw($VERSION write_config); # What the
+caller can find out
our @EXPORT = qw(read_config %settings); # What we expo
+rt
our %EXPORT_TAGS = (read => [qw(read_config %settings)],
write => [qw(write_config %settings)],
both => [qw(write_config read_config %settings)])
+;
#####################################################
# PUBLIC METHODS
#####################################################
# ---------------------
# Read a config file in
# ---------------------
sub read_config {
my $config_file = shift;
my $mode = shift;
_set_modes $mode if $mode;
# Load "self" if asked explicitly to do so
$config_file = $_file if ($_read_self && !$config_file);
# Check to see if we were give any file to work with and that it's
+there
croak "ERROR: No configuration file name provided" if ($_strict &&
+ !$config_file);
# If we can't find the file try reading the caller file
if (! $config_file) {
$config_file = $_file; # Set the file n
+ame to the callers name
carp "WARNING: Reverting to $_file as no file provided." if ($
+_verbose && ! $_read_self);
$_read_self = 1; # Switch on Read
+-Self mode
}
# Die if we can't read the file we have been asked (or tried to) re
+ad
croak "ERROR: Unable to find Configuration file: $config_file" unl
+ess (-e $config_file);
# Open up the confuguration file and process it
open CONF, "<$config_file" or croak "ERROR: Unable to read configu
+ration file: $config_file";
my $line; # Counter for config line num
+ber
if ($_read_self) { # We are now parsing the cal
+ling file for it's __DATA__ section
while (<CONF>) {
last if /^__DATA__$/;
}
}
while (<CONF>) {
next if /^\s*#/; # Skip comment lines #
next if /^\s*\n/; # Skip any empty lines
last if /^__END__$/; # Don't care what comes after
+this
if (s/\\\s*$//) { # Look for a continuation cha
+racter
$_ .= <CONF>; # If found then glue the line
+s together
redo unless eof(CONF);
}
$line++; # Increase the line counter, i
+t may be useful
_process_line ($_, $line); # Send the line off for proc
+essing
}
close CONF; # Close the file and end
carp "WARNING: Configuration file was empty" if ($_verbose && ! $l
+ine);
}
# -----------------------
# Write a Config file out
# -----------------------
sub write_config {
my $config_file = shift;
my $mode = shift;
_set_modes $mode if $mode;
# Check to see if we were give any file to work with and that it's
+there
croak "ERROR: No configuration file name provided" unless $config_
+file;
# if the file is there already then back it up first
if ((-e $config_file) && (! $_over)) {
carp "WARNING: Config file present already, backing up old fi
+le to $config_file.old" if $_verbose;
rename "$config_file.old", "$config_file.older" or croak "ERRO
+R: Unable to rename $config_file" if (-e "$config_file.old");
rename $config_file, "$config_file.old" or croak "ERROR: Unabl
+e to rename $config_file";
}
# Open the file up and write the header
open CONF, ">$config_file" or croak "ERROR: Unable to write config
+uration file: $config_file";
print CONF "#\n# Config file written by $_file\n# Using Config::Si
+mpleConf version $VERSION\n#\n\n";
# print out each key
foreach my $setting (sort keys %settings) {
if ($setting =~ / /) {
+ # Check for spaces in keys
croak "ERROR: Setting key \"$setting\" contains an illegal
+ space" if $_strict;
carp "WARNING: Setting key \"$setting\" contains an illega
+l space" if $_verbose;
my $old_setting = $setting;
$setting =~ s/ /_/g;
+ # Change spaces to _ silently
croak "ERROR: Unable to fix space in key, replacement key
+exists already" if $settings{$setting};
$settings{$old_setting} = " " unless $settings{$old_settin
+g};
printf CONF "$setting%s$settings{$old_setting}\n", length(
+$old_setting) >= 8 ? "\t" : "\t\t";
next;
}
$settings{$setting} = " " unless $settings{$setting};
+ # What is this doing?
printf CONF "$setting%s$settings{$setting}\n", length($setting
+) >= 8 ? "\t" : "\t\t"
}
# Print a datestamp and close the file
my $time = localtime;
print CONF "\n#\n# This file written at $time\n#\n";
close CONF;
}
#####################################################
# PRIVATE METHODS
#####################################################
# --------------------------------------------------------
# Process a config line and stuff the results in %settings
# --------------------------------------------------------
sub _process_line {
my $line = shift;
my $line_no = shift;
# Clean up the line
chomp $line; # Take the end off
$line =~ tr/\e\`\';,\*"$%^&//ds; # Remove any gross
+ crud from the input
$line =~ s/^\s+|\s+$|#+.*$//go; # Remove commen
+ts, and spaces at start or end
$line =~ s/\s+/ /go; # Convert multiple
+ whitespace to one space globally
# If anything is left then break it up
if ($line) {
my ($key, $value) = split / /, $line, 2;
$key = lc _clean_string $key;
if (exists $settings{$key}) {
croak "ERROR: Duplicate key \"$key\" found in config file
+on line $line_no" if $_strict;
carp "WARNING: Duplicate key \"$key\" found in config fil
+e on line $line_no" if $_verbose;
}
if ($key) {
$value = _clean_string $value if $value;
if ($value) {
$settings{$key} = $value;
} else {
carp "WARNING: Key \"$key\" has no valid value, on lin
+e $line_no of the config file" if $_verbose;
$settings{$key} = $value unless $_strict;
}
}
}
}
# -------------------------
# Clean entry up and use it
# -------------------------
sub _clean_string {
my $input = shift;
my $output;
if ($input =~ /^([-=\?\/\w.:\\\s\@~]+)$/) { # De-Taint the inpu
+t line
$output = $1;
}
$output =~ s/^\s+|\s+$//g if $output; # Remove spaces at st
+art or end
return $output;
}
# -------------------------
# Set the global mode flags
# -------------------------
sub _set_modes {
my $mode = shift;
$_strict = 1 if ($mode =~ /s/i); # Swicth on Stric
+t mode
$_verbose = 1 if ($mode =~ /v/i); # Switch on Verbo
+se mode
$_read_self= 1 if ($mode =~ /r/i); # Switch on Read
+-self mode
$_over = 1 if ($mode =~ /o/i); # Switch on Over-
+writing mode
}
1;
__END__
=head1 NAME
Config::SimpleConf - Perl extension for reading and writing very simpl
+e Configuration files
=head1 SYNOPSIS
use Config::SimpleConf qw(:both);
read_config("path/to/my/config.conf", mode);
print "Setting Colour is $settings{'colour'}\n";
$settings{'new-item'} = "New Setting";
write_config("path/to/my/config.conf");
=head1 DESCRIPTION
Use this module when you want use a simple, very light weight configur
+ation file. This module
is not very sophisticated or object orientated. The script exports a s
+ingle hash into your
name space called %settings, and uses the same hash to write a new con
+fig file.
In normal use, simply call the read or write passing the file name of
+the configuration file you
wish to use. You may also call the read and write methods with a mode
+flag. s turns on strict
checking, v turns on verbose mode and r turns on the read-self option,
+ o turns on over writing
mode on, For example:
read_config("path/to/my/config.conf", "sv");
for Strict and verbose mode.
If read_config is called without a config file, and is not running in
+strict mode it will try
read the __DATA__ section of the script that called it. In strict mode
+ this will only happen
if the "Read-Self" option is explicitly called.
Strict mode switches on additional safety checks that will result in d
+eath, that would not in
the default tollerant mode.
Verbose turns on a lot of extra warnings, useful in a debugging enviro
+nment, probably a pain in
production.
By default when you write a config file out, if the file is already pr
+esent the script will try and
rename this to .old, and if there is a .old alredy, it will rename tha
+t to .older. If you run in
overwriting mode then this behaviour is turned off.
The configuration file is a plain text file with a simple structure. E
+ach setting is stored as a
key value pair separated by the first space. Empty lines are ignored a
+nd anything after a hash #
is treate as a comment and is ignored. Depending upon mode, duplicate
+enteries will be silenty
ignored, warned about, or cause the module to die.
Spaces in key names will either cause the script to die (strict), blur
+t out a warning and subsitute
an underscore (verbose), or silently change to an underscore. Undersco
+res in keys are NOT changed
back to spaces on read. All key names are forced into lower case when
+read in, values are left intact.
If you delete a key/value pair it will not be written out when you do
+a write_config. When a key has
an undef value, the key will be written out with no matching value. Wh
+en you read a key with no value
in, in verbose mode you will get a warning.
=head2 EXPORT
By default only C<%settings> an C<read_config> are exported. If called
+ in write mode (:write), C<%settings>
and C<write_config> are exported. To read and write call the module in
+ full mode (:both).
:read (is also the default)
%settings
read_config
:write
%settings
write_config
:both
%settings
write_config
=head2 SAMPLE CONFIG FILE
#
# This is a smample config file
#
value-0 is very \
long so it's broken \
several lines
value-1 is foo
value-1 is bar
__END__
value-1 is baz
If parsed the value of value-1 would be "is bar" in normal mode, issue
+ a warning if in verbose mode
and die in strict mode. Everything after the __END__ will be ignored.
+value-0 will be "is very long
so it's broken several lines".
=head1 AUTHOR
Adam trickett, E<lt>adam@iredale.netE<gt>
=head1 SEE ALSO
C<perl>, C<ConfigReader::Simple>, C<Config::Ini>, C<Config::General> a
+nd C<Config::IniFiles>.
=head1 COPYRIGHT
Config::SimpleConf, Copyright iredale Consulting 2001
This program is free software; you can redistribute it and/or modify i
+t under the terms of the GNU General Public License as published by t
+he Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
This program is distributed in the hope that it will be useful, but WI
+THOUT ANY WARRANTY; without even the implied warranty of MERCHANTABIL
+ITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public L
+icense for more details.
You should have received a copy of the GNU General Public License alon
+g with this program; if not, write to the Free Software Foundation, I
+nc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
=cut
| [reply] [d/l] |