NAME
Data::Deep - Complexe Data Structure analysis and manipulation
SYNOPSIS
use Data::Deep;
$dom1=[ \{'toto' => 12}, 33, {o=>5,d=>12}, 'titi' ];
$dom2=[ \{'toto' => 12, E=>3},{d=>12,o=>5}, 'titi' ];
my @patch = compare($dom1, $dom2);
use Data::Deep qw(:DEFAULT :convert :config);
o_complex(1); # deeper analysis results
print join("\n", domPatch2TEXT( @patch ) );
@patch = ( 'add(@0$,@0$%E)=3','remove(@1,)=33','move(@2,@1)=','move(@3,@2)=' );
$dom2 = applyPatch($dom1,@patch);
@list_found = search($dom1, ['@',1])
@list_found = search($dom1, patternText2Dom('@1'))
DESCRIPTION
Data::Deep provides search, path, compare and applyPatch functions which may operate on complex Perl Data Structure for introspection, usage and manipulation (ref, hash or array, array of hash, blessed object and siple scalar). Package, Filehandles and functions are partially supported (type and location is considered). Loop circular references are also considered as a $t1 variable and partially supported.
path definition
path expression identify the current element node location in a complex Perl data structure. pattern used in function search is used to match a part of this path.
Path is composed internally of an array of following elements :
('%', '<key>') to match a hash table at <key> value
('@', <index>) to match an array at specified index value
('*', '<glob name>') to match a global reference
('|', '<module name>') to match a blessed module reference
('$') to match a reference
('&') to match a code reference
('$loop') to match a loop reference (circular reference)
('=' <value>) to match the leaf node <value>
In text mode a keyname may be defined by entering an hash-ref of keys in o_key() then '/keyname' will appears in the path text results or could be provided to convert function textPatch2dom() and patternText2dom()
Modifier <?> can be placed in the path with types to checks :
EX:
?% : match with hash-table content (any key match)
?@ : match with an array content (any index match)
?= : any value
?* : any glob type
?$ : any reference
?=%@ : any value, hash-table or array
?%@*|$&= : everything
Evaluation function : sub{... test with $_ ... } will be executed to match the node EX: sub { /\d{2,}/ } match numbers of minimal size of two
Patch is a directional operation to apply difference between two nodes resulting from compare($a, $b) Patch allow the $a complex perl data structure to be changed to $b using applyPatch($a,@patch)
Each Patch operation is composed of : - an action : 'add' for addition of an element from source to destination 'remove' is the suppression from source to destination 'move' if possible the move of a value or Perl Dom 'change' describe the modification of a value 'erase' is managed internally for array cleanup when using 'move' - a source path on which the value is taken from - a destination path on which is applied the change (most of the time same as source)
Three patch formats can be use : - dom : interaction with search, path, compare, ApplyPatch - text : programmer facilities to use a single scalar for a patch operation - ihm : a small readble IHM text aim for output only
Convert function may operation the change between this formats.
DOM : dom patch hash-ref sample
EX: my $patch1 =
{ action=>'change',
path_orig=>['@0','$','%a'],
path_dest=>['@0','$','%a'],
val_orig=>"toto",
val_dest=>"tata"
};
TEXT : text output mode patch could be :
add(<path source>,<path destination>)=<val dest>
remove(<path source>,<path destination>)=<val src>
change(<path source>,<path destination>)=<val src>/=><val dest>
move(<path source>,<path destination>)
Important note :
* search() and path() functions use paths in "dom" format :
DOM (simple array of elements described above)
EX: ['@',1,'%','r','=',432]
* applyPath() can use TEXT or DOM patch format in input.
* compare() produce "dom" patch format in output.
All function prefer the use of dom (internal format) then no convertion is done. Output (user point of view) is text or ihm.
format patches dom can be converted to TEXT : domPatch2TEXT format patches text can be converted to DOM : textPatch2DOM format patches dom can be converted to IHM : domPatch2IHM
See conversion function
Options Methods
- zap(<array of path>)
-
configure nodes to skip (in search or compare) without parameter will return those nodes
- o_debug([<debug mode>])
-
debug mode : 1: set debug mode on 0: set debug mode off undef : return debug mode
- o_follow_ref([<follow mode>])
-
follow mode : 1: follow every reference (default) 0: do not enter into any reference undef: return if reference are followed
- o_complex([<complex mode>])
-
complex mode is used for intelligency complex (EX: elements move in an array) 1: complex mode used in search() & compare() 0: simple analysis (no complex search) undef: return if reference are followed
- o_key(<hash of key path>)
-
key is a search pattern for simplifying search or compare. or a group of pattern for best identification of nodes.
hash of key path:
EX: key( CRC => {regexp=>['%','crc32'], eval=>'{crc32}', priority=>1 }, SZ => {regexp=>['%','sz'), eval=>'{sz}', priority=>2 } )
regexp : path to search in the dom eval : is the perl way to match the node priority : on the same node two ambigues keys are prioritized depth : how many upper node to return from the current match node
Operation Methods
- travel(<dom> [,<visitor function>])
-
travel make the visitor function to travel through each node of the <dom>
<dom> complexe perl data structure to travel into <visitor_fx>()
Return a list path where the <pattern> argument match with the corresponding node in the <dom> tree data type
EX:
travel( {ky=>['l','r','t',124],r=>2} returns ( [ '%', 'ky', '@' , 3 , '=' , 124 ] )
- search(<tree>, <pattern> [,<max occurrences>])
-
search the <pattern> into <tree>
<tree> is a complexe perl data structure to search into <pattern> is an array of type description to match <max occ.> optional argument to limit the number of results if undef all results are returned if 1 first one is returned
Return a list path where the <pattern> argument match with the corresponding node in the <dom> tree data type
EX: search( {ky=>['l','r','t',124],r=>2} ['?@','=',124])
Returns ( [ '%', 'ky', '@' , 3 , '=' , 124 ] ) search( [5,2,3,{r=>3,h=>5},4,\{r=>4},{r=>5}], ['%','r'], 2 ) Returns (['@',3,'%','r'],['@',5,'$','%','r']) search( [5,2,3,{r=>3},4,\3], ['?$@%','=',sub {$_ == 3 }], 2; Returns (['@',2,'=',3], ['@',3,'%','r','=',3])
- path(<tree>, <paths> [,<depth>])
-
gives a list of nodes pointed by <paths> <tree> is the complex perl data structure <paths> is the array reference of paths <depth> is the depth level to return from tree <nb> start counting from the top -<nb> start counting from the leaf 0 return the leaf or check the leaf with '=' or '&' types): * if code give the return of execution * scalar will check the value
Return a list of nodes reference to the <dom>
EX:
$eq_3 = path([5,{a=>3,b=>sub {return 'test'}}], ['@1%a']) $eq_3 = path([5,{a=>3,b=>sub {return 'test'}}], '@1%a','@1%b') @nodes = path([5,{a=>3,b=>sub {return 'test'}}], ['@1%b&'], # or [['@',1,'%','b','&']] 0 # return ('test') # -1 or 2 return ( sub { "DUMMY" } ) # -2 or 1 get the hash table # -3 get the root tree )]); @nodes = path([5,{a=>3,b=>sub {return 'test'}}], ['@1%a'], # or [['@',1,'%','b','&']] 0 # return 3 # -1 or 2 get the hash table # -2 or 1 get the root tree )]);
- compare(<node origine>, <node destination>)
-
compare nodes from origine to destination nodes are complex perl data structure
Return a list of <patch in dom format> (empty if node structures are equals)
EX:
compare( [{r=>new Data::Dumper([5],ui=>54},4], [{r=>new Data::Dumper([5,2],ui=>52},4] ) return ({ action=>'add', ... }, { action=>'change', ... }, ... )
- applyPatch(<tree>, <patch 1> [, <patch N>] )
-
applies the patches to the <tree> (perl data structure) <patch1> [,<patch N> ] is the list of your patches to apply supported patch format should be text or dom types, the patch should a clear description of a modification no '?' modifier or ambiguities)
Return the modified dom, die if patch are badly formated
EX: applyPatch([1,2,3],'add(,@4)=4') return [1,2,3,4]
Conversion Methods
- patternDom2Text(<pattern>)
-
convert the pattern DOM (array of element used by search(), path()) to text scalar string.
<pattern> is an array list of splited element of the pattern
Return equivalent text
EX: patternDom2Text( ['?@'] );
Return '?@' patternDom2Text( ['%', 'r'] ); Return '%r' patternDom2Text( ['@',3,'%','r'] ); Return '@3%r' patternDom2Text( ['@',2,'=','3'] ); Return '@2=3'
- domPatch2TEXT(<patch 1>, <patch 2> [,<patch N>])
-
convert a list of perl usable patches into a readable text format. Also convert to key patterns which are matching the regexp key definnition Mainly used to convert the compare result (format dom)
ARGS: a list of <patch in dom format>
Return a list of patches in TEXT mode
EX:
domPatch2TEXT($patch1) returns 'change(@0$%magic_key,@0$%magic_key)="toto"/=>"tata"' # one key defined o_key({ key_1 => {regexp=>['%','magic_key'], eval=>'{magic_key}' } } ); # same but with the related matched key in path domPatch2TEXT($patch1) returns 'change(@0$/key_1,@0$/key_1)="toto"/=>"tata"'
- domPatch2IHM(<patch 1>, <patch 2> [,<patch N>])
-
convert a list of patches in DOM format (internal Data;;Deep format) into a IHM format. Mainly used to convert the compare result (format dom)
ARGS: a list of <patch in dom format>
Return a list of patches in IHM mode IHM format is not convertible
EX:
domPatch2IHM
($patch1) returns '"toto" changed in "tata" from @0$%a into @0$%a - patternText2Dom(<text pattern>)
-
convert pattern scalar string to the array of element to be used by search(), path()
<pattern> is an array of type description to match <max occ.> optional argument to limit the number of results if undef all results are returned if 1 first one is returned
Return an array list of splited element of the <pattern> for usage
EX: patternText2Dom( '?@' );
Return ['?@'] patternText2Dom( '%r' ); Return '%', r'] patternText2Dom( '@3%r' ); Return ['@',3,'%','r'] patternText2Dom( '@2=3' ); Return ['@',2,'=','3']
- textPatch2DOM(<text patch 1>, <text patch 2> [,<text patch N>])
-
convert a list of patches formatted in text (readable text format format) to a perl DOM format (man perldsc). Mainly used to convert the compare result (format dom)
ARGS: a list of <patch in text format>
Return a list of patches in dom mode
EX:
textPatch2DOM
( 'change(@0$%a,@0$%a)="toto"/=>"tata"', 'move(... ' )returns ( { action=>'change', path_orig=>['@0','$','%a'], path_dest=>['@0','$','%a'], val_orig=>"toto", val_dest=>"tata" }, { action=>'move', ... });