* Copyright 2013, Rene Gollent, rene@gollent.com.
* Distributed under the terms of the MIT License.
*/
#include "RangeList.h"
#include <AutoDeleter.h>
RangeList::RangeList()
:
BObjectList<Range, true>(20)
{
}
RangeList::~RangeList()
{
}
status_t
RangeList::AddRange(int32 lowValue, int32 highValue)
{
if (lowValue > highValue)
return B_BAD_VALUE;
int32 i = 0;
if (CountItems() != 0) {
for (; i < CountItems(); i++) {
Range* range = ItemAt(i);
if (lowValue < range->lowerBound) {
if (highValue < range->lowerBound) {
break;
} else if (highValue <= range->upperBound) {
range->lowerBound = lowValue;
return B_OK;
} else {
range->lowerBound = lowValue;
range->upperBound = highValue;
_CollapseOverlappingRanges(i +1, highValue);
}
} else if (lowValue < range->upperBound) {
if (highValue <= range->upperBound) {
return B_OK;
} else {
range->upperBound = highValue;
_CollapseOverlappingRanges(i + 1, highValue);
return B_OK;
}
}
}
}
Range* range = new(std::nothrow) Range(lowValue, highValue);
if (range == NULL)
return B_NO_MEMORY;
BPrivate::ObjectDeleter<Range> rangeDeleter(range);
if (!AddItem(range, i))
return B_NO_MEMORY;
rangeDeleter.Detach();
return B_OK;
}
status_t
RangeList::AddRange(const Range& range)
{
return AddRange(range.lowerBound, range.upperBound);
}
void
RangeList::RemoveRangeAt(int32 index)
{
if (index < 0 || index >= CountItems())
return;
RemoveItem(ItemAt(index));
}
bool
RangeList::Contains(int32 value) const
{
for (int32 i = 0; i < CountItems(); i++) {
const Range* range = ItemAt(i);
if (value < range->lowerBound || value > range->upperBound)
break;
else if (value >= range->lowerBound && value <= range->upperBound)
return true;
}
return false;
}
int32
RangeList::CountRanges() const
{
return CountItems();
}
const Range*
RangeList::RangeAt(int32 index) const
{
return ItemAt(index);
}
void
RangeList::_CollapseOverlappingRanges(int32 startIndex, int32 highValue)
{
for (int32 i = startIndex; i < CountItems();) {
Range* nextRange = ItemAt(i);
if (nextRange->lowerBound > highValue)
return;
else if (nextRange->upperBound < highValue) {
RemoveItem(nextRange);
continue;
} else {
nextRange->lowerBound = highValue + 1;
return;
}
}
}