summaryrefslogtreecommitdiff
path: root/Data-MultiValued/lib/Data/MultiValued/RangeContainer.pm
diff options
context:
space:
mode:
Diffstat (limited to 'Data-MultiValued/lib/Data/MultiValued/RangeContainer.pm')
-rw-r--r--Data-MultiValued/lib/Data/MultiValued/RangeContainer.pm43
1 files changed, 29 insertions, 14 deletions
diff --git a/Data-MultiValued/lib/Data/MultiValued/RangeContainer.pm b/Data-MultiValued/lib/Data/MultiValued/RangeContainer.pm
index 5c4fb3a..33864da 100644
--- a/Data-MultiValued/lib/Data/MultiValued/RangeContainer.pm
+++ b/Data-MultiValued/lib/Data/MultiValued/RangeContainer.pm
@@ -9,8 +9,8 @@ has _storage => (
is => 'rw',
isa => ArrayRef[
Dict[
- from => Num,
- to => Num,
+ from => Num|Undef,
+ to => Num|Undef,
value => Any,
],
],
@@ -21,7 +21,7 @@ has _storage => (
sub get {
my ($self,$args) = @_;
- my $at = $args->{at} // 0-'inf';
+ my $at = $args->{at};
my ($range) = $self->_get_slot_at($at);
@@ -34,12 +34,23 @@ sub get {
return $range;
}
+# Num|Undef,Num|Undef,Bool,Bool
+# the bools mean "treat the undef as +inf" (-inf when omitted/false)
+sub _cmp {
+ my ($a,$b,$sa,$sb) = @_;
+
+ $a //= $sa ? 0+'inf' : 0-'inf';
+ $b //= $sb ? 0+'inf' : 0-'inf';
+
+ return $a <=> $b;
+}
+
sub _get_slot_at {
my ($self,$at) = @_;
for my $slot (@{$self->_storage}) {
- next if $slot->{to} <= $at;
- last if $slot->{from} > $at;
+ next if _cmp($slot->{to},$at,1,0) <= 0;
+ last if _cmp($slot->{from},$at,0,0) > 0;
return $slot;
}
return;
@@ -56,10 +67,10 @@ sub _partition_slots {
while (my ($idx,$slot) = each @$st) {
my ($sf,$st) = @$slot{'from','to'};
- if ($st<$from) {
+ if (_cmp($st,$from,1,0) <0) {
push @before,$idx;
}
- elsif ($sf>=$to) {
+ elsif (_cmp($sf,$to,0,1) >=0) {
push @after,$idx;
}
else {
@@ -72,17 +83,19 @@ sub _partition_slots {
sub set_or_create {
my ($self,$args) = @_;
- my $from = $args->{from} // 0-'inf';
- my $to = $args->{to} // 0+'inf';
+ my $from = $args->{from};
+ my $to = $args->{to};
- Data::MultiValued::Exceptions::BadRange->({
+ Data::MultiValued::Exceptions::BadRange->throw({
from => $from,
to => $to,
- }) if $from > $to;
+ }) if _cmp($from,$to,0,1)>0;
my ($range) = $self->_get_slot_at($from);
- if ($range && $range->{from}==$from && $range->{to}==$to) {
+ if ($range
+ && _cmp($range->{from},$from,0,0)==0
+ && _cmp($range->{to},$to,1,1)==0) {
return $range;
}
@@ -127,14 +140,16 @@ sub _create_slot {
my $first = $self->_storage->[$first_to_replace];
my $last = $self->_storage->[$last_to_replace];
- if ($first->{from} < $from && $first->{to} >= $from) {
+ if (_cmp($first->{from},$from,0,0)<0
+ && _cmp($first->{to},$from,1,0)>=0) {
unshift @replacement, {
from => $first->{from},
to => $from,
value => $first->{value},
}
}
- if ($last->{from} < $to && $last->{to} >= $to) {
+ if (_cmp($last->{from},$to,0,1)<0
+ && _cmp($last->{to},$to,1,1)>=0) {
push @replacement, {
from => $to,
to => $last->{to},