File Coverage

blib/lib/Data/Couplet.pm
Criterion Covered Total %
statement 8 10 80.0
branch n/a
condition n/a
subroutine 4 4 100.0
pod n/a
total 12 14 85.7


line stmt bran cond sub pod time code
1 3     3   135513 use strict;
  3         8  
  3         151  
2 3     3   19 use warnings FATAL => 'all';
  3         6  
  3         289  
3              
4             package Data::Couplet;
5             BEGIN {
6 3     3   133 $Data::Couplet::AUTHORITY = 'cpan:KENTNL';
7             }
8             {
9             $Data::Couplet::VERSION = '0.02004314';
10             }
11              
12             # ABSTRACT: Yet another (But Hopefully Better) Key-Value Storage mechanism
13              
14 3     3   2070 use Data::Couplet::Extension -base => 'Private', -with => [qw( KeyCount BasicReorder )];
  0            
  0            
15             use MooseX::Types::Moose qw( :all );
16             use Carp;
17             use namespace::autoclean;
18              
19             with( 'MooseX::Clone', );
20              
21              
22              
23              
24              
25              
26             sub BUILDARGS {
27             my @args = @_;
28             my $class = shift @args;
29             if ( scalar @args & 1 ) {
30             Carp::croak('Uneven list sent. ERROR: Must be an ordered array that simulates a hash [k,v,k,v]');
31             }
32              
33             my $c = Data::Couplet::Private->new();
34             while (@args) {
35             $c->_set( shift @args, shift @args );
36             }
37             return { %{$c} };
38             }
39              
40              
41              
42             sub set {
43             my ( $self, $object, $value ) = @_;
44             $self->_set( $object, $value );
45             return $self;
46             }
47              
48              
49              
50             sub unset {
51             my ( $self, @objects ) = @_;
52             foreach my $object (@objects) {
53             $self->unset_key( $self->_object_to_key($object) );
54             }
55             return $self;
56             }
57              
58              
59             sub __all_int {
60             my (@items) = @_;
61             for ( 0 .. $#items ) {
62             my $v = $items[$_];
63             carp("Token $_ is not an Int: $v ") unless is_Int($v);
64             }
65             return 1;
66             }
67              
68             sub __all_str {
69             my (@items) = @_;
70             for ( 0 .. $#items ) {
71             my $v = $items[$_];
72             carp("Token $_ is not a Str: $v ") unless is_Str($v);
73             }
74             return 1;
75             }
76              
77             sub unset_at {
78             my ( $self, @indices ) = @_;
79             __all_int(@indices);
80             @indices = sort { $a <=> $b } @indices;
81             @indices = grep {
82             $self->key_at($_) ? 1 : do {
83             Carp::carp("Warning: index $_ does not exist already");
84             0;
85             }
86             } @indices;
87             my $unset = 0;
88             foreach my $index (@indices) {
89             my $fake_index = ( $index - $unset );
90             my $key = $self->key_at($fake_index);
91             if ( not defined $key ) {
92             Carp::carp("Cant delete index $index($fake_index), it has no key.");
93             }
94             else {
95             $self->unset_key($key);
96             }
97             $unset++;
98             }
99             return $self;
100             }
101              
102              
103             sub unset_key {
104             my ( $self, @keys ) = @_;
105             __all_str(@keys);
106             foreach my $key (@keys) {
107              
108             #Skip any keys that aren't set
109             next unless ( exists $self->{_kv}->{$key} );
110             my $index = $self->{_ki}->{$key};
111             $self->_unset_at($index);
112             $self->_unset_key($key);
113             $self->_move_key_range( $index, $#{ $self->{_ik} }, 0 - 1 );
114             }
115             return $self;
116             }
117              
118              
119              
120             sub value {
121             my ( $self, $object ) = @_;
122             my $key = $self->_object_to_key($object);
123             return $self->{_kv}->{$key};
124             }
125              
126              
127             sub value_at {
128             my ( $self, $index ) = @_;
129             __all_int($index);
130             my $key = $self->{_ik}->[$index];
131             return $self->{_kv}->{$key};
132             }
133              
134              
135             sub values {
136             my ($self) = @_;
137             return map { $self->{_kv}->{$_} } @{ $self->{_ik} };
138             }
139              
140              
141             sub values_ref {
142             my ( $self, @args ) = @_;
143             return [ $self->values(@args) ];
144             }
145              
146              
147             sub key_values {
148             my ($self) = @_;
149             return map { ( $self->{_ko}->{$_}, $self->{_kv}->{$_} ) } @{ $self->{_ik} };
150             }
151              
152              
153             sub key_values_paired {
154             my ($self) = @_;
155             return map { [ $self->{_ko}->{$_}, $self->{_kv}->{$_} ] } @{ $self->{_ik} };
156             }
157              
158              
159              
160             sub keys {
161             my ($self) = @_;
162             return map { $self->key_object($_) } @{ $self->{_ik} };
163             }
164              
165              
166             sub key_at {
167             my ( $self, $index ) = @_;
168             __all_int($index);
169             return $self->{_ik}->[$index];
170             }
171              
172              
173             sub key_object {
174             my ( $self, $key ) = @_;
175             __all_str($key);
176             return $self->{_ko}->{$key};
177             }
178              
179              
180             sub key_object_at {
181             my ( $self, $index ) = @_;
182             __all_int($index);
183             return $self->{_ko}->{ $self->key_at($index) };
184             }
185              
186              
187             no Data::Couplet::Extension;
188             __PACKAGE__->meta->make_immutable();
189             1;
190              
191              
192             __END__
193             =pod
194              
195             =head1 NAME
196              
197             Data::Couplet - Yet another (But Hopefully Better) Key-Value Storage mechanism
198              
199             =head1 VERSION
200              
201             version 0.02004314
202              
203             =head1 SYNOPSIS
204              
205             use Data::Couplet;
206              
207             # Retain order.
208             my $couplet = Data::Couplet->new( a => $b , c => $d );
209              
210             my $output = $couplet->value('a'); # returns $b;
211              
212             my $hash = { 'this is a' => 'key' };
213              
214             $couplet->set( $hash, "hello");
215             $couplet->value( $hash ); # hello
216              
217             =head1 ALPHA CODE
218              
219             Lots of stuff is probably still broken, unimplemented, untested.
220              
221             User beware
222              
223             =head1 DIFFERENT
224              
225             Why is this module different?
226              
227             =over 4
228              
229             =item 1. No Tied Hashes.
230              
231             Tied hashes are IMO Ugly. Objects are far more handy for many things. Especially
232             in moose world. You want tied hashes, do it yourself.
233              
234             =item 2. Trying Hard to preserve non-scalar keys.
235              
236             I want it to be possible, to retain arbitrary references used as keys.
237              
238             =item 3. Permutation.
239              
240             Its not here yet, but there I<Will> eventually be reordering functions.
241              
242             =back
243              
244             I seriously looked all over CPAN for something that suited my needs and didn't find any.
245              
246             I then tried with Tie::IxHash::ButMoreFun, and then discovered that how I was
247             using Tie::IxHash wasn't even sustainable on different versions of Perl, and
248             based on the 1997 release date, I gave up on seeing that fixed.
249              
250             =head1 METHODS
251              
252             =head2 CONSTRUCTOR
253              
254             =head3 ->new( %orderd_pairs )
255              
256             Create a new Data::Couplet entity using a series of ordered pairs.
257              
258             $c = Data::Couplet->new( 'a' => 'b', 'c' => 'd' );
259              
260             =head2 ENTRY CREATION
261              
262             =head3 ->set( Any $object, Any $value ) : $self : Modifier
263              
264             Record the association of a key ( any object that can be coerced into a string ) to a value.
265              
266             New entries are pushed on the logical right hand end of it in array context.
267              
268             # { 'a' => 'b', 'c' => 'd' }
269             set( 'a', 'e' );
270             # { 'a' => 'e', 'c' => 'd' }
271             set('e', 'a' );
272             # { 'a' => 'e', 'c' => 'd', 'e' => 'a' }
273              
274             =head2 ENTRY REMOVAL
275              
276             =head3 ->unset( Array[Any] @objects ) : $self : Modifier
277              
278             Entries are ripped out of the structure, and all items moved around to fill the void.
279              
280             # { 'a' => 'b', 'c' => 'd','e'=>'f' }
281             ->unset( 'c' );
282             # { 'a' => 'b', 'e'=>'f' }
283             ->unset('a');
284             # { 'e' => 'f' }
285              
286             =head3 ->unset_at( Array[Int] @indices ) : $self : Modifier
287              
288             Like ->unset, except you know where ( logically ) in the order
289             off things the entry you wish to delete is.
290              
291             ->unset_at( 1 );
292             ->unset_at( 0 );
293              
294             Should be identical to the above code.
295              
296             =head3 ->unset_key( Array[Str] @keys ) : $self : Modifier
297              
298             This is what ->unset ultimately calls, except ->unset does implicit
299             object_to_key conversion first. At present, that's not anything huge, its just
300             C<$object> to convert it to a string. But this may change at some future time. So use that
301             method instead.
302              
303             =head2 VALUE MANIPULATION
304              
305             =head3 ->value( Any $object ) : Any $value
306              
307             Returns a value associated with a key object. See L</unset> for the semantics
308             of what object keys are.
309              
310             =head3 ->value_at( Int $index ) : Any $value
311              
312             Like value, but you need to know where in the data set the item is.
313              
314             =head3 ->values() : Any @list
315              
316             returns an array of all stored values in order.
317              
318             =head3 ->values_ref() : ArrayRef[Any] $list
319              
320             Just some nice syntax for [$o->values]
321              
322             =head3 ->key_values() : Any @list
323              
324             Returns an ordered sequence of key,value pairs, just like that passed
325             to the constructor.
326              
327             my @d = $o->key_values()
328             while( @d ){
329             my $key = shift @d;
330             my $value = shift @d;
331             print "$key => $value\n"
332             }
333              
334             =head3 ->key_values_paired() : Any[ArrayRef] @list
335              
336             Returns like ->key_values does but key/value is grouped for your convenience
337              
338             for ( $o->key_values_paired() ){
339             my ( $key, $value ) = @{ $_ };
340             }
341              
342             =head2 KEY MANIPULATION
343              
344             =head3 ->keys() : @list
345              
346             returns all known keys in order
347              
348             =head3 ->key_at( Int $index ) : String
349              
350             Given an index, return the key that holds that place.
351              
352             =head3 ->key_object( String $key ) : Any $object
353              
354             Given a string key, returns the object stored there.
355              
356             This is probably very unhelpful to you unless you explicitly
357             asked us for our internal key name.
358              
359             =head3 ->key_object_at( Int $index ) : Any $object
360              
361             As with key_object, except partially useful, because you can fetch
362             by ID.
363              
364             =head2 METHODS FROM PLUGINS
365              
366             By default, this package imports a few methods from various plug-ins.
367              
368             =over 4
369              
370             =item * L<Data::Couplet::Plugin::KeyCount>
371              
372             =over 4
373              
374             =item ->count
375              
376             =item ->last_index
377              
378             =item ->indices
379              
380             =back
381              
382             =item * L<Data::Couplet::Plugin::BasicReorder>
383              
384             =over 4
385              
386             =item ->move_up
387              
388             =item ->move_down
389              
390             =item ->swap
391              
392             =back
393              
394             =back
395              
396             =head1 AUTHOR
397              
398             Kent Fredric <kentnl at cpan.org>
399              
400             =head1 COPYRIGHT AND LICENSE
401              
402             This software is copyright (c) 2011 by Kent Fredric.
403              
404             This is free software; you can redistribute it and/or modify it under
405             the same terms as the Perl 5 programming language system itself.
406              
407             =cut
408