| line | stmt | bran | cond | sub | pod | time | code | 
| 1 |  |  |  |  |  |  | package Morpheus::Utils; | 
| 2 |  |  |  |  |  |  | { | 
| 3 |  |  |  |  |  |  | $Morpheus::Utils::VERSION = '0.46'; | 
| 4 |  |  |  |  |  |  | } | 
| 5 | 6 |  |  | 6 |  | 113759 | use strict; | 
|  | 6 |  |  |  |  | 14 |  | 
|  | 6 |  |  |  |  | 335 |  | 
| 6 |  |  |  |  |  |  |  | 
| 7 |  |  |  |  |  |  | # ABSTRACT: some common functions which don't fit anywhere else | 
| 8 |  |  |  |  |  |  |  | 
| 9 |  |  |  |  |  |  | sub normalize ($); | 
| 10 |  |  |  |  |  |  | sub adjust ($$); | 
| 11 |  |  |  |  |  |  | sub merge ($$;$); | 
| 12 |  |  |  |  |  |  |  | 
| 13 | 6 |  |  | 6 |  | 32 | use base qw(Exporter); | 
|  | 6 |  |  |  |  | 11 |  | 
|  | 6 |  |  |  |  | 982 |  | 
| 14 |  |  |  |  |  |  | our @EXPORT = qw(normalize merge adjust); | 
| 15 |  |  |  |  |  |  |  | 
| 16 | 6 |  |  | 6 |  | 4446 | use Symbol qw(gensym); | 
|  | 6 |  |  |  |  | 4672 |  | 
|  | 6 |  |  |  |  | 507 |  | 
| 17 |  |  |  |  |  |  |  | 
| 18 | 6 |  |  | 6 |  | 2241 | use Morpheus::Key qw(key); | 
|  | 6 |  |  |  |  | 14 |  | 
|  | 6 |  |  |  |  | 5545 |  | 
| 19 |  |  |  |  |  |  |  | 
| 20 |  |  |  |  |  |  | sub normalize ($) { | 
| 21 | 112 |  |  | 112 | 0 | 1344 | my ($data) = @_; | 
| 22 | 112 | 100 |  |  |  | 373 | return $data unless ref $data eq "HASH"; | 
| 23 | 91 |  |  |  |  | 323 | my $result = { %$data }; | 
| 24 | 91 |  |  |  |  | 362 | for my $key ( keys %$data) { | 
| 25 | 124 |  |  |  |  | 142 | my @keys = @{key($key)}; | 
|  | 124 |  |  |  |  | 333 |  | 
| 26 | 124 | 100 | 100 |  |  | 919 | next if @keys == 1 and $keys[0] eq $key; # "/a//" -> "a" | 
| 27 | 54 |  |  |  |  | 115 | my $value = delete $result->{$key}; | 
| 28 | 54 |  |  |  |  | 161 | my $p = my $patch = {}; | 
| 29 | 54 |  |  |  |  | 306 | $p = $p->{$_} = {} for splice @keys, 0, -1; | 
| 30 | 54 |  |  |  |  | 151 | $p->{$keys[0]} = $value; | 
| 31 | 54 |  |  |  |  | 110 | $result = merge($result, $patch); | 
| 32 |  |  |  |  |  |  | # {"a/b/c"=>"d"} -> {a=>{b=>{c=>"d"}}} | 
| 33 |  |  |  |  |  |  | } | 
| 34 | 91 |  |  |  |  | 313 | return $result; | 
| 35 |  |  |  |  |  |  | } | 
| 36 |  |  |  |  |  |  |  | 
| 37 |  |  |  |  |  |  | sub adjust ($$) { | 
| 38 | 950 |  |  | 950 | 0 | 1803 | my ($value, $delta) = @_; | 
| 39 | 950 | 50 |  |  |  | 2136 | return $value unless $delta; | 
| 40 | 950 |  |  |  |  | 1012 | for (@{key($delta)}) { | 
|  | 950 |  |  |  |  | 2109 |  | 
| 41 | 2486 | 100 | 100 |  |  | 11175 | if (defined $value and ref $value eq "HASH") { | 
|  |  | 100 | 66 |  |  |  |  | 
| 42 | 1802 |  |  |  |  | 3835 | $value = $value->{$_}; | 
| 43 |  |  |  |  |  |  | } elsif (defined $value and ref $value eq "GLOB") { | 
| 44 | 1 |  |  |  |  | 2 | $value = ${*$value}{$_}; | 
|  | 1 |  |  |  |  | 9 |  | 
| 45 |  |  |  |  |  |  | } else { | 
| 46 | 683 |  |  |  |  | 1854 | return (undef); | 
| 47 |  |  |  |  |  |  | } | 
| 48 |  |  |  |  |  |  | } | 
| 49 | 267 |  |  |  |  | 1221 | return $value; | 
| 50 |  |  |  |  |  |  | } | 
| 51 |  |  |  |  |  |  |  | 
| 52 |  |  |  |  |  |  | sub merge ($$;$) { | 
| 53 | 1573 |  |  | 1573 | 0 | 10994 | my ($value, $patch, $die_on_collision) = @_; | 
| 54 |  |  |  |  |  |  | #TODO: support $die_on_collision! | 
| 55 |  |  |  |  |  |  |  | 
| 56 | 1573 | 100 |  |  |  | 6435 | return $patch unless defined $value; | 
| 57 | 621 | 100 |  |  |  | 1660 | return $value unless defined $patch; | 
| 58 |  |  |  |  |  |  |  | 
| 59 | 516 |  |  |  |  | 791 | my %refs = map { $_ => 1 } qw(GLOB HASH ARRAY); | 
|  | 1548 |  |  |  |  | 3273 |  | 
| 60 |  |  |  |  |  |  |  | 
| 61 |  |  |  |  |  |  | # TODO: return a glob itself instead of a globref! | 
| 62 |  |  |  |  |  |  |  | 
| 63 | 516 |  |  |  |  | 941 | my $ref_value = ref $value; | 
| 64 | 516 | 100 |  |  |  | 1203 | $ref_value = "" unless $refs{$ref_value}; | 
| 65 | 516 |  |  |  |  | 713 | my $ref_patch = ref $patch; | 
| 66 | 516 | 100 |  |  |  | 1069 | $ref_patch = "" unless $refs{$ref_patch}; | 
| 67 |  |  |  |  |  |  |  | 
| 68 | 516 | 100 |  |  |  | 1063 | if ($ref_value eq "GLOB") { | 
| 69 | 1 |  |  |  |  | 3 | my $result = gensym; | 
| 70 | 1 |  |  |  |  | 9 | *{$result} = *{$value}; | 
|  | 1 |  |  |  |  | 2 |  | 
|  | 1 |  |  |  |  | 2 |  | 
| 71 | 1 | 50 |  |  |  | 4 | if ($ref_patch eq "GLOB") { | 
| 72 | 1 |  |  |  |  | 2 | my $hash = merge(*{$value}{HASH}, *{$patch}{HASH}); | 
|  | 1 |  |  |  |  | 2 |  | 
|  | 1 |  |  |  |  | 3 |  | 
| 73 | 1 | 50 |  |  |  | 3 | *{$result} = $hash if $hash; | 
|  | 1 |  |  |  |  | 3 |  | 
| 74 | 1 |  |  |  |  | 20 | my $array = merge(*{$value}{ARRAY}, *{$patch}{ARRAY}); | 
|  | 1 |  |  |  |  | 3 |  | 
|  | 1 |  |  |  |  | 2 |  | 
| 75 | 1 | 50 |  |  |  | 4 | *{$result} = $array if $array; | 
|  | 1 |  |  |  |  | 2 |  | 
| 76 | 1 |  |  |  |  | 1 | ${*{$result}} = merge(${*{$value}}, ${*{$patch}}); | 
|  | 1 |  |  |  |  | 1 |  | 
|  | 1 |  |  |  |  | 3 |  | 
|  | 1 |  |  |  |  | 2 |  | 
|  | 1 |  |  |  |  | 3 |  | 
|  | 1 |  |  |  |  | 2 |  | 
|  | 1 |  |  |  |  | 3 |  | 
| 77 |  |  |  |  |  |  | } else { | 
| 78 | 0 |  |  |  |  | 0 | ${*{$result}} = merge(${*{$value}}, $patch); | 
|  | 0 |  |  |  |  | 0 |  | 
|  | 0 |  |  |  |  | 0 |  | 
|  | 0 |  |  |  |  | 0 |  | 
|  | 0 |  |  |  |  | 0 |  | 
| 79 |  |  |  |  |  |  | } | 
| 80 | 1 |  |  |  |  | 4 | return $result; | 
| 81 |  |  |  |  |  |  | } | 
| 82 |  |  |  |  |  |  |  | 
| 83 | 515 | 100 |  |  |  | 960 | if ($ref_patch eq "GLOB") { | 
| 84 | 1 |  |  |  |  | 3 | my $result = gensym; | 
| 85 | 1 |  |  |  |  | 9 | *{$result} = *{$patch}; | 
|  | 1 |  |  |  |  | 3 |  | 
|  | 1 |  |  |  |  | 2 |  | 
| 86 | 1 |  |  |  |  | 1 | ${*{$result}} = merge($value, ${*{$patch}}); | 
|  | 1 |  |  |  |  | 1 |  | 
|  | 1 |  |  |  |  | 3 |  | 
|  | 1 |  |  |  |  | 2 |  | 
|  | 1 |  |  |  |  | 3 |  | 
| 87 | 1 |  |  |  |  | 4 | return $result; | 
| 88 |  |  |  |  |  |  | } | 
| 89 |  |  |  |  |  |  |  | 
| 90 | 514 | 100 | 66 |  |  | 1645 | if ($ref_value eq "HASH" and $ref_patch eq "HASH") { | 
| 91 | 234 |  |  |  |  | 808 | my $result = { %$value }; | 
| 92 | 234 |  |  |  |  | 642 | for (keys %$patch) { | 
| 93 | 498 |  |  |  |  | 1310 | $result->{$_} = merge($value->{$_}, $patch->{$_}); | 
| 94 |  |  |  |  |  |  | } | 
| 95 | 234 |  |  |  |  | 1287 | return $result; | 
| 96 |  |  |  |  |  |  | } | 
| 97 |  |  |  |  |  |  |  | 
| 98 | 280 |  |  |  |  | 1117 | return $value; | 
| 99 |  |  |  |  |  |  | } | 
| 100 |  |  |  |  |  |  |  | 
| 101 |  |  |  |  |  |  | 1; | 
| 102 |  |  |  |  |  |  |  | 
| 103 |  |  |  |  |  |  | __END__ |