summaryrefslogtreecommitdiff
path: root/Data-TagsAndRanges/lib/Data/TagsAndRanges/RangeContainer.pm
blob: 5f3653a14a053b0d57857c5f13eb2e53508917c4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
package Data::TagsAndRanges::RangeContainer; 
use Moose;
use Moose::Util::TypeConstraints;
use MooseX::Types::Moose qw(Num Str Any Undef ArrayRef);
use MooseX::Types::Structured qw(Dict);
use Data::TagsAndRanges::Exceptions;
 
has _storage => (
    is => 'rw',
    isa => ArrayRef[
        Dict[
            from => Num|Undef,
            to => Num|Undef,
            value => Any,
        ],
    ],
    init_arg => undef,
    default => sub { [ ]  },
);
 
sub get {
    my ($self,$args) = @_;
 
    my $at = $args->{at};
 
    my ($range) = $self->_get_slot_at($at);
 
    if (!$range) {
        Data::TagsAndRanges::Exceptions::RangeNotFound->throw({
            value => $at,
        });
    }
 
    return $range;
}
 
sub _cmp_less 
    return if !defined $_[0];
    return 1 if !defined $_[1];
    return $_[0] <= $_[1];
}
sub _cmp_more {
    return if !defined $_[0];
    return 1 if !defined $_[1];
    return $_[0] > $_[1];
}
sub _cmp_eq {
    return 1 if !defined($_[0]) && !defined($_[1]);
    return if defined($_[0]) xor defined($_[1]);
    return $_[0] == $_[1];
}
 
sub _get_slot_at {
    my ($self,$at) = @_;
 
    for my $slot (@{$self->_storage}) {
        next if _cmp_less($slot->{to},$at);
        last if _cmp_more($slot->{from},$at);
        return $slot;
    }
    return;
}
 
sub set_or_create {
    my ($self,$args) = @_;
 
    my $from = $args->{from};
    my $to = $args->{to};
 
    my ($range) = $self->_get_slot_at($from);
 
    if ($range && _cmp_eq($range->{from},$from) && _cmp_eq($range->{to},$to)) {
        return $range;
    }
 
    $range = $self->_create_slot($from,$to);
    return $range;
}
 
sub _create_slot {
    my ($self,$from,$to) = @_;
 
    push @{$self->_storage},{
        from => $from,
        to => $to,
        value => undef,
    };
    return $self->_storage->[-1];
}
 
1;