# Key Value Pair File Format reader/writer 1.0 # By Tyler Bletsch use Carp; # Format: # ; comment type one # # comment type two # ; # ; standard key value pair # key1=value1 # ; multiline value # key2=\ # This is literally the data. # The only problem is that there is no way to escape the end symbol, # which is a dot alone on a line (AKA "\n.\n"). # . # ; if your data has an equal sign, a multiline escape is used # ; (even if the data is one line) # key3=\ # This single-line data contains a '=', which is an equal sign. # . # ; A non-data, non-comment, non-blank line is an error. # ; If one is read, it will generate a carp (warning) # Read a file and return a hash of it's content. Returns undef on error. # Will carp if a file can't be opened for reading. # Ex: # %myData = kvpRead('myfile.kvp'); sub kvpRead { my ($filename) = @_; open $fp,$filename or (carp "Couldn't open '$filename' for read ($!).\n",return); my %result; my $lineNum=0; while (<$fp>) { my ($k,$v); $lineNum++; chomp; if (/\s*(.*)\s*=\s*\\\s*$/) { #multiline $k=$1; { local $/="\n.\n"; $v = <$fp>; chomp $v; } $result{$k}=$v; } elsif (/\s*(.*)\s*=(.*)/) { ($k,$v) = ($1,$2); $result{$k}=$v; } elsif (/^\s*[;#]/ || /^\s*$/) { #ignore this comment/blank } else { carp "Unrecognized format, line $lineNum of in '$filename'.\n"; } } return %result; } # Write a hash of printable scalars (i.e. not references) to a KVP file. # Return true on sucess, false on failure. Will carp if a file can't be opened # for writing. # Ex: # %myData = kvpRead('myfile.kvp'); sub kvpWrite { my ($filename,%data) = @_; open $fp,"> $filename" or (carp "Couldn't open '$filename' for write ($!).\n",return); while (my ($k,$v) = each(%data)) { $k =~ s/=/\\=/g; if ($v=~/[=\n]/ || $v=~/^\\$/) { print $fp "$k=\\\n$v\n.\n"; } else { $v =~ s/=/\\=/g; print $fp "$k=$v\n"; } } close $fp; return 1; } 1; __END__ # Tests: use Data::Dumper; $a{b} = '\\'; $a{c} = 'alpha=beta'; $a{m1} = "this\nis\nmulti=line\n"; $a{m2} = "=\nthis\nis\nmultiline too\n"; print Dumper(%a); print "------------------------------\n"; #kvpWrite "test1.kvp",%a; print Dumper(%a); print "------------------------------\n"; %b = kvpRead "test1.kvp"; print Dumper(%b);