File Coverage

blib/lib/Data/Struct.pm
Criterion Covered Total %
statement 56 57 98.2
branch 20 26 76.9
condition 7 14 50.0
subroutine 11 11 100.0
pod 0 1 0.0
total 94 109 86.2


line stmt bran cond sub pod time code
1             #! perl
2              
3             package Data::Struct;
4              
5 3     3   87558 use strict;
  3         8  
  3         105  
6 3     3   16 use warnings;
  3         5  
  3         4268  
7 3     3   183 use base qw(Exporter);
  3         176  
  3         1671  
8             our @EXPORT = qw( &struct );
9 3     3   15 use Carp;
  3         4  
  3         1317  
10              
11             $Carp::Internal{ (__PACKAGE__) }++;
12              
13             our $VERSION = "1.701";
14              
15             # use Data::Struct;
16             #
17             # Definition (void context):
18             # struct Foo => qw(foo bar);
19             #
20             # Contructing (scalar context):
21             # my $s2 = struct "Foo";
22             # my $s3 = struct Foo => { foo => 1, bar => 2 };
23              
24             sub struct {
25 8     8 0 1665 my @args = @_;
26 8 50       25 croak("'struct' needs at least a struct name") unless @args;
27 8         16 my $struct = shift(@args);
28              
29 8 100       26 if ( !defined wantarray ) { # void context -> definition
30             # struct Foo => [ attr1, attr2, ... ]
31 3 50 33     18 if ( @args == 1 && ref($args[0]) eq 'ARRAY' ) {
32 0         0 return _define( $struct, $args[0] );
33             }
34              
35             # struct Foo => qw( attr1 attr2 ...)
36 3 100       18 return _define( $struct, \@args ) if @args;
37             }
38              
39 6 50       20 if ( !wantarray ) { # scalar context -> construction
40             # $s = struct Foo => { attr1 => val1, attr2 = val2, ... }
41 6 100 66     27 if ( @args == 1 && ref($args[0]) eq 'HASH' ) {
42 2         4 my @ival = values %{ $args[0] };
  2         8  
43 2         4 @args = keys %{ $args[0] };
  2         8  
44 2         8 return _build( $struct, \@args, \@ival );
45             }
46              
47             # $s = struct foo;
48 4 100       23 return _build( $struct, [], [] ) unless @args;
49             }
50              
51 1         431 croak("Ambiguous use of \"struct '$struct'\"");
52             }
53              
54             sub _define {
55 2     2   6 my ( $struct, $attrs ) = @_;
56              
57 3     3   18 no strict 'refs';
  3         6  
  3         1177  
58 2         4 ${$struct.':: type'} = __PACKAGE__;
  2         21  
59              
60             # Undefined accessor catcher.
61 2         5 our $AUTOLOAD;
62 2         13 *{$struct.'::AUTOLOAD'} = sub {
63 1     1   23 my ( $s, $a ) = $AUTOLOAD =~ /^(.*)::([^:]+)$/;
64 1 50       178 croak("Unknown accessor '$a' for struct '$s'")
65             unless $a eq 'DESTROY';
66 2         13 };
67              
68             # Accessors.
69 2         6 foreach ( @$attrs ) {
70 4 50 33     59 croak("Invalid accessor name '$_' for struct '$struct'")
      33        
71             unless defined and !ref and /^[^\W\d]\w*$/s;
72              
73 4         7 my $attr = $_; # lexical for closure
74              
75 4         39 *{$struct.'::'.$_} = sub () :lvalue {
76 8 100   8   539 croak("Accessor '$attr' for struct '$struct' takes no arguments")
77             if @_ > 1;
78 7         45 $_[0]->{$attr};
79 4         20 };
80             };
81             }
82              
83             sub _build {
84 5     5   9 my ( $struct, $attrs, $values ) = @_;
85              
86 3     3   19 no strict 'refs';
  3         6  
  3         598  
87              
88             croak("Undefined struct '$struct'")
89 5 100 100     7 unless (${$struct . ":: type"}||'') eq __PACKAGE__;
90 4 50       10 Carp::confess("uneven") unless @$attrs == @$values;
91              
92             # Construct empty struct.
93 4         14 my $s = bless {}, $struct;
94              
95             # Assign initial attributes, if any.
96 4         12 foreach ( @$attrs ) {
97 2 100       158 croak("Unknown accessor '$_' for struct '$struct'")
98             unless $s->can($_);
99 1         4 $s->$_ = shift( @$values );
100             }
101              
102 3         12 return $s;
103             }
104              
105              
106             1;
107              
108             =pod
109              
110             =head1 NAME
111              
112             Data::Struct - Simple struct building
113              
114             =head1 SYNOPSIS
115              
116             use Data::Struct; # exports 'struct'
117              
118             # Define the struct and its accessors.
119             struct Foo => [ qw(foo bar) ];
120             struct Foo => qw(foo bar); # alternative
121              
122             # Construct the struct.
123             my $object = struct "Foo"; # empty struct
124             my $object = struct Foo => { bar => 1 };
125             my $object = struct Foo => { foo => "yes", bar => 1 };
126              
127             # Use it.
128             print "bar is " . $object->bar . "\n"; # 1
129             $object->bar = 2;
130             print "bar is now " . $object->bar . "\n"; # 2
131              
132             =head1 DESCRIPTION
133              
134             A I is a data structure that can contain values (attributes).
135             The values of the attributes can be set at creation time, and read and
136             modified at run time. This module implements a very basic and easy to
137             use I builder.
138              
139             Attributes can be anything that Perl can handle. There's no checking
140             on types. If you need Is with type checking and inheritance
141             and other fancy stuff, use one of the many CPAN modules that implement
142             data structures using classes and objects. Data::Struct deals with
143             data structures and not objects, so I placed this module under the
144             Data:: hierarchy.
145              
146             To use Data::Struct, just use it. This will export the struct()
147             function that does all the work.
148              
149             To define a structure, call struct() with the name of the structure and
150             a list of accessors to be created:
151              
152             struct( "Foo", "foo", "bar");
153              
154             which can be nicely written as:
155              
156             struct Foo => qw( foo bar );
157              
158             To prevent ambiguities, defining a struct requires struct() to be
159             called in void context.
160              
161             To create an empty structure:
162              
163             my $s = struct "Foo";
164              
165             To create a structure with one or more pre-initialised attributes:
166              
167             my $s = struct Foo => { foo => 3, bar => "Hi" };
168              
169             To prevent ambiguities, creating a struct requires struct() to be
170             called in scalar context.
171              
172             When the structure has been created, you can use accessor functions to
173             set and get the attributes:
174              
175             print "bar is " . $s->bar . "\n"; # "Hi"
176             $s->bar = 2;
177             print "bar is now " . $s->bar . "\n"; # 2
178              
179             =head1 PECULIARITIES
180              
181             Redefining a structure adds new attributes but leaves existing
182             attibutes untouched.
183              
184             struct "Foo" => qw(bar);
185             my $s = struct "Foo" => { bar => 2 };
186             struct Foo => qw(blech);
187             $s->blech = 4;
188             say $s->bar; # prints 2
189             say $s->blech; # prints 4
190              
191             This may change in a future version.
192              
193             =head1 SUPPORT
194              
195             Bugs should be reported via the CPAN bug tracker at
196              
197             L
198              
199             For other issues, contact the author.
200              
201             =head1 AUTHOR
202              
203             Johan Vromans Ejv@cpan.orgE.
204              
205             =head1 SEE ALSO
206              
207             L, L, L,
208             L.
209              
210             =head1 COPYRIGHT
211              
212             Copyright 2011 Johan Vromans
213              
214             This program is free software; you can redistribute
215             it and/or modify it under the same terms as Perl itself.
216              
217             =cut