line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
###################################################################### |
2
|
|
|
|
|
|
|
############################################################################# |
3
|
|
|
|
|
|
|
package Data::Deep; |
4
|
|
|
|
|
|
|
############################################################################## |
5
|
|
|
|
|
|
|
# Ultimate tool for Perl data manipulation |
6
|
|
|
|
|
|
|
############################################################################ |
7
|
|
|
|
|
|
|
### Deep.pm |
8
|
|
|
|
|
|
|
############################################################################ |
9
|
|
|
|
|
|
|
# Copyright (c) 2005 Matthieu Damerose. All rights reserved. |
10
|
|
|
|
|
|
|
# This program is free software; you can redistribute it and/or |
11
|
|
|
|
|
|
|
# modify it under the same terms as Perl itself. |
12
|
|
|
|
|
|
|
############################################################################ |
13
|
|
|
|
|
|
|
### |
14
|
|
|
|
|
|
|
## |
15
|
|
|
|
|
|
|
# |
16
|
|
|
|
|
|
|
# |
17
|
|
|
|
|
|
|
|
18
|
|
|
|
|
|
|
|
19
|
|
|
|
|
|
|
=head1 NAME |
20
|
|
|
|
|
|
|
|
21
|
|
|
|
|
|
|
Data::Deep - Complexe Data Structure analysis and manipulation |
22
|
|
|
|
|
|
|
|
23
|
|
|
|
|
|
|
=head1 SYNOPSIS |
24
|
|
|
|
|
|
|
|
25
|
|
|
|
|
|
|
use Data::Deep; |
26
|
|
|
|
|
|
|
|
27
|
|
|
|
|
|
|
$dom1=[ \{'toto' => 12}, 33, {o=>5,d=>12}, 'titi' ]; |
28
|
|
|
|
|
|
|
|
29
|
|
|
|
|
|
|
$dom2=[ \{'toto' => 12, E=>3},{d=>12,o=>5}, 'titi' ]; |
30
|
|
|
|
|
|
|
|
31
|
|
|
|
|
|
|
my @patch = compare($dom1, $dom2); |
32
|
|
|
|
|
|
|
|
33
|
|
|
|
|
|
|
use Data::Deep qw(:DEFAULT :convert :config); |
34
|
|
|
|
|
|
|
|
35
|
|
|
|
|
|
|
o_complex(1); # deeper analysis results |
36
|
|
|
|
|
|
|
|
37
|
|
|
|
|
|
|
print join("\n", domPatch2TEXT( @patch ) ); |
38
|
|
|
|
|
|
|
|
39
|
|
|
|
|
|
|
@patch = ( |
40
|
|
|
|
|
|
|
'add(@0$,@0$%E)=3','remove(@1,)=33','move(@2,@1)=','move(@3,@2)=' |
41
|
|
|
|
|
|
|
); |
42
|
|
|
|
|
|
|
|
43
|
|
|
|
|
|
|
$dom2 = applyPatch($dom1,@patch); |
44
|
|
|
|
|
|
|
|
45
|
|
|
|
|
|
|
@list_found = search($dom1, ['@',1]) |
46
|
|
|
|
|
|
|
|
47
|
|
|
|
|
|
|
@list_found = search($dom1, patternText2Dom('@1')) |
48
|
|
|
|
|
|
|
|
49
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
51
|
|
|
|
|
|
|
=head1 DESCRIPTION |
52
|
|
|
|
|
|
|
|
53
|
|
|
|
|
|
|
Data::Deep provides search, path, compare and applyPatch functions which may operate on complex Perl Data Structure |
54
|
|
|
|
|
|
|
for introspection, usage and manipulation |
55
|
|
|
|
|
|
|
(ref, hash or array, array of hash, blessed object and siple scalar). |
56
|
|
|
|
|
|
|
Package, Filehandles and functions are partially supported (type and location is considered). |
57
|
|
|
|
|
|
|
Loop circular references are also considered as a $t1 variable and partially supported. |
58
|
|
|
|
|
|
|
|
59
|
|
|
|
|
|
|
|
60
|
|
|
|
|
|
|
=head2 path definition |
61
|
|
|
|
|
|
|
|
62
|
|
|
|
|
|
|
path expression identify the current element node location in a complex Perl data structure. |
63
|
|
|
|
|
|
|
pattern used in function search is used to match a part of this path. |
64
|
|
|
|
|
|
|
|
65
|
|
|
|
|
|
|
Path is composed internally of an array of following elements : |
66
|
|
|
|
|
|
|
|
67
|
|
|
|
|
|
|
('%', '') to match a hash table at value |
68
|
|
|
|
|
|
|
('@', ) to match an array at specified index value |
69
|
|
|
|
|
|
|
('*', '') to match a global reference |
70
|
|
|
|
|
|
|
('|', '') to match a blessed module reference |
71
|
|
|
|
|
|
|
|
72
|
|
|
|
|
|
|
('$') to match a reference |
73
|
|
|
|
|
|
|
('&') to match a code reference |
74
|
|
|
|
|
|
|
('$loop') to match a loop reference (circular reference) |
75
|
|
|
|
|
|
|
|
76
|
|
|
|
|
|
|
('=' ) to match the leaf node |
77
|
|
|
|
|
|
|
|
78
|
|
|
|
|
|
|
In text mode a keyname may be defined by entering an hash-ref of keys in o_key() |
79
|
|
|
|
|
|
|
then '/keyname' will appears in the path text results or could be provided |
80
|
|
|
|
|
|
|
to convert function textPatch2dom() and patternText2dom() |
81
|
|
|
|
|
|
|
|
82
|
|
|
|
|
|
|
|
83
|
|
|
|
|
|
|
Modifier > can be placed in the path with types to checks : |
84
|
|
|
|
|
|
|
|
85
|
|
|
|
|
|
|
EX: |
86
|
|
|
|
|
|
|
|
87
|
|
|
|
|
|
|
?% : match with hash-table content (any key match) |
88
|
|
|
|
|
|
|
?@ : match with an array content (any index match) |
89
|
|
|
|
|
|
|
?= : any value |
90
|
|
|
|
|
|
|
?* : any glob type |
91
|
|
|
|
|
|
|
?$ : any reference |
92
|
|
|
|
|
|
|
?=%@ : any value, hash-table or array |
93
|
|
|
|
|
|
|
?%@*|$&= : everything |
94
|
|
|
|
|
|
|
|
95
|
|
|
|
|
|
|
Evaluation function : |
96
|
|
|
|
|
|
|
sub{... test with $_ ... } will be executed to match the node |
97
|
|
|
|
|
|
|
EX: sub { /\d{2,}/ } match numbers of minimal size of two |
98
|
|
|
|
|
|
|
|
99
|
|
|
|
|
|
|
Patch is a directional operation to apply difference between two nodes resulting from compare($a, $b) |
100
|
|
|
|
|
|
|
Patch allow the $a complex perl data structure to be changed to $b using applyPatch($a,@patch) |
101
|
|
|
|
|
|
|
|
102
|
|
|
|
|
|
|
Each Patch operation is composed of : |
103
|
|
|
|
|
|
|
- an action : |
104
|
|
|
|
|
|
|
'add' for addition of an element from source to destination |
105
|
|
|
|
|
|
|
'remove' is the suppression from source to destination |
106
|
|
|
|
|
|
|
'move' if possible the move of a value or Perl Dom |
107
|
|
|
|
|
|
|
'change' describe the modification of a value |
108
|
|
|
|
|
|
|
'erase' is managed internally for array cleanup when using 'move' |
109
|
|
|
|
|
|
|
- a source path on which the value is taken from |
110
|
|
|
|
|
|
|
- a destination path on which is applied the change (most of the time same as source) |
111
|
|
|
|
|
|
|
|
112
|
|
|
|
|
|
|
Three patch formats can be use : |
113
|
|
|
|
|
|
|
- dom : interaction with search, path, compare, ApplyPatch |
114
|
|
|
|
|
|
|
- text : programmer facilities to use a single scalar for a patch operation |
115
|
|
|
|
|
|
|
- ihm : a small readble IHM text aim for output only |
116
|
|
|
|
|
|
|
|
117
|
|
|
|
|
|
|
Convert function may operation the change between this formats. |
118
|
|
|
|
|
|
|
|
119
|
|
|
|
|
|
|
|
120
|
|
|
|
|
|
|
DOM : dom patch hash-ref sample |
121
|
|
|
|
|
|
|
|
122
|
|
|
|
|
|
|
EX: my $patch1 = |
123
|
|
|
|
|
|
|
{ action=>'change', |
124
|
|
|
|
|
|
|
path_orig=>['@0','$','%a'], |
125
|
|
|
|
|
|
|
path_dest=>['@0','$','%a'], |
126
|
|
|
|
|
|
|
val_orig=>"toto", |
127
|
|
|
|
|
|
|
val_dest=>"tata" |
128
|
|
|
|
|
|
|
}; |
129
|
|
|
|
|
|
|
|
130
|
|
|
|
|
|
|
TEXT : text output mode patch could be : |
131
|
|
|
|
|
|
|
|
132
|
|
|
|
|
|
|
add(,)= |
133
|
|
|
|
|
|
|
remove(,)= |
134
|
|
|
|
|
|
|
change(,)=/=> |
135
|
|
|
|
|
|
|
move(,) |
136
|
|
|
|
|
|
|
|
137
|
|
|
|
|
|
|
|
138
|
|
|
|
|
|
|
=head2 Important note : |
139
|
|
|
|
|
|
|
|
140
|
|
|
|
|
|
|
* search() and path() functions use paths in "dom" format : |
141
|
|
|
|
|
|
|
|
142
|
|
|
|
|
|
|
DOM (simple array of elements described above) |
143
|
|
|
|
|
|
|
EX: ['@',1,'%','r','=',432] |
144
|
|
|
|
|
|
|
|
145
|
|
|
|
|
|
|
* applyPath() can use TEXT or DOM patch format in input. |
146
|
|
|
|
|
|
|
|
147
|
|
|
|
|
|
|
* compare() produce "dom" patch format in output. |
148
|
|
|
|
|
|
|
|
149
|
|
|
|
|
|
|
|
150
|
|
|
|
|
|
|
All function prefer the use of dom (internal format) then no convertion is done. |
151
|
|
|
|
|
|
|
Output (user point of view) is text or ihm. |
152
|
|
|
|
|
|
|
|
153
|
|
|
|
|
|
|
format patches dom can be converted to TEXT : domPatch2TEXT |
154
|
|
|
|
|
|
|
format patches text can be converted to DOM : textPatch2DOM |
155
|
|
|
|
|
|
|
format patches dom can be converted to IHM : domPatch2IHM |
156
|
|
|
|
|
|
|
|
157
|
|
|
|
|
|
|
See conversion function |
158
|
|
|
|
|
|
|
|
159
|
|
|
|
|
|
|
=cut |
160
|
|
|
|
|
|
|
|
161
|
|
|
|
|
|
|
|
162
|
|
|
|
|
|
|
############################################################################## |
163
|
|
|
|
|
|
|
# General version and rules |
164
|
|
|
|
|
|
|
############################################################################## |
165
|
1
|
|
|
1
|
|
6586
|
use 5.004; |
|
1
|
|
|
|
|
3
|
|
166
|
|
|
|
|
|
|
$VERSION = '0.13'; |
167
|
|
|
|
|
|
|
#$| = 1; |
168
|
|
|
|
|
|
|
|
169
|
|
|
|
|
|
|
############################################################################## |
170
|
|
|
|
|
|
|
# Module dep |
171
|
|
|
|
|
|
|
############################################################################## |
172
|
|
|
|
|
|
|
|
173
|
1
|
|
|
1
|
|
7
|
use Carp; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
73
|
|
174
|
1
|
|
|
1
|
|
5
|
use strict; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
17
|
|
175
|
1
|
|
|
1
|
|
3
|
no warnings; |
|
1
|
|
|
|
|
1
|
|
|
1
|
|
|
|
|
28
|
|
176
|
1
|
|
|
1
|
|
278
|
no integer; |
|
1
|
|
|
|
|
11
|
|
|
1
|
|
|
|
|
4
|
|
177
|
1
|
|
|
1
|
|
27
|
no strict 'refs'; |
|
1
|
|
|
|
|
1
|
|
|
1
|
|
|
|
|
26
|
|
178
|
|
|
|
|
|
|
|
179
|
|
|
|
|
|
|
|
180
|
1
|
|
|
1
|
|
758
|
use overload; require Exporter; our @ISA = qw(Exporter); |
|
1
|
|
|
|
|
723
|
|
|
1
|
|
|
|
|
6
|
|
181
|
|
|
|
|
|
|
|
182
|
|
|
|
|
|
|
|
183
|
|
|
|
|
|
|
our @DEFAULT = |
184
|
|
|
|
|
|
|
qw( |
185
|
|
|
|
|
|
|
travel |
186
|
|
|
|
|
|
|
visitor_patch |
187
|
|
|
|
|
|
|
visitor_dump |
188
|
|
|
|
|
|
|
visitor_perl_dump |
189
|
|
|
|
|
|
|
search |
190
|
|
|
|
|
|
|
compare |
191
|
|
|
|
|
|
|
path |
192
|
|
|
|
|
|
|
applyPatch |
193
|
|
|
|
|
|
|
__d |
194
|
|
|
|
|
|
|
); |
195
|
|
|
|
|
|
|
|
196
|
|
|
|
|
|
|
our @EXPORT = @DEFAULT; |
197
|
|
|
|
|
|
|
|
198
|
|
|
|
|
|
|
|
199
|
|
|
|
|
|
|
our @CONFIG = |
200
|
|
|
|
|
|
|
qw( |
201
|
|
|
|
|
|
|
o_debug |
202
|
|
|
|
|
|
|
o_follow_ref |
203
|
|
|
|
|
|
|
o_complex |
204
|
|
|
|
|
|
|
o_key |
205
|
|
|
|
|
|
|
); |
206
|
|
|
|
|
|
|
|
207
|
|
|
|
|
|
|
our @CONVERT = |
208
|
|
|
|
|
|
|
qw( |
209
|
|
|
|
|
|
|
patternText2Dom |
210
|
|
|
|
|
|
|
patternDom2Text |
211
|
|
|
|
|
|
|
textPatch2DOM |
212
|
|
|
|
|
|
|
domPatch2TEXT |
213
|
|
|
|
|
|
|
domPatch2IHM |
214
|
|
|
|
|
|
|
); |
215
|
|
|
|
|
|
|
|
216
|
|
|
|
|
|
|
our @EXPORT_OK = (@DEFAULT, |
217
|
|
|
|
|
|
|
@CONFIG, |
218
|
|
|
|
|
|
|
@CONVERT |
219
|
|
|
|
|
|
|
); |
220
|
|
|
|
|
|
|
|
221
|
|
|
|
|
|
|
|
222
|
|
|
|
|
|
|
our %EXPORT_TAGS=( |
223
|
|
|
|
|
|
|
convert=>[@CONVERT], |
224
|
|
|
|
|
|
|
config=>[@CONFIG] |
225
|
|
|
|
|
|
|
); |
226
|
|
|
|
|
|
|
############################################################################## |
227
|
|
|
|
|
|
|
#/````````````````````````````````````````````````````````````````````````````\ |
228
|
|
|
|
|
|
|
|
229
|
|
|
|
|
|
|
|
230
|
|
|
|
|
|
|
my $CONSOLE_LINE=78; |
231
|
|
|
|
|
|
|
|
232
|
|
|
|
|
|
|
############################################################################## |
233
|
|
|
|
|
|
|
|
234
|
|
|
|
|
|
|
|
235
|
|
|
|
|
|
|
=head2 Options Methods |
236
|
|
|
|
|
|
|
|
237
|
|
|
|
|
|
|
=over 4 |
238
|
|
|
|
|
|
|
|
239
|
|
|
|
|
|
|
=item I() |
240
|
|
|
|
|
|
|
|
241
|
|
|
|
|
|
|
configure nodes to skip (in search or compare) |
242
|
|
|
|
|
|
|
without parameter will return those nodes |
243
|
|
|
|
|
|
|
|
244
|
|
|
|
|
|
|
=cut |
245
|
|
|
|
|
|
|
|
246
|
|
|
|
|
|
|
|
247
|
|
|
|
|
|
|
sub zap { |
248
|
|
|
|
|
|
|
@_ and $Data::Deep::CFG->{zap}=shift() |
249
|
0
|
0
|
0
|
0
|
1
|
0
|
or return $Data::Deep::CFG->{zap}; |
250
|
|
|
|
|
|
|
} |
251
|
|
|
|
|
|
|
|
252
|
|
|
|
|
|
|
|
253
|
|
|
|
|
|
|
############################################################################# |
254
|
|
|
|
|
|
|
### OPTIONS DECLARATION |
255
|
|
|
|
|
|
|
############################################################################## |
256
|
|
|
|
|
|
|
# Declare option : _opt_dcl 'o_flg' |
257
|
|
|
|
|
|
|
# Read the option : o_flg() |
258
|
|
|
|
|
|
|
# Set the option : o_flg(1) |
259
|
|
|
|
|
|
|
############################################################################ |
260
|
|
|
|
|
|
|
|
261
|
|
|
|
|
|
|
our $CFG = {}; |
262
|
|
|
|
|
|
|
|
263
|
|
|
|
|
|
|
my $__opt_dcl = sub { my $name = shift(); |
264
|
|
|
|
|
|
|
my $proto = shift() || '$'; |
265
|
|
|
|
|
|
|
|
266
|
146
|
100
|
100
|
146
|
1
|
16785
|
eval 'sub '.$name."(;$proto) {" |
|
12794
|
50
|
66
|
12794
|
1
|
68276
|
|
|
1
|
50
|
33
|
1
|
1
|
8
|
|
267
|
|
|
|
|
|
|
.' @_ and $Data::Deep::CFG->{'.$name.'}=shift() |
268
|
|
|
|
|
|
|
or return $Data::Deep::CFG->{'.$name.'} }'; |
269
|
|
|
|
|
|
|
$@ and die '__bool_opt_dcl('.$name.') : '.$@; |
270
|
|
|
|
|
|
|
}; |
271
|
|
|
|
|
|
|
############################################################################ |
272
|
|
|
|
|
|
|
|
273
|
|
|
|
|
|
|
=item I([]) |
274
|
|
|
|
|
|
|
|
275
|
|
|
|
|
|
|
debug mode : |
276
|
|
|
|
|
|
|
1: set debug mode on |
277
|
|
|
|
|
|
|
0: set debug mode off |
278
|
|
|
|
|
|
|
undef : return debug mode |
279
|
|
|
|
|
|
|
|
280
|
|
|
|
|
|
|
=cut |
281
|
|
|
|
|
|
|
|
282
|
|
|
|
|
|
|
$__opt_dcl->('o_debug'); |
283
|
|
|
|
|
|
|
|
284
|
|
|
|
|
|
|
############################################################################ |
285
|
|
|
|
|
|
|
|
286
|
|
|
|
|
|
|
=item I([]) |
287
|
|
|
|
|
|
|
|
288
|
|
|
|
|
|
|
follow mode : |
289
|
|
|
|
|
|
|
1: follow every reference (default) |
290
|
|
|
|
|
|
|
0: do not enter into any reference |
291
|
|
|
|
|
|
|
undef: return if reference are followed |
292
|
|
|
|
|
|
|
|
293
|
|
|
|
|
|
|
=cut |
294
|
|
|
|
|
|
|
|
295
|
|
|
|
|
|
|
$__opt_dcl->('o_follow_ref'); |
296
|
|
|
|
|
|
|
|
297
|
|
|
|
|
|
|
o_follow_ref(1); |
298
|
|
|
|
|
|
|
|
299
|
|
|
|
|
|
|
|
300
|
|
|
|
|
|
|
############################################################################ |
301
|
|
|
|
|
|
|
|
302
|
|
|
|
|
|
|
=item I([]) |
303
|
|
|
|
|
|
|
|
304
|
|
|
|
|
|
|
complex mode is used for intelligency complex (EX: elements move in an array) |
305
|
|
|
|
|
|
|
1: complex mode used in search() & compare() |
306
|
|
|
|
|
|
|
0: simple analysis (no complex search) |
307
|
|
|
|
|
|
|
undef: return if reference are followed |
308
|
|
|
|
|
|
|
|
309
|
|
|
|
|
|
|
=cut |
310
|
|
|
|
|
|
|
|
311
|
|
|
|
|
|
|
$__opt_dcl->('o_complex'); |
312
|
|
|
|
|
|
|
|
313
|
|
|
|
|
|
|
|
314
|
|
|
|
|
|
|
############################################################################## |
315
|
|
|
|
|
|
|
sub debug { |
316
|
|
|
|
|
|
|
############################################################################## |
317
|
11422
|
50
|
|
11422
|
0
|
124735
|
o_debug() or return; |
318
|
|
|
|
|
|
|
|
319
|
|
|
|
|
|
|
# B.S./WIN : no output using STDERR |
320
|
0
|
0
|
|
0
|
0
|
0
|
sub out__ { (($^O=~/win/i)?print @_:print SDTERR @_) } |
321
|
|
|
|
|
|
|
|
322
|
0
|
|
|
|
|
0
|
my $l; |
323
|
0
|
|
|
|
|
0
|
foreach $l(@_) { |
324
|
|
|
|
|
|
|
(ref $l) |
325
|
|
|
|
|
|
|
and out__ "\n".__d($l) |
326
|
0
|
0
|
0
|
|
|
0
|
or do { |
327
|
0
|
|
|
|
|
0
|
out__$l; |
328
|
0
|
0
|
|
|
|
0
|
if (length($l)>$CONSOLE_LINE) { out__ "\n" } |
|
0
|
|
|
|
|
0
|
|
329
|
0
|
|
|
|
|
0
|
else { out__ ' ' } |
330
|
|
|
|
|
|
|
} |
331
|
|
|
|
|
|
|
} |
332
|
0
|
|
|
|
|
0
|
out__ "\n" |
333
|
|
|
|
|
|
|
} |
334
|
|
|
|
|
|
|
|
335
|
|
|
|
|
|
|
|
336
|
|
|
|
|
|
|
############################################################################## |
337
|
|
|
|
|
|
|
#{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{ |
338
|
|
|
|
|
|
|
sub __d { |
339
|
|
|
|
|
|
|
#{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{ |
340
|
1831
|
|
|
1831
|
|
5894
|
my $res = join('', travel(shift(), \&visitor_perl_dump)); |
341
|
|
|
|
|
|
|
#}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}} |
342
|
|
|
|
|
|
|
|
343
|
1831
|
|
|
|
|
10025
|
$res =~ s/ |
344
|
|
|
|
|
|
|
([\000-\037]|[\177-\377]) |
345
|
31
|
|
|
|
|
664
|
/sprintf("\\%o", ord ($1))/egx; |
346
|
|
|
|
|
|
|
|
347
|
1831
|
|
|
|
|
4208
|
return $res; |
348
|
|
|
|
|
|
|
} |
349
|
|
|
|
|
|
|
|
350
|
|
|
|
|
|
|
############################################################################## |
351
|
|
|
|
|
|
|
############################################################################### |
352
|
|
|
|
|
|
|
############################################################################### |
353
|
|
|
|
|
|
|
# PRIVATE FX |
354
|
|
|
|
|
|
|
############################################################################### |
355
|
|
|
|
|
|
|
############################################################################### |
356
|
|
|
|
|
|
|
|
357
|
|
|
|
|
|
|
|
358
|
|
|
|
|
|
|
############################################################################## |
359
|
|
|
|
|
|
|
#{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{ |
360
|
|
|
|
|
|
|
my $matchPath = sub { |
361
|
|
|
|
|
|
|
#{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{ |
362
|
|
|
|
|
|
|
my @pattern=@{shift()}; # to match |
363
|
|
|
|
|
|
|
my @where=@_; # current path |
364
|
|
|
|
|
|
|
#}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}} |
365
|
|
|
|
|
|
|
|
366
|
|
|
|
|
|
|
# warn 'matchPath('.join(' ',@where).' , '.join(' ',@pattern).')'; |
367
|
|
|
|
|
|
|
|
368
|
|
|
|
|
|
|
|
369
|
|
|
|
|
|
|
my $ok; |
370
|
|
|
|
|
|
|
# warn 'matchPath:LongAlgo( '.join(' ',@pattern).', '.join(' ',@where).' )'; |
371
|
|
|
|
|
|
|
my $i = 0; |
372
|
|
|
|
|
|
|
PATH:while ($i<=$#where) { |
373
|
|
|
|
|
|
|
|
374
|
|
|
|
|
|
|
my $j = 0; |
375
|
|
|
|
|
|
|
my $sav_i = $i; |
376
|
|
|
|
|
|
|
|
377
|
|
|
|
|
|
|
PATTERN: while ($i<=$#where) { |
378
|
|
|
|
|
|
|
|
379
|
|
|
|
|
|
|
### CURRENT PATH |
380
|
|
|
|
|
|
|
my $t_where = $where[$i++]; # TYPE |
381
|
|
|
|
|
|
|
|
382
|
|
|
|
|
|
|
## PATTERN |
383
|
|
|
|
|
|
|
my $t_patt = $pattern[$j++]; # TYPE |
384
|
|
|
|
|
|
|
|
385
|
|
|
|
|
|
|
if ($t_patt eq '/') { |
386
|
|
|
|
|
|
|
die 'internal matchPath('.join('',@pattern).') : key usage is only in textual format (use Text and convertion patternText2Dom)'; |
387
|
|
|
|
|
|
|
} |
388
|
|
|
|
|
|
|
|
389
|
|
|
|
|
|
|
#print "$t_where =~ $t_patt : "; |
390
|
|
|
|
|
|
|
|
391
|
|
|
|
|
|
|
(index($t_patt,$t_where)==-1) and last PATTERN; # type where should be found in the pattern |
392
|
|
|
|
|
|
|
|
393
|
|
|
|
|
|
|
if ($t_where eq '&') { } |
394
|
|
|
|
|
|
|
elsif ($t_where eq '$') { } |
395
|
|
|
|
|
|
|
elsif ($t_where eq '=' or |
396
|
|
|
|
|
|
|
$t_where eq '%' or |
397
|
|
|
|
|
|
|
$t_where eq '@' or |
398
|
|
|
|
|
|
|
$t_where eq '*' or |
399
|
|
|
|
|
|
|
$t_where eq '|' |
400
|
|
|
|
|
|
|
) { |
401
|
|
|
|
|
|
|
|
402
|
|
|
|
|
|
|
my $v_where = $where[$i++]; |
403
|
|
|
|
|
|
|
|
404
|
|
|
|
|
|
|
unless (substr($t_patt,0,1) eq '?') { |
405
|
|
|
|
|
|
|
#print 'v'; |
406
|
|
|
|
|
|
|
|
407
|
|
|
|
|
|
|
my $v_patt = $pattern[$j++]; |
408
|
|
|
|
|
|
|
|
409
|
|
|
|
|
|
|
if (ref($v_patt) eq 'CODE') { # regexp or complexe val |
410
|
|
|
|
|
|
|
local ($_) = ($v_where); |
411
|
|
|
|
|
|
|
$v_patt->($_) or last PATTERN |
412
|
|
|
|
|
|
|
} |
413
|
|
|
|
|
|
|
elsif (ref($v_patt) and (__d($v_patt) ne __d($v_where))) { |
414
|
|
|
|
|
|
|
last PATTERN; |
415
|
|
|
|
|
|
|
} |
416
|
|
|
|
|
|
|
elsif (!defined($v_where) and defined($v_patt)) { |
417
|
|
|
|
|
|
|
# print '!'; |
418
|
|
|
|
|
|
|
last PATTERN; |
419
|
|
|
|
|
|
|
} |
420
|
|
|
|
|
|
|
elsif (defined($v_where) and !defined($v_patt)) { |
421
|
|
|
|
|
|
|
# print '!'; |
422
|
|
|
|
|
|
|
last PATTERN; |
423
|
|
|
|
|
|
|
} |
424
|
|
|
|
|
|
|
elsif (defined($v_where) and defined($v_patt) and $v_patt ne $v_where) { |
425
|
|
|
|
|
|
|
# print '!'; |
426
|
|
|
|
|
|
|
last PATTERN; |
427
|
|
|
|
|
|
|
} |
428
|
|
|
|
|
|
|
} |
429
|
|
|
|
|
|
|
} |
430
|
|
|
|
|
|
|
else { |
431
|
|
|
|
|
|
|
#print '#'; |
432
|
|
|
|
|
|
|
($i-1==$#where) |
433
|
|
|
|
|
|
|
or |
434
|
|
|
|
|
|
|
die 'Error in matched expression "'.join('',@where).'" not supported char type "'.$t_where.'".'; |
435
|
|
|
|
|
|
|
} |
436
|
|
|
|
|
|
|
#print '.'; |
437
|
|
|
|
|
|
|
if ($j-1==$#pattern and $i-1==$#where) { |
438
|
|
|
|
|
|
|
# warn "#found($i,$j)"; |
439
|
|
|
|
|
|
|
return $sav_i; |
440
|
|
|
|
|
|
|
} |
441
|
|
|
|
|
|
|
|
442
|
|
|
|
|
|
|
}# PATTERN: |
443
|
|
|
|
|
|
|
|
444
|
|
|
|
|
|
|
# next time |
445
|
|
|
|
|
|
|
($j>1) and $i = $sav_i+1; |
446
|
|
|
|
|
|
|
|
447
|
|
|
|
|
|
|
}# WHERE: |
448
|
|
|
|
|
|
|
|
449
|
|
|
|
|
|
|
#print "\n"; |
450
|
|
|
|
|
|
|
return undef; |
451
|
|
|
|
|
|
|
}; |
452
|
|
|
|
|
|
|
|
453
|
|
|
|
|
|
|
############################################################################## |
454
|
|
|
|
|
|
|
# KEY DCL : |
455
|
|
|
|
|
|
|
|
456
|
|
|
|
|
|
|
sub o_key { |
457
|
|
|
|
|
|
|
@_ and $CFG->{o_key}=shift() |
458
|
4
|
100
|
66
|
4
|
1
|
119
|
or return $CFG->{o_key}; |
459
|
|
|
|
|
|
|
} |
460
|
|
|
|
|
|
|
|
461
|
|
|
|
|
|
|
=item I() |
462
|
|
|
|
|
|
|
|
463
|
|
|
|
|
|
|
key is a search pattern for simplifying search or compare. |
464
|
|
|
|
|
|
|
or a group of pattern for best identification of nodes. |
465
|
|
|
|
|
|
|
|
466
|
|
|
|
|
|
|
hash of key path: |
467
|
|
|
|
|
|
|
|
468
|
|
|
|
|
|
|
|
469
|
|
|
|
|
|
|
EX: |
470
|
|
|
|
|
|
|
key( |
471
|
|
|
|
|
|
|
CRC => {regexp=>['%','crc32'], |
472
|
|
|
|
|
|
|
eval=>'{crc32}', |
473
|
|
|
|
|
|
|
priority=>1 |
474
|
|
|
|
|
|
|
}, |
475
|
|
|
|
|
|
|
SZ => {regexp=>['%','sz'), |
476
|
|
|
|
|
|
|
eval=>'{sz}', |
477
|
|
|
|
|
|
|
priority=>2 |
478
|
|
|
|
|
|
|
} |
479
|
|
|
|
|
|
|
) |
480
|
|
|
|
|
|
|
|
481
|
|
|
|
|
|
|
|
482
|
|
|
|
|
|
|
regexp : path to search in the dom |
483
|
|
|
|
|
|
|
eval : is the perl way to match the node |
484
|
|
|
|
|
|
|
priority : on the same node two ambigues keys are prioritized |
485
|
|
|
|
|
|
|
depth : how many upper node to return from the current match node |
486
|
|
|
|
|
|
|
|
487
|
|
|
|
|
|
|
=back |
488
|
|
|
|
|
|
|
|
489
|
|
|
|
|
|
|
=cut |
490
|
|
|
|
|
|
|
|
491
|
|
|
|
|
|
|
|
492
|
|
|
|
|
|
|
|
493
|
|
|
|
|
|
|
|
494
|
|
|
|
|
|
|
############################################################################## |
495
|
|
|
|
|
|
|
#{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{ |
496
|
|
|
|
|
|
|
my $patchDOM = sub($$$;$$) { |
497
|
|
|
|
|
|
|
#}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}} |
498
|
|
|
|
|
|
|
my $action = shift; |
499
|
|
|
|
|
|
|
my $p1= shift(); |
500
|
|
|
|
|
|
|
my $p2= shift(); |
501
|
|
|
|
|
|
|
my $v1 = shift(); |
502
|
|
|
|
|
|
|
my $v2 = shift(); |
503
|
|
|
|
|
|
|
#}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}} |
504
|
|
|
|
|
|
|
|
505
|
|
|
|
|
|
|
my $dom = {}; |
506
|
|
|
|
|
|
|
$dom->{action} = $action; |
507
|
|
|
|
|
|
|
$dom->{path_orig} = $p1; |
508
|
|
|
|
|
|
|
$dom->{path_dest} = $p2; |
509
|
|
|
|
|
|
|
$dom->{val_orig} = $v1; |
510
|
|
|
|
|
|
|
$dom->{val_dest} = $v2; |
511
|
|
|
|
|
|
|
|
512
|
|
|
|
|
|
|
return $dom; |
513
|
|
|
|
|
|
|
}; |
514
|
|
|
|
|
|
|
|
515
|
|
|
|
|
|
|
|
516
|
|
|
|
|
|
|
############################################################################## |
517
|
|
|
|
|
|
|
#{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{ |
518
|
|
|
|
|
|
|
my $path2eval__ = sub { |
519
|
|
|
|
|
|
|
#{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{ |
520
|
|
|
|
|
|
|
my $first_eval = shift(); |
521
|
|
|
|
|
|
|
my $deepness = shift(); # [ 0.. N ] return N from root |
522
|
|
|
|
|
|
|
# [-N..-1] return N stage from leaves |
523
|
|
|
|
|
|
|
#{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{ |
524
|
|
|
|
|
|
|
|
525
|
|
|
|
|
|
|
my $evaled = $first_eval; |
526
|
|
|
|
|
|
|
|
527
|
|
|
|
|
|
|
my $dbg_head = __PACKAGE__."::path2eval__(".join(',',@_).") : "; |
528
|
|
|
|
|
|
|
debug $dbg_head; |
529
|
|
|
|
|
|
|
my $max=$#_; |
530
|
|
|
|
|
|
|
|
531
|
|
|
|
|
|
|
@_ or return $evaled; |
532
|
|
|
|
|
|
|
|
533
|
|
|
|
|
|
|
if (defined $deepness and $deepness<=0) { # start from the end |
534
|
|
|
|
|
|
|
while ($deepness++<0 and $max>=0) { |
535
|
|
|
|
|
|
|
$_[$max-1] =~ /^[\@%\*\|\/=]$/ and $max-=2 |
536
|
|
|
|
|
|
|
or |
537
|
|
|
|
|
|
|
$_[$max] =~ /^[\$\&]$/ and $max--; |
538
|
|
|
|
|
|
|
} |
539
|
|
|
|
|
|
|
($max==0) and return $evaled; # upper as root |
540
|
|
|
|
|
|
|
|
541
|
|
|
|
|
|
|
debug "\n negative depth $deepness: -> remaining path(".join(',',@_[0..$max]).")\n"; |
542
|
|
|
|
|
|
|
$deepness=undef; |
543
|
|
|
|
|
|
|
} |
544
|
|
|
|
|
|
|
my $deref='->'; |
545
|
|
|
|
|
|
|
|
546
|
|
|
|
|
|
|
my $i=0; |
547
|
|
|
|
|
|
|
while($i<=$max) { |
548
|
|
|
|
|
|
|
$_ = $_[$i++]; |
549
|
|
|
|
|
|
|
|
550
|
|
|
|
|
|
|
if ($_ eq '$') { |
551
|
|
|
|
|
|
|
$evaled = '${'.$evaled.'}'; |
552
|
|
|
|
|
|
|
$deref = '->'; |
553
|
|
|
|
|
|
|
} |
554
|
|
|
|
|
|
|
elsif ($_ eq '%') { |
555
|
|
|
|
|
|
|
$evaled .= $deref."{'".$_[$i++]."'}"; |
556
|
|
|
|
|
|
|
$deref=''; |
557
|
|
|
|
|
|
|
} |
558
|
|
|
|
|
|
|
elsif ($_ eq '@') { |
559
|
|
|
|
|
|
|
$evaled .= $deref.'['.$_[$i++].']'; |
560
|
|
|
|
|
|
|
$deref=''; |
561
|
|
|
|
|
|
|
} |
562
|
|
|
|
|
|
|
elsif ($_ eq '|') { |
563
|
|
|
|
|
|
|
$i++; |
564
|
|
|
|
|
|
|
} |
565
|
|
|
|
|
|
|
elsif ($_ eq '*') { |
566
|
|
|
|
|
|
|
$i++; |
567
|
|
|
|
|
|
|
my $suiv = $_[$i] or next; |
568
|
|
|
|
|
|
|
if ($suiv eq '%') { |
569
|
|
|
|
|
|
|
$evaled = '*{'.$evaled.'}{HASH}'; |
570
|
|
|
|
|
|
|
$deref = '->'; |
571
|
|
|
|
|
|
|
} |
572
|
|
|
|
|
|
|
elsif ($suiv eq '@'){ |
573
|
|
|
|
|
|
|
$evaled = '*{'.$evaled.'}{ARRAY}'; |
574
|
|
|
|
|
|
|
$deref = '->'; |
575
|
|
|
|
|
|
|
} |
576
|
|
|
|
|
|
|
elsif ($suiv eq '$' or $suiv eq '='){ |
577
|
|
|
|
|
|
|
$evaled = '*{'.$evaled.'}{SCALAR}'; |
578
|
|
|
|
|
|
|
$deref = '->'; |
579
|
|
|
|
|
|
|
} |
580
|
|
|
|
|
|
|
} |
581
|
|
|
|
|
|
|
elsif ($_ eq '/') { # KEY->{eval} |
582
|
|
|
|
|
|
|
my $keyname = $_[$i++]; |
583
|
|
|
|
|
|
|
my $THEKEY = $CFG->{o_key}{$keyname}; |
584
|
|
|
|
|
|
|
my $ev = $THEKEY->{eval} or die $dbg_head.'bad eval code for '.$keyname; |
585
|
|
|
|
|
|
|
$evaled .= $deref.$ev; |
586
|
|
|
|
|
|
|
$deref=''; |
587
|
|
|
|
|
|
|
} |
588
|
|
|
|
|
|
|
elsif ($_ eq '&') { |
589
|
|
|
|
|
|
|
$evaled = $evaled.'->()'; |
590
|
|
|
|
|
|
|
} |
591
|
|
|
|
|
|
|
elsif ($_ eq '=') { |
592
|
|
|
|
|
|
|
($i==$#_) or die $dbg_head.'bad path format : value waited in path after "="'; |
593
|
|
|
|
|
|
|
|
594
|
|
|
|
|
|
|
if ($_[$i]=~/^\d+$/) { |
595
|
|
|
|
|
|
|
$evaled = 'int('.$evaled.'=='.$_[$i++].')' |
596
|
|
|
|
|
|
|
} |
597
|
|
|
|
|
|
|
else { |
598
|
|
|
|
|
|
|
$evaled = 'int('.$evaled.' eq \''.$_[$i++].'\')' |
599
|
|
|
|
|
|
|
} |
600
|
|
|
|
|
|
|
|
601
|
|
|
|
|
|
|
$deref=''; |
602
|
|
|
|
|
|
|
} |
603
|
|
|
|
|
|
|
else { |
604
|
|
|
|
|
|
|
die $dbg_head.'bad path format : Type '.$_.' not supported.' |
605
|
|
|
|
|
|
|
} |
606
|
|
|
|
|
|
|
|
607
|
|
|
|
|
|
|
if (defined($deepness)) { # >0 start from root |
608
|
|
|
|
|
|
|
#print "\n positive depth $deepness:"; |
609
|
|
|
|
|
|
|
last if (--$deepness==0); |
610
|
|
|
|
|
|
|
} |
611
|
|
|
|
|
|
|
} |
612
|
|
|
|
|
|
|
debug "-> $evaled #\n"; |
613
|
|
|
|
|
|
|
return $evaled; |
614
|
|
|
|
|
|
|
}; |
615
|
|
|
|
|
|
|
|
616
|
|
|
|
|
|
|
my %loop_ref=(); |
617
|
|
|
|
|
|
|
############################################################################## |
618
|
|
|
|
|
|
|
#{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{ |
619
|
|
|
|
|
|
|
sub loop_det($;@) { |
620
|
|
|
|
|
|
|
#{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{ |
621
|
|
|
|
|
|
|
|
622
|
13136
|
|
|
13136
|
0
|
15176
|
my $r = shift(); |
623
|
13136
|
100
|
|
|
|
22412
|
ref($r) or return 0; |
624
|
|
|
|
|
|
|
|
625
|
4687
|
|
|
|
|
8936
|
$r = $r.' '; |
626
|
|
|
|
|
|
|
|
627
|
4687
|
100
|
|
|
|
6742
|
if (exists($loop_ref{$r})) { |
628
|
66
|
|
|
|
|
163
|
debug "loop_det => LOOP".join('',@_) ; |
629
|
|
|
|
|
|
|
|
630
|
66
|
|
|
|
|
121
|
return 1; |
631
|
|
|
|
|
|
|
} |
632
|
|
|
|
|
|
|
|
633
|
4621
|
|
|
|
|
6569
|
$loop_ref{$r}=1; |
634
|
4621
|
|
|
|
|
7619
|
return 0; |
635
|
|
|
|
|
|
|
} |
636
|
|
|
|
|
|
|
|
637
|
|
|
|
|
|
|
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
638
|
|
|
|
|
|
|
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
639
|
|
|
|
|
|
|
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
640
|
|
|
|
|
|
|
# PUBLIC FX |
641
|
|
|
|
|
|
|
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
642
|
|
|
|
|
|
|
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
643
|
|
|
|
|
|
|
|
644
|
|
|
|
|
|
|
|
645
|
|
|
|
|
|
|
|
646
|
|
|
|
|
|
|
|
647
|
|
|
|
|
|
|
=head2 Operation Methods |
648
|
|
|
|
|
|
|
|
649
|
|
|
|
|
|
|
=over 4 |
650
|
|
|
|
|
|
|
|
651
|
|
|
|
|
|
|
=cut |
652
|
|
|
|
|
|
|
|
653
|
|
|
|
|
|
|
|
654
|
|
|
|
|
|
|
############################################################# |
655
|
|
|
|
|
|
|
sub visitor_patch { |
656
|
|
|
|
|
|
|
# Visitor which create patch for dom creation |
657
|
|
|
|
|
|
|
############################################################# |
658
|
111
|
|
|
111
|
0
|
113
|
my $node = shift(); |
659
|
111
|
|
|
|
|
96
|
my $depth = shift; |
660
|
111
|
|
|
|
|
89
|
my $open = shift; |
661
|
111
|
|
|
|
|
169
|
my @cur_path = @_; |
662
|
|
|
|
|
|
|
|
663
|
111
|
|
|
|
|
148
|
my $path = join('',@cur_path); |
664
|
|
|
|
|
|
|
|
665
|
|
|
|
|
|
|
# warn $depth.($open==1?' > ':(defined($open)?' < ':' ')).join('',@cur_path).' : '.ref($node); |
666
|
|
|
|
|
|
|
|
667
|
111
|
|
|
|
|
107
|
my $ref = ref($node); |
668
|
111
|
100
|
|
|
|
135
|
if ($ref) { |
669
|
91
|
100
|
|
|
|
133
|
if (!defined $open ) { |
|
|
100
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
670
|
49
|
100
|
|
|
|
87
|
($_[-1] eq '$loop') and return 'loop('.$path.','.$path.')='; |
671
|
45
|
100
|
|
|
|
66
|
($ref eq 'CODE') and return 'add('.$path.','.$path.')=sub{}'; |
672
|
|
|
|
|
|
|
#($ref eq 'REF') and return 'add('.$path.','.$path.')={}'; |
673
|
43
|
50
|
|
|
|
58
|
($ref eq 'GLOB') and return 'new '.$_[-1].'()'; |
674
|
|
|
|
|
|
|
} |
675
|
|
|
|
|
|
|
elsif ($open ==1 ) { |
676
|
21
|
100
|
|
|
|
62
|
($ref eq 'ARRAY') and return 'add('.$path.','.$path.')=[]'; |
677
|
11
|
100
|
|
|
|
45
|
($ref eq 'HASH') and return 'add('.$path.','.$path.')={}'; |
678
|
2
|
|
|
|
|
4
|
return ; |
679
|
|
|
|
|
|
|
} |
680
|
|
|
|
|
|
|
elsif ($open ==0 ) { |
681
|
|
|
|
|
|
|
#($ref eq 'ARRAY') and return ']'; |
682
|
|
|
|
|
|
|
#($ref eq 'HASH') and return '}'; |
683
|
21
|
|
|
|
|
35
|
return; |
684
|
|
|
|
|
|
|
} |
685
|
|
|
|
|
|
|
|
686
|
|
|
|
|
|
|
} |
687
|
|
|
|
|
|
|
|
688
|
63
|
100
|
66
|
|
|
185
|
defined($node) and $node = "'$node'" or $node = 'undef'; |
689
|
|
|
|
|
|
|
|
690
|
|
|
|
|
|
|
|
691
|
63
|
|
|
|
|
61
|
pop(@cur_path); |
692
|
63
|
|
|
|
|
63
|
pop(@cur_path); |
693
|
63
|
|
|
|
|
74
|
$path = join('',@cur_path); |
694
|
63
|
|
|
|
|
55
|
pop(@cur_path); |
695
|
63
|
|
|
|
|
61
|
pop(@cur_path); |
696
|
|
|
|
|
|
|
|
697
|
63
|
100
|
|
|
|
150
|
($_[-2] eq '=') and return 'add('.join('',@cur_path).','.$path.')='.$node; |
698
|
|
|
|
|
|
|
|
699
|
|
|
|
|
|
|
|
700
|
43
|
|
|
|
|
73
|
return; |
701
|
|
|
|
|
|
|
|
702
|
|
|
|
|
|
|
# get the source code => How ? |
703
|
|
|
|
|
|
|
# (ref($node) eq 'CODE') and return $dump.'CODE';#(&$node()); |
704
|
|
|
|
|
|
|
# return $dump.ref($node); |
705
|
|
|
|
|
|
|
|
706
|
|
|
|
|
|
|
} |
707
|
|
|
|
|
|
|
|
708
|
|
|
|
|
|
|
|
709
|
|
|
|
|
|
|
############################################################# |
710
|
|
|
|
|
|
|
sub visitor_perl_dump { |
711
|
|
|
|
|
|
|
# Visitor to dump Perl structure |
712
|
|
|
|
|
|
|
############################################################# |
713
|
23830
|
|
|
23830
|
0
|
24709
|
my $node = shift(); |
714
|
23830
|
|
|
|
|
21325
|
my $depth = shift; |
715
|
23830
|
|
|
|
|
19962
|
my $open = shift; |
716
|
23830
|
|
|
|
|
36547
|
my @cur_path = @_; |
717
|
|
|
|
|
|
|
|
718
|
23830
|
|
|
|
|
21518
|
my $path = @cur_path; |
719
|
|
|
|
|
|
|
|
720
|
23830
|
|
|
|
|
25982
|
my $ref = ref($node); |
721
|
|
|
|
|
|
|
|
722
|
23830
|
|
|
|
|
35828
|
my ($realpack, $realtype, $id) = |
723
|
|
|
|
|
|
|
(overload::StrVal($node) =~ /^(?:(.*)\=)?([^=]*)\(([^\(]*)\)$/); |
724
|
|
|
|
|
|
|
|
725
|
|
|
|
|
|
|
# warn $depth.($open==1?' > ':(defined($open)?' < ':' ')).join('',@cur_path).' : '.ref($node)." ($realpack/$realtype/$id)"; |
726
|
|
|
|
|
|
|
|
727
|
|
|
|
|
|
|
|
728
|
23830
|
100
|
|
|
|
124885
|
if ($ref) { |
729
|
15830
|
100
|
|
|
|
23648
|
if (!defined $open ) { |
|
|
100
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
730
|
9936
|
50
|
66
|
|
|
15319
|
($realpack and $realtype and $id) and $ref = $realtype; |
|
|
|
66
|
|
|
|
|
731
|
|
|
|
|
|
|
|
732
|
9936
|
100
|
100
|
|
|
25347
|
($ref eq 'REF' or $ref eq 'SCALAR') and return '\\'; |
733
|
|
|
|
|
|
|
|
734
|
9370
|
100
|
|
|
|
11241
|
($ref eq 'CODE') and return 'sub { "DUMMY" }'; |
735
|
|
|
|
|
|
|
|
736
|
9306
|
100
|
|
|
|
12849
|
if ($_[-1] eq '$loop') { |
737
|
56
|
|
|
|
|
129
|
return '$t1'; |
738
|
|
|
|
|
|
|
} |
739
|
|
|
|
|
|
|
|
740
|
9250
|
100
|
66
|
|
|
16172
|
if ($ref eq 'HASH' and $_[-2] eq '%') { |
741
|
4584
|
|
|
|
|
14126
|
my @keys = sort {$a cmp $b} keys(%$node); |
|
185918
|
|
|
|
|
152996
|
|
742
|
4584
|
|
|
|
|
7396
|
my $is_first = ($_[-1] eq $keys[0]); |
743
|
|
|
|
|
|
|
|
744
|
4584
|
100
|
|
|
|
8322
|
$is_first |
745
|
|
|
|
|
|
|
and |
746
|
|
|
|
|
|
|
return '\''.$_[-1].'\'=>'; |
747
|
|
|
|
|
|
|
|
748
|
3289
|
|
|
|
|
10888
|
return ',\''.$_[-1].'\'=>'; |
749
|
|
|
|
|
|
|
} |
750
|
4666
|
100
|
66
|
|
|
17915
|
($ref eq 'ARRAY' and $_[-2] eq '@' and $_[-1] != 0) and return ','; |
|
|
|
100
|
|
|
|
|
751
|
1380
|
|
|
|
|
3045
|
return; |
752
|
|
|
|
|
|
|
} |
753
|
|
|
|
|
|
|
elsif ($open ==1 ) { |
754
|
2947
|
100
|
|
|
|
5480
|
($ref eq 'ARRAY') and return '['; |
755
|
1403
|
100
|
|
|
|
3787
|
($ref eq 'HASH') and return '{'; |
756
|
|
|
|
|
|
|
|
757
|
37
|
50
|
|
|
|
89
|
($realtype eq 'ARRAY') and return 'bless(['; |
758
|
37
|
50
|
|
|
|
132
|
($realtype eq 'HASH') and return 'bless({'; |
759
|
|
|
|
|
|
|
} |
760
|
|
|
|
|
|
|
elsif ($open ==0 ) { |
761
|
2947
|
100
|
|
|
|
6145
|
($ref eq 'ARRAY') and return ']'; |
762
|
1403
|
100
|
|
|
|
3642
|
($ref eq 'HASH') and return '}'; |
763
|
|
|
|
|
|
|
|
764
|
37
|
50
|
|
|
|
55
|
($realtype eq 'ARRAY') and return "] , '$ref')"; |
765
|
37
|
50
|
|
|
|
160
|
($realtype eq 'HASH') and return "} , '$ref')"; |
766
|
|
|
|
|
|
|
|
767
|
|
|
|
|
|
|
} |
768
|
|
|
|
|
|
|
} |
769
|
|
|
|
|
|
|
|
770
|
8000
|
100
|
|
|
|
10713
|
(defined($node)) or return 'undef'; |
771
|
|
|
|
|
|
|
|
772
|
7825
|
50
|
|
|
|
10852
|
if ($_[-2] eq '=') { |
773
|
7825
|
|
|
|
|
9757
|
$node=~s/\'/\\\'/g; |
774
|
7825
|
100
|
|
|
|
23104
|
($node=~/^\d+$/) and return $node; |
775
|
3025
|
|
|
|
|
8585
|
return '\''.$node.'\''; |
776
|
|
|
|
|
|
|
} |
777
|
|
|
|
|
|
|
|
778
|
0
|
|
|
|
|
0
|
return; |
779
|
|
|
|
|
|
|
|
780
|
|
|
|
|
|
|
} |
781
|
|
|
|
|
|
|
|
782
|
|
|
|
|
|
|
|
783
|
|
|
|
|
|
|
############################################################# |
784
|
|
|
|
|
|
|
sub visitor_dump { |
785
|
|
|
|
|
|
|
# Visitor to dump Perl structure |
786
|
|
|
|
|
|
|
############################################################# |
787
|
40
|
|
|
40
|
0
|
43
|
my $node = shift(); |
788
|
40
|
|
|
|
|
80
|
my $depth = shift; |
789
|
40
|
|
|
|
|
36
|
my $open = shift; |
790
|
40
|
|
|
|
|
62
|
my @cur_path = @_; |
791
|
|
|
|
|
|
|
|
792
|
40
|
|
|
|
|
65
|
my $path = join('',@cur_path); |
793
|
|
|
|
|
|
|
|
794
|
40
|
|
|
|
|
68
|
my ($realpack, $realtype, $id) = |
795
|
|
|
|
|
|
|
(overload::StrVal($node) =~ /^(?:(.*)\=)?([^=]*)\(([^\(]*)\)$/); |
796
|
|
|
|
|
|
|
|
797
|
40
|
100
|
|
|
|
329
|
return $depth.($open==1?' > ':(defined($open)?' < ':' ')).join('',@cur_path).' : '.ref($node); #." ( $realpack/$realtype/$id)"; |
|
|
100
|
|
|
|
|
|
798
|
|
|
|
|
|
|
} |
799
|
|
|
|
|
|
|
|
800
|
|
|
|
|
|
|
|
801
|
|
|
|
|
|
|
############################################################# |
802
|
|
|
|
|
|
|
# IDEA : sub visitor_search { |
803
|
|
|
|
|
|
|
# IDEA : searching visitor to replace search |
804
|
|
|
|
|
|
|
############################################################# |
805
|
|
|
|
|
|
|
# my $node = shift(); |
806
|
|
|
|
|
|
|
# my $depth = shift; |
807
|
|
|
|
|
|
|
# my $open = shift; |
808
|
|
|
|
|
|
|
# my @cur_path = @_; |
809
|
|
|
|
|
|
|
|
810
|
|
|
|
|
|
|
# if (defined $matchPath->($pattern, @cur_path)) { |
811
|
|
|
|
|
|
|
# defined($nb_occ) and (--$nb_occ<1) and die 'STOP'; |
812
|
|
|
|
|
|
|
|
813
|
|
|
|
|
|
|
# return $node; |
814
|
|
|
|
|
|
|
# } |
815
|
|
|
|
|
|
|
#} |
816
|
|
|
|
|
|
|
|
817
|
|
|
|
|
|
|
|
818
|
|
|
|
|
|
|
############################################################################## |
819
|
|
|
|
|
|
|
#{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{ |
820
|
|
|
|
|
|
|
sub travel($;@) { |
821
|
|
|
|
|
|
|
#{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{ |
822
|
|
|
|
|
|
|
|
823
|
11782
|
|
|
11782
|
1
|
12858
|
my $where=shift(); |
824
|
11782
|
|
100
|
|
|
16526
|
my $visitor = shift() || \&visitor_patch; |
825
|
11782
|
|
100
|
|
|
15757
|
my $depth = shift()||0; |
826
|
11782
|
|
|
|
|
17506
|
my @path = @_; |
827
|
|
|
|
|
|
|
|
828
|
|
|
|
|
|
|
|
829
|
|
|
|
|
|
|
=over 4 |
830
|
|
|
|
|
|
|
|
831
|
|
|
|
|
|
|
=item I( [,]) |
832
|
|
|
|
|
|
|
|
833
|
|
|
|
|
|
|
travel make the visitor function to travel through each node of the |
834
|
|
|
|
|
|
|
|
835
|
|
|
|
|
|
|
complexe perl data structure to travel into |
836
|
|
|
|
|
|
|
() |
837
|
|
|
|
|
|
|
|
838
|
|
|
|
|
|
|
Return a list path where the argument match with the |
839
|
|
|
|
|
|
|
corresponding node in the tree data type |
840
|
|
|
|
|
|
|
|
841
|
|
|
|
|
|
|
I |
842
|
|
|
|
|
|
|
|
843
|
|
|
|
|
|
|
travel( {ky=>['l','r','t',124],r=>2} |
844
|
|
|
|
|
|
|
|
845
|
|
|
|
|
|
|
returns ( [ '%', 'ky', '@' , 3 , '=' , 124 ] ) |
846
|
|
|
|
|
|
|
|
847
|
|
|
|
|
|
|
=cut |
848
|
|
|
|
|
|
|
|
849
|
|
|
|
|
|
|
#}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}} |
850
|
11782
|
100
|
|
|
|
14939
|
if (@path) { |
851
|
9942
|
|
|
|
|
15147
|
debug "travel( dom=",@path, ' is ',ref($where),")"; |
852
|
|
|
|
|
|
|
#debug "return ".($arr && ' ARRAY ' || 'SCALAR'); |
853
|
|
|
|
|
|
|
} |
854
|
|
|
|
|
|
|
else { |
855
|
1840
|
|
|
|
|
3013
|
%loop_ref=(); |
856
|
|
|
|
|
|
|
} |
857
|
|
|
|
|
|
|
|
858
|
|
|
|
|
|
|
# |
859
|
|
|
|
|
|
|
|
860
|
|
|
|
|
|
|
sub __appendVisitorResult { |
861
|
33923
|
|
|
33923
|
|
36738
|
my $is_array = shift(); |
862
|
33923
|
|
|
|
|
27913
|
my @list; |
863
|
|
|
|
|
|
|
|
864
|
33923
|
|
|
|
|
37217
|
foreach (@_) { |
865
|
321940
|
50
|
|
|
|
337626
|
if (defined $_) { |
866
|
321940
|
50
|
|
|
|
330958
|
$is_array or return $_; |
867
|
321940
|
|
|
|
|
330182
|
push(@list, $_); |
868
|
|
|
|
|
|
|
} |
869
|
|
|
|
|
|
|
} |
870
|
33923
|
|
|
|
|
102228
|
return @list; |
871
|
|
|
|
|
|
|
} |
872
|
|
|
|
|
|
|
|
873
|
11782
|
|
|
|
|
18434
|
my ($k,$res); |
874
|
11782
|
|
|
|
|
0
|
my @res; |
875
|
|
|
|
|
|
|
|
876
|
|
|
|
|
|
|
#}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}} |
877
|
|
|
|
|
|
|
|
878
|
11782
|
|
|
|
|
13573
|
my $ref_type = ref $where; |
879
|
|
|
|
|
|
|
|
880
|
|
|
|
|
|
|
|
881
|
|
|
|
|
|
|
######################################## !!!!! Modules type resolution |
882
|
|
|
|
|
|
|
# if (index($ref_type,'::')!=-1) { |
883
|
11782
|
|
|
|
|
19435
|
my ($realpack, $realtype, $id) = |
884
|
|
|
|
|
|
|
(overload::StrVal(scalar($where)) =~ /^(?:(.*)\=)?([^=]*)\(([^\(]*)\)$/); |
885
|
|
|
|
|
|
|
|
886
|
11782
|
100
|
66
|
|
|
57170
|
if ($realpack and $realtype and $id) { |
|
|
|
100
|
|
|
|
|
887
|
40
|
|
|
|
|
58
|
push @path,'|',$ref_type; |
888
|
|
|
|
|
|
|
|
889
|
40
|
|
|
|
|
48
|
my $y = undef; |
890
|
40
|
50
|
|
|
|
101
|
if ($realtype eq 'SCALAR') { |
|
|
50
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
891
|
0
|
|
|
|
|
0
|
$y=$$where; |
892
|
|
|
|
|
|
|
} |
893
|
|
|
|
|
|
|
elsif ($realtype eq 'HASH') { |
894
|
40
|
|
|
|
|
64
|
$y=\%$where |
895
|
|
|
|
|
|
|
} |
896
|
|
|
|
|
|
|
elsif ($realtype eq 'ARRAY') { |
897
|
0
|
|
|
|
|
0
|
$y=\@$where |
898
|
|
|
|
|
|
|
} |
899
|
|
|
|
|
|
|
else { |
900
|
|
|
|
|
|
|
#die $realtype.' : '.$where; |
901
|
|
|
|
|
|
|
} |
902
|
|
|
|
|
|
|
|
903
|
|
|
|
|
|
|
#debug ref($y)." = $realpack -> real $realtype, $id"; |
904
|
|
|
|
|
|
|
|
905
|
40
|
|
|
|
|
68
|
$where=$y; |
906
|
40
|
|
|
|
|
55
|
$ref_type = $realtype; |
907
|
|
|
|
|
|
|
} |
908
|
|
|
|
|
|
|
|
909
|
|
|
|
|
|
|
|
910
|
|
|
|
|
|
|
######################################## !!!!! Loop detection |
911
|
11782
|
|
|
|
|
10698
|
my @p; |
912
|
|
|
|
|
|
|
|
913
|
11782
|
100
|
|
|
|
14335
|
if (loop_det($where)) { |
914
|
|
|
|
|
|
|
|
915
|
60
|
|
|
|
|
106
|
return __appendVisitorResult(wantarray(), @res, |
916
|
|
|
|
|
|
|
&$visitor($where, $depth, undef , (@path, '$loop'))); |
917
|
|
|
|
|
|
|
|
918
|
|
|
|
|
|
|
} |
919
|
|
|
|
|
|
|
else { |
920
|
|
|
|
|
|
|
######################################## !!!!! SCALAR TRAVEL |
921
|
11722
|
100
|
100
|
|
|
17851
|
if (!$ref_type) { |
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
922
|
|
|
|
|
|
|
|
923
|
8029
|
|
|
|
|
12812
|
return __appendVisitorResult(wantarray(), |
924
|
|
|
|
|
|
|
@res, |
925
|
|
|
|
|
|
|
&$visitor($where, $depth , undef, (@path, '=', $where))); |
926
|
|
|
|
|
|
|
|
927
|
|
|
|
|
|
|
} |
928
|
|
|
|
|
|
|
######################################## !!!!! HASH TRAVEL |
929
|
|
|
|
|
|
|
elsif ($ref_type eq 'HASH') |
930
|
|
|
|
|
|
|
{ |
931
|
|
|
|
|
|
|
|
932
|
1418
|
|
|
|
|
2329
|
@res = __appendVisitorResult(wantarray(), |
933
|
|
|
|
|
|
|
@res, |
934
|
|
|
|
|
|
|
&$visitor($where, $depth, 1, @path)); |
935
|
|
|
|
|
|
|
|
936
|
1418
|
|
|
|
|
1473
|
my $k; |
937
|
1418
|
|
|
|
|
1430
|
foreach $k (sort {$a cmp $b} keys(%{ $where })) { |
|
8953
|
|
|
|
|
8770
|
|
|
1418
|
|
|
|
|
4326
|
|
938
|
4605
|
|
|
|
|
7575
|
@p = (@path, '%', $k); |
939
|
|
|
|
|
|
|
|
940
|
4605
|
|
|
|
|
6876
|
@res = __appendVisitorResult(wantarray(), |
941
|
|
|
|
|
|
|
@res, |
942
|
|
|
|
|
|
|
&$visitor($where, $depth, undef, @p) |
943
|
|
|
|
|
|
|
); |
944
|
|
|
|
|
|
|
|
945
|
|
|
|
|
|
|
@res = __appendVisitorResult( |
946
|
|
|
|
|
|
|
wantarray(), |
947
|
|
|
|
|
|
|
@res, |
948
|
4605
|
|
|
|
|
10663
|
travel($where->{$k},$visitor,$depth+1, @p) |
949
|
|
|
|
|
|
|
); |
950
|
|
|
|
|
|
|
} |
951
|
|
|
|
|
|
|
|
952
|
1418
|
|
|
|
|
2650
|
return __appendVisitorResult( wantarray(), |
953
|
|
|
|
|
|
|
@res, |
954
|
|
|
|
|
|
|
&$visitor($where, $depth, 0, @path) |
955
|
|
|
|
|
|
|
); |
956
|
|
|
|
|
|
|
|
957
|
|
|
|
|
|
|
} |
958
|
|
|
|
|
|
|
######################################## !!!!! ARRAY TRAVEL |
959
|
|
|
|
|
|
|
elsif ($ref_type eq 'ARRAY') |
960
|
|
|
|
|
|
|
{ |
961
|
1557
|
|
|
|
|
2174
|
$res = &$visitor($where, $depth, 1, @path); |
962
|
|
|
|
|
|
|
|
963
|
1557
|
|
|
|
|
2451
|
@res = __appendVisitorResult( wantarray(), @res, $res ); |
964
|
|
|
|
|
|
|
|
965
|
1557
|
|
|
|
|
1647
|
for my $i (0..$#{ $where }) { |
|
1557
|
|
|
|
|
3165
|
|
966
|
|
|
|
|
|
|
#print "\narray $i (".$where->[$i].','.join('.',@p).")\n" if (join('_',@p)=~ /\@_1_\%_g_/); |
967
|
4692
|
|
|
|
|
7274
|
@p = (@path, '@', $i); |
968
|
|
|
|
|
|
|
|
969
|
4692
|
|
|
|
|
7140
|
@res = __appendVisitorResult(wantarray(), |
970
|
|
|
|
|
|
|
@res, |
971
|
|
|
|
|
|
|
&$visitor($where, $depth, undef, @p) |
972
|
|
|
|
|
|
|
); |
973
|
|
|
|
|
|
|
|
974
|
4692
|
|
|
|
|
9739
|
@res = __appendVisitorResult( |
975
|
|
|
|
|
|
|
wantarray(), |
976
|
|
|
|
|
|
|
@res, |
977
|
|
|
|
|
|
|
travel($where->[$i],$visitor,$depth+1, @p) |
978
|
|
|
|
|
|
|
); |
979
|
|
|
|
|
|
|
|
980
|
|
|
|
|
|
|
} |
981
|
|
|
|
|
|
|
|
982
|
1557
|
|
|
|
|
2815
|
return __appendVisitorResult( wantarray(), |
983
|
|
|
|
|
|
|
@res, |
984
|
|
|
|
|
|
|
&$visitor($where, $depth, 0, @path) |
985
|
|
|
|
|
|
|
); |
986
|
|
|
|
|
|
|
|
987
|
|
|
|
|
|
|
} |
988
|
|
|
|
|
|
|
######################################## !!!!! REFERENCE TRAVEL |
989
|
|
|
|
|
|
|
elsif ($ref_type eq 'REF' or $ref_type eq 'SCALAR') |
990
|
|
|
|
|
|
|
{ |
991
|
572
|
|
|
|
|
1048
|
@p = (@path, "\$"); |
992
|
|
|
|
|
|
|
|
993
|
572
|
|
|
|
|
1012
|
@res = __appendVisitorResult( wantarray(), |
994
|
|
|
|
|
|
|
@res, |
995
|
|
|
|
|
|
|
&$visitor($where, $depth, undef, @p ) |
996
|
|
|
|
|
|
|
); |
997
|
|
|
|
|
|
|
|
998
|
|
|
|
|
|
|
return __appendVisitorResult( wantarray(), |
999
|
|
|
|
|
|
|
@res, |
1000
|
572
|
|
|
|
|
688
|
travel( ${ $where }, $visitor, $depth+1, @p ) |
|
572
|
|
|
|
|
1053
|
|
1001
|
|
|
|
|
|
|
); |
1002
|
|
|
|
|
|
|
} |
1003
|
|
|
|
|
|
|
else { # others types |
1004
|
|
|
|
|
|
|
######################################## !!!!! CODE TRAVEL |
1005
|
146
|
100
|
|
|
|
281
|
if ($ref_type eq 'CODE') { |
|
|
50
|
|
|
|
|
|
1006
|
66
|
|
|
|
|
172
|
@p = (@path, '&'); |
1007
|
|
|
|
|
|
|
} |
1008
|
|
|
|
|
|
|
######################################## !!!!! GLOB TRAVEL |
1009
|
|
|
|
|
|
|
elsif ($ref_type eq 'GLOB') { |
1010
|
80
|
|
|
|
|
148
|
my $name=$$where; |
1011
|
80
|
|
|
|
|
163
|
$name=~s/b^\*//; |
1012
|
80
|
|
|
|
|
223
|
@p = (@path, '*', $name); |
1013
|
|
|
|
|
|
|
} |
1014
|
|
|
|
|
|
|
######################################## !!!!! MODULE TRAVEL |
1015
|
|
|
|
|
|
|
else { |
1016
|
|
|
|
|
|
|
#die $ref_type; |
1017
|
|
|
|
|
|
|
} |
1018
|
|
|
|
|
|
|
|
1019
|
|
|
|
|
|
|
######################################## !!!!! GLOB TRAVEL |
1020
|
|
|
|
|
|
|
# cf IO::Handle or Symbol::gensym() |
1021
|
|
|
|
|
|
|
|
1022
|
146
|
100
|
|
|
|
263
|
if ($p[-2] eq '*') { # GLOB |
1023
|
80
|
|
|
|
|
104
|
for $k (qw(SCALAR ARRAY HASH)) { |
1024
|
171
|
|
|
|
|
206
|
my $gval = *$where{$k}; |
1025
|
171
|
100
|
|
|
|
219
|
defined($gval) or next; |
1026
|
130
|
100
|
100
|
|
|
297
|
next if ($k eq "SCALAR" && ! defined $$gval); # always there |
1027
|
|
|
|
|
|
|
|
1028
|
73
|
|
|
|
|
133
|
return __appendVisitorResult( wantarray(), |
1029
|
|
|
|
|
|
|
@res, |
1030
|
|
|
|
|
|
|
travel($gval, $visitor, $depth+1, undef, @p) |
1031
|
|
|
|
|
|
|
); |
1032
|
|
|
|
|
|
|
} |
1033
|
|
|
|
|
|
|
} |
1034
|
|
|
|
|
|
|
|
1035
|
73
|
|
|
|
|
140
|
return __appendVisitorResult( |
1036
|
|
|
|
|
|
|
wantarray(), |
1037
|
|
|
|
|
|
|
@res, |
1038
|
|
|
|
|
|
|
&$visitor($where, $depth, undef, @p ) |
1039
|
|
|
|
|
|
|
); |
1040
|
|
|
|
|
|
|
} |
1041
|
|
|
|
|
|
|
} |
1042
|
|
|
|
|
|
|
|
1043
|
0
|
|
|
|
|
0
|
return (); |
1044
|
|
|
|
|
|
|
} |
1045
|
|
|
|
|
|
|
|
1046
|
|
|
|
|
|
|
|
1047
|
|
|
|
|
|
|
|
1048
|
|
|
|
|
|
|
my %circular_ref; |
1049
|
|
|
|
|
|
|
############################################################################## |
1050
|
|
|
|
|
|
|
#{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{ |
1051
|
|
|
|
|
|
|
sub search($$;$@) { |
1052
|
|
|
|
|
|
|
#{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{ |
1053
|
2759
|
|
|
2759
|
1
|
3405
|
my $where = shift(); |
1054
|
2759
|
|
|
|
|
2629
|
my $pattern = shift(); |
1055
|
2759
|
|
|
|
|
2266
|
my $nb_occ = shift(); |
1056
|
2759
|
|
|
|
|
3842
|
my @path=@_; |
1057
|
|
|
|
|
|
|
|
1058
|
|
|
|
|
|
|
# warn "search for #$nb_occ (",join('',@{$pattern}),")"; |
1059
|
|
|
|
|
|
|
|
1060
|
|
|
|
|
|
|
|
1061
|
|
|
|
|
|
|
=item I(, [,]) |
1062
|
|
|
|
|
|
|
|
1063
|
|
|
|
|
|
|
search the into |
1064
|
|
|
|
|
|
|
|
1065
|
|
|
|
|
|
|
is a complexe perl data structure to search into |
1066
|
|
|
|
|
|
|
is an array of type description to match |
1067
|
|
|
|
|
|
|
optional argument to limit the number of results |
1068
|
|
|
|
|
|
|
if undef all results are returned |
1069
|
|
|
|
|
|
|
if 1 first one is returned |
1070
|
|
|
|
|
|
|
|
1071
|
|
|
|
|
|
|
Return a list path where the argument match with the |
1072
|
|
|
|
|
|
|
corresponding node in the tree data type |
1073
|
|
|
|
|
|
|
|
1074
|
|
|
|
|
|
|
EX: |
1075
|
|
|
|
|
|
|
search( {ky=>['l','r','t',124],r=>2} |
1076
|
|
|
|
|
|
|
['?@','=',124]) |
1077
|
|
|
|
|
|
|
|
1078
|
|
|
|
|
|
|
Returns ( [ '%', 'ky', '@' , 3 , '=' , 124 ] ) |
1079
|
|
|
|
|
|
|
|
1080
|
|
|
|
|
|
|
|
1081
|
|
|
|
|
|
|
search( [5,2,3,{r=>3,h=>5},4,\{r=>4},{r=>5}], |
1082
|
|
|
|
|
|
|
['%','r'], 2 ) |
1083
|
|
|
|
|
|
|
|
1084
|
|
|
|
|
|
|
Returns (['@',3,'%','r'],['@',5,'$','%','r']) |
1085
|
|
|
|
|
|
|
|
1086
|
|
|
|
|
|
|
|
1087
|
|
|
|
|
|
|
search( [5,2,3,{r=>3},4,\3], |
1088
|
|
|
|
|
|
|
['?$@%','=',sub {$_ == 3 }], |
1089
|
|
|
|
|
|
|
2; |
1090
|
|
|
|
|
|
|
|
1091
|
|
|
|
|
|
|
Returns (['@',2,'=',3], ['@',3,'%','r','=',3]) |
1092
|
|
|
|
|
|
|
|
1093
|
|
|
|
|
|
|
=cut |
1094
|
|
|
|
|
|
|
|
1095
|
|
|
|
|
|
|
#}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}} |
1096
|
|
|
|
|
|
|
# warn "search($where / ref=".ref($where).','.$nb_occ.' ,'.join('',@path).")"; |
1097
|
|
|
|
|
|
|
|
1098
|
2759
|
100
|
|
|
|
3743
|
@path or %loop_ref=(); |
1099
|
|
|
|
|
|
|
|
1100
|
2759
|
50
|
66
|
|
|
6406
|
(defined($nb_occ) and ($nb_occ<1)) and return (); |
1101
|
|
|
|
|
|
|
|
1102
|
2759
|
|
|
|
|
2975
|
my $ref_type = ref $where; |
1103
|
|
|
|
|
|
|
|
1104
|
2759
|
|
|
|
|
2256
|
my @found; |
1105
|
2759
|
|
|
|
|
2473
|
my $next = undef; |
1106
|
2759
|
|
|
|
|
2185
|
my @p; |
1107
|
|
|
|
|
|
|
|
1108
|
|
|
|
|
|
|
######################################## !!!!! Modules type resolution |
1109
|
2759
|
100
|
|
|
|
2999
|
if ($ref_type) { |
1110
|
|
|
|
|
|
|
|
1111
|
|
|
|
|
|
|
#if (index($where,'::')!=-1) { ## !!!!! MODULE SEARCH |
1112
|
|
|
|
|
|
|
|
1113
|
676
|
|
|
|
|
1223
|
my ($realpack, $realtype, $id) = |
1114
|
|
|
|
|
|
|
(overload::StrVal($where) =~ /^(?:(.*)\=)?([^=]*)\(([^\(]*)\)$/); |
1115
|
|
|
|
|
|
|
|
1116
|
676
|
50
|
66
|
|
|
5418
|
if ($realpack and $realtype and $id) { |
|
|
|
66
|
|
|
|
|
1117
|
11
|
|
|
|
|
20
|
push @path, ('|', $ref_type); |
1118
|
|
|
|
|
|
|
|
1119
|
11
|
|
|
|
|
19
|
$ref_type = $realtype; |
1120
|
|
|
|
|
|
|
|
1121
|
|
|
|
|
|
|
#warn "$ref_type -> ($realpack, $realtype, $id )"; |
1122
|
|
|
|
|
|
|
} |
1123
|
|
|
|
|
|
|
|
1124
|
|
|
|
|
|
|
|
1125
|
|
|
|
|
|
|
######################################## !!!!! Loop detection |
1126
|
|
|
|
|
|
|
|
1127
|
676
|
100
|
100
|
|
|
898
|
if (loop_det($where)) { |
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
1128
|
2
|
|
|
|
|
6
|
@p = (@path, '$loop'); |
1129
|
|
|
|
|
|
|
} |
1130
|
|
|
|
|
|
|
######################################## HASH Search |
1131
|
|
|
|
|
|
|
elsif ($ref_type eq 'HASH') { |
1132
|
272
|
|
|
|
|
269
|
my $k; |
1133
|
272
|
|
|
|
|
289
|
foreach $k (sort {$a cmp $b} keys(%{ $where })) { |
|
3637
|
|
|
|
|
3178
|
|
|
272
|
|
|
|
|
898
|
|
1134
|
1422
|
|
|
|
|
2147
|
@p = (@path, '%', $k); |
1135
|
|
|
|
|
|
|
|
1136
|
1422
|
100
|
|
|
|
1832
|
if (defined $matchPath->($pattern, @p)) { |
1137
|
64
|
|
|
|
|
136
|
push @found,[@p]; |
1138
|
64
|
100
|
66
|
|
|
276
|
defined($nb_occ) and (--$nb_occ<1) and last; |
1139
|
|
|
|
|
|
|
} |
1140
|
|
|
|
|
|
|
else { |
1141
|
1358
|
|
|
|
|
2500
|
my @res = search($where->{$k}, $pattern, $nb_occ, @p); |
1142
|
1358
|
100
|
|
|
|
2161
|
@res and push @found,@res; |
1143
|
|
|
|
|
|
|
} |
1144
|
|
|
|
|
|
|
} |
1145
|
272
|
|
|
|
|
706
|
return @found; |
1146
|
|
|
|
|
|
|
} |
1147
|
|
|
|
|
|
|
######################################## HASH Search |
1148
|
|
|
|
|
|
|
elsif ($ref_type eq 'ARRAY') |
1149
|
|
|
|
|
|
|
{ |
1150
|
263
|
|
|
|
|
277
|
for my $i (0..$#{ $where }) { |
|
263
|
|
|
|
|
606
|
|
1151
|
1170
|
|
|
|
|
1711
|
@p = (@path, '@', $i); |
1152
|
|
|
|
|
|
|
|
1153
|
1170
|
100
|
|
|
|
1481
|
if (defined $matchPath->($pattern, @p)) { |
1154
|
25
|
|
|
|
|
53
|
push @found,[@p]; |
1155
|
25
|
100
|
66
|
|
|
84
|
defined($nb_occ) and (--$nb_occ<1) and last; |
1156
|
|
|
|
|
|
|
} |
1157
|
|
|
|
|
|
|
else { |
1158
|
1145
|
|
|
|
|
1898
|
my @res = search($where->[$i], $pattern, $nb_occ, @p); |
1159
|
1145
|
100
|
|
|
|
1890
|
@res and push @found,@res; |
1160
|
|
|
|
|
|
|
} |
1161
|
|
|
|
|
|
|
} |
1162
|
263
|
|
|
|
|
634
|
return @found; |
1163
|
|
|
|
|
|
|
} |
1164
|
|
|
|
|
|
|
######################################## REF Search |
1165
|
|
|
|
|
|
|
elsif ($ref_type eq 'REF' or $ref_type eq 'SCALAR') { |
1166
|
110
|
|
|
|
|
184
|
@p = (@path, '$'); |
1167
|
110
|
|
|
|
|
103
|
$next = ${ $where }; |
|
110
|
|
|
|
|
142
|
|
1168
|
|
|
|
|
|
|
} |
1169
|
|
|
|
|
|
|
######################################## CODE Search |
1170
|
|
|
|
|
|
|
elsif ($ref_type eq 'CODE') { |
1171
|
15
|
|
|
|
|
36
|
@p = (@path, '&'); |
1172
|
|
|
|
|
|
|
} |
1173
|
|
|
|
|
|
|
######################################## GLOB Search |
1174
|
|
|
|
|
|
|
elsif ($ref_type eq 'GLOB') { |
1175
|
14
|
|
|
|
|
28
|
my $name = $$where; |
1176
|
14
|
|
|
|
|
73
|
$name=~s/^\*//; |
1177
|
14
|
|
|
|
|
31
|
@p = (@path, '*',$name); |
1178
|
14
|
100
|
66
|
|
|
32
|
if (defined *$where{SCALAR} and defined(${*$where{SCALAR}})) { |
|
14
|
100
|
|
|
|
45
|
|
|
|
100
|
|
|
|
|
|
1179
|
4
|
|
|
|
|
7
|
$next = *$where{SCALAR}; |
1180
|
|
|
|
|
|
|
} |
1181
|
|
|
|
|
|
|
elsif (defined *$where{ARRAY}) { |
1182
|
4
|
|
|
|
|
8
|
$next = *$where{ARRAY}; |
1183
|
|
|
|
|
|
|
} |
1184
|
|
|
|
|
|
|
elsif (defined *$where{HASH}) { |
1185
|
4
|
|
|
|
|
8
|
$next = *$where{HASH}; |
1186
|
|
|
|
|
|
|
} |
1187
|
|
|
|
|
|
|
} |
1188
|
|
|
|
|
|
|
} |
1189
|
|
|
|
|
|
|
###################################### |
1190
|
|
|
|
|
|
|
else { ## !!!!! SCALAR Search |
1191
|
2083
|
|
|
|
|
2939
|
@p = (@path, '=', $where); |
1192
|
|
|
|
|
|
|
} |
1193
|
|
|
|
|
|
|
###################################### |
1194
|
|
|
|
|
|
|
|
1195
|
2224
|
100
|
|
|
|
2659
|
if (defined $matchPath->($pattern, @p)) { |
1196
|
136
|
|
|
|
|
310
|
push @found,[@p]; |
1197
|
136
|
100
|
|
|
|
221
|
defined($nb_occ) and --$nb_occ; |
1198
|
|
|
|
|
|
|
} |
1199
|
|
|
|
|
|
|
|
1200
|
2224
|
100
|
|
|
|
2849
|
if ((defined($next))) { |
1201
|
114
|
|
|
|
|
237
|
my @res = search($next, $pattern, $nb_occ, @p); |
1202
|
|
|
|
|
|
|
|
1203
|
114
|
100
|
|
|
|
178
|
@res and push @found,@res; |
1204
|
|
|
|
|
|
|
} |
1205
|
|
|
|
|
|
|
|
1206
|
2224
|
|
|
|
|
3427
|
return @found; |
1207
|
|
|
|
|
|
|
} |
1208
|
|
|
|
|
|
|
|
1209
|
|
|
|
|
|
|
|
1210
|
|
|
|
|
|
|
############################################################################## |
1211
|
|
|
|
|
|
|
#{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{ |
1212
|
|
|
|
|
|
|
sub path($$;$) { |
1213
|
|
|
|
|
|
|
#{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{ |
1214
|
108
|
|
|
108
|
1
|
208
|
my $dom = shift(); |
1215
|
108
|
|
|
|
|
148
|
my @paths = @{shift()}; |
|
108
|
|
|
|
|
255
|
|
1216
|
108
|
100
|
|
|
|
334
|
my $father_nb = shift() or 0; |
1217
|
|
|
|
|
|
|
|
1218
|
|
|
|
|
|
|
|
1219
|
|
|
|
|
|
|
=item I(, [,]) |
1220
|
|
|
|
|
|
|
|
1221
|
|
|
|
|
|
|
gives a list of nodes pointed by |
1222
|
|
|
|
|
|
|
is the complex perl data structure |
1223
|
|
|
|
|
|
|
is the array reference of paths |
1224
|
|
|
|
|
|
|
is the depth level to return from tree |
1225
|
|
|
|
|
|
|
start counting from the top |
1226
|
|
|
|
|
|
|
- start counting from the leaf |
1227
|
|
|
|
|
|
|
0 return the leaf or check the leaf with '=' or '&' types): |
1228
|
|
|
|
|
|
|
* if code give the return of execution |
1229
|
|
|
|
|
|
|
* scalar will check the value |
1230
|
|
|
|
|
|
|
|
1231
|
|
|
|
|
|
|
Return a list of nodes reference to the |
1232
|
|
|
|
|
|
|
|
1233
|
|
|
|
|
|
|
EX: |
1234
|
|
|
|
|
|
|
|
1235
|
|
|
|
|
|
|
$eq_3 = path([5,{a=>3,b=>sub {return 'test'}}], |
1236
|
|
|
|
|
|
|
['@1%a']) |
1237
|
|
|
|
|
|
|
|
1238
|
|
|
|
|
|
|
$eq_3 = path([5,{a=>3,b=>sub {return 'test'}}], |
1239
|
|
|
|
|
|
|
'@1%a','@1%b') |
1240
|
|
|
|
|
|
|
|
1241
|
|
|
|
|
|
|
|
1242
|
|
|
|
|
|
|
@nodes = path([5,{a=>3,b=>sub {return 'test'}}], |
1243
|
|
|
|
|
|
|
['@1%b&'], # or [['@',1,'%','b','&']] |
1244
|
|
|
|
|
|
|
|
1245
|
|
|
|
|
|
|
0 # return ('test') |
1246
|
|
|
|
|
|
|
# -1 or 2 return ( sub { "DUMMY" } ) |
1247
|
|
|
|
|
|
|
# -2 or 1 get the hash table |
1248
|
|
|
|
|
|
|
# -3 get the root tree |
1249
|
|
|
|
|
|
|
)]); |
1250
|
|
|
|
|
|
|
|
1251
|
|
|
|
|
|
|
@nodes = path([5,{a=>3,b=>sub {return 'test'}}], |
1252
|
|
|
|
|
|
|
['@1%a'], # or [['@',1,'%','b','&']] |
1253
|
|
|
|
|
|
|
|
1254
|
|
|
|
|
|
|
0 # return 3 |
1255
|
|
|
|
|
|
|
# -1 or 2 get the hash table |
1256
|
|
|
|
|
|
|
# -2 or 1 get the root tree |
1257
|
|
|
|
|
|
|
)]); |
1258
|
|
|
|
|
|
|
|
1259
|
|
|
|
|
|
|
|
1260
|
|
|
|
|
|
|
=cut |
1261
|
|
|
|
|
|
|
|
1262
|
|
|
|
|
|
|
#}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}} |
1263
|
|
|
|
|
|
|
|
1264
|
|
|
|
|
|
|
|
1265
|
108
|
|
|
|
|
496
|
debug "path( \$dom, $#paths patch, $father_nb)"; |
1266
|
|
|
|
|
|
|
|
1267
|
108
|
|
|
|
|
164
|
my @nodes; |
1268
|
|
|
|
|
|
|
|
1269
|
108
|
|
|
|
|
193
|
foreach my $node (@paths) { |
1270
|
153
|
50
|
|
|
|
323
|
(ref($node) eq 'ARRAY') or die 'path() : pattern "'.$node.'" should be a Dom pattern ("Dom" internal array, perhaps use patternText2dom)'; |
1271
|
|
|
|
|
|
|
|
1272
|
153
|
|
|
|
|
185
|
my @path = @{$node}; |
|
153
|
|
|
|
|
362
|
|
1273
|
|
|
|
|
|
|
|
1274
|
|
|
|
|
|
|
# perl evaluation of the dom path |
1275
|
153
|
|
|
|
|
383
|
my $e = $path2eval__->('$dom', $father_nb, @path); |
1276
|
|
|
|
|
|
|
|
1277
|
153
|
|
|
|
|
8377
|
my $r = eval $e; |
1278
|
153
|
|
|
|
|
660
|
debug $dom; |
1279
|
153
|
|
|
|
|
391
|
debug $e.' evaluated to '.__d($r); |
1280
|
153
|
50
|
|
|
|
335
|
die __FILE__.' : path() '.$e.' : '.$@ if ($@); |
1281
|
153
|
|
|
|
|
383
|
push @nodes,$r |
1282
|
|
|
|
|
|
|
} |
1283
|
108
|
50
|
|
|
|
281
|
return shift @nodes unless (wantarray()); |
1284
|
108
|
|
|
|
|
285
|
return @nodes; |
1285
|
|
|
|
|
|
|
} |
1286
|
|
|
|
|
|
|
|
1287
|
|
|
|
|
|
|
############################################################################## |
1288
|
|
|
|
|
|
|
#{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{ |
1289
|
|
|
|
|
|
|
sub compare { |
1290
|
|
|
|
|
|
|
#{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{ |
1291
|
|
|
|
|
|
|
|
1292
|
|
|
|
|
|
|
# ############ ret : 0 if equal / 1 else |
1293
|
936
|
|
|
936
|
1
|
1364
|
my $d1 = shift(); |
1294
|
936
|
|
|
|
|
900
|
my $d2 = shift(); |
1295
|
|
|
|
|
|
|
|
1296
|
936
|
|
|
|
|
928
|
my (@p1,@p2,$do_resolv_patch); |
1297
|
936
|
100
|
|
|
|
1054
|
if (@_) { |
1298
|
757
|
|
|
|
|
589
|
@p1 = @{$_[0]}; |
|
757
|
|
|
|
|
1115
|
|
1299
|
757
|
|
|
|
|
666
|
@p2 = @{$_[1]}; |
|
757
|
|
|
|
|
943
|
|
1300
|
|
|
|
|
|
|
} |
1301
|
|
|
|
|
|
|
else { |
1302
|
179
|
|
|
|
|
324
|
%loop_ref=(); |
1303
|
|
|
|
|
|
|
# equiv TEST on each function call: if ($CFG->{o_complex} and ($#a1==-1 and $#a2==-1)) { |
1304
|
179
|
100
|
|
|
|
325
|
$CFG->{o_complex} and $do_resolv_patch=1; |
1305
|
|
|
|
|
|
|
} |
1306
|
|
|
|
|
|
|
|
1307
|
|
|
|
|
|
|
=item I(, ) |
1308
|
|
|
|
|
|
|
|
1309
|
|
|
|
|
|
|
compare nodes from origine to destination |
1310
|
|
|
|
|
|
|
nodes are complex perl data structure |
1311
|
|
|
|
|
|
|
|
1312
|
|
|
|
|
|
|
Return a list of (empty if node structures are equals) |
1313
|
|
|
|
|
|
|
|
1314
|
|
|
|
|
|
|
EX: |
1315
|
|
|
|
|
|
|
|
1316
|
|
|
|
|
|
|
compare( |
1317
|
|
|
|
|
|
|
[{r=>new Data::Dumper([5],ui=>54},4], |
1318
|
|
|
|
|
|
|
[{r=>new Data::Dumper([5,2],ui=>52},4] |
1319
|
|
|
|
|
|
|
) |
1320
|
|
|
|
|
|
|
|
1321
|
|
|
|
|
|
|
return ({ action=>'add', |
1322
|
|
|
|
|
|
|
... |
1323
|
|
|
|
|
|
|
}, |
1324
|
|
|
|
|
|
|
{ action=>'change', |
1325
|
|
|
|
|
|
|
... |
1326
|
|
|
|
|
|
|
}, |
1327
|
|
|
|
|
|
|
... |
1328
|
|
|
|
|
|
|
) |
1329
|
|
|
|
|
|
|
|
1330
|
|
|
|
|
|
|
=cut |
1331
|
|
|
|
|
|
|
|
1332
|
|
|
|
|
|
|
|
1333
|
|
|
|
|
|
|
#}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}} |
1334
|
|
|
|
|
|
|
|
1335
|
|
|
|
|
|
|
|
1336
|
|
|
|
|
|
|
|
1337
|
|
|
|
|
|
|
############################################################################### |
1338
|
|
|
|
|
|
|
sub searchSuffix__{ |
1339
|
0
|
|
|
0
|
0
|
0
|
my @a1=@{shift()}; |
|
0
|
|
|
|
|
0
|
|
1340
|
0
|
|
|
|
|
0
|
my @a2=@{shift()}; |
|
0
|
|
|
|
|
0
|
|
1341
|
0
|
|
|
|
|
0
|
my @patch=@{shift()}; |
|
0
|
|
|
|
|
0
|
|
1342
|
|
|
|
|
|
|
|
1343
|
0
|
|
|
|
|
0
|
my @common; |
1344
|
0
|
|
0
|
|
|
0
|
while (@a1 and @a2) { |
1345
|
0
|
|
|
|
|
0
|
$_= pop(@a1); |
1346
|
0
|
0
|
0
|
|
|
0
|
($_ eq pop(@a2)) and unshift @common,$_ or return @common |
1347
|
|
|
|
|
|
|
} |
1348
|
|
|
|
|
|
|
return @common |
1349
|
0
|
|
|
|
|
0
|
} |
1350
|
|
|
|
|
|
|
############################################################################### |
1351
|
|
|
|
|
|
|
|
1352
|
|
|
|
|
|
|
sub resolve_patch { |
1353
|
53
|
|
|
53
|
0
|
87
|
my @patch = @_; |
1354
|
53
|
|
|
|
|
57
|
my ($p1,$p2); |
1355
|
|
|
|
|
|
|
|
1356
|
53
|
|
|
|
|
93
|
foreach $p1 (@patch) { |
1357
|
108
|
|
|
|
|
116
|
foreach $p2 (@patch) { |
1358
|
|
|
|
|
|
|
|
1359
|
470
|
100
|
100
|
|
|
789
|
if ($p1->{action} eq 'remove' and |
|
|
|
100
|
|
|
|
|
1360
|
|
|
|
|
|
|
$p2->{action} eq 'add' and |
1361
|
|
|
|
|
|
|
(__d($p1->{val_orig}) eq __d($p2->{val_dest}))) { |
1362
|
|
|
|
|
|
|
|
1363
|
|
|
|
|
|
|
#my @com = searchSuffix__($p1->{path_orig}, $p2->{path_dest}, \@patch); |
1364
|
|
|
|
|
|
|
#@com or next; |
1365
|
|
|
|
|
|
|
#grep({$_ eq '&'} @com) or next; |
1366
|
|
|
|
|
|
|
push @patch, |
1367
|
|
|
|
|
|
|
compare($p1->{val_orig}, |
1368
|
|
|
|
|
|
|
$p2->{val_dest}, |
1369
|
8
|
|
|
|
|
23
|
[@{$p1->{path_orig}}], |
1370
|
8
|
|
|
|
|
16
|
[@{$p2->{path_dest}}] |
|
8
|
|
|
|
|
20
|
|
1371
|
|
|
|
|
|
|
); |
1372
|
|
|
|
|
|
|
|
1373
|
8
|
|
|
|
|
21
|
$p1->{action}='move'; |
1374
|
8
|
|
|
|
|
14
|
$p1->{val_orig}= $p1->{val_dest}= undef; |
1375
|
8
|
|
|
|
|
13
|
$p1->{path_dest}= $p2->{path_dest}; |
1376
|
8
|
|
|
|
|
17
|
$p2->{action}='erase'; |
1377
|
|
|
|
|
|
|
} |
1378
|
|
|
|
|
|
|
} |
1379
|
|
|
|
|
|
|
} |
1380
|
|
|
|
|
|
|
|
1381
|
53
|
|
|
|
|
68
|
my $o = 0; |
1382
|
53
|
|
|
|
|
92
|
while ($o<=$#patch) { |
1383
|
108
|
100
|
66
|
|
|
185
|
($patch[$o]->{action} eq 'erase') and splice(@patch,$o,1) and next; |
1384
|
100
|
|
|
|
|
117
|
$o++ |
1385
|
|
|
|
|
|
|
} |
1386
|
|
|
|
|
|
|
|
1387
|
|
|
|
|
|
|
return @patch |
1388
|
53
|
|
|
|
|
207
|
} |
1389
|
|
|
|
|
|
|
|
1390
|
|
|
|
|
|
|
############################################################################### |
1391
|
|
|
|
|
|
|
#warn "\nComparing ORIG(".join(@p1,'=',ref($d1)||$d1).") <> DEST(".join('.',@p2,'=',ref($d2)||$d2).")\n"; |
1392
|
|
|
|
|
|
|
|
1393
|
|
|
|
|
|
|
# ############ ret : 0 if equal / 1 else |
1394
|
936
|
|
|
|
|
939
|
my @msg=(); |
1395
|
|
|
|
|
|
|
|
1396
|
|
|
|
|
|
|
######################################## !!!!! Type resolution |
1397
|
936
|
|
|
|
|
958
|
my $ref_type = ref $d1; |
1398
|
|
|
|
|
|
|
|
1399
|
936
|
100
|
|
|
|
1166
|
if ($ref_type) { |
1400
|
|
|
|
|
|
|
|
1401
|
446
|
100
|
|
|
|
714
|
($ref_type ne ref($d2)) |
1402
|
|
|
|
|
|
|
and |
1403
|
|
|
|
|
|
|
return ( $patchDOM->('change', \@p1,\@p2, $d1,$d2) ); |
1404
|
|
|
|
|
|
|
|
1405
|
|
|
|
|
|
|
#if (index($ref_type,'::')!=-1) { |
1406
|
|
|
|
|
|
|
|
1407
|
379
|
|
|
|
|
603
|
my ($realpack, $realtype, $id) = |
1408
|
|
|
|
|
|
|
(overload::StrVal($d1) =~ /^(?:(.*)\=)?([^=]*)\(([^\(]*)\)$/); |
1409
|
|
|
|
|
|
|
|
1410
|
379
|
50
|
66
|
|
|
2662
|
if ($realpack and $realtype and $id) { |
|
|
|
66
|
|
|
|
|
1411
|
2
|
|
|
|
|
6
|
my ($realpack2, $realtype2, $id2) = |
1412
|
|
|
|
|
|
|
(overload::StrVal($d2) =~ /^(?:(.*)\=)?([^=]*)\(([^\(]*)\)$/); |
1413
|
|
|
|
|
|
|
|
1414
|
2
|
50
|
|
|
|
27
|
($realtype ne $realtype2) |
1415
|
|
|
|
|
|
|
and |
1416
|
|
|
|
|
|
|
push @msg, $patchDOM->('change', \@p1 ,\@p2 , $realtype ,$realtype2); |
1417
|
|
|
|
|
|
|
|
1418
|
2
|
|
|
|
|
5
|
push @p1, '|',$ref_type; |
1419
|
2
|
|
|
|
|
4
|
push @p2, '|',$ref_type; |
1420
|
|
|
|
|
|
|
|
1421
|
2
|
|
|
|
|
10
|
debug "$ref_type -> ($realpack, $realtype, $id : $ref_type)"; |
1422
|
|
|
|
|
|
|
|
1423
|
2
|
|
|
|
|
4
|
$ref_type = $realtype; |
1424
|
|
|
|
|
|
|
} |
1425
|
|
|
|
|
|
|
} |
1426
|
|
|
|
|
|
|
|
1427
|
|
|
|
|
|
|
######################################## !!!!! SCALAR COMPARE |
1428
|
869
|
100
|
100
|
|
|
1375
|
if (!$ref_type) |
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
1429
|
|
|
|
|
|
|
{ |
1430
|
490
|
100
|
100
|
|
|
1292
|
(defined($d1) and $d1 ne $d2) and return ($patchDOM->('change', \@p1,\@p2, $d1,$d2) ); |
1431
|
407
|
100
|
100
|
|
|
642
|
(!defined($d1) and defined($d2)) and return ($patchDOM->('change', \@p1,\@p2, $d1,$d2) ); |
1432
|
405
|
|
|
|
|
864
|
return (); |
1433
|
|
|
|
|
|
|
} |
1434
|
|
|
|
|
|
|
######################################## !!!!! HASH COMPARE |
1435
|
|
|
|
|
|
|
elsif ($ref_type eq 'HASH') |
1436
|
|
|
|
|
|
|
{ |
1437
|
167
|
|
|
|
|
281
|
my (%seen,$k); |
1438
|
|
|
|
|
|
|
|
1439
|
167
|
|
|
|
|
167
|
foreach $k (sort {$a cmp $b} |
|
384
|
|
|
|
|
444
|
|
1440
|
167
|
|
|
|
|
431
|
keys(%{ $d1 })) |
1441
|
|
|
|
|
|
|
{ |
1442
|
360
|
|
|
|
|
473
|
$seen{$k}=1; |
1443
|
|
|
|
|
|
|
|
1444
|
360
|
100
|
|
|
|
445
|
if (exists $d2->{$k}) { |
1445
|
|
|
|
|
|
|
|
1446
|
338
|
50
|
|
|
|
466
|
loop_det($d1->{$k},@p1) and next; |
1447
|
|
|
|
|
|
|
|
1448
|
|
|
|
|
|
|
push @msg, |
1449
|
|
|
|
|
|
|
compare( $d1->{$k}, |
1450
|
338
|
|
|
|
|
959
|
$d2->{$k}, |
1451
|
|
|
|
|
|
|
[ @p1, '%',$k ], |
1452
|
|
|
|
|
|
|
[ @p2, '%',$k ], |
1453
|
|
|
|
|
|
|
); |
1454
|
|
|
|
|
|
|
} else { |
1455
|
22
|
|
|
|
|
67
|
push @msg,$patchDOM->('remove', [ @p1, '%', $k ] ,\@p2 , $d1->{$k} ,undef) |
1456
|
|
|
|
|
|
|
} |
1457
|
|
|
|
|
|
|
|
1458
|
|
|
|
|
|
|
}#foreach($d1) |
1459
|
|
|
|
|
|
|
|
1460
|
167
|
|
|
|
|
207
|
foreach $k (sort {$a cmp $b} keys(%{ $d2 })) { |
|
387
|
|
|
|
|
415
|
|
|
167
|
|
|
|
|
348
|
|
1461
|
361
|
100
|
|
|
|
502
|
next if exists $seen{$k}; |
1462
|
|
|
|
|
|
|
|
1463
|
23
|
|
|
|
|
30
|
my $v = $d2->{$k}; |
1464
|
23
|
|
|
|
|
62
|
push @msg,$patchDOM->('add', \@p1, [ @p2, '%', $k ], undef, $v) |
1465
|
|
|
|
|
|
|
} |
1466
|
|
|
|
|
|
|
|
1467
|
167
|
100
|
|
|
|
475
|
$do_resolv_patch or return @msg; |
1468
|
35
|
|
|
|
|
79
|
return resolve_patch(@msg); |
1469
|
|
|
|
|
|
|
} |
1470
|
|
|
|
|
|
|
elsif ($ref_type eq 'ARRAY') |
1471
|
|
|
|
|
|
|
{ |
1472
|
|
|
|
|
|
|
######################################## !!!!! ARRAY COMPARE (not complex mode) |
1473
|
|
|
|
|
|
|
|
1474
|
132
|
100
|
|
|
|
238
|
unless ($CFG->{o_complex}) { |
1475
|
|
|
|
|
|
|
|
1476
|
63
|
|
|
|
|
65
|
my $min = $#{$d1}; |
|
63
|
|
|
|
|
89
|
|
1477
|
63
|
100
|
|
|
|
67
|
$min = $#{$d2} if ($#{$d2}<$min); # min ($#{$d1},$#{$d2}) |
|
4
|
|
|
|
|
8
|
|
|
63
|
|
|
|
|
121
|
|
1478
|
|
|
|
|
|
|
|
1479
|
63
|
|
|
|
|
80
|
my $i; |
1480
|
63
|
|
|
|
|
104
|
foreach $i (0..$min) { |
1481
|
|
|
|
|
|
|
|
1482
|
120
|
100
|
|
|
|
181
|
loop_det($d1->[$i], @p1) |
1483
|
|
|
|
|
|
|
and |
1484
|
|
|
|
|
|
|
next; |
1485
|
|
|
|
|
|
|
|
1486
|
118
|
|
|
|
|
335
|
push @msg, |
1487
|
|
|
|
|
|
|
compare( $d1->[$i], $d2->[$i], [@p1, '@',$i], [@p2, '@',$i]); |
1488
|
|
|
|
|
|
|
} |
1489
|
|
|
|
|
|
|
|
1490
|
63
|
|
|
|
|
85
|
foreach $i ($min+1..$#{$d1}) { # $d1 is bigger |
|
63
|
|
|
|
|
113
|
|
1491
|
|
|
|
|
|
|
# silent just for complexe search mode |
1492
|
5
|
|
|
|
|
13
|
push @msg,$patchDOM->('remove', [ @p1, '@', $i ], \@p2 ,$d1->[$i], undef) |
1493
|
|
|
|
|
|
|
} |
1494
|
63
|
|
|
|
|
68
|
foreach $i ($#{$d1}+1..$#{$d2}) { # d2 is bigger |
|
63
|
|
|
|
|
80
|
|
|
63
|
|
|
|
|
91
|
|
1495
|
9
|
|
|
|
|
23
|
push @msg,$patchDOM->('add', \@p1, [ @p2, '@', $i ], undef, $d2->[$i]) |
1496
|
|
|
|
|
|
|
} |
1497
|
63
|
|
|
|
|
152
|
return @msg; |
1498
|
|
|
|
|
|
|
} |
1499
|
|
|
|
|
|
|
|
1500
|
|
|
|
|
|
|
######################################## !!!!! ARRAY COMPARE (in complex mode) |
1501
|
69
|
|
|
|
|
143
|
my @seen_src; |
1502
|
|
|
|
|
|
|
my @seen_dst; |
1503
|
69
|
|
|
|
|
0
|
my @res_Eq; |
1504
|
|
|
|
|
|
|
# perhaps not on the same index (search in the dest @) |
1505
|
69
|
|
|
|
|
0
|
my $i; |
1506
|
|
|
|
|
|
|
ARRAY_CPLX: |
1507
|
69
|
|
|
|
|
70
|
foreach $i (0..$#{$d1}) { |
|
69
|
|
|
|
|
142
|
|
1508
|
161
|
|
|
|
|
171
|
my $val1 = $d1->[$i]; |
1509
|
|
|
|
|
|
|
|
1510
|
|
|
|
|
|
|
#print "\n SAR($i) {"; |
1511
|
|
|
|
|
|
|
#if ($i<$#{$d2}) { |
1512
|
161
|
100
|
|
|
|
220
|
if (exists $d2->[$i]) { |
1513
|
155
|
|
|
|
|
127
|
my @res; |
1514
|
|
|
|
|
|
|
|
1515
|
155
|
100
|
|
|
|
202
|
loop_det($val1, @p1) |
1516
|
|
|
|
|
|
|
or |
1517
|
|
|
|
|
|
|
@res = compare($val1, |
1518
|
|
|
|
|
|
|
$d2->[$i], |
1519
|
|
|
|
|
|
|
[ @p1, '@',$i ], |
1520
|
|
|
|
|
|
|
[ @p2, '@',$i ]); |
1521
|
|
|
|
|
|
|
|
1522
|
155
|
100
|
|
|
|
294
|
if (@res) { $res_Eq[$i] = [@res] } # (*) |
|
29
|
|
|
|
|
51
|
|
1523
|
|
|
|
|
|
|
else |
1524
|
|
|
|
|
|
|
{ |
1525
|
126
|
|
|
|
|
150
|
$seen_src[$i]=$i; |
1526
|
126
|
|
|
|
|
114
|
$seen_dst[$i]=$i; |
1527
|
126
|
|
|
|
|
182
|
next ARRAY_CPLX; |
1528
|
|
|
|
|
|
|
} |
1529
|
|
|
|
|
|
|
} |
1530
|
35
|
|
|
|
|
47
|
my $j; |
1531
|
35
|
|
|
|
|
34
|
foreach $j (0..$#{$d2}) { #print " -> $j "; |
|
35
|
|
|
|
|
78
|
|
1532
|
102
|
100
|
|
|
|
141
|
next if ($i==$j); |
1533
|
78
|
100
|
|
|
|
105
|
next if (defined($seen_dst[$j])); |
1534
|
|
|
|
|
|
|
|
1535
|
61
|
100
|
|
|
|
125
|
unless (compare( $val1, |
1536
|
|
|
|
|
|
|
$d2->[$j], |
1537
|
|
|
|
|
|
|
[ @p1, '@',$i ], |
1538
|
|
|
|
|
|
|
[ @p2, '@',$j ])) |
1539
|
|
|
|
|
|
|
{ #print " (found) "; |
1540
|
|
|
|
|
|
|
|
1541
|
15
|
|
|
|
|
18
|
$seen_dst[$j] = 1; |
1542
|
15
|
|
|
|
|
39
|
$seen_src[$i] = $patchDOM->('move', |
1543
|
|
|
|
|
|
|
[ @p1, '@', $i ], |
1544
|
|
|
|
|
|
|
[ @p2, '@', $j ]); |
1545
|
15
|
|
|
|
|
35
|
next ARRAY_CPLX; |
1546
|
|
|
|
|
|
|
} |
1547
|
|
|
|
|
|
|
} |
1548
|
20
|
50
|
|
|
|
77
|
(defined $seen_src[$i]) |
1549
|
|
|
|
|
|
|
or |
1550
|
|
|
|
|
|
|
$seen_src[$i] = $patchDOM->('remove', |
1551
|
|
|
|
|
|
|
[ @p1, '@', $i ], |
1552
|
|
|
|
|
|
|
\@p2, |
1553
|
|
|
|
|
|
|
$val1, |
1554
|
|
|
|
|
|
|
undef |
1555
|
|
|
|
|
|
|
); |
1556
|
|
|
|
|
|
|
|
1557
|
|
|
|
|
|
|
#print " }SAR($i)"; |
1558
|
|
|
|
|
|
|
} # for $d1 (0..$min) |
1559
|
|
|
|
|
|
|
|
1560
|
|
|
|
|
|
|
### destination table $d2 is bigger |
1561
|
|
|
|
|
|
|
## |
1562
|
69
|
|
|
|
|
78
|
foreach $i (0..$#{$d2}) { |
|
69
|
|
|
|
|
107
|
|
1563
|
165
|
100
|
|
|
|
222
|
defined($seen_dst[$i]) and next; |
1564
|
|
|
|
|
|
|
|
1565
|
24
|
|
|
|
|
57
|
$seen_dst[$i] = $patchDOM->('add', |
1566
|
|
|
|
|
|
|
\@p1, |
1567
|
|
|
|
|
|
|
[ @p2, '@', $i ], |
1568
|
|
|
|
|
|
|
undef, |
1569
|
|
|
|
|
|
|
$d2->[$i] |
1570
|
|
|
|
|
|
|
) |
1571
|
|
|
|
|
|
|
} |
1572
|
|
|
|
|
|
|
|
1573
|
69
|
|
|
|
|
82
|
my $max = $#seen_dst; |
1574
|
|
|
|
|
|
|
|
1575
|
69
|
100
|
|
|
|
111
|
($#seen_src>$max) and $max = $#seen_src; |
1576
|
|
|
|
|
|
|
|
1577
|
69
|
|
|
|
|
100
|
foreach (0..$max) { |
1578
|
171
|
|
|
|
|
154
|
my $src = $seen_src[$_]; |
1579
|
171
|
|
|
|
|
143
|
my $dst = $seen_dst[$_]; |
1580
|
|
|
|
|
|
|
|
1581
|
171
|
100
|
66
|
|
|
301
|
if (ref($res_Eq[$_]) and # differences on the same index (*) |
|
|
|
100
|
|
|
|
|
1582
|
|
|
|
|
|
|
ref($src) and ref($dst)) { |
1583
|
|
|
|
|
|
|
|
1584
|
|
|
|
|
|
|
#print "\n src/dst : ".domPatch2TEXT($src)."/ ".domPatch2TEXT($dst)."\n"; |
1585
|
|
|
|
|
|
|
|
1586
|
|
|
|
|
|
|
# remove(@2,)= add(,@2)= |
1587
|
|
|
|
|
|
|
($src->{action} eq 'remove') and |
1588
|
|
|
|
|
|
|
($dst->{action} eq 'add') and |
1589
|
17
|
50
|
66
|
|
|
61
|
(push @msg, @{ $res_Eq[$_] }) |
|
12
|
|
66
|
|
|
41
|
|
1590
|
|
|
|
|
|
|
and next; |
1591
|
|
|
|
|
|
|
} |
1592
|
159
|
100
|
|
|
|
191
|
(ref $src) and push @msg,$src; |
1593
|
159
|
100
|
|
|
|
215
|
(ref $dst) and push @msg,$dst; |
1594
|
|
|
|
|
|
|
} |
1595
|
|
|
|
|
|
|
|
1596
|
69
|
100
|
|
|
|
214
|
$do_resolv_patch or return @msg; |
1597
|
14
|
|
|
|
|
27
|
return resolve_patch(@msg); |
1598
|
|
|
|
|
|
|
} |
1599
|
|
|
|
|
|
|
######################################## !!!!! REF COMPARE |
1600
|
|
|
|
|
|
|
elsif ($ref_type eq 'REF' or $ref_type eq 'SCALAR') |
1601
|
|
|
|
|
|
|
{ |
1602
|
65
|
50
|
|
|
|
103
|
if (loop_det($$d1, @p1)) { |
1603
|
|
|
|
|
|
|
} |
1604
|
|
|
|
|
|
|
else { |
1605
|
65
|
|
|
|
|
172
|
@msg = ( compare($$d1, $$d2, |
1606
|
|
|
|
|
|
|
[ @p1, '$' ], |
1607
|
|
|
|
|
|
|
[ @p2, '$' ]) |
1608
|
|
|
|
|
|
|
); |
1609
|
|
|
|
|
|
|
} |
1610
|
65
|
100
|
|
|
|
203
|
$do_resolv_patch or return @msg; |
1611
|
4
|
|
|
|
|
7
|
return resolve_patch(@msg); |
1612
|
|
|
|
|
|
|
} |
1613
|
|
|
|
|
|
|
######################################## !!!!! GLOBAL REF COMPARE |
1614
|
|
|
|
|
|
|
elsif ($ref_type eq 'GLOB') |
1615
|
|
|
|
|
|
|
{ |
1616
|
14
|
|
|
|
|
28
|
my $name1=$$d1; |
1617
|
14
|
|
|
|
|
65
|
$name1=~s/^\*//; |
1618
|
14
|
|
|
|
|
21
|
my $name2=$$d2; |
1619
|
14
|
|
|
|
|
44
|
$name2=~s/^\*//; |
1620
|
|
|
|
|
|
|
|
1621
|
14
|
|
|
|
|
26
|
push @p1,'*', $name1; |
1622
|
14
|
|
|
|
|
17
|
push @p2,'*', $name2; |
1623
|
|
|
|
|
|
|
|
1624
|
14
|
|
|
|
|
23
|
push @msg, $patchDOM->('change', \@p1 ,\@p2); |
1625
|
|
|
|
|
|
|
|
1626
|
14
|
|
|
|
|
22
|
my ($k,$g_d1,$g_d2)=(undef,undef,undef); |
1627
|
|
|
|
|
|
|
|
1628
|
14
|
100
|
66
|
|
|
32
|
if (defined *$d1{SCALAR} and defined(${*$d1{SCALAR}})) { |
|
14
|
100
|
|
|
|
51
|
|
|
|
50
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
1629
|
5
|
|
|
|
|
6
|
$g_d1 = *$d1{SCALAR}; |
1630
|
|
|
|
|
|
|
} |
1631
|
|
|
|
|
|
|
elsif (defined *$d1{ARRAY}) { |
1632
|
4
|
|
|
|
|
5
|
$g_d1 = *$d1{ARRAY}; |
1633
|
|
|
|
|
|
|
} |
1634
|
|
|
|
|
|
|
elsif (defined*$d1{HASH}) { |
1635
|
5
|
|
|
|
|
7
|
$g_d1 = *$d1{HASH}; |
1636
|
|
|
|
|
|
|
} |
1637
|
|
|
|
|
|
|
elsif (defined*$d1{GLOB}) { |
1638
|
0
|
|
|
|
|
0
|
$g_d1 = *$d1{GLOB}; |
1639
|
0
|
0
|
|
|
|
0
|
loop_det($g_d1, @p1) and return (); |
1640
|
|
|
|
|
|
|
} |
1641
|
|
|
|
|
|
|
else { |
1642
|
0
|
|
|
|
|
0
|
die $name1; |
1643
|
|
|
|
|
|
|
} |
1644
|
|
|
|
|
|
|
|
1645
|
14
|
100
|
66
|
|
|
28
|
if (defined *$d2{SCALAR} and defined(${*$d2{SCALAR}})) { |
|
14
|
100
|
|
|
|
35
|
|
|
|
50
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
1646
|
4
|
|
|
|
|
3
|
$g_d2 = *$d2{SCALAR}; |
1647
|
|
|
|
|
|
|
} |
1648
|
|
|
|
|
|
|
elsif (defined *$d2{ARRAY}) { |
1649
|
5
|
|
|
|
|
5
|
$g_d2 = *$d2{ARRAY}; |
1650
|
|
|
|
|
|
|
} |
1651
|
|
|
|
|
|
|
elsif (defined*$d2{HASH}) { |
1652
|
5
|
|
|
|
|
6
|
$g_d2 = *$d2{HASH}; |
1653
|
|
|
|
|
|
|
} |
1654
|
|
|
|
|
|
|
elsif (defined*$d2{GLOB}) { |
1655
|
0
|
|
|
|
|
0
|
$g_d2 = *$d2{GLOB}; |
1656
|
|
|
|
|
|
|
} |
1657
|
|
|
|
|
|
|
else { |
1658
|
0
|
|
|
|
|
0
|
die $name2; |
1659
|
|
|
|
|
|
|
} |
1660
|
|
|
|
|
|
|
|
1661
|
14
|
|
|
|
|
30
|
my @msg = ( compare($g_d1, $g_d2, \@p1, \@p2)); |
1662
|
|
|
|
|
|
|
|
1663
|
14
|
50
|
|
|
|
54
|
$do_resolv_patch or return @msg; |
1664
|
0
|
|
|
|
|
0
|
return resolve_patch(@msg); |
1665
|
|
|
|
|
|
|
|
1666
|
|
|
|
|
|
|
} |
1667
|
|
|
|
|
|
|
######################################## !!!!! CODE REF COMPARE |
1668
|
|
|
|
|
|
|
elsif ($ref_type eq 'CODE') { # cannot compare this type |
1669
|
|
|
|
|
|
|
|
1670
|
|
|
|
|
|
|
#push @msg,$patchDOM->('change', \@p1, [@p2, '@', $i ], undef, $d2->[$i]) |
1671
|
1
|
|
|
|
|
3
|
return (); |
1672
|
|
|
|
|
|
|
} |
1673
|
|
|
|
|
|
|
######################################## !!!!! What's that ? |
1674
|
|
|
|
|
|
|
else { |
1675
|
0
|
|
|
|
|
0
|
die 'unknown type /'.$ref_type.'/ '.join('',@p1); |
1676
|
|
|
|
|
|
|
} |
1677
|
0
|
|
|
|
|
0
|
return (); |
1678
|
|
|
|
|
|
|
} |
1679
|
|
|
|
|
|
|
|
1680
|
|
|
|
|
|
|
|
1681
|
|
|
|
|
|
|
|
1682
|
|
|
|
|
|
|
############################################################################## |
1683
|
|
|
|
|
|
|
#{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{ |
1684
|
|
|
|
|
|
|
sub applyPatch($@) { # modify a dom source with a patch |
1685
|
|
|
|
|
|
|
#{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{ |
1686
|
41
|
|
|
41
|
1
|
356
|
my $dom = shift(); |
1687
|
|
|
|
|
|
|
|
1688
|
|
|
|
|
|
|
|
1689
|
|
|
|
|
|
|
=item I(, [, ] ) |
1690
|
|
|
|
|
|
|
|
1691
|
|
|
|
|
|
|
applies the patches to the (perl data structure) |
1692
|
|
|
|
|
|
|
[, ] is the list of your patches to apply |
1693
|
|
|
|
|
|
|
supported patch format should be text or dom types, |
1694
|
|
|
|
|
|
|
the patch should a clear description of a modification |
1695
|
|
|
|
|
|
|
no '?' modifier or ambiguities) |
1696
|
|
|
|
|
|
|
|
1697
|
|
|
|
|
|
|
Return the modified dom, die if patch are badly formated |
1698
|
|
|
|
|
|
|
|
1699
|
|
|
|
|
|
|
EX: |
1700
|
|
|
|
|
|
|
applyPatch([1,2,3],'add(,@4)=4') |
1701
|
|
|
|
|
|
|
return [1,2,3,4] |
1702
|
|
|
|
|
|
|
|
1703
|
|
|
|
|
|
|
=back |
1704
|
|
|
|
|
|
|
|
1705
|
|
|
|
|
|
|
=cut |
1706
|
|
|
|
|
|
|
|
1707
|
|
|
|
|
|
|
#}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}} |
1708
|
41
|
|
|
|
|
80
|
debug 'applyPatch('.__d($dom).') :'; |
1709
|
41
|
|
|
|
|
95
|
my (@remove,@add,@change,@move); |
1710
|
|
|
|
|
|
|
|
1711
|
41
|
|
|
|
|
0
|
my $p; |
1712
|
41
|
|
|
|
|
65
|
foreach $p (@_) { # ordering the patch operations |
1713
|
145
|
50
|
|
|
|
239
|
defined($p) or next; |
1714
|
145
|
|
|
|
|
150
|
my $dom_patch = $p; |
1715
|
|
|
|
|
|
|
|
1716
|
145
|
100
|
|
|
|
273
|
(ref($p) eq 'HASH') |
1717
|
|
|
|
|
|
|
or ($dom_patch) = textPatch2DOM($p); |
1718
|
|
|
|
|
|
|
|
1719
|
145
|
|
|
|
|
264
|
debug(domPatch2TEXT($dom_patch)); |
1720
|
|
|
|
|
|
|
|
1721
|
145
|
|
|
|
|
5337
|
eval 'push @'.$dom_patch->{action}.', $dom_patch;'; |
1722
|
145
|
50
|
|
|
|
501
|
$@ and die 'applyPatch() : '.$@; |
1723
|
|
|
|
|
|
|
} |
1724
|
|
|
|
|
|
|
|
1725
|
41
|
|
|
|
|
109
|
my ($d,$t); |
1726
|
|
|
|
|
|
|
|
1727
|
41
|
|
|
|
|
0
|
my ($d1,$d2,$d3,$d4,$d5); |
1728
|
41
|
|
|
|
|
0
|
my ($t1,$t2,$t3,$t4,$t5); |
1729
|
|
|
|
|
|
|
|
1730
|
41
|
|
|
|
|
68
|
my $patch_eval='$d='.__d($dom).";\n"; |
1731
|
|
|
|
|
|
|
|
1732
|
41
|
|
|
|
|
75
|
$patch_eval .= '$t='.__d($dom).";\n"; |
1733
|
|
|
|
|
|
|
|
1734
|
41
|
|
|
|
|
61
|
my $post_eval; |
1735
|
|
|
|
|
|
|
|
1736
|
|
|
|
|
|
|
my $r; |
1737
|
41
|
|
|
|
|
73
|
foreach $r (@remove) { |
1738
|
23
|
|
|
|
|
35
|
my @porig = @{$r->{path_orig}}; |
|
23
|
|
|
|
|
59
|
|
1739
|
|
|
|
|
|
|
|
1740
|
23
|
|
|
|
|
38
|
my $key = pop @porig; |
1741
|
23
|
|
|
|
|
35
|
my $type = pop @porig; |
1742
|
|
|
|
|
|
|
|
1743
|
23
|
100
|
|
|
|
57
|
if ($type eq '@') { |
1744
|
12
|
|
|
|
|
28
|
$patch_eval .= 'splice @{'.$path2eval__->('$d',undef,@porig) ."},$key,1;\n"; |
1745
|
|
|
|
|
|
|
} |
1746
|
|
|
|
|
|
|
else { |
1747
|
11
|
|
|
|
|
30
|
$patch_eval .= 'delete '.$path2eval__->('$d',undef,@porig,$type,$key) .";\n"; |
1748
|
|
|
|
|
|
|
} |
1749
|
|
|
|
|
|
|
} |
1750
|
|
|
|
|
|
|
|
1751
|
41
|
|
|
|
|
47
|
my $m; |
1752
|
|
|
|
|
|
|
my @remove_patch = sort |
1753
|
|
|
|
|
|
|
{ |
1754
|
|
|
|
|
|
|
# the array indexes order from smallest to biggest |
1755
|
41
|
50
|
|
|
|
83
|
if (${$a->{path_orig}}[-2] eq '@') { |
|
4
|
|
|
|
|
6
|
|
|
4
|
|
|
|
|
14
|
|
1756
|
4
|
|
|
|
|
6
|
return (${$a->{path_orig}}[-1] > |
1757
|
4
|
|
|
|
|
6
|
${$b->{path_orig}}[-1]) |
|
4
|
|
|
|
|
14
|
|
1758
|
|
|
|
|
|
|
} |
1759
|
|
|
|
|
|
|
# smallest path after bigger ones |
1760
|
0
|
|
|
|
|
0
|
return $#{$a->{path_orig}} < $#{$b->{path_orig}}; |
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
1761
|
|
|
|
|
|
|
} @move; |
1762
|
|
|
|
|
|
|
|
1763
|
41
|
|
|
|
|
55
|
foreach $m (@remove_patch) { |
1764
|
16
|
|
|
|
|
19
|
my @porig = @{$m->{path_orig}}; |
|
16
|
|
|
|
|
34
|
|
1765
|
|
|
|
|
|
|
|
1766
|
16
|
|
|
|
|
22
|
my $key = pop @porig; |
1767
|
16
|
|
|
|
|
23
|
my $type = pop @porig; |
1768
|
|
|
|
|
|
|
|
1769
|
16
|
100
|
|
|
|
30
|
if ($type eq '@') { |
1770
|
8
|
|
|
|
|
16
|
$patch_eval .= 'splice @{'.$path2eval__->('$d',undef,@porig)."},$key,1;\n"; |
1771
|
|
|
|
|
|
|
} |
1772
|
|
|
|
|
|
|
else { |
1773
|
8
|
|
|
|
|
23
|
$patch_eval .= 'delete '.$path2eval__->('$d',undef,@porig,$type,$key) .";\n"; |
1774
|
|
|
|
|
|
|
} |
1775
|
|
|
|
|
|
|
} |
1776
|
|
|
|
|
|
|
|
1777
|
41
|
|
|
|
|
53
|
foreach $m (@remove_patch) { |
1778
|
16
|
|
|
|
|
17
|
my @porig = @{$m->{path_orig}}; |
|
16
|
|
|
|
|
28
|
|
1779
|
16
|
|
|
|
|
26
|
$patch_eval .= $path2eval__->('$d',undef,@{$m->{path_dest}}). |
|
16
|
|
|
|
|
31
|
|
1780
|
|
|
|
|
|
|
' = '.$path2eval__->('$t',undef,@porig).";\n"; |
1781
|
|
|
|
|
|
|
} |
1782
|
|
|
|
|
|
|
|
1783
|
|
|
|
|
|
|
|
1784
|
41
|
|
|
|
|
43
|
my $a; |
1785
|
41
|
|
|
|
|
55
|
foreach $a (@add) { |
1786
|
|
|
|
|
|
|
$patch_eval .= |
1787
|
38
|
|
|
|
|
78
|
$path2eval__->('$d',undef,@{$a->{path_dest}}). |
1788
|
38
|
|
|
|
|
50
|
' = '.__d($a->{val_dest}) .";\n"; |
1789
|
|
|
|
|
|
|
} |
1790
|
41
|
|
|
|
|
43
|
my $c; |
1791
|
41
|
|
|
|
|
56
|
foreach $c (@change) { |
1792
|
|
|
|
|
|
|
$patch_eval .= |
1793
|
68
|
|
|
|
|
116
|
$path2eval__->('$d',undef,@{$c->{path_dest}}). |
1794
|
68
|
|
|
|
|
73
|
' = '.__d($c->{val_dest}).";\n"; |
1795
|
|
|
|
|
|
|
} |
1796
|
|
|
|
|
|
|
|
1797
|
41
|
|
|
|
|
52
|
$patch_eval = $patch_eval.'$d;'; |
1798
|
|
|
|
|
|
|
|
1799
|
41
|
|
|
|
|
3887
|
my $res = eval($patch_eval); |
1800
|
|
|
|
|
|
|
|
1801
|
41
|
|
|
|
|
184
|
debug "\nEval=>> $patch_eval >>=".__d($res).".\n"; |
1802
|
|
|
|
|
|
|
|
1803
|
41
|
50
|
|
|
|
85
|
$@ |
1804
|
|
|
|
|
|
|
and |
1805
|
|
|
|
|
|
|
die 'applyPatch() : '.$patch_eval.$@; |
1806
|
|
|
|
|
|
|
|
1807
|
41
|
|
|
|
|
240
|
return $res |
1808
|
|
|
|
|
|
|
} |
1809
|
|
|
|
|
|
|
|
1810
|
|
|
|
|
|
|
=back |
1811
|
|
|
|
|
|
|
|
1812
|
|
|
|
|
|
|
=head2 Conversion Methods |
1813
|
|
|
|
|
|
|
|
1814
|
|
|
|
|
|
|
=over 4 |
1815
|
|
|
|
|
|
|
|
1816
|
|
|
|
|
|
|
=cut |
1817
|
|
|
|
|
|
|
|
1818
|
|
|
|
|
|
|
|
1819
|
|
|
|
|
|
|
############################################################################## |
1820
|
|
|
|
|
|
|
#{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{ |
1821
|
|
|
|
|
|
|
sub patternDom2Text($) { |
1822
|
|
|
|
|
|
|
#}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}} |
1823
|
605
|
|
|
605
|
1
|
776
|
my @path=@{shift()}; |
|
605
|
|
|
|
|
996
|
|
1824
|
|
|
|
|
|
|
#{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{ |
1825
|
|
|
|
|
|
|
|
1826
|
|
|
|
|
|
|
=item I() |
1827
|
|
|
|
|
|
|
|
1828
|
|
|
|
|
|
|
convert the pattern DOM (array of element used by search(), path()) to text scalar string. |
1829
|
|
|
|
|
|
|
|
1830
|
|
|
|
|
|
|
|
1831
|
|
|
|
|
|
|
is an array list of splited element of the pattern |
1832
|
|
|
|
|
|
|
|
1833
|
|
|
|
|
|
|
Return equivalent text |
1834
|
|
|
|
|
|
|
|
1835
|
|
|
|
|
|
|
EX: |
1836
|
|
|
|
|
|
|
patternDom2Text( ['?@'] ); |
1837
|
|
|
|
|
|
|
|
1838
|
|
|
|
|
|
|
Return '?@' |
1839
|
|
|
|
|
|
|
|
1840
|
|
|
|
|
|
|
patternDom2Text( ['%', 'r'] ); |
1841
|
|
|
|
|
|
|
|
1842
|
|
|
|
|
|
|
Return '%r' |
1843
|
|
|
|
|
|
|
|
1844
|
|
|
|
|
|
|
patternDom2Text( ['@',3,'%','r'] ); |
1845
|
|
|
|
|
|
|
|
1846
|
|
|
|
|
|
|
Return '@3%r' |
1847
|
|
|
|
|
|
|
|
1848
|
|
|
|
|
|
|
patternDom2Text( ['@',2,'=','3'] ); |
1849
|
|
|
|
|
|
|
|
1850
|
|
|
|
|
|
|
Return '@2=3' |
1851
|
|
|
|
|
|
|
|
1852
|
|
|
|
|
|
|
=cut |
1853
|
|
|
|
|
|
|
|
1854
|
|
|
|
|
|
|
#}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}} |
1855
|
|
|
|
|
|
|
|
1856
|
|
|
|
|
|
|
# patternDom2Text is a single join without key defined |
1857
|
|
|
|
|
|
|
|
1858
|
605
|
100
|
|
|
|
2139
|
(defined $CFG->{o_key}) or return join('',@path); |
1859
|
|
|
|
|
|
|
|
1860
|
74
|
50
|
|
|
|
65
|
(%{$CFG->{o_key}}) or join('',@path); |
|
74
|
|
|
|
|
117
|
|
1861
|
|
|
|
|
|
|
|
1862
|
|
|
|
|
|
|
|
1863
|
|
|
|
|
|
|
# matching Keys |
1864
|
|
|
|
|
|
|
|
1865
|
74
|
|
|
|
|
85
|
my $sz_path = scalar(@path); |
1866
|
|
|
|
|
|
|
|
1867
|
|
|
|
|
|
|
# debug "\n###".join('.',@{$path}).' '.join('|',keys %{$CFG->{o_key}}); <>; |
1868
|
|
|
|
|
|
|
|
1869
|
74
|
|
|
|
|
74
|
my %keys=%{$CFG->{o_key}}; |
|
74
|
|
|
|
|
289
|
|
1870
|
|
|
|
|
|
|
|
1871
|
|
|
|
|
|
|
# TODO : key priority sould be managed by a small getPrioritizedKey() function (warning) |
1872
|
|
|
|
|
|
|
|
1873
|
74
|
|
|
|
|
154
|
my @sorted_keys = |
1874
|
|
|
|
|
|
|
# sort { ( $keys{$a}->{priority} > $keys{$b}->{priority} ) } |
1875
|
|
|
|
|
|
|
keys %keys; |
1876
|
|
|
|
|
|
|
|
1877
|
74
|
|
|
|
|
87
|
my $k; |
1878
|
|
|
|
|
|
|
|
1879
|
74
|
|
|
|
|
90
|
my $i = 0; |
1880
|
74
|
|
|
|
|
112
|
while ($i
|
1881
|
|
|
|
|
|
|
|
1882
|
393
|
|
|
|
|
440
|
foreach $k (@sorted_keys) |
1883
|
|
|
|
|
|
|
{ |
1884
|
1831
|
|
|
|
|
1983
|
my $match = $keys{$k}{regexp}; |
1885
|
|
|
|
|
|
|
|
1886
|
|
|
|
|
|
|
#warn "\n=$k on ".join('',@path[0..$i]); |
1887
|
|
|
|
|
|
|
|
1888
|
1831
|
|
|
|
|
2784
|
my $min_index = $matchPath->($match, @path[0..$i]); |
1889
|
|
|
|
|
|
|
|
1890
|
1831
|
100
|
|
|
|
2856
|
if (defined $min_index) { |
1891
|
|
|
|
|
|
|
# debug |
1892
|
|
|
|
|
|
|
#warn " -> key($k -> ".join(' ',@{$match}).") = $min_index\n"; |
1893
|
|
|
|
|
|
|
|
1894
|
|
|
|
|
|
|
# replace the (matched key expression) by ('/' , ) |
1895
|
|
|
|
|
|
|
|
1896
|
79
|
|
|
|
|
196
|
splice @path, $min_index, scalar(@$match), '/',$k; |
1897
|
|
|
|
|
|
|
|
1898
|
79
|
|
|
|
|
123
|
$i = $i + 2 - scalar(@$match); |
1899
|
|
|
|
|
|
|
|
1900
|
|
|
|
|
|
|
#warn "-> path -> ".join('.',@path)." \$i=$i\n"; |
1901
|
|
|
|
|
|
|
} |
1902
|
|
|
|
|
|
|
} |
1903
|
393
|
|
|
|
|
518
|
$i++; |
1904
|
|
|
|
|
|
|
} |
1905
|
74
|
|
|
|
|
363
|
return join('',@path); |
1906
|
|
|
|
|
|
|
|
1907
|
|
|
|
|
|
|
}; |
1908
|
|
|
|
|
|
|
|
1909
|
|
|
|
|
|
|
|
1910
|
|
|
|
|
|
|
|
1911
|
|
|
|
|
|
|
############################################################################## |
1912
|
|
|
|
|
|
|
#{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{ |
1913
|
|
|
|
|
|
|
sub domPatch2TEXT(@) { |
1914
|
|
|
|
|
|
|
#}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}} |
1915
|
|
|
|
|
|
|
|
1916
|
|
|
|
|
|
|
=item I(, [,]) |
1917
|
|
|
|
|
|
|
|
1918
|
|
|
|
|
|
|
convert a list of perl usable patches into a readable text format. |
1919
|
|
|
|
|
|
|
Also convert to key patterns which are matching the regexp key definnition |
1920
|
|
|
|
|
|
|
Mainly used to convert the compare result (format dom) |
1921
|
|
|
|
|
|
|
|
1922
|
|
|
|
|
|
|
ARGS: |
1923
|
|
|
|
|
|
|
a list of |
1924
|
|
|
|
|
|
|
|
1925
|
|
|
|
|
|
|
Return a list of patches in TEXT mode |
1926
|
|
|
|
|
|
|
|
1927
|
|
|
|
|
|
|
EX: |
1928
|
|
|
|
|
|
|
|
1929
|
|
|
|
|
|
|
|
1930
|
|
|
|
|
|
|
domPatch2TEXT($patch1) |
1931
|
|
|
|
|
|
|
|
1932
|
|
|
|
|
|
|
returns 'change(@0$%magic_key,@0$%magic_key)="toto"/=>"tata"' |
1933
|
|
|
|
|
|
|
|
1934
|
|
|
|
|
|
|
|
1935
|
|
|
|
|
|
|
# one key defined |
1936
|
|
|
|
|
|
|
o_key({ key_1 => {regexp=>['%','magic_key'], eval=>'{magic_key}' } } ); |
1937
|
|
|
|
|
|
|
|
1938
|
|
|
|
|
|
|
# same but with the related matched key in path |
1939
|
|
|
|
|
|
|
|
1940
|
|
|
|
|
|
|
domPatch2TEXT($patch1) |
1941
|
|
|
|
|
|
|
|
1942
|
|
|
|
|
|
|
returns 'change(@0$/key_1,@0$/key_1)="toto"/=>"tata"' |
1943
|
|
|
|
|
|
|
|
1944
|
|
|
|
|
|
|
|
1945
|
|
|
|
|
|
|
=cut |
1946
|
|
|
|
|
|
|
|
1947
|
262
|
|
|
262
|
1
|
548
|
my @res; |
1948
|
|
|
|
|
|
|
my $patch; |
1949
|
262
|
|
|
|
|
327
|
foreach $patch (@_) { |
1950
|
|
|
|
|
|
|
#}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}} |
1951
|
|
|
|
|
|
|
|
1952
|
|
|
|
|
|
|
(ref($patch) eq 'HASH') and do { |
1953
|
|
|
|
|
|
|
|
1954
|
|
|
|
|
|
|
(exists $patch->{action}) |
1955
|
262
|
50
|
|
|
|
458
|
or die 'domPatch2TEXT(): bad internal dom structure '.__d($patch); |
1956
|
|
|
|
|
|
|
|
1957
|
|
|
|
|
|
|
|
1958
|
262
|
|
|
|
|
287
|
my $action = $patch->{action}; |
1959
|
262
|
|
|
|
|
291
|
my $v1 = $patch->{val_orig}; |
1960
|
262
|
|
|
|
|
274
|
my $v2 = $patch->{val_dest}; |
1961
|
|
|
|
|
|
|
|
1962
|
|
|
|
|
|
|
my $txt = $action |
1963
|
|
|
|
|
|
|
.'(' |
1964
|
|
|
|
|
|
|
.patternDom2Text($patch->{path_orig}) |
1965
|
|
|
|
|
|
|
.',' |
1966
|
|
|
|
|
|
|
.patternDom2Text($patch->{path_dest}) |
1967
|
262
|
|
|
|
|
461
|
.')='; |
1968
|
|
|
|
|
|
|
|
1969
|
262
|
100
|
100
|
|
|
784
|
if (($action eq 'remove') or ($action eq 'change')) { |
1970
|
168
|
|
|
|
|
240
|
$v1 = __d($v1); |
1971
|
168
|
|
|
|
|
222
|
$v1 =~ s|/=>|\/\\054\>|g; |
1972
|
168
|
|
|
|
|
191
|
$v1 =~ s/\s=>\s/=>/sg; |
1973
|
168
|
|
|
|
|
230
|
$txt .= $v1; |
1974
|
|
|
|
|
|
|
} |
1975
|
|
|
|
|
|
|
|
1976
|
262
|
100
|
|
|
|
395
|
($action eq 'change') and $txt .= '/=>'; |
1977
|
|
|
|
|
|
|
|
1978
|
262
|
100
|
100
|
|
|
597
|
if (($action eq 'add') or ($action eq 'change')) { |
1979
|
193
|
|
|
|
|
239
|
$v2 = __d($v2); |
1980
|
193
|
|
|
|
|
241
|
$v2 =~ s|/=>|\/\\054\>|g; |
1981
|
193
|
|
|
|
|
197
|
$v2 =~ s/\s=>\s/=>/sg; |
1982
|
193
|
|
|
|
|
227
|
$txt .= $v2; |
1983
|
|
|
|
|
|
|
} |
1984
|
|
|
|
|
|
|
|
1985
|
262
|
|
|
|
|
298
|
push @res, $txt; |
1986
|
|
|
|
|
|
|
next |
1987
|
262
|
|
|
|
|
388
|
} or |
1988
|
262
|
0
|
0
|
|
|
514
|
(ref($_) eq 'ARRAY') and do { |
|
|
|
33
|
|
|
|
|
1989
|
0
|
|
|
|
|
0
|
push @res,join '', @{$_}; |
|
0
|
|
|
|
|
0
|
|
1990
|
|
|
|
|
|
|
next |
1991
|
0
|
|
|
|
|
0
|
}; |
1992
|
|
|
|
|
|
|
} |
1993
|
|
|
|
|
|
|
|
1994
|
|
|
|
|
|
|
# |
1995
|
262
|
100
|
|
|
|
694
|
(wantarray()) and return @res; |
1996
|
2
|
|
|
|
|
9
|
return join("\n",@res); |
1997
|
|
|
|
|
|
|
} |
1998
|
|
|
|
|
|
|
|
1999
|
|
|
|
|
|
|
############################################################################## |
2000
|
|
|
|
|
|
|
#{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{ |
2001
|
|
|
|
|
|
|
sub domPatch2IHM(@) { |
2002
|
|
|
|
|
|
|
#}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}} |
2003
|
|
|
|
|
|
|
|
2004
|
|
|
|
|
|
|
=item I(, [,]) |
2005
|
|
|
|
|
|
|
|
2006
|
|
|
|
|
|
|
convert a list of patches in DOM format (internal Data;;Deep format) |
2007
|
|
|
|
|
|
|
into a IHM format. |
2008
|
|
|
|
|
|
|
Mainly used to convert the compare result (format dom) |
2009
|
|
|
|
|
|
|
|
2010
|
|
|
|
|
|
|
ARGS: |
2011
|
|
|
|
|
|
|
a list of |
2012
|
|
|
|
|
|
|
|
2013
|
|
|
|
|
|
|
Return a list of patches in IHM mode |
2014
|
|
|
|
|
|
|
IHM format is not convertible |
2015
|
|
|
|
|
|
|
|
2016
|
|
|
|
|
|
|
EX: |
2017
|
|
|
|
|
|
|
C($patch1) |
2018
|
|
|
|
|
|
|
returns |
2019
|
|
|
|
|
|
|
'"toto" changed in "tata" from @0$%a |
2020
|
|
|
|
|
|
|
into @0$%a |
2021
|
|
|
|
|
|
|
=cut |
2022
|
|
|
|
|
|
|
|
2023
|
|
|
|
|
|
|
|
2024
|
0
|
|
|
0
|
1
|
0
|
my ($msg,$patch); |
2025
|
|
|
|
|
|
|
|
2026
|
0
|
|
|
|
|
0
|
foreach $patch (@_) { |
2027
|
|
|
|
|
|
|
#}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}} |
2028
|
0
|
|
|
|
|
0
|
$_ = $patch->{action}; |
2029
|
|
|
|
|
|
|
|
2030
|
|
|
|
|
|
|
/^add$/ and ($msg .= __d($patch->{val_orig}).' added') |
2031
|
|
|
|
|
|
|
or |
2032
|
|
|
|
|
|
|
/^remove$/ and ($msg .= __d($patch->{val_orig}).' removed') |
2033
|
|
|
|
|
|
|
or |
2034
|
|
|
|
|
|
|
/^move$/ and ($msg .= 'Moved ') |
2035
|
|
|
|
|
|
|
or |
2036
|
|
|
|
|
|
|
/^change$/ and ($msg .= __d($patch->{val_orig}) |
2037
|
|
|
|
|
|
|
.' changed in ' |
2038
|
0
|
0
|
0
|
|
|
0
|
.__d($patch->{val_dest})); |
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
2039
|
0
|
|
|
|
|
0
|
my $l = length($msg); |
2040
|
0
|
|
|
|
|
0
|
my $MAX_COLS=40; |
2041
|
0
|
0
|
|
|
|
0
|
if ($l>$MAX_COLS) { |
2042
|
0
|
|
|
|
|
0
|
$msg .= "\n from ".join('',@{$patch->{path_orig}}); |
|
0
|
|
|
|
|
0
|
|
2043
|
0
|
|
|
|
|
0
|
$msg .= "\n into ".join('',@{$patch->{path_dest}}); |
|
0
|
|
|
|
|
0
|
|
2044
|
|
|
|
|
|
|
} |
2045
|
|
|
|
|
|
|
else { |
2046
|
0
|
|
|
|
|
0
|
$l-=($msg=~ s/\n//g); |
2047
|
0
|
|
|
|
|
0
|
$msg .= ' from '.join('',@{$patch->{path_orig}}); |
|
0
|
|
|
|
|
0
|
|
2048
|
0
|
|
|
|
|
0
|
$msg .= "\n".(' 'x $l).' into '.join('',@{$patch->{path_dest}}); |
|
0
|
|
|
|
|
0
|
|
2049
|
|
|
|
|
|
|
} |
2050
|
0
|
|
|
|
|
0
|
$msg .= "\n"; |
2051
|
|
|
|
|
|
|
} |
2052
|
0
|
|
|
|
|
0
|
return $msg; |
2053
|
|
|
|
|
|
|
} |
2054
|
|
|
|
|
|
|
|
2055
|
|
|
|
|
|
|
|
2056
|
|
|
|
|
|
|
############################################################################## |
2057
|
|
|
|
|
|
|
#{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{ |
2058
|
|
|
|
|
|
|
sub patternText2Dom($) { |
2059
|
|
|
|
|
|
|
#}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}} |
2060
|
|
|
|
|
|
|
|
2061
|
82
|
|
|
82
|
1
|
253
|
my $pathTxt = shift(); |
2062
|
|
|
|
|
|
|
|
2063
|
82
|
50
|
|
|
|
128
|
(ref($pathTxt)) and die 'patternText2Dom() : bad call with a reference instead of scalar containing pattern text '; |
2064
|
|
|
|
|
|
|
|
2065
|
|
|
|
|
|
|
=item I() |
2066
|
|
|
|
|
|
|
|
2067
|
|
|
|
|
|
|
convert pattern scalar string to the array of element to be used by search(), path() |
2068
|
|
|
|
|
|
|
|
2069
|
|
|
|
|
|
|
|
2070
|
|
|
|
|
|
|
is an array of type description to match |
2071
|
|
|
|
|
|
|
optional argument to limit the number of results |
2072
|
|
|
|
|
|
|
if undef all results are returned |
2073
|
|
|
|
|
|
|
if 1 first one is returned |
2074
|
|
|
|
|
|
|
|
2075
|
|
|
|
|
|
|
Return an array list of splited element of the for usage |
2076
|
|
|
|
|
|
|
|
2077
|
|
|
|
|
|
|
EX: |
2078
|
|
|
|
|
|
|
patternText2Dom( '?@' ); |
2079
|
|
|
|
|
|
|
|
2080
|
|
|
|
|
|
|
Return ['?@'] |
2081
|
|
|
|
|
|
|
|
2082
|
|
|
|
|
|
|
patternText2Dom( '%r' ); |
2083
|
|
|
|
|
|
|
|
2084
|
|
|
|
|
|
|
Return '%', r'] |
2085
|
|
|
|
|
|
|
|
2086
|
|
|
|
|
|
|
patternText2Dom( '@3%r' ); |
2087
|
|
|
|
|
|
|
|
2088
|
|
|
|
|
|
|
Return ['@',3,'%','r'] |
2089
|
|
|
|
|
|
|
|
2090
|
|
|
|
|
|
|
patternText2Dom( '@2=3' ); |
2091
|
|
|
|
|
|
|
|
2092
|
|
|
|
|
|
|
Return ['@',2,'=','3'] |
2093
|
|
|
|
|
|
|
|
2094
|
|
|
|
|
|
|
=cut |
2095
|
|
|
|
|
|
|
|
2096
|
|
|
|
|
|
|
#}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}} |
2097
|
|
|
|
|
|
|
|
2098
|
82
|
|
|
|
|
65
|
my @path; |
2099
|
|
|
|
|
|
|
|
2100
|
|
|
|
|
|
|
#debug "patternText2Dom($pathTxt)";; |
2101
|
|
|
|
|
|
|
|
2102
|
82
|
|
|
|
|
94
|
my %keys=(); |
2103
|
|
|
|
|
|
|
|
2104
|
82
|
100
|
|
|
|
144
|
(ref($CFG->{o_key})) and %keys = %{$CFG->{o_key}}; |
|
12
|
|
|
|
|
68
|
|
2105
|
|
|
|
|
|
|
|
2106
|
82
|
|
|
|
|
202
|
my @pathTxt = split('',$pathTxt); |
2107
|
|
|
|
|
|
|
|
2108
|
82
|
|
|
|
|
135
|
while (@pathTxt) { |
2109
|
|
|
|
|
|
|
|
2110
|
427
|
|
|
|
|
464
|
$_ = shift @pathTxt; |
2111
|
|
|
|
|
|
|
|
2112
|
427
|
100
|
100
|
|
|
1690
|
if (defined($path[-1]) and $path[-1] =~ /^\?/ and m/^[\=\%\$\@\%\*]/) { |
|
|
100
|
66
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
2113
|
3
|
|
|
|
|
8
|
$path[-1].= $_; |
2114
|
|
|
|
|
|
|
} |
2115
|
|
|
|
|
|
|
elsif ($_ eq '$') { |
2116
|
22
|
|
|
|
|
35
|
push(@path,'$'); |
2117
|
|
|
|
|
|
|
} |
2118
|
|
|
|
|
|
|
elsif ($_ eq '?') { |
2119
|
3
|
|
|
|
|
9
|
push(@path,'?'); |
2120
|
|
|
|
|
|
|
} |
2121
|
|
|
|
|
|
|
elsif ($_ eq '&') { |
2122
|
3
|
|
|
|
|
7
|
push(@path,'&'); |
2123
|
|
|
|
|
|
|
} |
2124
|
|
|
|
|
|
|
elsif (/([%\@\=\|\*\/])/) { |
2125
|
144
|
|
|
|
|
330
|
push(@path,$1,''); |
2126
|
|
|
|
|
|
|
} |
2127
|
|
|
|
|
|
|
else { |
2128
|
252
|
100
|
100
|
|
|
435
|
if ($path[-2] eq '/' and exists($keys{$path[-1]})) { |
2129
|
|
|
|
|
|
|
# cf test "Search Complex key 3..5" |
2130
|
3
|
|
|
|
|
6
|
push(@path,''); |
2131
|
|
|
|
|
|
|
} |
2132
|
252
|
|
|
|
|
372
|
$path[-1].= $_; |
2133
|
|
|
|
|
|
|
} |
2134
|
|
|
|
|
|
|
} |
2135
|
|
|
|
|
|
|
|
2136
|
|
|
|
|
|
|
# post - convertion of array & key convertion |
2137
|
|
|
|
|
|
|
|
2138
|
82
|
|
|
|
|
86
|
my $i; |
2139
|
82
|
|
|
|
|
141
|
for $i (0..$#path) { |
2140
|
|
|
|
|
|
|
|
2141
|
319
|
100
|
|
|
|
503
|
if ($path[$i] eq '@') { |
|
|
100
|
|
|
|
|
|
2142
|
56
|
|
|
|
|
93
|
$path[$i+1] = int($path[$i+1]); |
2143
|
|
|
|
|
|
|
} |
2144
|
|
|
|
|
|
|
elsif ($path[$i] eq '/') { |
2145
|
16
|
|
|
|
|
22
|
my $keyname = $path[$i+1]; |
2146
|
16
|
50
|
|
|
|
31
|
(exists($keys{$keyname})) or die 'patternText2Dom() ! no key '.$keyname; |
2147
|
|
|
|
|
|
|
|
2148
|
16
|
|
|
|
|
22
|
splice @path, $i, 2, @{ $keys{$keyname}{regexp} }; |
|
16
|
|
|
|
|
65
|
|
2149
|
|
|
|
|
|
|
|
2150
|
|
|
|
|
|
|
} |
2151
|
|
|
|
|
|
|
} |
2152
|
|
|
|
|
|
|
|
2153
|
|
|
|
|
|
|
#warn "patternText2Dom(".join('',@pathTxt).')=> '.join(' ',@path)." ."; |
2154
|
|
|
|
|
|
|
|
2155
|
|
|
|
|
|
|
#debug '=>'.join('.',@path); |
2156
|
82
|
|
|
|
|
284
|
return [@path]; |
2157
|
|
|
|
|
|
|
}; |
2158
|
|
|
|
|
|
|
|
2159
|
|
|
|
|
|
|
|
2160
|
|
|
|
|
|
|
############################################################################## |
2161
|
|
|
|
|
|
|
#{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{ |
2162
|
|
|
|
|
|
|
sub textPatch2DOM(@) { |
2163
|
|
|
|
|
|
|
#}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}} |
2164
|
|
|
|
|
|
|
|
2165
|
|
|
|
|
|
|
=item I(, [,]) |
2166
|
|
|
|
|
|
|
|
2167
|
|
|
|
|
|
|
convert a list of patches formatted in text (readable text format format) |
2168
|
|
|
|
|
|
|
to a perl DOM format (man perldsc). |
2169
|
|
|
|
|
|
|
Mainly used to convert the compare result (format dom) |
2170
|
|
|
|
|
|
|
|
2171
|
|
|
|
|
|
|
ARGS: |
2172
|
|
|
|
|
|
|
a list of |
2173
|
|
|
|
|
|
|
|
2174
|
|
|
|
|
|
|
Return a list of patches in dom mode |
2175
|
|
|
|
|
|
|
|
2176
|
|
|
|
|
|
|
EX: |
2177
|
|
|
|
|
|
|
C( 'change(@0$%a,@0$%a)="toto"/=>"tata"', |
2178
|
|
|
|
|
|
|
'move(... ' |
2179
|
|
|
|
|
|
|
) |
2180
|
|
|
|
|
|
|
|
2181
|
|
|
|
|
|
|
returns ( |
2182
|
|
|
|
|
|
|
{ action=>'change', |
2183
|
|
|
|
|
|
|
path_orig=>['@0','$','%a'], |
2184
|
|
|
|
|
|
|
path_dest=>['@0','$','%a'], |
2185
|
|
|
|
|
|
|
val_orig=>"toto", |
2186
|
|
|
|
|
|
|
val_dest=>"tata" |
2187
|
|
|
|
|
|
|
}, |
2188
|
|
|
|
|
|
|
{ action=>'move', |
2189
|
|
|
|
|
|
|
... |
2190
|
|
|
|
|
|
|
}); |
2191
|
|
|
|
|
|
|
|
2192
|
|
|
|
|
|
|
=cut |
2193
|
|
|
|
|
|
|
|
2194
|
27
|
|
|
27
|
1
|
33
|
my @res; |
2195
|
27
|
|
|
|
|
50
|
while (@_) { |
2196
|
|
|
|
|
|
|
#}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}} |
2197
|
27
|
|
|
|
|
33
|
my $patch=pop; |
2198
|
|
|
|
|
|
|
|
2199
|
27
|
50
|
|
|
|
38
|
defined($patch) or next; |
2200
|
|
|
|
|
|
|
|
2201
|
27
|
|
|
|
|
71
|
debug "textPatch2DOM in ".$patch; |
2202
|
|
|
|
|
|
|
|
2203
|
27
|
|
|
|
|
35
|
my ($p1,$p2,$v1,$v2); |
2204
|
27
|
50
|
|
|
|
111
|
$patch =~ s/^(\w+)\(// or die 'Data::Deep::textPatch2DOM / bad patch format :'.$patch.' !!!'; |
2205
|
|
|
|
|
|
|
|
2206
|
27
|
|
|
|
|
51
|
my $action = $1; # or die 'action ???'; |
2207
|
|
|
|
|
|
|
|
2208
|
27
|
50
|
|
|
|
102
|
( $patch =~ s/^([^,]*?),// |
2209
|
|
|
|
|
|
|
) and $p1 = patternText2Dom($1); |
2210
|
|
|
|
|
|
|
|
2211
|
27
|
50
|
|
|
|
115
|
( $patch =~ s/^([^\(]*?)\)=// |
2212
|
|
|
|
|
|
|
) and $p2 = patternText2Dom($1); |
2213
|
|
|
|
|
|
|
|
2214
|
27
|
50
|
|
|
|
47
|
if ($action ne 'move') { |
2215
|
27
|
|
|
|
|
47
|
my $i = index($patch, '/=>'); |
2216
|
27
|
100
|
|
|
|
64
|
if ($i ==-1 ) { |
2217
|
19
|
100
|
66
|
|
|
59
|
($action eq 'add') && ($v2 = $patch) or ($v1 = $patch); |
2218
|
|
|
|
|
|
|
} |
2219
|
|
|
|
|
|
|
else { |
2220
|
8
|
|
|
|
|
13
|
$v1 = substr($patch, 0, $i); |
2221
|
8
|
|
|
|
|
17
|
$v2 = substr($patch, $i+3); |
2222
|
|
|
|
|
|
|
} |
2223
|
|
|
|
|
|
|
} |
2224
|
27
|
|
|
|
|
662
|
my $a = eval($v1); |
2225
|
27
|
50
|
|
|
|
84
|
($@) and die "textPatch2DOM() error in eval($v1) : ".$@; |
2226
|
|
|
|
|
|
|
|
2227
|
27
|
|
|
|
|
648
|
my $b = eval($v2); |
2228
|
27
|
50
|
|
|
|
81
|
($@) and die "textPatch2DOM() error in eval($v2) : ".$@; |
2229
|
|
|
|
|
|
|
|
2230
|
27
|
|
|
|
|
53
|
push @res,$patchDOM->($action, $p1, $p2, $a, $b); |
2231
|
|
|
|
|
|
|
} |
2232
|
|
|
|
|
|
|
|
2233
|
|
|
|
|
|
|
# |
2234
|
27
|
50
|
|
|
|
88
|
(wantarray()) and return @res; |
2235
|
0
|
|
|
|
|
|
return [@res]; |
2236
|
|
|
|
|
|
|
} |
2237
|
|
|
|
|
|
|
|
2238
|
|
|
|
|
|
|
=back |
2239
|
|
|
|
|
|
|
|
2240
|
|
|
|
|
|
|
=begin end |
2241
|
|
|
|
|
|
|
|
2242
|
|
|
|
|
|
|
=head1 AUTHOR |
2243
|
|
|
|
|
|
|
|
2244
|
|
|
|
|
|
|
|
2245
|
|
|
|
|
|
|
Data::Deep was written by Matthieu Damerose Idamo@cpan.orgE> in 2005. |
2246
|
|
|
|
|
|
|
|
2247
|
|
|
|
|
|
|
=cut |
2248
|
|
|
|
|
|
|
|
2249
|
|
|
|
|
|
|
|
2250
|
|
|
|
|
|
|
########################################################################### |
2251
|
|
|
|
|
|
|
1;############################################################################# |
2252
|
|
|
|
|
|
|
__END__ Deep::Manip.pm |