File Coverage

blib/lib/Data/ModeMerge/Mode/Base.pm
Criterion Covered Total %
statement 344 365 94.2
branch 181 196 92.3
condition 113 132 85.6
subroutine 21 26 80.7
pod 7 10 70.0
total 666 729 91.3


line stmt bran cond sub pod time code
1             package Data::ModeMerge::Mode::Base;
2              
3             our $DATE = '2016-02-25'; # DATE
4             our $VERSION = '0.33'; # VERSION
5              
6 31     31   17417 use 5.010;
  31         81  
7 31     31   115 use strict;
  31         36  
  31         567  
8 31     31   100 use warnings;
  31         43  
  31         661  
9              
10 31     31   96 use Data::Dmp;
  31         40  
  31         1706  
11              
12             #use Log::Any '$log';
13 31     31   136 use Mo qw(build default);
  31         49  
  31         164  
14              
15             #use Data::Clone qw/clone/;
16              
17             has merger => (is => 'rw');
18             has prefix => (is => 'rw');
19             has prefix_re => (is => 'rw');
20             has check_prefix_sub => (is => 'rw');
21             has add_prefix_sub => (is => 'rw');
22             has remove_prefix_sub => (is => 'rw');
23              
24             sub name {
25 0     0 1 0 die "Subclass must provide name()";
26             }
27              
28             sub precedence_level {
29 0     0 1 0 die "Subclass must provide precedence_level()";
30             }
31              
32             sub default_prefix {
33 0     0 1 0 die "Subclass must provide default_prefix()";
34             }
35              
36             sub default_prefix_re {
37 0     0 1 0 die "Subclass must provide default_prefix_re()";
38             }
39              
40             sub BUILD {
41 1980     1980 0 67439 my ($self) = @_;
42 1980         4988 $self->prefix($self->default_prefix);
43 1980         10253 $self->prefix_re($self->default_prefix_re);
44             }
45              
46             sub check_prefix {
47 11482     11482 1 20881 my ($self, $hash_key) = @_;
48 11482 50       14794 if ($self->check_prefix_sub) {
49 0         0 $self->check_prefix_sub->($hash_key);
50             } else {
51 11482         34484 $hash_key =~ $self->prefix_re;
52             }
53             }
54              
55             sub add_prefix {
56 101     101 1 930 my ($self, $hash_key) = @_;
57 101 100       310 if ($self->add_prefix_sub) {
58 4         20 $self->add_prefix_sub->($hash_key);
59             } else {
60 97         466 $self->prefix . $hash_key;
61             }
62             }
63              
64             sub remove_prefix {
65 942     942 1 3468 my ($self, $hash_key) = @_;
66 942 100       1640 if ($self->remove_prefix_sub) {
67 10         38 $self->remove_prefix_sub->($hash_key);
68             } else {
69 932         3452 my $re = $self->prefix_re;
70 932         4613 $hash_key =~ s/$re//;
71 932         2111 $hash_key;
72             }
73             }
74              
75             sub merge_ARRAY_ARRAY {
76 13     13 0 27 my ($self, $key, $l, $r) = @_;
77 13         28 my $mm = $self->merger;
78 13         53 my $c = $mm->config;
79 13 100       82 return $self->merge_SCALAR_SCALAR($key, $l, $r) unless $c->recurse_array;
80 4 50 33     31 return if $c->wanted_path && !$mm->_path_is_included($mm->path, $c->wanted_path);
81              
82 4         22 my @res;
83             my @backup;
84 4         5 my $la = @$l;
85 4         12 my $lb = @$r;
86 4         6 push @{ $mm->path }, -1;
  4         8  
87 4 100       35 for my $i (0..($la > $lb ? $la : $lb)-1) {
88             #print "DEBUG: merge_A_A: #$i: a->[$i]=".Data::Dumper->new([$l->[$i]])->Indent(0)->Terse(1)->Dump.", b->[$i]=".Data::Dumper->new([$r->[$i]])->Indent(0)->Terse(1)->Dump."\n";
89 6         14 $mm->path->[-1] = $i;
90 6 100 66     60 if ($i < $la && $i < $lb) {
    50          
91 5         11 push @backup, $l->[$i];
92 5         12 my ($subnewkey, $subres, $subbackup, $is_circular) = $mm->_merge($i, $l->[$i], $r->[$i], $c->default_mode);
93 5 50       6 last if @{ $mm->errors };
  5         10  
94 5 50       32 if ($is_circular) {
95 0         0 push @res, undef;
96             #print "DEBUG: pushing todo to mem<".$mm->cur_mem_key.">\n";
97 0         0 push @{ $mm->mem->{ $mm->cur_mem_key }{todo} }, sub {
98 0     0   0 my ($subnewkey, $subres, $subbackup) = @_;
99             #print "DEBUG: Entering todo subroutine (i=$i)\n";
100 0         0 $res[$i] = $subres;
101             }
102 0         0 } else {
103 5         14 push @res, $subres;# if defined($newkey); = we allow DELETE on array?
104             }
105             } elsif ($i < $la) {
106 1         8 push @res, $l->[$i];
107             } else {
108 0         0 push @res, $r->[$i];
109             }
110             }
111 4         5 pop @{ $mm->path };
  4         12  
112 4         30 ($key, \@res, \@backup);
113             }
114              
115             sub _prefilter_hash {
116 18     18   63 my ($self, $h, $desc, $sub) = @_;
117 18         25 my $mm = $self->merger;
118              
119 18 100       65 if (ref($sub) ne 'CODE') {
120 3         12 $mm->push_error("$desc failed: filter must be a coderef");
121 3         4 return;
122             }
123              
124 15         18 my $res = {};
125 15         32 for (keys %$h) {
126 17         93 my @r = $sub->($_, $h->{$_});
127 17         97 while (my ($k, $v) = splice @r, 0, 2) {
128 21 100       37 next unless defined $k;
129 17 100       27 if (exists $res->{$k}) {
130 1         10 $mm->push_error("$desc failed; key conflict: ".
131             "$_ -> $k, but key $k already exists");
132 1         4 return;
133             }
134 16         52 $res->{$k} = $v;
135             }
136             }
137              
138 14         21 $res;
139             }
140              
141             # turn {[prefix]key => val, ...} into { key => [MODE, val], ...}, push
142             # error if there's conflicting key
143             sub _gen_left {
144 566     566   791 my ($self, $l, $mode, $esub, $ep, $ip, $epr, $ipr) = @_;
145 566         987 my $mm = $self->merger;
146 566         1849 my $c = $mm->config;
147              
148             #print "DEBUG: Entering _gen_left(".dmp($l).", $mode, ...)\n";
149              
150 566 100       1700 if ($c->premerge_pair_filter) {
151 11         45 $l = $self->_prefilter_hash($l, "premerge filter left hash",
152             $c->premerge_pair_filter);
153 11 100       15 return if @{ $mm->errors };
  11         19  
154             }
155              
156 562         1957 my $hl = {};
157 562 100       1012 if ($c->parse_prefix) {
158 553         2496 for (keys %$l) {
159 1171         1022 my $do_parse = 1;
160 1171 100 66     3872 $do_parse = 0 if $do_parse && $ep && $mm->_in($_, $ep);
      100        
161 1171 100 100     3548 $do_parse = 0 if $do_parse && $ip && !$mm->_in($_, $ip);
      66        
162 1171 100 100     3600 $do_parse = 0 if $do_parse && $epr && /$epr/;
      100        
163 1171 100 100     3390 $do_parse = 0 if $do_parse && $ipr && !/$ipr/;
      100        
164              
165 1171 100       1412 if ($do_parse) {
166 1128         934 my $old = $_;
167 1128         741 my $m2;
168 1128         2167 ($_, $m2) = $mm->remove_prefix($_);
169 1127 100 66     8687 next if $esub && !$esub->($_);
170 538 50 66     1335 if ($old ne $_ && exists($l->{$_})) {
171 0         0 $mm->push_error("Conflict when removing prefix on left-side ".
172             "hash key: $old -> $_ but $_ already exists");
173 0         0 return;
174             }
175 538         1630 $hl->{$_} = [$m2, $l->{$old}];
176             } else {
177 43 100 66     90 next if $esub && !$esub->($_);
178 41         118 $hl->{$_} = [$mode, $l->{$_}];
179             }
180             }
181             } else {
182 9         60 for (keys %$l) {
183 27 100 66     55 next if $esub && !$esub->($_);
184 21         175 $hl->{$_} = [$mode, $l->{$_}];
185             }
186             }
187              
188             #print "DEBUG: Leaving _gen_left, result = ".dmp($hl)."\n";
189 561         1030 $hl;
190             }
191              
192             # turn {[prefix]key => val, ...} into { key => {MODE=>val, ...}, ...},
193             # push error if there's conflicting key+MODE
194             sub _gen_right {
195 561     561   779 my ($self, $r, $mode, $esub, $ep, $ip, $epr, $ipr) = @_;
196 561         967 my $mm = $self->merger;
197 561         1792 my $c = $mm->config;
198              
199             #print "DEBUG: Entering _gen_right(".dmp($r).", $mode, ...)\n";
200              
201 561 100       1685 if ($c->premerge_pair_filter) {
202 7         32 $r = $self->_prefilter_hash($r, "premerge filter right hash",
203             $c->premerge_pair_filter);
204 7 50       6 return if @{ $mm->errors };
  7         35  
205             }
206              
207 561         2091 my $hr = {};
208 561 100       940 if ($c->parse_prefix) {
209 552         3344 for (keys %$r) {
210 1201         1050 my $do_parse = 1;
211 1201 100 66     4001 $do_parse = 0 if $do_parse && $ep && $mm->_in($_, $ep);
      100        
212 1201 100 100     3648 $do_parse = 0 if $do_parse && $ip && !$mm->_in($_, $ip);
      100        
213 1201 100 100     3664 $do_parse = 0 if $do_parse && $epr && /$epr/;
      100        
214 1201 100 100     3582 $do_parse = 0 if $do_parse && $ipr && !/$ipr/;
      100        
215              
216 1201 100       1318 if ($do_parse) {
217 1155         963 my $old = $_;
218 1155         817 my $m2;
219 1155         2228 ($_, $m2) = $mm->remove_prefix($_);
220 1155 100 66     5253 next if $esub && !$esub->($_);
221 550 50       1431 if (exists $hr->{$_}{$m2}) {
222 0         0 $mm->push_error("Conflict when removing prefix on right-side ".
223             "hash key: $old($m2) -> $_ ($m2) but $_ ($m2) ".
224             "already exists");
225 0         0 return;
226             }
227 550         1303 $hr->{$_}{$m2} = $r->{$old};
228             } else {
229 46 100 66     98 next if $esub && !$esub->($_);
230 44         135 $hr->{$_} = {$mode => $r->{$_}};
231             }
232             }
233             } else {
234 9         54 for (keys %$r) {
235 25 100 66     51 next if $esub && !$esub->($_);
236 20         48 $hr->{$_} = {$mode => $r->{$_}}
237             }
238             }
239             #print "DEBUG: Leaving _gen_right, result = ".dmp($hr)."\n";
240 561         1042 $hr;
241             }
242              
243             # merge two hashes which have been prepared by _gen_left and
244             # _gen_right, will result in { key => [final_mode, val], ... }
245             sub _merge_gen {
246 554     554   740 my ($self, $hl, $hr, $mode, $em, $im, $emr, $imr) = @_;
247 554         917 my $mm = $self->merger;
248 554         1745 my $c = $mm->config;
249              
250             #print "DEBUG: Entering _merge_gen(".dmp($hl).", ".dmp($hr).", $mode, ...)\n";
251              
252 554         1348 my $res = {};
253 554         565 my $backup = {};
254              
255 554         1622 my %k = map {$_=>1} keys(%$hl), keys(%$hr);
  1186         1798  
256 554         604 push @{ $mm->path }, "";
  554         975  
257             K:
258 554         3057 for my $k (keys %k) {
259 706         587 my @o;
260 706         1171 $mm->path->[-1] = $k;
261 706         2966 my $do_merge = 1;
262 706 100 66     2529 $do_merge = 0 if $do_merge && $em && $mm->_in($k, $em);
      100        
263 706 100 100     2265 $do_merge = 0 if $do_merge && $im && !$mm->_in($k, $im);
      100        
264 706 100 100     2552 $do_merge = 0 if $do_merge && $emr && $k =~ /$emr/;
      100        
265 706 100 100     2288 $do_merge = 0 if $do_merge && $imr && $k !~ /$imr/;
      100        
266              
267 706 100       1074 if (!$do_merge) {
268 47 100       110 $res->{$k} = $hl->{$k} if $hl->{$k};
269 47         77 next K;
270             }
271              
272 659 100 66     2026 $backup->{$k} = $hl->{$k}[1] if $hl->{$k} && $hr->{$k};
273 659 100       972 if ($hl->{$k}) {
274 553         681 push @o, $hl->{$k};
275             }
276 659 100       1054 if ($hr->{$k}) {
277 541         447 my %m = map {$_=>$mm->modes->{$_}->precedence_level} keys %{ $hr->{$k} };
  561         1138  
  541         1220  
278             #print "DEBUG: \\%m=".Data::Dumper->new([\%m])->Indent(0)->Terse(1)->Dump."\n";
279 541         1102 push @o, map { [$_, $hr->{$k}{$_}] } sort { $m{$b} <=> $m{$a} } keys %m;
  561         1820  
  25         39  
280             }
281 659         614 my $final_mode;
282             my $is_circular;
283 0         0 my $v;
284             #print "DEBUG: k=$k, o=".Data::Dumper->new([\@o])->Indent(0)->Terse(1)->Dump."\n";
285 659         1359 for my $i (0..$#o) {
286 1112 100       1418 if ($i == 0) {
287 659         1172 my $mh = $mm->modes->{$o[$i][0]};
288 659 100 66     5570 if (@o == 1 &&
      66        
289             (($hl->{$k} && $mh->can("merge_left_only")) ||
290             ($hr->{$k} && $mh->can("merge_right_only")))) {
291             # there's only left-side or right-side
292 3 100       9 my $meth = $hl->{$k} ? "merge_left_only" : "merge_right_only";
293 3         15 my ($subnewkey, $v, $subbackup, $is_circular, $newmode) = $mh->$meth($k, $o[$i][1]); # XXX handle circular?
294 3 50       14 next K unless defined($subnewkey);
295 0         0 $final_mode = $newmode;
296 0         0 $v = $res;
297             } else {
298 656         722 $final_mode = $o[$i][0];
299 656         915 $v = $o[$i][1];
300             }
301             } else {
302             my $m = $mm->combine_rules->{"$final_mode+$o[$i][0]"}
303 453 100       805 or do {
304 8         78 $mm->push_error("Can't merge $final_mode + $o[$i][0]");
305 8         31 return;
306             };
307             #print "DEBUG: merge $final_mode+$o[$i][0] = $m->[0], $m->[1]\n";
308 445         2077 my ($subnewkey, $subbackup);
309 445         1271 ($subnewkey, $v, $subbackup, $is_circular) = $mm->_merge($k, $v, $o[$i][1], $m->[0]);
310 445 100       494 return if @{ $mm->errors };
  445         777  
311 409 100       2392 if ($is_circular) {
312 3 100       7 if ($i < $#o) {
313 1         6 $mm->push_error("Can't handle circular at $i of $#o merges (mode $m->[0]): not the last merge");
314 1         4 return;
315             }
316             #print "DEBUG: pushing todo to mem<".$mm->cur_mem_key.">\n";
317 2         4 push @{ $mm->mem->{ $mm->cur_mem_key }{todo} }, sub {
318 2     2   3 my ($subnewkey, $subres, $subbackup) = @_;
319             #print "DEBUG: Entering todo subroutine (k=$k)\n";
320 2         2 my $final_mode = $m->[1];
321             #XXX return unless defined($subnewkey);
322 2         3 $res->{$k} = [$m->[1], $subres];
323 2 50       4 if ($c->readd_prefix) {
324             # XXX if there is a conflict error in
325             # _readd_prefix, how to adjust path?
326 2         12 $self->_readd_prefix($res, $k, $c->default_mode);
327             } else {
328 0         0 $res->{$k} = $res->{$k}[1];
329             }
330 2         3 };
331 2         26 delete $res->{$k};
332             }
333 408 100       858 next K unless defined $subnewkey;
334 351         695 $final_mode = $m->[1];
335             }
336             }
337 554 100       2026 $res->{$k} = [$final_mode, $v] unless $is_circular;
338             }
339 509         447 pop @{ $mm->path };
  509         836  
340             #print "DEBUG: Leaving _merge_gen, res = ".dmp($res)."\n";
341 509         3188 ($res, $backup);
342             }
343              
344             # hh is {key=>[MODE, val], ...} which is the format returned by _merge_gen
345             sub _readd_prefix {
346 508     508   2592 my ($self, $hh, $k, $defmode) = @_;
347 508         738 my $mm = $self->merger;
348 508         1428 my $c = $mm->config;
349              
350 508         1157 my $m = $hh->{$k}[0];
351 508 100       728 if ($m eq $defmode) {
352 443         1019 $hh->{$k} = $hh->{$k}[1];
353             } else {
354 65         145 my $kp = $mm->modes->{$m}->add_prefix($k);
355 65 50       408 if (exists $hh->{$kp}) {
356 0         0 $mm->push_error("BUG: conflict when re-adding prefix after merge: $kp");
357 0         0 return;
358             }
359 65         230 $hh->{$kp} = $hh->{$k}[1];
360 65         184 delete $hh->{$k};
361             }
362             }
363              
364             sub merge_HASH_HASH {
365 304     304 0 419 my ($self, $key, $l, $r, $mode) = @_;
366 304         576 my $mm = $self->merger;
367 304         1266 my $c = $mm->config;
368 304   66     1398 $mode //= $c->default_mode;
369             #print "DEBUG: entering merge_H_H(".dmp($l).", ".dmp($r).", $mode), config=($c)=",dmp($c),"\n";
370             #$log->trace("using config($c)");
371              
372 304 100       2152 return $self->merge_SCALAR_SCALAR($key, $l, $r) unless $c->recurse_hash;
373 300 100 100     850 return if $c->wanted_path && !$mm->_path_is_included($mm->path, $c->wanted_path);
374              
375             # STEP 1. MERGE LEFT & RIGHT OPTIONS KEY
376 298         1097 my $config_replaced;
377 298         279 my $orig_c = $c;
378 298         582 my $ok = $c->options_key;
379             {
380 298 100       429 last unless defined $ok;
  298         515  
381              
382 297     611   1529 my $okl = $self->_gen_left ($l, $mode, sub {$_[0] eq $ok});
  611         2597  
383 296 100       720 return if @{ $mm->errors };
  296         622  
384              
385 292     626   2696 my $okr = $self->_gen_right($r, $mode, sub {$_[0] eq $ok});
  626         2367  
386 292 50       652 return if @{ $mm->errors };
  292         582  
387              
388 292         1631 push @{ $mm->path }, $ok;
  292         569  
389 292         1425 my ($res, $backup);
390             {
391 292         255 local $c->{readd_prefix} = 0;
  292         616  
392 292         782 ($res, $backup) = $self->_merge_gen($okl, $okr, $mode);
393             }
394 292         313 pop @{ $mm->path };
  292         487  
395 292 100       1227 return if @{ $mm->errors };
  292         477  
396              
397             #print "DEBUG: merge options key (".dmp($okl).", ".dmp($okr).") = ".dmp($res)."\n";
398              
399 291 100       1760 $res = $res->{$ok} ? $res->{$ok}[1] : undef;
400 291 100 100     922 if (defined($res) && ref($res) ne 'HASH') {
401 6         7 $mm->push_error("Invalid options key after merge: value must be hash");
402 6         17 return;
403             }
404 285 100       1026 last unless keys %$res;
405             #$log->tracef("cloning config ...");
406             # Data::Clone by default does *not* deep-copy object
407             #my $c2 = clone($c);
408 62         411 my $c2 = bless({ %$c }, ref($c));
409              
410 62         150 for (keys %$res) {
411 62 100       146 if ($c->allow_override) {
412 5         21 my $re = $c->allow_override;
413 5 100       29 if (!/$re/) {
414 2         9 $mm->push_error("Configuration in options key `$_` not allowed by allow_override $re");
415 2         8 return;
416             }
417             }
418 60 100       263 if ($c->disallow_override) {
419 4         14 my $re = $c->disallow_override;
420 4 100       24 if (/$re/) {
421 2         10 $mm->push_error("Configuration in options key `$_` not allowed by disallow_override $re");
422 2         10 return;
423             }
424             }
425 58 100       277 if ($mm->_in($_, $c->_config_config)) {
426 4         15 $mm->push_error("Configuration not allowed in options key: $_");
427 4         20 return;
428             }
429 54 100 66     211 if ($_ ne $ok && !$mm->_in($_, $c->_config_ok)) {
430 1         9 $mm->push_error("Unknown configuration in options key: $_");
431 1         14 return;
432             }
433 53 50       237 $c2->$_($res->{$_}) unless $_ eq $ok;
434             }
435 53         337 $mm->config($c2);
436 53         138 $config_replaced++;
437 53         140 $c = $c2;
438             #$log->trace("config now changed to $c2");
439             }
440              
441 277         626 my $sp = $c->set_prefix;
442 277         735 my $saved_prefixes;
443 277 100       489 if (defined($sp)) {
444 7 100       31 if (ref($sp) ne 'HASH') {
445 2         5 $mm->push_error("Invalid config value `set_prefix`: must be a hash");
446 2         5 return;
447             }
448 5         10 $saved_prefixes = {};
449 5         7 for my $mh (values %{ $mm->modes }) {
  5         19  
450 30         103 my $n = $mh->name;
451 30 100       67 if ($sp->{$n}) {
452 7         18 $saved_prefixes->{$n} = {
453             prefix => $mh->prefix,
454             prefix_re => $mh->prefix_re,
455             check_prefix_sub => $mh->check_prefix_sub,
456             add_prefix_sub => $mh->add_prefix_sub,
457             remove_prefix_sub => $mh->remove_prefix_sub,
458             };
459 7         107 $mh->prefix($sp->{$n});
460 7         25 my $re = quotemeta($sp->{$n});
461 7         90 $mh->prefix_re(qr/^$re/);
462 7         27 $mh->check_prefix_sub(undef);
463 7         35 $mh->add_prefix_sub(undef);
464 7         21 $mh->remove_prefix_sub(undef);
465             }
466             }
467             }
468              
469 275         551 my $ep = $c->exclude_parse;
470 275         1023 my $ip = $c->include_parse;
471 275 100 100     1006 if (defined($ep) && ref($ep) ne 'ARRAY') {
472 2         4 $mm->push_error("Invalid config value `exclude_parse`: must be an array");
473 2         4 return;
474             }
475 273 100 100     588 if (defined($ip) && ref($ip) ne 'ARRAY') {
476 2         6 $mm->push_error("Invalid config value `include_parse`: must be an array");
477 2         4 return;
478             }
479              
480 271         525 my $epr = $c->exclude_parse_regex;
481 271         912 my $ipr = $c->include_parse_regex;
482 271 100       876 if (defined($epr)) {
483 5         8 eval { $epr = qr/$epr/ };
  5         50  
484 5 100       12 if ($@) {
485 1         4 $mm->push_error("Invalid config value `exclude_parse_regex`: invalid regex: $@");
486 1         2 return;
487             }
488             }
489 270 100       467 if (defined($ipr)) {
490 5         9 eval { $ipr = qr/$ipr/ };
  5         70  
491 5 100       17 if ($@) {
492 1         4 $mm->push_error("Invalid config value `include_parse_regex`: invalid regex: $@");
493 1         3 return;
494             }
495             }
496              
497             # STEP 2. PREPARE LEFT HASH
498 269 100   586   1455 my $hl = $self->_gen_left ($l, $mode, sub {defined($ok) ? $_[0] ne $ok : 1}, $ep, $ip, $epr, $ipr);
  586         2453  
499 269 50       645 return if @{ $mm->errors };
  269         564  
500              
501             # STEP 3. PREPARE RIGHT HASH
502 269 100   600   2705 my $hr = $self->_gen_right($r, $mode, sub {defined($ok) ? $_[0] ne $ok : 1}, $ep, $ip, $epr, $ipr);
  600         2175  
503 269 50       597 return if @{ $mm->errors };
  269         546  
504              
505             #print "DEBUG: hl=".Data::Dumper->new([$hl])->Indent(0)->Terse(1)->Dump."\n";
506             #print "DEBUG: hr=".Data::Dumper->new([$hr])->Indent(0)->Terse(1)->Dump."\n";
507              
508 269         1778 my $em = $c->exclude_merge;
509 269         932 my $im = $c->include_merge;
510 269 100 100     999 if (defined($em) && ref($em) ne 'ARRAY') {
511 2         5 $mm->push_error("Invalid config value `exclude_marge`: must be an array");
512 2         6 return;
513             }
514 267 100 100     578 if (defined($im) && ref($im) ne 'ARRAY') {
515 2         5 $mm->push_error("Invalid config value `include_merge`: must be an array");
516 2         6 return;
517             }
518              
519 265         499 my $emr = $c->exclude_merge_regex;
520 265         891 my $imr = $c->include_merge_regex;
521 265 100       931 if (defined($emr)) {
522 13         19 eval { $emr = qr/$emr/ };
  13         112  
523 13 100       32 if ($@) {
524 2         8 $mm->push_error("Invalid config value `exclude_merge_regex`: invalid regex: $@");
525 2         7 return;
526             }
527             }
528 263 100       454 if (defined($imr)) {
529 7         8 eval { $imr = qr/$imr/ };
  7         76  
530 7 100       18 if ($@) {
531 1         4 $mm->push_error("Invalid config value `include_merge_regex`: invalid regex: $@");
532 1         3 return;
533             }
534             }
535              
536             # STEP 4. MERGE LEFT & RIGHT
537 262         543 my ($res, $backup) = $self->_merge_gen($hl, $hr, $mode, $em, $im, $emr, $imr);
538 262 100       556 return if @{ $mm->errors };
  262         464  
539              
540             #print "DEBUG: intermediate res(5) = ".Data::Dumper->new([$res])->Indent(0)->Terse(1)->Dump."\n";
541              
542             # STEP 5. TURN BACK {key=>[MODE=>val]}, ...} INTO {(prefix)key => val, ...}
543 218 100       1348 if ($c->readd_prefix) {
544 197         591 for my $k (keys %$res) {
545 506         832 $self->_readd_prefix($res, $k, $c->default_mode);
546             }
547             } else {
548 21         141 $res->{$_} = $res->{$_}[1] for keys %$res;
549             }
550              
551 218 100       471 if ($saved_prefixes) {
552 5         15 for (keys %$saved_prefixes) {
553 7         21 my $mh = $mm->modes->{$_};
554 7         34 my $s = $saved_prefixes->{$_};
555 7         24 $mh->prefix($s->{prefix});
556 7         28 $mh->prefix_re($s->{prefix_re});
557 7         34 $mh->check_prefix_sub($s->{check_prefix_sub});
558 7         27 $mh->add_prefix_sub($s->{add_prefix_sub});
559 7         22 $mh->remove_prefix_sub($s->{remove_prefix_sub});
560             }
561             }
562              
563             # restore config
564 218 100       375 if ($config_replaced) {
565 44         103 $mm->config($orig_c);
566             #print "DEBUG: Restored config, config=", dmp($mm->config), "\n";
567             }
568              
569             #print "DEBUG: backup = ".Data::Dumper->new([$backup])->Indent(0)->Terse(1)->Dump."\n";
570             #print "DEBUG: leaving merge_H_H, result = ".dmp($res)."\n";
571 218         1282 ($key, $res, $backup);
572             }
573              
574             1;
575             # ABSTRACT: Base class for Data::ModeMerge mode handler
576              
577             __END__
578              
579             =pod
580              
581             =encoding UTF-8
582              
583             =head1 NAME
584              
585             Data::ModeMerge::Mode::Base - Base class for Data::ModeMerge mode handler
586              
587             =head1 VERSION
588              
589             This document describes version 0.33 of Data::ModeMerge::Mode::Base (from Perl distribution Data-ModeMerge), released on 2016-02-25.
590              
591             =head1 SYNOPSIS
592              
593             use Data::ModeMerge;
594              
595             =head1 DESCRIPTION
596              
597             This is the base class for mode type handlers.
598              
599             =for Pod::Coverage ^(BUILD|merge_.+)$
600              
601             =head1 ATTRIBUTES
602              
603             =head2 merger
604              
605             =head2 prefix
606              
607             =head2 prefix_re
608              
609             =head2 check_prefix_sub
610              
611             =head2 add_prefix_sub
612              
613             =head2 remove_prefix_sub
614              
615             =head1 METHODS
616              
617             =head2 name
618              
619             Return name of mode. Subclass must override this method.
620              
621             =head2 precedence_level
622              
623             Return precedence level, which is a number. The greater the number,
624             the higher the precedence. Subclass must override this method.
625              
626             =head2 default_prefix
627              
628             Return default prefix. Subclass must override this method.
629              
630             =head2 default_prefix_re
631              
632             Return default prefix regex. Subclass must override this method.
633              
634             =head2 check_prefix($hash_key)
635              
636             Return true if hash key has prefix for this mode.
637              
638             =head2 add_prefix($hash_key)
639              
640             Return hash key with added prefix of this mode.
641              
642             =head2 remove_prefix($hash_key)
643              
644             Return hash key with prefix of this mode prefix removed.
645              
646             =head1 HOMEPAGE
647              
648             Please visit the project's homepage at L<https://metacpan.org/release/Data-ModeMerge>.
649              
650             =head1 SOURCE
651              
652             Source repository is at L<https://github.com/perlancar/perl-Data-ModeMerge>.
653              
654             =head1 BUGS
655              
656             Please report any bugs or feature requests on the bugtracker website L<https://rt.cpan.org/Public/Dist/Display.html?Name=Data-ModeMerge>
657              
658             When submitting a bug or request, please include a test-file or a
659             patch to an existing test-file that illustrates the bug or desired
660             feature.
661              
662             =head1 AUTHOR
663              
664             perlancar <perlancar@cpan.org>
665              
666             =head1 COPYRIGHT AND LICENSE
667              
668             This software is copyright (c) 2016 by perlancar@cpan.org.
669              
670             This is free software; you can redistribute it and/or modify it under
671             the same terms as the Perl 5 programming language system itself.
672              
673             =cut