1 package Graph
::AdjacencyMap
::Heavy
;
3 # THIS IS INTERNAL IMPLEMENTATION ONLY, NOT TO BE USED DIRECTLY.
4 # THE INTERFACE IS HARD TO USE AND GOING TO STAY THAT WAY AND
5 # ALMOST GUARANTEED TO CHANGE OR GO AWAY IN FUTURE RELEASES.
9 # $SIG{__DIE__ } = sub { use Carp; confess };
10 # $SIG{__WARN__} = sub { use Carp; confess };
12 use Graph
::AdjacencyMap
qw(:flags :fields);
13 use base
'Graph::AdjacencyMap';
15 require overload
; # for de-overloading
22 my $id = pop if ($f & _MULTI
);
23 if (@_ != $m->[ _a
] && !($f & _HYPER
)) {
25 Carp
::confess
(sprintf "Graph::AdjacencyMap::Heavy: arguments %d expected %d",
26 scalar @_, $m->[ _a
]);
30 (( $m->[ _s
] ||= [ ] )->[ @_ ] ||= { }) :
31 ( $m->[ _s
] ||= { });
36 my $q = ref $k && ($f & _REF
) && overload
::Method
($k, '""') ? overload
::StrVal
($k) : $k;
38 $p = $p->{ $q } ||= {};
48 my ($m, $p, $l) = splice @_, 0, 3;
50 my $id = pop if ($f & _MULTI
);
51 unless (exists $p->[-1]->{ $l }) {
52 my $i = $m->_new_node( \
$p->[-1]->{ $l }, $id );
53 $m->[ _i
]->{ defined $i ?
$i : "" } = [ @_ ];
54 return defined $id ?
($id eq _GEN_ID ?
$$id : $id) : $i;
56 return $m->_inc_node( \
$p->[-1]->{ $l }, $id );
63 if (@_ > 1 && ($f & _UNORDUNIQ
)) {
64 if (($f & _UNORDUNIQ
) == _UNORD
&& @_ == 2) { @_ = sort @_ }
65 else { $m->__arg(\
@_) }
67 my ($p, $k) = $m->__set_path( @_ );
68 return unless defined $p && defined $k;
69 my $l = defined $k->[-1] ?
$k->[-1] : "";
70 return $m->__set_path_node( $p, $l, @_ );
76 if (@_ != $m->[ _a
] && !($f & _HYPER
)) {
78 Carp
::confess
(sprintf "Graph::AdjacencyMap::Heavy: arguments %d expected %d",
79 scalar @_, $m->[ _a
]);
81 if (@_ > 1 && ($f & _UNORDUNIQ
)) {
82 if (($f & _UNORDUNIQ
) == _UNORD
&& @_ == 2) { @_ = sort @_ }
83 else { $m->__arg(\
@_) }
86 return unless defined $p;
87 $p = $p->[ @_ ] if ($f & _HYPER
);
88 return unless defined $p;
93 my $q = ref $k && ($f & _REF
) && overload
::Method
($k, '""') ? overload
::StrVal
($k) : $k;
96 return unless defined $p;
107 if (@_ > 1 && ($f & _UNORDUNIQ
)) {
108 if (($f & _UNORDUNIQ
) == _UNORD
&& @_ == 2) { @_ = sort @_ }
109 else { $m->__arg(\
@_) }
111 my ($p, $k) = $m->__has_path( @_ );
112 return unless defined $p && defined $k;
113 return exists $p->[-1]->{ defined $k->[-1] ?
$k->[-1] : "" };
116 sub has_path_by_multi_id
{
120 if (@_ > 1 && ($f & _UNORDUNIQ
)) {
121 if (($f & _UNORDUNIQ
) == _UNORD
&& @_ == 2) { @_ = sort @_ }
122 else { $m->__arg(\
@_) }
124 my ($e, $n) = $m->__get_path_node( @_ );
125 return undef unless $e;
126 return exists $n->[ _nm
]->{ $id };
132 if ($m->[ _a
] == 2 && @_ == 2 && !($f & (_HYPER
|_REF
|_UNIQ
))) { # Fast path.
133 @_ = sort @_ if ($f & _UNORD
);
134 return unless exists $m->[ _s
]->{ $_[0] };
135 my $p = [ $m->[ _s
], $m->[ _s
]->{ $_[0] } ];
136 my $k = [ $_[0], $_[1] ];
138 return ( exists $p->[-1]->{ $l }, $p->[-1]->{ $l }, $p, $k, $l );
140 if (@_ > 1 && ($f & _UNORDUNIQ
)) {
141 if (($f & _UNORDUNIQ
) == _UNORD
&& @_ == 2) { @_ = sort @_ }
142 else { $m->__arg(\
@_) }
144 $m->__get_path_node( @_ );
152 if ($m->[ _a
] == 2 && @_ == 2 && !($f & (_HYPER
|_REF
|_UNIQ
))) { # Fast path.
153 @_ = sort @_ if ($f & _UNORD
);
154 return unless exists $m->[ _s
]->{ $_[0] };
155 my $p = $m->[ _s
]->{ $_[0] };
156 $e = exists $p->{ $_[1] };
159 ($e, $n) = $m->_get_path_node( @_ );
161 return undef unless $e;
162 return ref $n ?
$n->[ _ni
] : $n;
165 sub _get_path_count
{
168 my ($e, $n) = $m->_get_path_node( @_ );
169 return undef unless $e && defined $n;
171 ($f & _COUNT
) ?
$n->[ _nc
] :
172 ($f & _MULTI
) ?
scalar keys %{ $n->[ _nm
] } : 1;
178 if (ref $_[0] && @
{ $_[0] }) {
179 if (@
{ $_[0] } != $m->[ _a
]) {
181 Carp
::confess
(sprintf
182 "Graph::AdjacencyMap::Heavy: arguments %d expected %d\n",
183 scalar @
{ $_[0] }, $m->[ _a
]);
186 if (@
{ $_[0] } > 1 && ($f & _UNORDUNIQ
)) {
187 if (($f & _UNORDUNIQ
) == _UNORD
&& @
{ $_[0] } == 2) {
188 @
{ $_[0] } = sort @
{ $_[0] }
189 } else { $m->__arg(\
@_) }
197 my $p = defined $i ?
$m->[ _i
]->{ $i } : undef;
198 return defined $p ? @
$p : ( );
204 if (@_ > 1 && ($f & _UNORDUNIQ
)) {
205 if (($f & _UNORDUNIQ
) == _UNORD
&& @_ == 2) { @_ = sort @_ }
206 else { $m->__arg(\
@_) }
208 my ($e, $n, $p, $k, $l) = $m->__get_path_node( @_ );
210 my $c = ($f & _COUNT
) ?
--$n->[ _nc
] : 0;
212 delete $m->[ _i
]->{ ref $n ?
$n->[ _ni
] : $n };
213 delete $p->[-1]->{ $l };
214 while (@
$p && @
$k && keys %{ $p->[-1]->{ $k->[-1] } } == 0) {
215 delete $p->[-1]->{ $k->[-1] };
223 sub del_path_by_multi_id
{
227 if (@_ > 1 && ($f & _UNORDUNIQ
)) {
228 if (($f & _UNORDUNIQ
) == _UNORD
&& @_ == 2) { @_ = sort @_ }
229 else { $m->__arg(\
@_) }
231 my ($e, $n, $p, $k, $l) = $m->__get_path_node( @_ );
233 delete $n->[ _nm
]->{ $id };
234 unless (keys %{ $n->[ _nm
] }) {
235 delete $m->[ _i
]->{ $n->[ _ni
] };
236 delete $p->[-1]->{ $l };
237 while (@
$p && @
$k && keys %{ $p->[-1]->{ $k->[-1] } } == 0) {
238 delete $p->[-1]->{ $k->[-1] };
248 return values %{ $m->[ _i
] } if defined $m->[ _i
];