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', ... });