File Coverage

blib/lib/Data/ModeMerge.pm
Criterion Covered Total %
statement 179 196 91.3
branch 103 126 81.7
condition 55 67 82.0
subroutine 18 18 100.0
pod 9 10 90.0
total 364 417 87.2


line stmt bran cond sub pod time code
1             ## no critic: Modules::ProhibitAutomaticExportation
2             package Data::ModeMerge;
3              
4             our $AUTHORITY = 'cpan:PERLANCAR'; # AUTHORITY
5             our $DATE = '2021-08-15'; # DATE
6             our $DIST = 'Data-ModeMerge'; # DIST
7             our $VERSION = '0.360'; # VERSION
8              
9 31     31   1887182 use 5.010001;
  31         336  
10 31     31   138 use strict;
  31         62  
  31         725  
11 31     31   146 use warnings;
  31         48  
  31         962  
12              
13 31     31   11322 use Mo qw(build default);
  31         13281  
  31         133  
14              
15             require Exporter;
16             our @ISA = qw(Exporter);
17             our @EXPORT = qw(mode_merge);
18              
19             sub mode_merge {
20 133     133 1 85225 my ($l, $r, $config_vars) = @_;
21 133         474 my $mm = __PACKAGE__->new(config => $config_vars);
22 133         1053 $mm->merge($l, $r);
23             }
24              
25             has config => (is => "rw");
26              
27             # hash of modename => handler
28             has modes => (is => 'rw', default => sub { {} });
29              
30             has combine_rules => (is => 'rw');
31              
32             # merging process state
33             has path => (is => "rw", default => sub { [] });
34             has errors => (is => "rw", default => sub { [] });
35             has mem => (is => "rw", default => sub { {} }); # for handling circular refs. {key=>{res=>[...], todo=>[sub1, ...]}, ...}
36             has cur_mem_key => (is => "rw"); # for handling circular refs. instead of passing around this as argument, we put it here.
37              
38             sub _in($$) {
39 1680     1680   1628 state $load_dmp = do { require Data::Dmp };
  10         61  
40 1680         2098 my ($self, $needle, $haystack) = @_;
41 1680 100       2350 return 0 unless defined($needle);
42 1679         1761 my $r1 = ref($needle);
43 1679 100       1996 my $f1 = $r1 ? Data::Dmp::dmp($needle) : undef;
44 1679         2367 for (@$haystack) {
45 2577         2553 my $r2 = ref($_);
46 2577 100 100     5272 next if $r1 xor $r2;
47 2572 100 100     3355 return 1 if $r2 && $f1 eq Data::Dmp::dmp($_);
48 2567 100 100     6777 return 1 if !$r2 && $needle eq $_;
49             }
50 1318         3117 0;
51             }
52              
53             sub BUILD {
54 330     330 0 167045 require Data::ModeMerge::Config;
55              
56 330         707 my ($self, $args) = @_;
57              
58 330 100       734 if ($self->config) {
59             # some sanity checks
60 107         511 my $is_hashref = ref($self->config) eq 'HASH';
61 107 50 33     514 die "config must be a hashref or a Data::ModeMerge::Config" unless
62             $is_hashref || UNIVERSAL::isa($self->config, "Data::ModeMerge::Config");
63 107 50       207 $self->config(Data::ModeMerge::Config->new(%{ $self->config })) if $is_hashref;
  107         194  
64             } else {
65 223         1410 $self->config(Data::ModeMerge::Config->new);
66             }
67              
68 330         9777 for (qw(NORMAL KEEP ADD CONCAT SUBTRACT DELETE)) {
69 1980         9567 $self->register_mode($_);
70             }
71              
72 330 50       1995 if (!$self->combine_rules) {
73 330         8381 $self->combine_rules({
74             # "left + right" => [which mode to use, which mode after merge]
75             'ADD+ADD' => ['ADD' , 'ADD' ],
76             #'ADD+CONCAT' => undef,
77             'ADD+DELETE' => ['DELETE' , 'DELETE'],
78             #'ADD+KEEP' => undef,
79             'ADD+NORMAL' => ['NORMAL' , 'NORMAL'],
80             'ADD+SUBTRACT' => ['SUBTRACT', 'ADD' ],
81              
82             #'CONCAT+ADD' => undef,
83             'CONCAT+CONCAT' => ['CONCAT' , 'CONCAT'],
84             'CONCAT+DELETE' => ['DELETE' , 'DELETE'],
85             #'CONCAT+KEEP' => undef,
86             'CONCAT+NORMAL' => ['NORMAL' , 'NORMAL'],
87             #'CONCAT+SUBTRACT' => undef,
88              
89             'DELETE+ADD' => ['NORMAL' , 'ADD' ],
90             'DELETE+CONCAT' => ['NORMAL' , 'CONCAT' ],
91             'DELETE+DELETE' => ['DELETE' , 'DELETE' ],
92             'DELETE+KEEP' => ['NORMAL' , 'KEEP' ],
93             'DELETE+NORMAL' => ['NORMAL' , 'NORMAL' ],
94             'DELETE+SUBTRACT' => ['NORMAL' , 'SUBTRACT'],
95              
96             'KEEP+ADD' => ['KEEP', 'KEEP'],
97             'KEEP+CONCAT' => ['KEEP', 'KEEP'],
98             'KEEP+DELETE' => ['KEEP', 'KEEP'],
99             'KEEP+KEEP' => ['KEEP', 'KEEP'],
100             'KEEP+NORMAL' => ['KEEP', 'KEEP'],
101             'KEEP+SUBTRACT' => ['KEEP', 'KEEP'],
102              
103             'NORMAL+ADD' => ['ADD' , 'NORMAL'],
104             'NORMAL+CONCAT' => ['CONCAT' , 'NORMAL'],
105             'NORMAL+DELETE' => ['DELETE' , 'NORMAL'],
106             'NORMAL+KEEP' => ['NORMAL' , 'KEEP' ],
107             'NORMAL+NORMAL' => ['NORMAL' , 'NORMAL'],
108             'NORMAL+SUBTRACT' => ['SUBTRACT', 'NORMAL'],
109              
110             'SUBTRACT+ADD' => ['SUBTRACT', 'SUBTRACT'],
111             #'SUBTRACT+CONCAT' => undef,
112             'SUBTRACT+DELETE' => ['DELETE' , 'DELETE' ],
113             #'SUBTRACT+KEEP' => undef,
114             'SUBTRACT+NORMAL' => ['NORMAL' , 'NORMAL' ],
115             'SUBTRACT+SUBTRACT' => ['ADD' , 'SUBTRACT'],
116             });
117             }
118             }
119              
120             sub push_error {
121 89     89 1 231 my ($self, $errmsg) = @_;
122 89         113 push @{ $self->errors }, [[@{ $self->path }], $errmsg];
  89         150  
  89         442  
123 89         541 return;
124             }
125              
126             sub register_mode {
127 1980     1980 1 3127 my ($self, $name0) = @_;
128 1980         2229 my $obj;
129 1980 50       9148 if (ref($name0)) {
    50          
    50          
130 0         0 my $obj = $name0;
131             } elsif ($name0 =~ /^\w+(::\w+)+$/) {
132 0         0 eval "require $name0; \$obj = $name0->new";
133 0 0       0 die "Can't load module $name0: $@" if $@;
134             } elsif ($name0 =~ /^\w+$/) {
135 1980         3488 my $modname = "Data::ModeMerge::Mode::$name0";
136 1980         104883 eval "require $modname; \$obj = $modname->new";
137 1980 50       25845 die "Can't load module $modname: $@" if $@;
138             } else {
139 0         0 die "Invalid mode name $name0";
140             }
141 1980         3948 my $name = $obj->name;
142 1980 50       4301 die "Mode $name already registered" if $self->modes->{$name};
143 1980         12024 $obj->merger($self);
144 1980         6016 $self->modes->{$name} = $obj;
145             }
146              
147             sub check_prefix {
148 17     17 1 821 my ($self, $hash_key) = @_;
149 17 100       68 die "Hash key not a string" if ref($hash_key);
150 15         39 my $dis = $self->config->disable_modes;
151 15 50 66     110 if (defined($dis) && ref($dis) ne 'ARRAY') {
152 0         0 $self->push_error("Invalid config value `disable_modes`: must be an array");
153 0         0 return;
154             }
155 15         18 for my $mh (sort { $b->precedence_level <=> $a->precedence_level }
  148         217  
156 90   100     270 grep { !$dis || !$self->_in($_->name, $dis) }
157 15         43 values %{ $self->modes }) {
158 75 100       358 if ($mh->check_prefix($hash_key)) {
159 5         39 return $mh->name;
160             }
161             }
162 10         67 return;
163             }
164              
165             sub check_prefix_on_hash {
166 7     7 1 82 my ($self, $hash) = @_;
167 7 100       31 die "Not a hash" unless ref($hash) eq 'HASH';
168 5         7 my $res = 0;
169 5         14 for (keys %$hash) {
170 6 100       13 do { $res++; last } if $self->check_prefix($_);
  2         5  
  2         3  
171             }
172 5         17 $res;
173             }
174              
175             sub add_prefix {
176 36     36 1 11333 my ($self, $hash_key, $mode) = @_;
177 36 100       99 die "Hash key not a string" if ref($hash_key);
178 34         112 my $dis = $self->config->disable_modes;
179 34 50 33     270 if (defined($dis) && ref($dis) ne 'ARRAY') {
180 0         0 die "Invalid config value `disable_modes`: must be an array";
181             }
182 34 50 33     91 if ($dis && $self->_in($mode, $dis)) {
183 0         0 $self->push_error("Can't add prefix for currently disabled mode `$mode`");
184 0         0 return $hash_key;
185             }
186 34 50       103 my $mh = $self->modes->{$mode} or die "Unknown mode: $mode";
187 34         317 $mh->add_prefix($hash_key);
188             }
189              
190             sub remove_prefix {
191 2293     2293 1 4360 my ($self, $hash_key) = @_;
192 2293 100       3368 die "Hash key not a string" if ref($hash_key);
193 2291         3457 my $dis = $self->config->disable_modes;
194 2291 100 100     11061 if (defined($dis) && ref($dis) ne 'ARRAY') {
195 1         14 die "Invalid config value `disable_modes`: must be an array";
196             }
197 2290         2450 for my $mh (sort { $b->precedence_level <=> $a->precedence_level }
  21355         31546  
198 13740   100     33540 grep { !$dis || !$self->_in($_->name, $dis) }
199 2290         3580 values %{ $self->modes }) {
200 11372 100       48462 if ($mh->check_prefix($hash_key)) {
201 912         5890 my $r = $mh->remove_prefix($hash_key);
202 912 100       1444 if (wantarray) { return ($r, $mh->name) }
  909         1654  
203 3         8 else { return $r }
204             }
205             }
206 1378 100       6371 if (wantarray) { return ($hash_key, $self->config->default_mode) }
  1377         2214  
207 1         2 else { return $hash_key }
208             }
209              
210             sub remove_prefix_on_hash {
211 3     3 1 67 my ($self, $hash) = @_;
212 3 100       34 die "Not a hash" unless ref($hash) eq 'HASH';
213 1         5 for (keys %$hash) {
214 4         6 my $old = $_;
215 4         7 $_ = $self->remove_prefix($_);
216 4 100       7 next unless $old ne $_;
217             die "Conflict when removing prefix on hash: $old -> $_ but $_ already exists"
218 3 50       7 if exists $hash->{$_};
219 3         5 $hash->{$_} = $hash->{$old};
220 3         5 delete $hash->{$old};
221             }
222 1         7 $hash;
223             }
224              
225             sub merge {
226 323     323 1 4728 my ($self, $l, $r) = @_;
227 323         826 $self->path([]);
228 323         1839 $self->errors([]);
229 323         1602 $self->mem({});
230 323         1627 $self->cur_mem_key(undef);
231 323         1099 my ($key, $res, $backup) = $self->_merge(undef, $l, $r);
232             {
233 322         528 success => !@{ $self->errors },
234 322         1510 error => (@{ $self->errors } ?
235             join(", ",
236 89         374 map { sprintf("/%s: %s", join("/", @{ $_->[0] }), $_->[1]) }
  89         829  
237 322 100       461 @{ $self->errors }) : ''),
  89         449  
238             result => $res,
239             backup => $backup,
240             };
241             }
242              
243             # handle circular refs: process todo's
244             sub _process_todo {
245 755     755   1034 my ($self) = @_;
246 755 100       1208 if ($self->cur_mem_key) {
247 746         2404 for my $mk (keys %{ $self->mem }) {
  746         1106  
248 1029         5233 my $res = $self->mem->{$mk}{res};
249 1029 100 100     5028 if (defined($res) && @{ $self->mem->{$mk}{todo} }) {
  541         776  
250             #print "DEBUG: processing todo for mem<$mk>\n";
251 2         10 for (@{ $self->mem->{$mk}{todo} }) {
  2         3  
252 2         13 $_->(@$res);
253 2 50       3 return if @{ $self->errors };
  2         3  
254             }
255 2         14 $self->mem->{$mk}{todo} = [];
256             }
257             }
258             }
259             }
260              
261             sub _merge {
262 776     776   1403 my ($self, $key, $l, $r, $mode) = @_;
263 776         1422 my $c = $self->config;
264 776   66     3029 $mode //= $c->default_mode;
265              
266 776         1439 my $mh = $self->modes->{$mode};
267 776 50       3833 die "Can't find handler for mode $mode" unless $mh;
268              
269             # determine which merge method we will call
270 776         1142 my $rl = ref($l);
271 776         913 my $rr = ref($r);
272 776 50       1845 my $tl = $rl eq 'HASH' ? 'HASH' : $rl eq 'ARRAY' ? 'ARRAY' : $rl eq 'CODE' ? 'CODE' : !$rl ? 'SCALAR' : '';
    100          
    100          
    100          
273 776 50       1553 my $tr = $rr eq 'HASH' ? 'HASH' : $rr eq 'ARRAY' ? 'ARRAY' : $rr eq 'CODE' ? 'CODE' : !$rr ? 'SCALAR' : '';
    100          
    100          
    100          
274 776 50       1231 if (!$tl) { $self->push_error("Unknown type in left side: $rl"); return }
  0         0  
  0         0  
275 776 50       1127 if (!$tr) { $self->push_error("Unknown type in right side: $rr"); return }
  0         0  
  0         0  
276 776 100 100     1372 if (!$c->allow_create_array && $tl ne 'ARRAY' && $tr eq 'ARRAY') {
      66        
277 5         46 $self->push_error("Not allowed to create array"); return;
  5         22  
278             }
279 771 100 100     2937 if (!$c->allow_create_hash && $tl ne 'HASH' && $tr eq 'HASH') {
      66        
280 5         43 $self->push_error("Not allowed to create hash"); return;
  5         10  
281             }
282 766 100 100     2821 if (!$c->allow_destroy_array && $tl eq 'ARRAY' && $tr ne 'ARRAY') {
      100        
283 5         51 $self->push_error("Not allowed to destroy array"); return;
  5         12  
284             }
285 761 100 66     2781 if (!$c->allow_destroy_hash && $tl eq 'HASH' && $tr ne 'HASH') {
      100        
286 5         48 $self->push_error("Not allowed to destroy hash"); return;
  5         12  
287             }
288 756         2831 my $meth = "merge_${tl}_${tr}";
289 756 50       2794 if (!$mh->can($meth)) { $self->push_error("No merge method found for $tl + $tr (mode $mode)"); return }
  0         0  
  0         0  
290              
291             #$self->_process_todo;
292             # handle circular refs: add to todo if necessary
293 756         1012 my $memkey;
294 756 100 100     1704 if ($rl || $rr) {
295 406 100       2024 $memkey = sprintf "%s%s %s%s %s %s",
    100          
    100          
    100          
    100          
    100          
296             (defined($l) ? ($rl ? 2 : 1) : 0),
297             (defined($l) ? "$l" : ''),
298             (defined($r) ? ($rr ? 2 : 1) : 0),
299             (defined($r) ? "$r" : ''),
300             $mode,
301             $self->config;
302             #print "DEBUG: number of keys in mem = ".scalar(keys %{ $self->mem })."\n";
303             #print "DEBUG: mem keys = \n".join("", map { " $_\n" } keys %{ $self->mem }) if keys %{ $self->mem };
304             #print "DEBUG: calculating memkey = <$memkey>\n";
305             }
306 756 100       3356 if ($memkey) {
307 406 100       729 if (exists $self->mem->{$memkey}) {
308 3         18 $self->_process_todo;
309 3 50       7 if (defined $self->mem->{$memkey}{res}) {
310             #print "DEBUG: already calculated, using cached result\n";
311 0         0 return @{ $self->mem->{$memkey}{res} };
  0         0  
312             } else {
313             #print "DEBUG: detecting circular\n";
314 3         30 return ($key, undef, undef, 1);
315             }
316             } else {
317 403         2983 $self->mem->{$memkey} = {res=>undef, todo=>[]};
318 403         2561 $self->cur_mem_key($memkey);
319             #print "DEBUG: invoking ".$mh->name."'s $meth(".dmp($key).", ".dmp($l).", ".dmp($r).")\n";
320 403         2000 my ($newkey, $res, $backup) = $mh->$meth($key, $l, $r);
321             #print "DEBUG: setting res for mem<$memkey>\n";
322 402         1376 $self->mem->{$memkey}{res} = [$newkey, $res, $backup];
323 402         2299 $self->_process_todo;
324 402         2996 return ($newkey, $res, $backup);
325             }
326             } else {
327 350         689 $self->_process_todo;
328             #print "DEBUG: invoking ".$mh->name."'s $meth(".dmp($key).", ".dmp($l).", ".dmp($r).")\n";
329 350         958 return $mh->$meth($key, $l, $r);
330             }
331             }
332              
333             # returns 1 if a is included in b (e.g. [user => "jajang"] in included in [user
334             # => jajang => "quota"], but [user => "paijo"] is not)
335             sub _path_is_included {
336 5     5   65 my ($self, $p1, $p2) = @_;
337 5         7 my $res = 1;
338 5         21 for my $i (0..@$p1-1) {
339 6 100 66     32 do { $res = 0; last } if !defined($p2->[$i]) || $p1->[$i] ne $p2->[$i];
  2         4  
  2         4  
340             }
341             #print "_path_is_included([".join(", ", @$p1)."], [".join(", ", @$p2)."])? $res\n";
342 5         24 $res;
343             }
344              
345             1;
346             # ABSTRACT: Merge two nested data structures, with merging modes and options
347              
348             __END__
349              
350             =pod
351              
352             =encoding UTF-8
353              
354             =head1 NAME
355              
356             Data::ModeMerge - Merge two nested data structures, with merging modes and options
357              
358             =head1 VERSION
359              
360             This document describes version 0.360 of Data::ModeMerge (from Perl distribution Data-ModeMerge), released on 2021-08-15.
361              
362             =head1 SYNOPSIS
363              
364             use Data::ModeMerge;
365              
366             my $hash1 = { a=>1, c=>1, d=>{ da =>[1]} };
367             my $hash2 = { a=>2, "-c"=>2, d=>{"+da"=>[2]} };
368              
369              
370             # if you want Data::ModeMerge to behave like many other merging
371             # modules (e.g. Hash::Merge or Data::Merger), turn off modes
372             # (prefix) parsing and options key parsing.
373              
374             my $mm = Data::ModeMerge->new(config => {parse_prefix=>0, options_key=>undef});
375             my $res = $mm->merge($hash1, $hash2);
376             die $res->{error} if $res->{error};
377             # $res->{result} -> { a=>2, c=>1, "-c"=>2, d=>{da=>[1], "+da"=>[2]} }
378              
379              
380             # otherwise Data::ModeMerge will parse prefix as well as options
381             # key
382              
383             my $res = $mm->merge($hash1, $hash2);
384             die $res->{error} if $res->{error};
385             # $res->{result} -> { a=>2, c=>-1, d=>{da=>[1,2]} }
386              
387             $res = $merge({ a =>1, { a2 =>1, ""=>{parse_prefix=>0}},
388             {".a"=>2, {".a2"=>2 }});
389             # $res->{result} -> { a=>12, {a2=>1, ".a2"=>2} }, parse_prefix is turned off in just the subhash
390              
391              
392             # procedural interface
393              
394             my $res = mode_merge($hash1, $hash2, {allow_destroy_hash=>0});
395              
396             =head1 DESCRIPTION
397              
398             There are already several modules on CPAN to do recursive data
399             structure merging, like L<Data::Merger> and
400             L<Hash::Merge>. C<Data::ModeMerge> differs in that it offers merging
401             "modes" and "options". It provides greater flexibility on what the
402             result of a merge between two data should/can be. This module may or
403             may not be what you need.
404              
405             One application of this module is in handling configuration. Often
406             there are multiple levels of configuration, e.g. in your typical Unix
407             command-line program there are system-wide config file in /etc,
408             per-user config file under ~/, and command-line options. It's
409             convenient programatically to load each of those in a hash and then
410             merge system-wide hash with the per-user hash, and then merge the
411             result with the command-line hash to get the a single hash as the
412             final configuration. Your program can from there on deal with this
413             just one hash instead of three.
414              
415             In a typical merging process between two hashes (left-side and
416             right-side), when there is a conflicting key, then the right-side key
417             will override the left-side. This is usually the desired behaviour in
418             our said program as the system-wide config is there to provide
419             defaults, and the per-user config (and the command-line arguments)
420             allow a user to override those defaults.
421              
422             But suppose that the user wants to I<unset> a certain configuration
423             setting that is defined by the system-wide config? She can't do that
424             unless she edits the system-wide config (in which she might need admin
425             rights), or the program allows the user to disregard the system-wide
426             config. The latter is usually what's implemented by many Unix
427             programs, e.g. the C<-noconfig> command-line option in C<mplayer>. But
428             this has two drawbacks: a slightly added complexity in the program
429             (need to provide a special, extra comand-line option) and the user
430             loses all the default settings in the system-wide config. What she
431             needed in the first place was to just unset I<a single setting> (a
432             single key-value pair of the hash).
433              
434             L<Data::ModeMerge> comes to the rescue. It provides a so-called
435             C<DELETE mode>.
436              
437             mode_merge({foo=>1, bar=>2}, {"!foo"=>undef, bar=>3, baz=>1});
438              
439             will result ini:
440              
441             {bar=>3, baz=>1}
442              
443             The C<!> prefix tells Data::ModeMerge to do a DELETE mode merging. So
444             the final result will lack the C<foo> key.
445              
446             On the other hand, what if the system admin wants to I<protect> a
447             certain configuration setting from being overriden by the user or the
448             command-line? This is useful in a hosting or other retrictive
449             environment where we want to limit users' freedom to some levels. This
450             is possible via the KEEP mode merging.
451              
452             mode_merge({"^bar"=>2, "^baz"=>1}, {bar=>3, "!baz"=>0, qux=>7});
453              
454             will result in:
455              
456             {"^bar"=>2, "^baz"=>1, qux=>7}
457              
458             effectively protecting C<bar> and C<baz> from being
459             overriden/deleted/etc.
460              
461             Aside from the two mentioned modes, there are also a few others
462             available by default: ADD (prefix C<+>), CONCAT (prefix C<.>),
463             SUBTRACT (prefix C<->), as well as the plain ol' NORMAL/override
464             (optional prefix C<*>).
465              
466             You can add other modes by writing a mode handler module.
467              
468             You can change the default prefixes for each mode if you want. You can
469             disable each mode individually.
470              
471             You can default to always using a certain mode, like the NORMAL mode,
472             and ignore all the prefixes, in which case Data::ModeMerge will behave
473             like most other merge modules.
474              
475             There are a few other options like whether or not the right side is
476             allowed a "change the structure" of the left side (e.g. replacing a
477             scalar with an array/hash, destroying an existing array/hash with
478             scalar), maximum length of scalar/array/hash, etc.
479              
480             You can change default mode, prefixes, disable/enable modes, etc on a
481             per-hash basis using the so-called B<options key>. See the B<OPTIONS
482             KEY> section for more details.
483              
484             This module can handle (though not all possible cases)
485             circular/recursive references.
486              
487             =for Pod::Coverage ^(BUILD)$
488              
489             =head1 MERGING PREFIXES AND YOUR DATA
490              
491             Merging with this module means you need to be careful when your hash
492             keys might contain one of the mode prefixes characters by accident,
493             because it will trigger the wrong merge mode and moreover the prefix
494             characters will be B<stripped> from the final result (unless you
495             configure the module not to do so).
496              
497             A rather common case is when you have regexes in your hash
498             keys. Regexes often begins with C<^>, which coincidentally is a prefix
499             for the KEEP mode. Or perhaps you have dot filenames as hash keys,
500             where it clashes with the CONCAT mode. Or perhaps shell wildcards,
501             where C<*> is also used as the prefix for NORMAL mode.
502              
503             To avoid clashes, you can either:
504              
505             =over 4
506              
507             =item * exclude the keys using
508             C<exclude_merge>/C<include_merge>/C<exclude_parse>/C<include_parse>
509             config settings
510              
511             =item * turn off some modes which you don't want via the
512             C<disable_modes> config
513              
514             =item * change the prefix for that mode so that it doesn't clash with
515             your data via the C<set_prefix> config
516              
517             =item * disable prefix parsing altogether via setting C<parse_prefix>
518             config to 0
519              
520             =back
521              
522             You can do this via the configuration, or on a per-hash basis, using
523             the options key.
524              
525             See L<Data::ModeMerge::Config> for more details on configuration.
526              
527             =head1 OPTIONS KEY
528              
529             Aside from merging mode prefixes, you also need to watch out if your
530             hash contains a "" (empty string) key, because by default this is the
531             key used for options key.
532              
533             Options key are used to specify configuration on a per-hash basis.
534              
535             If your hash keys might contain "" keys which are not meant to be an
536             options key, you can either:
537              
538             =over 4
539              
540             =item * change the name of the key for options key, via setting
541             C<options_key> config to another string.
542              
543             =item * turn off options key mechanism,
544             by setting C<options_key> config to undef.
545              
546             =back
547              
548             See L<Data::ModeMerge::Config> for more details about options key.
549              
550             =head1 MERGING MODES
551              
552             =head2 NORMAL (optional '*' prefix on left/right side)
553              
554             mode_merge({ a =>11, b=>12}, { b =>22, c=>23}); # {a=>11, b=>22, c=>23}
555             mode_merge({"*a"=>11, b=>12}, {"*b"=>22, c=>23}); # {a=>11, b=>22, c=>23}
556              
557             =head2 ADD ('+' prefix on the right side)
558              
559             mode_merge({i=>3}, {"+i"=>4, "+j"=>1}); # {i=>7, j=>1}
560             mode_merge({a=>[1]}, {"+a"=>[2, 3]}); # {a=>[1, 2, 3]}
561              
562             Additive merge on hashes will be treated like a normal merge.
563              
564             =head2 CONCAT ('.' prefix on the right side)
565              
566             mode_merge({i=>3}, {".i"=>4, ".j"=>1}); # {i=>34, j=>1}
567              
568             Concative merge on arrays will be treated like additive merge.
569              
570             =head2 SUBTRACT ('-' prefix on the right side)
571              
572             mode_merge({i=>3}, {"-i"=>4}); # {i=>-1}
573             mode_merge({a=>["a","b","c"]}, {"-a"=>["b"]}); # {a=>["a","c"]}
574              
575             Subtractive merge on hashes behaves like a normal merge, except that
576             each key on the right-side hash without any prefix will be assumed to
577             have a DELETE prefix, i.e.:
578              
579             mode_merge({h=>{a=>1, b=>1}}, {-h=>{a=>2, "+b"=>2, c=>2}})
580              
581             is equivalent to:
582              
583             mode_merge({h=>{a=>1, b=>1}}, {h=>{"!a"=>2, "+b"=>2, "!c"=>2}})
584              
585             and will merge to become:
586              
587             {h=>{b=>3}}
588              
589             =head2 DELETE ('!' prefix on the right side)
590              
591             mode_merge({x=>WHATEVER}, {"!x"=>WHATEVER}); # {}
592              
593             =head2 KEEP ('^' prefix on the left/right side)
594              
595             If you add '^' prefix on the left side, it will be protected from
596             being replaced/deleted/etc.
597              
598             mode_merge({'^x'=>WHATEVER1}, {"x"=>WHATEVER2}); # {x=>WHATEVER1}
599              
600             For hashes, KEEP mode means that all keys on the left side will not be
601             replaced/modified/deleted, *but* you can still add more keys from the
602             right side hash.
603              
604             mode_merge({a=>1, b=>2, c=>3},
605             {a=>4, '^c'=>1, d=>5},
606             {default_mode=>'KEEP'});
607             # {a=>1, b=>2, c=>3, d=>5}
608              
609             Multiple prefixes on the right side is allowed, where the merging will
610             be done by precedence level (highest first):
611              
612             mode_merge({a=>[1,2]}, {'-a'=>[1], '+a'=>[10]}); # {a=>[2,10]}
613              
614             but not on the left side:
615              
616             mode_merge({a=>1, '^a'=>2}, {a=>3}); # error!
617              
618             Precedence levels (from highest to lowest):
619              
620             KEEP
621             NORMAL
622             SUBTRACT
623             CONCAT ADD
624             DELETE
625              
626             =head1 CREATING AND USING YOUR OWN MODE
627              
628             Let's say you want to add a mode named C<FOO>. It will have the prefix
629             '?'.
630              
631             Create the mode handler class,
632             e.g. C<Data::ModeMerge::Mode::FOO>. It's probably best to subclass
633             from L<Data::ModeMerge::Mode::Base>. The class must implement name(),
634             precedence_level(), default_prefix(), default_prefix_re(), and
635             merge_{SCALAR,ARRAY,HASH}_{SCALAR,ARRAY,HASH}(). For more details, see
636             the source code of Base.pm and one of the mode handlers
637             (e.g. NORMAL.pm).
638              
639             To use the mode, register it:
640              
641             my $mm = Data::ModeMerge->new;
642             $mm->register_mode('FOO');
643              
644             This will require C<Data::ModeMerge::Mode::FOO>. After that, define
645             the operations against other modes:
646              
647             # if there's FOO on the left and NORMAL on the right, what mode
648             # should the merge be done in (FOO), and what the mode should be
649             # after the merge? (NORMAL)
650             $mm->combine_rules->{"FOO+NORMAL"} = ["FOO", "NORMAL"];
651              
652             # we don't define FOO+ADD
653              
654             $mm->combine_rules->{"FOO+KEEP"} = ["KEEP", "KEEP"];
655              
656             # and so on
657              
658             =head1 FUNCTIONS
659              
660             =head2 mode_merge($l, $r[, $config_vars])
661              
662             A non-OO wrapper for merge() method. Exported by default. See C<merge>
663             method for more details.
664              
665             =head1 ATTRIBUTES
666              
667             =head2 config
668              
669             A hashref for config. See L<Data::ModeMerge::Config>.
670              
671             =head2 modes
672              
673             =head2 combine_rules
674              
675             =head2 path
676              
677             =head2 errors
678              
679             =head2 mem
680              
681             =head2 cur_mem_key
682              
683             =head1 METHODS
684              
685             For typical usage, you only need merge().
686              
687             =head2 push_error($errmsg)
688              
689             Used by mode handlers to push error when doing merge. End users
690             normally should not need this.
691              
692             =head2 register_mode($name_or_package_or_obj)
693              
694             Register a mode. Will die if mode with the same name already exists.
695              
696             =head2 check_prefix($hash_key)
697              
698             Check whether hash key has prefix for certain mode. Return the name of
699             the mode, or undef if no prefix is detected.
700              
701             =head2 check_prefix_on_hash($hash)
702              
703             This is like C<check_prefix> but performed on every key of the
704             specified hash. Return true if any of the key contain a merge prefix.
705              
706             =head2 add_prefix($hash_key, $mode)
707              
708             Return hash key with added prefix with specified mode. Log merge error
709             if mode is unknown or is disabled.
710              
711             =head2 remove_prefix($hash_key)
712              
713             Return hash key will any prefix removed.
714              
715             =head2 remove_prefix_on_hash($hash)
716              
717             This is like C<remove_prefix> but performed on every key of the
718             specified hash. Return the same hash but with prefixes removed.
719              
720             =head2 merge($l, $r)
721              
722             Merge two nested data structures. Returns the result hash: {
723             success=>0|1, error=>'...', result=>..., backup=>... }. The 'error'
724             key is set to contain an error message if there is an error. The merge
725             result is in the 'result' key. The 'backup' key contains replaced
726             elements from the original hash/array.
727              
728             =head1 FAQ
729              
730             =head2 What is this module good for? Why would I want to use this module instead of the other hash merge modules?
731              
732             If you just need to (deeply) merge two hashes, chances are you do not
733             need this module. Use, for example, L<Hash::Merge>, which is also
734             flexible enough because it allows you to set merging behaviour for
735             merging different types (e.g. SCALAR vs ARRAY).
736              
737             You might need this module if your data is recursive/self-referencing
738             (which, last time I checked, is not handled well by Hash::Merge), or
739             if you want to be able to merge differently (i.e. apply different
740             merging B<modes>) according to different prefixes on the key, or
741             through special key. In other words, you specify merging modes from
742             inside the hash itself.
743              
744             I originally wrote Data::ModeMerge this for L<Data::Schema> and
745             L<Config::Tree>. I want to reuse the "parent" schema (or
746             configuration) in more ways other than just override conflicting
747             keys. I also want to be able to allow the parent to protect certain
748             keys from being overriden. I found these two features lacking in all
749             merging modules that I've evaluated prior to writing Data::ModeMerge.
750              
751             =head1 HOMEPAGE
752              
753             Please visit the project's homepage at L<https://metacpan.org/release/Data-ModeMerge>.
754              
755             =head1 SOURCE
756              
757             Source repository is at L<https://github.com/perlancar/perl-Data-ModeMerge>.
758              
759             =head1 BUGS
760              
761             Please report any bugs or feature requests on the bugtracker website L<https://rt.cpan.org/Public/Dist/Display.html?Name=Data-ModeMerge>
762              
763             When submitting a bug or request, please include a test-file or a
764             patch to an existing test-file that illustrates the bug or desired
765             feature.
766              
767             =head1 SEE ALSO
768              
769             L<Data::ModeMerge::Config>
770              
771             Other merging modules on CPAN: L<Data::Merger> (from Data-Utilities),
772             L<Hash::Merge>, L<Hash::Merge::Simple>
773              
774             L<Data::Schema> and L<Config::Tree> (among others, two modules which
775             use Data::ModeMerge)
776              
777             =head1 AUTHOR
778              
779             perlancar <perlancar@cpan.org>
780              
781             =head1 CONTRIBUTORS
782              
783             =for stopwords Steven Haryanto (on PC)
784              
785             =over 4
786              
787             =item *
788              
789             Steven Haryanto (on PC) <stevenharyanto@gmail.com>
790              
791             =item *
792              
793             Steven Haryanto <steven@masterweb.net>
794              
795             =back
796              
797             =head1 COPYRIGHT AND LICENSE
798              
799             This software is copyright (c) 2021, 2016, 2015, 2013, 2012, 2011, 2010 by perlancar <perlancar@cpan.org>.
800              
801             This is free software; you can redistribute it and/or modify it under
802             the same terms as the Perl 5 programming language system itself.
803              
804             =cut