1 # Perl module for manipulating Sherlock objects
3 # (c) 2007 Martin Mares <mj@ucw.cz>
5 # This software may be freely distributed and used according to the terms
6 # of the GNU Lesser General Public License.
10 Sherlock::Object -- Manipulation with Sherlock objects
14 This module offers a simple interface to Sherlock objects. See F<doc/objects>
15 for a description of how the object system works.
23 Creates a new empty object.
25 =item B<< new(I<name> => I<value>, ...) >>
27 Creates a new object with some attributes initialized.
29 =item B<< set(I<name> => I<value>, ...) >>
31 Sets given attributes to specified values. If any of the attributes already
32 exists, the old value is replaced by the new one.
48 a reference to an array of values, which creates a multi-valued attribute.
52 a reference to another object, which created a nested object. In this case
53 (and only in this case), the name of the attribute must start with C<(>.
57 =item B<< unset(I<name>, ...) >>
59 Removes given attributes.
61 =item B<< add(I<name> => I<value>, ...) >>
63 Sets given attributes to specified values. If any of the attributes already
64 exists, the new value is added to the original one, creating a multi-valued
67 The repertoir of values is the same as in the C<set> method except for references
68 to arrays, which are not allowed.
70 =item B<< get(I<name>) >>
72 Gets the value of the given attribute or C<undef> if it does not exist.
73 If the attribute is multi-valued, the first value is returned.
75 =item B<< getarray(I<name>) >>
77 Gets all values of the given attribute as an array or an empty array if the
78 attribute does not exist.
80 =item B<< get_attrs() >>
82 Get an array of names of all attributes present in the object.
84 =item B<< read(I<handle>) >>
86 Reads a textual representation of an object from the given handle and adds it
87 to the object it is invoked on. The effect is the same as calling the C<add>
88 method on all read attributes.
90 Returns 1 if the object has been read successfully, 0 if the input
91 stream ended before an object started or C<undef> if the input was
94 =item B<< read(I<handle>, raw => 1) >>
96 Reads an object as above, but add a special attribute called C<< RAW >>, which will
97 contain the raw form of the object.
99 =item B<< write(I<handle>) >>
101 Writes a textual representation of the object to the given handle.
103 =item B<< write_indented(I<handle>, [I<base_indent>]) >>
105 Writes an indented textual representation of the object to the given handle.
106 The I<base_indent> will be prepended to all printed lines, each nested level
107 will get one tab character more.
109 This is intended for debugging dumps and the output cannot be read back by any
110 of the Sherlock libraries.
116 Martin Mares <mj@ucw.cz>
120 package Sherlock::Object;
138 while (defined($attr = shift @_)) {
139 $self->{$attr} = shift @_;
145 foreach my $attr (@_) {
146 delete $self->{$attr};
153 while (defined($attr = shift @_)) {
155 if (!exists $self->{$attr}) {
156 $self->{$attr} = $val;
157 } elsif (ref $self->{$attr} eq "ARRAY") {
158 push @{$self->{$attr}}, $val;
160 $self->{$attr} = [ $self->{$attr}, $val ];
166 my ($self, $attr) = @_;
167 if (!exists $self->{$attr}) {
169 } elsif (ref $self->{$attr} eq "ARRAY") {
170 return $self->{$attr}->[0];
172 return $self->{$attr};
177 my ($self, $attr) = @_;
178 if (!exists $self->{$attr}) {
180 } elsif (ref $self->{$attr} eq "ARRAY") {
181 return @{$self->{$attr}};
183 return ( $self->{$attr} );
197 my $read_something = 0;
200 my $read = $opts{read} ? $opts{read} : sub { my $fh = shift; return $_ = <$fh>; };
202 $raw = $obj->{"RAW"} = [];
204 while ($read->($fh)) {
207 my ($a, $v) = /^(.)(.*)$/ or return undef;
208 push @$raw, $_ if $raw;
211 my $new = new Sherlock::Object;
215 } elsif ($a eq ")") {
216 @stack or return undef;
223 @stack and return undef;
224 return $read_something;
228 my ($self, $fh) = @_;
229 foreach my $a (keys %$self) {
230 my $vals = $self->{$a};
231 ref $vals eq "ARRAY" or $vals = [$vals];
232 foreach my $v (@{$vals}) {
234 print $fh $a, $v, "\n";
235 } elsif (ref $v eq "Sherlock::Object") {
246 sub write_indented($$$) {
247 my ($self, $fh, $indent) = @_;
248 defined $indent or $indent = "";
249 foreach my $a (sort keys %$self) {
250 my $vals = $self->{$a};
251 ref $vals eq "ARRAY" or $vals = [$vals];
252 foreach my $v (@{$vals}) {
254 print $fh $indent, $a, $v, "\n";
255 } elsif (ref $v eq "Sherlock::Object") {
256 print $fh $indent, $a, "\n";
257 $v->write_indented($fh, $indent . "\t");
258 print $fh $indent, ")\n";