mirror of
https://github.com/XRPLF/rippled.git
synced 2025-11-20 11:05:54 +00:00
Replace the boost range set code with our own
This commit is contained in:
@@ -6,100 +6,152 @@ inline uint32 max(uint32 x, uint32 y) { return (x > y) ? x : y; }
|
|||||||
|
|
||||||
bool RangeSet::hasValue(uint32 v) const
|
bool RangeSet::hasValue(uint32 v) const
|
||||||
{
|
{
|
||||||
return mRanges.find(v) != mRanges.end();
|
BOOST_FOREACH(const value_type& it, mRanges)
|
||||||
|
{
|
||||||
|
if (contains(it, v))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32 RangeSet::getFirst() const
|
uint32 RangeSet::getFirst() const
|
||||||
{
|
{
|
||||||
const_iterator it = begin();
|
const_iterator it = mRanges.begin();
|
||||||
if (it == end())
|
if (it == mRanges.end())
|
||||||
return RangeSetAbsent;
|
return RangeSetAbsent;
|
||||||
return lower(it);
|
return it->first;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32 RangeSet::getNext(uint32 v) const
|
uint32 RangeSet::getNext(uint32 v) const
|
||||||
{
|
{
|
||||||
for (const_iterator it = begin(); it != end(); ++it)
|
BOOST_FOREACH(const value_type& it, mRanges)
|
||||||
{
|
{
|
||||||
if (upper(it) > v)
|
if (it.first > v)
|
||||||
return max(v + 1, lower(it));
|
return it.first;
|
||||||
|
if (contains(it, v + 1))
|
||||||
|
return v + 1;
|
||||||
}
|
}
|
||||||
return RangeSetAbsent;
|
return RangeSetAbsent;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32 RangeSet::getLast() const
|
uint32 RangeSet::getLast() const
|
||||||
{
|
{
|
||||||
const_reverse_iterator it = rbegin();
|
const_reverse_iterator it = mRanges.rbegin();
|
||||||
if (it == rend())
|
if (it == mRanges.rend())
|
||||||
return RangeSetAbsent;
|
return RangeSetAbsent;
|
||||||
return upper(it);
|
return it->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32 RangeSet::getPrev(uint32 v) const
|
uint32 RangeSet::getPrev(uint32 v) const
|
||||||
{
|
{
|
||||||
for (const_reverse_iterator it = rbegin(); it != rend(); ++it)
|
BOOST_REVERSE_FOREACH(const value_type& it, mRanges)
|
||||||
{
|
{
|
||||||
if (lower(it) < v)
|
if (it.second < v)
|
||||||
return min(v - 1, upper(it));
|
return it.second;
|
||||||
|
if (contains(it, v + 1))
|
||||||
|
return v - 1;
|
||||||
}
|
}
|
||||||
return RangeSetAbsent;
|
return RangeSetAbsent;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32 RangeSet::prevMissing(uint32 v) const
|
uint32 RangeSet::prevMissing(uint32 v) const
|
||||||
{ // largest number not in the set that is less than the given number
|
{ // largest number not in the set that is less than the given number
|
||||||
WriteLog (lsTRACE, RangeSet) << "prevMissing(" << v << ") " << toString();
|
BOOST_FOREACH(const value_type& it, mRanges)
|
||||||
for (const_reverse_iterator it = rbegin(); it != rend(); ++it)
|
|
||||||
{
|
{
|
||||||
if ((upper(it) + 1) < v)
|
if (contains(it, v))
|
||||||
return upper(it) + 1;
|
return it.first - 1;
|
||||||
if (lower(it) == 0)
|
if (it.first > v)
|
||||||
return RangeSetAbsent;
|
return v + 1;
|
||||||
if ((lower(it) - 1) < v)
|
|
||||||
return lower(it) - 1;
|
|
||||||
}
|
}
|
||||||
if (v > 0)
|
|
||||||
return v - 1;
|
|
||||||
return RangeSetAbsent;
|
return RangeSetAbsent;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RangeSet::setValue(uint32 v)
|
void RangeSet::setValue(uint32 v)
|
||||||
{
|
{
|
||||||
setRange(v, v);
|
if (!hasValue(v))
|
||||||
|
{
|
||||||
|
mRanges[v] = v;
|
||||||
|
simplify();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void RangeSet::setRange(uint32 minV, uint32 maxV)
|
void RangeSet::setRange(uint32 minV, uint32 maxV)
|
||||||
{
|
{
|
||||||
mRanges.add(boost::icl::discrete_interval<uint32>(minV, maxV + 1));
|
while (hasValue(minV))
|
||||||
|
{
|
||||||
|
++minV;
|
||||||
|
if (minV >= maxV)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
mRanges[minV] = maxV;
|
||||||
|
simplify();
|
||||||
}
|
}
|
||||||
|
|
||||||
void RangeSet::clearValue(uint32 v)
|
void RangeSet::clearValue(uint32 v)
|
||||||
{
|
{
|
||||||
clearRange(v, v);
|
for (iterator it = mRanges.begin(); it != mRanges.end(); ++it)
|
||||||
}
|
{
|
||||||
|
if (contains(*it, v))
|
||||||
void RangeSet::clearRange(uint32 minV, uint32 maxV)
|
{
|
||||||
{
|
if (it->first == v)
|
||||||
mRanges.erase(boost::icl::discrete_interval<uint32>(minV, maxV + 1));
|
{
|
||||||
|
if (it->second == v)
|
||||||
|
mRanges.erase(it);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mRanges[v + 1] = it->second;
|
||||||
|
it->second = v - 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (it->second == v)
|
||||||
|
--(it->second);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
uint32 oldEnd = it->second;
|
||||||
|
it->second = v - 1;
|
||||||
|
mRanges[v + 1] = oldEnd;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string RangeSet::toString() const
|
std::string RangeSet::toString() const
|
||||||
{
|
{
|
||||||
std::string ret;
|
std::string ret;
|
||||||
for (const_iterator it = begin(); it != end(); ++it)
|
BOOST_FOREACH(value_type const& it, mRanges)
|
||||||
{
|
{
|
||||||
if (!ret.empty())
|
if (!ret.empty())
|
||||||
ret += ",";
|
ret += ",";
|
||||||
if (lower(it) == upper(it))
|
if (it.first == it.second)
|
||||||
ret += boost::lexical_cast<std::string>(lower(it));
|
ret += boost::lexical_cast<std::string>((it.first));
|
||||||
else
|
else
|
||||||
ret += boost::lexical_cast<std::string>(lower(it)) + "-"
|
ret += boost::lexical_cast<std::string>(it.first) + "-"
|
||||||
+ boost::lexical_cast<std::string>(upper(it));
|
+ boost::lexical_cast<std::string>(it.second);
|
||||||
}
|
}
|
||||||
if (ret.empty())
|
if (ret.empty())
|
||||||
return "empty";
|
return "empty";
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RangeSet::simplify()
|
||||||
|
{
|
||||||
|
iterator it = mRanges.begin();
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
iterator nit = it;
|
||||||
|
if (++nit == mRanges.end())
|
||||||
|
return;
|
||||||
|
if (it->second >= (nit->first - 1))
|
||||||
|
{ // ranges overlap
|
||||||
|
it->second = nit->second;
|
||||||
|
mRanges.erase(nit);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
it = nit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_SUITE(RangeSet_suite)
|
BOOST_AUTO_TEST_SUITE(RangeSet_suite)
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(RangeSet_test)
|
BOOST_AUTO_TEST_CASE(RangeSet_test)
|
||||||
|
|||||||
@@ -4,15 +4,22 @@
|
|||||||
class RangeSet
|
class RangeSet
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
typedef boost::icl::interval_set<uint32> 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 uint32 RangeSetAbsent = static_cast<uint32>(-1);
|
static const uint32 RangeSetAbsent = static_cast<uint32>(-1);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
iRangeSet mRanges;
|
std::map<uint32, uint32> mRanges; // First is lowest value in range, last is highest value in range
|
||||||
|
|
||||||
|
typedef std::map<uint32, uint32>::const_iterator const_iterator;
|
||||||
|
typedef std::map<uint32, uint32>::const_reverse_iterator const_reverse_iterator;
|
||||||
|
typedef std::map<uint32, uint32>::value_type value_type;
|
||||||
|
typedef std::map<uint32, uint32>::iterator iterator;
|
||||||
|
|
||||||
|
static bool contains(value_type const& it, uint32 v)
|
||||||
|
{
|
||||||
|
return (it.first <= v) && (it.second >= v);
|
||||||
|
}
|
||||||
|
|
||||||
|
void simplify();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
@@ -29,71 +36,10 @@ public:
|
|||||||
void setValue(uint32);
|
void setValue(uint32);
|
||||||
void setRange(uint32, uint32);
|
void setRange(uint32, uint32);
|
||||||
void clearValue(uint32);
|
void clearValue(uint32);
|
||||||
void clearRange(uint32, uint32);
|
|
||||||
|
|
||||||
|
|
||||||
// iterator stuff
|
|
||||||
iterator begin() { return mRanges.begin(); }
|
|
||||||
iterator end() { return mRanges.end(); }
|
|
||||||
const_iterator begin() const { return mRanges.begin(); }
|
|
||||||
const_iterator end() const { return mRanges.end(); }
|
|
||||||
reverse_iterator rbegin() { return mRanges.rbegin(); }
|
|
||||||
reverse_iterator rend() { return mRanges.rend(); }
|
|
||||||
const_reverse_iterator rbegin() const { return mRanges.rbegin(); }
|
|
||||||
const_reverse_iterator rend() const { return mRanges.rend(); }
|
|
||||||
|
|
||||||
static uint32 lower(const_iterator& it) { return it->lower(); }
|
|
||||||
static uint32 upper(const_iterator& it) { return it->upper() - 1; }
|
|
||||||
static uint32 lower(const_reverse_iterator& it) { return it->lower(); }
|
|
||||||
static uint32 upper(const_reverse_iterator& it) { return it->upper() - 1; }
|
|
||||||
|
|
||||||
|
|
||||||
std::string toString() const;
|
std::string toString() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
inline RangeSet::const_iterator range_begin(const RangeSet& r) { return r.begin(); }
|
|
||||||
inline RangeSet::iterator range_begin(RangeSet& r) { return r.begin(); }
|
|
||||||
inline RangeSet::const_iterator range_end(const RangeSet& r) { return r.end(); }
|
|
||||||
inline RangeSet::iterator range_end(RangeSet& r) { return r.end(); }
|
|
||||||
|
|
||||||
namespace boost
|
|
||||||
{
|
|
||||||
template<> struct range_mutable_iterator<RangeSet>
|
|
||||||
{
|
|
||||||
typedef RangeSet::iterator type;
|
|
||||||
};
|
|
||||||
template<> struct range_const_iterator<RangeSet>
|
|
||||||
{
|
|
||||||
typedef RangeSet::const_iterator type;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
// VFALCO Maybe not the best place for this but it sort of makes sense here
|
|
||||||
|
|
||||||
// VFALCO NOTE these three are unused.
|
|
||||||
/*
|
|
||||||
template<typename T> T range_check(const T& value, const T& minimum, const T& maximum)
|
|
||||||
{
|
|
||||||
if ((value < minimum) || (value > maximum))
|
|
||||||
throw std::runtime_error("Value out of range");
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T> T range_check_min(const T& value, const T& minimum)
|
|
||||||
{
|
|
||||||
if (value < minimum)
|
|
||||||
throw std::runtime_error("Value out of range");
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T> T range_check_max(const T& value, const T& maximum)
|
|
||||||
{
|
|
||||||
if (value > maximum)
|
|
||||||
throw std::runtime_error("Value out of range");
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
// VFALCO TODO these parameters should not be const references.
|
// VFALCO TODO these parameters should not be const references.
|
||||||
template<typename T, typename U> T range_check_cast(const U& value, const T& minimum, const T& maximum)
|
template<typename T, typename U> T range_check_cast(const U& value, const T& minimum, const T& maximum)
|
||||||
{
|
{
|
||||||
@@ -102,6 +48,7 @@ template<typename T, typename U> T range_check_cast(const U& value, const T& min
|
|||||||
return static_cast<T>(value);
|
return static_cast<T>(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// vim:ts=4
|
// vim:ts=4
|
||||||
|
|||||||
@@ -72,7 +72,6 @@ namespace boost {
|
|||||||
|
|
||||||
// RangeSet
|
// RangeSet
|
||||||
#include <boost/foreach.hpp>
|
#include <boost/foreach.hpp>
|
||||||
#include <boost/icl/interval_set.hpp> // oof this one is ugly
|
|
||||||
|
|
||||||
// InstanceCounter
|
// InstanceCounter
|
||||||
//#include <string>
|
//#include <string>
|
||||||
|
|||||||
@@ -1021,13 +1021,13 @@ UPTR_T<STObject> STObject::parseJson(const Json::Value& object, SField::ref inNa
|
|||||||
else if (value.isInt())
|
else if (value.isInt())
|
||||||
{
|
{
|
||||||
if (value.asInt() < 0 || value.asInt() > 255)
|
if (value.asInt() < 0 || value.asInt() > 255)
|
||||||
throw std::runtime_error("value out of rand");
|
throw std::runtime_error("value out of range");
|
||||||
data.push_back(new STUInt8(field, range_check_cast<unsigned char>(value.asInt(), 0, 255)));
|
data.push_back(new STUInt8(field, range_check_cast<unsigned char>(value.asInt(), 0, 255)));
|
||||||
}
|
}
|
||||||
else if (value.isUInt())
|
else if (value.isUInt())
|
||||||
{
|
{
|
||||||
if (value.asUInt() > 255)
|
if (value.asUInt() > 255)
|
||||||
throw std::runtime_error("value out of rand");
|
throw std::runtime_error("value out of range");
|
||||||
data.push_back(new STUInt8(field, range_check_cast<unsigned char>(value.asUInt(), 0, 255)));
|
data.push_back(new STUInt8(field, range_check_cast<unsigned char>(value.asUInt(), 0, 255)));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|||||||
Reference in New Issue
Block a user