mirror of
https://github.com/XRPLF/rippled.git
synced 2025-12-06 17:27:55 +00:00
Traverse functions have not been fully tested.
This commit is contained in:
134
src/RangeSet.cpp
134
src/RangeSet.cpp
@@ -1,17 +1,19 @@
|
||||
|
||||
#include "RangeSet.h"
|
||||
|
||||
#include <boost/test/unit_test.hpp>
|
||||
#include <boost/lexical_cast.hpp>
|
||||
|
||||
#include "Log.h"
|
||||
|
||||
SETUP_LOG();
|
||||
|
||||
inline int min(int x, int y) { return (x < y) ? x : y; }
|
||||
inline int max(int x, int y) { return (x > y) ? x : y; }
|
||||
|
||||
bool RangeSet::hasValue(int v) const
|
||||
{
|
||||
for (const_iterator it = begin(); it != end(); ++it)
|
||||
{
|
||||
if ((v >= it->first) && (v <= it->second))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
return mRanges.find(v) != mRanges.end();
|
||||
}
|
||||
|
||||
int RangeSet::getFirst() const
|
||||
@@ -19,15 +21,15 @@ int RangeSet::getFirst() const
|
||||
const_iterator it = begin();
|
||||
if (it == end())
|
||||
return RangeSetAbsent;
|
||||
return it->first;
|
||||
return it->lower();
|
||||
}
|
||||
|
||||
int RangeSet::getNext(int v) const
|
||||
{
|
||||
for (const_iterator it = begin(); it != end(); ++it)
|
||||
{
|
||||
if (it->second > v)
|
||||
return min(v + 1, it->first);
|
||||
if ((it->upper() - 1) > v)
|
||||
return max(v + 1, it->lower());
|
||||
}
|
||||
return RangeSetAbsent;
|
||||
}
|
||||
@@ -37,76 +39,90 @@ int RangeSet::getLast() const
|
||||
const_reverse_iterator it = rbegin();
|
||||
if (it == rend())
|
||||
return RangeSetAbsent;
|
||||
return it->second;
|
||||
return it->upper() - 1;
|
||||
}
|
||||
|
||||
int RangeSet::getPrev(int v) const
|
||||
{
|
||||
for (const_reverse_iterator it = rbegin(); it != rend(); ++it)
|
||||
{
|
||||
if (it->first < v)
|
||||
return max(v - 1, it->second);
|
||||
if (it->lower() < v)
|
||||
return min(v - 1, it->upper() - 1);
|
||||
}
|
||||
return RangeSetAbsent;
|
||||
}
|
||||
|
||||
bool RangeSet::setValue(int v)
|
||||
void RangeSet::setValue(int v)
|
||||
{
|
||||
for (iterator it = begin(); it != end(); ++it)
|
||||
{
|
||||
if (it->first >= v)
|
||||
{ // entry goes before or in this entry
|
||||
if (it->second <= v)
|
||||
return false;
|
||||
if (it->first > (v - 1))
|
||||
{
|
||||
mRanges.insert(it, std::make_pair(v, v));
|
||||
return true;
|
||||
}
|
||||
else if (it->first == (v - 1))
|
||||
{
|
||||
it->first = v;
|
||||
// WRITEME: check for consolidation
|
||||
}
|
||||
// WRITEME
|
||||
}
|
||||
}
|
||||
mRanges.push_back(std::make_pair(v, v));
|
||||
return true;
|
||||
setRange(v, v);
|
||||
}
|
||||
|
||||
void RangeSet::setRange(int minV, int maxV)
|
||||
{
|
||||
mRanges.add(boost::icl::discrete_interval<int>(minV, maxV + 1));
|
||||
}
|
||||
|
||||
bool RangeSet::clearValue(int v)
|
||||
void RangeSet::clearValue(int v)
|
||||
{
|
||||
for (iterator it = begin(); it != end(); ++it)
|
||||
{
|
||||
if (it->first >= v)
|
||||
{ // we are at or past the value we need to clear
|
||||
|
||||
if (it->second > v)
|
||||
return false;
|
||||
|
||||
if ((it->first == v) && (it->second == v))
|
||||
mRanges.erase(it);
|
||||
else if (it->first == v)
|
||||
++it->first;
|
||||
else if (it->second == v)
|
||||
--it->second;
|
||||
else
|
||||
{ // this pokes a hole
|
||||
int first = it->first;
|
||||
it->first = v + 1;
|
||||
mRanges.insert(it, std::make_pair(first, v - 1));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
clearRange(v, v);
|
||||
}
|
||||
|
||||
void RangeSet::clearRange(int minV, int maxV)
|
||||
{
|
||||
mRanges.erase(boost::icl::discrete_interval<int>(minV, maxV + 1));
|
||||
}
|
||||
|
||||
std::string RangeSet::toString() const
|
||||
{
|
||||
std::string ret;
|
||||
for (const_iterator it = begin(); it != end(); ++it)
|
||||
{
|
||||
if (!ret.empty())
|
||||
ret += ",";
|
||||
if (it->lower() == (it->upper() - 1))
|
||||
ret += boost::lexical_cast<std::string>(it->lower());
|
||||
else
|
||||
ret += boost::lexical_cast<std::string>(it->lower()) + "-"
|
||||
+ boost::lexical_cast<std::string>(it->upper() - 1);
|
||||
}
|
||||
if (ret.empty())
|
||||
return "empty";
|
||||
return ret;
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE(RangeSet_suite)
|
||||
|
||||
BOOST_AUTO_TEST_CASE(RangeSet_test)
|
||||
{
|
||||
cLog(lsTRACE) << "RangeSet test begins";
|
||||
|
||||
RangeSet r1, r2;
|
||||
|
||||
if (r1 != r2) BOOST_FAIL("RangeSet fail");
|
||||
|
||||
r1.setValue(1);
|
||||
if (r1 == r2) BOOST_FAIL("RangeSet fail");
|
||||
r2.setRange(1, 1);
|
||||
if (r1 != r2) BOOST_FAIL("RangeSet fail");
|
||||
|
||||
r1.clear();
|
||||
r1.setRange(1,10);
|
||||
r1.clearValue(5);
|
||||
r1.setRange(11, 20);
|
||||
|
||||
r2.clear();
|
||||
r2.setRange(1, 4);
|
||||
r2.setRange(6, 10);
|
||||
r2.setRange(10, 20);
|
||||
if (r1 != r2) BOOST_FAIL("RangeSet fail");
|
||||
if (r1.hasValue(5)) BOOST_FAIL("RangeSet fail");
|
||||
if (!r2.hasValue(9)) BOOST_FAIL("RangeSet fail");
|
||||
|
||||
// TODO: Traverse functions must be tested
|
||||
|
||||
cLog(lsTRACE) << "RangeSet test complete";
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
||||
|
||||
// vim:ts=4
|
||||
|
||||
@@ -2,24 +2,26 @@
|
||||
#define RANGESET__H
|
||||
|
||||
#include <list>
|
||||
#include <string>
|
||||
|
||||
#include <boost/foreach.hpp>
|
||||
#include <boost/icl/interval_set.hpp>
|
||||
|
||||
class RangeSet
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
typedef std::pair<int, int> Range;
|
||||
typedef std::list<Range>::iterator iterator;
|
||||
typedef std::list<Range>::const_iterator const_iterator;
|
||||
typedef std::list<Range>::reverse_iterator reverse_iterator;
|
||||
typedef std::list<Range>::const_reverse_iterator const_reverse_iterator;
|
||||
typedef boost::icl::interval_set<int> iRangeSet;
|
||||
typedef iRangeSet::iterator iterator;
|
||||
typedef iRangeSet::const_iterator const_iterator;
|
||||
typedef iRangeSet::reverse_iterator reverse_iterator;
|
||||
typedef iRangeSet::const_reverse_iterator const_reverse_iterator;
|
||||
static const int RangeSetAbsent = -1;
|
||||
|
||||
protected:
|
||||
|
||||
std::list<Range> mRanges;
|
||||
iRangeSet mRanges;
|
||||
|
||||
public:
|
||||
|
||||
@@ -31,11 +33,13 @@ public:
|
||||
int getLast() const;
|
||||
int getPrev(int) const;
|
||||
|
||||
bool setValue(int);
|
||||
void setValue(int);
|
||||
void setRange(int, int);
|
||||
bool clearValue(int);
|
||||
void clearValue(int);
|
||||
void clearRange(int, int);
|
||||
|
||||
void clear() { mRanges.clear(); }
|
||||
|
||||
// iterator stuff
|
||||
iterator begin() { return mRanges.begin(); }
|
||||
iterator end() { return mRanges.end(); }
|
||||
@@ -45,6 +49,11 @@ public:
|
||||
reverse_iterator rend() { return mRanges.rend(); }
|
||||
const_reverse_iterator rbegin() const { return mRanges.rbegin(); }
|
||||
const_reverse_iterator rend() const { return mRanges.rend(); }
|
||||
|
||||
bool operator!=(const RangeSet& r) const { return mRanges != r.mRanges; }
|
||||
bool operator==(const RangeSet& r) const { return mRanges == r.mRanges; }
|
||||
|
||||
std::string toString() const;
|
||||
};
|
||||
|
||||
inline RangeSet::const_iterator range_begin(const RangeSet& r) { return r.begin(); }
|
||||
@@ -65,3 +74,5 @@ namespace boost
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// vim:ts=4
|
||||
|
||||
Reference in New Issue
Block a user