|  line  | 
 stmt  | 
 bran  | 
 cond  | 
 sub  | 
 pod  | 
 time  | 
 code  | 
| 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 ### Data::DRef - Delimited-key access to complex data structures  | 
| 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
3
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 ### Copyright 1996, 1997, 1998, 1999 Evolution Online Systems, Inc.  | 
| 
4
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   # You may use this software for free under the terms of the Artistic License.   | 
| 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
6
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 ### Change History  | 
| 
7
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   # 1999-02-06 Added to CPAN module list. Repackaged for distribution.  | 
| 
8
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   # 1999-01-31 Collapsed Data::Collection into Data::DRef.  | 
| 
9
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   # 1999-01-31 Removed Data::Collection's dependancy on Data::Sorting.  | 
| 
10
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   # 1999-01-22 Revision of documentation, and improved Exporter tagging.  | 
| 
11
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   # 1998-12-01 Added get_value_for_optional_dref; minor doc revisions.  | 
| 
12
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   # 1998-10-15 Added explicit undef return value from get_value_for_key.  | 
| 
13
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   # 1998-10-14 Added doc caveat about possible use of UNIVERSAL methods.  | 
| 
14
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   # 1998-10-07 Reworked, conventionalized documentation and Exporter behaviour.  | 
| 
15
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   # 1998-10-06 Refactored value_for_keys algorithm; clarified dref syntax.  | 
| 
16
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   # 1998-07-16 Preliminary support for DRef pragmas: ignore (!reverse). -Simon  | 
| 
17
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   # 1998-05-21 Added undef behavior in matching_keys and matching_values.  | 
| 
18
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   # 1998-05-07 Replaced map with foreach in a few places.  | 
| 
19
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   # 1998-04-17 Updated to use new Data::Sorting interface.  | 
| 
20
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   # 1998-04-10 Added hash_by_array_key.  | 
| 
21
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   # 1998-04-09 Fixed single-item problem with scalarkeysof algorithm. -Simon  | 
| 
22
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   # 1998-03-12 Patched dref manipulation functions to escape separator.  | 
| 
23
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   # 1998-02-24 Changed valuesof to return value of non-ref arguments. -Piglet  | 
| 
24
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   # 1998-01-30 Added array_by_hash_key($) and intersperse($@) -Simon  | 
| 
25
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   # 1997-12-08 Removed package Data::Types, replaced with UNIVERSAL isa.  | 
| 
26
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   # 1997-12-07 Exported uniqueindexby.  -Piglet  | 
| 
27
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   # 1997-11-24 Finished orderedindexby.  | 
| 
28
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   # 1997-11-19 Renamed removekey function to shiftdref at Jeremy's suggestion.  | 
| 
29
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   # 1997-11-14 Added resolveparens behaviour to standard syntax.  | 
| 
30
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   # 1997-11-14 Added getDRef, setDRef functions as can() wrappers for get, set  | 
| 
31
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   # 1997-11-13 Added orderedindexby, but it still needs a bit of work.  | 
| 
32
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   # 1997-10-29 Add'l modifications; replaced recursion with iteration in get()  | 
| 
33
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   # 1997-10-25 Revisions; separator changed from colon to period.  | 
| 
34
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   # 1997-10-03 Refactored get and set operations  | 
| 
35
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   # 1997-09-05 Package split from the original dataops.pm into Data::*.  | 
| 
36
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   # 1997-04-18 Cleaned up documentation a smidge.  | 
| 
37
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   # 1997-04-08 Added getbysubkeys, now called matching_values  | 
| 
38
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   # 1997-01-29 Altered set to create hashes even for numerics  | 
| 
39
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   # 1997-01-28 Possible fix to recurring "keysof operates on containers" error.  | 
| 
40
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   # 1997-01-26 Catch bad argument types for sortby, indexby.  | 
| 
41
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   # 1997-01-21 Failure for keysof, valuesof now returns () rather than undef.  | 
| 
42
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   # 1997-01-21 Added scalarsof.  | 
| 
43
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   # 1997-01-11 Cloned and cleaned for IWAE; removed asdf code to dictionary.pm.  | 
| 
44
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   # 1996-11-18 Moved v2 code into production, additional cleanup. -Simon  | 
| 
45
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   # 1996-11-13 Version 2.00, major overhaul.   | 
| 
46
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   # 1996-10-29 Fixed set to handle '0' items. -Piglet  | 
| 
47
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   # 1996-09-09 Various changes, esp. fixing get to handle '0' items. -Simon  | 
| 
48
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   # 1996-07-24 Wrote copy, getString, added 'append' to set.  | 
| 
49
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   # 1996-07-18 Wrote setData, fixed headers.  -Piglet  | 
| 
50
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   # 1996-07-18 Additional Exporter fudging.  | 
| 
51
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   # 1996-07-17 Globalized theData. -Simon  | 
| 
52
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   # 1996-07-13 Simplified getData into get; wrote set. -Piglet  | 
| 
53
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   # 1996-06-25 Various tweaks.  | 
| 
54
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   # 1996-06-24 First version of dataops.pm created. -Simon  | 
| 
55
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
56
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 package Data::DRef;  | 
| 
57
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
58
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 require 5;  | 
| 
59
 | 
2
 | 
 
 | 
 
 | 
  
2
  
 | 
 
 | 
12650
 | 
 use strict;  | 
| 
 
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
4
 | 
    | 
| 
 
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
67
 | 
    | 
