summaryrefslogtreecommitdiff
path: root/lib/Simplestore.pm
blob: f46ef038efa65d1a65d976b60337676552cca471 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
## Library for the Simplestore format
## Copyright © 2009 by Daniel Friesel <derf@derf.homelinux.org>
## License: WTFPL <http://sam.zoy.org/wtfpl>
package Simplestore;
use strict;
use warnings;
use Carp;
use base 'Exporter';

our @EXPORT_OK = ('load', 'save');
my $VERSION = '0.1';

sub load {
	my ($file, $store) = @_;
	my @keys;

	open(my $handle, '<', $file) or confess("Cannot open $file for reading: $!");

	while (<$handle>) {
		chomp;
		if ($_ !~ / ^ (\S+) \s+ (.*) $ /x) {
			next;
		}
		my ($key, $value) = ($1, $2);

		if (exists($store->{$key}) and grep {$_ eq $key} @keys) {
			$store->{$key} .= "\n$value";
		} else {
			$store->{$key} = $value;
			push(@keys, $key);
		}
	}

	close($handle) or confess("Cannot close $file: $!");
	return($store);
}

sub save {
	my ($file, $store) = @_;

	open(my $handle, '>', $file) or confess("Cannot open $file for writing: $!");
	foreach my $key (keys(%{$store})) {
		if ($key !~ / ^ \w+ $ /x) {
			confess("Invalid key name: May only contain alphanumeric and _");
		}
		foreach (split(/\n/, $store->{$key})) {
			print $handle "$key\t$_\n";
		}
	}
	close($handle) or confess("Cannot close $file: $!");
	return 1;
}

1;

__END__

=head1 NAME

Simplestore - simple storage format for hash refs

=head1 SYNOPSIS


  use Simplestore;

  # somefile contains:
  #   word purrl
  #   foo eggs
  my $hash = Simplestore::load('somefile');
  say $hash->{word}; # purrl

  $hash->{foo} = 'bar';
  $hash->{sentence} = "Mind the\nnewnile.";
  Simplestore::save('somefile', $hash);

  # somefile contains:
  #   word purrl
  #   foo bar
  #   sentence Mind the
  #   sentence newline.

=head1 DESCRIPTION

B<Simplestore> is a perl library to store hashes in a very simple,
easy-to-parse file format.

Note that it can only store simple hashes with string/digit values and
word keys (the key must match \w+, like a perl variable name for example).
References or any other complex stuff are not supported.

=head1 FUNCTIONS

Note: The function names are quite generic, so by default they are not
exported.  Use C<< use Simplestore qw/load save/ >> if you want to use them
directly.

=over

=item B<Simplestore::load>(I<storefile>[, I<hashref>])

Load the hash saved in I<storefile>. Returns a hash ref containing the hash
saved in I<storefile>.

If I<hashref> is specified, I<storefile> will not be loaded into an empty hash,
but into I<hashref>. However, keys in I<storefile> overwrite those in I<hashref>.

=item B<Simplestore::save>(I<storefile>, I<hashref>)

save I<hashref> in I<storefile>. Returns nothing.

=back

=head1 STORAGE FORMAT

The store file contains key-value-pairs, each of them separated by a newline,
the key and value are separated by a single tab.
If a value contains newlines, they will be printed, but the next line(s) will be
prefixed by the key. For a little example, see SYNOPSIS.

=head1 MOTIVATION

B<Simplestore> aims to provide a common, simple format to store data.
The format is extremely easy to parse in almost all languages, even C or Shell,
thus Simplestore should offer a good way to exchange non-complex data between
apps of all kinds.

=head1 AUTHOR

Copyright (C) 2009 by Daniel Friesel.
Licensed under the terms of the WTFPL E<lt>http://sam.zoy.org/wtfplE<gt>.