summaryrefslogtreecommitdiff
path: root/Data-TagsAndRanges/lib/Data/TagsAndRanges/RangeContainer.pm
diff options
context:
space:
mode:
Diffstat (limited to 'Data-TagsAndRanges/lib/Data/TagsAndRanges/RangeContainer.pm')
-rw-r--r--Data-TagsAndRanges/lib/Data/TagsAndRanges/RangeContainer.pm91
1 files changed, 91 insertions, 0 deletions
diff --git a/Data-TagsAndRanges/lib/Data/TagsAndRanges/RangeContainer.pm b/Data-TagsAndRanges/lib/Data/TagsAndRanges/RangeContainer.pm
new file mode 100644
index 0000000..5f3653a
--- /dev/null
+++ b/Data-TagsAndRanges/lib/Data/TagsAndRanges/RangeContainer.pm
@@ -0,0 +1,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;