| 
60
 | 
2
 | 
 
 | 
 
 | 
  
2
  
 | 
 
 | 
12
 | 
 use Carp;  | 
| 
 
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
3
 | 
    | 
| 
 
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
142
 | 
    | 
| 
61
 | 
2
 | 
 
 | 
 
 | 
  
2
  
 | 
 
 | 
10
 | 
 use Exporter;  | 
| 
 
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
13
 | 
    | 
| 
 
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
81
 | 
    | 
| 
62
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
63
 | 
2
 | 
 
 | 
 
 | 
  
2
  
 | 
 
 | 
2987
 | 
 use String::Escape qw( printable unprintable );  | 
| 
 
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
13172
 | 
    | 
| 
 
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
188
 | 
    | 
| 
64
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
65
 | 
2
 | 
 
 | 
 
 | 
  
2
  
 | 
 
 | 
17
 | 
 use vars qw( $VERSION @ISA %EXPORT_TAGS );  | 
| 
 
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
2
 | 
    | 
| 
 
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
2976
 | 
    | 
| 
66
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 $VERSION = 1999.02_06;  | 
| 
67
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
68
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 push @ISA, qw( Exporter );  | 
| 
69
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 %EXPORT_TAGS = (  | 
| 
70
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   key_access => [ qw(  | 
| 
71
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     get_keys get_values get_value_for_key set_value_for_key   | 
| 
72
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     get_or_create_value_for_key get_reference_for_key   | 
| 
73
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     get_value_for_keys set_value_for_keys  | 
| 
74
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   ) ],   | 
| 
75
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   dref_syntax => [ qw(  | 
| 
76
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     $Separator $DRefPrefix dref_from_keys keys_from_dref   | 
| 
77
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     join_drefs unshift_dref_key shift_dref_key resolve_pragmas  | 
| 
78
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   ) ],   | 
| 
79
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   dref_access => [ qw(  | 
| 
80
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     get_key_drefs get_value_for_dref set_value_for_dref   | 
| 
81
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   ) ],   | 
| 
82
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   root_dref => [ qw(  | 
| 
83
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     $Root get_value_for_root_dref set_value_for_root_dref  | 
| 
84
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   ) ],   | 
| 
85
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   'select' => [ qw(   | 
| 
86
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     matching_keys matching_values   | 
| 
87
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   ) ],   | 
| 
88
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   'index' => [ qw(  | 
| 
89
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     index_by_drefs unique_index_by_drefs ordered_index_by_drefs  | 
| 
90
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   ) ],   | 
| 
91
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   'leaf' => [ qw(   | 
| 
92
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     leaf_drefs leaf_values leaf_drefs_and_values   | 
| 
93
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   ) ],   | 
| 
94
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   compat => [ qw(  | 
| 
95
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     getData setData getDRef setDRef joindref shiftdref $Root get set   | 
| 
96
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     $Separator splitdref keysof valuesof scalarkeysof scalarkeysandvalues   | 
| 
97
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     matching_values matching_keys indexby uniqueindexby orderedindexby  | 
| 
98
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   ) ],   | 
| 
99
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 );  | 
| 
100
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 Exporter::export_ok_tags( keys %EXPORT_TAGS );  | 
| 
101
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
102
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 ### Value-For-Key Interface  | 
| 
103
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
104
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # @keys = get_keys($target)  | 
| 
105
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub get_keys {  | 
| 
106
 | 
3
 | 
 
 | 
 
 | 
  
3
  
 | 
  
1
  
 | 
4
 | 
   my $target = shift;  | 
| 
107
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     | 
| 
108
 | 
3
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
17
 | 
   if ( UNIVERSAL::can($target, 'm_get_keys') ) {  | 
| 
 
 | 
 
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
 
 | 
 
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
109
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     return $target->m_get_keys(@_);  | 
| 
110
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   } elsif ( UNIVERSAL::isa($target, 'HASH') ) {  | 
| 
111
 | 
3
 | 
 
 | 
 
 | 
 
 | 
 
 | 
10
 | 
     return keys %$target;  | 
| 
112
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   } elsif ( UNIVERSAL::isa($target, 'ARRAY') ) {  | 
| 
113
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     return ( 0 .. $#$target );  | 
| 
114
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   } else {  | 
| 
115
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     return ();  | 
| 
116
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   }  | 
| 
117
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
118
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
119
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # @values = get_values($target)  | 
| 
120
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   # Returns a list of scalar values in a referenced hash or list  | 
| 
121
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub get_values {  | 
| 
122
 | 
0
 | 
 
 | 
 
 | 
  
0
  
 | 
  
1
  
 | 
0
 | 
   my $target = shift;  | 
| 
123
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     | 
| 
124
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
   if ( UNIVERSAL::can($target, 'm_get_values') ) {  | 
| 
 
 | 
 
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
 
 | 
 
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
 
 | 
 
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
125
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     return $target->m_get_values(@_);  | 
| 
126
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   } elsif ( UNIVERSAL::isa($target, 'HASH') ) {  | 
| 
127
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     return values %$target;  | 
| 
128
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   } elsif ( UNIVERSAL::isa($target, 'ARRAY') ) {  | 
| 
129
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     return @$target;   | 
| 
130
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   } elsif ( ! ref $target ) {  | 
| 
131
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     return $target;  | 
| 
132
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   } else {  | 
| 
133
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     return ();  | 
| 
134
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   }  | 
| 
135
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
136
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
137
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # $value = get_value_for_key($target, $key);  | 
| 
138
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub get_value_for_key ($$) {  | 
| 
139
 | 
29
 | 
 
 | 
 
 | 
  
29
  
 | 
  
1
  
 | 
29
 | 
   my $target = shift;  | 
| 
140
 | 
29
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
57
 | 
   croak "get called without target \n" unless (defined $target);  | 
| 
141
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     | 
| 
142
 | 
29
 | 
 
 | 
 
 | 
 
 | 
 
 | 
28
 | 
   my $key = shift;  | 
| 
143
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     | 
| 
144
 | 
29
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
144
 | 
   if ( UNIVERSAL::can($target, 'm_get_value_for_key') ) {  | 
| 
 
 | 
 
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
 
 | 
 
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
145
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     return $target->m_get_value_for_key($key);  | 
| 
146
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   } elsif ( UNIVERSAL::isa($target, 'HASH') ) {  | 
| 
147
 | 
26
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
98
 | 
     return $target->{$key} if (exists $target->{$key});  | 
| 
148
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   } elsif ( UNIVERSAL::isa($target, 'ARRAY') ) {  | 
| 
149
 | 
3
 | 
  
 50
  
 | 
  
 66
  
 | 
 
 | 
 
 | 
13
 | 
     carp "Use of non-numeric key '$key'" unless ( $key eq '0' or $key > 0 );  | 
| 
150
 | 
3
 | 
  
 50
  
 | 
  
 33
  
 | 
 
 | 
 
 | 
16
 | 
     return $target->[$key] if ($key >= 0 and $key < scalar @$target);  | 
| 
151
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   } else {  | 
| 
152
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     carp "'$target' can't get_value_for_key '$key'\n";  | 
| 
153
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   }  | 
| 
154
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
   return undef;  | 
| 
155
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
156
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
157
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # set_value_for_key($target, $key, $value);  | 
| 
158
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub set_value_for_key ($$$) {  | 
| 
159
 | 
5
 | 
 
 | 
 
 | 
  
5
  
 | 
  
1
  
 | 
7
 | 
   my $target = shift;  | 
| 
160
 | 
5
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
10
 | 
   croak "set_value_for_key called without target \n" unless (defined $target);  | 
| 
161
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     | 
| 
162
 | 
5
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
18
 | 
   if ( UNIVERSAL::can($target, 'm_set_value_for_key') ) {  | 
| 
 
 | 
 
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
 
 | 
 
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
163
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     return $target->m_set_value_for_key(@_);  | 
| 
164
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   } elsif ( UNIVERSAL::isa($target, 'HASH') ) {  | 
| 
165
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
30
 | 
     $target->{ $_[0] } = $_[1];  | 
| 
166
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   } elsif ( UNIVERSAL::isa($target, 'ARRAY') ) {  | 
| 
167
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     $target->[ $_[0] ] = $_[1];  | 
| 
168
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   } else {  | 
| 
169
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # We do not natively support set() on anything else.  | 
| 
170
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     carp "'$target' can't set_value_for_key '$_[0]'\n";  | 
| 
171
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   }  | 
| 
172
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
173
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
174
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # $value = get_or_create_value_for_key($target, $key);  | 
| 
175
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub get_or_create_value_for_key {  | 
| 
176
 | 
1
 | 
 
 | 
 
 | 
  
1
  
 | 
  
1
  
 | 
1
 | 
   my $target = shift;    | 
| 
177
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
2
 | 
   my $key = shift;  | 
| 
178
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     | 
| 
179
 | 
1
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
4
 | 
   return $target->m_get_or_create_value_for_key($key)  | 
| 
180
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	if ( UNIVERSAL::can($target, 'm_get_or_create_value_for_key') );  | 
| 
181
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     | 
| 
182
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
3
 | 
   my $value = get_value_for_key($target, $key);  | 
| 
183
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     | 
| 
184
 | 
1
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
4
 | 
   unless (defined $value) {  | 
| 
185
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     $value = {};  | 
| 
186
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     set_value_for_key($target, $key, $value);  | 
| 
187
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   }  | 
| 
188
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     | 
| 
189
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
66
 | 
   return $value;  | 
| 
190
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
191
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
192
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # $value_reference = get_reference_for_key($target, $key);  | 
| 
193
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub get_reference_for_key ($$) {  | 
| 
194
 | 
0
 | 
 
 | 
 
 | 
  
0
  
 | 
  
1
  
 | 
0
 | 
   my $target = shift;  | 
| 
195
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
   croak "get_reference_for_key called w/o target\n" unless (defined $target);  | 
| 
196
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     | 
| 
197
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
   my $key = shift;  | 
| 
198
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     | 
| 
199
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
   if ( UNIVERSAL::can($target, 'm_get_reference_for_key') ) {  | 
| 
 
 | 
 
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
 
 | 
 
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
200
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     return $target->m_get_reference_for_key($key);  | 
| 
201
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   } elsif ( UNIVERSAL::isa($target, 'HASH') ) {  | 
| 
202
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     return \${$target}{$key};  | 
| 
 
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
    | 
| 
203
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   } elsif ( UNIVERSAL::isa($target, 'ARRAY') ) {  | 
| 
204
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     return \${$target}[$key];  | 
| 
 
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
    | 
| 
205
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   } else {  | 
| 
206
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     carp "'$target' can't get_reference_for_key '$_[0]'\n";  | 
| 
207
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   }  | 
| 
208
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
209
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
210
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 ### Multiple-Key Chaining  | 
| 
211
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   #   | 
| 
212
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   # These functions allow access through a series of keys. Generally, the list   | 
| 
213
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   # of keys is interpreted each starting from the result of the previous one.   | 
| 
214
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
215
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # $value = get_value_for_keys($target, @keys);  | 
| 
216
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub get_value_for_keys ($@) {  | 
| 
217
 | 
17
 | 
 
 | 
 
 | 
  
17
  
 | 
  
1
  
 | 
21
 | 
   my $target = shift;  | 
| 
218
 | 
17
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
32
 | 
   croak "get_value_for_keys called without target \n" unless (defined $target);  | 
| 
219
 | 
17
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
35
 | 
   croak "get_value_for_keys called without keys \n" unless (scalar @_);  | 
| 
220
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     | 
| 
221
 | 
17
 | 
 
 | 
 
 | 
 
 | 
 
 | 
44
 | 
   while ( scalar @_ ) {  | 
| 
222
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # If we've got keys remaining, use the appropriate get method...  | 
| 
223
 | 
28
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
69
 | 
     return $target->m_get_value_for_keys(@_)   | 
| 
224
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	if UNIVERSAL::can($target, 'm_get_value_for_keys');  | 
| 
225
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       | 
| 
226
 | 
28
 | 
 
 | 
 
 | 
 
 | 
 
 | 
55
 | 
     my $key = shift @_;  | 
| 
227
 | 
28
 | 
 
 | 
 
 | 
 
 | 
 
 | 
49
 | 
     my $result = get_value_for_key($target, $key);  | 
| 
228
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       | 
| 
229
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # If there aren't any more keys, we're done!  | 
| 
230
 | 
28
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
114
 | 
     return $result unless (scalar @_);  | 
| 
231
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       | 
| 
232
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # We can't keep going without a ref value, despite the remaining keys  | 
| 
233
 | 
11
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
30
 | 
     return undef unless (ref $result);  | 
| 
234
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       | 
| 
235
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # ... or select the target and iterate through another key  | 
| 
236
 | 
11
 | 
 
 | 
 
 | 
 
 | 
 
 | 
31
 | 
     $target = $result;  | 
| 
237
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   }  | 
| 
238
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
239
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
240
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # set_value_for_keys($target, $value, @keys);  | 
| 
241
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub set_value_for_keys {  | 
| 
242
 | 
5
 | 
 
 | 
 
 | 
  
5
  
 | 
  
1
  
 | 
7
 | 
   my $target = shift;  | 
| 
243
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
6
 | 
   my $value = shift;  | 
| 
244
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     | 
| 
245
 | 
5
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
12
 | 
   croak "set_value_for_keys called without target \n" unless (defined $target);  | 
| 
246
 | 
5
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
12
 | 
   croak "set_value_for_keys called without keys \n" unless (scalar @_);  | 
| 
247
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     | 
| 
248
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
11
 | 
   while ( scalar @_ ) {  | 
| 
249
 | 
6
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
18
 | 
     return $target->m_set_value_for_keys($value, @_)   | 
| 
250
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	  if UNIVERSAL::can($target, 'm_set_value_for_keys');  | 
| 
251
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       | 
| 
252
 | 
6
 | 
 
 | 
 
 | 
 
 | 
 
 | 
7
 | 
     my $key = shift @_;  | 
| 
253
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       | 
| 
254
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # Last key -- we're at the end of the line  | 
| 
255
 | 
6
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
21
 | 
     return set_value_for_key($target, $key, $value) unless (scalar @_);  | 
| 
256
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       | 
| 
257
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # Get the value for this key, or create an empty hash ref to build into.  | 
| 
258
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
4
 | 
     my $result = get_or_create_value_for_key($target, $key);  | 
| 
259
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
           | 
| 
260
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # We've got keys remaining, but we can't keep going  | 
| 
261
 | 
1
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
21
 | 
     return undef unless (ref $result);  | 
| 
262
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       | 
| 
263
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
3
 | 
     $target = $result;  | 
| 
264
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   }  | 
| 
265
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
266
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
267
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # $value = get_or_create_value_for_keys($target, @keys);  | 
| 
268
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub get_or_create_value_for_keys {  | 
| 
269
 | 
0
 | 
 
 | 
 
 | 
  
0
  
 | 
  
1
  
 | 
0
 | 
   my $target = shift;  | 
| 
270
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
   my $value = shift;  | 
| 
271
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     | 
| 
272
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
   croak "set_value_for_keys called without target \n" unless (defined $target);  | 
| 
273
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
   croak "set_value_for_keys called without keys \n" unless (scalar @_);  | 
| 
274
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     | 
| 
275
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
   while ( scalar @_ ) {  | 
| 
276
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     return $target->m_get_or_create_value_for_keys($value, @_)   | 
| 
277
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	  if UNIVERSAL::can($target, 'm_get_or_create_value_for_keys');  | 
| 
278
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       | 
| 
279
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     my $key = shift @_;  | 
| 
280
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     my $result = get_or_create_value_for_key($target, $key);  | 
| 
281
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       | 
| 
282
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # If there aren't any more keys, we're done!  | 
| 
283
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     return $result unless (scalar @_);  | 
| 
284
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       | 
| 
285
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # We can't keep going without a ref value, despite the remaining keys  | 
| 
286
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     return undef unless (ref $result);  | 
| 
287
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       | 
| 
288
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # ... or select the target and iterate through another key  | 
| 
289
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     $target = $result;  | 
| 
290
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   }  | 
| 
291
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
292
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
293
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # $val_ref = get_reference_for_keys($target, @keys);  | 
| 
294
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub get_reference_for_keys {  | 
| 
295
 | 
0
 | 
 
 | 
 
 | 
  
0
  
 | 
  
1
  
 | 
0
 | 
   my $target = shift;  | 
| 
296
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     | 
| 
297
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
   croak "get_reference_for_keys called w/o target\n" unless (defined $target);  | 
| 
298
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
   croak "get_reference_for_keys called w/o keys \n" unless (scalar @_);  | 
| 
299
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     | 
| 
300
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
   while ( scalar @_ ) {  | 
| 
301
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     return $target->m_get_reference_for_keys(@_)   | 
| 
302
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	  if UNIVERSAL::can($target, 'm_get_reference_for_keys');  | 
| 
303
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       | 
| 
304
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     my $key = shift @_;  | 
| 
305
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       | 
| 
306
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # Last key -- we're at the end of the line  | 
| 
307
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     return get_reference_for_key($target, $key) unless (scalar @_);  | 
| 
308
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       | 
| 
309
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # Get the value for this key, or create an empty hash ref to build into.  | 
| 
310
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     my $result = get_or_create_value_for_key($target, $key);  | 
| 
311
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       | 
| 
312
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # We've got keys remaining, but we can't keep going  | 
| 
313
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     return undef unless (ref $result);  | 
| 
314
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       | 
| 
315
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     $target = $result;  | 
| 
316
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   }  | 
| 
317
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
318
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
319
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 ### DRef Syntax  | 
| 
320
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   #   | 
| 
321
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   # DRef strings are dot-separated   | 
| 
322
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
323
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # $Separator - Multiple-key delimiter character  | 
| 
324
 | 
2
 | 
 
 | 
 
 | 
  
2
  
 | 
 
 | 
11
 | 
 use vars qw( $Separator $DRefPrefix );  | 
| 
 
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
4
 | 
    | 
| 
 
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
1428
 | 
    | 
| 
325
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 $Separator = '.';  | 
| 
326
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 $DRefPrefix = '#';  | 
| 
327
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
328
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # @drefs = get_key_drefs($target);  | 
| 
329
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub get_key_drefs {  | 
| 
330
 | 
3
 | 
 
 | 
 
 | 
  
3
  
 | 
  
1
  
 | 
9
 | 
   map { printable($_) } get_keys( @_ );  | 
| 
 
 | 
4
 | 
 
 | 
 
 | 
 
 | 
 
 | 
20
 | 
    | 
| 
331
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
332
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
333
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # $dref = dref_from_keys( @keys );  | 
| 
334
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   # Return a dref composed of a list of $Separator-protected keys   | 
| 
335
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub dref_from_keys (@) {  | 
| 
336
 | 
0
 | 
 
 | 
 
 | 
  
0
  
 | 
  
1
  
 | 
0
 | 
   join $Separator, map { printable($_) } @_;  | 
| 
 
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
    | 
| 
337
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
338
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
339
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # @keys = keys_from_dref( $dref );  | 
| 
340
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   # Return a series of key strings extracted from a dref  | 
| 
341
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub keys_from_dref ($) {  | 
| 
342
 | 
22
 | 
 
 | 
 
 | 
  
22
  
 | 
  
1
  
 | 
28
 | 
   my $dref = shift;  | 
| 
343
 | 
22
 | 
 
 | 
 
 | 
 
 | 
 
 | 
21
 | 
   my @keys;  | 
| 
344
 | 
22
 | 
 
 | 
  
 66
  
 | 
 
 | 
 
 | 
119
 | 
   while ( defined $dref and length $dref ) {  | 
| 
345
 | 
34
 | 
 
 | 
 
 | 
 
 | 
 
 | 
397
 | 
     $dref =~ s/\A((?:[^\\\Q$Separator\E]+|\\.)*)(?:\Q$Separator\E|\Z)//m;  | 
| 
346
 | 
34
 | 
 
 | 
 
 | 
 
 | 
 
 | 
107
 | 
     push(@keys, unprintable($1));  | 
| 
347
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   }  | 
| 
348
 | 
22
 | 
 
 | 
 
 | 
 
 | 
 
 | 
266
 | 
   return @keys;  | 
| 
349
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
350
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
351
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # $dref = join_drefs( @drefs );  | 
| 
352
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub join_drefs (@) {   | 
| 
353
 | 
2
 | 
 
 | 
 
 | 
  
2
  
 | 
  
1
  
 | 
8
 | 
   join($Separator, @_);   | 
| 
354
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
355
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
356
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # unshift_dref_key( $dref, $key );  | 
| 
357
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   # Prepends key to dref -- modifies value of first argument  | 
| 
358
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub unshift_dref_key {  | 
| 
359
 | 
0
 | 
 
 | 
 
 | 
  
0
  
 | 
  
1
  
 | 
0
 | 
   $_[0] = join($Separator, unprintable($_[1]), $_[0]);  | 
| 
360
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
361
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
362
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # $key = shift_dref_key( $dref );  | 
| 
363
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   # Removes first key from dref -- modifies value of its argument  | 
| 
364
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub shift_dref_key {  | 
| 
365
 | 
0
 | 
 
 | 
 
 | 
  
0
  
 | 
  
1
  
 | 
0
 | 
   $_[0] =~ s/\A((?:[^\\\Q$Separator\E]+|\\.)*)(?:\Q$Separator\E|\Z)//m;  | 
| 
366
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
   return unprintable($1);  | 
| 
367
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
368
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
369
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # $dref = resolve_pragmas( $dref_with_embedded_parens );  | 
| 
370
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # ($dref, %options) = resolve_pragmas( $dref_with_embedded_parens );  | 
| 
371
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub resolve_pragmas ($) {  | 
| 
372
 | 
22
 | 
 
 | 
 
 | 
  
22
  
 | 
  
1
  
 | 
27
 | 
   my $path = shift;  | 
| 
373
 | 
22
 | 
 
 | 
 
 | 
 
 | 
 
 | 
33
 | 
   my $options = {};  | 
| 
374
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     | 
| 
375
 | 
22
 | 
 
 | 
 
 | 
 
 | 
 
 | 
69
 | 
   do {} while (   | 
| 
376
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     $path =~ s/(\A|[^\\]|[^\\](?:\\{2})*)\(([\#\!])([^\(\)]+)\)  | 
| 
377
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 		    /$1._expand_pragma($2, $3, $options)/ex   | 
| 
378
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   );  | 
| 
379
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     | 
| 
380
 | 
22
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
101
 | 
   return wantarray ? ($path, %$options) : $path;  | 
| 
381
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
382
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
383
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub _expand_pragma {  | 
| 
384
 | 
0
 | 
 
 | 
 
 | 
  
0
  
 | 
 
 | 
0
 | 
   my ($type, $value, $options) = @_;  | 
| 
385
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
   if ( $type eq $DRefPrefix ) {  | 
| 
 
 | 
 
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
386
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     return get_value_for_root_dref($value);  | 
| 
387
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   } elsif ( $type eq '!' ) {  | 
| 
388
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     $options->{ $value } = 1;  | 
| 
389
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   } else {  | 
| 
390
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     carp "use of unsupported DRef pragma '$type$value'";  | 
| 
391
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   }  | 
| 
392
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
   return '';  | 
| 
393
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
394
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
395
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 ### DRef Access  | 
| 
396
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
397
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # $value = get_value_for_dref($target, $dref);  | 
| 
398
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub get_value_for_dref {  | 
| 
399
 | 
17
 | 
 
 | 
 
 | 
  
17
  
 | 
  
1
  
 | 
40
 | 
   get_value_for_keys $_[0], keys_from_dref( (resolve_pragmas($_[1]))[0] );  | 
| 
400
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
401
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
402
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # set_value_for_dref($target, $dref, $value);  | 
| 
403
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub set_value_for_dref {  | 
| 
404
 | 
5
 | 
 
 | 
 
 | 
  
5
  
 | 
  
1
  
 | 
14
 | 
   set_value_for_keys $_[0], $_[2], keys_from_dref((resolve_pragmas($_[1]))[0]);  | 
| 
405
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
406
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
407
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 ### Shared Data Graph Entry  | 
| 
408
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
409
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # $Root - Data graph entry point  | 
| 
410
 | 
2
 | 
 
 | 
 
 | 
  
2
  
 | 
 
 | 
12
 | 
 use vars qw( $Root );  | 
| 
 
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
4
 | 
    | 
| 
 
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
2737
 | 
    | 
| 
411
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 $Root = {};  | 
| 
412
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
413
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # $value = get_value_for_root_dref($dref);  | 
| 
414
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub get_value_for_root_dref ($)  {   | 
| 
415
 | 
11
 | 
 
 | 
 
 | 
  
11
  
 | 
  
1
  
 | 
382
 | 
   get_value_for_dref($Root, @_)   | 
| 
416
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
417
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
418
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # $value = set_value_for_root_dref($dref, $value);  | 
| 
419
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub set_value_for_root_dref ($$) {   | 
| 
420
 | 
5
 | 
 
 | 
 
 | 
  
5
  
 | 
  
1
  
 | 
193
 | 
   set_value_for_dref($Root, @_)   | 
| 
421
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
422
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
423
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # $value = get_value_for_optional_dref($literal_or_dref_with_leading_hashmark);  | 
| 
424
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub get_value_for_optional_dref ($)  {   | 
| 
425
 | 
0
 | 
  
  0
  
 | 
 
 | 
  
0
  
 | 
  
1
  
 | 
0
 | 
   $_[0] =~ /^\Q$DRefPrefix\E(.*)/o ? get_value_for_root_dref($1) : $_[0]  | 
| 
426
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
427
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
428
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 ### Select by DRefs  | 
| 
429
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
430
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # $key or @keys = matching_keys($target, %dref_value_criteria_pairs);  | 
| 
431
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub matching_keys {  | 
| 
432
 | 
0
 | 
 
 | 
 
 | 
  
0
  
 | 
  
1
  
 | 
0
 | 
   my($target, %kvp_criteria) = @_;  | 
| 
433
 | 
0
 | 
  
  0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
0
 | 
   return unless ($target and scalar %kvp_criteria);  | 
| 
434
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
   my ($key, $dref, @keys);  | 
| 
435
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
   ITEM: foreach $key (get_keys $target) {  | 
| 
436
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     my $item = get_value_for_key($target,$key);  | 
| 
437
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     foreach $dref (keys %kvp_criteria) {  | 
| 
438
 | 
0
 | 
  
  0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
0
 | 
       next ITEM unless $kvp_criteria{$dref} eq (   | 
| 
 
 | 
 
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
439
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         defined $dref && length $dref ? get_value_for_dref($item,$dref) : $item   | 
| 
440
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       );  | 
| 
441
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
442
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     return $key unless (wantarray);  | 
| 
443
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     push @keys, $key;  | 
| 
444
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   }  | 
| 
445
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
   return @keys;  | 
| 
446
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
447
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
448
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # $item or @items = matching_values($target, %dref_value_criteria_pairs);  | 
| 
449
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub matching_values {  | 
| 
450
 | 
0
 | 
 
 | 
 
 | 
  
0
  
 | 
  
1
  
 | 
0
 | 
   my($target, %kvp_criteria) = @_;  | 
| 
451
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
   my($item, $dref, @items);  | 
| 
452
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
   ITEM: foreach $item ( get_values($target) ) {  | 
| 
453
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     foreach $dref (keys %kvp_criteria) {  | 
| 
454
 | 
0
 | 
  
  0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
0
 | 
       next ITEM unless $kvp_criteria{$dref} eq (   | 
| 
 
 | 
 
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
455
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         defined $dref && length $dref ? get_value_for_dref($item,$dref) : $item   | 
| 
456
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       );  | 
| 
457
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
458
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     return $item unless (wantarray);  | 
| 
459
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     push @items, $item;  | 
| 
460
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   }  | 
| 
461
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
   return @items;  | 
| 
462
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
463
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
464
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 ### Index by DRefs   | 
| 
465
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
466
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # $index = index_by_drefs($target, @drefs)  | 
| 
467
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub index_by_drefs {  | 
| 
468
 | 
0
 | 
 
 | 
 
 | 
  
0
  
 | 
  
1
  
 | 
0
 | 
   my($target, @drefs) = @_;  | 
| 
469
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
   my $index = {};  | 
| 
470
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     | 
| 
471
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
   my $item;  | 
| 
472
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
   foreach $item ( get_values($target) ) {  | 
| 
473
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     my @keys = map { get_value_for_dref($item, $_) } @drefs;  | 
| 
 
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
    | 
| 
474
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     my $grouping = get_reference_for_keys($index, @keys);  | 
| 
475
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     push @$$grouping, $item;  | 
| 
476
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   }  | 
| 
477
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     | 
| 
478
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
   return $index;  | 
| 
479
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
480
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
481
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # $index = unique_index_by_drefs($target, @drefs)  | 
| 
482
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub unique_index_by_drefs {  | 
| 
483
 | 
0
 | 
 
 | 
 
 | 
  
0
  
 | 
  
1
  
 | 
0
 | 
   my($target, @drefs) = @_;  | 
| 
484
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
   my $index = {};  | 
| 
485
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     | 
| 
486
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
   my $item;  | 
| 
487
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
   foreach $item (get_values ($target)) {  | 
| 
488
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     my @keys = map { get_value_for_dref($item, $_) } @drefs;  | 
| 
 
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
    | 
| 
489
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     set_value_for_keys($index, $item, @keys);  | 
| 
490
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   }  | 
| 
491
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     | 
| 
492
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
   return $index;  | 
| 
493
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
494
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
495
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # $entry_ary = ordered_index_by_drefs( $target, $index_dref );  | 
| 
496
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub ordered_index_by_drefs {  | 
| 
497
 | 
0
 | 
 
 | 
 
 | 
  
0
  
 | 
  
1
  
 | 
0
 | 
   my($target, $grouper) = @_;  | 
| 
498
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
   my $index = {};  | 
| 
499
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
   my $order = [];  | 
| 
500
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     | 
| 
501
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
   my $item;  | 
| 
502
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
   foreach $item ( get_values($target) ) {  | 
| 
503
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     my $value = get_value_for_dref($item, $grouper);  | 
| 
504
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     $value = '' unless (defined $value);  | 
| 
505
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     push @$order, (   | 
| 
506
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       $index->{$value} = { 'value' => $value, 'items' => [] }   | 
| 
507
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     ) unless ( exists($index->{ $value }) );  | 
| 
508
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     push @{ $index->{ $value }{'items'} }, $item;  | 
| 
 
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
    | 
| 
509
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   }  | 
| 
510
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
   return $order;  | 
| 
511
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
512
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
513
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 ### DRefs to Leaf nodes  | 
| 
514
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
515
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # @drefs = leaf_drefs($target);  | 
| 
516
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   # Returns a list of drefs for non-ref leaves in a referenced structure.  | 
| 
517
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   # Keep track of items we've visited previously to protect against loops.  | 
| 
518
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub leaf_drefs ($) {  | 
| 
519
 | 
1
 | 
 
 | 
 
 | 
  
1
  
 | 
  
1
  
 | 
2
 | 
   my $target = shift;  | 
| 
520
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
5
 | 
   my @drefs = get_key_drefs( $target );  | 
| 
521
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
9
 | 
   my %visited;  | 
| 
522
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   my $i;  | 
| 
523
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
6
 | 
   for ( $i = 0; $i <= $#drefs; $i++ ) {  | 
| 
524
 | 
4
 | 
 
 | 
 
 | 
 
 | 
 
 | 
13
 | 
     my $dref = $drefs[$i];  | 
| 
525
 | 
4
 | 
 
 | 
 
 | 
 
 | 
 
 | 
28
 | 
     my $value = get_value_for_dref($target, $dref);  | 
| 
526
 | 
4
 | 
  
100
  
 | 
  
 66
  
 | 
 
 | 
 
 | 
28
 | 
     next if ( ! ref $value or $visited{$value}++ );  | 
| 
527
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
4
 | 
     my @subkeys = get_key_drefs( $value );  | 
| 
528
 | 
2
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
18
 | 
     if ( scalar @subkeys ) {  | 
| 
529
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
5
 | 
       splice @drefs, $i, 1, map { join_drefs($dref, $_) } @subkeys;  | 
| 
 
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
4
 | 
    | 
| 
530
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
10
 | 
       $i--;  | 
| 
531
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
532
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   }  | 
| 
533
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
5
 | 
   return @drefs;  | 
| 
534
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
535
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
536
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # @values = leaf_values( $target )  | 
| 
537
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub leaf_values ($) {  | 
| 
538
 | 
0
 | 
 
 | 
 
 | 
  
0
  
 | 
  
1
  
 | 
0
 | 
   my $target = shift;  | 
| 
539
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
   map { get_value_for_dref($target, $_) } leaf_drefs( $target );  | 
| 
 
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
    | 
| 
540
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
541
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
542
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # %dref_value_pairs = leaf_drefs_and_values( $target )  | 
| 
543
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub leaf_drefs_and_values ($) {  | 
| 
544
 | 
1
 | 
 
 | 
 
 | 
  
1
  
 | 
  
1
  
 | 
15
 | 
   my $target = shift;  | 
| 
545
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
4
 | 
   map { $_, get_value_for_dref($target, $_) } leaf_drefs( $target );  | 
| 
 
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
7
 | 
    | 
| 
546
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
547
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
548
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 ### Compatiblity   | 
| 
549
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
550
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 *get = *get_value_for_dref;  | 
| 
551
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 *set = *set_value_for_dref;  | 
| 
552
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 *getDRef = *get_value_for_dref;  | 
| 
553
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 *setDRef = *set_value_for_dref;  | 
| 
554
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 *getData = *get_value_for_root_dref;  | 
| 
555
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 *setData = *set_value_for_root_dref;  | 
| 
556
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 *splitdref = *keys_from_dref;  | 
| 
557
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 *joindref = *dref_from_keys;  | 
| 
558
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 *shiftdref = *shift_dref_key;  | 
| 
559
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 *keysof = *get_keys;  | 
| 
560
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 *valuesof = *get_values;  | 
| 
561
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 *indexby = *index_by_drefs;  | 
| 
562
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 *uniqueindexby = *unique_index_by_drefs;  | 
| 
563
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 *orderedindexby = *ordered_index_by_drefs;  | 
| 
564
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 *scalarkeysof = *leaf_drefs;  | 
| 
565
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 *scalarkeysandvalues = *leaf_drefs_and_values;  | 
| 
566
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
567
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 ### Data::DRef::MethodBased  | 
| 
568
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
569
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 package Data::DRef::MethodBased;  | 
| 
570
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
571
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 ### Minimal DRef Interface for Object Methods  | 
| 
572
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
573
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # @keys = $target->m_get_keys()  | 
| 
574
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub m_get_keys {  | 
| 
575
 | 
0
 | 
 
 | 
 
 | 
  
0
  
 | 
 
 | 
 
 | 
   return ();  | 
| 
576
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
577
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
578
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # @values = $target->m_get_values()  | 
| 
579
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub m_get_values {  | 
| 
580
 | 
0
 | 
 
 | 
 
 | 
  
0
  
 | 
 
 | 
 
 | 
   my $target = shift;  | 
| 
581
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   map { $target->m_get_value_for_key($_) } $target->m_get_keys;  | 
| 
 
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
582
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
583
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
584
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # $value = $target->m_get_value_for_key($key);  | 
| 
585
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub m_get_value_for_key {  | 
| 
586
 | 
0
 | 
 
 | 
 
 | 
  
0
  
 | 
 
 | 
 
 | 
   my ($target, $key) = @_;  | 
| 
587
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   return $target->$key() if ( $target->can($key) );  | 
| 
588
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   die "$target is unable to get value for key '$key'\n";  | 
| 
589
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
590
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
591
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # $target->m_set_value_for_key($key, $value);  | 
| 
592
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub m_set_value_for_key {  | 
| 
593
 | 
0
 | 
 
 | 
 
 | 
  
0
  
 | 
 
 | 
 
 | 
   my ($target, $key, $value) = @_;  | 
| 
594
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   return $target->$key($value) if ( $target->can($key) );  | 
| 
595
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   die "$target is unable to set value for key '$key'\n";  | 
| 
596
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
597
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
598
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # No default implementation provided for these other supported methods...  | 
| 
599
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   # $value_reference = $target->m_get_reference_for_key($key);  | 
| 
600
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   # $value = $target->m_get_or_create_value_for_key($key);  | 
| 
601
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   # $value = $target->m_get_value_for_keys(@keys);  | 
| 
602
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   # $target->m_set_value_for_keys($value, @keys);  | 
| 
603
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   # $val_ref = $target->m_get_reference_for_keys(@keys);  | 
| 
604
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   # $target->m_set_value_for_keys($value, @keys);  | 
| 
605
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
606
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 1;  | 
| 
607
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
608
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 __END__  |