mirror of
https://github.com/Xahau/xahaud.git
synced 2025-12-06 17:27:52 +00:00
Reformatting using AStyle
This commit is contained in:
@@ -6,186 +6,195 @@
|
||||
|
||||
/** Maintains a cache of keys with no associated data.
|
||||
|
||||
The cache has a target size and an expiration time. When cached items become
|
||||
older than the maximum age they are eligible for removal during a
|
||||
call to @ref sweep.
|
||||
The cache has a target size and an expiration time. When cached items become
|
||||
older than the maximum age they are eligible for removal during a
|
||||
call to @ref sweep.
|
||||
|
||||
@note
|
||||
Timer must provide this function:
|
||||
@code
|
||||
static int getElapsedSeconds ();
|
||||
@endcode
|
||||
@note
|
||||
Timer must provide this function:
|
||||
@code
|
||||
static int getElapsedSeconds ();
|
||||
@endcode
|
||||
|
||||
file vf_db.h
|
||||
file vf_db.h
|
||||
@ingroup ripple_basics
|
||||
*/
|
||||
template <class Key, class Timer>
|
||||
class KeyCache
|
||||
{
|
||||
public:
|
||||
/** Provides a type for the key.
|
||||
*/
|
||||
typedef Key key_type;
|
||||
/** Provides a type for the key.
|
||||
*/
|
||||
typedef Key key_type;
|
||||
|
||||
/** Construct with the specified name.
|
||||
/** Construct with the specified name.
|
||||
|
||||
@param size The initial target size.
|
||||
@param age The initial expiration time.
|
||||
*/
|
||||
KeyCache (const std::string& name,
|
||||
int size = 0,
|
||||
int age = 120) : mName(name), mTargetSize(size), mTargetAge(age)
|
||||
{
|
||||
assert((size >= 0) && (age > 2));
|
||||
}
|
||||
@param size The initial target size.
|
||||
@param age The initial expiration time.
|
||||
*/
|
||||
KeyCache (const std::string& name,
|
||||
int size = 0,
|
||||
int age = 120) : mName (name), mTargetSize (size), mTargetAge (age)
|
||||
{
|
||||
assert ((size >= 0) && (age > 2));
|
||||
}
|
||||
|
||||
/** Returns the current size.
|
||||
*/
|
||||
unsigned int getSize ()
|
||||
{
|
||||
boost::mutex::scoped_lock sl(mNCLock);
|
||||
return mCache.size();
|
||||
}
|
||||
/** Returns the current size.
|
||||
*/
|
||||
unsigned int getSize ()
|
||||
{
|
||||
boost::mutex::scoped_lock sl (mNCLock);
|
||||
return mCache.size ();
|
||||
}
|
||||
|
||||
/** Returns the desired target size.
|
||||
*/
|
||||
unsigned int getTargetSize ()
|
||||
{
|
||||
boost::mutex::scoped_lock sl(mNCLock);
|
||||
return mTargetSize;
|
||||
}
|
||||
/** Returns the desired target size.
|
||||
*/
|
||||
unsigned int getTargetSize ()
|
||||
{
|
||||
boost::mutex::scoped_lock sl (mNCLock);
|
||||
return mTargetSize;
|
||||
}
|
||||
|
||||
/** Returns the desired target age.
|
||||
*/
|
||||
unsigned int getTargetAge ()
|
||||
{
|
||||
boost::mutex::scoped_lock sl(mNCLock);
|
||||
return mTargetAge;
|
||||
}
|
||||
/** Returns the desired target age.
|
||||
*/
|
||||
unsigned int getTargetAge ()
|
||||
{
|
||||
boost::mutex::scoped_lock sl (mNCLock);
|
||||
return mTargetAge;
|
||||
}
|
||||
|
||||
/** Simultaneously set the target size and age.
|
||||
/** Simultaneously set the target size and age.
|
||||
|
||||
@param size The target size.
|
||||
@param age The target age.
|
||||
*/
|
||||
void setTargets(int size, int age)
|
||||
{
|
||||
boost::mutex::scoped_lock sl(mNCLock);
|
||||
mTargetSize = size;
|
||||
mTargetAge = age;
|
||||
assert((mTargetSize >= 0) && (mTargetAge > 2));
|
||||
}
|
||||
@param size The target size.
|
||||
@param age The target age.
|
||||
*/
|
||||
void setTargets (int size, int age)
|
||||
{
|
||||
boost::mutex::scoped_lock sl (mNCLock);
|
||||
mTargetSize = size;
|
||||
mTargetAge = age;
|
||||
assert ((mTargetSize >= 0) && (mTargetAge > 2));
|
||||
}
|
||||
|
||||
/** Retrieve the name of this object.
|
||||
*/
|
||||
const std::string& getName()
|
||||
{
|
||||
return mName;
|
||||
}
|
||||
/** Retrieve the name of this object.
|
||||
*/
|
||||
const std::string& getName ()
|
||||
{
|
||||
return mName;
|
||||
}
|
||||
|
||||
/** Determine if the specified key is cached, and optionally refresh it.
|
||||
/** Determine if the specified key is cached, and optionally refresh it.
|
||||
|
||||
@param key The key to check
|
||||
@param refresh Whether or not to refresh the entry.
|
||||
@return `true` if the key was found.
|
||||
*/
|
||||
bool isPresent(const key_type& key, bool refresh = true)
|
||||
{
|
||||
boost::mutex::scoped_lock sl(mNCLock);
|
||||
@param key The key to check
|
||||
@param refresh Whether or not to refresh the entry.
|
||||
@return `true` if the key was found.
|
||||
*/
|
||||
bool isPresent (const key_type& key, bool refresh = true)
|
||||
{
|
||||
boost::mutex::scoped_lock sl (mNCLock);
|
||||
|
||||
map_iterator it = mCache.find(key);
|
||||
if (it == mCache.end())
|
||||
return false;
|
||||
if (refresh)
|
||||
it->second = Timer::getElapsedSeconds ();
|
||||
return true;
|
||||
}
|
||||
map_iterator it = mCache.find (key);
|
||||
|
||||
/** Remove the specified cache entry.
|
||||
if (it == mCache.end ())
|
||||
return false;
|
||||
|
||||
@param key The key to remove.
|
||||
@return `false` if the key was not found.
|
||||
*/
|
||||
bool del(const key_type& key)
|
||||
{
|
||||
boost::mutex::scoped_lock sl(mNCLock);
|
||||
if (refresh)
|
||||
it->second = Timer::getElapsedSeconds ();
|
||||
|
||||
map_iterator it = mCache.find(key);
|
||||
if (it == mCache.end())
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
mCache.erase(it);
|
||||
return true;
|
||||
}
|
||||
/** Remove the specified cache entry.
|
||||
|
||||
/** Add the specified cache entry.
|
||||
@param key The key to remove.
|
||||
@return `false` if the key was not found.
|
||||
*/
|
||||
bool del (const key_type& key)
|
||||
{
|
||||
boost::mutex::scoped_lock sl (mNCLock);
|
||||
|
||||
@param key The key to add.
|
||||
@return `true` if the key did not previously exist.
|
||||
*/
|
||||
bool add (const key_type& key)
|
||||
{
|
||||
boost::mutex::scoped_lock sl(mNCLock);
|
||||
map_iterator it = mCache.find (key);
|
||||
|
||||
map_iterator it = mCache.find(key);
|
||||
if (it != mCache.end())
|
||||
{
|
||||
it->second = Timer::getElapsedSeconds ();
|
||||
return false;
|
||||
}
|
||||
mCache.insert(std::make_pair(key, Timer::getElapsedSeconds ()));
|
||||
return true;
|
||||
}
|
||||
if (it == mCache.end ())
|
||||
return false;
|
||||
|
||||
/** Remove stale entries from the cache.
|
||||
*/
|
||||
void sweep ()
|
||||
{
|
||||
int now = Timer::getElapsedSeconds ();
|
||||
boost::mutex::scoped_lock sl(mNCLock);
|
||||
mCache.erase (it);
|
||||
return true;
|
||||
}
|
||||
|
||||
int target;
|
||||
if ((mTargetSize == 0) || (mCache.size() <= mTargetSize))
|
||||
target = now - mTargetAge;
|
||||
else
|
||||
{
|
||||
target = now - (mTargetAge * mTargetSize / mCache.size());
|
||||
if (target > (now - 2))
|
||||
target = now - 2;
|
||||
}
|
||||
/** Add the specified cache entry.
|
||||
|
||||
map_iterator it = mCache.begin();
|
||||
while (it != mCache.end())
|
||||
{
|
||||
if (it->second > now)
|
||||
{
|
||||
it->second = now;
|
||||
++it;
|
||||
}
|
||||
else if (it->second < target)
|
||||
{
|
||||
it = mCache.erase(it);
|
||||
}
|
||||
else
|
||||
{
|
||||
++it;
|
||||
}
|
||||
}
|
||||
}
|
||||
@param key The key to add.
|
||||
@return `true` if the key did not previously exist.
|
||||
*/
|
||||
bool add (const key_type& key)
|
||||
{
|
||||
boost::mutex::scoped_lock sl (mNCLock);
|
||||
|
||||
map_iterator it = mCache.find (key);
|
||||
|
||||
if (it != mCache.end ())
|
||||
{
|
||||
it->second = Timer::getElapsedSeconds ();
|
||||
return false;
|
||||
}
|
||||
|
||||
mCache.insert (std::make_pair (key, Timer::getElapsedSeconds ()));
|
||||
return true;
|
||||
}
|
||||
|
||||
/** Remove stale entries from the cache.
|
||||
*/
|
||||
void sweep ()
|
||||
{
|
||||
int now = Timer::getElapsedSeconds ();
|
||||
boost::mutex::scoped_lock sl (mNCLock);
|
||||
|
||||
int target;
|
||||
|
||||
if ((mTargetSize == 0) || (mCache.size () <= mTargetSize))
|
||||
target = now - mTargetAge;
|
||||
else
|
||||
{
|
||||
target = now - (mTargetAge * mTargetSize / mCache.size ());
|
||||
|
||||
if (target > (now - 2))
|
||||
target = now - 2;
|
||||
}
|
||||
|
||||
map_iterator it = mCache.begin ();
|
||||
|
||||
while (it != mCache.end ())
|
||||
{
|
||||
if (it->second > now)
|
||||
{
|
||||
it->second = now;
|
||||
++it;
|
||||
}
|
||||
else if (it->second < target)
|
||||
{
|
||||
it = mCache.erase (it);
|
||||
}
|
||||
else
|
||||
{
|
||||
++it;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
/** Provides a type for the underlying map.
|
||||
*/
|
||||
typedef boost::unordered_map<key_type, int> map_type;
|
||||
/** Provides a type for the underlying map.
|
||||
*/
|
||||
typedef boost::unordered_map<key_type, int> map_type;
|
||||
|
||||
/** The type of the iterator used for traversals.
|
||||
*/
|
||||
typedef typename map_type::iterator map_iterator;
|
||||
/** The type of the iterator used for traversals.
|
||||
*/
|
||||
typedef typename map_type::iterator map_iterator;
|
||||
|
||||
std::string const mName;
|
||||
boost::mutex mNCLock;
|
||||
map_type mCache;
|
||||
unsigned int mTargetSize, mTargetAge;
|
||||
std::string const mName;
|
||||
boost::mutex mNCLock;
|
||||
map_type mCache;
|
||||
unsigned int mTargetSize, mTargetAge;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,180 +1,206 @@
|
||||
|
||||
SETUP_LOG (RangeSet)
|
||||
|
||||
inline uint32 min(uint32 x, uint32 y) { return (x < y) ? x : y; }
|
||||
inline uint32 max(uint32 x, uint32 y) { return (x > y) ? x : y; }
|
||||
|
||||
bool RangeSet::hasValue(uint32 v) const
|
||||
inline uint32 min (uint32 x, uint32 y)
|
||||
{
|
||||
BOOST_FOREACH(const value_type& it, mRanges)
|
||||
{
|
||||
if (contains(it, v))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
return (x < y) ? x : y;
|
||||
}
|
||||
|
||||
uint32 RangeSet::getFirst() const
|
||||
inline uint32 max (uint32 x, uint32 y)
|
||||
{
|
||||
const_iterator it = mRanges.begin();
|
||||
if (it == mRanges.end())
|
||||
return RangeSetAbsent;
|
||||
return it->first;
|
||||
return (x > y) ? x : y;
|
||||
}
|
||||
|
||||
uint32 RangeSet::getNext(uint32 v) const
|
||||
bool RangeSet::hasValue (uint32 v) const
|
||||
{
|
||||
BOOST_FOREACH(const value_type& it, mRanges)
|
||||
{
|
||||
if (it.first > v)
|
||||
return it.first;
|
||||
if (contains(it, v + 1))
|
||||
return v + 1;
|
||||
}
|
||||
return RangeSetAbsent;
|
||||
BOOST_FOREACH (const value_type & it, mRanges)
|
||||
{
|
||||
if (contains (it, v))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32 RangeSet::getLast() const
|
||||
uint32 RangeSet::getFirst () const
|
||||
{
|
||||
const_reverse_iterator it = mRanges.rbegin();
|
||||
if (it == mRanges.rend())
|
||||
return RangeSetAbsent;
|
||||
return it->second;
|
||||
const_iterator it = mRanges.begin ();
|
||||
|
||||
if (it == mRanges.end ())
|
||||
return RangeSetAbsent;
|
||||
|
||||
return it->first;
|
||||
}
|
||||
|
||||
uint32 RangeSet::getPrev(uint32 v) const
|
||||
uint32 RangeSet::getNext (uint32 v) const
|
||||
{
|
||||
BOOST_REVERSE_FOREACH(const value_type& it, mRanges)
|
||||
{
|
||||
if (it.second < v)
|
||||
return it.second;
|
||||
if (contains(it, v + 1))
|
||||
return v - 1;
|
||||
}
|
||||
return RangeSetAbsent;
|
||||
BOOST_FOREACH (const value_type & it, mRanges)
|
||||
{
|
||||
if (it.first > v)
|
||||
return it.first;
|
||||
|
||||
if (contains (it, v + 1))
|
||||
return v + 1;
|
||||
}
|
||||
return RangeSetAbsent;
|
||||
}
|
||||
|
||||
uint32 RangeSet::prevMissing(uint32 v) const
|
||||
{ // largest number not in the set that is less than the given number
|
||||
BOOST_FOREACH(const value_type& it, mRanges)
|
||||
{
|
||||
if (contains(it, v))
|
||||
return it.first - 1;
|
||||
if (it.first > v)
|
||||
return v + 1;
|
||||
}
|
||||
return RangeSetAbsent;
|
||||
}
|
||||
|
||||
void RangeSet::setValue(uint32 v)
|
||||
uint32 RangeSet::getLast () const
|
||||
{
|
||||
if (!hasValue(v))
|
||||
{
|
||||
mRanges[v] = v;
|
||||
simplify();
|
||||
}
|
||||
const_reverse_iterator it = mRanges.rbegin ();
|
||||
|
||||
if (it == mRanges.rend ())
|
||||
return RangeSetAbsent;
|
||||
|
||||
return it->second;
|
||||
}
|
||||
|
||||
void RangeSet::setRange(uint32 minV, uint32 maxV)
|
||||
uint32 RangeSet::getPrev (uint32 v) const
|
||||
{
|
||||
while (hasValue(minV))
|
||||
{
|
||||
++minV;
|
||||
if (minV >= maxV)
|
||||
return;
|
||||
}
|
||||
mRanges[minV] = maxV;
|
||||
simplify();
|
||||
BOOST_REVERSE_FOREACH (const value_type & it, mRanges)
|
||||
{
|
||||
if (it.second < v)
|
||||
return it.second;
|
||||
|
||||
if (contains (it, v + 1))
|
||||
return v - 1;
|
||||
}
|
||||
return RangeSetAbsent;
|
||||
}
|
||||
|
||||
void RangeSet::clearValue(uint32 v)
|
||||
uint32 RangeSet::prevMissing (uint32 v) const
|
||||
{
|
||||
for (iterator it = mRanges.begin(); it != mRanges.end(); ++it)
|
||||
{
|
||||
if (contains(*it, v))
|
||||
{
|
||||
if (it->first == v)
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
// largest number not in the set that is less than the given number
|
||||
BOOST_FOREACH (const value_type & it, mRanges)
|
||||
{
|
||||
if (contains (it, v))
|
||||
return it.first - 1;
|
||||
|
||||
if (it.first > v)
|
||||
return v + 1;
|
||||
}
|
||||
return RangeSetAbsent;
|
||||
}
|
||||
|
||||
std::string RangeSet::toString() const
|
||||
void RangeSet::setValue (uint32 v)
|
||||
{
|
||||
std::string ret;
|
||||
BOOST_FOREACH(value_type const& it, mRanges)
|
||||
{
|
||||
if (!ret.empty())
|
||||
ret += ",";
|
||||
if (it.first == it.second)
|
||||
ret += boost::lexical_cast<std::string>((it.first));
|
||||
else
|
||||
ret += boost::lexical_cast<std::string>(it.first) + "-"
|
||||
+ boost::lexical_cast<std::string>(it.second);
|
||||
}
|
||||
if (ret.empty())
|
||||
return "empty";
|
||||
return ret;
|
||||
if (!hasValue (v))
|
||||
{
|
||||
mRanges[v] = v;
|
||||
simplify ();
|
||||
}
|
||||
}
|
||||
|
||||
void RangeSet::simplify()
|
||||
void RangeSet::setRange (uint32 minV, uint32 maxV)
|
||||
{
|
||||
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;
|
||||
}
|
||||
while (hasValue (minV))
|
||||
{
|
||||
++minV;
|
||||
|
||||
if (minV >= maxV)
|
||||
return;
|
||||
}
|
||||
|
||||
mRanges[minV] = maxV;
|
||||
simplify ();
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE(RangeSet_suite)
|
||||
|
||||
BOOST_AUTO_TEST_CASE(RangeSet_test)
|
||||
void RangeSet::clearValue (uint32 v)
|
||||
{
|
||||
WriteLog (lsTRACE, RangeSet) << "RangeSet test begins";
|
||||
for (iterator it = mRanges.begin (); it != mRanges.end (); ++it)
|
||||
{
|
||||
if (contains (*it, v))
|
||||
{
|
||||
if (it->first == v)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
RangeSet r1, r2;
|
||||
|
||||
r1.setRange(1,10);
|
||||
r1.clearValue(5);
|
||||
r1.setRange(11, 20);
|
||||
|
||||
r2.setRange(1, 4);
|
||||
r2.setRange(6, 10);
|
||||
r2.setRange(10, 20);
|
||||
if (r1.hasValue(5)) BOOST_FAIL("RangeSet fail");
|
||||
if (!r2.hasValue(9)) BOOST_FAIL("RangeSet fail");
|
||||
|
||||
// TODO: Traverse functions must be tested
|
||||
|
||||
WriteLog (lsTRACE, RangeSet) << "RangeSet test complete";
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
||||
std::string RangeSet::toString () const
|
||||
{
|
||||
std::string ret;
|
||||
BOOST_FOREACH (value_type const & it, mRanges)
|
||||
{
|
||||
if (!ret.empty ())
|
||||
ret += ",";
|
||||
|
||||
if (it.first == it.second)
|
||||
ret += boost::lexical_cast<std::string> ((it.first));
|
||||
else
|
||||
ret += boost::lexical_cast<std::string> (it.first) + "-"
|
||||
+ boost::lexical_cast<std::string> (it.second);
|
||||
}
|
||||
|
||||
if (ret.empty ())
|
||||
return "empty";
|
||||
|
||||
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_CASE (RangeSet_test)
|
||||
{
|
||||
WriteLog (lsTRACE, RangeSet) << "RangeSet test begins";
|
||||
|
||||
RangeSet r1, r2;
|
||||
|
||||
r1.setRange (1, 10);
|
||||
r1.clearValue (5);
|
||||
r1.setRange (11, 20);
|
||||
|
||||
r2.setRange (1, 4);
|
||||
r2.setRange (6, 10);
|
||||
r2.setRange (10, 20);
|
||||
|
||||
if (r1.hasValue (5)) BOOST_FAIL ("RangeSet fail");
|
||||
|
||||
if (!r2.hasValue (9)) BOOST_FAIL ("RangeSet fail");
|
||||
|
||||
// TODO: Traverse functions must be tested
|
||||
|
||||
WriteLog (lsTRACE, RangeSet) << "RangeSet test complete";
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END ()
|
||||
|
||||
// vim:ts=4
|
||||
|
||||
@@ -4,47 +4,48 @@
|
||||
class RangeSet
|
||||
{
|
||||
public:
|
||||
static const uint32 RangeSetAbsent = static_cast<uint32>(-1);
|
||||
static const uint32 RangeSetAbsent = static_cast<uint32> (-1);
|
||||
|
||||
protected:
|
||||
std::map<uint32, uint32> mRanges; // First is lowest value in range, last is highest value in range
|
||||
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;
|
||||
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);
|
||||
}
|
||||
static bool contains (value_type const& it, uint32 v)
|
||||
{
|
||||
return (it.first <= v) && (it.second >= v);
|
||||
}
|
||||
|
||||
void simplify();
|
||||
void simplify ();
|
||||
|
||||
public:
|
||||
RangeSet () { }
|
||||
RangeSet () { }
|
||||
|
||||
bool hasValue(uint32) const;
|
||||
uint32 getFirst() const;
|
||||
uint32 getNext(uint32) const;
|
||||
uint32 getLast() const;
|
||||
uint32 getPrev(uint32) const;
|
||||
bool hasValue (uint32) const;
|
||||
uint32 getFirst () const;
|
||||
uint32 getNext (uint32) const;
|
||||
uint32 getLast () const;
|
||||
uint32 getPrev (uint32) const;
|
||||
|
||||
uint32 prevMissing(uint32) const; // largest number not in the set that is less than the given number
|
||||
uint32 prevMissing (uint32) const; // largest number not in the set that is less than the given number
|
||||
|
||||
void setValue(uint32);
|
||||
void setRange(uint32, uint32);
|
||||
void clearValue(uint32);
|
||||
void setValue (uint32);
|
||||
void setRange (uint32, uint32);
|
||||
void clearValue (uint32);
|
||||
|
||||
std::string toString() const;
|
||||
std::string toString () const;
|
||||
};
|
||||
|
||||
// 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)
|
||||
{
|
||||
if ((value < minimum) || (value > maximum))
|
||||
throw std::runtime_error("Value out of range");
|
||||
return static_cast<T>(value);
|
||||
if ((value < minimum) || (value > maximum))
|
||||
throw std::runtime_error ("Value out of range");
|
||||
|
||||
return static_cast<T> (value);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -9,41 +9,46 @@
|
||||
template<typename T>
|
||||
struct secure_allocator : public std::allocator<T>
|
||||
{
|
||||
// MSVC8 default copy constructor is broken
|
||||
typedef std::allocator<T> base;
|
||||
typedef typename base::size_type size_type;
|
||||
typedef typename base::difference_type difference_type;
|
||||
typedef typename base::pointer pointer;
|
||||
typedef typename base::const_pointer const_pointer;
|
||||
typedef typename base::reference reference;
|
||||
typedef typename base::const_reference const_reference;
|
||||
typedef typename base::value_type value_type;
|
||||
secure_allocator() throw() {}
|
||||
secure_allocator(const secure_allocator& a) throw() : base(a) {}
|
||||
template <typename U>
|
||||
secure_allocator(const secure_allocator<U>& a) throw() : base(a) {}
|
||||
~secure_allocator() throw() {}
|
||||
template<typename _Other> struct rebind
|
||||
{ typedef secure_allocator<_Other> other; };
|
||||
// MSVC8 default copy constructor is broken
|
||||
typedef std::allocator<T> base;
|
||||
typedef typename base::size_type size_type;
|
||||
typedef typename base::difference_type difference_type;
|
||||
typedef typename base::pointer pointer;
|
||||
typedef typename base::const_pointer const_pointer;
|
||||
typedef typename base::reference reference;
|
||||
typedef typename base::const_reference const_reference;
|
||||
typedef typename base::value_type value_type;
|
||||
secure_allocator () throw () {}
|
||||
secure_allocator (const secure_allocator& a) throw () : base (a) {}
|
||||
template <typename U>
|
||||
secure_allocator (const secure_allocator<U>& a) throw () : base (a) {}
|
||||
~secure_allocator () throw () {}
|
||||
template<typename _Other> struct rebind
|
||||
{
|
||||
typedef secure_allocator<_Other> other;
|
||||
};
|
||||
|
||||
T* allocate(std::size_t n, const void *hint = 0)
|
||||
{
|
||||
T *p;
|
||||
p = std::allocator<T>::allocate(n, hint);
|
||||
if (p != NULL)
|
||||
mlock(p, sizeof(T) * n);
|
||||
return p;
|
||||
}
|
||||
T* allocate (std::size_t n, const void* hint = 0)
|
||||
{
|
||||
T* p;
|
||||
p = std::allocator<T>::allocate (n, hint);
|
||||
|
||||
void deallocate(T* p, std::size_t n)
|
||||
{
|
||||
if (p != NULL)
|
||||
{
|
||||
memset(p, 0, sizeof(T) * n);
|
||||
munlock(p, sizeof(T) * n);
|
||||
}
|
||||
std::allocator<T>::deallocate(p, n);
|
||||
}
|
||||
if (p != NULL)
|
||||
mlock (p, sizeof (T) * n);
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
void deallocate (T* p, std::size_t n)
|
||||
{
|
||||
if (p != NULL)
|
||||
{
|
||||
memset (p, 0, sizeof (T) * n);
|
||||
munlock (p, sizeof (T) * n);
|
||||
}
|
||||
|
||||
std::allocator<T>::deallocate (p, n);
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -16,367 +16,423 @@ struct TaggedCacheLog;
|
||||
|
||||
/** Combination cache/map container.
|
||||
|
||||
NOTE:
|
||||
NOTE:
|
||||
|
||||
Timer must have this interface:
|
||||
Timer must have this interface:
|
||||
|
||||
static int Timer::getElapsedSeconds ();
|
||||
static int Timer::getElapsedSeconds ();
|
||||
*/
|
||||
template <typename c_Key, typename c_Data, class Timer>
|
||||
class TaggedCache
|
||||
{
|
||||
public:
|
||||
typedef c_Key key_type;
|
||||
typedef c_Data data_type;
|
||||
typedef boost::weak_ptr<data_type> weak_data_ptr;
|
||||
typedef boost::shared_ptr<data_type> data_ptr;
|
||||
typedef c_Key key_type;
|
||||
typedef c_Data data_type;
|
||||
typedef boost::weak_ptr<data_type> weak_data_ptr;
|
||||
typedef boost::shared_ptr<data_type> data_ptr;
|
||||
|
||||
public:
|
||||
TaggedCache(const char *name, int size, int age)
|
||||
: mName(name)
|
||||
, mTargetSize(size)
|
||||
, mTargetAge(age)
|
||||
, mCacheCount(0)
|
||||
, mLastSweep(Timer::getElapsedSeconds())
|
||||
, mHits(0)
|
||||
, mMisses(0)
|
||||
{
|
||||
}
|
||||
TaggedCache (const char* name, int size, int age)
|
||||
: mName (name)
|
||||
, mTargetSize (size)
|
||||
, mTargetAge (age)
|
||||
, mCacheCount (0)
|
||||
, mLastSweep (Timer::getElapsedSeconds ())
|
||||
, mHits (0)
|
||||
, mMisses (0)
|
||||
{
|
||||
}
|
||||
|
||||
int getTargetSize() const;
|
||||
int getTargetAge() const;
|
||||
int getTargetSize () const;
|
||||
int getTargetAge () const;
|
||||
|
||||
int getCacheSize();
|
||||
int getTrackSize();
|
||||
float getHitRate();
|
||||
void clearStats();
|
||||
int getCacheSize ();
|
||||
int getTrackSize ();
|
||||
float getHitRate ();
|
||||
void clearStats ();
|
||||
|
||||
void setTargetSize(int size);
|
||||
void setTargetAge(int age);
|
||||
void sweep();
|
||||
void clear();
|
||||
void setTargetSize (int size);
|
||||
void setTargetAge (int age);
|
||||
void sweep ();
|
||||
void clear ();
|
||||
|
||||
bool touch(const key_type& key);
|
||||
bool del(const key_type& key, bool valid);
|
||||
bool canonicalize(const key_type& key, boost::shared_ptr<c_Data>& data, bool replace = false);
|
||||
bool store(const key_type& key, const c_Data& data);
|
||||
boost::shared_ptr<c_Data> fetch(const key_type& key);
|
||||
bool retrieve(const key_type& key, c_Data& data);
|
||||
bool touch (const key_type& key);
|
||||
bool del (const key_type& key, bool valid);
|
||||
bool canonicalize (const key_type& key, boost::shared_ptr<c_Data>& data, bool replace = false);
|
||||
bool store (const key_type& key, const c_Data& data);
|
||||
boost::shared_ptr<c_Data> fetch (const key_type& key);
|
||||
bool retrieve (const key_type& key, c_Data& data);
|
||||
|
||||
boost::recursive_mutex& peekMutex() { return mLock; }
|
||||
boost::recursive_mutex& peekMutex ()
|
||||
{
|
||||
return mLock;
|
||||
}
|
||||
|
||||
private:
|
||||
class cache_entry
|
||||
{
|
||||
public:
|
||||
int last_use;
|
||||
data_ptr ptr;
|
||||
weak_data_ptr weak_ptr;
|
||||
class cache_entry
|
||||
{
|
||||
public:
|
||||
int last_use;
|
||||
data_ptr ptr;
|
||||
weak_data_ptr weak_ptr;
|
||||
|
||||
cache_entry(int l, const data_ptr& d) : last_use(l), ptr(d), weak_ptr(d) { ; }
|
||||
bool isWeak() { return !ptr; }
|
||||
bool isCached() { return !!ptr; }
|
||||
bool isExpired() { return weak_ptr.expired(); }
|
||||
data_ptr lock() { return weak_ptr.lock(); }
|
||||
void touch() { last_use = Timer::getElapsedSeconds (); }
|
||||
};
|
||||
cache_entry (int l, const data_ptr& d) : last_use (l), ptr (d), weak_ptr (d)
|
||||
{
|
||||
;
|
||||
}
|
||||
bool isWeak ()
|
||||
{
|
||||
return !ptr;
|
||||
}
|
||||
bool isCached ()
|
||||
{
|
||||
return !!ptr;
|
||||
}
|
||||
bool isExpired ()
|
||||
{
|
||||
return weak_ptr.expired ();
|
||||
}
|
||||
data_ptr lock ()
|
||||
{
|
||||
return weak_ptr.lock ();
|
||||
}
|
||||
void touch ()
|
||||
{
|
||||
last_use = Timer::getElapsedSeconds ();
|
||||
}
|
||||
};
|
||||
|
||||
typedef std::pair<key_type, cache_entry> cache_pair;
|
||||
typedef boost::unordered_map<key_type, cache_entry> cache_type;
|
||||
typedef typename cache_type::iterator cache_iterator;
|
||||
typedef std::pair<key_type, cache_entry> cache_pair;
|
||||
typedef boost::unordered_map<key_type, cache_entry> cache_type;
|
||||
typedef typename cache_type::iterator cache_iterator;
|
||||
|
||||
mutable boost::recursive_mutex mLock;
|
||||
mutable boost::recursive_mutex mLock;
|
||||
|
||||
std::string mName; // Used for logging
|
||||
int mTargetSize; // Desired number of cache entries (0 = ignore)
|
||||
int mTargetAge; // Desired maximum cache age
|
||||
int mCacheCount; // Number of items cached
|
||||
std::string mName; // Used for logging
|
||||
int mTargetSize; // Desired number of cache entries (0 = ignore)
|
||||
int mTargetAge; // Desired maximum cache age
|
||||
int mCacheCount; // Number of items cached
|
||||
|
||||
cache_type mCache; // Hold strong reference to recent objects
|
||||
int mLastSweep;
|
||||
cache_type mCache; // Hold strong reference to recent objects
|
||||
int mLastSweep;
|
||||
|
||||
uint64 mHits, mMisses;
|
||||
uint64 mHits, mMisses;
|
||||
};
|
||||
|
||||
template<typename c_Key, typename c_Data, class Timer>
|
||||
int TaggedCache<c_Key, c_Data, Timer>::getTargetSize() const
|
||||
int TaggedCache<c_Key, c_Data, Timer>::getTargetSize () const
|
||||
{
|
||||
boost::recursive_mutex::scoped_lock sl(mLock);
|
||||
return mTargetSize;
|
||||
boost::recursive_mutex::scoped_lock sl (mLock);
|
||||
return mTargetSize;
|
||||
}
|
||||
|
||||
template<typename c_Key, typename c_Data, class Timer>
|
||||
void TaggedCache<c_Key, c_Data, Timer>::setTargetSize(int s)
|
||||
void TaggedCache<c_Key, c_Data, Timer>::setTargetSize (int s)
|
||||
{
|
||||
boost::recursive_mutex::scoped_lock sl(mLock);
|
||||
mTargetSize = s;
|
||||
if (s > 0)
|
||||
mCache.rehash(static_cast<std::size_t>((s + (s >> 2)) / mCache.max_load_factor() + 1));
|
||||
WriteLog (lsDEBUG, TaggedCacheLog) << mName << " target size set to " << s;
|
||||
boost::recursive_mutex::scoped_lock sl (mLock);
|
||||
mTargetSize = s;
|
||||
|
||||
if (s > 0)
|
||||
mCache.rehash (static_cast<std::size_t> ((s + (s >> 2)) / mCache.max_load_factor () + 1));
|
||||
|
||||
WriteLog (lsDEBUG, TaggedCacheLog) << mName << " target size set to " << s;
|
||||
}
|
||||
|
||||
template<typename c_Key, typename c_Data, class Timer>
|
||||
int TaggedCache<c_Key, c_Data, Timer>::getTargetAge() const
|
||||
int TaggedCache<c_Key, c_Data, Timer>::getTargetAge () const
|
||||
{
|
||||
boost::recursive_mutex::scoped_lock sl(mLock);
|
||||
return mTargetAge;
|
||||
boost::recursive_mutex::scoped_lock sl (mLock);
|
||||
return mTargetAge;
|
||||
}
|
||||
|
||||
template<typename c_Key, typename c_Data, class Timer>
|
||||
void TaggedCache<c_Key, c_Data, Timer>::setTargetAge(int s)
|
||||
void TaggedCache<c_Key, c_Data, Timer>::setTargetAge (int s)
|
||||
{
|
||||
boost::recursive_mutex::scoped_lock sl(mLock);
|
||||
mTargetAge = s;
|
||||
WriteLog (lsDEBUG, TaggedCacheLog) << mName << " target age set to " << s;
|
||||
boost::recursive_mutex::scoped_lock sl (mLock);
|
||||
mTargetAge = s;
|
||||
WriteLog (lsDEBUG, TaggedCacheLog) << mName << " target age set to " << s;
|
||||
}
|
||||
|
||||
template<typename c_Key, typename c_Data, class Timer>
|
||||
int TaggedCache<c_Key, c_Data, Timer>::getCacheSize()
|
||||
int TaggedCache<c_Key, c_Data, Timer>::getCacheSize ()
|
||||
{
|
||||
boost::recursive_mutex::scoped_lock sl(mLock);
|
||||
return mCacheCount;
|
||||
boost::recursive_mutex::scoped_lock sl (mLock);
|
||||
return mCacheCount;
|
||||
}
|
||||
|
||||
template<typename c_Key, typename c_Data, class Timer>
|
||||
int TaggedCache<c_Key, c_Data, Timer>::getTrackSize()
|
||||
int TaggedCache<c_Key, c_Data, Timer>::getTrackSize ()
|
||||
{
|
||||
boost::recursive_mutex::scoped_lock sl(mLock);
|
||||
return mCache.size();
|
||||
boost::recursive_mutex::scoped_lock sl (mLock);
|
||||
return mCache.size ();
|
||||
}
|
||||
|
||||
template<typename c_Key, typename c_Data, class Timer>
|
||||
float TaggedCache<c_Key, c_Data, Timer>::getHitRate()
|
||||
float TaggedCache<c_Key, c_Data, Timer>::getHitRate ()
|
||||
{
|
||||
boost::recursive_mutex::scoped_lock sl(mLock);
|
||||
return (static_cast<float>(mHits) * 100) / (1.0f + mHits + mMisses);
|
||||
boost::recursive_mutex::scoped_lock sl (mLock);
|
||||
return (static_cast<float> (mHits) * 100) / (1.0f + mHits + mMisses);
|
||||
}
|
||||
|
||||
template<typename c_Key, typename c_Data, class Timer>
|
||||
void TaggedCache<c_Key, c_Data, Timer>::clearStats()
|
||||
void TaggedCache<c_Key, c_Data, Timer>::clearStats ()
|
||||
{
|
||||
boost::recursive_mutex::scoped_lock sl(mLock);
|
||||
mHits = 0;
|
||||
mMisses = 0;
|
||||
boost::recursive_mutex::scoped_lock sl (mLock);
|
||||
mHits = 0;
|
||||
mMisses = 0;
|
||||
}
|
||||
|
||||
template<typename c_Key, typename c_Data, class Timer>
|
||||
void TaggedCache<c_Key, c_Data, Timer>::clear()
|
||||
void TaggedCache<c_Key, c_Data, Timer>::clear ()
|
||||
{
|
||||
boost::recursive_mutex::scoped_lock sl(mLock);
|
||||
mCache.clear();
|
||||
mCacheCount = 0;
|
||||
boost::recursive_mutex::scoped_lock sl (mLock);
|
||||
mCache.clear ();
|
||||
mCacheCount = 0;
|
||||
}
|
||||
|
||||
template<typename c_Key, typename c_Data, class Timer>
|
||||
void TaggedCache<c_Key, c_Data, Timer>::sweep()
|
||||
void TaggedCache<c_Key, c_Data, Timer>::sweep ()
|
||||
{
|
||||
boost::recursive_mutex::scoped_lock sl(mLock);
|
||||
boost::recursive_mutex::scoped_lock sl (mLock);
|
||||
|
||||
int mLastSweep = Timer::getElapsedSeconds ();
|
||||
int target = mLastSweep - mTargetAge;
|
||||
int cacheRemovals = 0, mapRemovals = 0, cc = 0;
|
||||
int mLastSweep = Timer::getElapsedSeconds ();
|
||||
int target = mLastSweep - mTargetAge;
|
||||
int cacheRemovals = 0, mapRemovals = 0, cc = 0;
|
||||
|
||||
if ((mTargetSize != 0) && (static_cast<int>(mCache.size()) > mTargetSize))
|
||||
{
|
||||
target = mLastSweep - (mTargetAge * mTargetSize / mCache.size());
|
||||
if (target > (mLastSweep - 2))
|
||||
target = mLastSweep - 2;
|
||||
WriteLog (lsINFO, TaggedCacheLog) << mName << " is growing fast " <<
|
||||
mCache.size() << " of " << mTargetSize <<
|
||||
" aging at " << (mLastSweep - target) << " of " << mTargetAge;
|
||||
}
|
||||
if ((mTargetSize != 0) && (static_cast<int> (mCache.size ()) > mTargetSize))
|
||||
{
|
||||
target = mLastSweep - (mTargetAge * mTargetSize / mCache.size ());
|
||||
|
||||
cache_iterator cit = mCache.begin();
|
||||
while (cit != mCache.end())
|
||||
{
|
||||
if (cit->second.isWeak())
|
||||
{ // weak
|
||||
if (cit->second.isExpired())
|
||||
{
|
||||
++mapRemovals;
|
||||
cit = mCache.erase(cit);
|
||||
}
|
||||
else
|
||||
++cit;
|
||||
}
|
||||
else if (cit->second.last_use < target)
|
||||
{ // strong, expired
|
||||
--mCacheCount;
|
||||
++cacheRemovals;
|
||||
cit->second.ptr.reset();
|
||||
if (cit->second.isExpired())
|
||||
{
|
||||
++mapRemovals;
|
||||
cit = mCache.erase(cit);
|
||||
}
|
||||
else // remains weakly cached
|
||||
++cit;
|
||||
}
|
||||
else
|
||||
{ // strong, not expired
|
||||
++cc;
|
||||
++cit;
|
||||
}
|
||||
}
|
||||
if (target > (mLastSweep - 2))
|
||||
target = mLastSweep - 2;
|
||||
|
||||
assert(cc == mCacheCount);
|
||||
if (ShouldLog (lsTRACE, TaggedCacheLog) && (mapRemovals || cacheRemovals))
|
||||
{
|
||||
WriteLog (lsTRACE, TaggedCacheLog) << mName << ": cache = " << mCache.size() << "-" << cacheRemovals <<
|
||||
", map-=" << mapRemovals;
|
||||
}
|
||||
WriteLog (lsINFO, TaggedCacheLog) << mName << " is growing fast " <<
|
||||
mCache.size () << " of " << mTargetSize <<
|
||||
" aging at " << (mLastSweep - target) << " of " << mTargetAge;
|
||||
}
|
||||
|
||||
cache_iterator cit = mCache.begin ();
|
||||
|
||||
while (cit != mCache.end ())
|
||||
{
|
||||
if (cit->second.isWeak ())
|
||||
{
|
||||
// weak
|
||||
if (cit->second.isExpired ())
|
||||
{
|
||||
++mapRemovals;
|
||||
cit = mCache.erase (cit);
|
||||
}
|
||||
else
|
||||
++cit;
|
||||
}
|
||||
else if (cit->second.last_use < target)
|
||||
{
|
||||
// strong, expired
|
||||
--mCacheCount;
|
||||
++cacheRemovals;
|
||||
cit->second.ptr.reset ();
|
||||
|
||||
if (cit->second.isExpired ())
|
||||
{
|
||||
++mapRemovals;
|
||||
cit = mCache.erase (cit);
|
||||
}
|
||||
else // remains weakly cached
|
||||
++cit;
|
||||
}
|
||||
else
|
||||
{
|
||||
// strong, not expired
|
||||
++cc;
|
||||
++cit;
|
||||
}
|
||||
}
|
||||
|
||||
assert (cc == mCacheCount);
|
||||
|
||||
if (ShouldLog (lsTRACE, TaggedCacheLog) && (mapRemovals || cacheRemovals))
|
||||
{
|
||||
WriteLog (lsTRACE, TaggedCacheLog) << mName << ": cache = " << mCache.size () << "-" << cacheRemovals <<
|
||||
", map-=" << mapRemovals;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename c_Key, typename c_Data, class Timer>
|
||||
bool TaggedCache<c_Key, c_Data, Timer>::touch(const key_type& key)
|
||||
{ // If present, make current in cache
|
||||
boost::recursive_mutex::scoped_lock sl(mLock);
|
||||
|
||||
cache_iterator cit = mCache.find(key);
|
||||
if (cit == mCache.end()) // Don't have the object
|
||||
return false;
|
||||
cache_entry& entry = cit->second;
|
||||
|
||||
if (entry.isCached())
|
||||
{
|
||||
entry.touch();
|
||||
return true;
|
||||
}
|
||||
|
||||
entry.ptr = entry.lock();
|
||||
if (entry.isCached())
|
||||
{ // We just put the object back in cache
|
||||
++mCacheCount;
|
||||
entry.touch();
|
||||
return true;
|
||||
}
|
||||
|
||||
// Object fell out
|
||||
mCache.erase(cit);
|
||||
return false;
|
||||
}
|
||||
|
||||
template<typename c_Key, typename c_Data, class Timer>
|
||||
bool TaggedCache<c_Key, c_Data, Timer>::del(const key_type& key, bool valid)
|
||||
{ // Remove from cache, if !valid, remove from map too. Returns true if removed from cache
|
||||
boost::recursive_mutex::scoped_lock sl(mLock);
|
||||
|
||||
cache_iterator cit = mCache.find(key);
|
||||
if (cit == mCache.end())
|
||||
return false;
|
||||
cache_entry& entry = cit->second;
|
||||
|
||||
bool ret = false;
|
||||
if (entry.isCached())
|
||||
{
|
||||
--mCacheCount;
|
||||
entry.ptr.reset();
|
||||
ret = true;
|
||||
}
|
||||
|
||||
if (!valid || entry.isExpired())
|
||||
mCache.erase(cit);
|
||||
return ret;
|
||||
}
|
||||
|
||||
template<typename c_Key, typename c_Data, class Timer>
|
||||
bool TaggedCache<c_Key, c_Data, Timer>::canonicalize(const key_type& key, boost::shared_ptr<c_Data>& data, bool replace)
|
||||
{ // Return canonical value, store if needed, refresh in cache
|
||||
// Return values: true=we had the data already
|
||||
boost::recursive_mutex::scoped_lock sl(mLock);
|
||||
|
||||
cache_iterator cit = mCache.find(key);
|
||||
if (cit == mCache.end())
|
||||
{
|
||||
mCache.insert(cache_pair(key, cache_entry(Timer::getElapsedSeconds(), data)));
|
||||
++mCacheCount;
|
||||
return false;
|
||||
}
|
||||
cache_entry& entry = cit->second;
|
||||
entry.touch();
|
||||
|
||||
if (entry.isCached())
|
||||
{
|
||||
if (replace)
|
||||
{
|
||||
entry.ptr = data;
|
||||
entry.weak_ptr = data;
|
||||
}
|
||||
else
|
||||
data = entry.ptr;
|
||||
return true;
|
||||
}
|
||||
|
||||
data_ptr cachedData = entry.lock();
|
||||
if (cachedData)
|
||||
{
|
||||
if (replace)
|
||||
{
|
||||
entry.ptr = data;
|
||||
entry.weak_ptr = data;
|
||||
}
|
||||
else
|
||||
{
|
||||
entry.ptr = cachedData;
|
||||
data = cachedData;
|
||||
}
|
||||
++mCacheCount;
|
||||
return true;
|
||||
}
|
||||
|
||||
entry.ptr = data;
|
||||
entry.weak_ptr = data;
|
||||
++mCacheCount;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
template<typename c_Key, typename c_Data, class Timer>
|
||||
boost::shared_ptr<c_Data> TaggedCache<c_Key, c_Data, Timer>::fetch(const key_type& key)
|
||||
{ // fetch us a shared pointer to the stored data object
|
||||
boost::recursive_mutex::scoped_lock sl(mLock);
|
||||
|
||||
cache_iterator cit = mCache.find(key);
|
||||
if (cit == mCache.end())
|
||||
{
|
||||
++mMisses;
|
||||
return data_ptr();
|
||||
}
|
||||
cache_entry& entry = cit->second;
|
||||
entry.touch();
|
||||
|
||||
if (entry.isCached())
|
||||
{
|
||||
++mHits;
|
||||
return entry.ptr;
|
||||
}
|
||||
|
||||
entry.ptr = entry.lock();
|
||||
if (entry.isCached())
|
||||
{ // independent of cache size, so not counted as a hit
|
||||
++mCacheCount;
|
||||
return entry.ptr;
|
||||
}
|
||||
mCache.erase(cit);
|
||||
++mMisses;
|
||||
return data_ptr();
|
||||
}
|
||||
|
||||
template<typename c_Key, typename c_Data, class Timer>
|
||||
bool TaggedCache<c_Key, c_Data, Timer>::store(const key_type& key, const c_Data& data)
|
||||
bool TaggedCache<c_Key, c_Data, Timer>::touch (const key_type& key)
|
||||
{
|
||||
data_ptr d = boost::make_shared<c_Data>(boost::cref(data));
|
||||
return canonicalize(key, d);
|
||||
// If present, make current in cache
|
||||
boost::recursive_mutex::scoped_lock sl (mLock);
|
||||
|
||||
cache_iterator cit = mCache.find (key);
|
||||
|
||||
if (cit == mCache.end ()) // Don't have the object
|
||||
return false;
|
||||
|
||||
cache_entry& entry = cit->second;
|
||||
|
||||
if (entry.isCached ())
|
||||
{
|
||||
entry.touch ();
|
||||
return true;
|
||||
}
|
||||
|
||||
entry.ptr = entry.lock ();
|
||||
|
||||
if (entry.isCached ())
|
||||
{
|
||||
// We just put the object back in cache
|
||||
++mCacheCount;
|
||||
entry.touch ();
|
||||
return true;
|
||||
}
|
||||
|
||||
// Object fell out
|
||||
mCache.erase (cit);
|
||||
return false;
|
||||
}
|
||||
|
||||
template<typename c_Key, typename c_Data, class Timer>
|
||||
bool TaggedCache<c_Key, c_Data, Timer>::retrieve(const key_type& key, c_Data& data)
|
||||
{ // retrieve the value of the stored data
|
||||
data_ptr entry = fetch(key);
|
||||
if (!entry)
|
||||
return false;
|
||||
data = *entry;
|
||||
return true;
|
||||
bool TaggedCache<c_Key, c_Data, Timer>::del (const key_type& key, bool valid)
|
||||
{
|
||||
// Remove from cache, if !valid, remove from map too. Returns true if removed from cache
|
||||
boost::recursive_mutex::scoped_lock sl (mLock);
|
||||
|
||||
cache_iterator cit = mCache.find (key);
|
||||
|
||||
if (cit == mCache.end ())
|
||||
return false;
|
||||
|
||||
cache_entry& entry = cit->second;
|
||||
|
||||
bool ret = false;
|
||||
|
||||
if (entry.isCached ())
|
||||
{
|
||||
--mCacheCount;
|
||||
entry.ptr.reset ();
|
||||
ret = true;
|
||||
}
|
||||
|
||||
if (!valid || entry.isExpired ())
|
||||
mCache.erase (cit);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
template<typename c_Key, typename c_Data, class Timer>
|
||||
bool TaggedCache<c_Key, c_Data, Timer>::canonicalize (const key_type& key, boost::shared_ptr<c_Data>& data, bool replace)
|
||||
{
|
||||
// Return canonical value, store if needed, refresh in cache
|
||||
// Return values: true=we had the data already
|
||||
boost::recursive_mutex::scoped_lock sl (mLock);
|
||||
|
||||
cache_iterator cit = mCache.find (key);
|
||||
|
||||
if (cit == mCache.end ())
|
||||
{
|
||||
mCache.insert (cache_pair (key, cache_entry (Timer::getElapsedSeconds (), data)));
|
||||
++mCacheCount;
|
||||
return false;
|
||||
}
|
||||
|
||||
cache_entry& entry = cit->second;
|
||||
entry.touch ();
|
||||
|
||||
if (entry.isCached ())
|
||||
{
|
||||
if (replace)
|
||||
{
|
||||
entry.ptr = data;
|
||||
entry.weak_ptr = data;
|
||||
}
|
||||
else
|
||||
data = entry.ptr;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
data_ptr cachedData = entry.lock ();
|
||||
|
||||
if (cachedData)
|
||||
{
|
||||
if (replace)
|
||||
{
|
||||
entry.ptr = data;
|
||||
entry.weak_ptr = data;
|
||||
}
|
||||
else
|
||||
{
|
||||
entry.ptr = cachedData;
|
||||
data = cachedData;
|
||||
}
|
||||
|
||||
++mCacheCount;
|
||||
return true;
|
||||
}
|
||||
|
||||
entry.ptr = data;
|
||||
entry.weak_ptr = data;
|
||||
++mCacheCount;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
template<typename c_Key, typename c_Data, class Timer>
|
||||
boost::shared_ptr<c_Data> TaggedCache<c_Key, c_Data, Timer>::fetch (const key_type& key)
|
||||
{
|
||||
// fetch us a shared pointer to the stored data object
|
||||
boost::recursive_mutex::scoped_lock sl (mLock);
|
||||
|
||||
cache_iterator cit = mCache.find (key);
|
||||
|
||||
if (cit == mCache.end ())
|
||||
{
|
||||
++mMisses;
|
||||
return data_ptr ();
|
||||
}
|
||||
|
||||
cache_entry& entry = cit->second;
|
||||
entry.touch ();
|
||||
|
||||
if (entry.isCached ())
|
||||
{
|
||||
++mHits;
|
||||
return entry.ptr;
|
||||
}
|
||||
|
||||
entry.ptr = entry.lock ();
|
||||
|
||||
if (entry.isCached ())
|
||||
{
|
||||
// independent of cache size, so not counted as a hit
|
||||
++mCacheCount;
|
||||
return entry.ptr;
|
||||
}
|
||||
|
||||
mCache.erase (cit);
|
||||
++mMisses;
|
||||
return data_ptr ();
|
||||
}
|
||||
|
||||
template<typename c_Key, typename c_Data, class Timer>
|
||||
bool TaggedCache<c_Key, c_Data, Timer>::store (const key_type& key, const c_Data& data)
|
||||
{
|
||||
data_ptr d = boost::make_shared<c_Data> (boost::cref (data));
|
||||
return canonicalize (key, d);
|
||||
}
|
||||
|
||||
template<typename c_Key, typename c_Data, class Timer>
|
||||
bool TaggedCache<c_Key, c_Data, Timer>::retrieve (const key_type& key, c_Data& data)
|
||||
{
|
||||
// retrieve the value of the stored data
|
||||
data_ptr entry = fetch (key);
|
||||
|
||||
if (!entry)
|
||||
return false;
|
||||
|
||||
data = *entry;
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,22 +1,22 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
Copyright (c) 2011-2013, OpenCoin, Inc.
|
||||
Copyright (c) 2011-2013, OpenCoin, Inc.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
/** Add this to get the @ref ripple_basics module.
|
||||
/** Add this to get the @ref ripple_basics module.
|
||||
|
||||
@file ripple_basics.cpp
|
||||
@ingroup ripple_basics
|
||||
|
||||
@@ -1,32 +1,32 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
Copyright (c) 2011-2013, OpenCoin, Inc.
|
||||
Copyright (c) 2011-2013, OpenCoin, Inc.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
/** Include this to get the @ref ripple_basics module.
|
||||
/** Include this to get the @ref ripple_basics module.
|
||||
|
||||
@file ripple_basics.h
|
||||
@ingroup ripple_basics
|
||||
*/
|
||||
|
||||
/** Basic classes.
|
||||
/** Basic classes.
|
||||
|
||||
This module provides utility classes and types used in the Ripple system.
|
||||
This module provides utility classes and types used in the Ripple system.
|
||||
|
||||
@defgroup ripple_basics
|
||||
@defgroup ripple_basics
|
||||
*/
|
||||
|
||||
#ifndef RIPPLE_BASICS_H
|
||||
@@ -57,9 +57,9 @@
|
||||
// Forward declaration
|
||||
/*
|
||||
namespace boost {
|
||||
namespace filesystem {
|
||||
class path;
|
||||
}
|
||||
namespace filesystem {
|
||||
class path;
|
||||
}
|
||||
}
|
||||
*/
|
||||
#include <boost/filesystem.hpp> // VFALCO TODO try to eliminate thie dependency
|
||||
@@ -97,7 +97,7 @@ namespace boost {
|
||||
|
||||
// ByteOrder
|
||||
#ifdef WIN32
|
||||
// (nothing)
|
||||
// (nothing)
|
||||
#elif __APPLE__
|
||||
# include <libkern/OSByteOrder.h>
|
||||
#elif defined(__FreeBSD__) || defined(__NetBSD__)
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
|
||||
std::size_t hash_value(uint256 const& u)
|
||||
std::size_t hash_value (uint256 const& u)
|
||||
{
|
||||
std::size_t seed = HashMaps::getInstance ().getNonce <size_t> ();
|
||||
std::size_t seed = HashMaps::getInstance ().getNonce <size_t> ();
|
||||
|
||||
return u.hash_combine (seed);
|
||||
return u.hash_combine (seed);
|
||||
}
|
||||
|
||||
std::size_t hash_value(const uint160& u)
|
||||
std::size_t hash_value (const uint160& u)
|
||||
{
|
||||
std::size_t seed = HashMaps::getInstance ().getNonce <size_t> ();
|
||||
std::size_t seed = HashMaps::getInstance ().getNonce <size_t> ();
|
||||
|
||||
return u.hash_combine(seed);
|
||||
return u.hash_combine (seed);
|
||||
}
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -3,37 +3,37 @@
|
||||
//#include <windows.h>
|
||||
// from: http://stackoverflow.com/questions/3022552/is-there-any-standard-htonl-like-function-for-64-bits-integers-in-c
|
||||
// but we don't need to check the endianness
|
||||
uint64_t htobe64(uint64_t value)
|
||||
uint64_t htobe64 (uint64_t value)
|
||||
{
|
||||
// The answer is 42
|
||||
//static const int num = 42;
|
||||
// The answer is 42
|
||||
//static const int num = 42;
|
||||
|
||||
// Check the endianness
|
||||
//if (*reinterpret_cast<const char*>(&num) == num)
|
||||
//{
|
||||
const uint32_t high_part = htonl(static_cast<uint32_t>(value >> 32));
|
||||
const uint32_t low_part = htonl(static_cast<uint32_t>(value & 0xFFFFFFFFLL));
|
||||
// Check the endianness
|
||||
//if (*reinterpret_cast<const char*>(&num) == num)
|
||||
//{
|
||||
const uint32_t high_part = htonl (static_cast<uint32_t> (value >> 32));
|
||||
const uint32_t low_part = htonl (static_cast<uint32_t> (value & 0xFFFFFFFFLL));
|
||||
|
||||
return (static_cast<uint64_t>(low_part) << 32) | high_part;
|
||||
//} else
|
||||
//{
|
||||
// return value;
|
||||
//}
|
||||
return (static_cast<uint64_t> (low_part) << 32) | high_part;
|
||||
//} else
|
||||
//{
|
||||
// return value;
|
||||
//}
|
||||
}
|
||||
|
||||
uint64_t be64toh(uint64_t value)
|
||||
uint64_t be64toh (uint64_t value)
|
||||
{
|
||||
return(_byteswap_uint64(value));
|
||||
return (_byteswap_uint64 (value));
|
||||
}
|
||||
|
||||
uint32_t htobe32(uint32_t value)
|
||||
uint32_t htobe32 (uint32_t value)
|
||||
{
|
||||
return(htonl(value));
|
||||
return (htonl (value));
|
||||
}
|
||||
|
||||
uint32_t be32toh(uint32_t value)
|
||||
uint32_t be32toh (uint32_t value)
|
||||
{
|
||||
return( _byteswap_ulong(value));
|
||||
return ( _byteswap_ulong (value));
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -7,10 +7,10 @@
|
||||
|
||||
// VFALCO TODO use VFLIB_* platform macros instead of hard-coded compiler specific ones
|
||||
#ifdef WIN32
|
||||
extern uint64_t htobe64(uint64_t value);
|
||||
extern uint64_t be64toh(uint64_t value);
|
||||
extern uint32_t htobe32(uint32_t value);
|
||||
extern uint32_t be32toh(uint32_t value);
|
||||
extern uint64_t htobe64 (uint64_t value);
|
||||
extern uint64_t be64toh (uint64_t value);
|
||||
extern uint32_t htobe32 (uint32_t value);
|
||||
extern uint32_t be32toh (uint32_t value);
|
||||
|
||||
#elif __APPLE__
|
||||
#include <libkern/OSByteOrder.h>
|
||||
|
||||
@@ -1,31 +1,33 @@
|
||||
|
||||
|
||||
std::string DH_der_gen(int iKeyLength)
|
||||
std::string DH_der_gen (int iKeyLength)
|
||||
{
|
||||
DH* dh = 0;
|
||||
int iCodes;
|
||||
std::string strDer;
|
||||
DH* dh = 0;
|
||||
int iCodes;
|
||||
std::string strDer;
|
||||
|
||||
do {
|
||||
dh = DH_generate_parameters(iKeyLength, DH_GENERATOR_5, NULL, NULL);
|
||||
iCodes = 0;
|
||||
DH_check(dh, &iCodes);
|
||||
} while (iCodes & (DH_CHECK_P_NOT_PRIME|DH_CHECK_P_NOT_SAFE_PRIME|DH_UNABLE_TO_CHECK_GENERATOR|DH_NOT_SUITABLE_GENERATOR));
|
||||
do
|
||||
{
|
||||
dh = DH_generate_parameters (iKeyLength, DH_GENERATOR_5, NULL, NULL);
|
||||
iCodes = 0;
|
||||
DH_check (dh, &iCodes);
|
||||
}
|
||||
while (iCodes & (DH_CHECK_P_NOT_PRIME | DH_CHECK_P_NOT_SAFE_PRIME | DH_UNABLE_TO_CHECK_GENERATOR | DH_NOT_SUITABLE_GENERATOR));
|
||||
|
||||
strDer.resize(i2d_DHparams(dh, NULL));
|
||||
strDer.resize (i2d_DHparams (dh, NULL));
|
||||
|
||||
unsigned char* next = reinterpret_cast<unsigned char *>(&strDer[0]);
|
||||
unsigned char* next = reinterpret_cast<unsigned char*> (&strDer[0]);
|
||||
|
||||
(void) i2d_DHparams(dh, &next);
|
||||
(void) i2d_DHparams (dh, &next);
|
||||
|
||||
return strDer;
|
||||
return strDer;
|
||||
}
|
||||
|
||||
DH* DH_der_load(const std::string& strDer)
|
||||
DH* DH_der_load (const std::string& strDer)
|
||||
{
|
||||
const unsigned char *pbuf = reinterpret_cast<const unsigned char *>(&strDer[0]);
|
||||
const unsigned char* pbuf = reinterpret_cast<const unsigned char*> (&strDer[0]);
|
||||
|
||||
return d2i_DHparams(NULL, &pbuf, strDer.size());
|
||||
return d2i_DHparams (NULL, &pbuf, strDer.size ());
|
||||
}
|
||||
|
||||
// vim:ts=4
|
||||
|
||||
@@ -4,60 +4,60 @@
|
||||
// VFALCO NOTE these came from BitcoinUtil.h
|
||||
|
||||
// VFALCO TODO Rewrite the callers so we don't need templates,
|
||||
// then define these in a .cpp so they are no longer inline.
|
||||
// then define these in a .cpp so they are no longer inline.
|
||||
//
|
||||
template<typename T1>
|
||||
inline uint256 SHA256Hash(const T1 pbegin, const T1 pend)
|
||||
inline uint256 SHA256Hash (const T1 pbegin, const T1 pend)
|
||||
{
|
||||
static unsigned char pblank[1];
|
||||
uint256 hash1;
|
||||
SHA256((pbegin == pend ? pblank : (unsigned char*)&pbegin[0]), (pend - pbegin) * sizeof(pbegin[0]), (unsigned char*)&hash1);
|
||||
uint256 hash2;
|
||||
SHA256((unsigned char*)&hash1, sizeof(hash1), (unsigned char*)&hash2);
|
||||
return hash2;
|
||||
static unsigned char pblank[1];
|
||||
uint256 hash1;
|
||||
SHA256 ((pbegin == pend ? pblank : (unsigned char*)&pbegin[0]), (pend - pbegin) * sizeof (pbegin[0]), (unsigned char*)&hash1);
|
||||
uint256 hash2;
|
||||
SHA256 ((unsigned char*)&hash1, sizeof (hash1), (unsigned char*)&hash2);
|
||||
return hash2;
|
||||
}
|
||||
|
||||
template<typename T1, typename T2>
|
||||
inline uint256 SHA256Hash(const T1 p1begin, const T1 p1end,
|
||||
const T2 p2begin, const T2 p2end)
|
||||
inline uint256 SHA256Hash (const T1 p1begin, const T1 p1end,
|
||||
const T2 p2begin, const T2 p2end)
|
||||
{
|
||||
static unsigned char pblank[1];
|
||||
uint256 hash1;
|
||||
SHA256_CTX ctx;
|
||||
SHA256_Init(&ctx);
|
||||
SHA256_Update(&ctx, (p1begin == p1end ? pblank : (unsigned char*)&p1begin[0]), (p1end - p1begin) * sizeof(p1begin[0]));
|
||||
SHA256_Update(&ctx, (p2begin == p2end ? pblank : (unsigned char*)&p2begin[0]), (p2end - p2begin) * sizeof(p2begin[0]));
|
||||
SHA256_Final((unsigned char*)&hash1, &ctx);
|
||||
uint256 hash2;
|
||||
SHA256((unsigned char*)&hash1, sizeof(hash1), (unsigned char*)&hash2);
|
||||
return hash2;
|
||||
static unsigned char pblank[1];
|
||||
uint256 hash1;
|
||||
SHA256_CTX ctx;
|
||||
SHA256_Init (&ctx);
|
||||
SHA256_Update (&ctx, (p1begin == p1end ? pblank : (unsigned char*)&p1begin[0]), (p1end - p1begin) * sizeof (p1begin[0]));
|
||||
SHA256_Update (&ctx, (p2begin == p2end ? pblank : (unsigned char*)&p2begin[0]), (p2end - p2begin) * sizeof (p2begin[0]));
|
||||
SHA256_Final ((unsigned char*)&hash1, &ctx);
|
||||
uint256 hash2;
|
||||
SHA256 ((unsigned char*)&hash1, sizeof (hash1), (unsigned char*)&hash2);
|
||||
return hash2;
|
||||
}
|
||||
|
||||
template<typename T1, typename T2, typename T3>
|
||||
inline uint256 SHA256Hash(const T1 p1begin, const T1 p1end,
|
||||
const T2 p2begin, const T2 p2end,
|
||||
const T3 p3begin, const T3 p3end)
|
||||
inline uint256 SHA256Hash (const T1 p1begin, const T1 p1end,
|
||||
const T2 p2begin, const T2 p2end,
|
||||
const T3 p3begin, const T3 p3end)
|
||||
{
|
||||
static unsigned char pblank[1];
|
||||
uint256 hash1;
|
||||
SHA256_CTX ctx;
|
||||
SHA256_Init(&ctx);
|
||||
SHA256_Update(&ctx, (p1begin == p1end ? pblank : (unsigned char*)&p1begin[0]), (p1end - p1begin) * sizeof(p1begin[0]));
|
||||
SHA256_Update(&ctx, (p2begin == p2end ? pblank : (unsigned char*)&p2begin[0]), (p2end - p2begin) * sizeof(p2begin[0]));
|
||||
SHA256_Update(&ctx, (p3begin == p3end ? pblank : (unsigned char*)&p3begin[0]), (p3end - p3begin) * sizeof(p3begin[0]));
|
||||
SHA256_Final((unsigned char*)&hash1, &ctx);
|
||||
uint256 hash2;
|
||||
SHA256((unsigned char*)&hash1, sizeof(hash1), (unsigned char*)&hash2);
|
||||
return hash2;
|
||||
static unsigned char pblank[1];
|
||||
uint256 hash1;
|
||||
SHA256_CTX ctx;
|
||||
SHA256_Init (&ctx);
|
||||
SHA256_Update (&ctx, (p1begin == p1end ? pblank : (unsigned char*)&p1begin[0]), (p1end - p1begin) * sizeof (p1begin[0]));
|
||||
SHA256_Update (&ctx, (p2begin == p2end ? pblank : (unsigned char*)&p2begin[0]), (p2end - p2begin) * sizeof (p2begin[0]));
|
||||
SHA256_Update (&ctx, (p3begin == p3end ? pblank : (unsigned char*)&p3begin[0]), (p3end - p3begin) * sizeof (p3begin[0]));
|
||||
SHA256_Final ((unsigned char*)&hash1, &ctx);
|
||||
uint256 hash2;
|
||||
SHA256 ((unsigned char*)&hash1, sizeof (hash1), (unsigned char*)&hash2);
|
||||
return hash2;
|
||||
}
|
||||
|
||||
inline uint160 Hash160(Blob const& vch)
|
||||
inline uint160 Hash160 (Blob const& vch)
|
||||
{
|
||||
uint256 hash1;
|
||||
SHA256(&vch[0], vch.size(), (unsigned char*)&hash1);
|
||||
uint160 hash2;
|
||||
RIPEMD160((unsigned char*)&hash1, sizeof(hash1), (unsigned char*)&hash2);
|
||||
return hash2;
|
||||
uint256 hash1;
|
||||
SHA256 (&vch[0], vch.size (), (unsigned char*)&hash1);
|
||||
uint160 hash2;
|
||||
RIPEMD160 ((unsigned char*)&hash1, sizeof (hash1), (unsigned char*)&hash2);
|
||||
return hash2;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -78,11 +78,11 @@ inline uint160 Hash160(Blob const& vch)
|
||||
#define PAGESIZE sysconf(_SC_PAGESIZE)
|
||||
#endif
|
||||
#define mlock(a,b) \
|
||||
mlock(((void *)(((size_t)(a)) & (~((PAGESIZE)-1)))),\
|
||||
(((((size_t)(a)) + (b) - 1) | ((PAGESIZE) - 1)) + 1) - (((size_t)(a)) & (~((PAGESIZE) - 1))))
|
||||
mlock(((void *)(((size_t)(a)) & (~((PAGESIZE)-1)))),\
|
||||
(((((size_t)(a)) + (b) - 1) | ((PAGESIZE) - 1)) + 1) - (((size_t)(a)) & (~((PAGESIZE) - 1))))
|
||||
#define munlock(a,b) \
|
||||
munlock(((void *)(((size_t)(a)) & (~((PAGESIZE)-1)))),\
|
||||
(((((size_t)(a)) + (b) - 1) | ((PAGESIZE) - 1)) + 1) - (((size_t)(a)) & (~((PAGESIZE) - 1))))
|
||||
munlock(((void *)(((size_t)(a)) & (~((PAGESIZE)-1)))),\
|
||||
(((((size_t)(a)) + (b) - 1) | ((PAGESIZE) - 1)) + 1) - (((size_t)(a)) & (~((PAGESIZE) - 1))))
|
||||
#endif
|
||||
*/
|
||||
|
||||
|
||||
@@ -2,14 +2,17 @@
|
||||
InstanceType* InstanceType::sHeadInstance = NULL;
|
||||
bool InstanceType::sMultiThreaded = false;
|
||||
|
||||
std::vector<InstanceType::InstanceCount> InstanceType::getInstanceCounts(int min)
|
||||
std::vector<InstanceType::InstanceCount> InstanceType::getInstanceCounts (int min)
|
||||
{
|
||||
std::vector<InstanceCount> ret;
|
||||
for (InstanceType* i = sHeadInstance; i != NULL; i = i->mNextInstance)
|
||||
{
|
||||
int c = i->getCount();
|
||||
if (c >= min)
|
||||
ret.push_back(InstanceCount(i->getName(), c));
|
||||
}
|
||||
return ret;
|
||||
std::vector<InstanceCount> ret;
|
||||
|
||||
for (InstanceType* i = sHeadInstance; i != NULL; i = i->mNextInstance)
|
||||
{
|
||||
int c = i->getCount ();
|
||||
|
||||
if (c >= min)
|
||||
ret.push_back (InstanceCount (i->getName (), c));
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -2,24 +2,24 @@
|
||||
#define RIPPLE_INSTANCECOUNTER_H
|
||||
|
||||
// VFALCO TODO Clean this up, remove the macros, replace
|
||||
// with a robust leak checker when we have atomics.
|
||||
// with a robust leak checker when we have atomics.
|
||||
//
|
||||
|
||||
// VFALCO TODO swap these. Declaration means header, definition means .cpp!!!
|
||||
#define DEFINE_INSTANCE(x) \
|
||||
extern InstanceType IT_##x; \
|
||||
class Instance_##x : private Instance \
|
||||
{ \
|
||||
protected: \
|
||||
Instance_##x() : Instance(IT_##x) { ; } \
|
||||
Instance_##x(const Instance_##x &) : \
|
||||
Instance(IT_##x) { ; } \
|
||||
Instance_##x& operator=(const Instance_##x&) \
|
||||
{ return *this; } \
|
||||
}
|
||||
#define DEFINE_INSTANCE(x) \
|
||||
extern InstanceType IT_##x; \
|
||||
class Instance_##x : private Instance \
|
||||
{ \
|
||||
protected: \
|
||||
Instance_##x() : Instance(IT_##x) { ; } \
|
||||
Instance_##x(const Instance_##x &) : \
|
||||
Instance(IT_##x) { ; } \
|
||||
Instance_##x& operator=(const Instance_##x&) \
|
||||
{ return *this; } \
|
||||
}
|
||||
|
||||
#define DECLARE_INSTANCE(x) \
|
||||
InstanceType IT_##x(#x);
|
||||
#define DECLARE_INSTANCE(x) \
|
||||
InstanceType IT_##x(#x);
|
||||
|
||||
#define IS_INSTANCE(x) Instance_##x
|
||||
|
||||
@@ -27,84 +27,93 @@
|
||||
class InstanceType
|
||||
{
|
||||
protected:
|
||||
int mInstances;
|
||||
std::string mName;
|
||||
boost::mutex mLock;
|
||||
int mInstances;
|
||||
std::string mName;
|
||||
boost::mutex mLock;
|
||||
|
||||
InstanceType* mNextInstance;
|
||||
static InstanceType* sHeadInstance;
|
||||
static bool sMultiThreaded;
|
||||
InstanceType* mNextInstance;
|
||||
static InstanceType* sHeadInstance;
|
||||
static bool sMultiThreaded;
|
||||
|
||||
public:
|
||||
typedef std::pair<std::string, int> InstanceCount;
|
||||
typedef std::pair<std::string, int> InstanceCount;
|
||||
|
||||
explicit InstanceType (const char *n) : mInstances(0), mName(n)
|
||||
{
|
||||
mNextInstance = sHeadInstance;
|
||||
sHeadInstance = this;
|
||||
}
|
||||
explicit InstanceType (const char* n) : mInstances (0), mName (n)
|
||||
{
|
||||
mNextInstance = sHeadInstance;
|
||||
sHeadInstance = this;
|
||||
}
|
||||
|
||||
static void multiThread()
|
||||
{
|
||||
// We can support global objects and multi-threaded code, but not both
|
||||
// at the same time. Switch to multi-threaded.
|
||||
sMultiThreaded = true;
|
||||
}
|
||||
static void multiThread ()
|
||||
{
|
||||
// We can support global objects and multi-threaded code, but not both
|
||||
// at the same time. Switch to multi-threaded.
|
||||
sMultiThreaded = true;
|
||||
}
|
||||
|
||||
static void shutdown()
|
||||
{
|
||||
sMultiThreaded = false;
|
||||
}
|
||||
static void shutdown ()
|
||||
{
|
||||
sMultiThreaded = false;
|
||||
}
|
||||
|
||||
static bool isMultiThread()
|
||||
{
|
||||
return sMultiThreaded;
|
||||
}
|
||||
static bool isMultiThread ()
|
||||
{
|
||||
return sMultiThreaded;
|
||||
}
|
||||
|
||||
void addInstance()
|
||||
{
|
||||
if (sMultiThreaded)
|
||||
{
|
||||
// VFALCO NOTE This will go away with atomics
|
||||
mLock.lock();
|
||||
++mInstances;
|
||||
mLock.unlock();
|
||||
}
|
||||
else ++mInstances;
|
||||
}
|
||||
void decInstance()
|
||||
{
|
||||
if (sMultiThreaded)
|
||||
{
|
||||
mLock.lock();
|
||||
--mInstances;
|
||||
mLock.unlock();
|
||||
}
|
||||
else --mInstances;
|
||||
}
|
||||
int getCount()
|
||||
{
|
||||
boost::mutex::scoped_lock sl(mLock);
|
||||
return mInstances;
|
||||
}
|
||||
const std::string& getName()
|
||||
{
|
||||
return mName;
|
||||
}
|
||||
void addInstance ()
|
||||
{
|
||||
if (sMultiThreaded)
|
||||
{
|
||||
// VFALCO NOTE This will go away with atomics
|
||||
mLock.lock ();
|
||||
++mInstances;
|
||||
mLock.unlock ();
|
||||
}
|
||||
else ++mInstances;
|
||||
}
|
||||
void decInstance ()
|
||||
{
|
||||
if (sMultiThreaded)
|
||||
{
|
||||
mLock.lock ();
|
||||
--mInstances;
|
||||
mLock.unlock ();
|
||||
}
|
||||
else --mInstances;
|
||||
}
|
||||
int getCount ()
|
||||
{
|
||||
boost::mutex::scoped_lock sl (mLock);
|
||||
return mInstances;
|
||||
}
|
||||
const std::string& getName ()
|
||||
{
|
||||
return mName;
|
||||
}
|
||||
|
||||
static std::vector<InstanceCount> getInstanceCounts(int min = 1);
|
||||
static std::vector<InstanceCount> getInstanceCounts (int min = 1);
|
||||
};
|
||||
|
||||
class Instance
|
||||
{
|
||||
protected:
|
||||
static bool running;
|
||||
InstanceType& mType;
|
||||
static bool running;
|
||||
InstanceType& mType;
|
||||
|
||||
public:
|
||||
Instance(InstanceType& t) : mType(t) { mType.addInstance(); }
|
||||
~Instance() { if (running) mType.decInstance(); }
|
||||
static void shutdown() { running = false; }
|
||||
Instance (InstanceType& t) : mType (t)
|
||||
{
|
||||
mType.addInstance ();
|
||||
}
|
||||
~Instance ()
|
||||
{
|
||||
if (running) mType.decInstance ();
|
||||
}
|
||||
static void shutdown ()
|
||||
{
|
||||
running = false;
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -4,7 +4,7 @@ boost::recursive_mutex Log::sLock;
|
||||
LogSeverity Log::sMinSeverity = lsINFO;
|
||||
|
||||
std::ofstream* Log::outStream = NULL;
|
||||
boost::filesystem::path *Log::pathToLog = NULL;
|
||||
boost::filesystem::path* Log::pathToLog = NULL;
|
||||
uint32 Log::logRotateCounter = 0;
|
||||
|
||||
#ifndef LOG_MAX_MESSAGE
|
||||
@@ -13,26 +13,27 @@ uint32 Log::logRotateCounter = 0;
|
||||
|
||||
LogPartition* LogPartition::headLog = NULL;
|
||||
|
||||
LogPartition::LogPartition(const char *name) : mNextLog(headLog), mMinSeverity(lsWARNING)
|
||||
LogPartition::LogPartition (const char* name) : mNextLog (headLog), mMinSeverity (lsWARNING)
|
||||
{
|
||||
const char *ptr = strrchr(name, '/');
|
||||
mName = (ptr == NULL) ? name : (ptr + 1);
|
||||
const char* ptr = strrchr (name, '/');
|
||||
mName = (ptr == NULL) ? name : (ptr + 1);
|
||||
|
||||
size_t p = mName.find(".cpp");
|
||||
if (p != std::string::npos)
|
||||
mName.erase(mName.begin() + p, mName.end());
|
||||
size_t p = mName.find (".cpp");
|
||||
|
||||
headLog = this;
|
||||
if (p != std::string::npos)
|
||||
mName.erase (mName.begin () + p, mName.end ());
|
||||
|
||||
headLog = this;
|
||||
}
|
||||
|
||||
std::vector< std::pair<std::string, std::string> > LogPartition::getSeverities()
|
||||
std::vector< std::pair<std::string, std::string> > LogPartition::getSeverities ()
|
||||
{
|
||||
std::vector< std::pair<std::string, std::string> > sevs;
|
||||
std::vector< std::pair<std::string, std::string> > sevs;
|
||||
|
||||
for (LogPartition *l = headLog; l != NULL; l = l->mNextLog)
|
||||
sevs.push_back(std::make_pair(l->mName, Log::severityToString(l->mMinSeverity)));
|
||||
for (LogPartition* l = headLog; l != NULL; l = l->mNextLog)
|
||||
sevs.push_back (std::make_pair (l->mName, Log::severityToString (l->mMinSeverity)));
|
||||
|
||||
return sevs;
|
||||
return sevs;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
@@ -44,12 +45,12 @@ std::string ls = oss.str();
|
||||
size_t s = ls.find("\"secret\"");
|
||||
if (s != std::string::npos)
|
||||
{
|
||||
s += 8;
|
||||
size_t sEnd = ls.size() - 1;
|
||||
if (sEnd > (s + 35))
|
||||
sEnd = s + 35;
|
||||
for (int i = s; i < sEnd; ++i)
|
||||
ls[i] = '*';
|
||||
s += 8;
|
||||
size_t sEnd = ls.size() - 1;
|
||||
if (sEnd > (s + 35))
|
||||
sEnd = s + 35;
|
||||
for (int i = s; i < sEnd; ++i)
|
||||
ls[i] = '*';
|
||||
}
|
||||
logMsg += ls;
|
||||
*/
|
||||
@@ -85,169 +86,223 @@ std::string Log::replaceFirstSecretWithAsterisks (std::string s)
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
Log::~Log()
|
||||
Log::~Log ()
|
||||
{
|
||||
std::string logMsg = boost::posix_time::to_simple_string(boost::posix_time::second_clock::universal_time());
|
||||
if (!mPartitionName.empty())
|
||||
logMsg += " " + mPartitionName + ":";
|
||||
else
|
||||
logMsg += " ";
|
||||
std::string logMsg = boost::posix_time::to_simple_string (boost::posix_time::second_clock::universal_time ());
|
||||
|
||||
switch (mSeverity)
|
||||
{
|
||||
case lsTRACE: logMsg += "TRC "; break;
|
||||
case lsDEBUG: logMsg += "DBG "; break;
|
||||
case lsINFO: logMsg += "NFO "; break;
|
||||
case lsWARNING: logMsg += "WRN "; break;
|
||||
case lsERROR: logMsg += "ERR "; break;
|
||||
case lsFATAL: logMsg += "FTL "; break;
|
||||
case lsINVALID: assert(false); return;
|
||||
}
|
||||
if (!mPartitionName.empty ())
|
||||
logMsg += " " + mPartitionName + ":";
|
||||
else
|
||||
logMsg += " ";
|
||||
|
||||
switch (mSeverity)
|
||||
{
|
||||
case lsTRACE:
|
||||
logMsg += "TRC ";
|
||||
break;
|
||||
|
||||
case lsDEBUG:
|
||||
logMsg += "DBG ";
|
||||
break;
|
||||
|
||||
case lsINFO:
|
||||
logMsg += "NFO ";
|
||||
break;
|
||||
|
||||
case lsWARNING:
|
||||
logMsg += "WRN ";
|
||||
break;
|
||||
|
||||
case lsERROR:
|
||||
logMsg += "ERR ";
|
||||
break;
|
||||
|
||||
case lsFATAL:
|
||||
logMsg += "FTL ";
|
||||
break;
|
||||
|
||||
case lsINVALID:
|
||||
assert (false);
|
||||
return;
|
||||
}
|
||||
|
||||
logMsg += replaceFirstSecretWithAsterisks (oss.str ());
|
||||
|
||||
if (logMsg.size() > LOG_MAX_MESSAGE)
|
||||
{
|
||||
logMsg.resize(LOG_MAX_MESSAGE);
|
||||
logMsg += "...";
|
||||
}
|
||||
|
||||
boost::recursive_mutex::scoped_lock sl(sLock);
|
||||
|
||||
if (mSeverity >= sMinSeverity)
|
||||
std::cerr << logMsg << std::endl;
|
||||
if (outStream != NULL)
|
||||
(*outStream) << logMsg << std::endl;
|
||||
}
|
||||
|
||||
std::string Log::rotateLog(void)
|
||||
{
|
||||
boost::recursive_mutex::scoped_lock sl(sLock);
|
||||
boost::filesystem::path abs_path;
|
||||
std::string abs_path_str;
|
||||
|
||||
uint32 failsafe = 0;
|
||||
|
||||
std::string abs_new_path_str;
|
||||
do {
|
||||
std::string s;
|
||||
std::stringstream out;
|
||||
|
||||
failsafe++;
|
||||
if (failsafe == std::numeric_limits<uint32>::max()) {
|
||||
return "unable to create new log file; too many log files!";
|
||||
if (logMsg.size () > LOG_MAX_MESSAGE)
|
||||
{
|
||||
logMsg.resize (LOG_MAX_MESSAGE);
|
||||
logMsg += "...";
|
||||
}
|
||||
abs_path = boost::filesystem::absolute("");
|
||||
abs_path /= *pathToLog;
|
||||
abs_path_str = abs_path.parent_path().string();
|
||||
|
||||
out << logRotateCounter;
|
||||
s = out.str();
|
||||
boost::recursive_mutex::scoped_lock sl (sLock);
|
||||
|
||||
abs_new_path_str = abs_path_str + "/" + s + "_" + pathToLog->filename().string();
|
||||
if (mSeverity >= sMinSeverity)
|
||||
std::cerr << logMsg << std::endl;
|
||||
|
||||
logRotateCounter++;
|
||||
|
||||
} while (boost::filesystem::exists(boost::filesystem::path(abs_new_path_str)));
|
||||
|
||||
outStream->close();
|
||||
|
||||
try
|
||||
{
|
||||
boost::filesystem::rename(abs_path, boost::filesystem::path(abs_new_path_str));
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
// unable to rename existing log file
|
||||
}
|
||||
|
||||
setLogFile(*pathToLog);
|
||||
|
||||
return abs_new_path_str;
|
||||
if (outStream != NULL)
|
||||
(*outStream) << logMsg << std::endl;
|
||||
}
|
||||
|
||||
void Log::setMinSeverity(LogSeverity s, bool all)
|
||||
std::string Log::rotateLog (void)
|
||||
{
|
||||
boost::recursive_mutex::scoped_lock sl(sLock);
|
||||
boost::recursive_mutex::scoped_lock sl (sLock);
|
||||
boost::filesystem::path abs_path;
|
||||
std::string abs_path_str;
|
||||
|
||||
sMinSeverity = s;
|
||||
if (all)
|
||||
LogPartition::setSeverity(s);
|
||||
uint32 failsafe = 0;
|
||||
|
||||
std::string abs_new_path_str;
|
||||
|
||||
do
|
||||
{
|
||||
std::string s;
|
||||
std::stringstream out;
|
||||
|
||||
failsafe++;
|
||||
|
||||
if (failsafe == std::numeric_limits<uint32>::max ())
|
||||
{
|
||||
return "unable to create new log file; too many log files!";
|
||||
}
|
||||
|
||||
abs_path = boost::filesystem::absolute ("");
|
||||
abs_path /= *pathToLog;
|
||||
abs_path_str = abs_path.parent_path ().string ();
|
||||
|
||||
out << logRotateCounter;
|
||||
s = out.str ();
|
||||
|
||||
abs_new_path_str = abs_path_str + "/" + s + "_" + pathToLog->filename ().string ();
|
||||
|
||||
logRotateCounter++;
|
||||
|
||||
}
|
||||
while (boost::filesystem::exists (boost::filesystem::path (abs_new_path_str)));
|
||||
|
||||
outStream->close ();
|
||||
|
||||
try
|
||||
{
|
||||
boost::filesystem::rename (abs_path, boost::filesystem::path (abs_new_path_str));
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
// unable to rename existing log file
|
||||
}
|
||||
|
||||
setLogFile (*pathToLog);
|
||||
|
||||
return abs_new_path_str;
|
||||
}
|
||||
|
||||
LogSeverity Log::getMinSeverity()
|
||||
void Log::setMinSeverity (LogSeverity s, bool all)
|
||||
{
|
||||
boost::recursive_mutex::scoped_lock sl(sLock);
|
||||
boost::recursive_mutex::scoped_lock sl (sLock);
|
||||
|
||||
return sMinSeverity;
|
||||
sMinSeverity = s;
|
||||
|
||||
if (all)
|
||||
LogPartition::setSeverity (s);
|
||||
}
|
||||
|
||||
std::string Log::severityToString(LogSeverity s)
|
||||
LogSeverity Log::getMinSeverity ()
|
||||
{
|
||||
switch (s)
|
||||
{
|
||||
case lsTRACE: return "Trace";
|
||||
case lsDEBUG: return "Debug";
|
||||
case lsINFO: return "Info";
|
||||
case lsWARNING: return "Warning";
|
||||
case lsERROR: return "Error";
|
||||
case lsFATAL: return "Fatal";
|
||||
default: assert(false); return "Unknown";
|
||||
}
|
||||
boost::recursive_mutex::scoped_lock sl (sLock);
|
||||
|
||||
return sMinSeverity;
|
||||
}
|
||||
|
||||
LogSeverity Log::stringToSeverity(const std::string& s)
|
||||
std::string Log::severityToString (LogSeverity s)
|
||||
{
|
||||
if (boost::iequals(s, "trace"))
|
||||
return lsTRACE;
|
||||
if (boost::iequals(s, "debug"))
|
||||
return lsDEBUG;
|
||||
if (boost::iequals(s, "info") || boost::iequals(s, "information"))
|
||||
return lsINFO;
|
||||
if (boost::iequals(s, "warn") || boost::iequals(s, "warning") || boost::iequals(s, "warnings"))
|
||||
return lsWARNING;
|
||||
if (boost::iequals(s, "error") || boost::iequals(s, "errors"))
|
||||
return lsERROR;
|
||||
if (boost::iequals(s, "fatal") || boost::iequals(s, "fatals"))
|
||||
return lsFATAL;
|
||||
return lsINVALID;
|
||||
switch (s)
|
||||
{
|
||||
case lsTRACE:
|
||||
return "Trace";
|
||||
|
||||
case lsDEBUG:
|
||||
return "Debug";
|
||||
|
||||
case lsINFO:
|
||||
return "Info";
|
||||
|
||||
case lsWARNING:
|
||||
return "Warning";
|
||||
|
||||
case lsERROR:
|
||||
return "Error";
|
||||
|
||||
case lsFATAL:
|
||||
return "Fatal";
|
||||
|
||||
default:
|
||||
assert (false);
|
||||
return "Unknown";
|
||||
}
|
||||
}
|
||||
|
||||
void Log::setLogFile(boost::filesystem::path const& path)
|
||||
LogSeverity Log::stringToSeverity (const std::string& s)
|
||||
{
|
||||
std::ofstream* newStream = new std::ofstream(path.c_str(), std::fstream::app);
|
||||
if (!newStream->good())
|
||||
{
|
||||
Log(lsFATAL) << "Unable to open logfile " << path;
|
||||
delete newStream;
|
||||
newStream = NULL;
|
||||
}
|
||||
if (boost::iequals (s, "trace"))
|
||||
return lsTRACE;
|
||||
|
||||
boost::recursive_mutex::scoped_lock sl(sLock);
|
||||
if (outStream != NULL)
|
||||
delete outStream;
|
||||
outStream = newStream;
|
||||
if (boost::iequals (s, "debug"))
|
||||
return lsDEBUG;
|
||||
|
||||
if (pathToLog != NULL)
|
||||
delete pathToLog;
|
||||
pathToLog = new boost::filesystem::path(path);
|
||||
if (boost::iequals (s, "info") || boost::iequals (s, "information"))
|
||||
return lsINFO;
|
||||
|
||||
if (boost::iequals (s, "warn") || boost::iequals (s, "warning") || boost::iequals (s, "warnings"))
|
||||
return lsWARNING;
|
||||
|
||||
if (boost::iequals (s, "error") || boost::iequals (s, "errors"))
|
||||
return lsERROR;
|
||||
|
||||
if (boost::iequals (s, "fatal") || boost::iequals (s, "fatals"))
|
||||
return lsFATAL;
|
||||
|
||||
return lsINVALID;
|
||||
}
|
||||
|
||||
bool LogPartition::setSeverity(const std::string& partition, LogSeverity severity)
|
||||
void Log::setLogFile (boost::filesystem::path const& path)
|
||||
{
|
||||
for (LogPartition *p = headLog; p != NULL; p = p->mNextLog)
|
||||
if (boost::iequals(p->mName, partition))
|
||||
{
|
||||
p->mMinSeverity = severity;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
std::ofstream* newStream = new std::ofstream (path.c_str (), std::fstream::app);
|
||||
|
||||
if (!newStream->good ())
|
||||
{
|
||||
Log (lsFATAL) << "Unable to open logfile " << path;
|
||||
delete newStream;
|
||||
newStream = NULL;
|
||||
}
|
||||
|
||||
boost::recursive_mutex::scoped_lock sl (sLock);
|
||||
|
||||
if (outStream != NULL)
|
||||
delete outStream;
|
||||
|
||||
outStream = newStream;
|
||||
|
||||
if (pathToLog != NULL)
|
||||
delete pathToLog;
|
||||
|
||||
pathToLog = new boost::filesystem::path (path);
|
||||
}
|
||||
|
||||
void LogPartition::setSeverity(LogSeverity severity)
|
||||
bool LogPartition::setSeverity (const std::string& partition, LogSeverity severity)
|
||||
{
|
||||
for (LogPartition *p = headLog; p != NULL; p = p->mNextLog)
|
||||
p->mMinSeverity = severity;
|
||||
for (LogPartition* p = headLog; p != NULL; p = p->mNextLog)
|
||||
if (boost::iequals (p->mName, partition))
|
||||
{
|
||||
p->mMinSeverity = severity;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void LogPartition::setSeverity (LogSeverity severity)
|
||||
{
|
||||
for (LogPartition* p = headLog; p != NULL; p = p->mNextLog)
|
||||
p->mMinSeverity = severity;
|
||||
}
|
||||
|
||||
// vim:ts=4
|
||||
|
||||
@@ -3,13 +3,13 @@
|
||||
|
||||
enum LogSeverity
|
||||
{
|
||||
lsINVALID = -1, // used to indicate an invalid severity
|
||||
lsTRACE = 0, // Very low-level progress information, details inside an operation
|
||||
lsDEBUG = 1, // Function-level progress information, operations
|
||||
lsINFO = 2, // Server-level progress information, major operations
|
||||
lsWARNING = 3, // Conditions that warrant human attention, may indicate a problem
|
||||
lsERROR = 4, // A condition that indicates a problem
|
||||
lsFATAL = 5 // A severe condition that indicates a server problem
|
||||
lsINVALID = -1, // used to indicate an invalid severity
|
||||
lsTRACE = 0, // Very low-level progress information, details inside an operation
|
||||
lsDEBUG = 1, // Function-level progress information, operations
|
||||
lsINFO = 2, // Server-level progress information, major operations
|
||||
lsWARNING = 3, // Conditions that warrant human attention, may indicate a problem
|
||||
lsERROR = 4, // A condition that indicates a problem
|
||||
lsFATAL = 5 // A severe condition that indicates a server problem
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
@@ -18,80 +18,86 @@ enum LogSeverity
|
||||
class LogPartition
|
||||
{
|
||||
protected:
|
||||
static LogPartition* headLog;
|
||||
static LogPartition* headLog;
|
||||
|
||||
LogPartition* mNextLog;
|
||||
LogSeverity mMinSeverity;
|
||||
std::string mName;
|
||||
LogPartition* mNextLog;
|
||||
LogSeverity mMinSeverity;
|
||||
std::string mName;
|
||||
|
||||
public:
|
||||
LogPartition(const char *name);
|
||||
LogPartition (const char* name);
|
||||
|
||||
bool doLog(LogSeverity s) const { return s >= mMinSeverity; }
|
||||
const std::string& getName() const { return mName; }
|
||||
bool doLog (LogSeverity s) const
|
||||
{
|
||||
return s >= mMinSeverity;
|
||||
}
|
||||
const std::string& getName () const
|
||||
{
|
||||
return mName;
|
||||
}
|
||||
|
||||
static bool setSeverity(const std::string& partition, LogSeverity severity);
|
||||
static void setSeverity(LogSeverity severity);
|
||||
static std::vector< std::pair<std::string, std::string> > getSeverities();
|
||||
static bool setSeverity (const std::string& partition, LogSeverity severity);
|
||||
static void setSeverity (LogSeverity severity);
|
||||
static std::vector< std::pair<std::string, std::string> > getSeverities ();
|
||||
|
||||
private:
|
||||
/** Retrieve file name from a log partition.
|
||||
*/
|
||||
template <class Key>
|
||||
static char const* getFileName ();
|
||||
/*
|
||||
{
|
||||
static_vfassert (false);
|
||||
}
|
||||
*/
|
||||
/** Retrieve file name from a log partition.
|
||||
*/
|
||||
template <class Key>
|
||||
static char const* getFileName ();
|
||||
/*
|
||||
{
|
||||
static_vfassert (false);
|
||||
}
|
||||
*/
|
||||
|
||||
public:
|
||||
template <class Key>
|
||||
static LogPartition const& get ()
|
||||
{
|
||||
static LogPartition logPartition (getFileName <Key> ());
|
||||
return logPartition;
|
||||
}
|
||||
template <class Key>
|
||||
static LogPartition const& get ()
|
||||
{
|
||||
static LogPartition logPartition (getFileName <Key> ());
|
||||
return logPartition;
|
||||
}
|
||||
};
|
||||
|
||||
#define SETUP_LOG(k) \
|
||||
template <> char const* LogPartition::getFileName <k> () { return __FILE__; } \
|
||||
struct k##Instantiator { k##Instantiator () { LogPartition::get <k> (); } }; \
|
||||
static k##Instantiator k##Instantiator_instance;
|
||||
template <> char const* LogPartition::getFileName <k> () { return __FILE__; } \
|
||||
struct k##Instantiator { k##Instantiator () { LogPartition::get <k> (); } }; \
|
||||
static k##Instantiator k##Instantiator_instance;
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
class Log
|
||||
{
|
||||
public:
|
||||
explicit Log (LogSeverity s) : mSeverity(s)
|
||||
{
|
||||
explicit Log (LogSeverity s) : mSeverity (s)
|
||||
{
|
||||
}
|
||||
|
||||
Log (LogSeverity s, LogPartition const& p)
|
||||
Log (LogSeverity s, LogPartition const& p)
|
||||
: mSeverity (s)
|
||||
, mPartitionName (p.getName())
|
||||
{
|
||||
, mPartitionName (p.getName ())
|
||||
{
|
||||
}
|
||||
|
||||
~Log ();
|
||||
~Log ();
|
||||
|
||||
template <class T>
|
||||
template <class T>
|
||||
std::ostream& operator<< (const T& t) const
|
||||
{
|
||||
return oss << t;
|
||||
}
|
||||
{
|
||||
return oss << t;
|
||||
}
|
||||
|
||||
std::ostringstream& ref () const
|
||||
{
|
||||
return oss;
|
||||
}
|
||||
std::ostringstream& ref () const
|
||||
{
|
||||
return oss;
|
||||
}
|
||||
|
||||
static std::string severityToString (LogSeverity);
|
||||
static std::string severityToString (LogSeverity);
|
||||
|
||||
static LogSeverity stringToSeverity (std::string const&);
|
||||
|
||||
static LogSeverity getMinSeverity ();
|
||||
static LogSeverity getMinSeverity ();
|
||||
|
||||
static void setMinSeverity (LogSeverity, bool all);
|
||||
|
||||
@@ -101,24 +107,24 @@ public:
|
||||
|
||||
private:
|
||||
// VFALCO TODO derive from beast::Uncopyable
|
||||
Log (const Log&); // no implementation
|
||||
Log& operator= (const Log&); // no implementation
|
||||
Log (const Log&); // no implementation
|
||||
Log& operator= (const Log&); // no implementation
|
||||
|
||||
// VFALCO TODO looks like there are really TWO classes in here.
|
||||
// One is a stream target for '<<' operator and the other
|
||||
// is a singleton. Split the singleton out to a new class.
|
||||
//
|
||||
static boost::recursive_mutex sLock;
|
||||
static LogSeverity sMinSeverity;
|
||||
static std::ofstream* outStream;
|
||||
static boost::filesystem::path *pathToLog;
|
||||
static uint32 logRotateCounter;
|
||||
static LogSeverity sMinSeverity;
|
||||
static std::ofstream* outStream;
|
||||
static boost::filesystem::path* pathToLog;
|
||||
static uint32 logRotateCounter;
|
||||
|
||||
static std::string replaceFirstSecretWithAsterisks (std::string s);
|
||||
|
||||
mutable std::ostringstream oss;
|
||||
LogSeverity mSeverity;
|
||||
std::string mPartitionName;
|
||||
mutable std::ostringstream oss;
|
||||
LogSeverity mSeverity;
|
||||
std::string mPartitionName;
|
||||
};
|
||||
|
||||
// Manually test for whether we should log
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
Copyright (c) 2011-2013, OpenCoin, Inc.
|
||||
Copyright (c) 2011-2013, OpenCoin, Inc.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
@@ -26,33 +26,33 @@
|
||||
// VFALCO TODO replace BIND_TYPE with a namespace lift
|
||||
|
||||
#define C11X
|
||||
#include <functional>
|
||||
#define UPTR_T std::unique_ptr
|
||||
#define MOVE_P(p) std::move(p)
|
||||
#define BIND_TYPE std::bind
|
||||
#define FUNCTION_TYPE std::function
|
||||
#define P_1 std::placeholders::_1
|
||||
#define P_2 std::placeholders::_2
|
||||
#define P_3 std::placeholders::_3
|
||||
#define P_4 std::placeholders::_4
|
||||
#include <functional>
|
||||
#define UPTR_T std::unique_ptr
|
||||
#define MOVE_P(p) std::move(p)
|
||||
#define BIND_TYPE std::bind
|
||||
#define FUNCTION_TYPE std::function
|
||||
#define P_1 std::placeholders::_1
|
||||
#define P_2 std::placeholders::_2
|
||||
#define P_3 std::placeholders::_3
|
||||
#define P_4 std::placeholders::_4
|
||||
|
||||
#else
|
||||
|
||||
#define UPTR_T std::auto_ptr
|
||||
#define MOVE_P(p) (p)
|
||||
#define BIND_TYPE boost::bind
|
||||
#define FUNCTION_TYPE boost::function
|
||||
#define P_1 _1
|
||||
#define P_2 _2
|
||||
#define P_3 _3
|
||||
#define P_4 _4
|
||||
#define UPTR_T std::auto_ptr
|
||||
#define MOVE_P(p) (p)
|
||||
#define BIND_TYPE boost::bind
|
||||
#define FUNCTION_TYPE boost::function
|
||||
#define P_1 _1
|
||||
#define P_2 _2
|
||||
#define P_3 _3
|
||||
#define P_4 _4
|
||||
|
||||
#endif
|
||||
|
||||
// VFALCO TODO Clean this junk up
|
||||
#define nothing() do {} while (0)
|
||||
#define fallthru() do {} while (0)
|
||||
#define NUMBER(x) (sizeof(x)/sizeof((x)[0]))
|
||||
#define isSetBit(x,y) (!!((x) & (y)))
|
||||
#define nothing() do {} while (0)
|
||||
#define fallthru() do {} while (0)
|
||||
#define NUMBER(x) (sizeof(x)/sizeof((x)[0]))
|
||||
#define isSetBit(x,y) (!!((x) & (y)))
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
Copyright (c) 2011-2013, OpenCoin, Inc.
|
||||
Copyright (c) 2011-2013, OpenCoin, Inc.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
@@ -55,15 +55,15 @@ void RandomNumbers::fillBytes (void* destinationBuffer, int numberOfBytes)
|
||||
}
|
||||
|
||||
#ifdef PURIFY
|
||||
memset (destinationBuffer, 0, numberOfBytes);
|
||||
memset (destinationBuffer, 0, numberOfBytes);
|
||||
#endif
|
||||
|
||||
if (RAND_bytes (reinterpret_cast <unsigned char*> (destinationBuffer), numberOfBytes) != 1)
|
||||
{
|
||||
assert(false);
|
||||
if (RAND_bytes (reinterpret_cast <unsigned char*> (destinationBuffer), numberOfBytes) != 1)
|
||||
{
|
||||
assert (false);
|
||||
|
||||
throw std::runtime_error ("Entropy pool not seeded");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RandomNumbers& RandomNumbers::getInstance ()
|
||||
@@ -82,68 +82,72 @@ RandomNumbers& RandomNumbers::getInstance ()
|
||||
// Get entropy from the Windows crypto provider
|
||||
bool RandomNumbers::platformAddEntropy ()
|
||||
{
|
||||
char name[512], rand[128];
|
||||
DWORD count = 500;
|
||||
HCRYPTPROV cryptoHandle;
|
||||
char name[512], rand[128];
|
||||
DWORD count = 500;
|
||||
HCRYPTPROV cryptoHandle;
|
||||
|
||||
if (!CryptGetDefaultProvider(PROV_RSA_FULL, NULL, CRYPT_MACHINE_DEFAULT, name, &count))
|
||||
{
|
||||
if (!CryptGetDefaultProvider (PROV_RSA_FULL, NULL, CRYPT_MACHINE_DEFAULT, name, &count))
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::cerr << "Unable to get default crypto provider" << std::endl;
|
||||
std::cerr << "Unable to get default crypto provider" << std::endl;
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!CryptAcquireContext(&cryptoHandle, NULL, name, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT | CRYPT_SILENT))
|
||||
{
|
||||
if (!CryptAcquireContext (&cryptoHandle, NULL, name, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT | CRYPT_SILENT))
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::cerr << "Unable to acquire crypto provider" << std::endl;
|
||||
std::cerr << "Unable to acquire crypto provider" << std::endl;
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!CryptGenRandom(cryptoHandle, 128, reinterpret_cast<BYTE*>(rand)))
|
||||
{
|
||||
if (!CryptGenRandom (cryptoHandle, 128, reinterpret_cast<BYTE*> (rand)))
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::cerr << "Unable to get entropy from crypto provider" << std::endl;
|
||||
std::cerr << "Unable to get entropy from crypto provider" << std::endl;
|
||||
#endif
|
||||
CryptReleaseContext(cryptoHandle, 0);
|
||||
return false;
|
||||
}
|
||||
CryptReleaseContext (cryptoHandle, 0);
|
||||
return false;
|
||||
}
|
||||
|
||||
CryptReleaseContext(cryptoHandle, 0);
|
||||
RAND_seed(rand, 128);
|
||||
CryptReleaseContext (cryptoHandle, 0);
|
||||
RAND_seed (rand, 128);
|
||||
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
bool RandomNumbers::platformAddEntropy ()
|
||||
{
|
||||
char rand[128];
|
||||
std::ifstream reader;
|
||||
char rand[128];
|
||||
std::ifstream reader;
|
||||
|
||||
reader.open("/dev/urandom", std::ios::in | std::ios::binary);
|
||||
if (!reader.is_open())
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::cerr << "Unable to open random source" << std::endl;
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
reader.read(rand, 128);
|
||||
reader.open ("/dev/urandom", std::ios::in | std::ios::binary);
|
||||
|
||||
int bytesRead = reader.gcount();
|
||||
if (bytesRead == 0)
|
||||
{
|
||||
if (!reader.is_open ())
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::cerr << "Unable to read from random source" << std::endl;
|
||||
std::cerr << "Unable to open random source" << std::endl;
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
RAND_seed(rand, bytesRead);
|
||||
return bytesRead >= 64;
|
||||
return false;
|
||||
}
|
||||
|
||||
reader.read (rand, 128);
|
||||
|
||||
int bytesRead = reader.gcount ();
|
||||
|
||||
if (bytesRead == 0)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::cerr << "Unable to read from random source" << std::endl;
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
RAND_seed (rand, bytesRead);
|
||||
return bytesRead >= 64;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -161,63 +165,67 @@ bool RandomNumbers::platformAddEntropy ()
|
||||
void RandomNumbers::platformAddPerformanceMonitorEntropy ()
|
||||
{
|
||||
// VFALCO TODO Remove all this fancy stuff
|
||||
struct
|
||||
{
|
||||
int64 operator() () const
|
||||
{
|
||||
return time (NULL);
|
||||
}
|
||||
} GetTime;
|
||||
struct
|
||||
{
|
||||
int64 operator () () const
|
||||
{
|
||||
return time (NULL);
|
||||
}
|
||||
} GetTime;
|
||||
|
||||
struct
|
||||
{
|
||||
void operator() ()
|
||||
{
|
||||
struct
|
||||
{
|
||||
// VFALCO TODO clean this up
|
||||
int64 operator() () const
|
||||
{
|
||||
int64 nCounter = 0;
|
||||
struct
|
||||
{
|
||||
void operator () ()
|
||||
{
|
||||
struct
|
||||
{
|
||||
// VFALCO TODO clean this up
|
||||
int64 operator () () const
|
||||
{
|
||||
int64 nCounter = 0;
|
||||
#if defined(WIN32) || defined(WIN64)
|
||||
QueryPerformanceCounter((LARGE_INTEGER*)&nCounter);
|
||||
QueryPerformanceCounter ((LARGE_INTEGER*)&nCounter);
|
||||
#else
|
||||
timeval t;
|
||||
gettimeofday(&t, NULL);
|
||||
nCounter = t.tv_sec * 1000000 + t.tv_usec;
|
||||
timeval t;
|
||||
gettimeofday (&t, NULL);
|
||||
nCounter = t.tv_sec * 1000000 + t.tv_usec;
|
||||
#endif
|
||||
return nCounter;
|
||||
}
|
||||
} GetPerformanceCounter;
|
||||
return nCounter;
|
||||
}
|
||||
} GetPerformanceCounter;
|
||||
|
||||
// Seed with CPU performance counter
|
||||
int64 nCounter = GetPerformanceCounter();
|
||||
RAND_add(&nCounter, sizeof(nCounter), 1.5);
|
||||
memset(&nCounter, 0, sizeof(nCounter));
|
||||
}
|
||||
} RandAddSeed;
|
||||
// Seed with CPU performance counter
|
||||
int64 nCounter = GetPerformanceCounter ();
|
||||
RAND_add (&nCounter, sizeof (nCounter), 1.5);
|
||||
memset (&nCounter, 0, sizeof (nCounter));
|
||||
}
|
||||
} RandAddSeed;
|
||||
|
||||
RandAddSeed();
|
||||
RandAddSeed ();
|
||||
|
||||
// This can take up to 2 seconds, so only do it every 10 minutes
|
||||
static int64 nLastPerfmon;
|
||||
if (GetTime () < nLastPerfmon + 10 * 60)
|
||||
return;
|
||||
nLastPerfmon = GetTime ();
|
||||
// This can take up to 2 seconds, so only do it every 10 minutes
|
||||
static int64 nLastPerfmon;
|
||||
|
||||
if (GetTime () < nLastPerfmon + 10 * 60)
|
||||
return;
|
||||
|
||||
nLastPerfmon = GetTime ();
|
||||
|
||||
#ifdef WIN32
|
||||
// Don't need this on Linux, OpenSSL automatically uses /dev/urandom
|
||||
// Seed with the entire set of perfmon data
|
||||
unsigned char pdata[250000];
|
||||
memset(pdata, 0, sizeof(pdata));
|
||||
unsigned long nSize = sizeof(pdata);
|
||||
long ret = RegQueryValueExA(HKEY_PERFORMANCE_DATA, "Global", NULL, NULL, pdata, &nSize);
|
||||
RegCloseKey(HKEY_PERFORMANCE_DATA);
|
||||
if (ret == ERROR_SUCCESS)
|
||||
{
|
||||
RAND_add(pdata, nSize, nSize/100.0);
|
||||
memset(pdata, 0, nSize);
|
||||
//printf("%s RandAddSeed() %d bytes\n", DateTimeStrFormat("%x %H:%M", GetTime()).c_str(), nSize);
|
||||
}
|
||||
// Don't need this on Linux, OpenSSL automatically uses /dev/urandom
|
||||
// Seed with the entire set of perfmon data
|
||||
unsigned char pdata[250000];
|
||||
memset (pdata, 0, sizeof (pdata));
|
||||
unsigned long nSize = sizeof (pdata);
|
||||
long ret = RegQueryValueExA (HKEY_PERFORMANCE_DATA, "Global", NULL, NULL, pdata, &nSize);
|
||||
RegCloseKey (HKEY_PERFORMANCE_DATA);
|
||||
|
||||
if (ret == ERROR_SUCCESS)
|
||||
{
|
||||
RAND_add (pdata, nSize, nSize / 100.0);
|
||||
memset (pdata, 0, nSize);
|
||||
//printf("%s RandAddSeed() %d bytes\n", DateTimeStrFormat("%x %H:%M", GetTime()).c_str(), nSize);
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
Copyright (c) 2011-2013, OpenCoin, Inc.
|
||||
Copyright (c) 2011-2013, OpenCoin, Inc.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
|
||||
@@ -11,14 +11,23 @@ typedef boost::recursive_mutex::scoped_lock ScopedLock;
|
||||
class SharedScopedLock
|
||||
{
|
||||
protected:
|
||||
mutable boost::shared_ptr<boost::recursive_mutex::scoped_lock> mHolder;
|
||||
mutable boost::shared_ptr<boost::recursive_mutex::scoped_lock> mHolder;
|
||||
|
||||
public:
|
||||
SharedScopedLock(boost::recursive_mutex& mutex) :
|
||||
mHolder(boost::make_shared<boost::recursive_mutex::scoped_lock>(boost::ref(mutex))) { ; }
|
||||
SharedScopedLock (boost::recursive_mutex& mutex) :
|
||||
mHolder (boost::make_shared<boost::recursive_mutex::scoped_lock> (boost::ref (mutex)))
|
||||
{
|
||||
;
|
||||
}
|
||||
|
||||
void lock() const { mHolder->lock(); }
|
||||
void unlock() const { mHolder->unlock(); }
|
||||
void lock () const
|
||||
{
|
||||
mHolder->lock ();
|
||||
}
|
||||
void unlock () const
|
||||
{
|
||||
mHolder->unlock ();
|
||||
}
|
||||
};
|
||||
|
||||
// A class that unlocks on construction and locks on destruction
|
||||
@@ -26,44 +35,44 @@ public:
|
||||
class ScopedUnlock
|
||||
{
|
||||
protected:
|
||||
bool mUnlocked;
|
||||
boost::recursive_mutex& mMutex;
|
||||
bool mUnlocked;
|
||||
boost::recursive_mutex& mMutex;
|
||||
|
||||
public:
|
||||
// VFALCO TODO get rid of this unlock parameter to restore sanity
|
||||
ScopedUnlock(boost::recursive_mutex& mutex, bool unlock = true) : mUnlocked(unlock), mMutex(mutex)
|
||||
{
|
||||
if (unlock)
|
||||
mMutex.unlock();
|
||||
}
|
||||
// VFALCO TODO get rid of this unlock parameter to restore sanity
|
||||
ScopedUnlock (boost::recursive_mutex& mutex, bool unlock = true) : mUnlocked (unlock), mMutex (mutex)
|
||||
{
|
||||
if (unlock)
|
||||
mMutex.unlock ();
|
||||
}
|
||||
|
||||
~ScopedUnlock()
|
||||
{
|
||||
if (mUnlocked)
|
||||
mMutex.lock();
|
||||
}
|
||||
~ScopedUnlock ()
|
||||
{
|
||||
if (mUnlocked)
|
||||
mMutex.lock ();
|
||||
}
|
||||
|
||||
void lock()
|
||||
{
|
||||
if (mUnlocked)
|
||||
{
|
||||
mMutex.lock();
|
||||
mUnlocked = false;
|
||||
}
|
||||
}
|
||||
void lock ()
|
||||
{
|
||||
if (mUnlocked)
|
||||
{
|
||||
mMutex.lock ();
|
||||
mUnlocked = false;
|
||||
}
|
||||
}
|
||||
|
||||
void unlock()
|
||||
{
|
||||
if (!mUnlocked)
|
||||
{
|
||||
mUnlocked = true;
|
||||
mMutex.unlock();
|
||||
}
|
||||
}
|
||||
void unlock ()
|
||||
{
|
||||
if (!mUnlocked)
|
||||
{
|
||||
mUnlocked = true;
|
||||
mMutex.unlock ();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
ScopedUnlock(const ScopedUnlock&); // no implementation
|
||||
ScopedUnlock& operator=(const ScopedUnlock&); // no implementation
|
||||
ScopedUnlock (const ScopedUnlock&); // no implementation
|
||||
ScopedUnlock& operator= (const ScopedUnlock&); // no implementation
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -3,293 +3,304 @@
|
||||
#define _vsnprintf(a,b,c,d) vsnprintf(a,b,c,d)
|
||||
#endif
|
||||
|
||||
std::string strprintf(const char* format, ...)
|
||||
std::string strprintf (const char* format, ...)
|
||||
{
|
||||
char buffer[50000];
|
||||
char* p = buffer;
|
||||
int limit = sizeof(buffer);
|
||||
int ret;
|
||||
for (;;)
|
||||
{
|
||||
va_list arg_ptr;
|
||||
va_start(arg_ptr, format);
|
||||
ret = _vsnprintf(p, limit, format, arg_ptr);
|
||||
va_end(arg_ptr);
|
||||
if (ret >= 0 && ret < limit)
|
||||
break;
|
||||
if (p != buffer)
|
||||
delete[] p;
|
||||
limit *= 2;
|
||||
p = new char[limit];
|
||||
if (p == NULL)
|
||||
throw std::bad_alloc();
|
||||
}
|
||||
std::string str(p, p+ret);
|
||||
if (p != buffer)
|
||||
delete[] p;
|
||||
return str;
|
||||
char buffer[50000];
|
||||
char* p = buffer;
|
||||
int limit = sizeof (buffer);
|
||||
int ret;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
va_list arg_ptr;
|
||||
va_start (arg_ptr, format);
|
||||
ret = _vsnprintf (p, limit, format, arg_ptr);
|
||||
va_end (arg_ptr);
|
||||
|
||||
if (ret >= 0 && ret < limit)
|
||||
break;
|
||||
|
||||
if (p != buffer)
|
||||
delete[] p;
|
||||
|
||||
limit *= 2;
|
||||
p = new char[limit];
|
||||
|
||||
if (p == NULL)
|
||||
throw std::bad_alloc ();
|
||||
}
|
||||
|
||||
std::string str (p, p + ret);
|
||||
|
||||
if (p != buffer)
|
||||
delete[] p;
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
char charHex(int iDigit)
|
||||
char charHex (int iDigit)
|
||||
{
|
||||
return iDigit < 10 ? '0' + iDigit : 'A' - 10 + iDigit;
|
||||
return iDigit < 10 ? '0' + iDigit : 'A' - 10 + iDigit;
|
||||
}
|
||||
|
||||
int charUnHex(char cDigit)
|
||||
int charUnHex (char cDigit)
|
||||
{
|
||||
return cDigit >= '0' && cDigit <= '9'
|
||||
? cDigit - '0'
|
||||
: cDigit >= 'A' && cDigit <= 'F'
|
||||
? cDigit - 'A' + 10
|
||||
: cDigit >= 'a' && cDigit <= 'f'
|
||||
? cDigit - 'a' + 10
|
||||
: -1;
|
||||
return cDigit >= '0' && cDigit <= '9'
|
||||
? cDigit - '0'
|
||||
: cDigit >= 'A' && cDigit <= 'F'
|
||||
? cDigit - 'A' + 10
|
||||
: cDigit >= 'a' && cDigit <= 'f'
|
||||
? cDigit - 'a' + 10
|
||||
: -1;
|
||||
}
|
||||
|
||||
int strUnHex(std::string& strDst, const std::string& strSrc)
|
||||
int strUnHex (std::string& strDst, const std::string& strSrc)
|
||||
{
|
||||
int iBytes = (strSrc.size()+1)/2;
|
||||
int iBytes = (strSrc.size () + 1) / 2;
|
||||
|
||||
strDst.resize(iBytes);
|
||||
strDst.resize (iBytes);
|
||||
|
||||
const char* pSrc = &strSrc[0];
|
||||
char* pDst = &strDst[0];
|
||||
const char* pSrc = &strSrc[0];
|
||||
char* pDst = &strDst[0];
|
||||
|
||||
if (strSrc.size() & 1)
|
||||
{
|
||||
int c = charUnHex(*pSrc++);
|
||||
if (strSrc.size () & 1)
|
||||
{
|
||||
int c = charUnHex (*pSrc++);
|
||||
|
||||
if (c < 0)
|
||||
{
|
||||
iBytes = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
*pDst++ = c;
|
||||
}
|
||||
}
|
||||
if (c < 0)
|
||||
{
|
||||
iBytes = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
*pDst++ = c;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i=0; iBytes >= 0 && i != iBytes; i++)
|
||||
{
|
||||
int cHigh = charUnHex(*pSrc++);
|
||||
int cLow = charUnHex(*pSrc++);
|
||||
for (int i = 0; iBytes >= 0 && i != iBytes; i++)
|
||||
{
|
||||
int cHigh = charUnHex (*pSrc++);
|
||||
int cLow = charUnHex (*pSrc++);
|
||||
|
||||
if (cHigh < 0 || cLow < 0)
|
||||
{
|
||||
iBytes = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
strDst[i] = (cHigh << 4) | cLow;
|
||||
}
|
||||
}
|
||||
if (cHigh < 0 || cLow < 0)
|
||||
{
|
||||
iBytes = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
strDst[i] = (cHigh << 4) | cLow;
|
||||
}
|
||||
}
|
||||
|
||||
if (iBytes < 0)
|
||||
strDst.clear();
|
||||
if (iBytes < 0)
|
||||
strDst.clear ();
|
||||
|
||||
return iBytes;
|
||||
return iBytes;
|
||||
}
|
||||
|
||||
Blob strUnHex(const std::string& strSrc)
|
||||
Blob strUnHex (const std::string& strSrc)
|
||||
{
|
||||
std::string strTmp;
|
||||
std::string strTmp;
|
||||
|
||||
strUnHex(strTmp, strSrc);
|
||||
strUnHex (strTmp, strSrc);
|
||||
|
||||
return strCopy(strTmp);
|
||||
return strCopy (strTmp);
|
||||
}
|
||||
|
||||
uint64_t uintFromHex(const std::string& strSrc)
|
||||
uint64_t uintFromHex (const std::string& strSrc)
|
||||
{
|
||||
uint64_t uValue = 0;
|
||||
uint64_t uValue = 0;
|
||||
|
||||
BOOST_FOREACH(char c, strSrc)
|
||||
uValue = (uValue << 4) | charUnHex(c);
|
||||
BOOST_FOREACH (char c, strSrc)
|
||||
uValue = (uValue << 4) | charUnHex (c);
|
||||
|
||||
return uValue;
|
||||
return uValue;
|
||||
}
|
||||
|
||||
//
|
||||
// Misc string
|
||||
//
|
||||
|
||||
Blob strCopy(const std::string& strSrc)
|
||||
Blob strCopy (const std::string& strSrc)
|
||||
{
|
||||
Blob vucDst;
|
||||
Blob vucDst;
|
||||
|
||||
vucDst.resize(strSrc.size());
|
||||
vucDst.resize (strSrc.size ());
|
||||
|
||||
std::copy(strSrc.begin(), strSrc.end(), vucDst.begin());
|
||||
std::copy (strSrc.begin (), strSrc.end (), vucDst.begin ());
|
||||
|
||||
return vucDst;
|
||||
return vucDst;
|
||||
}
|
||||
|
||||
std::string strCopy(Blob const& vucSrc)
|
||||
std::string strCopy (Blob const& vucSrc)
|
||||
{
|
||||
std::string strDst;
|
||||
std::string strDst;
|
||||
|
||||
strDst.resize(vucSrc.size());
|
||||
strDst.resize (vucSrc.size ());
|
||||
|
||||
std::copy(vucSrc.begin(), vucSrc.end(), strDst.begin());
|
||||
std::copy (vucSrc.begin (), vucSrc.end (), strDst.begin ());
|
||||
|
||||
return strDst;
|
||||
return strDst;
|
||||
|
||||
}
|
||||
|
||||
extern std::string urlEncode(const std::string& strSrc)
|
||||
extern std::string urlEncode (const std::string& strSrc)
|
||||
{
|
||||
std::string strDst;
|
||||
int iOutput = 0;
|
||||
int iSize = strSrc.length();
|
||||
std::string strDst;
|
||||
int iOutput = 0;
|
||||
int iSize = strSrc.length ();
|
||||
|
||||
strDst.resize(iSize*3);
|
||||
strDst.resize (iSize * 3);
|
||||
|
||||
for (int iInput = 0; iInput < iSize; iInput++) {
|
||||
unsigned char c = strSrc[iInput];
|
||||
for (int iInput = 0; iInput < iSize; iInput++)
|
||||
{
|
||||
unsigned char c = strSrc[iInput];
|
||||
|
||||
if (c == ' ')
|
||||
{
|
||||
strDst[iOutput++] = '+';
|
||||
}
|
||||
else if (isalnum(c))
|
||||
{
|
||||
strDst[iOutput++] = c;
|
||||
}
|
||||
else
|
||||
{
|
||||
strDst[iOutput++] = '%';
|
||||
strDst[iOutput++] = charHex(c >> 4);
|
||||
strDst[iOutput++] = charHex(c & 15);
|
||||
}
|
||||
}
|
||||
if (c == ' ')
|
||||
{
|
||||
strDst[iOutput++] = '+';
|
||||
}
|
||||
else if (isalnum (c))
|
||||
{
|
||||
strDst[iOutput++] = c;
|
||||
}
|
||||
else
|
||||
{
|
||||
strDst[iOutput++] = '%';
|
||||
strDst[iOutput++] = charHex (c >> 4);
|
||||
strDst[iOutput++] = charHex (c & 15);
|
||||
}
|
||||
}
|
||||
|
||||
strDst.resize(iOutput);
|
||||
strDst.resize (iOutput);
|
||||
|
||||
return strDst;
|
||||
return strDst;
|
||||
}
|
||||
|
||||
//
|
||||
// IP Port parsing
|
||||
//
|
||||
// <-- iPort: "" = -1
|
||||
bool parseIpPort(const std::string& strSource, std::string& strIP, int& iPort)
|
||||
bool parseIpPort (const std::string& strSource, std::string& strIP, int& iPort)
|
||||
{
|
||||
boost::smatch smMatch;
|
||||
bool bValid = false;
|
||||
boost::smatch smMatch;
|
||||
bool bValid = false;
|
||||
|
||||
static boost::regex reEndpoint("\\`\\s*(\\S+)(?:\\s+(\\d+))?\\s*\\'");
|
||||
static boost::regex reEndpoint ("\\`\\s*(\\S+)(?:\\s+(\\d+))?\\s*\\'");
|
||||
|
||||
if (boost::regex_match(strSource, smMatch, reEndpoint))
|
||||
{
|
||||
boost::system::error_code err;
|
||||
std::string strIPRaw = smMatch[1];
|
||||
std::string strPortRaw = smMatch[2];
|
||||
if (boost::regex_match (strSource, smMatch, reEndpoint))
|
||||
{
|
||||
boost::system::error_code err;
|
||||
std::string strIPRaw = smMatch[1];
|
||||
std::string strPortRaw = smMatch[2];
|
||||
|
||||
boost::asio::ip::address addrIP = boost::asio::ip::address::from_string(strIPRaw, err);
|
||||
boost::asio::ip::address addrIP = boost::asio::ip::address::from_string (strIPRaw, err);
|
||||
|
||||
bValid = !err;
|
||||
if (bValid)
|
||||
{
|
||||
strIP = addrIP.to_string();
|
||||
iPort = strPortRaw.empty() ? -1 : boost::lexical_cast<int>(strPortRaw);
|
||||
}
|
||||
}
|
||||
bValid = !err;
|
||||
|
||||
return bValid;
|
||||
if (bValid)
|
||||
{
|
||||
strIP = addrIP.to_string ();
|
||||
iPort = strPortRaw.empty () ? -1 : boost::lexical_cast<int> (strPortRaw);
|
||||
}
|
||||
}
|
||||
|
||||
return bValid;
|
||||
}
|
||||
|
||||
bool parseUrl(const std::string& strUrl, std::string& strScheme, std::string& strDomain, int& iPort, std::string& strPath)
|
||||
bool parseUrl (const std::string& strUrl, std::string& strScheme, std::string& strDomain, int& iPort, std::string& strPath)
|
||||
{
|
||||
// scheme://username:password@hostname:port/rest
|
||||
static boost::regex reUrl("(?i)\\`\\s*([[:alpha:]][-+.[:alpha:][:digit:]]*)://([^:/]+)(?::(\\d+))?(/.*)?\\s*?\\'");
|
||||
boost::smatch smMatch;
|
||||
// scheme://username:password@hostname:port/rest
|
||||
static boost::regex reUrl ("(?i)\\`\\s*([[:alpha:]][-+.[:alpha:][:digit:]]*)://([^:/]+)(?::(\\d+))?(/.*)?\\s*?\\'");
|
||||
boost::smatch smMatch;
|
||||
|
||||
bool bMatch = boost::regex_match(strUrl, smMatch, reUrl); // Match status code.
|
||||
bool bMatch = boost::regex_match (strUrl, smMatch, reUrl); // Match status code.
|
||||
|
||||
if (bMatch)
|
||||
{
|
||||
std::string strPort;
|
||||
if (bMatch)
|
||||
{
|
||||
std::string strPort;
|
||||
|
||||
strScheme = smMatch[1];
|
||||
strDomain = smMatch[2];
|
||||
strPort = smMatch[3];
|
||||
strPath = smMatch[4];
|
||||
strScheme = smMatch[1];
|
||||
strDomain = smMatch[2];
|
||||
strPort = smMatch[3];
|
||||
strPath = smMatch[4];
|
||||
|
||||
boost::algorithm::to_lower(strScheme);
|
||||
boost::algorithm::to_lower (strScheme);
|
||||
|
||||
iPort = strPort.empty() ? -1 : lexical_cast_s<int>(strPort);
|
||||
// std::cerr << strUrl << " : " << bMatch << " : '" << strDomain << "' : '" << strPort << "' : " << iPort << " : '" << strPath << "'" << std::endl;
|
||||
}
|
||||
// std::cerr << strUrl << " : " << bMatch << " : '" << strDomain << "' : '" << strPath << "'" << std::endl;
|
||||
iPort = strPort.empty () ? -1 : lexical_cast_s<int> (strPort);
|
||||
// std::cerr << strUrl << " : " << bMatch << " : '" << strDomain << "' : '" << strPort << "' : " << iPort << " : '" << strPath << "'" << std::endl;
|
||||
}
|
||||
|
||||
return bMatch;
|
||||
// std::cerr << strUrl << " : " << bMatch << " : '" << strDomain << "' : '" << strPath << "'" << std::endl;
|
||||
|
||||
return bMatch;
|
||||
}
|
||||
|
||||
//
|
||||
// Quality parsing
|
||||
// - integers as is.
|
||||
// - floats multiplied by a billion
|
||||
bool parseQuality(const std::string& strSource, uint32& uQuality)
|
||||
bool parseQuality (const std::string& strSource, uint32& uQuality)
|
||||
{
|
||||
uQuality = lexical_cast_s<uint32>(strSource);
|
||||
uQuality = lexical_cast_s<uint32> (strSource);
|
||||
|
||||
if (!uQuality)
|
||||
{
|
||||
float fQuality = lexical_cast_s<float>(strSource);
|
||||
if (!uQuality)
|
||||
{
|
||||
float fQuality = lexical_cast_s<float> (strSource);
|
||||
|
||||
if (fQuality)
|
||||
uQuality = (uint32)(QUALITY_ONE*fQuality);
|
||||
}
|
||||
if (fQuality)
|
||||
uQuality = (uint32) (QUALITY_ONE * fQuality);
|
||||
}
|
||||
|
||||
return !!uQuality;
|
||||
return !!uQuality;
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE( Utils)
|
||||
BOOST_AUTO_TEST_SUITE ( Utils)
|
||||
|
||||
BOOST_AUTO_TEST_CASE( ParseUrl )
|
||||
BOOST_AUTO_TEST_CASE ( ParseUrl )
|
||||
{
|
||||
std::string strScheme;
|
||||
std::string strDomain;
|
||||
int iPort;
|
||||
std::string strPath;
|
||||
std::string strScheme;
|
||||
std::string strDomain;
|
||||
int iPort;
|
||||
std::string strPath;
|
||||
|
||||
if (!parseUrl("lower://domain", strScheme, strDomain, iPort, strPath))
|
||||
BOOST_FAIL("parseUrl: lower://domain failed");
|
||||
if (!parseUrl ("lower://domain", strScheme, strDomain, iPort, strPath))
|
||||
BOOST_FAIL ("parseUrl: lower://domain failed");
|
||||
|
||||
if (strScheme != "lower")
|
||||
BOOST_FAIL("parseUrl: lower://domain : scheme failed");
|
||||
if (strScheme != "lower")
|
||||
BOOST_FAIL ("parseUrl: lower://domain : scheme failed");
|
||||
|
||||
if (strDomain != "domain")
|
||||
BOOST_FAIL("parseUrl: lower://domain : domain failed");
|
||||
if (strDomain != "domain")
|
||||
BOOST_FAIL ("parseUrl: lower://domain : domain failed");
|
||||
|
||||
if (iPort != -1)
|
||||
BOOST_FAIL("parseUrl: lower://domain : port failed");
|
||||
if (iPort != -1)
|
||||
BOOST_FAIL ("parseUrl: lower://domain : port failed");
|
||||
|
||||
if (strPath != "")
|
||||
BOOST_FAIL("parseUrl: lower://domain : path failed");
|
||||
if (strPath != "")
|
||||
BOOST_FAIL ("parseUrl: lower://domain : path failed");
|
||||
|
||||
if (!parseUrl("UPPER://domain:234/", strScheme, strDomain, iPort, strPath))
|
||||
BOOST_FAIL("parseUrl: UPPER://domain:234/ failed");
|
||||
if (!parseUrl ("UPPER://domain:234/", strScheme, strDomain, iPort, strPath))
|
||||
BOOST_FAIL ("parseUrl: UPPER://domain:234/ failed");
|
||||
|
||||
if (strScheme != "upper")
|
||||
BOOST_FAIL("parseUrl: UPPER://domain:234/ : scheme failed");
|
||||
if (strScheme != "upper")
|
||||
BOOST_FAIL ("parseUrl: UPPER://domain:234/ : scheme failed");
|
||||
|
||||
if (iPort != 234)
|
||||
BOOST_FAIL(boost::str(boost::format("parseUrl: UPPER://domain:234/ : port failed: %d") % iPort));
|
||||
if (iPort != 234)
|
||||
BOOST_FAIL (boost::str (boost::format ("parseUrl: UPPER://domain:234/ : port failed: %d") % iPort));
|
||||
|
||||
if (strPath != "/")
|
||||
BOOST_FAIL("parseUrl: UPPER://domain:234/ : path failed");
|
||||
if (strPath != "/")
|
||||
BOOST_FAIL ("parseUrl: UPPER://domain:234/ : path failed");
|
||||
|
||||
if (!parseUrl("Mixed://domain/path", strScheme, strDomain, iPort, strPath))
|
||||
BOOST_FAIL("parseUrl: Mixed://domain/path failed");
|
||||
if (!parseUrl ("Mixed://domain/path", strScheme, strDomain, iPort, strPath))
|
||||
BOOST_FAIL ("parseUrl: Mixed://domain/path failed");
|
||||
|
||||
if (strScheme != "mixed")
|
||||
BOOST_FAIL("parseUrl: Mixed://domain/path tolower failed");
|
||||
if (strScheme != "mixed")
|
||||
BOOST_FAIL ("parseUrl: Mixed://domain/path tolower failed");
|
||||
|
||||
if (strPath != "/path")
|
||||
BOOST_FAIL("parseUrl: Mixed://domain/path path failed");
|
||||
if (strPath != "/path")
|
||||
BOOST_FAIL ("parseUrl: Mixed://domain/path path failed");
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
||||
BOOST_AUTO_TEST_SUITE_END ()
|
||||
|
||||
// vim:ts=4
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
// Ripple specific constant used for parsing qualities and other things
|
||||
//
|
||||
#define QUALITY_ONE 1000000000 // 10e9
|
||||
#define QUALITY_ONE 1000000000 // 10e9
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
@@ -58,152 +58,158 @@
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
extern std::string strprintf(const char* format, ...);
|
||||
extern std::string strprintf (const char* format, ...);
|
||||
|
||||
extern std::string urlEncode(const std::string& strSrc);
|
||||
extern std::string urlEncode (const std::string& strSrc);
|
||||
|
||||
template<class Iterator>
|
||||
std::string strJoin(Iterator first, Iterator last, std::string strSeperator)
|
||||
std::string strJoin (Iterator first, Iterator last, std::string strSeperator)
|
||||
{
|
||||
std::ostringstream ossValues;
|
||||
std::ostringstream ossValues;
|
||||
|
||||
for (Iterator start = first; first != last; first++)
|
||||
{
|
||||
ossValues << str(boost::format("%s%s") % (start == first ? "" : strSeperator) % *first);
|
||||
}
|
||||
for (Iterator start = first; first != last; first++)
|
||||
{
|
||||
ossValues << str (boost::format ("%s%s") % (start == first ? "" : strSeperator) % *first);
|
||||
}
|
||||
|
||||
return ossValues.str();
|
||||
return ossValues.str ();
|
||||
}
|
||||
|
||||
char charHex(int iDigit);
|
||||
char charHex (int iDigit);
|
||||
|
||||
template<class Iterator>
|
||||
std::string strHex(Iterator first, int iSize)
|
||||
std::string strHex (Iterator first, int iSize)
|
||||
{
|
||||
std::string strDst;
|
||||
std::string strDst;
|
||||
|
||||
strDst.resize(iSize*2);
|
||||
strDst.resize (iSize * 2);
|
||||
|
||||
for (int i = 0; i < iSize; i++) {
|
||||
unsigned char c = *first++;
|
||||
for (int i = 0; i < iSize; i++)
|
||||
{
|
||||
unsigned char c = *first++;
|
||||
|
||||
strDst[i*2] = charHex(c >> 4);
|
||||
strDst[i*2+1] = charHex(c & 15);
|
||||
}
|
||||
strDst[i * 2] = charHex (c >> 4);
|
||||
strDst[i * 2 + 1] = charHex (c & 15);
|
||||
}
|
||||
|
||||
return strDst;
|
||||
return strDst;
|
||||
}
|
||||
|
||||
inline const std::string strHex(const std::string& strSrc)
|
||||
inline const std::string strHex (const std::string& strSrc)
|
||||
{
|
||||
return strHex(strSrc.begin(), strSrc.size());
|
||||
return strHex (strSrc.begin (), strSrc.size ());
|
||||
}
|
||||
|
||||
inline std::string strHex(Blob const& vucData)
|
||||
inline std::string strHex (Blob const& vucData)
|
||||
{
|
||||
return strHex(vucData.begin(), vucData.size());
|
||||
return strHex (vucData.begin (), vucData.size ());
|
||||
}
|
||||
|
||||
inline std::string strHex(const uint64 uiHost)
|
||||
inline std::string strHex (const uint64 uiHost)
|
||||
{
|
||||
uint64_t uBig = htobe64(uiHost);
|
||||
uint64_t uBig = htobe64 (uiHost);
|
||||
|
||||
return strHex((unsigned char*) &uBig, sizeof(uBig));
|
||||
return strHex ((unsigned char*) &uBig, sizeof (uBig));
|
||||
}
|
||||
|
||||
inline static std::string sqlEscape(const std::string& strSrc)
|
||||
inline static std::string sqlEscape (const std::string& strSrc)
|
||||
{
|
||||
static boost::format f("X'%s'");
|
||||
return str(boost::format(f) % strHex(strSrc));
|
||||
static boost::format f ("X'%s'");
|
||||
return str (boost::format (f) % strHex (strSrc));
|
||||
}
|
||||
|
||||
inline static std::string sqlEscape(Blob const& vecSrc)
|
||||
inline static std::string sqlEscape (Blob const& vecSrc)
|
||||
{
|
||||
size_t size = vecSrc.size();
|
||||
if (size == 0)
|
||||
return "X''";
|
||||
size_t size = vecSrc.size ();
|
||||
|
||||
std::string j(size * 2 + 3, 0);
|
||||
if (size == 0)
|
||||
return "X''";
|
||||
|
||||
unsigned char *oPtr = reinterpret_cast<unsigned char *>(&*j.begin());
|
||||
const unsigned char *iPtr = &vecSrc[0];
|
||||
std::string j (size * 2 + 3, 0);
|
||||
|
||||
*oPtr++ = 'X';
|
||||
*oPtr++ = '\'';
|
||||
unsigned char* oPtr = reinterpret_cast<unsigned char*> (&*j.begin ());
|
||||
const unsigned char* iPtr = &vecSrc[0];
|
||||
|
||||
for (int i = size; i != 0; --i)
|
||||
{
|
||||
unsigned char c = *iPtr++;
|
||||
*oPtr++ = charHex(c >> 4);
|
||||
*oPtr++ = charHex(c & 15);
|
||||
}
|
||||
*oPtr++ = 'X';
|
||||
*oPtr++ = '\'';
|
||||
|
||||
*oPtr++ = '\'';
|
||||
return j;
|
||||
for (int i = size; i != 0; --i)
|
||||
{
|
||||
unsigned char c = *iPtr++;
|
||||
*oPtr++ = charHex (c >> 4);
|
||||
*oPtr++ = charHex (c & 15);
|
||||
}
|
||||
|
||||
*oPtr++ = '\'';
|
||||
return j;
|
||||
}
|
||||
|
||||
template<class Iterator>
|
||||
bool isZero(Iterator first, int iSize)
|
||||
bool isZero (Iterator first, int iSize)
|
||||
{
|
||||
while (iSize && !*first++)
|
||||
--iSize;
|
||||
while (iSize && !*first++)
|
||||
--iSize;
|
||||
|
||||
return !iSize;
|
||||
return !iSize;
|
||||
}
|
||||
|
||||
int charUnHex(char cDigit);
|
||||
int strUnHex(std::string& strDst, const std::string& strSrc);
|
||||
int charUnHex (char cDigit);
|
||||
int strUnHex (std::string& strDst, const std::string& strSrc);
|
||||
|
||||
uint64_t uintFromHex(const std::string& strSrc);
|
||||
uint64_t uintFromHex (const std::string& strSrc);
|
||||
|
||||
Blob strUnHex(const std::string& strSrc);
|
||||
Blob strUnHex (const std::string& strSrc);
|
||||
|
||||
Blob strCopy(const std::string& strSrc);
|
||||
std::string strCopy(Blob const& vucSrc);
|
||||
Blob strCopy (const std::string& strSrc);
|
||||
std::string strCopy (Blob const& vucSrc);
|
||||
|
||||
bool parseIpPort(const std::string& strSource, std::string& strIP, int& iPort);
|
||||
bool parseQuality(const std::string& strSource, uint32& uQuality);
|
||||
bool parseIpPort (const std::string& strSource, std::string& strIP, int& iPort);
|
||||
bool parseQuality (const std::string& strSource, uint32& uQuality);
|
||||
|
||||
inline std::string strGetEnv(const std::string& strKey)
|
||||
inline std::string strGetEnv (const std::string& strKey)
|
||||
{
|
||||
return getenv(strKey.c_str()) ? getenv(strKey.c_str()) : "";
|
||||
return getenv (strKey.c_str ()) ? getenv (strKey.c_str ()) : "";
|
||||
}
|
||||
|
||||
template<typename T> T lexical_cast_s(const std::string& string)
|
||||
{ // lexically cast a string to the selected type. Does not throw
|
||||
try
|
||||
{
|
||||
return boost::lexical_cast<T>(string);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
template<typename T> T lexical_cast_s (const std::string& string)
|
||||
{
|
||||
// lexically cast a string to the selected type. Does not throw
|
||||
try
|
||||
{
|
||||
return boost::lexical_cast<T> (string);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T> std::string lexical_cast_i(const T& t)
|
||||
{ // lexicaly cast the selected type to a string. Does not throw
|
||||
try
|
||||
{
|
||||
return boost::lexical_cast<std::string>(t);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
template<typename T> std::string lexical_cast_i (const T& t)
|
||||
{
|
||||
// lexicaly cast the selected type to a string. Does not throw
|
||||
try
|
||||
{
|
||||
return boost::lexical_cast<std::string> (t);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T> T lexical_cast_st(const std::string& string)
|
||||
{ // lexically cast a string to the selected type. Does throw
|
||||
return boost::lexical_cast<T>(string);
|
||||
template<typename T> T lexical_cast_st (const std::string& string)
|
||||
{
|
||||
// lexically cast a string to the selected type. Does throw
|
||||
return boost::lexical_cast<T> (string);
|
||||
}
|
||||
|
||||
template<typename T> std::string lexical_cast_it(const T& t)
|
||||
{ // lexicaly cast the selected type to a string. Does not throw
|
||||
return boost::lexical_cast<std::string>(t);
|
||||
template<typename T> std::string lexical_cast_it (const T& t)
|
||||
{
|
||||
// lexicaly cast the selected type to a string. Does not throw
|
||||
return boost::lexical_cast<std::string> (t);
|
||||
}
|
||||
|
||||
bool parseUrl(const std::string& strUrl, std::string& strScheme, std::string& strDomain, int& iPort, std::string& strPath);
|
||||
bool parseUrl (const std::string& strUrl, std::string& strScheme, std::string& strDomain, int& iPort, std::string& strPath);
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -1,90 +1,106 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
Copyright (c) 2011-2013, OpenCoin, Inc.
|
||||
Copyright (c) 2011-2013, OpenCoin, Inc.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifdef __unix__
|
||||
|
||||
static pid_t pManager = static_cast<pid_t>(0);
|
||||
static pid_t pChild = static_cast<pid_t>(0);
|
||||
static pid_t pManager = static_cast<pid_t> (0);
|
||||
static pid_t pChild = static_cast<pid_t> (0);
|
||||
|
||||
static void pass_signal(int a)
|
||||
static void pass_signal (int a)
|
||||
{
|
||||
kill(pChild, a);
|
||||
kill (pChild, a);
|
||||
}
|
||||
|
||||
static void stop_manager(int)
|
||||
static void stop_manager (int)
|
||||
{
|
||||
kill(pChild, SIGINT);
|
||||
_exit(0);
|
||||
kill (pChild, SIGINT);
|
||||
_exit (0);
|
||||
}
|
||||
|
||||
bool HaveSustain()
|
||||
bool HaveSustain ()
|
||||
{
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string StopSustain()
|
||||
std::string StopSustain ()
|
||||
{
|
||||
if (getppid() != pManager)
|
||||
return std::string();
|
||||
kill(pManager, SIGHUP);
|
||||
return "Terminating monitor";
|
||||
if (getppid () != pManager)
|
||||
return std::string ();
|
||||
|
||||
kill (pManager, SIGHUP);
|
||||
return "Terminating monitor";
|
||||
}
|
||||
|
||||
std::string DoSustain()
|
||||
std::string DoSustain ()
|
||||
{
|
||||
int childCount = 0;
|
||||
pManager = getpid();
|
||||
signal(SIGINT, stop_manager);
|
||||
signal(SIGHUP, stop_manager);
|
||||
signal(SIGUSR1, pass_signal);
|
||||
signal(SIGUSR2, pass_signal);
|
||||
while (1)
|
||||
{
|
||||
++childCount;
|
||||
pChild = fork();
|
||||
if (pChild == -1)
|
||||
_exit(0);
|
||||
if (pChild == 0)
|
||||
{
|
||||
setCallingThreadName("main");
|
||||
signal(SIGINT, SIG_DFL);
|
||||
signal(SIGHUP, SIG_DFL);
|
||||
signal(SIGUSR1, SIG_DFL);
|
||||
signal(SIGUSR2, SIG_DFL);
|
||||
return str(boost::format("Launching child %d") % childCount);;
|
||||
}
|
||||
setCallingThreadName(boost::str(boost::format("#%d") % childCount).c_str());
|
||||
do
|
||||
{
|
||||
int i;
|
||||
sleep(10);
|
||||
waitpid(-1, &i, 0);
|
||||
}
|
||||
while (kill(pChild, 0) == 0);
|
||||
rename("core", boost::str(boost::format("core.%d") % static_cast<int>(pChild)).c_str());
|
||||
rename("debug.log", boost::str(boost::format("debug.log.%d") % static_cast<int>(pChild)).c_str());
|
||||
}
|
||||
int childCount = 0;
|
||||
pManager = getpid ();
|
||||
signal (SIGINT, stop_manager);
|
||||
signal (SIGHUP, stop_manager);
|
||||
signal (SIGUSR1, pass_signal);
|
||||
signal (SIGUSR2, pass_signal);
|
||||
|
||||
while (1)
|
||||
{
|
||||
++childCount;
|
||||
pChild = fork ();
|
||||
|
||||
if (pChild == -1)
|
||||
_exit (0);
|
||||
|
||||
if (pChild == 0)
|
||||
{
|
||||
setCallingThreadName ("main");
|
||||
signal (SIGINT, SIG_DFL);
|
||||
signal (SIGHUP, SIG_DFL);
|
||||
signal (SIGUSR1, SIG_DFL);
|
||||
signal (SIGUSR2, SIG_DFL);
|
||||
return str (boost::format ("Launching child %d") % childCount);;
|
||||
}
|
||||
|
||||
setCallingThreadName (boost::str (boost::format ("#%d") % childCount).c_str ());
|
||||
|
||||
do
|
||||
{
|
||||
int i;
|
||||
sleep (10);
|
||||
waitpid (-1, &i, 0);
|
||||
}
|
||||
while (kill (pChild, 0) == 0);
|
||||
|
||||
rename ("core", boost::str (boost::format ("core.%d") % static_cast<int> (pChild)).c_str ());
|
||||
rename ("debug.log", boost::str (boost::format ("debug.log.%d") % static_cast<int> (pChild)).c_str ());
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
bool HaveSustain() { return false; }
|
||||
std::string DoSustain() { return std::string(); }
|
||||
std::string StopSustain() { return std::string(); }
|
||||
bool HaveSustain ()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
std::string DoSustain ()
|
||||
{
|
||||
return std::string ();
|
||||
}
|
||||
std::string StopSustain ()
|
||||
{
|
||||
return std::string ();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
Copyright (c) 2011-2013, OpenCoin, Inc.
|
||||
Copyright (c) 2011-2013, OpenCoin, Inc.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
@@ -23,8 +23,8 @@
|
||||
// and relaunches it on a fault.
|
||||
//
|
||||
// VFALCO TODO Rename this and put it in a class.
|
||||
extern bool HaveSustain();
|
||||
extern std::string StopSustain();
|
||||
extern std::string DoSustain();
|
||||
extern bool HaveSustain ();
|
||||
extern std::string StopSustain ();
|
||||
extern std::string DoSustain ();
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
Copyright (c) 2011-2013, OpenCoin, Inc.
|
||||
Copyright (c) 2011-2013, OpenCoin, Inc.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
@@ -21,15 +21,15 @@
|
||||
|
||||
void setCallingThreadName (char const* threadName)
|
||||
{
|
||||
struct ThreadInfo
|
||||
{
|
||||
DWORD dwType;
|
||||
LPCSTR szName;
|
||||
DWORD dwThreadID;
|
||||
DWORD dwFlags;
|
||||
};
|
||||
struct ThreadInfo
|
||||
{
|
||||
DWORD dwType;
|
||||
LPCSTR szName;
|
||||
DWORD dwThreadID;
|
||||
DWORD dwFlags;
|
||||
};
|
||||
|
||||
ThreadInfo info;
|
||||
ThreadInfo info;
|
||||
|
||||
info.dwType = 0x1000;
|
||||
info.szName = threadName;
|
||||
@@ -38,45 +38,52 @@ void setCallingThreadName (char const* threadName)
|
||||
|
||||
__try
|
||||
{
|
||||
// This is a VisualStudio specific exception
|
||||
// This is a VisualStudio specific exception
|
||||
RaiseException (0x406d1388, 0, sizeof (info) / sizeof (ULONG_PTR), (ULONG_PTR*) &info);
|
||||
}
|
||||
__except (EXCEPTION_CONTINUE_EXECUTION)
|
||||
{
|
||||
}
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
#ifdef PR_SET_NAME
|
||||
#define HAVE_NAME_THREAD
|
||||
extern void setCallingThreadName (const char* n)
|
||||
{
|
||||
static std::string pName;
|
||||
#ifdef PR_SET_NAME
|
||||
#define HAVE_NAME_THREAD
|
||||
extern void setCallingThreadName (const char* n)
|
||||
{
|
||||
static std::string pName;
|
||||
|
||||
if (pName.empty())
|
||||
{
|
||||
std::ifstream cLine("/proc/self/cmdline", std::ios::in);
|
||||
cLine >> pName;
|
||||
if (pName.empty())
|
||||
pName = "rippled";
|
||||
else
|
||||
{
|
||||
size_t zero = pName.find_first_of('\0');
|
||||
if ((zero != std::string::npos) && (zero != 0))
|
||||
pName = pName.substr(0, zero);
|
||||
size_t slash = pName.find_last_of('/');
|
||||
if (slash != std::string::npos)
|
||||
pName = pName.substr(slash + 1);
|
||||
}
|
||||
pName += " ";
|
||||
}
|
||||
if (pName.empty ())
|
||||
{
|
||||
std::ifstream cLine ("/proc/self/cmdline", std::ios::in);
|
||||
cLine >> pName;
|
||||
|
||||
prctl(PR_SET_NAME, (pName + n).c_str(), 0, 0, 0);
|
||||
}
|
||||
#endif
|
||||
if (pName.empty ())
|
||||
pName = "rippled";
|
||||
else
|
||||
{
|
||||
size_t zero = pName.find_first_of ('\0');
|
||||
|
||||
#ifndef HAVE_NAME_THREAD
|
||||
extern void setCallingThreadName(const char*)
|
||||
{ ; }
|
||||
#endif
|
||||
if ((zero != std::string::npos) && (zero != 0))
|
||||
pName = pName.substr (0, zero);
|
||||
|
||||
size_t slash = pName.find_last_of ('/');
|
||||
|
||||
if (slash != std::string::npos)
|
||||
pName = pName.substr (slash + 1);
|
||||
}
|
||||
|
||||
pName += " ";
|
||||
}
|
||||
|
||||
prctl (PR_SET_NAME, (pName + n).c_str (), 0, 0, 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_NAME_THREAD
|
||||
extern void setCallingThreadName (const char*)
|
||||
{
|
||||
;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
Copyright (c) 2011-2013, OpenCoin, Inc.
|
||||
Copyright (c) 2011-2013, OpenCoin, Inc.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
Copyright (c) 2011-2013, OpenCoin, Inc.
|
||||
Copyright (c) 2011-2013, OpenCoin, Inc.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
@@ -21,34 +21,34 @@
|
||||
// We have our own epoch.
|
||||
//
|
||||
|
||||
boost::posix_time::ptime ptEpoch()
|
||||
boost::posix_time::ptime ptEpoch ()
|
||||
{
|
||||
return boost::posix_time::ptime(boost::gregorian::date(2000, boost::gregorian::Jan, 1));
|
||||
return boost::posix_time::ptime (boost::gregorian::date (2000, boost::gregorian::Jan, 1));
|
||||
}
|
||||
|
||||
int iToSeconds(boost::posix_time::ptime ptWhen)
|
||||
int iToSeconds (boost::posix_time::ptime ptWhen)
|
||||
{
|
||||
return ptWhen.is_not_a_date_time()
|
||||
? -1
|
||||
: (ptWhen-ptEpoch()).total_seconds();
|
||||
return ptWhen.is_not_a_date_time ()
|
||||
? -1
|
||||
: (ptWhen - ptEpoch ()).total_seconds ();
|
||||
}
|
||||
|
||||
// Convert our time in seconds to a ptime.
|
||||
boost::posix_time::ptime ptFromSeconds(int iSeconds)
|
||||
boost::posix_time::ptime ptFromSeconds (int iSeconds)
|
||||
{
|
||||
return iSeconds < 0
|
||||
? boost::posix_time::ptime(boost::posix_time::not_a_date_time)
|
||||
: ptEpoch() + boost::posix_time::seconds(iSeconds);
|
||||
return iSeconds < 0
|
||||
? boost::posix_time::ptime (boost::posix_time::not_a_date_time)
|
||||
: ptEpoch () + boost::posix_time::seconds (iSeconds);
|
||||
}
|
||||
|
||||
// Convert from our time to UNIX time in seconds.
|
||||
uint64_t utFromSeconds(int iSeconds)
|
||||
uint64_t utFromSeconds (int iSeconds)
|
||||
{
|
||||
boost::posix_time::time_duration tdDelta =
|
||||
boost::posix_time::ptime(boost::gregorian::date(2000, boost::gregorian::Jan, 1))
|
||||
-boost::posix_time::ptime(boost::gregorian::date(1970, boost::gregorian::Jan, 1))
|
||||
+boost::posix_time::seconds(iSeconds)
|
||||
;
|
||||
boost::posix_time::time_duration tdDelta =
|
||||
boost::posix_time::ptime (boost::gregorian::date (2000, boost::gregorian::Jan, 1))
|
||||
- boost::posix_time::ptime (boost::gregorian::date (1970, boost::gregorian::Jan, 1))
|
||||
+ boost::posix_time::seconds (iSeconds)
|
||||
;
|
||||
|
||||
return tdDelta.total_seconds();
|
||||
return tdDelta.total_seconds ();
|
||||
}
|
||||
|
||||
@@ -1,27 +1,27 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
Copyright (c) 2011-2013, OpenCoin, Inc.
|
||||
Copyright (c) 2011-2013, OpenCoin, Inc.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef RIPPLE_TIME_H
|
||||
#define RIPPLE_TIME_H
|
||||
|
||||
boost::posix_time::ptime ptEpoch();
|
||||
int iToSeconds(boost::posix_time::ptime ptWhen);
|
||||
boost::posix_time::ptime ptFromSeconds(int iSeconds);
|
||||
uint64_t utFromSeconds(int iSeconds);
|
||||
boost::posix_time::ptime ptEpoch ();
|
||||
int iToSeconds (boost::posix_time::ptime ptWhen);
|
||||
boost::posix_time::ptime ptFromSeconds (int iSeconds);
|
||||
uint64_t utFromSeconds (int iSeconds);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,25 +1,25 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
Copyright (c) 2011-2013, OpenCoin, Inc.
|
||||
Copyright (c) 2011-2013, OpenCoin, Inc.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
UptimeTimer::UptimeTimer ()
|
||||
: m_elapsedTime (0)
|
||||
, m_startTime (::time (0))
|
||||
, m_isUpdatingManually (false)
|
||||
: m_elapsedTime (0)
|
||||
, m_startTime (::time (0))
|
||||
, m_isUpdatingManually (false)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -29,45 +29,45 @@ UptimeTimer::~UptimeTimer ()
|
||||
|
||||
int UptimeTimer::getElapsedSeconds () const
|
||||
{
|
||||
int result;
|
||||
int result;
|
||||
|
||||
if (m_isUpdatingManually)
|
||||
{
|
||||
// vf::memoryBarrier();
|
||||
result = m_elapsedTime;
|
||||
}
|
||||
else
|
||||
{
|
||||
// VFALCO TODO use time_t instead of int return
|
||||
result = static_cast <int> (::time (0) - m_startTime);
|
||||
}
|
||||
if (m_isUpdatingManually)
|
||||
{
|
||||
// vf::memoryBarrier();
|
||||
result = m_elapsedTime;
|
||||
}
|
||||
else
|
||||
{
|
||||
// VFALCO TODO use time_t instead of int return
|
||||
result = static_cast <int> (::time (0) - m_startTime);
|
||||
}
|
||||
|
||||
return result;
|
||||
return result;
|
||||
}
|
||||
|
||||
void UptimeTimer::beginManualUpdates ()
|
||||
{
|
||||
//assert (!m_isUpdatingManually);
|
||||
//assert (!m_isUpdatingManually);
|
||||
|
||||
m_isUpdatingManually = true;
|
||||
m_isUpdatingManually = true;
|
||||
}
|
||||
|
||||
void UptimeTimer::endManualUpdates ()
|
||||
{
|
||||
//assert (m_isUpdatingManually);
|
||||
//assert (m_isUpdatingManually);
|
||||
|
||||
m_isUpdatingManually = false;
|
||||
m_isUpdatingManually = false;
|
||||
}
|
||||
|
||||
void UptimeTimer::incrementElapsedTime ()
|
||||
{
|
||||
//assert (m_isUpdatingManually);
|
||||
++m_elapsedTime;
|
||||
//assert (m_isUpdatingManually);
|
||||
++m_elapsedTime;
|
||||
}
|
||||
|
||||
UptimeTimer& UptimeTimer::getInstance ()
|
||||
{
|
||||
static UptimeTimer instance;
|
||||
static UptimeTimer instance;
|
||||
|
||||
return instance;
|
||||
return instance;
|
||||
}
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
Copyright (c) 2011-2013, OpenCoin, Inc.
|
||||
Copyright (c) 2011-2013, OpenCoin, Inc.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
@@ -21,35 +21,35 @@
|
||||
|
||||
/** Tracks program uptime.
|
||||
|
||||
The timer can be switched to a manual system of updating, to reduce
|
||||
system calls. (?)
|
||||
The timer can be switched to a manual system of updating, to reduce
|
||||
system calls. (?)
|
||||
*/
|
||||
// VFALCO TODO determine if the non-manual timing is actually needed
|
||||
class UptimeTimer
|
||||
{
|
||||
private:
|
||||
UptimeTimer ();
|
||||
~UptimeTimer ();
|
||||
UptimeTimer ();
|
||||
~UptimeTimer ();
|
||||
|
||||
public:
|
||||
int getElapsedSeconds () const;
|
||||
int getElapsedSeconds () const;
|
||||
|
||||
void beginManualUpdates ();
|
||||
void endManualUpdates ();
|
||||
void beginManualUpdates ();
|
||||
void endManualUpdates ();
|
||||
|
||||
void incrementElapsedTime ();
|
||||
void incrementElapsedTime ();
|
||||
|
||||
static UptimeTimer& getInstance ();
|
||||
static UptimeTimer& getInstance ();
|
||||
|
||||
private:
|
||||
// VFALCO DEPRECATED, Use a memory barrier instead of forcing a cache line
|
||||
int m_pad1; // make sure m_elapsedTime fits in its own cache line
|
||||
int volatile m_elapsedTime;
|
||||
int m_pad2;
|
||||
// VFALCO DEPRECATED, Use a memory barrier instead of forcing a cache line
|
||||
int m_pad1; // make sure m_elapsedTime fits in its own cache line
|
||||
int volatile m_elapsedTime;
|
||||
int m_pad2;
|
||||
|
||||
time_t m_startTime;
|
||||
time_t m_startTime;
|
||||
|
||||
bool m_isUpdatingManually;
|
||||
bool m_isUpdatingManually;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,22 +1,22 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
Copyright (c) 2011-2013, OpenCoin, Inc.
|
||||
Copyright (c) 2011-2013, OpenCoin, Inc.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
/** Add this to get the @ref ripple_client module.
|
||||
/** Add this to get the @ref ripple_client module.
|
||||
|
||||
@file ripple_client.cpp
|
||||
@ingroup ripple_client
|
||||
@@ -38,36 +38,36 @@
|
||||
|
||||
// Order and indentation reflect the hierarchy of dependencies
|
||||
// VFALCO NOTE Don't add anything here!!!
|
||||
#include "src/cpp/ripple/ripple_HashedObject.h"
|
||||
#include "src/cpp/ripple/ripple_SHAMapItem.h"
|
||||
#include "src/cpp/ripple/ripple_SHAMapNode.h"
|
||||
#include "src/cpp/ripple/ripple_SHAMapAddNode.h"
|
||||
#include "src/cpp/ripple/ripple_SHAMapMissingNode.h"
|
||||
#include "src/cpp/ripple/ripple_SHAMapTreeNode.h"
|
||||
#include "src/cpp/ripple/ripple_SHAMapSyncFilter.h"
|
||||
#include "src/cpp/ripple/ripple_SHAMap.h"
|
||||
#include "src/cpp/ripple/ripple_SerializedTransaction.h"
|
||||
#include "src/cpp/ripple/ripple_SerializedLedger.h"
|
||||
#include "src/cpp/ripple/TransactionMeta.h"
|
||||
#include "src/cpp/ripple/Transaction.h"
|
||||
#include "src/cpp/ripple/ripple_AccountState.h"
|
||||
#include "src/cpp/ripple/NicknameState.h"
|
||||
#include "src/cpp/ripple/Ledger.h"
|
||||
#include "src/cpp/ripple/LedgerEntrySet.h"
|
||||
#include "src/cpp/ripple/TransactionEngine.h"
|
||||
#include "src/cpp/ripple/LoadManager.h"
|
||||
#include "src/cpp/ripple/ripple_Peer.h"
|
||||
#include "src/cpp/ripple/ripple_PeerSet.h"
|
||||
#include "src/cpp/ripple/ripple_LedgerAcquire.h"
|
||||
#include "src/cpp/ripple/ripple_LedgerHistory.h"
|
||||
#include "src/cpp/ripple/ripple_CanonicalTXSet.h"
|
||||
#include "src/cpp/ripple/LedgerMaster.h"
|
||||
#include "src/cpp/ripple/ripple_InfoSub.h"
|
||||
#include "src/cpp/ripple/SerializedValidation.h"
|
||||
#include "src/cpp/ripple/LedgerProposal.h"
|
||||
#include "src/cpp/ripple/ripple_AcceptedLedgerTx.h"
|
||||
#include "src/cpp/ripple/NetworkOPs.h"
|
||||
#include "src/cpp/ripple/ripple_IApplication.h"
|
||||
#include "src/cpp/ripple/ripple_HashedObject.h"
|
||||
#include "src/cpp/ripple/ripple_SHAMapItem.h"
|
||||
#include "src/cpp/ripple/ripple_SHAMapNode.h"
|
||||
#include "src/cpp/ripple/ripple_SHAMapAddNode.h"
|
||||
#include "src/cpp/ripple/ripple_SHAMapMissingNode.h"
|
||||
#include "src/cpp/ripple/ripple_SHAMapTreeNode.h"
|
||||
#include "src/cpp/ripple/ripple_SHAMapSyncFilter.h"
|
||||
#include "src/cpp/ripple/ripple_SHAMap.h"
|
||||
#include "src/cpp/ripple/ripple_SerializedTransaction.h"
|
||||
#include "src/cpp/ripple/ripple_SerializedLedger.h"
|
||||
#include "src/cpp/ripple/TransactionMeta.h"
|
||||
#include "src/cpp/ripple/Transaction.h"
|
||||
#include "src/cpp/ripple/ripple_AccountState.h"
|
||||
#include "src/cpp/ripple/NicknameState.h"
|
||||
#include "src/cpp/ripple/Ledger.h"
|
||||
#include "src/cpp/ripple/LedgerEntrySet.h"
|
||||
#include "src/cpp/ripple/TransactionEngine.h"
|
||||
#include "src/cpp/ripple/LoadManager.h"
|
||||
#include "src/cpp/ripple/ripple_Peer.h"
|
||||
#include "src/cpp/ripple/ripple_PeerSet.h"
|
||||
#include "src/cpp/ripple/ripple_LedgerAcquire.h"
|
||||
#include "src/cpp/ripple/ripple_LedgerHistory.h"
|
||||
#include "src/cpp/ripple/ripple_CanonicalTXSet.h"
|
||||
#include "src/cpp/ripple/LedgerMaster.h"
|
||||
#include "src/cpp/ripple/ripple_InfoSub.h"
|
||||
#include "src/cpp/ripple/SerializedValidation.h"
|
||||
#include "src/cpp/ripple/LedgerProposal.h"
|
||||
#include "src/cpp/ripple/ripple_AcceptedLedgerTx.h"
|
||||
#include "src/cpp/ripple/NetworkOPs.h"
|
||||
#include "src/cpp/ripple/ripple_IApplication.h"
|
||||
|
||||
#include "src/cpp/ripple/ripple_InfoSub.cpp"
|
||||
//#include "src/cpp/ripple/NetworkOPs.cpp"
|
||||
|
||||
@@ -1,32 +1,32 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
Copyright (c) 2011-2013, OpenCoin, Inc.
|
||||
Copyright (c) 2011-2013, OpenCoin, Inc.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
/** Include this to get the @ref ripple_client module.
|
||||
/** Include this to get the @ref ripple_client module.
|
||||
|
||||
@file ripple_client.h
|
||||
@ingroup ripple_client
|
||||
*/
|
||||
|
||||
/** Client classes.
|
||||
/** Client classes.
|
||||
|
||||
This module provides classes that perform client interaction with the server.
|
||||
This module provides classes that perform client interaction with the server.
|
||||
|
||||
@defgroup ripple_client
|
||||
@defgroup ripple_client
|
||||
*/
|
||||
|
||||
#ifndef RIPPLE_CLIENT_H
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
Copyright (c) 2011-2013, OpenCoin, Inc.
|
||||
Copyright (c) 2011-2013, OpenCoin, Inc.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
@@ -25,161 +25,176 @@ char const* Base58::s_currentAlphabet = Base58::getRippleAlphabet ();
|
||||
|
||||
char const* Base58::getCurrentAlphabet ()
|
||||
{
|
||||
return s_currentAlphabet;
|
||||
return s_currentAlphabet;
|
||||
}
|
||||
|
||||
void Base58::setCurrentAlphabet (char const* alphabet)
|
||||
{
|
||||
s_currentAlphabet = alphabet;
|
||||
s_currentAlphabet = alphabet;
|
||||
}
|
||||
|
||||
char const* Base58::getBitcoinAlphabet ()
|
||||
{
|
||||
return "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
|
||||
return "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
|
||||
}
|
||||
|
||||
char const* Base58::getRippleAlphabet ()
|
||||
{
|
||||
return "rpshnaf39wBUDNEGHJKLM4PQRST7VWXYZ2bcdeCg65jkm8oFqi1tuvAxyz";
|
||||
return "rpshnaf39wBUDNEGHJKLM4PQRST7VWXYZ2bcdeCg65jkm8oFqi1tuvAxyz";
|
||||
}
|
||||
|
||||
char const* Base58::getTestnetAlphabet ()
|
||||
{
|
||||
return "RPShNAF39wBUDnEGHJKLM4pQrsT7VWXYZ2bcdeCg65jkm8ofqi1tuvaxyz";
|
||||
return "RPShNAF39wBUDnEGHJKLM4pQrsT7VWXYZ2bcdeCg65jkm8ofqi1tuvaxyz";
|
||||
}
|
||||
|
||||
std::string Base58::encode (const unsigned char* pbegin, const unsigned char* pend)
|
||||
{
|
||||
char const* alphabet = getCurrentAlphabet ();
|
||||
char const* alphabet = getCurrentAlphabet ();
|
||||
|
||||
CAutoBN_CTX pctx;
|
||||
CBigNum bn58 = 58;
|
||||
CBigNum bn0 = 0;
|
||||
CAutoBN_CTX pctx;
|
||||
CBigNum bn58 = 58;
|
||||
CBigNum bn0 = 0;
|
||||
|
||||
// Convert big endian data to little endian
|
||||
// Extra zero at the end make sure bignum will interpret as a positive number
|
||||
Blob vchTmp(pend-pbegin+1, 0);
|
||||
std::reverse_copy(pbegin, pend, vchTmp.begin());
|
||||
// Convert big endian data to little endian
|
||||
// Extra zero at the end make sure bignum will interpret as a positive number
|
||||
Blob vchTmp (pend - pbegin + 1, 0);
|
||||
std::reverse_copy (pbegin, pend, vchTmp.begin ());
|
||||
|
||||
// Convert little endian data to bignum
|
||||
CBigNum bn(vchTmp);
|
||||
// Convert little endian data to bignum
|
||||
CBigNum bn (vchTmp);
|
||||
|
||||
// Convert bignum to std::string
|
||||
std::string str;
|
||||
// Expected size increase from base58 conversion is approximately 137%
|
||||
// use 138% to be safe
|
||||
str.reserve((pend - pbegin) * 138 / 100 + 1);
|
||||
CBigNum dv;
|
||||
CBigNum rem;
|
||||
while (bn > bn0)
|
||||
{
|
||||
if (!BN_div(&dv, &rem, &bn, &bn58, pctx))
|
||||
throw bignum_error("EncodeBase58 : BN_div failed");
|
||||
bn = dv;
|
||||
unsigned int c = rem.getuint();
|
||||
str += alphabet [c];
|
||||
}
|
||||
// Convert bignum to std::string
|
||||
std::string str;
|
||||
// Expected size increase from base58 conversion is approximately 137%
|
||||
// use 138% to be safe
|
||||
str.reserve ((pend - pbegin) * 138 / 100 + 1);
|
||||
CBigNum dv;
|
||||
CBigNum rem;
|
||||
|
||||
// Leading zeroes encoded as base58 zeros
|
||||
for (const unsigned char* p = pbegin; p < pend && *p == 0; p++)
|
||||
str += alphabet [0];
|
||||
while (bn > bn0)
|
||||
{
|
||||
if (!BN_div (&dv, &rem, &bn, &bn58, pctx))
|
||||
throw bignum_error ("EncodeBase58 : BN_div failed");
|
||||
|
||||
// Convert little endian std::string to big endian
|
||||
reverse(str.begin(), str.end());
|
||||
return str;
|
||||
bn = dv;
|
||||
unsigned int c = rem.getuint ();
|
||||
str += alphabet [c];
|
||||
}
|
||||
|
||||
// Leading zeroes encoded as base58 zeros
|
||||
for (const unsigned char* p = pbegin; p < pend && *p == 0; p++)
|
||||
str += alphabet [0];
|
||||
|
||||
// Convert little endian std::string to big endian
|
||||
reverse (str.begin (), str.end ());
|
||||
return str;
|
||||
}
|
||||
|
||||
std::string Base58::encode (Blob const& vch)
|
||||
{
|
||||
return encode (&vch[0], &vch[0] + vch.size());
|
||||
return encode (&vch[0], &vch[0] + vch.size ());
|
||||
}
|
||||
|
||||
std::string Base58::encodeWithCheck (Blob const& vchIn)
|
||||
{
|
||||
// add 4-byte hash check to the end
|
||||
Blob vch(vchIn);
|
||||
uint256 hash = SHA256Hash(vch.begin(), vch.end());
|
||||
vch.insert(vch.end(), (unsigned char*)&hash, (unsigned char*)&hash + 4);
|
||||
return encode (vch);
|
||||
// add 4-byte hash check to the end
|
||||
Blob vch (vchIn);
|
||||
uint256 hash = SHA256Hash (vch.begin (), vch.end ());
|
||||
vch.insert (vch.end (), (unsigned char*)&hash, (unsigned char*)&hash + 4);
|
||||
return encode (vch);
|
||||
}
|
||||
|
||||
bool Base58::decode (const char* psz, Blob& vchRet, const char* pAlpha)
|
||||
{
|
||||
assert (pAlpha != 0);
|
||||
assert (pAlpha != 0);
|
||||
|
||||
CAutoBN_CTX pctx;
|
||||
vchRet.clear();
|
||||
CBigNum bn58 = 58;
|
||||
CBigNum bn = 0;
|
||||
CBigNum bnChar;
|
||||
while (isspace(*psz))
|
||||
psz++;
|
||||
CAutoBN_CTX pctx;
|
||||
vchRet.clear ();
|
||||
CBigNum bn58 = 58;
|
||||
CBigNum bn = 0;
|
||||
CBigNum bnChar;
|
||||
|
||||
// Convert big endian string to bignum
|
||||
for (const char* p = psz; *p; p++)
|
||||
{
|
||||
const char* p1 = strchr(pAlpha, *p);
|
||||
if (p1 == NULL)
|
||||
{
|
||||
while (isspace(*p))
|
||||
p++;
|
||||
if (*p != '\0')
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
bnChar.setuint(p1 - pAlpha);
|
||||
if (!BN_mul(&bn, &bn, &bn58, pctx))
|
||||
throw bignum_error("DecodeBase58 : BN_mul failed");
|
||||
bn += bnChar;
|
||||
}
|
||||
while (isspace (*psz))
|
||||
psz++;
|
||||
|
||||
// Get bignum as little endian data
|
||||
Blob vchTmp = bn.getvch();
|
||||
// Convert big endian string to bignum
|
||||
for (const char* p = psz; *p; p++)
|
||||
{
|
||||
const char* p1 = strchr (pAlpha, *p);
|
||||
|
||||
// Trim off sign byte if present
|
||||
if (vchTmp.size() >= 2 && vchTmp.end()[-1] == 0 && vchTmp.end()[-2] >= 0x80)
|
||||
vchTmp.erase(vchTmp.end()-1);
|
||||
if (p1 == NULL)
|
||||
{
|
||||
while (isspace (*p))
|
||||
p++;
|
||||
|
||||
// Restore leading zeros
|
||||
int nLeadingZeros = 0;
|
||||
for (const char* p = psz; *p == pAlpha[0]; p++)
|
||||
nLeadingZeros++;
|
||||
vchRet.assign(nLeadingZeros + vchTmp.size(), 0);
|
||||
if (*p != '\0')
|
||||
return false;
|
||||
|
||||
// Convert little endian data to big endian
|
||||
std::reverse_copy(vchTmp.begin(), vchTmp.end(), vchRet.end() - vchTmp.size());
|
||||
return true;
|
||||
break;
|
||||
}
|
||||
|
||||
bnChar.setuint (p1 - pAlpha);
|
||||
|
||||
if (!BN_mul (&bn, &bn, &bn58, pctx))
|
||||
throw bignum_error ("DecodeBase58 : BN_mul failed");
|
||||
|
||||
bn += bnChar;
|
||||
}
|
||||
|
||||
// Get bignum as little endian data
|
||||
Blob vchTmp = bn.getvch ();
|
||||
|
||||
// Trim off sign byte if present
|
||||
if (vchTmp.size () >= 2 && vchTmp.end ()[-1] == 0 && vchTmp.end ()[-2] >= 0x80)
|
||||
vchTmp.erase (vchTmp.end () - 1);
|
||||
|
||||
// Restore leading zeros
|
||||
int nLeadingZeros = 0;
|
||||
|
||||
for (const char* p = psz; *p == pAlpha[0]; p++)
|
||||
nLeadingZeros++;
|
||||
|
||||
vchRet.assign (nLeadingZeros + vchTmp.size (), 0);
|
||||
|
||||
// Convert little endian data to big endian
|
||||
std::reverse_copy (vchTmp.begin (), vchTmp.end (), vchRet.end () - vchTmp.size ());
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Base58::decode (const std::string& str, Blob& vchRet)
|
||||
{
|
||||
return decode (str.c_str(), vchRet);
|
||||
return decode (str.c_str (), vchRet);
|
||||
}
|
||||
|
||||
bool Base58::decodeWithCheck (const char* psz, Blob& vchRet, const char* pAlphabet)
|
||||
{
|
||||
assert (pAlphabet != NULL);
|
||||
assert (pAlphabet != NULL);
|
||||
|
||||
if (!decode (psz, vchRet, pAlphabet))
|
||||
return false;
|
||||
if (vchRet.size() < 4)
|
||||
{
|
||||
vchRet.clear();
|
||||
return false;
|
||||
}
|
||||
uint256 hash = SHA256Hash(vchRet.begin(), vchRet.end()-4);
|
||||
if (memcmp(&hash, &vchRet.end()[-4], 4) != 0)
|
||||
{
|
||||
vchRet.clear();
|
||||
return false;
|
||||
}
|
||||
vchRet.resize(vchRet.size()-4);
|
||||
return true;
|
||||
if (!decode (psz, vchRet, pAlphabet))
|
||||
return false;
|
||||
|
||||
if (vchRet.size () < 4)
|
||||
{
|
||||
vchRet.clear ();
|
||||
return false;
|
||||
}
|
||||
|
||||
uint256 hash = SHA256Hash (vchRet.begin (), vchRet.end () - 4);
|
||||
|
||||
if (memcmp (&hash, &vchRet.end ()[-4], 4) != 0)
|
||||
{
|
||||
vchRet.clear ();
|
||||
return false;
|
||||
}
|
||||
|
||||
vchRet.resize (vchRet.size () - 4);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Base58::decodeWithCheck (const std::string& str, Blob& vchRet, const char* pAlphabet)
|
||||
{
|
||||
return decodeWithCheck (str.c_str(), vchRet, pAlphabet);
|
||||
return decodeWithCheck (str.c_str (), vchRet, pAlphabet);
|
||||
}
|
||||
|
||||
// vim:ts=4
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
Copyright (c) 2011-2013, OpenCoin, Inc.
|
||||
Copyright (c) 2011-2013, OpenCoin, Inc.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
@@ -36,25 +36,25 @@
|
||||
class Base58
|
||||
{
|
||||
public:
|
||||
// VFALCO TODO clean up this poor API
|
||||
static char const* getCurrentAlphabet ();
|
||||
static void setCurrentAlphabet (char const* alphabet);
|
||||
// VFALCO TODO clean up this poor API
|
||||
static char const* getCurrentAlphabet ();
|
||||
static void setCurrentAlphabet (char const* alphabet);
|
||||
|
||||
static char const* getBitcoinAlphabet ();
|
||||
static char const* getRippleAlphabet ();
|
||||
static char const* getTestnetAlphabet ();
|
||||
static char const* getBitcoinAlphabet ();
|
||||
static char const* getRippleAlphabet ();
|
||||
static char const* getTestnetAlphabet ();
|
||||
|
||||
static std::string encode (const unsigned char* pbegin, const unsigned char* pend);
|
||||
static std::string encode (Blob const& vch);
|
||||
static std::string encodeWithCheck (Blob const& vchIn);
|
||||
static std::string encode (const unsigned char* pbegin, const unsigned char* pend);
|
||||
static std::string encode (Blob const& vch);
|
||||
static std::string encodeWithCheck (Blob const& vchIn);
|
||||
|
||||
static bool decode (const char* psz, Blob& vchRet, const char* pAlphabet=getCurrentAlphabet ());
|
||||
static bool decode (const std::string& str, Blob& vchRet);
|
||||
static bool decodeWithCheck (const char* psz, Blob& vchRet, const char* pAlphabet=getCurrentAlphabet ());
|
||||
static bool decodeWithCheck (const std::string& str, Blob& vchRet, const char* pAlphabet);
|
||||
static bool decode (const char* psz, Blob& vchRet, const char* pAlphabet = getCurrentAlphabet ());
|
||||
static bool decode (const std::string& str, Blob& vchRet);
|
||||
static bool decodeWithCheck (const char* psz, Blob& vchRet, const char* pAlphabet = getCurrentAlphabet ());
|
||||
static bool decodeWithCheck (const std::string& str, Blob& vchRet, const char* pAlphabet);
|
||||
|
||||
private:
|
||||
static char const* s_currentAlphabet;
|
||||
static char const* s_currentAlphabet;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
Copyright (c) 2011-2013, OpenCoin, Inc.
|
||||
Copyright (c) 2011-2013, OpenCoin, Inc.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
@@ -29,85 +29,112 @@
|
||||
// - Doubleclicking selects the whole number as one word if it's all alphanumeric.
|
||||
//
|
||||
|
||||
CBase58Data::CBase58Data()
|
||||
: nVersion(1)
|
||||
CBase58Data::CBase58Data ()
|
||||
: nVersion (1)
|
||||
{
|
||||
}
|
||||
|
||||
CBase58Data::~CBase58Data()
|
||||
CBase58Data::~CBase58Data ()
|
||||
{
|
||||
if (!vchData.empty())
|
||||
memset(&vchData[0], 0, vchData.size());
|
||||
if (!vchData.empty ())
|
||||
memset (&vchData[0], 0, vchData.size ());
|
||||
}
|
||||
|
||||
void CBase58Data::SetData(int nVersionIn, Blob const& vchDataIn)
|
||||
void CBase58Data::SetData (int nVersionIn, Blob const& vchDataIn)
|
||||
{
|
||||
nVersion = nVersionIn;
|
||||
vchData = vchDataIn;
|
||||
nVersion = nVersionIn;
|
||||
vchData = vchDataIn;
|
||||
}
|
||||
|
||||
void CBase58Data::SetData(int nVersionIn, const void* pdata, size_t nSize)
|
||||
void CBase58Data::SetData (int nVersionIn, const void* pdata, size_t nSize)
|
||||
{
|
||||
nVersion = nVersionIn;
|
||||
vchData.resize(nSize);
|
||||
vchData.resize (nSize);
|
||||
|
||||
if (nSize)
|
||||
memcpy(&vchData[0], pdata, nSize);
|
||||
memcpy (&vchData[0], pdata, nSize);
|
||||
}
|
||||
|
||||
void CBase58Data::SetData(int nVersionIn, const unsigned char *pbegin, const unsigned char *pend)
|
||||
void CBase58Data::SetData (int nVersionIn, const unsigned char* pbegin, const unsigned char* pend)
|
||||
{
|
||||
SetData(nVersionIn, (void*)pbegin, pend - pbegin);
|
||||
SetData (nVersionIn, (void*)pbegin, pend - pbegin);
|
||||
}
|
||||
|
||||
bool CBase58Data::SetString(const char* psz, unsigned char version, const char* pAlphabet)
|
||||
bool CBase58Data::SetString (const char* psz, unsigned char version, const char* pAlphabet)
|
||||
{
|
||||
Blob vchTemp;
|
||||
Base58::decodeWithCheck (psz, vchTemp, pAlphabet);
|
||||
if (vchTemp.empty() || vchTemp[0] != version)
|
||||
|
||||
if (vchTemp.empty () || vchTemp[0] != version)
|
||||
{
|
||||
vchData.clear();
|
||||
vchData.clear ();
|
||||
nVersion = 1;
|
||||
return false;
|
||||
}
|
||||
|
||||
nVersion = vchTemp[0];
|
||||
vchData.resize(vchTemp.size() - 1);
|
||||
if (!vchData.empty())
|
||||
memcpy(&vchData[0], &vchTemp[1], vchData.size());
|
||||
memset(&vchTemp[0], 0, vchTemp.size());
|
||||
vchData.resize (vchTemp.size () - 1);
|
||||
|
||||
if (!vchData.empty ())
|
||||
memcpy (&vchData[0], &vchTemp[1], vchData.size ());
|
||||
|
||||
memset (&vchTemp[0], 0, vchTemp.size ());
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CBase58Data::SetString(const std::string& str, unsigned char version)
|
||||
bool CBase58Data::SetString (const std::string& str, unsigned char version)
|
||||
{
|
||||
return SetString(str.c_str(), version);
|
||||
return SetString (str.c_str (), version);
|
||||
}
|
||||
|
||||
std::string CBase58Data::ToString() const
|
||||
std::string CBase58Data::ToString () const
|
||||
{
|
||||
Blob vch(1, nVersion);
|
||||
Blob vch (1, nVersion);
|
||||
|
||||
vch.insert(vch.end(), vchData.begin(), vchData.end());
|
||||
vch.insert (vch.end (), vchData.begin (), vchData.end ());
|
||||
|
||||
return Base58::encodeWithCheck (vch);
|
||||
}
|
||||
|
||||
int CBase58Data::CompareTo(const CBase58Data& b58) const
|
||||
int CBase58Data::CompareTo (const CBase58Data& b58) const
|
||||
{
|
||||
if (nVersion < b58.nVersion) return -1;
|
||||
|
||||
if (nVersion > b58.nVersion) return 1;
|
||||
|
||||
if (vchData < b58.vchData) return -1;
|
||||
|
||||
if (vchData > b58.vchData) return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool CBase58Data::operator==(const CBase58Data& b58) const { return CompareTo(b58) == 0; }
|
||||
bool CBase58Data::operator!=(const CBase58Data& b58) const { return CompareTo(b58) != 0; }
|
||||
bool CBase58Data::operator<=(const CBase58Data& b58) const { return CompareTo(b58) <= 0; }
|
||||
bool CBase58Data::operator>=(const CBase58Data& b58) const { return CompareTo(b58) >= 0; }
|
||||
bool CBase58Data::operator< (const CBase58Data& b58) const { return CompareTo(b58) < 0; }
|
||||
bool CBase58Data::operator> (const CBase58Data& b58) const { return CompareTo(b58) > 0; }
|
||||
bool CBase58Data::operator== (const CBase58Data& b58) const
|
||||
{
|
||||
return CompareTo (b58) == 0;
|
||||
}
|
||||
bool CBase58Data::operator!= (const CBase58Data& b58) const
|
||||
{
|
||||
return CompareTo (b58) != 0;
|
||||
}
|
||||
bool CBase58Data::operator<= (const CBase58Data& b58) const
|
||||
{
|
||||
return CompareTo (b58) <= 0;
|
||||
}
|
||||
bool CBase58Data::operator>= (const CBase58Data& b58) const
|
||||
{
|
||||
return CompareTo (b58) >= 0;
|
||||
}
|
||||
bool CBase58Data::operator< (const CBase58Data& b58) const
|
||||
{
|
||||
return CompareTo (b58) < 0;
|
||||
}
|
||||
bool CBase58Data::operator> (const CBase58Data& b58) const
|
||||
{
|
||||
return CompareTo (b58) > 0;
|
||||
}
|
||||
|
||||
std::size_t hash_value(const CBase58Data& b58)
|
||||
std::size_t hash_value (const CBase58Data& b58)
|
||||
{
|
||||
std::size_t seed = HashMaps::getInstance ().getNonce <size_t> ()
|
||||
+ (b58.nVersion * HashMaps::goldenRatio);
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
Copyright (c) 2011-2013, OpenCoin, Inc.
|
||||
Copyright (c) 2011-2013, OpenCoin, Inc.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
@@ -37,28 +37,28 @@ protected:
|
||||
unsigned char nVersion;
|
||||
Blob vchData;
|
||||
|
||||
CBase58Data();
|
||||
~CBase58Data();
|
||||
CBase58Data ();
|
||||
~CBase58Data ();
|
||||
|
||||
void SetData(int nVersionIn, Blob const& vchDataIn);
|
||||
void SetData(int nVersionIn, const void* pdata, size_t nSize);
|
||||
void SetData(int nVersionIn, const unsigned char *pbegin, const unsigned char *pend);
|
||||
void SetData (int nVersionIn, Blob const& vchDataIn);
|
||||
void SetData (int nVersionIn, const void* pdata, size_t nSize);
|
||||
void SetData (int nVersionIn, const unsigned char* pbegin, const unsigned char* pend);
|
||||
|
||||
public:
|
||||
bool SetString(const char* psz, unsigned char version, const char* pAlphabet = Base58::getCurrentAlphabet());
|
||||
bool SetString(const std::string& str, unsigned char version);
|
||||
bool SetString (const char* psz, unsigned char version, const char* pAlphabet = Base58::getCurrentAlphabet ());
|
||||
bool SetString (const std::string& str, unsigned char version);
|
||||
|
||||
std::string ToString() const;
|
||||
int CompareTo(const CBase58Data& b58) const;
|
||||
std::string ToString () const;
|
||||
int CompareTo (const CBase58Data& b58) const;
|
||||
|
||||
bool operator==(const CBase58Data& b58) const;
|
||||
bool operator!=(const CBase58Data& b58) const;
|
||||
bool operator<=(const CBase58Data& b58) const;
|
||||
bool operator>=(const CBase58Data& b58) const;
|
||||
bool operator== (const CBase58Data& b58) const;
|
||||
bool operator!= (const CBase58Data& b58) const;
|
||||
bool operator<= (const CBase58Data& b58) const;
|
||||
bool operator>= (const CBase58Data& b58) const;
|
||||
bool operator< (const CBase58Data& b58) const;
|
||||
bool operator> (const CBase58Data& b58) const;
|
||||
|
||||
friend std::size_t hash_value(const CBase58Data& b58);
|
||||
friend std::size_t hash_value (const CBase58Data& b58);
|
||||
};
|
||||
|
||||
extern std::size_t hash_value (const CBase58Data& b58);
|
||||
|
||||
@@ -3,528 +3,635 @@
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file license.txt or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
CBigNum::CBigNum()
|
||||
CBigNum::CBigNum ()
|
||||
{
|
||||
BN_init(this);
|
||||
BN_init (this);
|
||||
}
|
||||
|
||||
CBigNum::CBigNum(const CBigNum& b)
|
||||
CBigNum::CBigNum (const CBigNum& b)
|
||||
{
|
||||
BN_init(this);
|
||||
if (!BN_copy(this, &b))
|
||||
{
|
||||
BN_clear_free(this);
|
||||
throw bignum_error("CBigNum::CBigNum(const CBigNum&) : BN_copy failed");
|
||||
}
|
||||
BN_init (this);
|
||||
|
||||
if (!BN_copy (this, &b))
|
||||
{
|
||||
BN_clear_free (this);
|
||||
throw bignum_error ("CBigNum::CBigNum(const CBigNum&) : BN_copy failed");
|
||||
}
|
||||
}
|
||||
|
||||
CBigNum& CBigNum::operator=(const CBigNum& b)
|
||||
CBigNum& CBigNum::operator= (const CBigNum& b)
|
||||
{
|
||||
if (!BN_copy(this, &b))
|
||||
throw bignum_error("CBigNum::operator= : BN_copy failed");
|
||||
return (*this);
|
||||
if (!BN_copy (this, &b))
|
||||
throw bignum_error ("CBigNum::operator= : BN_copy failed");
|
||||
|
||||
return (*this);
|
||||
}
|
||||
|
||||
CBigNum::~CBigNum()
|
||||
CBigNum::~CBigNum ()
|
||||
{
|
||||
BN_clear_free(this);
|
||||
BN_clear_free (this);
|
||||
}
|
||||
|
||||
CBigNum::CBigNum(char n) { BN_init(this); if (n >= 0) setulong(n); else setint64(n); }
|
||||
CBigNum::CBigNum(short n) { BN_init(this); if (n >= 0) setulong(n); else setint64(n); }
|
||||
CBigNum::CBigNum(int n) { BN_init(this); if (n >= 0) setulong(n); else setint64(n); }
|
||||
CBigNum::CBigNum(long n) { BN_init(this); if (n >= 0) setulong(n); else setint64(n); }
|
||||
CBigNum::CBigNum(int64 n) { BN_init(this); setint64(n); }
|
||||
CBigNum::CBigNum(unsigned char n) { BN_init(this); setulong(n); }
|
||||
CBigNum::CBigNum(unsigned short n) { BN_init(this); setulong(n); }
|
||||
CBigNum::CBigNum(unsigned int n) { BN_init(this); setulong(n); }
|
||||
CBigNum::CBigNum(uint64 n) { BN_init(this); setuint64(n); }
|
||||
CBigNum::CBigNum(uint256 n) { BN_init(this); setuint256(n); }
|
||||
|
||||
CBigNum::CBigNum(Blob const& vch)
|
||||
CBigNum::CBigNum (char n)
|
||||
{
|
||||
BN_init(this);
|
||||
setvch(vch);
|
||||
BN_init (this);
|
||||
|
||||
if (n >= 0) setulong (n);
|
||||
else setint64 (n);
|
||||
}
|
||||
CBigNum::CBigNum (short n)
|
||||
{
|
||||
BN_init (this);
|
||||
|
||||
if (n >= 0) setulong (n);
|
||||
else setint64 (n);
|
||||
}
|
||||
CBigNum::CBigNum (int n)
|
||||
{
|
||||
BN_init (this);
|
||||
|
||||
if (n >= 0) setulong (n);
|
||||
else setint64 (n);
|
||||
}
|
||||
CBigNum::CBigNum (long n)
|
||||
{
|
||||
BN_init (this);
|
||||
|
||||
if (n >= 0) setulong (n);
|
||||
else setint64 (n);
|
||||
}
|
||||
CBigNum::CBigNum (int64 n)
|
||||
{
|
||||
BN_init (this);
|
||||
setint64 (n);
|
||||
}
|
||||
CBigNum::CBigNum (unsigned char n)
|
||||
{
|
||||
BN_init (this);
|
||||
setulong (n);
|
||||
}
|
||||
CBigNum::CBigNum (unsigned short n)
|
||||
{
|
||||
BN_init (this);
|
||||
setulong (n);
|
||||
}
|
||||
CBigNum::CBigNum (unsigned int n)
|
||||
{
|
||||
BN_init (this);
|
||||
setulong (n);
|
||||
}
|
||||
CBigNum::CBigNum (uint64 n)
|
||||
{
|
||||
BN_init (this);
|
||||
setuint64 (n);
|
||||
}
|
||||
CBigNum::CBigNum (uint256 n)
|
||||
{
|
||||
BN_init (this);
|
||||
setuint256 (n);
|
||||
}
|
||||
|
||||
void CBigNum::setuint(unsigned int n)
|
||||
CBigNum::CBigNum (Blob const& vch)
|
||||
{
|
||||
setulong(static_cast<unsigned long>(n));
|
||||
BN_init (this);
|
||||
setvch (vch);
|
||||
}
|
||||
|
||||
unsigned int CBigNum::getuint() const
|
||||
void CBigNum::setuint (unsigned int n)
|
||||
{
|
||||
return BN_get_word(this);
|
||||
setulong (static_cast<unsigned long> (n));
|
||||
}
|
||||
|
||||
int CBigNum::getint() const
|
||||
unsigned int CBigNum::getuint () const
|
||||
{
|
||||
unsigned long n = BN_get_word(this);
|
||||
if (!BN_is_negative(this))
|
||||
return (n > INT_MAX ? INT_MAX : n);
|
||||
else
|
||||
return (n > INT_MAX ? INT_MIN : -(int)n);
|
||||
return BN_get_word (this);
|
||||
}
|
||||
|
||||
void CBigNum::setint64(int64 n)
|
||||
int CBigNum::getint () const
|
||||
{
|
||||
unsigned char pch[sizeof(n) + 6];
|
||||
unsigned char* p = pch + 4;
|
||||
bool fNegative = false;
|
||||
if (n < (int64)0)
|
||||
{
|
||||
n = -n;
|
||||
fNegative = true;
|
||||
}
|
||||
bool fLeadingZeroes = true;
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
unsigned char c = (n >> 56) & 0xff;
|
||||
n <<= 8;
|
||||
if (fLeadingZeroes)
|
||||
{
|
||||
if (c == 0)
|
||||
continue;
|
||||
if (c & 0x80)
|
||||
*p++ = (fNegative ? 0x80 : 0);
|
||||
else if (fNegative)
|
||||
c |= 0x80;
|
||||
fLeadingZeroes = false;
|
||||
}
|
||||
*p++ = c;
|
||||
}
|
||||
unsigned int nSize = p - (pch + 4);
|
||||
pch[0] = (nSize >> 24) & 0xff;
|
||||
pch[1] = (nSize >> 16) & 0xff;
|
||||
pch[2] = (nSize >> 8) & 0xff;
|
||||
pch[3] = (nSize) & 0xff;
|
||||
BN_mpi2bn(pch, p - pch, this);
|
||||
unsigned long n = BN_get_word (this);
|
||||
|
||||
if (!BN_is_negative (this))
|
||||
return (n > INT_MAX ? INT_MAX : n);
|
||||
else
|
||||
return (n > INT_MAX ? INT_MIN : - (int)n);
|
||||
}
|
||||
|
||||
uint64 CBigNum::getuint64() const
|
||||
void CBigNum::setint64 (int64 n)
|
||||
{
|
||||
unsigned char pch[sizeof (n) + 6];
|
||||
unsigned char* p = pch + 4;
|
||||
bool fNegative = false;
|
||||
|
||||
if (n < (int64)0)
|
||||
{
|
||||
n = -n;
|
||||
fNegative = true;
|
||||
}
|
||||
|
||||
bool fLeadingZeroes = true;
|
||||
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
unsigned char c = (n >> 56) & 0xff;
|
||||
n <<= 8;
|
||||
|
||||
if (fLeadingZeroes)
|
||||
{
|
||||
if (c == 0)
|
||||
continue;
|
||||
|
||||
if (c & 0x80)
|
||||
*p++ = (fNegative ? 0x80 : 0);
|
||||
else if (fNegative)
|
||||
c |= 0x80;
|
||||
|
||||
fLeadingZeroes = false;
|
||||
}
|
||||
|
||||
*p++ = c;
|
||||
}
|
||||
|
||||
unsigned int nSize = p - (pch + 4);
|
||||
pch[0] = (nSize >> 24) & 0xff;
|
||||
pch[1] = (nSize >> 16) & 0xff;
|
||||
pch[2] = (nSize >> 8) & 0xff;
|
||||
pch[3] = (nSize) & 0xff;
|
||||
BN_mpi2bn (pch, p - pch, this);
|
||||
}
|
||||
|
||||
uint64 CBigNum::getuint64 () const
|
||||
{
|
||||
#if (ULONG_MAX > UINT_MAX)
|
||||
return static_cast<uint64>(getulong());
|
||||
return static_cast<uint64> (getulong ());
|
||||
#else
|
||||
int len = BN_num_bytes(this);
|
||||
if (len > 8)
|
||||
throw std::runtime_error("BN getuint64 overflow");
|
||||
int len = BN_num_bytes (this);
|
||||
|
||||
unsigned char buf[8];
|
||||
memset(buf, 0, sizeof(buf));
|
||||
BN_bn2bin(this, buf + 8 - len);
|
||||
return
|
||||
static_cast<uint64>(buf[0]) << 56 | static_cast<uint64>(buf[1]) << 48 |
|
||||
static_cast<uint64>(buf[2]) << 40 | static_cast<uint64>(buf[3]) << 32 |
|
||||
static_cast<uint64>(buf[4]) << 24 | static_cast<uint64>(buf[5]) << 16 |
|
||||
static_cast<uint64>(buf[6]) << 8 | static_cast<uint64>(buf[7]);
|
||||
if (len > 8)
|
||||
throw std::runtime_error ("BN getuint64 overflow");
|
||||
|
||||
unsigned char buf[8];
|
||||
memset (buf, 0, sizeof (buf));
|
||||
BN_bn2bin (this, buf + 8 - len);
|
||||
return
|
||||
static_cast<uint64> (buf[0]) << 56 | static_cast<uint64> (buf[1]) << 48 |
|
||||
static_cast<uint64> (buf[2]) << 40 | static_cast<uint64> (buf[3]) << 32 |
|
||||
static_cast<uint64> (buf[4]) << 24 | static_cast<uint64> (buf[5]) << 16 |
|
||||
static_cast<uint64> (buf[6]) << 8 | static_cast<uint64> (buf[7]);
|
||||
#endif
|
||||
}
|
||||
|
||||
void CBigNum::setuint64(uint64 n)
|
||||
void CBigNum::setuint64 (uint64 n)
|
||||
{
|
||||
#if (ULONG_MAX > UINT_MAX)
|
||||
setulong(static_cast<unsigned long>(n));
|
||||
setulong (static_cast<unsigned long> (n));
|
||||
#else
|
||||
unsigned char buf[8];
|
||||
buf[0] = static_cast<unsigned char>((n >> 56) & 0xff);
|
||||
buf[1] = static_cast<unsigned char>((n >> 48) & 0xff);
|
||||
buf[2] = static_cast<unsigned char>((n >> 40) & 0xff);
|
||||
buf[3] = static_cast<unsigned char>((n >> 32) & 0xff);
|
||||
buf[4] = static_cast<unsigned char>((n >> 24) & 0xff);
|
||||
buf[5] = static_cast<unsigned char>((n >> 16) & 0xff);
|
||||
buf[6] = static_cast<unsigned char>((n >> 8) & 0xff);
|
||||
buf[7] = static_cast<unsigned char>((n) & 0xff);
|
||||
BN_bin2bn(buf, 8, this);
|
||||
unsigned char buf[8];
|
||||
buf[0] = static_cast<unsigned char> ((n >> 56) & 0xff);
|
||||
buf[1] = static_cast<unsigned char> ((n >> 48) & 0xff);
|
||||
buf[2] = static_cast<unsigned char> ((n >> 40) & 0xff);
|
||||
buf[3] = static_cast<unsigned char> ((n >> 32) & 0xff);
|
||||
buf[4] = static_cast<unsigned char> ((n >> 24) & 0xff);
|
||||
buf[5] = static_cast<unsigned char> ((n >> 16) & 0xff);
|
||||
buf[6] = static_cast<unsigned char> ((n >> 8) & 0xff);
|
||||
buf[7] = static_cast<unsigned char> ((n) & 0xff);
|
||||
BN_bin2bn (buf, 8, this);
|
||||
#endif
|
||||
}
|
||||
|
||||
void CBigNum::setuint256(uint256 const& n)
|
||||
void CBigNum::setuint256 (uint256 const& n)
|
||||
{
|
||||
BN_bin2bn(n.begin(), n.size(), NULL);
|
||||
BN_bin2bn (n.begin (), n.size (), NULL);
|
||||
}
|
||||
|
||||
uint256 CBigNum::getuint256()
|
||||
uint256 CBigNum::getuint256 ()
|
||||
{
|
||||
uint256 ret;
|
||||
unsigned int size = BN_num_bytes(this);
|
||||
if (size > ret.size())
|
||||
return ret;
|
||||
BN_bn2bin(this, ret.begin() + (ret.size() - BN_num_bytes(this)));
|
||||
return ret;
|
||||
uint256 ret;
|
||||
unsigned int size = BN_num_bytes (this);
|
||||
|
||||
if (size > ret.size ())
|
||||
return ret;
|
||||
|
||||
BN_bn2bin (this, ret.begin () + (ret.size () - BN_num_bytes (this)));
|
||||
return ret;
|
||||
}
|
||||
|
||||
void CBigNum::setvch(Blob const& vch)
|
||||
void CBigNum::setvch (Blob const& vch)
|
||||
{
|
||||
Blob vch2(vch.size() + 4);
|
||||
unsigned int nSize = vch.size();
|
||||
// BIGNUM's byte stream format expects 4 bytes of
|
||||
// big endian size data info at the front
|
||||
vch2[0] = (nSize >> 24) & 0xff;
|
||||
vch2[1] = (nSize >> 16) & 0xff;
|
||||
vch2[2] = (nSize >> 8) & 0xff;
|
||||
vch2[3] = (nSize >> 0) & 0xff;
|
||||
// swap data to big endian
|
||||
std::reverse_copy(vch.begin(), vch.end(), vch2.begin() + 4);
|
||||
BN_mpi2bn(&vch2[0], vch2.size(), this);
|
||||
Blob vch2 (vch.size () + 4);
|
||||
unsigned int nSize = vch.size ();
|
||||
// BIGNUM's byte stream format expects 4 bytes of
|
||||
// big endian size data info at the front
|
||||
vch2[0] = (nSize >> 24) & 0xff;
|
||||
vch2[1] = (nSize >> 16) & 0xff;
|
||||
vch2[2] = (nSize >> 8) & 0xff;
|
||||
vch2[3] = (nSize >> 0) & 0xff;
|
||||
// swap data to big endian
|
||||
std::reverse_copy (vch.begin (), vch.end (), vch2.begin () + 4);
|
||||
BN_mpi2bn (&vch2[0], vch2.size (), this);
|
||||
}
|
||||
|
||||
Blob CBigNum::getvch() const
|
||||
Blob CBigNum::getvch () const
|
||||
{
|
||||
unsigned int nSize = BN_bn2mpi(this, NULL);
|
||||
if (nSize < 4)
|
||||
return Blob ();
|
||||
Blob vch(nSize);
|
||||
BN_bn2mpi(this, &vch[0]);
|
||||
vch.erase(vch.begin(), vch.begin() + 4);
|
||||
reverse(vch.begin(), vch.end());
|
||||
return vch;
|
||||
unsigned int nSize = BN_bn2mpi (this, NULL);
|
||||
|
||||
if (nSize < 4)
|
||||
return Blob ();
|
||||
|
||||
Blob vch (nSize);
|
||||
BN_bn2mpi (this, &vch[0]);
|
||||
vch.erase (vch.begin (), vch.begin () + 4);
|
||||
reverse (vch.begin (), vch.end ());
|
||||
return vch;
|
||||
}
|
||||
|
||||
CBigNum& CBigNum::SetCompact(unsigned int nCompact)
|
||||
CBigNum& CBigNum::SetCompact (unsigned int nCompact)
|
||||
{
|
||||
unsigned int nSize = nCompact >> 24;
|
||||
Blob vch(4 + nSize);
|
||||
vch[3] = nSize;
|
||||
if (nSize >= 1) vch[4] = (nCompact >> 16) & 0xff;
|
||||
if (nSize >= 2) vch[5] = (nCompact >> 8) & 0xff;
|
||||
if (nSize >= 3) vch[6] = (nCompact >> 0) & 0xff;
|
||||
BN_mpi2bn(&vch[0], vch.size(), this);
|
||||
return *this;
|
||||
unsigned int nSize = nCompact >> 24;
|
||||
Blob vch (4 + nSize);
|
||||
vch[3] = nSize;
|
||||
|
||||
if (nSize >= 1) vch[4] = (nCompact >> 16) & 0xff;
|
||||
|
||||
if (nSize >= 2) vch[5] = (nCompact >> 8) & 0xff;
|
||||
|
||||
if (nSize >= 3) vch[6] = (nCompact >> 0) & 0xff;
|
||||
|
||||
BN_mpi2bn (&vch[0], vch.size (), this);
|
||||
return *this;
|
||||
}
|
||||
|
||||
unsigned int CBigNum::GetCompact() const
|
||||
unsigned int CBigNum::GetCompact () const
|
||||
{
|
||||
unsigned int nSize = BN_bn2mpi(this, NULL);
|
||||
Blob vch(nSize);
|
||||
nSize -= 4;
|
||||
BN_bn2mpi(this, &vch[0]);
|
||||
unsigned int nCompact = nSize << 24;
|
||||
if (nSize >= 1) nCompact |= (vch[4] << 16);
|
||||
if (nSize >= 2) nCompact |= (vch[5] << 8);
|
||||
if (nSize >= 3) nCompact |= (vch[6] << 0);
|
||||
return nCompact;
|
||||
unsigned int nSize = BN_bn2mpi (this, NULL);
|
||||
Blob vch (nSize);
|
||||
nSize -= 4;
|
||||
BN_bn2mpi (this, &vch[0]);
|
||||
unsigned int nCompact = nSize << 24;
|
||||
|
||||
if (nSize >= 1) nCompact |= (vch[4] << 16);
|
||||
|
||||
if (nSize >= 2) nCompact |= (vch[5] << 8);
|
||||
|
||||
if (nSize >= 3) nCompact |= (vch[6] << 0);
|
||||
|
||||
return nCompact;
|
||||
}
|
||||
|
||||
void CBigNum::SetHex(const std::string& str)
|
||||
void CBigNum::SetHex (const std::string& str)
|
||||
{
|
||||
// skip 0x
|
||||
const char* psz = str.c_str();
|
||||
while (isspace(*psz))
|
||||
psz++;
|
||||
bool fNegative = false;
|
||||
if (*psz == '-')
|
||||
{
|
||||
fNegative = true;
|
||||
psz++;
|
||||
}
|
||||
if (psz[0] == '0' && tolower(psz[1]) == 'x')
|
||||
psz += 2;
|
||||
while (isspace(*psz))
|
||||
psz++;
|
||||
// skip 0x
|
||||
const char* psz = str.c_str ();
|
||||
|
||||
// hex string to bignum
|
||||
static char phexdigit[256] = {
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,1,2,3,4,5,6,7,8,9,0,0,0,0,0,0,
|
||||
0,0xa,0xb,0xc,0xd,0xe,0xf,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0xa,0xb,0xc,0xd,0xe,0xf,0,0,0,0,0,0,0,0,0 };
|
||||
*this = 0;
|
||||
while (isxdigit(*psz))
|
||||
{
|
||||
*this <<= 4;
|
||||
int n = phexdigit[(int) *psz++];
|
||||
*this += n;
|
||||
}
|
||||
if (fNegative)
|
||||
*this = 0 - *this;
|
||||
while (isspace (*psz))
|
||||
psz++;
|
||||
|
||||
bool fNegative = false;
|
||||
|
||||
if (*psz == '-')
|
||||
{
|
||||
fNegative = true;
|
||||
psz++;
|
||||
}
|
||||
|
||||
if (psz[0] == '0' && tolower (psz[1]) == 'x')
|
||||
psz += 2;
|
||||
|
||||
while (isspace (*psz))
|
||||
psz++;
|
||||
|
||||
// hex string to bignum
|
||||
static char phexdigit[256] =
|
||||
{
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0, 0,
|
||||
0, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
||||
};
|
||||
*this = 0;
|
||||
|
||||
while (isxdigit (*psz))
|
||||
{
|
||||
*this <<= 4;
|
||||
int n = phexdigit[ (int) * psz++];
|
||||
*this += n;
|
||||
}
|
||||
|
||||
if (fNegative)
|
||||
*this = 0 - *this;
|
||||
}
|
||||
|
||||
std::string CBigNum::ToString(int nBase) const
|
||||
std::string CBigNum::ToString (int nBase) const
|
||||
{
|
||||
CAutoBN_CTX pctx;
|
||||
CBigNum bnBase = nBase;
|
||||
CBigNum bn0 = 0;
|
||||
std::string str;
|
||||
CBigNum bn = *this;
|
||||
BN_set_negative(&bn, false);
|
||||
CBigNum dv;
|
||||
CBigNum rem;
|
||||
if (BN_cmp(&bn, &bn0) == 0)
|
||||
return "0";
|
||||
while (BN_cmp(&bn, &bn0) > 0)
|
||||
{
|
||||
if (!BN_div(&dv, &rem, &bn, &bnBase, pctx))
|
||||
throw bignum_error("CBigNum::ToString() : BN_div failed");
|
||||
bn = dv;
|
||||
unsigned int c = rem.getuint();
|
||||
str += "0123456789abcdef"[c];
|
||||
}
|
||||
if (BN_is_negative(this))
|
||||
str += "-";
|
||||
reverse(str.begin(), str.end());
|
||||
return str;
|
||||
CAutoBN_CTX pctx;
|
||||
CBigNum bnBase = nBase;
|
||||
CBigNum bn0 = 0;
|
||||
std::string str;
|
||||
CBigNum bn = *this;
|
||||
BN_set_negative (&bn, false);
|
||||
CBigNum dv;
|
||||
CBigNum rem;
|
||||
|
||||
if (BN_cmp (&bn, &bn0) == 0)
|
||||
return "0";
|
||||
|
||||
while (BN_cmp (&bn, &bn0) > 0)
|
||||
{
|
||||
if (!BN_div (&dv, &rem, &bn, &bnBase, pctx))
|
||||
throw bignum_error ("CBigNum::ToString() : BN_div failed");
|
||||
|
||||
bn = dv;
|
||||
unsigned int c = rem.getuint ();
|
||||
str += "0123456789abcdef"[c];
|
||||
}
|
||||
|
||||
if (BN_is_negative (this))
|
||||
str += "-";
|
||||
|
||||
reverse (str.begin (), str.end ());
|
||||
return str;
|
||||
}
|
||||
|
||||
std::string CBigNum::GetHex() const
|
||||
std::string CBigNum::GetHex () const
|
||||
{
|
||||
return ToString(16);
|
||||
return ToString (16);
|
||||
}
|
||||
|
||||
bool CBigNum::operator!() const
|
||||
bool CBigNum::operator! () const
|
||||
{
|
||||
return BN_is_zero(this);
|
||||
return BN_is_zero (this);
|
||||
}
|
||||
|
||||
CBigNum& CBigNum::operator+=(const CBigNum& b)
|
||||
CBigNum& CBigNum::operator+= (const CBigNum& b)
|
||||
{
|
||||
if (!BN_add(this, this, &b))
|
||||
throw bignum_error("CBigNum::operator+= : BN_add failed");
|
||||
return *this;
|
||||
if (!BN_add (this, this, &b))
|
||||
throw bignum_error ("CBigNum::operator+= : BN_add failed");
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
CBigNum& CBigNum::operator-=(const CBigNum& b)
|
||||
CBigNum& CBigNum::operator-= (const CBigNum& b)
|
||||
{
|
||||
*this = *this - b;
|
||||
return *this;
|
||||
*this = *this - b;
|
||||
return *this;
|
||||
}
|
||||
|
||||
CBigNum& CBigNum::operator*=(const CBigNum& b)
|
||||
CBigNum& CBigNum::operator*= (const CBigNum& b)
|
||||
{
|
||||
CAutoBN_CTX pctx;
|
||||
if (!BN_mul(this, this, &b, pctx))
|
||||
throw bignum_error("CBigNum::operator*= : BN_mul failed");
|
||||
return *this;
|
||||
CAutoBN_CTX pctx;
|
||||
|
||||
if (!BN_mul (this, this, &b, pctx))
|
||||
throw bignum_error ("CBigNum::operator*= : BN_mul failed");
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
CBigNum& CBigNum::operator/=(const CBigNum& b)
|
||||
CBigNum& CBigNum::operator/= (const CBigNum& b)
|
||||
{
|
||||
*this = *this / b;
|
||||
return *this;
|
||||
*this = *this / b;
|
||||
return *this;
|
||||
}
|
||||
|
||||
CBigNum& CBigNum::operator%=(const CBigNum& b)
|
||||
CBigNum& CBigNum::operator%= (const CBigNum& b)
|
||||
{
|
||||
*this = *this % b;
|
||||
return *this;
|
||||
*this = *this % b;
|
||||
return *this;
|
||||
}
|
||||
|
||||
CBigNum& CBigNum::operator<<=(unsigned int shift)
|
||||
CBigNum& CBigNum::operator<<= (unsigned int shift)
|
||||
{
|
||||
if (!BN_lshift(this, this, shift))
|
||||
throw bignum_error("CBigNum:operator<<= : BN_lshift failed");
|
||||
return *this;
|
||||
if (!BN_lshift (this, this, shift))
|
||||
throw bignum_error ("CBigNum:operator<<= : BN_lshift failed");
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
CBigNum& CBigNum::operator>>=(unsigned int shift)
|
||||
CBigNum& CBigNum::operator>>= (unsigned int shift)
|
||||
{
|
||||
// Note: BN_rshift segfaults on 64-bit if 2^shift is greater than the number
|
||||
// if built on ubuntu 9.04 or 9.10, probably depends on version of openssl
|
||||
CBigNum a = 1;
|
||||
a <<= shift;
|
||||
if (BN_cmp(&a, this) > 0)
|
||||
{
|
||||
*this = 0;
|
||||
return *this;
|
||||
}
|
||||
// Note: BN_rshift segfaults on 64-bit if 2^shift is greater than the number
|
||||
// if built on ubuntu 9.04 or 9.10, probably depends on version of openssl
|
||||
CBigNum a = 1;
|
||||
a <<= shift;
|
||||
|
||||
if (!BN_rshift(this, this, shift))
|
||||
throw bignum_error("CBigNum:operator>>= : BN_rshift failed");
|
||||
return *this;
|
||||
if (BN_cmp (&a, this) > 0)
|
||||
{
|
||||
*this = 0;
|
||||
return *this;
|
||||
}
|
||||
|
||||
if (!BN_rshift (this, this, shift))
|
||||
throw bignum_error ("CBigNum:operator>>= : BN_rshift failed");
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
CBigNum& CBigNum::operator++()
|
||||
CBigNum& CBigNum::operator++ ()
|
||||
{
|
||||
// prefix operator
|
||||
if (!BN_add(this, this, BN_value_one()))
|
||||
throw bignum_error("CBigNum::operator++ : BN_add failed");
|
||||
return *this;
|
||||
// prefix operator
|
||||
if (!BN_add (this, this, BN_value_one ()))
|
||||
throw bignum_error ("CBigNum::operator++ : BN_add failed");
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
const CBigNum CBigNum::operator++(int)
|
||||
const CBigNum CBigNum::operator++ (int)
|
||||
{
|
||||
// postfix operator
|
||||
const CBigNum ret = *this;
|
||||
++(*this);
|
||||
return ret;
|
||||
// postfix operator
|
||||
const CBigNum ret = *this;
|
||||
++ (*this);
|
||||
return ret;
|
||||
}
|
||||
|
||||
CBigNum& CBigNum::operator--()
|
||||
CBigNum& CBigNum::operator-- ()
|
||||
{
|
||||
// prefix operator
|
||||
CBigNum r;
|
||||
if (!BN_sub(&r, this, BN_value_one()))
|
||||
throw bignum_error("CBigNum::operator-- : BN_sub failed");
|
||||
*this = r;
|
||||
return *this;
|
||||
// prefix operator
|
||||
CBigNum r;
|
||||
|
||||
if (!BN_sub (&r, this, BN_value_one ()))
|
||||
throw bignum_error ("CBigNum::operator-- : BN_sub failed");
|
||||
|
||||
*this = r;
|
||||
return *this;
|
||||
}
|
||||
|
||||
const CBigNum CBigNum::operator--(int)
|
||||
const CBigNum CBigNum::operator-- (int)
|
||||
{
|
||||
// postfix operator
|
||||
const CBigNum ret = *this;
|
||||
--(*this);
|
||||
return ret;
|
||||
// postfix operator
|
||||
const CBigNum ret = *this;
|
||||
-- (*this);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void CBigNum::setulong(unsigned long n)
|
||||
void CBigNum::setulong (unsigned long n)
|
||||
{
|
||||
if (!BN_set_word(this, n))
|
||||
throw bignum_error("CBigNum conversion from unsigned long : BN_set_word failed");
|
||||
if (!BN_set_word (this, n))
|
||||
throw bignum_error ("CBigNum conversion from unsigned long : BN_set_word failed");
|
||||
}
|
||||
|
||||
unsigned long CBigNum::getulong() const
|
||||
unsigned long CBigNum::getulong () const
|
||||
{
|
||||
return BN_get_word(this);
|
||||
return BN_get_word (this);
|
||||
}
|
||||
|
||||
const CBigNum operator+(const CBigNum& a, const CBigNum& b)
|
||||
const CBigNum operator+ (const CBigNum& a, const CBigNum& b)
|
||||
{
|
||||
CBigNum r;
|
||||
if (!BN_add(&r, &a, &b))
|
||||
throw bignum_error("CBigNum::operator+ : BN_add failed");
|
||||
return r;
|
||||
CBigNum r;
|
||||
|
||||
if (!BN_add (&r, &a, &b))
|
||||
throw bignum_error ("CBigNum::operator+ : BN_add failed");
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
const CBigNum operator-(const CBigNum& a, const CBigNum& b)
|
||||
const CBigNum operator- (const CBigNum& a, const CBigNum& b)
|
||||
{
|
||||
CBigNum r;
|
||||
if (!BN_sub(&r, &a, &b))
|
||||
throw bignum_error("CBigNum::operator- : BN_sub failed");
|
||||
return r;
|
||||
CBigNum r;
|
||||
|
||||
if (!BN_sub (&r, &a, &b))
|
||||
throw bignum_error ("CBigNum::operator- : BN_sub failed");
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
const CBigNum operator-(const CBigNum& a)
|
||||
const CBigNum operator- (const CBigNum& a)
|
||||
{
|
||||
CBigNum r(a);
|
||||
BN_set_negative(&r, !BN_is_negative(&r));
|
||||
return r;
|
||||
CBigNum r (a);
|
||||
BN_set_negative (&r, !BN_is_negative (&r));
|
||||
return r;
|
||||
}
|
||||
|
||||
const CBigNum operator*(const CBigNum& a, const CBigNum& b)
|
||||
const CBigNum operator* (const CBigNum& a, const CBigNum& b)
|
||||
{
|
||||
CAutoBN_CTX pctx;
|
||||
CBigNum r;
|
||||
if (!BN_mul(&r, &a, &b, pctx))
|
||||
throw bignum_error("CBigNum::operator* : BN_mul failed");
|
||||
return r;
|
||||
CAutoBN_CTX pctx;
|
||||
CBigNum r;
|
||||
|
||||
if (!BN_mul (&r, &a, &b, pctx))
|
||||
throw bignum_error ("CBigNum::operator* : BN_mul failed");
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
const CBigNum operator/(const CBigNum& a, const CBigNum& b)
|
||||
const CBigNum operator/ (const CBigNum& a, const CBigNum& b)
|
||||
{
|
||||
CAutoBN_CTX pctx;
|
||||
CBigNum r;
|
||||
if (!BN_div(&r, NULL, &a, &b, pctx))
|
||||
throw bignum_error("CBigNum::operator/ : BN_div failed");
|
||||
return r;
|
||||
CAutoBN_CTX pctx;
|
||||
CBigNum r;
|
||||
|
||||
if (!BN_div (&r, NULL, &a, &b, pctx))
|
||||
throw bignum_error ("CBigNum::operator/ : BN_div failed");
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
const CBigNum operator%(const CBigNum& a, const CBigNum& b)
|
||||
const CBigNum operator% (const CBigNum& a, const CBigNum& b)
|
||||
{
|
||||
CAutoBN_CTX pctx;
|
||||
CBigNum r;
|
||||
if (!BN_mod(&r, &a, &b, pctx))
|
||||
throw bignum_error("CBigNum::operator% : BN_div failed");
|
||||
return r;
|
||||
CAutoBN_CTX pctx;
|
||||
CBigNum r;
|
||||
|
||||
if (!BN_mod (&r, &a, &b, pctx))
|
||||
throw bignum_error ("CBigNum::operator% : BN_div failed");
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
const CBigNum operator<<(const CBigNum& a, unsigned int shift)
|
||||
const CBigNum operator<< (const CBigNum& a, unsigned int shift)
|
||||
{
|
||||
CBigNum r;
|
||||
if (!BN_lshift(&r, &a, shift))
|
||||
throw bignum_error("CBigNum:operator<< : BN_lshift failed");
|
||||
return r;
|
||||
CBigNum r;
|
||||
|
||||
if (!BN_lshift (&r, &a, shift))
|
||||
throw bignum_error ("CBigNum:operator<< : BN_lshift failed");
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
const CBigNum operator>>(const CBigNum& a, unsigned int shift)
|
||||
const CBigNum operator>> (const CBigNum& a, unsigned int shift)
|
||||
{
|
||||
CBigNum r = a;
|
||||
r >>= shift;
|
||||
return r;
|
||||
CBigNum r = a;
|
||||
r >>= shift;
|
||||
return r;
|
||||
}
|
||||
|
||||
bool operator== (const CBigNum& a, const CBigNum& b)
|
||||
{
|
||||
return (BN_cmp(&a, &b) == 0);
|
||||
return (BN_cmp (&a, &b) == 0);
|
||||
}
|
||||
|
||||
bool operator!= (const CBigNum& a, const CBigNum& b)
|
||||
{
|
||||
return (BN_cmp(&a, &b) != 0);
|
||||
return (BN_cmp (&a, &b) != 0);
|
||||
}
|
||||
|
||||
bool operator<= (const CBigNum& a, const CBigNum& b)
|
||||
{
|
||||
return (BN_cmp(&a, &b) <= 0);
|
||||
return (BN_cmp (&a, &b) <= 0);
|
||||
}
|
||||
|
||||
bool operator>= (const CBigNum& a, const CBigNum& b)
|
||||
{
|
||||
return (BN_cmp(&a, &b) >= 0);
|
||||
return (BN_cmp (&a, &b) >= 0);
|
||||
}
|
||||
|
||||
bool operator< (const CBigNum& a, const CBigNum& b)
|
||||
{
|
||||
return (BN_cmp(&a, &b) < 0);
|
||||
return (BN_cmp (&a, &b) < 0);
|
||||
}
|
||||
|
||||
bool operator> (const CBigNum& a, const CBigNum& b)
|
||||
{
|
||||
return (BN_cmp(&a, &b) > 0);
|
||||
return (BN_cmp (&a, &b) > 0);
|
||||
}
|
||||
|
||||
#if (ULONG_MAX > UINT_MAX)
|
||||
|
||||
int BN_add_word64 (BIGNUM* bn, uint64 word)
|
||||
{
|
||||
return BN_add_word(bn, word);
|
||||
return BN_add_word (bn, word);
|
||||
}
|
||||
|
||||
int BN_sub_word64 (BIGNUM* bn, uint64 word)
|
||||
{
|
||||
return BN_sub_word(bn, word);
|
||||
return BN_sub_word (bn, word);
|
||||
}
|
||||
|
||||
int BN_mul_word64 (BIGNUM* bn, uint64 word)
|
||||
{
|
||||
return BN_mul_word(bn, word);
|
||||
return BN_mul_word (bn, word);
|
||||
}
|
||||
|
||||
uint64 BN_div_word64 (BIGNUM* bn, uint64 word)
|
||||
{
|
||||
return BN_div_word(bn, word);
|
||||
return BN_div_word (bn, word);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
int BN_add_word64 (BIGNUM *a, uint64 w)
|
||||
int BN_add_word64 (BIGNUM* a, uint64 w)
|
||||
{
|
||||
CBigNum bn(w);
|
||||
return BN_add(a, &bn, a);
|
||||
CBigNum bn (w);
|
||||
return BN_add (a, &bn, a);
|
||||
}
|
||||
|
||||
int BN_sub_word64 (BIGNUM *a, uint64 w)
|
||||
int BN_sub_word64 (BIGNUM* a, uint64 w)
|
||||
{
|
||||
CBigNum bn(w);
|
||||
return BN_sub(a, &bn, a);
|
||||
CBigNum bn (w);
|
||||
return BN_sub (a, &bn, a);
|
||||
}
|
||||
|
||||
int BN_mul_word64 (BIGNUM *a, uint64 w)
|
||||
int BN_mul_word64 (BIGNUM* a, uint64 w)
|
||||
{
|
||||
CBigNum bn(w);
|
||||
CAutoBN_CTX ctx;
|
||||
return BN_mul(a, &bn, a, ctx);
|
||||
CBigNum bn (w);
|
||||
CAutoBN_CTX ctx;
|
||||
return BN_mul (a, &bn, a, ctx);
|
||||
}
|
||||
|
||||
uint64 BN_div_word64 (BIGNUM *a, uint64 w)
|
||||
uint64 BN_div_word64 (BIGNUM* a, uint64 w)
|
||||
{
|
||||
CBigNum bn(w);
|
||||
CAutoBN_CTX ctx;
|
||||
return (BN_div(a, NULL, a, &bn, ctx) == 1) ? 0 : ((uint64)-1);
|
||||
CBigNum bn (w);
|
||||
CAutoBN_CTX ctx;
|
||||
return (BN_div (a, NULL, a, &bn, ctx) == 1) ? 0 : ((uint64) - 1);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
class bignum_error : public std::runtime_error
|
||||
{
|
||||
public:
|
||||
explicit bignum_error(const std::string& str) : std::runtime_error(str) {}
|
||||
explicit bignum_error (const std::string& str) : std::runtime_error (str) {}
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
@@ -22,111 +22,128 @@ public:
|
||||
class CAutoBN_CTX
|
||||
{
|
||||
private:
|
||||
CAutoBN_CTX(const CAutoBN_CTX&); // no implementation
|
||||
CAutoBN_CTX& operator=(const CAutoBN_CTX&); // no implementation
|
||||
CAutoBN_CTX (const CAutoBN_CTX&); // no implementation
|
||||
CAutoBN_CTX& operator= (const CAutoBN_CTX&); // no implementation
|
||||
|
||||
protected:
|
||||
BN_CTX* pctx;
|
||||
CAutoBN_CTX& operator=(BN_CTX* pnew) { pctx = pnew; return *this; }
|
||||
BN_CTX* pctx;
|
||||
CAutoBN_CTX& operator= (BN_CTX* pnew)
|
||||
{
|
||||
pctx = pnew;
|
||||
return *this;
|
||||
}
|
||||
|
||||
public:
|
||||
CAutoBN_CTX()
|
||||
{
|
||||
pctx = BN_CTX_new();
|
||||
if (pctx == NULL)
|
||||
throw bignum_error("CAutoBN_CTX : BN_CTX_new() returned NULL");
|
||||
}
|
||||
CAutoBN_CTX ()
|
||||
{
|
||||
pctx = BN_CTX_new ();
|
||||
|
||||
~CAutoBN_CTX()
|
||||
{
|
||||
if (pctx != NULL)
|
||||
BN_CTX_free(pctx);
|
||||
}
|
||||
if (pctx == NULL)
|
||||
throw bignum_error ("CAutoBN_CTX : BN_CTX_new() returned NULL");
|
||||
}
|
||||
|
||||
operator BN_CTX*() { return pctx; }
|
||||
BN_CTX& operator*() { return *pctx; }
|
||||
BN_CTX** operator&() { return &pctx; }
|
||||
bool operator!() { return (pctx == NULL); }
|
||||
~CAutoBN_CTX ()
|
||||
{
|
||||
if (pctx != NULL)
|
||||
BN_CTX_free (pctx);
|
||||
}
|
||||
|
||||
operator BN_CTX* ()
|
||||
{
|
||||
return pctx;
|
||||
}
|
||||
BN_CTX& operator* ()
|
||||
{
|
||||
return *pctx;
|
||||
}
|
||||
BN_CTX** operator& ()
|
||||
{
|
||||
return &pctx;
|
||||
}
|
||||
bool operator! ()
|
||||
{
|
||||
return (pctx == NULL);
|
||||
}
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
// VFALCO TODO figure out a way to remove the dependency on openssl in the
|
||||
// header. Maybe rewrite this to use cryptopp.
|
||||
// header. Maybe rewrite this to use cryptopp.
|
||||
|
||||
class CBigNum : public BIGNUM
|
||||
{
|
||||
public:
|
||||
CBigNum();
|
||||
CBigNum(const CBigNum& b);
|
||||
CBigNum& operator=(const CBigNum& b);
|
||||
CBigNum(char n);
|
||||
CBigNum(short n);
|
||||
CBigNum(int n);
|
||||
CBigNum(long n);
|
||||
CBigNum(int64 n);
|
||||
CBigNum(unsigned char n);
|
||||
CBigNum(unsigned short n);
|
||||
CBigNum(unsigned int n);
|
||||
CBigNum(uint64 n);
|
||||
explicit CBigNum(uint256 n);
|
||||
explicit CBigNum(Blob const& vch);
|
||||
~CBigNum();
|
||||
CBigNum ();
|
||||
CBigNum (const CBigNum& b);
|
||||
CBigNum& operator= (const CBigNum& b);
|
||||
CBigNum (char n);
|
||||
CBigNum (short n);
|
||||
CBigNum (int n);
|
||||
CBigNum (long n);
|
||||
CBigNum (int64 n);
|
||||
CBigNum (unsigned char n);
|
||||
CBigNum (unsigned short n);
|
||||
CBigNum (unsigned int n);
|
||||
CBigNum (uint64 n);
|
||||
explicit CBigNum (uint256 n);
|
||||
explicit CBigNum (Blob const& vch);
|
||||
~CBigNum ();
|
||||
|
||||
void setuint(unsigned int n);
|
||||
unsigned int getuint() const;
|
||||
int getint() const;
|
||||
void setint64(int64 n);
|
||||
uint64 getuint64() const;
|
||||
void setuint64(uint64 n);
|
||||
void setuint256(uint256 const& n);
|
||||
uint256 getuint256();
|
||||
void setvch(Blob const& vch);
|
||||
Blob getvch() const;
|
||||
CBigNum& SetCompact(unsigned int nCompact);
|
||||
unsigned int GetCompact() const;
|
||||
void SetHex(const std::string& str);
|
||||
std::string ToString(int nBase=10) const;
|
||||
std::string GetHex() const;
|
||||
bool operator!() const;
|
||||
CBigNum& operator+=(const CBigNum& b);
|
||||
CBigNum& operator-=(const CBigNum& b);
|
||||
CBigNum& operator*=(const CBigNum& b);
|
||||
CBigNum& operator/=(const CBigNum& b);
|
||||
CBigNum& operator%=(const CBigNum& b);
|
||||
CBigNum& operator<<=(unsigned int shift);
|
||||
CBigNum& operator>>=(unsigned int shift);
|
||||
CBigNum& operator++();
|
||||
CBigNum& operator--();
|
||||
const CBigNum operator++(int);
|
||||
const CBigNum operator--(int);
|
||||
void setuint (unsigned int n);
|
||||
unsigned int getuint () const;
|
||||
int getint () const;
|
||||
void setint64 (int64 n);
|
||||
uint64 getuint64 () const;
|
||||
void setuint64 (uint64 n);
|
||||
void setuint256 (uint256 const& n);
|
||||
uint256 getuint256 ();
|
||||
void setvch (Blob const& vch);
|
||||
Blob getvch () const;
|
||||
CBigNum& SetCompact (unsigned int nCompact);
|
||||
unsigned int GetCompact () const;
|
||||
void SetHex (const std::string& str);
|
||||
std::string ToString (int nBase = 10) const;
|
||||
std::string GetHex () const;
|
||||
bool operator! () const;
|
||||
CBigNum& operator+= (const CBigNum& b);
|
||||
CBigNum& operator-= (const CBigNum& b);
|
||||
CBigNum& operator*= (const CBigNum& b);
|
||||
CBigNum& operator/= (const CBigNum& b);
|
||||
CBigNum& operator%= (const CBigNum& b);
|
||||
CBigNum& operator<<= (unsigned int shift);
|
||||
CBigNum& operator>>= (unsigned int shift);
|
||||
CBigNum& operator++ ();
|
||||
CBigNum& operator-- ();
|
||||
const CBigNum operator++ (int);
|
||||
const CBigNum operator-- (int);
|
||||
|
||||
friend inline const CBigNum operator-(const CBigNum& a, const CBigNum& b);
|
||||
friend inline const CBigNum operator/(const CBigNum& a, const CBigNum& b);
|
||||
friend inline const CBigNum operator%(const CBigNum& a, const CBigNum& b);
|
||||
friend inline const CBigNum operator- (const CBigNum& a, const CBigNum& b);
|
||||
friend inline const CBigNum operator/ (const CBigNum& a, const CBigNum& b);
|
||||
friend inline const CBigNum operator% (const CBigNum& a, const CBigNum& b);
|
||||
|
||||
private:
|
||||
// private because the size of an unsigned long varies by platform
|
||||
// private because the size of an unsigned long varies by platform
|
||||
|
||||
void setulong(unsigned long n);
|
||||
unsigned long getulong() const;
|
||||
void setulong (unsigned long n);
|
||||
unsigned long getulong () const;
|
||||
};
|
||||
|
||||
const CBigNum operator+(const CBigNum& a, const CBigNum& b);
|
||||
const CBigNum operator-(const CBigNum& a, const CBigNum& b);
|
||||
const CBigNum operator-(const CBigNum& a);
|
||||
const CBigNum operator*(const CBigNum& a, const CBigNum& b);
|
||||
const CBigNum operator/(const CBigNum& a, const CBigNum& b);
|
||||
const CBigNum operator%(const CBigNum& a, const CBigNum& b);
|
||||
const CBigNum operator<<(const CBigNum& a, unsigned int shift);
|
||||
const CBigNum operator>>(const CBigNum& a, unsigned int shift);
|
||||
const CBigNum operator+ (const CBigNum& a, const CBigNum& b);
|
||||
const CBigNum operator- (const CBigNum& a, const CBigNum& b);
|
||||
const CBigNum operator- (const CBigNum& a);
|
||||
const CBigNum operator* (const CBigNum& a, const CBigNum& b);
|
||||
const CBigNum operator/ (const CBigNum& a, const CBigNum& b);
|
||||
const CBigNum operator% (const CBigNum& a, const CBigNum& b);
|
||||
const CBigNum operator<< (const CBigNum& a, unsigned int shift);
|
||||
const CBigNum operator>> (const CBigNum& a, unsigned int shift);
|
||||
|
||||
bool operator==(const CBigNum& a, const CBigNum& b);
|
||||
bool operator!=(const CBigNum& a, const CBigNum& b);
|
||||
bool operator<=(const CBigNum& a, const CBigNum& b);
|
||||
bool operator>=(const CBigNum& a, const CBigNum& b);
|
||||
bool operator<(const CBigNum& a, const CBigNum& b);
|
||||
bool operator>(const CBigNum& a, const CBigNum& b);
|
||||
bool operator== (const CBigNum& a, const CBigNum& b);
|
||||
bool operator!= (const CBigNum& a, const CBigNum& b);
|
||||
bool operator<= (const CBigNum& a, const CBigNum& b);
|
||||
bool operator>= (const CBigNum& a, const CBigNum& b);
|
||||
bool operator< (const CBigNum& a, const CBigNum& b);
|
||||
bool operator> (const CBigNum& a, const CBigNum& b);
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
@@ -141,10 +158,10 @@ bool operator>(const CBigNum& a, const CBigNum& b);
|
||||
//#endif
|
||||
|
||||
// VFALCO I believe only STAmount uses these
|
||||
extern int BN_add_word64 (BIGNUM *a, uint64 w);
|
||||
extern int BN_sub_word64 (BIGNUM *a, uint64 w);
|
||||
extern int BN_mul_word64 (BIGNUM *a, uint64 w);
|
||||
extern uint64 BN_div_word64 (BIGNUM *a, uint64 w);
|
||||
extern int BN_add_word64 (BIGNUM* a, uint64 w);
|
||||
extern int BN_sub_word64 (BIGNUM* a, uint64 w);
|
||||
extern int BN_mul_word64 (BIGNUM* a, uint64 w);
|
||||
extern uint64 BN_div_word64 (BIGNUM* a, uint64 w);
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
Copyright (c) 2011-2013, OpenCoin, Inc.
|
||||
Copyright (c) 2011-2013, OpenCoin, Inc.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
@@ -36,261 +36,280 @@
|
||||
/*
|
||||
int static inline EC_KEY_regenerate_key(EC_KEY *eckey, BIGNUM *priv_key)
|
||||
{
|
||||
int okay = 0;
|
||||
BN_CTX *ctx = NULL;
|
||||
EC_POINT *pub_key = NULL;
|
||||
int okay = 0;
|
||||
BN_CTX *ctx = NULL;
|
||||
EC_POINT *pub_key = NULL;
|
||||
|
||||
if (!eckey) return 0;
|
||||
if (!eckey) return 0;
|
||||
|
||||
const EC_GROUP *group = EC_KEY_get0_group(eckey);
|
||||
const EC_GROUP *group = EC_KEY_get0_group(eckey);
|
||||
|
||||
if ((ctx = BN_CTX_new()) == NULL)
|
||||
goto err;
|
||||
if ((ctx = BN_CTX_new()) == NULL)
|
||||
goto err;
|
||||
|
||||
pub_key = EC_POINT_new(group);
|
||||
pub_key = EC_POINT_new(group);
|
||||
|
||||
if (pub_key == NULL)
|
||||
goto err;
|
||||
if (pub_key == NULL)
|
||||
goto err;
|
||||
|
||||
if (!EC_POINT_mul(group, pub_key, priv_key, NULL, NULL, ctx))
|
||||
goto err;
|
||||
if (!EC_POINT_mul(group, pub_key, priv_key, NULL, NULL, ctx))
|
||||
goto err;
|
||||
|
||||
EC_KEY_set_conv_form(eckey, POINT_CONVERSION_COMPRESSED);
|
||||
EC_KEY_set_private_key(eckey, priv_key);
|
||||
EC_KEY_set_public_key(eckey, pub_key);
|
||||
EC_KEY_set_conv_form(eckey, POINT_CONVERSION_COMPRESSED);
|
||||
EC_KEY_set_private_key(eckey, priv_key);
|
||||
EC_KEY_set_public_key(eckey, pub_key);
|
||||
|
||||
okay = 1;
|
||||
okay = 1;
|
||||
|
||||
err:
|
||||
|
||||
if (pub_key)
|
||||
EC_POINT_free(pub_key);
|
||||
if (ctx != NULL)
|
||||
BN_CTX_free(ctx);
|
||||
if (pub_key)
|
||||
EC_POINT_free(pub_key);
|
||||
if (ctx != NULL)
|
||||
BN_CTX_free(ctx);
|
||||
|
||||
return (okay);
|
||||
return (okay);
|
||||
}
|
||||
*/
|
||||
|
||||
class key_error : public std::runtime_error
|
||||
{
|
||||
public:
|
||||
explicit key_error(const std::string& str) : std::runtime_error(str) {}
|
||||
explicit key_error (const std::string& str) : std::runtime_error (str) {}
|
||||
};
|
||||
|
||||
class CKey
|
||||
{
|
||||
protected:
|
||||
EC_KEY* pkey;
|
||||
bool fSet;
|
||||
EC_KEY* pkey;
|
||||
bool fSet;
|
||||
|
||||
|
||||
public:
|
||||
typedef boost::shared_ptr<CKey> pointer;
|
||||
typedef boost::shared_ptr<CKey> pointer;
|
||||
|
||||
CKey()
|
||||
{
|
||||
pkey = EC_KEY_new_by_curve_name(NID_secp256k1);
|
||||
EC_KEY_set_conv_form(pkey, POINT_CONVERSION_COMPRESSED);
|
||||
if (pkey == NULL)
|
||||
throw key_error("CKey::CKey() : EC_KEY_new_by_curve_name failed");
|
||||
fSet = false;
|
||||
}
|
||||
CKey ()
|
||||
{
|
||||
pkey = EC_KEY_new_by_curve_name (NID_secp256k1);
|
||||
EC_KEY_set_conv_form (pkey, POINT_CONVERSION_COMPRESSED);
|
||||
|
||||
CKey(const CKey& b)
|
||||
{
|
||||
pkey = EC_KEY_dup(b.pkey);
|
||||
EC_KEY_set_conv_form(pkey, POINT_CONVERSION_COMPRESSED);
|
||||
if (pkey == NULL)
|
||||
throw key_error("CKey::CKey(const CKey&) : EC_KEY_dup failed");
|
||||
fSet = b.fSet;
|
||||
}
|
||||
if (pkey == NULL)
|
||||
throw key_error ("CKey::CKey() : EC_KEY_new_by_curve_name failed");
|
||||
|
||||
CKey& operator=(const CKey& b)
|
||||
{
|
||||
if (!EC_KEY_copy(pkey, b.pkey))
|
||||
throw key_error("CKey::operator=(const CKey&) : EC_KEY_copy failed");
|
||||
fSet = b.fSet;
|
||||
return (*this);
|
||||
}
|
||||
fSet = false;
|
||||
}
|
||||
|
||||
CKey (const CKey& b)
|
||||
{
|
||||
pkey = EC_KEY_dup (b.pkey);
|
||||
EC_KEY_set_conv_form (pkey, POINT_CONVERSION_COMPRESSED);
|
||||
|
||||
if (pkey == NULL)
|
||||
throw key_error ("CKey::CKey(const CKey&) : EC_KEY_dup failed");
|
||||
|
||||
fSet = b.fSet;
|
||||
}
|
||||
|
||||
CKey& operator= (const CKey& b)
|
||||
{
|
||||
if (!EC_KEY_copy (pkey, b.pkey))
|
||||
throw key_error ("CKey::operator=(const CKey&) : EC_KEY_copy failed");
|
||||
|
||||
fSet = b.fSet;
|
||||
return (*this);
|
||||
}
|
||||
|
||||
|
||||
~CKey()
|
||||
{
|
||||
EC_KEY_free(pkey);
|
||||
}
|
||||
~CKey ()
|
||||
{
|
||||
EC_KEY_free (pkey);
|
||||
}
|
||||
|
||||
|
||||
static uint128 PassPhraseToKey(const std::string& passPhrase);
|
||||
static EC_KEY* GenerateRootDeterministicKey(const uint128& passPhrase);
|
||||
static EC_KEY* GenerateRootPubKey(BIGNUM* pubGenerator);
|
||||
static EC_KEY* GeneratePublicDeterministicKey(const RippleAddress& generator, int n);
|
||||
static EC_KEY* GeneratePrivateDeterministicKey(const RippleAddress& family, const BIGNUM* rootPriv, int n);
|
||||
static EC_KEY* GeneratePrivateDeterministicKey(const RippleAddress& family, uint256 const& rootPriv, int n);
|
||||
static uint128 PassPhraseToKey (const std::string& passPhrase);
|
||||
static EC_KEY* GenerateRootDeterministicKey (const uint128& passPhrase);
|
||||
static EC_KEY* GenerateRootPubKey (BIGNUM* pubGenerator);
|
||||
static EC_KEY* GeneratePublicDeterministicKey (const RippleAddress& generator, int n);
|
||||
static EC_KEY* GeneratePrivateDeterministicKey (const RippleAddress& family, const BIGNUM* rootPriv, int n);
|
||||
static EC_KEY* GeneratePrivateDeterministicKey (const RippleAddress& family, uint256 const& rootPriv, int n);
|
||||
|
||||
CKey(const uint128& passPhrase) : fSet(false)
|
||||
{
|
||||
pkey = GenerateRootDeterministicKey(passPhrase);
|
||||
fSet = true;
|
||||
assert(pkey);
|
||||
}
|
||||
CKey (const uint128& passPhrase) : fSet (false)
|
||||
{
|
||||
pkey = GenerateRootDeterministicKey (passPhrase);
|
||||
fSet = true;
|
||||
assert (pkey);
|
||||
}
|
||||
|
||||
CKey(const RippleAddress& generator, int n) : fSet(false)
|
||||
{ // public deterministic key
|
||||
pkey = GeneratePublicDeterministicKey(generator, n);
|
||||
fSet = true;
|
||||
assert(pkey);
|
||||
}
|
||||
CKey (const RippleAddress& generator, int n) : fSet (false)
|
||||
{
|
||||
// public deterministic key
|
||||
pkey = GeneratePublicDeterministicKey (generator, n);
|
||||
fSet = true;
|
||||
assert (pkey);
|
||||
}
|
||||
|
||||
CKey(const RippleAddress& base, const BIGNUM* rootPrivKey, int n) : fSet(false)
|
||||
{ // private deterministic key
|
||||
pkey = GeneratePrivateDeterministicKey(base, rootPrivKey, n);
|
||||
fSet = true;
|
||||
assert(pkey);
|
||||
}
|
||||
CKey (const RippleAddress& base, const BIGNUM* rootPrivKey, int n) : fSet (false)
|
||||
{
|
||||
// private deterministic key
|
||||
pkey = GeneratePrivateDeterministicKey (base, rootPrivKey, n);
|
||||
fSet = true;
|
||||
assert (pkey);
|
||||
}
|
||||
|
||||
CKey(uint256 const& privateKey) : pkey(NULL), fSet(false)
|
||||
{
|
||||
// XXX Broken pkey is null.
|
||||
SetPrivateKeyU(privateKey);
|
||||
}
|
||||
CKey (uint256 const& privateKey) : pkey (NULL), fSet (false)
|
||||
{
|
||||
// XXX Broken pkey is null.
|
||||
SetPrivateKeyU (privateKey);
|
||||
}
|
||||
|
||||
#if 0
|
||||
CKey(const RippleAddress& masterKey, int keyNum, bool isPublic) : pkey(NULL), fSet(false)
|
||||
{
|
||||
if (isPublic)
|
||||
SetPubSeq(masterKey, keyNum);
|
||||
else
|
||||
SetPrivSeq(masterKey, keyNum); // broken, need seed
|
||||
fSet = true;
|
||||
}
|
||||
CKey (const RippleAddress& masterKey, int keyNum, bool isPublic) : pkey (NULL), fSet (false)
|
||||
{
|
||||
if (isPublic)
|
||||
SetPubSeq (masterKey, keyNum);
|
||||
else
|
||||
SetPrivSeq (masterKey, keyNum); // broken, need seed
|
||||
|
||||
fSet = true;
|
||||
}
|
||||
#endif
|
||||
|
||||
bool IsNull() const
|
||||
{
|
||||
return !fSet;
|
||||
}
|
||||
bool IsNull () const
|
||||
{
|
||||
return !fSet;
|
||||
}
|
||||
|
||||
void MakeNewKey()
|
||||
{
|
||||
if (!EC_KEY_generate_key(pkey))
|
||||
throw key_error("CKey::MakeNewKey() : EC_KEY_generate_key failed");
|
||||
EC_KEY_set_conv_form(pkey, POINT_CONVERSION_COMPRESSED);
|
||||
fSet = true;
|
||||
}
|
||||
void MakeNewKey ()
|
||||
{
|
||||
if (!EC_KEY_generate_key (pkey))
|
||||
throw key_error ("CKey::MakeNewKey() : EC_KEY_generate_key failed");
|
||||
|
||||
// XXX Still used!
|
||||
BIGNUM* GetSecretBN() const
|
||||
{ // DEPRECATED
|
||||
return BN_dup(EC_KEY_get0_private_key(pkey));
|
||||
}
|
||||
EC_KEY_set_conv_form (pkey, POINT_CONVERSION_COMPRESSED);
|
||||
fSet = true;
|
||||
}
|
||||
|
||||
void GetPrivateKeyU(uint256& privKey)
|
||||
{
|
||||
const BIGNUM* bn = EC_KEY_get0_private_key(pkey);
|
||||
if (bn == NULL)
|
||||
throw key_error("CKey::GetPrivateKeyU: EC_KEY_get0_private_key failed");
|
||||
privKey.zero();
|
||||
BN_bn2bin(bn, privKey.begin() + (privKey.size() - BN_num_bytes(bn)));
|
||||
}
|
||||
// XXX Still used!
|
||||
BIGNUM* GetSecretBN () const
|
||||
{
|
||||
// DEPRECATED
|
||||
return BN_dup (EC_KEY_get0_private_key (pkey));
|
||||
}
|
||||
|
||||
bool SetPrivateKeyU(uint256 const& key, bool bThrow=false)
|
||||
{
|
||||
// XXX Broken if pkey is not set.
|
||||
BIGNUM* bn = BN_bin2bn(key.begin(), key.size(), NULL);
|
||||
bool bSuccess = !!EC_KEY_set_private_key(pkey, bn);
|
||||
void GetPrivateKeyU (uint256& privKey)
|
||||
{
|
||||
const BIGNUM* bn = EC_KEY_get0_private_key (pkey);
|
||||
|
||||
BN_clear_free(bn);
|
||||
if (bn == NULL)
|
||||
throw key_error ("CKey::GetPrivateKeyU: EC_KEY_get0_private_key failed");
|
||||
|
||||
if (bSuccess)
|
||||
{
|
||||
fSet = true;
|
||||
}
|
||||
else if (bThrow)
|
||||
{
|
||||
throw key_error("CKey::SetPrivateKeyU: EC_KEY_set_private_key failed");
|
||||
}
|
||||
privKey.zero ();
|
||||
BN_bn2bin (bn, privKey.begin () + (privKey.size () - BN_num_bytes (bn)));
|
||||
}
|
||||
|
||||
return bSuccess;
|
||||
}
|
||||
bool SetPrivateKeyU (uint256 const& key, bool bThrow = false)
|
||||
{
|
||||
// XXX Broken if pkey is not set.
|
||||
BIGNUM* bn = BN_bin2bn (key.begin (), key.size (), NULL);
|
||||
bool bSuccess = !!EC_KEY_set_private_key (pkey, bn);
|
||||
|
||||
bool SetPubKey(const void *ptr, size_t len)
|
||||
{
|
||||
const unsigned char* pbegin = static_cast<const unsigned char *>(ptr);
|
||||
if (!o2i_ECPublicKey(&pkey, &pbegin, len))
|
||||
return false;
|
||||
EC_KEY_set_conv_form(pkey, POINT_CONVERSION_COMPRESSED);
|
||||
fSet = true;
|
||||
return true;
|
||||
}
|
||||
BN_clear_free (bn);
|
||||
|
||||
bool SetPubKey(Blob const& vchPubKey)
|
||||
{
|
||||
return SetPubKey(&vchPubKey[0], vchPubKey.size());
|
||||
}
|
||||
if (bSuccess)
|
||||
{
|
||||
fSet = true;
|
||||
}
|
||||
else if (bThrow)
|
||||
{
|
||||
throw key_error ("CKey::SetPrivateKeyU: EC_KEY_set_private_key failed");
|
||||
}
|
||||
|
||||
bool SetPubKey(const std::string& pubKey)
|
||||
{
|
||||
return SetPubKey(pubKey.data(), pubKey.size());
|
||||
}
|
||||
return bSuccess;
|
||||
}
|
||||
|
||||
Blob GetPubKey() const
|
||||
{
|
||||
unsigned int nSize = i2o_ECPublicKey(pkey, NULL);
|
||||
assert(nSize<=33);
|
||||
if (!nSize)
|
||||
throw key_error("CKey::GetPubKey() : i2o_ECPublicKey failed");
|
||||
Blob vchPubKey(33, 0);
|
||||
unsigned char* pbegin = &vchPubKey[0];
|
||||
if (i2o_ECPublicKey(pkey, &pbegin) != nSize)
|
||||
throw key_error("CKey::GetPubKey() : i2o_ECPublicKey returned unexpected size");
|
||||
assert(vchPubKey.size()<=33);
|
||||
return vchPubKey;
|
||||
}
|
||||
bool SetPubKey (const void* ptr, size_t len)
|
||||
{
|
||||
const unsigned char* pbegin = static_cast<const unsigned char*> (ptr);
|
||||
|
||||
bool Sign(uint256 const& hash, Blob& vchSig)
|
||||
{
|
||||
unsigned char pchSig[10000];
|
||||
unsigned int nSize = 0;
|
||||
if (!o2i_ECPublicKey (&pkey, &pbegin, len))
|
||||
return false;
|
||||
|
||||
vchSig.clear();
|
||||
EC_KEY_set_conv_form (pkey, POINT_CONVERSION_COMPRESSED);
|
||||
fSet = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!ECDSA_sign(0, (unsigned char*)hash.begin(), hash.size(), pchSig, &nSize, pkey))
|
||||
return false;
|
||||
bool SetPubKey (Blob const& vchPubKey)
|
||||
{
|
||||
return SetPubKey (&vchPubKey[0], vchPubKey.size ());
|
||||
}
|
||||
|
||||
vchSig.resize(nSize);
|
||||
memcpy(&vchSig[0], pchSig, nSize);
|
||||
bool SetPubKey (const std::string& pubKey)
|
||||
{
|
||||
return SetPubKey (pubKey.data (), pubKey.size ());
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
Blob GetPubKey () const
|
||||
{
|
||||
unsigned int nSize = i2o_ECPublicKey (pkey, NULL);
|
||||
assert (nSize <= 33);
|
||||
|
||||
bool Verify(uint256 const& hash, const void *sig, size_t sigLen) const
|
||||
{
|
||||
// -1 = error, 0 = bad sig, 1 = good
|
||||
if (ECDSA_verify(0, hash.begin(), hash.size(), (const unsigned char *) sig, sigLen, pkey) != 1)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
if (!nSize)
|
||||
throw key_error ("CKey::GetPubKey() : i2o_ECPublicKey failed");
|
||||
|
||||
bool Verify(uint256 const& hash, Blob const& vchSig) const
|
||||
{
|
||||
return Verify(hash, &vchSig[0], vchSig.size());
|
||||
}
|
||||
Blob vchPubKey (33, 0);
|
||||
unsigned char* pbegin = &vchPubKey[0];
|
||||
|
||||
bool Verify(uint256 const& hash, const std::string& sig) const
|
||||
{
|
||||
return Verify(hash, sig.data(), sig.size());
|
||||
}
|
||||
if (i2o_ECPublicKey (pkey, &pbegin) != nSize)
|
||||
throw key_error ("CKey::GetPubKey() : i2o_ECPublicKey returned unexpected size");
|
||||
|
||||
// ECIES functions. These throw on failure
|
||||
assert (vchPubKey.size () <= 33);
|
||||
return vchPubKey;
|
||||
}
|
||||
|
||||
// returns a 32-byte secret unique to these two keys. At least one private key must be known.
|
||||
void getECIESSecret(CKey& otherKey, uint256& enc_key, uint256& hmac_key);
|
||||
bool Sign (uint256 const& hash, Blob& vchSig)
|
||||
{
|
||||
unsigned char pchSig[10000];
|
||||
unsigned int nSize = 0;
|
||||
|
||||
// encrypt/decrypt functions with integrity checking.
|
||||
// Note that the other side must somehow know what keys to use
|
||||
Blob encryptECIES(CKey& otherKey, Blob const& plaintext);
|
||||
Blob decryptECIES(CKey& otherKey, Blob const& ciphertext);
|
||||
vchSig.clear ();
|
||||
|
||||
if (!ECDSA_sign (0, (unsigned char*)hash.begin (), hash.size (), pchSig, &nSize, pkey))
|
||||
return false;
|
||||
|
||||
vchSig.resize (nSize);
|
||||
memcpy (&vchSig[0], pchSig, nSize);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Verify (uint256 const& hash, const void* sig, size_t sigLen) const
|
||||
{
|
||||
// -1 = error, 0 = bad sig, 1 = good
|
||||
if (ECDSA_verify (0, hash.begin (), hash.size (), (const unsigned char*) sig, sigLen, pkey) != 1)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Verify (uint256 const& hash, Blob const& vchSig) const
|
||||
{
|
||||
return Verify (hash, &vchSig[0], vchSig.size ());
|
||||
}
|
||||
|
||||
bool Verify (uint256 const& hash, const std::string& sig) const
|
||||
{
|
||||
return Verify (hash, sig.data (), sig.size ());
|
||||
}
|
||||
|
||||
// ECIES functions. These throw on failure
|
||||
|
||||
// returns a 32-byte secret unique to these two keys. At least one private key must be known.
|
||||
void getECIESSecret (CKey& otherKey, uint256& enc_key, uint256& hmac_key);
|
||||
|
||||
// encrypt/decrypt functions with integrity checking.
|
||||
// Note that the other side must somehow know what keys to use
|
||||
Blob encryptECIES (CKey& otherKey, Blob const& plaintext);
|
||||
Blob decryptECIES (CKey& otherKey, Blob const& ciphertext);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -4,328 +4,375 @@
|
||||
// Functions to add CKey support for deterministic EC keys
|
||||
|
||||
// <-- seed
|
||||
uint128 CKey::PassPhraseToKey(const std::string& passPhrase)
|
||||
uint128 CKey::PassPhraseToKey (const std::string& passPhrase)
|
||||
{
|
||||
Serializer s;
|
||||
Serializer s;
|
||||
|
||||
s.addRaw(passPhrase);
|
||||
uint256 hash256 = s.getSHA512Half();
|
||||
uint128 ret(hash256);
|
||||
s.addRaw (passPhrase);
|
||||
uint256 hash256 = s.getSHA512Half ();
|
||||
uint128 ret (hash256);
|
||||
|
||||
s.secureErase();
|
||||
s.secureErase ();
|
||||
|
||||
return ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
// --> seed
|
||||
// <-- private root generator + public root generator
|
||||
EC_KEY* CKey::GenerateRootDeterministicKey(const uint128& seed)
|
||||
EC_KEY* CKey::GenerateRootDeterministicKey (const uint128& seed)
|
||||
{
|
||||
BN_CTX* ctx=BN_CTX_new();
|
||||
if(!ctx) return NULL;
|
||||
BN_CTX* ctx = BN_CTX_new ();
|
||||
|
||||
EC_KEY* pkey=EC_KEY_new_by_curve_name(NID_secp256k1);
|
||||
if(!pkey)
|
||||
{
|
||||
BN_CTX_free(ctx);
|
||||
return NULL;
|
||||
}
|
||||
EC_KEY_set_conv_form(pkey, POINT_CONVERSION_COMPRESSED);
|
||||
if (!ctx) return NULL;
|
||||
|
||||
BIGNUM* order=BN_new();
|
||||
if(!order)
|
||||
{
|
||||
BN_CTX_free(ctx);
|
||||
EC_KEY_free(pkey);
|
||||
return NULL;
|
||||
}
|
||||
if(!EC_GROUP_get_order(EC_KEY_get0_group(pkey), order, ctx))
|
||||
{
|
||||
assert(false);
|
||||
BN_free(order);
|
||||
EC_KEY_free(pkey);
|
||||
BN_CTX_free(ctx);
|
||||
return NULL;
|
||||
}
|
||||
EC_KEY* pkey = EC_KEY_new_by_curve_name (NID_secp256k1);
|
||||
|
||||
BIGNUM *privKey=NULL;
|
||||
int seq=0;
|
||||
do
|
||||
{ // private key must be non-zero and less than the curve's order
|
||||
Serializer s((128+32)/8);
|
||||
s.add128(seed);
|
||||
s.add32(seq++);
|
||||
uint256 root=s.getSHA512Half();
|
||||
s.secureErase();
|
||||
privKey=BN_bin2bn((const unsigned char *) &root, sizeof(root), privKey);
|
||||
if(privKey==NULL)
|
||||
{
|
||||
EC_KEY_free(pkey);
|
||||
BN_free(order);
|
||||
BN_CTX_free(ctx);
|
||||
}
|
||||
root.zero();
|
||||
} while(BN_is_zero(privKey) || (BN_cmp(privKey, order)>=0));
|
||||
if (!pkey)
|
||||
{
|
||||
BN_CTX_free (ctx);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
BN_free(order);
|
||||
EC_KEY_set_conv_form (pkey, POINT_CONVERSION_COMPRESSED);
|
||||
|
||||
if(!EC_KEY_set_private_key(pkey, privKey))
|
||||
{ // set the random point as the private key
|
||||
assert(false);
|
||||
EC_KEY_free(pkey);
|
||||
BN_clear_free(privKey);
|
||||
BN_CTX_free(ctx);
|
||||
return NULL;
|
||||
}
|
||||
BIGNUM* order = BN_new ();
|
||||
|
||||
EC_POINT *pubKey=EC_POINT_new(EC_KEY_get0_group(pkey));
|
||||
if(!EC_POINT_mul(EC_KEY_get0_group(pkey), pubKey, privKey, NULL, NULL, ctx))
|
||||
{ // compute the corresponding public key point
|
||||
assert(false);
|
||||
BN_clear_free(privKey);
|
||||
EC_POINT_free(pubKey);
|
||||
EC_KEY_free(pkey);
|
||||
BN_CTX_free(ctx);
|
||||
return NULL;
|
||||
}
|
||||
BN_clear_free(privKey);
|
||||
if(!EC_KEY_set_public_key(pkey, pubKey))
|
||||
{
|
||||
assert(false);
|
||||
EC_POINT_free(pubKey);
|
||||
EC_KEY_free(pkey);
|
||||
BN_CTX_free(ctx);
|
||||
return NULL;
|
||||
}
|
||||
EC_POINT_free(pubKey);
|
||||
if (!order)
|
||||
{
|
||||
BN_CTX_free (ctx);
|
||||
EC_KEY_free (pkey);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
BN_CTX_free(ctx);
|
||||
if (!EC_GROUP_get_order (EC_KEY_get0_group (pkey), order, ctx))
|
||||
{
|
||||
assert (false);
|
||||
BN_free (order);
|
||||
EC_KEY_free (pkey);
|
||||
BN_CTX_free (ctx);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
BIGNUM* privKey = NULL;
|
||||
int seq = 0;
|
||||
|
||||
do
|
||||
{
|
||||
// private key must be non-zero and less than the curve's order
|
||||
Serializer s ((128 + 32) / 8);
|
||||
s.add128 (seed);
|
||||
s.add32 (seq++);
|
||||
uint256 root = s.getSHA512Half ();
|
||||
s.secureErase ();
|
||||
privKey = BN_bin2bn ((const unsigned char*) &root, sizeof (root), privKey);
|
||||
|
||||
if (privKey == NULL)
|
||||
{
|
||||
EC_KEY_free (pkey);
|
||||
BN_free (order);
|
||||
BN_CTX_free (ctx);
|
||||
}
|
||||
|
||||
root.zero ();
|
||||
}
|
||||
while (BN_is_zero (privKey) || (BN_cmp (privKey, order) >= 0));
|
||||
|
||||
BN_free (order);
|
||||
|
||||
if (!EC_KEY_set_private_key (pkey, privKey))
|
||||
{
|
||||
// set the random point as the private key
|
||||
assert (false);
|
||||
EC_KEY_free (pkey);
|
||||
BN_clear_free (privKey);
|
||||
BN_CTX_free (ctx);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
EC_POINT* pubKey = EC_POINT_new (EC_KEY_get0_group (pkey));
|
||||
|
||||
if (!EC_POINT_mul (EC_KEY_get0_group (pkey), pubKey, privKey, NULL, NULL, ctx))
|
||||
{
|
||||
// compute the corresponding public key point
|
||||
assert (false);
|
||||
BN_clear_free (privKey);
|
||||
EC_POINT_free (pubKey);
|
||||
EC_KEY_free (pkey);
|
||||
BN_CTX_free (ctx);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
BN_clear_free (privKey);
|
||||
|
||||
if (!EC_KEY_set_public_key (pkey, pubKey))
|
||||
{
|
||||
assert (false);
|
||||
EC_POINT_free (pubKey);
|
||||
EC_KEY_free (pkey);
|
||||
BN_CTX_free (ctx);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
EC_POINT_free (pubKey);
|
||||
|
||||
BN_CTX_free (ctx);
|
||||
|
||||
#ifdef EC_DEBUG
|
||||
assert(EC_KEY_check_key(pkey)==1); // CAUTION: This check is *very* expensive
|
||||
assert (EC_KEY_check_key (pkey) == 1); // CAUTION: This check is *very* expensive
|
||||
#endif
|
||||
return pkey;
|
||||
return pkey;
|
||||
}
|
||||
|
||||
// Take ripple address.
|
||||
// --> root public generator (consumes)
|
||||
// <-- root public generator in EC format
|
||||
EC_KEY* CKey::GenerateRootPubKey(BIGNUM* pubGenerator)
|
||||
EC_KEY* CKey::GenerateRootPubKey (BIGNUM* pubGenerator)
|
||||
{
|
||||
if (pubGenerator == NULL)
|
||||
{
|
||||
assert(false);
|
||||
return NULL;
|
||||
}
|
||||
if (pubGenerator == NULL)
|
||||
{
|
||||
assert (false);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
EC_KEY* pkey = EC_KEY_new_by_curve_name(NID_secp256k1);
|
||||
if (!pkey)
|
||||
{
|
||||
BN_free(pubGenerator);
|
||||
return NULL;
|
||||
}
|
||||
EC_KEY_set_conv_form(pkey, POINT_CONVERSION_COMPRESSED);
|
||||
EC_KEY* pkey = EC_KEY_new_by_curve_name (NID_secp256k1);
|
||||
|
||||
EC_POINT* pubPoint = EC_POINT_bn2point(EC_KEY_get0_group(pkey), pubGenerator, NULL, NULL);
|
||||
BN_free(pubGenerator);
|
||||
if(!pubPoint)
|
||||
{
|
||||
assert(false);
|
||||
EC_KEY_free(pkey);
|
||||
return NULL;
|
||||
}
|
||||
if (!pkey)
|
||||
{
|
||||
BN_free (pubGenerator);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(!EC_KEY_set_public_key(pkey, pubPoint))
|
||||
{
|
||||
assert(false);
|
||||
EC_POINT_free(pubPoint);
|
||||
EC_KEY_free(pkey);
|
||||
return NULL;
|
||||
}
|
||||
EC_POINT_free(pubPoint);
|
||||
EC_KEY_set_conv_form (pkey, POINT_CONVERSION_COMPRESSED);
|
||||
|
||||
return pkey;
|
||||
EC_POINT* pubPoint = EC_POINT_bn2point (EC_KEY_get0_group (pkey), pubGenerator, NULL, NULL);
|
||||
BN_free (pubGenerator);
|
||||
|
||||
if (!pubPoint)
|
||||
{
|
||||
assert (false);
|
||||
EC_KEY_free (pkey);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!EC_KEY_set_public_key (pkey, pubPoint))
|
||||
{
|
||||
assert (false);
|
||||
EC_POINT_free (pubPoint);
|
||||
EC_KEY_free (pkey);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
EC_POINT_free (pubPoint);
|
||||
|
||||
return pkey;
|
||||
}
|
||||
|
||||
// --> public generator
|
||||
static BIGNUM* makeHash(const RippleAddress& pubGen, int seq, BIGNUM* order)
|
||||
static BIGNUM* makeHash (const RippleAddress& pubGen, int seq, BIGNUM* order)
|
||||
{
|
||||
int subSeq=0;
|
||||
BIGNUM* ret=NULL;
|
||||
do
|
||||
{
|
||||
Serializer s((33*8+32+32)/8);
|
||||
s.addRaw(pubGen.getGenerator());
|
||||
s.add32(seq);
|
||||
s.add32(subSeq++);
|
||||
uint256 root=s.getSHA512Half();
|
||||
s.secureErase();
|
||||
ret=BN_bin2bn((const unsigned char *) &root, sizeof(root), ret);
|
||||
if(!ret) return NULL;
|
||||
} while (BN_is_zero(ret) || (BN_cmp(ret, order)>=0));
|
||||
int subSeq = 0;
|
||||
BIGNUM* ret = NULL;
|
||||
|
||||
return ret;
|
||||
do
|
||||
{
|
||||
Serializer s ((33 * 8 + 32 + 32) / 8);
|
||||
s.addRaw (pubGen.getGenerator ());
|
||||
s.add32 (seq);
|
||||
s.add32 (subSeq++);
|
||||
uint256 root = s.getSHA512Half ();
|
||||
s.secureErase ();
|
||||
ret = BN_bin2bn ((const unsigned char*) &root, sizeof (root), ret);
|
||||
|
||||
if (!ret) return NULL;
|
||||
}
|
||||
while (BN_is_zero (ret) || (BN_cmp (ret, order) >= 0));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
// --> public generator
|
||||
EC_KEY* CKey::GeneratePublicDeterministicKey(const RippleAddress& pubGen, int seq)
|
||||
{ // publicKey(n) = rootPublicKey EC_POINT_+ Hash(pubHash|seq)*point
|
||||
EC_KEY* rootKey = CKey::GenerateRootPubKey(pubGen.getGeneratorBN());
|
||||
const EC_POINT* rootPubKey = EC_KEY_get0_public_key(rootKey);
|
||||
BN_CTX* ctx = BN_CTX_new();
|
||||
EC_KEY* pkey = EC_KEY_new_by_curve_name(NID_secp256k1);
|
||||
EC_POINT* newPoint = 0;
|
||||
BIGNUM* order = 0;
|
||||
BIGNUM* hash = 0;
|
||||
bool success = true;
|
||||
EC_KEY* CKey::GeneratePublicDeterministicKey (const RippleAddress& pubGen, int seq)
|
||||
{
|
||||
// publicKey(n) = rootPublicKey EC_POINT_+ Hash(pubHash|seq)*point
|
||||
EC_KEY* rootKey = CKey::GenerateRootPubKey (pubGen.getGeneratorBN ());
|
||||
const EC_POINT* rootPubKey = EC_KEY_get0_public_key (rootKey);
|
||||
BN_CTX* ctx = BN_CTX_new ();
|
||||
EC_KEY* pkey = EC_KEY_new_by_curve_name (NID_secp256k1);
|
||||
EC_POINT* newPoint = 0;
|
||||
BIGNUM* order = 0;
|
||||
BIGNUM* hash = 0;
|
||||
bool success = true;
|
||||
|
||||
if (!ctx || !pkey) success = false;
|
||||
if (!ctx || !pkey) success = false;
|
||||
|
||||
if (success)
|
||||
EC_KEY_set_conv_form(pkey, POINT_CONVERSION_COMPRESSED);
|
||||
if (success)
|
||||
EC_KEY_set_conv_form (pkey, POINT_CONVERSION_COMPRESSED);
|
||||
|
||||
if (success) {
|
||||
newPoint = EC_POINT_new(EC_KEY_get0_group(pkey));
|
||||
if(!newPoint) success = false;
|
||||
}
|
||||
if (success)
|
||||
{
|
||||
newPoint = EC_POINT_new (EC_KEY_get0_group (pkey));
|
||||
|
||||
if (success) {
|
||||
order = BN_new();
|
||||
if (!newPoint) success = false;
|
||||
}
|
||||
|
||||
if(!order || !EC_GROUP_get_order(EC_KEY_get0_group(pkey), order, ctx))
|
||||
success = false;
|
||||
}
|
||||
if (success)
|
||||
{
|
||||
order = BN_new ();
|
||||
|
||||
// Calculate the private additional key.
|
||||
if (success) {
|
||||
hash = makeHash(pubGen, seq, order);
|
||||
if(!hash) success = false;
|
||||
}
|
||||
if (!order || !EC_GROUP_get_order (EC_KEY_get0_group (pkey), order, ctx))
|
||||
success = false;
|
||||
}
|
||||
|
||||
if (success) {
|
||||
// Calculate the corresponding public key.
|
||||
EC_POINT_mul(EC_KEY_get0_group(pkey), newPoint, hash, NULL, NULL, ctx);
|
||||
// Calculate the private additional key.
|
||||
if (success)
|
||||
{
|
||||
hash = makeHash (pubGen, seq, order);
|
||||
|
||||
// Add the master public key and set.
|
||||
EC_POINT_add(EC_KEY_get0_group(pkey), newPoint, newPoint, rootPubKey, ctx);
|
||||
EC_KEY_set_public_key(pkey, newPoint);
|
||||
}
|
||||
if (!hash) success = false;
|
||||
}
|
||||
|
||||
if (order) BN_free(order);
|
||||
if (hash) BN_free(hash);
|
||||
if (newPoint) EC_POINT_free(newPoint);
|
||||
if (ctx) BN_CTX_free(ctx);
|
||||
if (rootKey) EC_KEY_free(rootKey);
|
||||
if (pkey && !success) EC_KEY_free(pkey);
|
||||
if (success)
|
||||
{
|
||||
// Calculate the corresponding public key.
|
||||
EC_POINT_mul (EC_KEY_get0_group (pkey), newPoint, hash, NULL, NULL, ctx);
|
||||
|
||||
return success ? pkey : NULL;
|
||||
// Add the master public key and set.
|
||||
EC_POINT_add (EC_KEY_get0_group (pkey), newPoint, newPoint, rootPubKey, ctx);
|
||||
EC_KEY_set_public_key (pkey, newPoint);
|
||||
}
|
||||
|
||||
if (order) BN_free (order);
|
||||
|
||||
if (hash) BN_free (hash);
|
||||
|
||||
if (newPoint) EC_POINT_free (newPoint);
|
||||
|
||||
if (ctx) BN_CTX_free (ctx);
|
||||
|
||||
if (rootKey) EC_KEY_free (rootKey);
|
||||
|
||||
if (pkey && !success) EC_KEY_free (pkey);
|
||||
|
||||
return success ? pkey : NULL;
|
||||
}
|
||||
|
||||
EC_KEY* CKey::GeneratePrivateDeterministicKey(const RippleAddress& pubGen, uint256 const& u, int seq)
|
||||
EC_KEY* CKey::GeneratePrivateDeterministicKey (const RippleAddress& pubGen, uint256 const& u, int seq)
|
||||
{
|
||||
CBigNum bn(u);
|
||||
return GeneratePrivateDeterministicKey(pubGen, static_cast<BIGNUM*>(&bn), seq);
|
||||
CBigNum bn (u);
|
||||
return GeneratePrivateDeterministicKey (pubGen, static_cast<BIGNUM*> (&bn), seq);
|
||||
}
|
||||
|
||||
// --> root private key
|
||||
EC_KEY* CKey::GeneratePrivateDeterministicKey(const RippleAddress& pubGen, const BIGNUM* rootPrivKey, int seq)
|
||||
{ // privateKey(n) = (rootPrivateKey + Hash(pubHash|seq)) % order
|
||||
BN_CTX* ctx=BN_CTX_new();
|
||||
if(ctx==NULL) return NULL;
|
||||
|
||||
EC_KEY* pkey=EC_KEY_new_by_curve_name(NID_secp256k1);
|
||||
if(pkey==NULL)
|
||||
{
|
||||
BN_CTX_free(ctx);
|
||||
return NULL;
|
||||
}
|
||||
EC_KEY_set_conv_form(pkey, POINT_CONVERSION_COMPRESSED);
|
||||
|
||||
BIGNUM* order=BN_new();
|
||||
if(order==NULL)
|
||||
{
|
||||
BN_CTX_free(ctx);
|
||||
EC_KEY_free(pkey);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(!EC_GROUP_get_order(EC_KEY_get0_group(pkey), order, ctx))
|
||||
{
|
||||
BN_free(order);
|
||||
BN_CTX_free(ctx);
|
||||
EC_KEY_free(pkey);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// calculate the private additional key
|
||||
BIGNUM* privKey=makeHash(pubGen, seq, order);
|
||||
if(privKey==NULL)
|
||||
{
|
||||
BN_free(order);
|
||||
BN_CTX_free(ctx);
|
||||
EC_KEY_free(pkey);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// calculate the final private key
|
||||
BN_mod_add(privKey, privKey, rootPrivKey, order, ctx);
|
||||
BN_free(order);
|
||||
EC_KEY_set_private_key(pkey, privKey);
|
||||
|
||||
// compute the corresponding public key
|
||||
EC_POINT* pubKey=EC_POINT_new(EC_KEY_get0_group(pkey));
|
||||
if(!pubKey)
|
||||
{
|
||||
BN_clear_free(privKey);
|
||||
BN_CTX_free(ctx);
|
||||
EC_KEY_free(pkey);
|
||||
return NULL;
|
||||
}
|
||||
if(EC_POINT_mul(EC_KEY_get0_group(pkey), pubKey, privKey, NULL, NULL, ctx)==0)
|
||||
{
|
||||
BN_clear_free(privKey);
|
||||
EC_POINT_free(pubKey);
|
||||
EC_KEY_free(pkey);
|
||||
BN_CTX_free(ctx);
|
||||
return NULL;
|
||||
}
|
||||
BN_clear_free(privKey);
|
||||
EC_KEY_set_public_key(pkey, pubKey);
|
||||
|
||||
EC_POINT_free(pubKey);
|
||||
BN_CTX_free(ctx);
|
||||
|
||||
return pkey;
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE(DeterministicKeys_test)
|
||||
|
||||
BOOST_AUTO_TEST_CASE(DeterminsticKeys_test1)
|
||||
EC_KEY* CKey::GeneratePrivateDeterministicKey (const RippleAddress& pubGen, const BIGNUM* rootPrivKey, int seq)
|
||||
{
|
||||
Log(lsDEBUG) << "Beginning deterministic key test";
|
||||
// privateKey(n) = (rootPrivateKey + Hash(pubHash|seq)) % order
|
||||
BN_CTX* ctx = BN_CTX_new ();
|
||||
|
||||
uint128 seed1, seed2;
|
||||
seed1.SetHex("71ED064155FFADFA38782C5E0158CB26");
|
||||
seed2.SetHex("CF0C3BE4485961858C4198515AE5B965");
|
||||
CKey root1(seed1), root2(seed2);
|
||||
if (ctx == NULL) return NULL;
|
||||
|
||||
uint256 priv1, priv2;
|
||||
root1.GetPrivateKeyU(priv1);
|
||||
root2.GetPrivateKeyU(priv2);
|
||||
EC_KEY* pkey = EC_KEY_new_by_curve_name (NID_secp256k1);
|
||||
|
||||
if (priv1.GetHex() != "7CFBA64F771E93E817E15039215430B53F7401C34931D111EAB3510B22DBB0D8")
|
||||
BOOST_FAIL("Incorrect private key for generator");
|
||||
if (priv2.GetHex() != "98BC2EACB26EB021D1A6293C044D88BA2F0B6729A2772DEEBF2E21A263C1740B")
|
||||
BOOST_FAIL("Incorrect private key for generator");
|
||||
if (pkey == NULL)
|
||||
{
|
||||
BN_CTX_free (ctx);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
RippleAddress nSeed;
|
||||
nSeed.setSeed(seed1);
|
||||
if (nSeed.humanSeed() != "shHM53KPZ87Gwdqarm1bAmPeXg8Tn")
|
||||
BOOST_FAIL("Incorrect human seed");
|
||||
if (nSeed.humanSeed1751() != "MAD BODY ACE MINT OKAY HUB WHAT DATA SACK FLAT DANA MATH")
|
||||
BOOST_FAIL("Incorrect 1751 seed");
|
||||
EC_KEY_set_conv_form (pkey, POINT_CONVERSION_COMPRESSED);
|
||||
|
||||
BIGNUM* order = BN_new ();
|
||||
|
||||
if (order == NULL)
|
||||
{
|
||||
BN_CTX_free (ctx);
|
||||
EC_KEY_free (pkey);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!EC_GROUP_get_order (EC_KEY_get0_group (pkey), order, ctx))
|
||||
{
|
||||
BN_free (order);
|
||||
BN_CTX_free (ctx);
|
||||
EC_KEY_free (pkey);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// calculate the private additional key
|
||||
BIGNUM* privKey = makeHash (pubGen, seq, order);
|
||||
|
||||
if (privKey == NULL)
|
||||
{
|
||||
BN_free (order);
|
||||
BN_CTX_free (ctx);
|
||||
EC_KEY_free (pkey);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// calculate the final private key
|
||||
BN_mod_add (privKey, privKey, rootPrivKey, order, ctx);
|
||||
BN_free (order);
|
||||
EC_KEY_set_private_key (pkey, privKey);
|
||||
|
||||
// compute the corresponding public key
|
||||
EC_POINT* pubKey = EC_POINT_new (EC_KEY_get0_group (pkey));
|
||||
|
||||
if (!pubKey)
|
||||
{
|
||||
BN_clear_free (privKey);
|
||||
BN_CTX_free (ctx);
|
||||
EC_KEY_free (pkey);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (EC_POINT_mul (EC_KEY_get0_group (pkey), pubKey, privKey, NULL, NULL, ctx) == 0)
|
||||
{
|
||||
BN_clear_free (privKey);
|
||||
EC_POINT_free (pubKey);
|
||||
EC_KEY_free (pkey);
|
||||
BN_CTX_free (ctx);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
BN_clear_free (privKey);
|
||||
EC_KEY_set_public_key (pkey, pubKey);
|
||||
|
||||
EC_POINT_free (pubKey);
|
||||
BN_CTX_free (ctx);
|
||||
|
||||
return pkey;
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END();
|
||||
BOOST_AUTO_TEST_SUITE (DeterministicKeys_test)
|
||||
|
||||
BOOST_AUTO_TEST_CASE (DeterminsticKeys_test1)
|
||||
{
|
||||
Log (lsDEBUG) << "Beginning deterministic key test";
|
||||
|
||||
uint128 seed1, seed2;
|
||||
seed1.SetHex ("71ED064155FFADFA38782C5E0158CB26");
|
||||
seed2.SetHex ("CF0C3BE4485961858C4198515AE5B965");
|
||||
CKey root1 (seed1), root2 (seed2);
|
||||
|
||||
uint256 priv1, priv2;
|
||||
root1.GetPrivateKeyU (priv1);
|
||||
root2.GetPrivateKeyU (priv2);
|
||||
|
||||
if (priv1.GetHex () != "7CFBA64F771E93E817E15039215430B53F7401C34931D111EAB3510B22DBB0D8")
|
||||
BOOST_FAIL ("Incorrect private key for generator");
|
||||
|
||||
if (priv2.GetHex () != "98BC2EACB26EB021D1A6293C044D88BA2F0B6729A2772DEEBF2E21A263C1740B")
|
||||
BOOST_FAIL ("Incorrect private key for generator");
|
||||
|
||||
RippleAddress nSeed;
|
||||
nSeed.setSeed (seed1);
|
||||
|
||||
if (nSeed.humanSeed () != "shHM53KPZ87Gwdqarm1bAmPeXg8Tn")
|
||||
BOOST_FAIL ("Incorrect human seed");
|
||||
|
||||
if (nSeed.humanSeed1751 () != "MAD BODY ACE MINT OKAY HUB WHAT DATA SACK FLAT DANA MATH")
|
||||
BOOST_FAIL ("Incorrect 1751 seed");
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END ();
|
||||
|
||||
// vim:ts=4
|
||||
|
||||
@@ -24,267 +24,288 @@
|
||||
// key. They *must* be called in try/catch blocks.
|
||||
|
||||
// Algorithmic choices:
|
||||
#define ECIES_KEY_HASH SHA512 // Hash used to expand shared secret
|
||||
#define ECIES_KEY_LENGTH (512/8) // Size of expanded shared secret
|
||||
#define ECIES_MIN_SEC (128/8) // The minimum equivalent security
|
||||
#define ECIES_ENC_ALGO EVP_aes_256_cbc() // Encryption algorithm
|
||||
#define ECIES_ENC_KEY_TYPE uint256 // Type used to hold shared secret
|
||||
#define ECIES_ENC_KEY_SIZE (256/8) // Encryption key size
|
||||
#define ECIES_ENC_BLK_SIZE (128/8) // Encryption block size
|
||||
#define ECIES_ENC_IV_TYPE uint128 // Type used to hold IV
|
||||
#define ECIES_HMAC_ALGO EVP_sha256() // HMAC algorithm
|
||||
#define ECIES_HMAC_KEY_TYPE uint256 // Type used to hold HMAC key
|
||||
#define ECIES_HMAC_KEY_SIZE (256/8) // Size of HMAC key
|
||||
#define ECIES_HMAC_TYPE uint256 // Type used to hold HMAC value
|
||||
#define ECIES_HMAC_SIZE (256/8) // Size of HMAC value
|
||||
#define ECIES_KEY_HASH SHA512 // Hash used to expand shared secret
|
||||
#define ECIES_KEY_LENGTH (512/8) // Size of expanded shared secret
|
||||
#define ECIES_MIN_SEC (128/8) // The minimum equivalent security
|
||||
#define ECIES_ENC_ALGO EVP_aes_256_cbc() // Encryption algorithm
|
||||
#define ECIES_ENC_KEY_TYPE uint256 // Type used to hold shared secret
|
||||
#define ECIES_ENC_KEY_SIZE (256/8) // Encryption key size
|
||||
#define ECIES_ENC_BLK_SIZE (128/8) // Encryption block size
|
||||
#define ECIES_ENC_IV_TYPE uint128 // Type used to hold IV
|
||||
#define ECIES_HMAC_ALGO EVP_sha256() // HMAC algorithm
|
||||
#define ECIES_HMAC_KEY_TYPE uint256 // Type used to hold HMAC key
|
||||
#define ECIES_HMAC_KEY_SIZE (256/8) // Size of HMAC key
|
||||
#define ECIES_HMAC_TYPE uint256 // Type used to hold HMAC value
|
||||
#define ECIES_HMAC_SIZE (256/8) // Size of HMAC value
|
||||
|
||||
void CKey::getECIESSecret(CKey& otherKey, ECIES_ENC_KEY_TYPE& enc_key, ECIES_HMAC_KEY_TYPE& hmac_key)
|
||||
{ // Retrieve a secret generated from an EC key pair. At least one private key must be known.
|
||||
if (!pkey || !otherKey.pkey)
|
||||
throw std::runtime_error("missing key");
|
||||
void CKey::getECIESSecret (CKey& otherKey, ECIES_ENC_KEY_TYPE& enc_key, ECIES_HMAC_KEY_TYPE& hmac_key)
|
||||
{
|
||||
// Retrieve a secret generated from an EC key pair. At least one private key must be known.
|
||||
if (!pkey || !otherKey.pkey)
|
||||
throw std::runtime_error ("missing key");
|
||||
|
||||
EC_KEY *pubkey, *privkey;
|
||||
if (EC_KEY_get0_private_key(pkey))
|
||||
{
|
||||
privkey = pkey;
|
||||
pubkey = otherKey.pkey;
|
||||
}
|
||||
else if (EC_KEY_get0_private_key(otherKey.pkey))
|
||||
{
|
||||
privkey = otherKey.pkey;
|
||||
pubkey = pkey;
|
||||
}
|
||||
else throw std::runtime_error("no private key");
|
||||
EC_KEY* pubkey, *privkey;
|
||||
|
||||
unsigned char rawbuf[512];
|
||||
int buflen = ECDH_compute_key(rawbuf, 512, EC_KEY_get0_public_key(pubkey), privkey, NULL);
|
||||
if (buflen < ECIES_MIN_SEC)
|
||||
throw std::runtime_error("ecdh key failed");
|
||||
if (EC_KEY_get0_private_key (pkey))
|
||||
{
|
||||
privkey = pkey;
|
||||
pubkey = otherKey.pkey;
|
||||
}
|
||||
else if (EC_KEY_get0_private_key (otherKey.pkey))
|
||||
{
|
||||
privkey = otherKey.pkey;
|
||||
pubkey = pkey;
|
||||
}
|
||||
else throw std::runtime_error ("no private key");
|
||||
|
||||
unsigned char hbuf[ECIES_KEY_LENGTH];
|
||||
ECIES_KEY_HASH(rawbuf, buflen, hbuf);
|
||||
memset(rawbuf, 0, ECIES_HMAC_KEY_SIZE);
|
||||
unsigned char rawbuf[512];
|
||||
int buflen = ECDH_compute_key (rawbuf, 512, EC_KEY_get0_public_key (pubkey), privkey, NULL);
|
||||
|
||||
assert((ECIES_ENC_KEY_SIZE + ECIES_HMAC_KEY_SIZE) >= ECIES_KEY_LENGTH);
|
||||
memcpy(enc_key.begin(), hbuf, ECIES_ENC_KEY_SIZE);
|
||||
memcpy(hmac_key.begin(), hbuf + ECIES_ENC_KEY_SIZE, ECIES_HMAC_KEY_SIZE);
|
||||
memset(hbuf, 0, ECIES_KEY_LENGTH);
|
||||
if (buflen < ECIES_MIN_SEC)
|
||||
throw std::runtime_error ("ecdh key failed");
|
||||
|
||||
unsigned char hbuf[ECIES_KEY_LENGTH];
|
||||
ECIES_KEY_HASH (rawbuf, buflen, hbuf);
|
||||
memset (rawbuf, 0, ECIES_HMAC_KEY_SIZE);
|
||||
|
||||
assert ((ECIES_ENC_KEY_SIZE + ECIES_HMAC_KEY_SIZE) >= ECIES_KEY_LENGTH);
|
||||
memcpy (enc_key.begin (), hbuf, ECIES_ENC_KEY_SIZE);
|
||||
memcpy (hmac_key.begin (), hbuf + ECIES_ENC_KEY_SIZE, ECIES_HMAC_KEY_SIZE);
|
||||
memset (hbuf, 0, ECIES_KEY_LENGTH);
|
||||
}
|
||||
|
||||
static ECIES_HMAC_TYPE makeHMAC(const ECIES_HMAC_KEY_TYPE& secret, Blob const& data)
|
||||
static ECIES_HMAC_TYPE makeHMAC (const ECIES_HMAC_KEY_TYPE& secret, Blob const& data)
|
||||
{
|
||||
HMAC_CTX ctx;
|
||||
HMAC_CTX_init(&ctx);
|
||||
HMAC_CTX ctx;
|
||||
HMAC_CTX_init (&ctx);
|
||||
|
||||
if (HMAC_Init_ex(&ctx, secret.begin(), ECIES_HMAC_KEY_SIZE, ECIES_HMAC_ALGO, NULL) != 1)
|
||||
{
|
||||
HMAC_CTX_cleanup(&ctx);
|
||||
throw std::runtime_error("init hmac");
|
||||
}
|
||||
if (HMAC_Init_ex (&ctx, secret.begin (), ECIES_HMAC_KEY_SIZE, ECIES_HMAC_ALGO, NULL) != 1)
|
||||
{
|
||||
HMAC_CTX_cleanup (&ctx);
|
||||
throw std::runtime_error ("init hmac");
|
||||
}
|
||||
|
||||
if (HMAC_Update(&ctx, &(data.front()), data.size()) != 1)
|
||||
{
|
||||
HMAC_CTX_cleanup(&ctx);
|
||||
throw std::runtime_error("update hmac");
|
||||
}
|
||||
if (HMAC_Update (&ctx, & (data.front ()), data.size ()) != 1)
|
||||
{
|
||||
HMAC_CTX_cleanup (&ctx);
|
||||
throw std::runtime_error ("update hmac");
|
||||
}
|
||||
|
||||
ECIES_HMAC_TYPE ret;
|
||||
unsigned int ml = ECIES_HMAC_SIZE;
|
||||
if (HMAC_Final(&ctx, ret.begin(), &ml) != 1)
|
||||
{
|
||||
HMAC_CTX_cleanup(&ctx);
|
||||
throw std::runtime_error("finalize hmac");
|
||||
}
|
||||
assert(ml == ECIES_HMAC_SIZE);
|
||||
HMAC_CTX_cleanup(&ctx);
|
||||
ECIES_HMAC_TYPE ret;
|
||||
unsigned int ml = ECIES_HMAC_SIZE;
|
||||
|
||||
return ret;
|
||||
if (HMAC_Final (&ctx, ret.begin (), &ml) != 1)
|
||||
{
|
||||
HMAC_CTX_cleanup (&ctx);
|
||||
throw std::runtime_error ("finalize hmac");
|
||||
}
|
||||
|
||||
assert (ml == ECIES_HMAC_SIZE);
|
||||
HMAC_CTX_cleanup (&ctx);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
Blob CKey::encryptECIES(CKey& otherKey, Blob const& plaintext)
|
||||
Blob CKey::encryptECIES (CKey& otherKey, Blob const& plaintext)
|
||||
{
|
||||
|
||||
ECIES_ENC_IV_TYPE iv;
|
||||
RandomNumbers::getInstance ().fillBytes (iv.begin (), ECIES_ENC_BLK_SIZE);
|
||||
ECIES_ENC_IV_TYPE iv;
|
||||
RandomNumbers::getInstance ().fillBytes (iv.begin (), ECIES_ENC_BLK_SIZE);
|
||||
|
||||
ECIES_ENC_KEY_TYPE secret;
|
||||
ECIES_HMAC_KEY_TYPE hmacKey;
|
||||
ECIES_ENC_KEY_TYPE secret;
|
||||
ECIES_HMAC_KEY_TYPE hmacKey;
|
||||
|
||||
getECIESSecret(otherKey, secret, hmacKey);
|
||||
ECIES_HMAC_TYPE hmac = makeHMAC(hmacKey, plaintext);
|
||||
hmacKey.zero();
|
||||
getECIESSecret (otherKey, secret, hmacKey);
|
||||
ECIES_HMAC_TYPE hmac = makeHMAC (hmacKey, plaintext);
|
||||
hmacKey.zero ();
|
||||
|
||||
EVP_CIPHER_CTX ctx;
|
||||
EVP_CIPHER_CTX_init(&ctx);
|
||||
EVP_CIPHER_CTX ctx;
|
||||
EVP_CIPHER_CTX_init (&ctx);
|
||||
|
||||
if (EVP_EncryptInit_ex(&ctx, ECIES_ENC_ALGO, NULL, secret.begin(), iv.begin()) != 1)
|
||||
{
|
||||
EVP_CIPHER_CTX_cleanup(&ctx);
|
||||
secret.zero();
|
||||
throw std::runtime_error("init cipher ctx");
|
||||
}
|
||||
secret.zero();
|
||||
if (EVP_EncryptInit_ex (&ctx, ECIES_ENC_ALGO, NULL, secret.begin (), iv.begin ()) != 1)
|
||||
{
|
||||
EVP_CIPHER_CTX_cleanup (&ctx);
|
||||
secret.zero ();
|
||||
throw std::runtime_error ("init cipher ctx");
|
||||
}
|
||||
|
||||
Blob out(plaintext.size() + ECIES_HMAC_SIZE + ECIES_ENC_KEY_SIZE + ECIES_ENC_BLK_SIZE, 0);
|
||||
int len = 0, bytesWritten;
|
||||
secret.zero ();
|
||||
|
||||
// output IV
|
||||
memcpy(&(out.front()), iv.begin(), ECIES_ENC_BLK_SIZE);
|
||||
len = ECIES_ENC_BLK_SIZE;
|
||||
Blob out (plaintext.size () + ECIES_HMAC_SIZE + ECIES_ENC_KEY_SIZE + ECIES_ENC_BLK_SIZE, 0);
|
||||
int len = 0, bytesWritten;
|
||||
|
||||
// Encrypt/output HMAC
|
||||
bytesWritten = out.capacity() - len;
|
||||
assert(bytesWritten>0);
|
||||
if (EVP_EncryptUpdate(&ctx, &(out.front()) + len, &bytesWritten, hmac.begin(), ECIES_HMAC_SIZE) < 0)
|
||||
{
|
||||
EVP_CIPHER_CTX_cleanup(&ctx);
|
||||
throw std::runtime_error("");
|
||||
}
|
||||
len += bytesWritten;
|
||||
// output IV
|
||||
memcpy (& (out.front ()), iv.begin (), ECIES_ENC_BLK_SIZE);
|
||||
len = ECIES_ENC_BLK_SIZE;
|
||||
|
||||
// encrypt/output plaintext
|
||||
bytesWritten = out.capacity() - len;
|
||||
assert(bytesWritten>0);
|
||||
if (EVP_EncryptUpdate(&ctx, &(out.front()) + len, &bytesWritten, &(plaintext.front()), plaintext.size()) < 0)
|
||||
{
|
||||
EVP_CIPHER_CTX_cleanup(&ctx);
|
||||
throw std::runtime_error("");
|
||||
}
|
||||
len += bytesWritten;
|
||||
// Encrypt/output HMAC
|
||||
bytesWritten = out.capacity () - len;
|
||||
assert (bytesWritten > 0);
|
||||
|
||||
// finalize
|
||||
bytesWritten = out.capacity() - len;
|
||||
if (EVP_EncryptFinal_ex(&ctx, &(out.front()) + len, &bytesWritten) < 0)
|
||||
{
|
||||
EVP_CIPHER_CTX_cleanup(&ctx);
|
||||
throw std::runtime_error("encryption error");
|
||||
}
|
||||
len += bytesWritten;
|
||||
if (EVP_EncryptUpdate (&ctx, & (out.front ()) + len, &bytesWritten, hmac.begin (), ECIES_HMAC_SIZE) < 0)
|
||||
{
|
||||
EVP_CIPHER_CTX_cleanup (&ctx);
|
||||
throw std::runtime_error ("");
|
||||
}
|
||||
|
||||
// Output contains: IV, encrypted HMAC, encrypted data, encrypted padding
|
||||
assert(len <= (plaintext.size() + ECIES_HMAC_SIZE + (2 * ECIES_ENC_BLK_SIZE)));
|
||||
assert(len >= (plaintext.size() + ECIES_HMAC_SIZE + ECIES_ENC_BLK_SIZE)); // IV, HMAC, data
|
||||
out.resize(len);
|
||||
EVP_CIPHER_CTX_cleanup(&ctx);
|
||||
return out;
|
||||
len += bytesWritten;
|
||||
|
||||
// encrypt/output plaintext
|
||||
bytesWritten = out.capacity () - len;
|
||||
assert (bytesWritten > 0);
|
||||
|
||||
if (EVP_EncryptUpdate (&ctx, & (out.front ()) + len, &bytesWritten, & (plaintext.front ()), plaintext.size ()) < 0)
|
||||
{
|
||||
EVP_CIPHER_CTX_cleanup (&ctx);
|
||||
throw std::runtime_error ("");
|
||||
}
|
||||
|
||||
len += bytesWritten;
|
||||
|
||||
// finalize
|
||||
bytesWritten = out.capacity () - len;
|
||||
|
||||
if (EVP_EncryptFinal_ex (&ctx, & (out.front ()) + len, &bytesWritten) < 0)
|
||||
{
|
||||
EVP_CIPHER_CTX_cleanup (&ctx);
|
||||
throw std::runtime_error ("encryption error");
|
||||
}
|
||||
|
||||
len += bytesWritten;
|
||||
|
||||
// Output contains: IV, encrypted HMAC, encrypted data, encrypted padding
|
||||
assert (len <= (plaintext.size () + ECIES_HMAC_SIZE + (2 * ECIES_ENC_BLK_SIZE)));
|
||||
assert (len >= (plaintext.size () + ECIES_HMAC_SIZE + ECIES_ENC_BLK_SIZE)); // IV, HMAC, data
|
||||
out.resize (len);
|
||||
EVP_CIPHER_CTX_cleanup (&ctx);
|
||||
return out;
|
||||
}
|
||||
|
||||
Blob CKey::decryptECIES(CKey& otherKey, Blob const& ciphertext)
|
||||
Blob CKey::decryptECIES (CKey& otherKey, Blob const& ciphertext)
|
||||
{
|
||||
// minimum ciphertext = IV + HMAC + 1 block
|
||||
if (ciphertext.size() < ((2 * ECIES_ENC_BLK_SIZE) + ECIES_HMAC_SIZE) )
|
||||
throw std::runtime_error("ciphertext too short");
|
||||
// minimum ciphertext = IV + HMAC + 1 block
|
||||
if (ciphertext.size () < ((2 * ECIES_ENC_BLK_SIZE) + ECIES_HMAC_SIZE) )
|
||||
throw std::runtime_error ("ciphertext too short");
|
||||
|
||||
// extract IV
|
||||
ECIES_ENC_IV_TYPE iv;
|
||||
memcpy(iv.begin(), &(ciphertext.front()), ECIES_ENC_BLK_SIZE);
|
||||
// extract IV
|
||||
ECIES_ENC_IV_TYPE iv;
|
||||
memcpy (iv.begin (), & (ciphertext.front ()), ECIES_ENC_BLK_SIZE);
|
||||
|
||||
// begin decrypting
|
||||
EVP_CIPHER_CTX ctx;
|
||||
EVP_CIPHER_CTX_init(&ctx);
|
||||
// begin decrypting
|
||||
EVP_CIPHER_CTX ctx;
|
||||
EVP_CIPHER_CTX_init (&ctx);
|
||||
|
||||
ECIES_ENC_KEY_TYPE secret;
|
||||
ECIES_HMAC_KEY_TYPE hmacKey;
|
||||
getECIESSecret(otherKey, secret, hmacKey);
|
||||
ECIES_ENC_KEY_TYPE secret;
|
||||
ECIES_HMAC_KEY_TYPE hmacKey;
|
||||
getECIESSecret (otherKey, secret, hmacKey);
|
||||
|
||||
if (EVP_DecryptInit_ex(&ctx, ECIES_ENC_ALGO, NULL, secret.begin(), iv.begin()) != 1)
|
||||
{
|
||||
secret.zero();
|
||||
hmacKey.zero();
|
||||
EVP_CIPHER_CTX_cleanup(&ctx);
|
||||
throw std::runtime_error("unable to init cipher");
|
||||
}
|
||||
if (EVP_DecryptInit_ex (&ctx, ECIES_ENC_ALGO, NULL, secret.begin (), iv.begin ()) != 1)
|
||||
{
|
||||
secret.zero ();
|
||||
hmacKey.zero ();
|
||||
EVP_CIPHER_CTX_cleanup (&ctx);
|
||||
throw std::runtime_error ("unable to init cipher");
|
||||
}
|
||||
|
||||
// decrypt mac
|
||||
ECIES_HMAC_TYPE hmac;
|
||||
int outlen = ECIES_HMAC_SIZE;
|
||||
if ( (EVP_DecryptUpdate(&ctx, hmac.begin(), &outlen,
|
||||
&(ciphertext.front()) + ECIES_ENC_BLK_SIZE, ECIES_HMAC_SIZE + 1) != 1) || (outlen != ECIES_HMAC_SIZE) )
|
||||
{
|
||||
secret.zero();
|
||||
hmacKey.zero();
|
||||
EVP_CIPHER_CTX_cleanup(&ctx);
|
||||
throw std::runtime_error("unable to extract hmac");
|
||||
}
|
||||
// decrypt mac
|
||||
ECIES_HMAC_TYPE hmac;
|
||||
int outlen = ECIES_HMAC_SIZE;
|
||||
|
||||
// decrypt plaintext (after IV and encrypted mac)
|
||||
Blob plaintext(ciphertext.size() - ECIES_HMAC_SIZE - ECIES_ENC_BLK_SIZE);
|
||||
outlen = plaintext.size();
|
||||
if (EVP_DecryptUpdate(&ctx, &(plaintext.front()), &outlen,
|
||||
&(ciphertext.front()) + ECIES_ENC_BLK_SIZE + ECIES_HMAC_SIZE + 1,
|
||||
ciphertext.size() - ECIES_ENC_BLK_SIZE - ECIES_HMAC_SIZE - 1) != 1)
|
||||
{
|
||||
secret.zero();
|
||||
hmacKey.zero();
|
||||
EVP_CIPHER_CTX_cleanup(&ctx);
|
||||
throw std::runtime_error("unable to extract plaintext");
|
||||
}
|
||||
if ( (EVP_DecryptUpdate (&ctx, hmac.begin (), &outlen,
|
||||
& (ciphertext.front ()) + ECIES_ENC_BLK_SIZE, ECIES_HMAC_SIZE + 1) != 1) || (outlen != ECIES_HMAC_SIZE) )
|
||||
{
|
||||
secret.zero ();
|
||||
hmacKey.zero ();
|
||||
EVP_CIPHER_CTX_cleanup (&ctx);
|
||||
throw std::runtime_error ("unable to extract hmac");
|
||||
}
|
||||
|
||||
// decrypt padding
|
||||
int flen = 0;
|
||||
if (EVP_DecryptFinal(&ctx, &(plaintext.front()) + outlen, &flen) != 1)
|
||||
{
|
||||
secret.zero();
|
||||
hmacKey.zero();
|
||||
EVP_CIPHER_CTX_cleanup(&ctx);
|
||||
throw std::runtime_error("plaintext had bad padding");
|
||||
}
|
||||
plaintext.resize(flen + outlen);
|
||||
// decrypt plaintext (after IV and encrypted mac)
|
||||
Blob plaintext (ciphertext.size () - ECIES_HMAC_SIZE - ECIES_ENC_BLK_SIZE);
|
||||
outlen = plaintext.size ();
|
||||
|
||||
// verify integrity
|
||||
if (hmac != makeHMAC(hmacKey, plaintext))
|
||||
{
|
||||
secret.zero();
|
||||
hmacKey.zero();
|
||||
EVP_CIPHER_CTX_cleanup(&ctx);
|
||||
throw std::runtime_error("plaintext had bad hmac");
|
||||
}
|
||||
secret.zero();
|
||||
hmacKey.zero();
|
||||
if (EVP_DecryptUpdate (&ctx, & (plaintext.front ()), &outlen,
|
||||
& (ciphertext.front ()) + ECIES_ENC_BLK_SIZE + ECIES_HMAC_SIZE + 1,
|
||||
ciphertext.size () - ECIES_ENC_BLK_SIZE - ECIES_HMAC_SIZE - 1) != 1)
|
||||
{
|
||||
secret.zero ();
|
||||
hmacKey.zero ();
|
||||
EVP_CIPHER_CTX_cleanup (&ctx);
|
||||
throw std::runtime_error ("unable to extract plaintext");
|
||||
}
|
||||
|
||||
EVP_CIPHER_CTX_cleanup(&ctx);
|
||||
return plaintext;
|
||||
// decrypt padding
|
||||
int flen = 0;
|
||||
|
||||
if (EVP_DecryptFinal (&ctx, & (plaintext.front ()) + outlen, &flen) != 1)
|
||||
{
|
||||
secret.zero ();
|
||||
hmacKey.zero ();
|
||||
EVP_CIPHER_CTX_cleanup (&ctx);
|
||||
throw std::runtime_error ("plaintext had bad padding");
|
||||
}
|
||||
|
||||
plaintext.resize (flen + outlen);
|
||||
|
||||
// verify integrity
|
||||
if (hmac != makeHMAC (hmacKey, plaintext))
|
||||
{
|
||||
secret.zero ();
|
||||
hmacKey.zero ();
|
||||
EVP_CIPHER_CTX_cleanup (&ctx);
|
||||
throw std::runtime_error ("plaintext had bad hmac");
|
||||
}
|
||||
|
||||
secret.zero ();
|
||||
hmacKey.zero ();
|
||||
|
||||
EVP_CIPHER_CTX_cleanup (&ctx);
|
||||
return plaintext;
|
||||
}
|
||||
|
||||
bool checkECIES(void)
|
||||
bool checkECIES (void)
|
||||
{
|
||||
CKey senderPriv, recipientPriv, senderPub, recipientPub;
|
||||
CKey senderPriv, recipientPriv, senderPub, recipientPub;
|
||||
|
||||
for (int i = 0; i < 30000; ++i)
|
||||
{
|
||||
if ((i % 100) == 0)
|
||||
{ // generate new keys every 100 times
|
||||
// std::cerr << "new keys" << std::endl;
|
||||
senderPriv.MakeNewKey();
|
||||
recipientPriv.MakeNewKey();
|
||||
for (int i = 0; i < 30000; ++i)
|
||||
{
|
||||
if ((i % 100) == 0)
|
||||
{
|
||||
// generate new keys every 100 times
|
||||
// std::cerr << "new keys" << std::endl;
|
||||
senderPriv.MakeNewKey ();
|
||||
recipientPriv.MakeNewKey ();
|
||||
|
||||
if (!senderPub.SetPubKey(senderPriv.GetPubKey()))
|
||||
throw std::runtime_error("key error");
|
||||
if (!recipientPub.SetPubKey(recipientPriv.GetPubKey()))
|
||||
throw std::runtime_error("key error");
|
||||
}
|
||||
if (!senderPub.SetPubKey (senderPriv.GetPubKey ()))
|
||||
throw std::runtime_error ("key error");
|
||||
|
||||
// generate message
|
||||
Blob message(4096);
|
||||
int msglen = i%3000;
|
||||
if (!recipientPub.SetPubKey (recipientPriv.GetPubKey ()))
|
||||
throw std::runtime_error ("key error");
|
||||
}
|
||||
|
||||
RandomNumbers::getInstance ().fillBytes (&message.front(), msglen);
|
||||
message.resize(msglen);
|
||||
// generate message
|
||||
Blob message (4096);
|
||||
int msglen = i % 3000;
|
||||
|
||||
// encrypt message with sender's private key and recipient's public key
|
||||
Blob ciphertext = senderPriv.encryptECIES(recipientPub, message);
|
||||
RandomNumbers::getInstance ().fillBytes (&message.front (), msglen);
|
||||
message.resize (msglen);
|
||||
|
||||
// decrypt message with recipient's private key and sender's public key
|
||||
Blob decrypt = recipientPriv.decryptECIES(senderPub, ciphertext);
|
||||
// encrypt message with sender's private key and recipient's public key
|
||||
Blob ciphertext = senderPriv.encryptECIES (recipientPub, message);
|
||||
|
||||
if (decrypt != message)
|
||||
{
|
||||
assert(false);
|
||||
return false;
|
||||
}
|
||||
// std::cerr << "Msg(" << msglen << ") ok " << ciphertext.size() << std::endl;
|
||||
}
|
||||
return true;
|
||||
// decrypt message with recipient's private key and sender's public key
|
||||
Blob decrypt = recipientPriv.decryptECIES (senderPub, ciphertext);
|
||||
|
||||
if (decrypt != message)
|
||||
{
|
||||
assert (false);
|
||||
return false;
|
||||
}
|
||||
|
||||
// std::cerr << "Msg(" << msglen << ") ok " << ciphertext.size() << std::endl;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// vim:ts=4
|
||||
|
||||
@@ -12,363 +12,370 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
char const* RFC1751::s_dictionary [2048] = {
|
||||
"A", "ABE", "ACE", "ACT", "AD", "ADA", "ADD",
|
||||
"AGO", "AID", "AIM", "AIR", "ALL", "ALP", "AM", "AMY", "AN", "ANA",
|
||||
"AND", "ANN", "ANT", "ANY", "APE", "APS", "APT", "ARC", "ARE", "ARK",
|
||||
"ARM", "ART", "AS", "ASH", "ASK", "AT", "ATE", "AUG", "AUK", "AVE",
|
||||
"AWE", "AWK", "AWL", "AWN", "AX", "AYE", "BAD", "BAG", "BAH", "BAM",
|
||||
"BAN", "BAR", "BAT", "BAY", "BE", "BED", "BEE", "BEG", "BEN", "BET",
|
||||
"BEY", "BIB", "BID", "BIG", "BIN", "BIT", "BOB", "BOG", "BON", "BOO",
|
||||
"BOP", "BOW", "BOY", "BUB", "BUD", "BUG", "BUM", "BUN", "BUS", "BUT",
|
||||
"BUY", "BY", "BYE", "CAB", "CAL", "CAM", "CAN", "CAP", "CAR", "CAT",
|
||||
"CAW", "COD", "COG", "COL", "CON", "COO", "COP", "COT", "COW", "COY",
|
||||
"CRY", "CUB", "CUE", "CUP", "CUR", "CUT", "DAB", "DAD", "DAM", "DAN",
|
||||
"DAR", "DAY", "DEE", "DEL", "DEN", "DES", "DEW", "DID", "DIE", "DIG",
|
||||
"DIN", "DIP", "DO", "DOE", "DOG", "DON", "DOT", "DOW", "DRY", "DUB",
|
||||
"DUD", "DUE", "DUG", "DUN", "EAR", "EAT", "ED", "EEL", "EGG", "EGO",
|
||||
"ELI", "ELK", "ELM", "ELY", "EM", "END", "EST", "ETC", "EVA", "EVE",
|
||||
"EWE", "EYE", "FAD", "FAN", "FAR", "FAT", "FAY", "FED", "FEE", "FEW",
|
||||
"FIB", "FIG", "FIN", "FIR", "FIT", "FLO", "FLY", "FOE", "FOG", "FOR",
|
||||
"FRY", "FUM", "FUN", "FUR", "GAB", "GAD", "GAG", "GAL", "GAM", "GAP",
|
||||
"GAS", "GAY", "GEE", "GEL", "GEM", "GET", "GIG", "GIL", "GIN", "GO",
|
||||
"GOT", "GUM", "GUN", "GUS", "GUT", "GUY", "GYM", "GYP", "HA", "HAD",
|
||||
"HAL", "HAM", "HAN", "HAP", "HAS", "HAT", "HAW", "HAY", "HE", "HEM",
|
||||
"HEN", "HER", "HEW", "HEY", "HI", "HID", "HIM", "HIP", "HIS", "HIT",
|
||||
"HO", "HOB", "HOC", "HOE", "HOG", "HOP", "HOT", "HOW", "HUB", "HUE",
|
||||
"HUG", "HUH", "HUM", "HUT", "I", "ICY", "IDA", "IF", "IKE", "ILL",
|
||||
"INK", "INN", "IO", "ION", "IQ", "IRA", "IRE", "IRK", "IS", "IT", "ITS",
|
||||
"IVY", "JAB", "JAG", "JAM", "JAN", "JAR", "JAW", "JAY", "JET", "JIG",
|
||||
"JIM", "JO", "JOB", "JOE", "JOG", "JOT", "JOY", "JUG", "JUT", "KAY",
|
||||
"KEG", "KEN", "KEY", "KID", "KIM", "KIN", "KIT", "LA", "LAB", "LAC",
|
||||
"LAD", "LAG", "LAM", "LAP", "LAW", "LAY", "LEA", "LED", "LEE", "LEG",
|
||||
"LEN", "LEO", "LET", "LEW", "LID", "LIE", "LIN", "LIP", "LIT", "LO",
|
||||
"LOB", "LOG", "LOP", "LOS", "LOT", "LOU", "LOW", "LOY", "LUG", "LYE",
|
||||
"MA", "MAC", "MAD", "MAE", "MAN", "MAO", "MAP", "MAT", "MAW", "MAY",
|
||||
"ME", "MEG", "MEL", "MEN", "MET", "MEW", "MID", "MIN", "MIT", "MOB",
|
||||
"MOD", "MOE", "MOO", "MOP", "MOS", "MOT", "MOW", "MUD", "MUG", "MUM",
|
||||
"MY", "NAB", "NAG", "NAN", "NAP", "NAT", "NAY", "NE", "NED", "NEE",
|
||||
"NET", "NEW", "NIB", "NIL", "NIP", "NIT", "NO", "NOB", "NOD", "NON",
|
||||
"NOR", "NOT", "NOV", "NOW", "NU", "NUN", "NUT", "O", "OAF", "OAK",
|
||||
"OAR", "OAT", "ODD", "ODE", "OF", "OFF", "OFT", "OH", "OIL", "OK",
|
||||
"OLD", "ON", "ONE", "OR", "ORB", "ORE", "ORR", "OS", "OTT", "OUR",
|
||||
"OUT", "OVA", "OW", "OWE", "OWL", "OWN", "OX", "PA", "PAD", "PAL",
|
||||
"PAM", "PAN", "PAP", "PAR", "PAT", "PAW", "PAY", "PEA", "PEG", "PEN",
|
||||
"PEP", "PER", "PET", "PEW", "PHI", "PI", "PIE", "PIN", "PIT", "PLY",
|
||||
"PO", "POD", "POE", "POP", "POT", "POW", "PRO", "PRY", "PUB", "PUG",
|
||||
"PUN", "PUP", "PUT", "QUO", "RAG", "RAM", "RAN", "RAP", "RAT", "RAW",
|
||||
"RAY", "REB", "RED", "REP", "RET", "RIB", "RID", "RIG", "RIM", "RIO",
|
||||
"RIP", "ROB", "ROD", "ROE", "RON", "ROT", "ROW", "ROY", "RUB", "RUE",
|
||||
"RUG", "RUM", "RUN", "RYE", "SAC", "SAD", "SAG", "SAL", "SAM", "SAN",
|
||||
"SAP", "SAT", "SAW", "SAY", "SEA", "SEC", "SEE", "SEN", "SET", "SEW",
|
||||
"SHE", "SHY", "SIN", "SIP", "SIR", "SIS", "SIT", "SKI", "SKY", "SLY",
|
||||
"SO", "SOB", "SOD", "SON", "SOP", "SOW", "SOY", "SPA", "SPY", "SUB",
|
||||
"SUD", "SUE", "SUM", "SUN", "SUP", "TAB", "TAD", "TAG", "TAN", "TAP",
|
||||
"TAR", "TEA", "TED", "TEE", "TEN", "THE", "THY", "TIC", "TIE", "TIM",
|
||||
"TIN", "TIP", "TO", "TOE", "TOG", "TOM", "TON", "TOO", "TOP", "TOW",
|
||||
"TOY", "TRY", "TUB", "TUG", "TUM", "TUN", "TWO", "UN", "UP", "US",
|
||||
"USE", "VAN", "VAT", "VET", "VIE", "WAD", "WAG", "WAR", "WAS", "WAY",
|
||||
"WE", "WEB", "WED", "WEE", "WET", "WHO", "WHY", "WIN", "WIT", "WOK",
|
||||
"WON", "WOO", "WOW", "WRY", "WU", "YAM", "YAP", "YAW", "YE", "YEA",
|
||||
"YES", "YET", "YOU", "ABED", "ABEL", "ABET", "ABLE", "ABUT", "ACHE",
|
||||
"ACID", "ACME", "ACRE", "ACTA", "ACTS", "ADAM", "ADDS", "ADEN", "AFAR",
|
||||
"AFRO", "AGEE", "AHEM", "AHOY", "AIDA", "AIDE", "AIDS", "AIRY", "AJAR",
|
||||
"AKIN", "ALAN", "ALEC", "ALGA", "ALIA", "ALLY", "ALMA", "ALOE", "ALSO",
|
||||
"ALTO", "ALUM", "ALVA", "AMEN", "AMES", "AMID", "AMMO", "AMOK", "AMOS",
|
||||
"AMRA", "ANDY", "ANEW", "ANNA", "ANNE", "ANTE", "ANTI", "AQUA", "ARAB",
|
||||
"ARCH", "AREA", "ARGO", "ARID", "ARMY", "ARTS", "ARTY", "ASIA", "ASKS",
|
||||
"ATOM", "AUNT", "AURA", "AUTO", "AVER", "AVID", "AVIS", "AVON", "AVOW",
|
||||
"AWAY", "AWRY", "BABE", "BABY", "BACH", "BACK", "BADE", "BAIL", "BAIT",
|
||||
"BAKE", "BALD", "BALE", "BALI", "BALK", "BALL", "BALM", "BAND", "BANE",
|
||||
"BANG", "BANK", "BARB", "BARD", "BARE", "BARK", "BARN", "BARR", "BASE",
|
||||
"BASH", "BASK", "BASS", "BATE", "BATH", "BAWD", "BAWL", "BEAD", "BEAK",
|
||||
"BEAM", "BEAN", "BEAR", "BEAT", "BEAU", "BECK", "BEEF", "BEEN", "BEER",
|
||||
"BEET", "BELA", "BELL", "BELT", "BEND", "BENT", "BERG", "BERN", "BERT",
|
||||
"BESS", "BEST", "BETA", "BETH", "BHOY", "BIAS", "BIDE", "BIEN", "BILE",
|
||||
"BILK", "BILL", "BIND", "BING", "BIRD", "BITE", "BITS", "BLAB", "BLAT",
|
||||
"BLED", "BLEW", "BLOB", "BLOC", "BLOT", "BLOW", "BLUE", "BLUM", "BLUR",
|
||||
"BOAR", "BOAT", "BOCA", "BOCK", "BODE", "BODY", "BOGY", "BOHR", "BOIL",
|
||||
"BOLD", "BOLO", "BOLT", "BOMB", "BONA", "BOND", "BONE", "BONG", "BONN",
|
||||
"BONY", "BOOK", "BOOM", "BOON", "BOOT", "BORE", "BORG", "BORN", "BOSE",
|
||||
"BOSS", "BOTH", "BOUT", "BOWL", "BOYD", "BRAD", "BRAE", "BRAG", "BRAN",
|
||||
"BRAY", "BRED", "BREW", "BRIG", "BRIM", "BROW", "BUCK", "BUDD", "BUFF",
|
||||
"BULB", "BULK", "BULL", "BUNK", "BUNT", "BUOY", "BURG", "BURL", "BURN",
|
||||
"BURR", "BURT", "BURY", "BUSH", "BUSS", "BUST", "BUSY", "BYTE", "CADY",
|
||||
"CAFE", "CAGE", "CAIN", "CAKE", "CALF", "CALL", "CALM", "CAME", "CANE",
|
||||
"CANT", "CARD", "CARE", "CARL", "CARR", "CART", "CASE", "CASH", "CASK",
|
||||
"CAST", "CAVE", "CEIL", "CELL", "CENT", "CERN", "CHAD", "CHAR", "CHAT",
|
||||
"CHAW", "CHEF", "CHEN", "CHEW", "CHIC", "CHIN", "CHOU", "CHOW", "CHUB",
|
||||
"CHUG", "CHUM", "CITE", "CITY", "CLAD", "CLAM", "CLAN", "CLAW", "CLAY",
|
||||
"CLOD", "CLOG", "CLOT", "CLUB", "CLUE", "COAL", "COAT", "COCA", "COCK",
|
||||
"COCO", "CODA", "CODE", "CODY", "COED", "COIL", "COIN", "COKE", "COLA",
|
||||
"COLD", "COLT", "COMA", "COMB", "COME", "COOK", "COOL", "COON", "COOT",
|
||||
"CORD", "CORE", "CORK", "CORN", "COST", "COVE", "COWL", "CRAB", "CRAG",
|
||||
"CRAM", "CRAY", "CREW", "CRIB", "CROW", "CRUD", "CUBA", "CUBE", "CUFF",
|
||||
"CULL", "CULT", "CUNY", "CURB", "CURD", "CURE", "CURL", "CURT", "CUTS",
|
||||
"DADE", "DALE", "DAME", "DANA", "DANE", "DANG", "DANK", "DARE", "DARK",
|
||||
"DARN", "DART", "DASH", "DATA", "DATE", "DAVE", "DAVY", "DAWN", "DAYS",
|
||||
"DEAD", "DEAF", "DEAL", "DEAN", "DEAR", "DEBT", "DECK", "DEED", "DEEM",
|
||||
"DEER", "DEFT", "DEFY", "DELL", "DENT", "DENY", "DESK", "DIAL", "DICE",
|
||||
"DIED", "DIET", "DIME", "DINE", "DING", "DINT", "DIRE", "DIRT", "DISC",
|
||||
"DISH", "DISK", "DIVE", "DOCK", "DOES", "DOLE", "DOLL", "DOLT", "DOME",
|
||||
"DONE", "DOOM", "DOOR", "DORA", "DOSE", "DOTE", "DOUG", "DOUR", "DOVE",
|
||||
"DOWN", "DRAB", "DRAG", "DRAM", "DRAW", "DREW", "DRUB", "DRUG", "DRUM",
|
||||
"DUAL", "DUCK", "DUCT", "DUEL", "DUET", "DUKE", "DULL", "DUMB", "DUNE",
|
||||
"DUNK", "DUSK", "DUST", "DUTY", "EACH", "EARL", "EARN", "EASE", "EAST",
|
||||
"EASY", "EBEN", "ECHO", "EDDY", "EDEN", "EDGE", "EDGY", "EDIT", "EDNA",
|
||||
"EGAN", "ELAN", "ELBA", "ELLA", "ELSE", "EMIL", "EMIT", "EMMA", "ENDS",
|
||||
"ERIC", "EROS", "EVEN", "EVER", "EVIL", "EYED", "FACE", "FACT", "FADE",
|
||||
"FAIL", "FAIN", "FAIR", "FAKE", "FALL", "FAME", "FANG", "FARM", "FAST",
|
||||
"FATE", "FAWN", "FEAR", "FEAT", "FEED", "FEEL", "FEET", "FELL", "FELT",
|
||||
"FEND", "FERN", "FEST", "FEUD", "FIEF", "FIGS", "FILE", "FILL", "FILM",
|
||||
"FIND", "FINE", "FINK", "FIRE", "FIRM", "FISH", "FISK", "FIST", "FITS",
|
||||
"FIVE", "FLAG", "FLAK", "FLAM", "FLAT", "FLAW", "FLEA", "FLED", "FLEW",
|
||||
"FLIT", "FLOC", "FLOG", "FLOW", "FLUB", "FLUE", "FOAL", "FOAM", "FOGY",
|
||||
"FOIL", "FOLD", "FOLK", "FOND", "FONT", "FOOD", "FOOL", "FOOT", "FORD",
|
||||
"FORE", "FORK", "FORM", "FORT", "FOSS", "FOUL", "FOUR", "FOWL", "FRAU",
|
||||
"FRAY", "FRED", "FREE", "FRET", "FREY", "FROG", "FROM", "FUEL", "FULL",
|
||||
"FUME", "FUND", "FUNK", "FURY", "FUSE", "FUSS", "GAFF", "GAGE", "GAIL",
|
||||
"GAIN", "GAIT", "GALA", "GALE", "GALL", "GALT", "GAME", "GANG", "GARB",
|
||||
"GARY", "GASH", "GATE", "GAUL", "GAUR", "GAVE", "GAWK", "GEAR", "GELD",
|
||||
"GENE", "GENT", "GERM", "GETS", "GIBE", "GIFT", "GILD", "GILL", "GILT",
|
||||
"GINA", "GIRD", "GIRL", "GIST", "GIVE", "GLAD", "GLEE", "GLEN", "GLIB",
|
||||
"GLOB", "GLOM", "GLOW", "GLUE", "GLUM", "GLUT", "GOAD", "GOAL", "GOAT",
|
||||
"GOER", "GOES", "GOLD", "GOLF", "GONE", "GONG", "GOOD", "GOOF", "GORE",
|
||||
"GORY", "GOSH", "GOUT", "GOWN", "GRAB", "GRAD", "GRAY", "GREG", "GREW",
|
||||
"GREY", "GRID", "GRIM", "GRIN", "GRIT", "GROW", "GRUB", "GULF", "GULL",
|
||||
"GUNK", "GURU", "GUSH", "GUST", "GWEN", "GWYN", "HAAG", "HAAS", "HACK",
|
||||
"HAIL", "HAIR", "HALE", "HALF", "HALL", "HALO", "HALT", "HAND", "HANG",
|
||||
"HANK", "HANS", "HARD", "HARK", "HARM", "HART", "HASH", "HAST", "HATE",
|
||||
"HATH", "HAUL", "HAVE", "HAWK", "HAYS", "HEAD", "HEAL", "HEAR", "HEAT",
|
||||
"HEBE", "HECK", "HEED", "HEEL", "HEFT", "HELD", "HELL", "HELM", "HERB",
|
||||
"HERD", "HERE", "HERO", "HERS", "HESS", "HEWN", "HICK", "HIDE", "HIGH",
|
||||
"HIKE", "HILL", "HILT", "HIND", "HINT", "HIRE", "HISS", "HIVE", "HOBO",
|
||||
"HOCK", "HOFF", "HOLD", "HOLE", "HOLM", "HOLT", "HOME", "HONE", "HONK",
|
||||
"HOOD", "HOOF", "HOOK", "HOOT", "HORN", "HOSE", "HOST", "HOUR", "HOVE",
|
||||
"HOWE", "HOWL", "HOYT", "HUCK", "HUED", "HUFF", "HUGE", "HUGH", "HUGO",
|
||||
"HULK", "HULL", "HUNK", "HUNT", "HURD", "HURL", "HURT", "HUSH", "HYDE",
|
||||
"HYMN", "IBIS", "ICON", "IDEA", "IDLE", "IFFY", "INCA", "INCH", "INTO",
|
||||
"IONS", "IOTA", "IOWA", "IRIS", "IRMA", "IRON", "ISLE", "ITCH", "ITEM",
|
||||
"IVAN", "JACK", "JADE", "JAIL", "JAKE", "JANE", "JAVA", "JEAN", "JEFF",
|
||||
"JERK", "JESS", "JEST", "JIBE", "JILL", "JILT", "JIVE", "JOAN", "JOBS",
|
||||
"JOCK", "JOEL", "JOEY", "JOHN", "JOIN", "JOKE", "JOLT", "JOVE", "JUDD",
|
||||
"JUDE", "JUDO", "JUDY", "JUJU", "JUKE", "JULY", "JUNE", "JUNK", "JUNO",
|
||||
"JURY", "JUST", "JUTE", "KAHN", "KALE", "KANE", "KANT", "KARL", "KATE",
|
||||
"KEEL", "KEEN", "KENO", "KENT", "KERN", "KERR", "KEYS", "KICK", "KILL",
|
||||
"KIND", "KING", "KIRK", "KISS", "KITE", "KLAN", "KNEE", "KNEW", "KNIT",
|
||||
"KNOB", "KNOT", "KNOW", "KOCH", "KONG", "KUDO", "KURD", "KURT", "KYLE",
|
||||
"LACE", "LACK", "LACY", "LADY", "LAID", "LAIN", "LAIR", "LAKE", "LAMB",
|
||||
"LAME", "LAND", "LANE", "LANG", "LARD", "LARK", "LASS", "LAST", "LATE",
|
||||
"LAUD", "LAVA", "LAWN", "LAWS", "LAYS", "LEAD", "LEAF", "LEAK", "LEAN",
|
||||
"LEAR", "LEEK", "LEER", "LEFT", "LEND", "LENS", "LENT", "LEON", "LESK",
|
||||
"LESS", "LEST", "LETS", "LIAR", "LICE", "LICK", "LIED", "LIEN", "LIES",
|
||||
"LIEU", "LIFE", "LIFT", "LIKE", "LILA", "LILT", "LILY", "LIMA", "LIMB",
|
||||
"LIME", "LIND", "LINE", "LINK", "LINT", "LION", "LISA", "LIST", "LIVE",
|
||||
"LOAD", "LOAF", "LOAM", "LOAN", "LOCK", "LOFT", "LOGE", "LOIS", "LOLA",
|
||||
"LONE", "LONG", "LOOK", "LOON", "LOOT", "LORD", "LORE", "LOSE", "LOSS",
|
||||
"LOST", "LOUD", "LOVE", "LOWE", "LUCK", "LUCY", "LUGE", "LUKE", "LULU",
|
||||
"LUND", "LUNG", "LURA", "LURE", "LURK", "LUSH", "LUST", "LYLE", "LYNN",
|
||||
"LYON", "LYRA", "MACE", "MADE", "MAGI", "MAID", "MAIL", "MAIN", "MAKE",
|
||||
"MALE", "MALI", "MALL", "MALT", "MANA", "MANN", "MANY", "MARC", "MARE",
|
||||
"MARK", "MARS", "MART", "MARY", "MASH", "MASK", "MASS", "MAST", "MATE",
|
||||
"MATH", "MAUL", "MAYO", "MEAD", "MEAL", "MEAN", "MEAT", "MEEK", "MEET",
|
||||
"MELD", "MELT", "MEMO", "MEND", "MENU", "MERT", "MESH", "MESS", "MICE",
|
||||
"MIKE", "MILD", "MILE", "MILK", "MILL", "MILT", "MIMI", "MIND", "MINE",
|
||||
"MINI", "MINK", "MINT", "MIRE", "MISS", "MIST", "MITE", "MITT", "MOAN",
|
||||
"MOAT", "MOCK", "MODE", "MOLD", "MOLE", "MOLL", "MOLT", "MONA", "MONK",
|
||||
"MONT", "MOOD", "MOON", "MOOR", "MOOT", "MORE", "MORN", "MORT", "MOSS",
|
||||
"MOST", "MOTH", "MOVE", "MUCH", "MUCK", "MUDD", "MUFF", "MULE", "MULL",
|
||||
"MURK", "MUSH", "MUST", "MUTE", "MUTT", "MYRA", "MYTH", "NAGY", "NAIL",
|
||||
"NAIR", "NAME", "NARY", "NASH", "NAVE", "NAVY", "NEAL", "NEAR", "NEAT",
|
||||
"NECK", "NEED", "NEIL", "NELL", "NEON", "NERO", "NESS", "NEST", "NEWS",
|
||||
"NEWT", "NIBS", "NICE", "NICK", "NILE", "NINA", "NINE", "NOAH", "NODE",
|
||||
"NOEL", "NOLL", "NONE", "NOOK", "NOON", "NORM", "NOSE", "NOTE", "NOUN",
|
||||
"NOVA", "NUDE", "NULL", "NUMB", "OATH", "OBEY", "OBOE", "ODIN", "OHIO",
|
||||
"OILY", "OINT", "OKAY", "OLAF", "OLDY", "OLGA", "OLIN", "OMAN", "OMEN",
|
||||
"OMIT", "ONCE", "ONES", "ONLY", "ONTO", "ONUS", "ORAL", "ORGY", "OSLO",
|
||||
"OTIS", "OTTO", "OUCH", "OUST", "OUTS", "OVAL", "OVEN", "OVER", "OWLY",
|
||||
"OWNS", "QUAD", "QUIT", "QUOD", "RACE", "RACK", "RACY", "RAFT", "RAGE",
|
||||
"RAID", "RAIL", "RAIN", "RAKE", "RANK", "RANT", "RARE", "RASH", "RATE",
|
||||
"RAVE", "RAYS", "READ", "REAL", "REAM", "REAR", "RECK", "REED", "REEF",
|
||||
"REEK", "REEL", "REID", "REIN", "RENA", "REND", "RENT", "REST", "RICE",
|
||||
"RICH", "RICK", "RIDE", "RIFT", "RILL", "RIME", "RING", "RINK", "RISE",
|
||||
"RISK", "RITE", "ROAD", "ROAM", "ROAR", "ROBE", "ROCK", "RODE", "ROIL",
|
||||
"ROLL", "ROME", "ROOD", "ROOF", "ROOK", "ROOM", "ROOT", "ROSA", "ROSE",
|
||||
"ROSS", "ROSY", "ROTH", "ROUT", "ROVE", "ROWE", "ROWS", "RUBE", "RUBY",
|
||||
"RUDE", "RUDY", "RUIN", "RULE", "RUNG", "RUNS", "RUNT", "RUSE", "RUSH",
|
||||
"RUSK", "RUSS", "RUST", "RUTH", "SACK", "SAFE", "SAGE", "SAID", "SAIL",
|
||||
"SALE", "SALK", "SALT", "SAME", "SAND", "SANE", "SANG", "SANK", "SARA",
|
||||
"SAUL", "SAVE", "SAYS", "SCAN", "SCAR", "SCAT", "SCOT", "SEAL", "SEAM",
|
||||
"SEAR", "SEAT", "SEED", "SEEK", "SEEM", "SEEN", "SEES", "SELF", "SELL",
|
||||
"SEND", "SENT", "SETS", "SEWN", "SHAG", "SHAM", "SHAW", "SHAY", "SHED",
|
||||
"SHIM", "SHIN", "SHOD", "SHOE", "SHOT", "SHOW", "SHUN", "SHUT", "SICK",
|
||||
"SIDE", "SIFT", "SIGH", "SIGN", "SILK", "SILL", "SILO", "SILT", "SINE",
|
||||
"SING", "SINK", "SIRE", "SITE", "SITS", "SITU", "SKAT", "SKEW", "SKID",
|
||||
"SKIM", "SKIN", "SKIT", "SLAB", "SLAM", "SLAT", "SLAY", "SLED", "SLEW",
|
||||
"SLID", "SLIM", "SLIT", "SLOB", "SLOG", "SLOT", "SLOW", "SLUG", "SLUM",
|
||||
"SLUR", "SMOG", "SMUG", "SNAG", "SNOB", "SNOW", "SNUB", "SNUG", "SOAK",
|
||||
"SOAR", "SOCK", "SODA", "SOFA", "SOFT", "SOIL", "SOLD", "SOME", "SONG",
|
||||
"SOON", "SOOT", "SORE", "SORT", "SOUL", "SOUR", "SOWN", "STAB", "STAG",
|
||||
"STAN", "STAR", "STAY", "STEM", "STEW", "STIR", "STOW", "STUB", "STUN",
|
||||
"SUCH", "SUDS", "SUIT", "SULK", "SUMS", "SUNG", "SUNK", "SURE", "SURF",
|
||||
"SWAB", "SWAG", "SWAM", "SWAN", "SWAT", "SWAY", "SWIM", "SWUM", "TACK",
|
||||
"TACT", "TAIL", "TAKE", "TALE", "TALK", "TALL", "TANK", "TASK", "TATE",
|
||||
"TAUT", "TEAL", "TEAM", "TEAR", "TECH", "TEEM", "TEEN", "TEET", "TELL",
|
||||
"TEND", "TENT", "TERM", "TERN", "TESS", "TEST", "THAN", "THAT", "THEE",
|
||||
"THEM", "THEN", "THEY", "THIN", "THIS", "THUD", "THUG", "TICK", "TIDE",
|
||||
"TIDY", "TIED", "TIER", "TILE", "TILL", "TILT", "TIME", "TINA", "TINE",
|
||||
"TINT", "TINY", "TIRE", "TOAD", "TOGO", "TOIL", "TOLD", "TOLL", "TONE",
|
||||
"TONG", "TONY", "TOOK", "TOOL", "TOOT", "TORE", "TORN", "TOTE", "TOUR",
|
||||
"TOUT", "TOWN", "TRAG", "TRAM", "TRAY", "TREE", "TREK", "TRIG", "TRIM",
|
||||
"TRIO", "TROD", "TROT", "TROY", "TRUE", "TUBA", "TUBE", "TUCK", "TUFT",
|
||||
"TUNA", "TUNE", "TUNG", "TURF", "TURN", "TUSK", "TWIG", "TWIN", "TWIT",
|
||||
"ULAN", "UNIT", "URGE", "USED", "USER", "USES", "UTAH", "VAIL", "VAIN",
|
||||
"VALE", "VARY", "VASE", "VAST", "VEAL", "VEDA", "VEIL", "VEIN", "VEND",
|
||||
"VENT", "VERB", "VERY", "VETO", "VICE", "VIEW", "VINE", "VISE", "VOID",
|
||||
"VOLT", "VOTE", "WACK", "WADE", "WAGE", "WAIL", "WAIT", "WAKE", "WALE",
|
||||
"WALK", "WALL", "WALT", "WAND", "WANE", "WANG", "WANT", "WARD", "WARM",
|
||||
"WARN", "WART", "WASH", "WAST", "WATS", "WATT", "WAVE", "WAVY", "WAYS",
|
||||
"WEAK", "WEAL", "WEAN", "WEAR", "WEED", "WEEK", "WEIR", "WELD", "WELL",
|
||||
"WELT", "WENT", "WERE", "WERT", "WEST", "WHAM", "WHAT", "WHEE", "WHEN",
|
||||
"WHET", "WHOA", "WHOM", "WICK", "WIFE", "WILD", "WILL", "WIND", "WINE",
|
||||
"WING", "WINK", "WINO", "WIRE", "WISE", "WISH", "WITH", "WOLF", "WONT",
|
||||
"WOOD", "WOOL", "WORD", "WORE", "WORK", "WORM", "WORN", "WOVE", "WRIT",
|
||||
"WYNN", "YALE", "YANG", "YANK", "YARD", "YARN", "YAWL", "YAWN", "YEAH",
|
||||
"YEAR", "YELL", "YOGA", "YOKE"
|
||||
char const* RFC1751::s_dictionary [2048] =
|
||||
{
|
||||
"A", "ABE", "ACE", "ACT", "AD", "ADA", "ADD",
|
||||
"AGO", "AID", "AIM", "AIR", "ALL", "ALP", "AM", "AMY", "AN", "ANA",
|
||||
"AND", "ANN", "ANT", "ANY", "APE", "APS", "APT", "ARC", "ARE", "ARK",
|
||||
"ARM", "ART", "AS", "ASH", "ASK", "AT", "ATE", "AUG", "AUK", "AVE",
|
||||
"AWE", "AWK", "AWL", "AWN", "AX", "AYE", "BAD", "BAG", "BAH", "BAM",
|
||||
"BAN", "BAR", "BAT", "BAY", "BE", "BED", "BEE", "BEG", "BEN", "BET",
|
||||
"BEY", "BIB", "BID", "BIG", "BIN", "BIT", "BOB", "BOG", "BON", "BOO",
|
||||
"BOP", "BOW", "BOY", "BUB", "BUD", "BUG", "BUM", "BUN", "BUS", "BUT",
|
||||
"BUY", "BY", "BYE", "CAB", "CAL", "CAM", "CAN", "CAP", "CAR", "CAT",
|
||||
"CAW", "COD", "COG", "COL", "CON", "COO", "COP", "COT", "COW", "COY",
|
||||
"CRY", "CUB", "CUE", "CUP", "CUR", "CUT", "DAB", "DAD", "DAM", "DAN",
|
||||
"DAR", "DAY", "DEE", "DEL", "DEN", "DES", "DEW", "DID", "DIE", "DIG",
|
||||
"DIN", "DIP", "DO", "DOE", "DOG", "DON", "DOT", "DOW", "DRY", "DUB",
|
||||
"DUD", "DUE", "DUG", "DUN", "EAR", "EAT", "ED", "EEL", "EGG", "EGO",
|
||||
"ELI", "ELK", "ELM", "ELY", "EM", "END", "EST", "ETC", "EVA", "EVE",
|
||||
"EWE", "EYE", "FAD", "FAN", "FAR", "FAT", "FAY", "FED", "FEE", "FEW",
|
||||
"FIB", "FIG", "FIN", "FIR", "FIT", "FLO", "FLY", "FOE", "FOG", "FOR",
|
||||
"FRY", "FUM", "FUN", "FUR", "GAB", "GAD", "GAG", "GAL", "GAM", "GAP",
|
||||
"GAS", "GAY", "GEE", "GEL", "GEM", "GET", "GIG", "GIL", "GIN", "GO",
|
||||
"GOT", "GUM", "GUN", "GUS", "GUT", "GUY", "GYM", "GYP", "HA", "HAD",
|
||||
"HAL", "HAM", "HAN", "HAP", "HAS", "HAT", "HAW", "HAY", "HE", "HEM",
|
||||
"HEN", "HER", "HEW", "HEY", "HI", "HID", "HIM", "HIP", "HIS", "HIT",
|
||||
"HO", "HOB", "HOC", "HOE", "HOG", "HOP", "HOT", "HOW", "HUB", "HUE",
|
||||
"HUG", "HUH", "HUM", "HUT", "I", "ICY", "IDA", "IF", "IKE", "ILL",
|
||||
"INK", "INN", "IO", "ION", "IQ", "IRA", "IRE", "IRK", "IS", "IT", "ITS",
|
||||
"IVY", "JAB", "JAG", "JAM", "JAN", "JAR", "JAW", "JAY", "JET", "JIG",
|
||||
"JIM", "JO", "JOB", "JOE", "JOG", "JOT", "JOY", "JUG", "JUT", "KAY",
|
||||
"KEG", "KEN", "KEY", "KID", "KIM", "KIN", "KIT", "LA", "LAB", "LAC",
|
||||
"LAD", "LAG", "LAM", "LAP", "LAW", "LAY", "LEA", "LED", "LEE", "LEG",
|
||||
"LEN", "LEO", "LET", "LEW", "LID", "LIE", "LIN", "LIP", "LIT", "LO",
|
||||
"LOB", "LOG", "LOP", "LOS", "LOT", "LOU", "LOW", "LOY", "LUG", "LYE",
|
||||
"MA", "MAC", "MAD", "MAE", "MAN", "MAO", "MAP", "MAT", "MAW", "MAY",
|
||||
"ME", "MEG", "MEL", "MEN", "MET", "MEW", "MID", "MIN", "MIT", "MOB",
|
||||
"MOD", "MOE", "MOO", "MOP", "MOS", "MOT", "MOW", "MUD", "MUG", "MUM",
|
||||
"MY", "NAB", "NAG", "NAN", "NAP", "NAT", "NAY", "NE", "NED", "NEE",
|
||||
"NET", "NEW", "NIB", "NIL", "NIP", "NIT", "NO", "NOB", "NOD", "NON",
|
||||
"NOR", "NOT", "NOV", "NOW", "NU", "NUN", "NUT", "O", "OAF", "OAK",
|
||||
"OAR", "OAT", "ODD", "ODE", "OF", "OFF", "OFT", "OH", "OIL", "OK",
|
||||
"OLD", "ON", "ONE", "OR", "ORB", "ORE", "ORR", "OS", "OTT", "OUR",
|
||||
"OUT", "OVA", "OW", "OWE", "OWL", "OWN", "OX", "PA", "PAD", "PAL",
|
||||
"PAM", "PAN", "PAP", "PAR", "PAT", "PAW", "PAY", "PEA", "PEG", "PEN",
|
||||
"PEP", "PER", "PET", "PEW", "PHI", "PI", "PIE", "PIN", "PIT", "PLY",
|
||||
"PO", "POD", "POE", "POP", "POT", "POW", "PRO", "PRY", "PUB", "PUG",
|
||||
"PUN", "PUP", "PUT", "QUO", "RAG", "RAM", "RAN", "RAP", "RAT", "RAW",
|
||||
"RAY", "REB", "RED", "REP", "RET", "RIB", "RID", "RIG", "RIM", "RIO",
|
||||
"RIP", "ROB", "ROD", "ROE", "RON", "ROT", "ROW", "ROY", "RUB", "RUE",
|
||||
"RUG", "RUM", "RUN", "RYE", "SAC", "SAD", "SAG", "SAL", "SAM", "SAN",
|
||||
"SAP", "SAT", "SAW", "SAY", "SEA", "SEC", "SEE", "SEN", "SET", "SEW",
|
||||
"SHE", "SHY", "SIN", "SIP", "SIR", "SIS", "SIT", "SKI", "SKY", "SLY",
|
||||
"SO", "SOB", "SOD", "SON", "SOP", "SOW", "SOY", "SPA", "SPY", "SUB",
|
||||
"SUD", "SUE", "SUM", "SUN", "SUP", "TAB", "TAD", "TAG", "TAN", "TAP",
|
||||
"TAR", "TEA", "TED", "TEE", "TEN", "THE", "THY", "TIC", "TIE", "TIM",
|
||||
"TIN", "TIP", "TO", "TOE", "TOG", "TOM", "TON", "TOO", "TOP", "TOW",
|
||||
"TOY", "TRY", "TUB", "TUG", "TUM", "TUN", "TWO", "UN", "UP", "US",
|
||||
"USE", "VAN", "VAT", "VET", "VIE", "WAD", "WAG", "WAR", "WAS", "WAY",
|
||||
"WE", "WEB", "WED", "WEE", "WET", "WHO", "WHY", "WIN", "WIT", "WOK",
|
||||
"WON", "WOO", "WOW", "WRY", "WU", "YAM", "YAP", "YAW", "YE", "YEA",
|
||||
"YES", "YET", "YOU", "ABED", "ABEL", "ABET", "ABLE", "ABUT", "ACHE",
|
||||
"ACID", "ACME", "ACRE", "ACTA", "ACTS", "ADAM", "ADDS", "ADEN", "AFAR",
|
||||
"AFRO", "AGEE", "AHEM", "AHOY", "AIDA", "AIDE", "AIDS", "AIRY", "AJAR",
|
||||
"AKIN", "ALAN", "ALEC", "ALGA", "ALIA", "ALLY", "ALMA", "ALOE", "ALSO",
|
||||
"ALTO", "ALUM", "ALVA", "AMEN", "AMES", "AMID", "AMMO", "AMOK", "AMOS",
|
||||
"AMRA", "ANDY", "ANEW", "ANNA", "ANNE", "ANTE", "ANTI", "AQUA", "ARAB",
|
||||
"ARCH", "AREA", "ARGO", "ARID", "ARMY", "ARTS", "ARTY", "ASIA", "ASKS",
|
||||
"ATOM", "AUNT", "AURA", "AUTO", "AVER", "AVID", "AVIS", "AVON", "AVOW",
|
||||
"AWAY", "AWRY", "BABE", "BABY", "BACH", "BACK", "BADE", "BAIL", "BAIT",
|
||||
"BAKE", "BALD", "BALE", "BALI", "BALK", "BALL", "BALM", "BAND", "BANE",
|
||||
"BANG", "BANK", "BARB", "BARD", "BARE", "BARK", "BARN", "BARR", "BASE",
|
||||
"BASH", "BASK", "BASS", "BATE", "BATH", "BAWD", "BAWL", "BEAD", "BEAK",
|
||||
"BEAM", "BEAN", "BEAR", "BEAT", "BEAU", "BECK", "BEEF", "BEEN", "BEER",
|
||||
"BEET", "BELA", "BELL", "BELT", "BEND", "BENT", "BERG", "BERN", "BERT",
|
||||
"BESS", "BEST", "BETA", "BETH", "BHOY", "BIAS", "BIDE", "BIEN", "BILE",
|
||||
"BILK", "BILL", "BIND", "BING", "BIRD", "BITE", "BITS", "BLAB", "BLAT",
|
||||
"BLED", "BLEW", "BLOB", "BLOC", "BLOT", "BLOW", "BLUE", "BLUM", "BLUR",
|
||||
"BOAR", "BOAT", "BOCA", "BOCK", "BODE", "BODY", "BOGY", "BOHR", "BOIL",
|
||||
"BOLD", "BOLO", "BOLT", "BOMB", "BONA", "BOND", "BONE", "BONG", "BONN",
|
||||
"BONY", "BOOK", "BOOM", "BOON", "BOOT", "BORE", "BORG", "BORN", "BOSE",
|
||||
"BOSS", "BOTH", "BOUT", "BOWL", "BOYD", "BRAD", "BRAE", "BRAG", "BRAN",
|
||||
"BRAY", "BRED", "BREW", "BRIG", "BRIM", "BROW", "BUCK", "BUDD", "BUFF",
|
||||
"BULB", "BULK", "BULL", "BUNK", "BUNT", "BUOY", "BURG", "BURL", "BURN",
|
||||
"BURR", "BURT", "BURY", "BUSH", "BUSS", "BUST", "BUSY", "BYTE", "CADY",
|
||||
"CAFE", "CAGE", "CAIN", "CAKE", "CALF", "CALL", "CALM", "CAME", "CANE",
|
||||
"CANT", "CARD", "CARE", "CARL", "CARR", "CART", "CASE", "CASH", "CASK",
|
||||
"CAST", "CAVE", "CEIL", "CELL", "CENT", "CERN", "CHAD", "CHAR", "CHAT",
|
||||
"CHAW", "CHEF", "CHEN", "CHEW", "CHIC", "CHIN", "CHOU", "CHOW", "CHUB",
|
||||
"CHUG", "CHUM", "CITE", "CITY", "CLAD", "CLAM", "CLAN", "CLAW", "CLAY",
|
||||
"CLOD", "CLOG", "CLOT", "CLUB", "CLUE", "COAL", "COAT", "COCA", "COCK",
|
||||
"COCO", "CODA", "CODE", "CODY", "COED", "COIL", "COIN", "COKE", "COLA",
|
||||
"COLD", "COLT", "COMA", "COMB", "COME", "COOK", "COOL", "COON", "COOT",
|
||||
"CORD", "CORE", "CORK", "CORN", "COST", "COVE", "COWL", "CRAB", "CRAG",
|
||||
"CRAM", "CRAY", "CREW", "CRIB", "CROW", "CRUD", "CUBA", "CUBE", "CUFF",
|
||||
"CULL", "CULT", "CUNY", "CURB", "CURD", "CURE", "CURL", "CURT", "CUTS",
|
||||
"DADE", "DALE", "DAME", "DANA", "DANE", "DANG", "DANK", "DARE", "DARK",
|
||||
"DARN", "DART", "DASH", "DATA", "DATE", "DAVE", "DAVY", "DAWN", "DAYS",
|
||||
"DEAD", "DEAF", "DEAL", "DEAN", "DEAR", "DEBT", "DECK", "DEED", "DEEM",
|
||||
"DEER", "DEFT", "DEFY", "DELL", "DENT", "DENY", "DESK", "DIAL", "DICE",
|
||||
"DIED", "DIET", "DIME", "DINE", "DING", "DINT", "DIRE", "DIRT", "DISC",
|
||||
"DISH", "DISK", "DIVE", "DOCK", "DOES", "DOLE", "DOLL", "DOLT", "DOME",
|
||||
"DONE", "DOOM", "DOOR", "DORA", "DOSE", "DOTE", "DOUG", "DOUR", "DOVE",
|
||||
"DOWN", "DRAB", "DRAG", "DRAM", "DRAW", "DREW", "DRUB", "DRUG", "DRUM",
|
||||
"DUAL", "DUCK", "DUCT", "DUEL", "DUET", "DUKE", "DULL", "DUMB", "DUNE",
|
||||
"DUNK", "DUSK", "DUST", "DUTY", "EACH", "EARL", "EARN", "EASE", "EAST",
|
||||
"EASY", "EBEN", "ECHO", "EDDY", "EDEN", "EDGE", "EDGY", "EDIT", "EDNA",
|
||||
"EGAN", "ELAN", "ELBA", "ELLA", "ELSE", "EMIL", "EMIT", "EMMA", "ENDS",
|
||||
"ERIC", "EROS", "EVEN", "EVER", "EVIL", "EYED", "FACE", "FACT", "FADE",
|
||||
"FAIL", "FAIN", "FAIR", "FAKE", "FALL", "FAME", "FANG", "FARM", "FAST",
|
||||
"FATE", "FAWN", "FEAR", "FEAT", "FEED", "FEEL", "FEET", "FELL", "FELT",
|
||||
"FEND", "FERN", "FEST", "FEUD", "FIEF", "FIGS", "FILE", "FILL", "FILM",
|
||||
"FIND", "FINE", "FINK", "FIRE", "FIRM", "FISH", "FISK", "FIST", "FITS",
|
||||
"FIVE", "FLAG", "FLAK", "FLAM", "FLAT", "FLAW", "FLEA", "FLED", "FLEW",
|
||||
"FLIT", "FLOC", "FLOG", "FLOW", "FLUB", "FLUE", "FOAL", "FOAM", "FOGY",
|
||||
"FOIL", "FOLD", "FOLK", "FOND", "FONT", "FOOD", "FOOL", "FOOT", "FORD",
|
||||
"FORE", "FORK", "FORM", "FORT", "FOSS", "FOUL", "FOUR", "FOWL", "FRAU",
|
||||
"FRAY", "FRED", "FREE", "FRET", "FREY", "FROG", "FROM", "FUEL", "FULL",
|
||||
"FUME", "FUND", "FUNK", "FURY", "FUSE", "FUSS", "GAFF", "GAGE", "GAIL",
|
||||
"GAIN", "GAIT", "GALA", "GALE", "GALL", "GALT", "GAME", "GANG", "GARB",
|
||||
"GARY", "GASH", "GATE", "GAUL", "GAUR", "GAVE", "GAWK", "GEAR", "GELD",
|
||||
"GENE", "GENT", "GERM", "GETS", "GIBE", "GIFT", "GILD", "GILL", "GILT",
|
||||
"GINA", "GIRD", "GIRL", "GIST", "GIVE", "GLAD", "GLEE", "GLEN", "GLIB",
|
||||
"GLOB", "GLOM", "GLOW", "GLUE", "GLUM", "GLUT", "GOAD", "GOAL", "GOAT",
|
||||
"GOER", "GOES", "GOLD", "GOLF", "GONE", "GONG", "GOOD", "GOOF", "GORE",
|
||||
"GORY", "GOSH", "GOUT", "GOWN", "GRAB", "GRAD", "GRAY", "GREG", "GREW",
|
||||
"GREY", "GRID", "GRIM", "GRIN", "GRIT", "GROW", "GRUB", "GULF", "GULL",
|
||||
"GUNK", "GURU", "GUSH", "GUST", "GWEN", "GWYN", "HAAG", "HAAS", "HACK",
|
||||
"HAIL", "HAIR", "HALE", "HALF", "HALL", "HALO", "HALT", "HAND", "HANG",
|
||||
"HANK", "HANS", "HARD", "HARK", "HARM", "HART", "HASH", "HAST", "HATE",
|
||||
"HATH", "HAUL", "HAVE", "HAWK", "HAYS", "HEAD", "HEAL", "HEAR", "HEAT",
|
||||
"HEBE", "HECK", "HEED", "HEEL", "HEFT", "HELD", "HELL", "HELM", "HERB",
|
||||
"HERD", "HERE", "HERO", "HERS", "HESS", "HEWN", "HICK", "HIDE", "HIGH",
|
||||
"HIKE", "HILL", "HILT", "HIND", "HINT", "HIRE", "HISS", "HIVE", "HOBO",
|
||||
"HOCK", "HOFF", "HOLD", "HOLE", "HOLM", "HOLT", "HOME", "HONE", "HONK",
|
||||
"HOOD", "HOOF", "HOOK", "HOOT", "HORN", "HOSE", "HOST", "HOUR", "HOVE",
|
||||
"HOWE", "HOWL", "HOYT", "HUCK", "HUED", "HUFF", "HUGE", "HUGH", "HUGO",
|
||||
"HULK", "HULL", "HUNK", "HUNT", "HURD", "HURL", "HURT", "HUSH", "HYDE",
|
||||
"HYMN", "IBIS", "ICON", "IDEA", "IDLE", "IFFY", "INCA", "INCH", "INTO",
|
||||
"IONS", "IOTA", "IOWA", "IRIS", "IRMA", "IRON", "ISLE", "ITCH", "ITEM",
|
||||
"IVAN", "JACK", "JADE", "JAIL", "JAKE", "JANE", "JAVA", "JEAN", "JEFF",
|
||||
"JERK", "JESS", "JEST", "JIBE", "JILL", "JILT", "JIVE", "JOAN", "JOBS",
|
||||
"JOCK", "JOEL", "JOEY", "JOHN", "JOIN", "JOKE", "JOLT", "JOVE", "JUDD",
|
||||
"JUDE", "JUDO", "JUDY", "JUJU", "JUKE", "JULY", "JUNE", "JUNK", "JUNO",
|
||||
"JURY", "JUST", "JUTE", "KAHN", "KALE", "KANE", "KANT", "KARL", "KATE",
|
||||
"KEEL", "KEEN", "KENO", "KENT", "KERN", "KERR", "KEYS", "KICK", "KILL",
|
||||
"KIND", "KING", "KIRK", "KISS", "KITE", "KLAN", "KNEE", "KNEW", "KNIT",
|
||||
"KNOB", "KNOT", "KNOW", "KOCH", "KONG", "KUDO", "KURD", "KURT", "KYLE",
|
||||
"LACE", "LACK", "LACY", "LADY", "LAID", "LAIN", "LAIR", "LAKE", "LAMB",
|
||||
"LAME", "LAND", "LANE", "LANG", "LARD", "LARK", "LASS", "LAST", "LATE",
|
||||
"LAUD", "LAVA", "LAWN", "LAWS", "LAYS", "LEAD", "LEAF", "LEAK", "LEAN",
|
||||
"LEAR", "LEEK", "LEER", "LEFT", "LEND", "LENS", "LENT", "LEON", "LESK",
|
||||
"LESS", "LEST", "LETS", "LIAR", "LICE", "LICK", "LIED", "LIEN", "LIES",
|
||||
"LIEU", "LIFE", "LIFT", "LIKE", "LILA", "LILT", "LILY", "LIMA", "LIMB",
|
||||
"LIME", "LIND", "LINE", "LINK", "LINT", "LION", "LISA", "LIST", "LIVE",
|
||||
"LOAD", "LOAF", "LOAM", "LOAN", "LOCK", "LOFT", "LOGE", "LOIS", "LOLA",
|
||||
"LONE", "LONG", "LOOK", "LOON", "LOOT", "LORD", "LORE", "LOSE", "LOSS",
|
||||
"LOST", "LOUD", "LOVE", "LOWE", "LUCK", "LUCY", "LUGE", "LUKE", "LULU",
|
||||
"LUND", "LUNG", "LURA", "LURE", "LURK", "LUSH", "LUST", "LYLE", "LYNN",
|
||||
"LYON", "LYRA", "MACE", "MADE", "MAGI", "MAID", "MAIL", "MAIN", "MAKE",
|
||||
"MALE", "MALI", "MALL", "MALT", "MANA", "MANN", "MANY", "MARC", "MARE",
|
||||
"MARK", "MARS", "MART", "MARY", "MASH", "MASK", "MASS", "MAST", "MATE",
|
||||
"MATH", "MAUL", "MAYO", "MEAD", "MEAL", "MEAN", "MEAT", "MEEK", "MEET",
|
||||
"MELD", "MELT", "MEMO", "MEND", "MENU", "MERT", "MESH", "MESS", "MICE",
|
||||
"MIKE", "MILD", "MILE", "MILK", "MILL", "MILT", "MIMI", "MIND", "MINE",
|
||||
"MINI", "MINK", "MINT", "MIRE", "MISS", "MIST", "MITE", "MITT", "MOAN",
|
||||
"MOAT", "MOCK", "MODE", "MOLD", "MOLE", "MOLL", "MOLT", "MONA", "MONK",
|
||||
"MONT", "MOOD", "MOON", "MOOR", "MOOT", "MORE", "MORN", "MORT", "MOSS",
|
||||
"MOST", "MOTH", "MOVE", "MUCH", "MUCK", "MUDD", "MUFF", "MULE", "MULL",
|
||||
"MURK", "MUSH", "MUST", "MUTE", "MUTT", "MYRA", "MYTH", "NAGY", "NAIL",
|
||||
"NAIR", "NAME", "NARY", "NASH", "NAVE", "NAVY", "NEAL", "NEAR", "NEAT",
|
||||
"NECK", "NEED", "NEIL", "NELL", "NEON", "NERO", "NESS", "NEST", "NEWS",
|
||||
"NEWT", "NIBS", "NICE", "NICK", "NILE", "NINA", "NINE", "NOAH", "NODE",
|
||||
"NOEL", "NOLL", "NONE", "NOOK", "NOON", "NORM", "NOSE", "NOTE", "NOUN",
|
||||
"NOVA", "NUDE", "NULL", "NUMB", "OATH", "OBEY", "OBOE", "ODIN", "OHIO",
|
||||
"OILY", "OINT", "OKAY", "OLAF", "OLDY", "OLGA", "OLIN", "OMAN", "OMEN",
|
||||
"OMIT", "ONCE", "ONES", "ONLY", "ONTO", "ONUS", "ORAL", "ORGY", "OSLO",
|
||||
"OTIS", "OTTO", "OUCH", "OUST", "OUTS", "OVAL", "OVEN", "OVER", "OWLY",
|
||||
"OWNS", "QUAD", "QUIT", "QUOD", "RACE", "RACK", "RACY", "RAFT", "RAGE",
|
||||
"RAID", "RAIL", "RAIN", "RAKE", "RANK", "RANT", "RARE", "RASH", "RATE",
|
||||
"RAVE", "RAYS", "READ", "REAL", "REAM", "REAR", "RECK", "REED", "REEF",
|
||||
"REEK", "REEL", "REID", "REIN", "RENA", "REND", "RENT", "REST", "RICE",
|
||||
"RICH", "RICK", "RIDE", "RIFT", "RILL", "RIME", "RING", "RINK", "RISE",
|
||||
"RISK", "RITE", "ROAD", "ROAM", "ROAR", "ROBE", "ROCK", "RODE", "ROIL",
|
||||
"ROLL", "ROME", "ROOD", "ROOF", "ROOK", "ROOM", "ROOT", "ROSA", "ROSE",
|
||||
"ROSS", "ROSY", "ROTH", "ROUT", "ROVE", "ROWE", "ROWS", "RUBE", "RUBY",
|
||||
"RUDE", "RUDY", "RUIN", "RULE", "RUNG", "RUNS", "RUNT", "RUSE", "RUSH",
|
||||
"RUSK", "RUSS", "RUST", "RUTH", "SACK", "SAFE", "SAGE", "SAID", "SAIL",
|
||||
"SALE", "SALK", "SALT", "SAME", "SAND", "SANE", "SANG", "SANK", "SARA",
|
||||
"SAUL", "SAVE", "SAYS", "SCAN", "SCAR", "SCAT", "SCOT", "SEAL", "SEAM",
|
||||
"SEAR", "SEAT", "SEED", "SEEK", "SEEM", "SEEN", "SEES", "SELF", "SELL",
|
||||
"SEND", "SENT", "SETS", "SEWN", "SHAG", "SHAM", "SHAW", "SHAY", "SHED",
|
||||
"SHIM", "SHIN", "SHOD", "SHOE", "SHOT", "SHOW", "SHUN", "SHUT", "SICK",
|
||||
"SIDE", "SIFT", "SIGH", "SIGN", "SILK", "SILL", "SILO", "SILT", "SINE",
|
||||
"SING", "SINK", "SIRE", "SITE", "SITS", "SITU", "SKAT", "SKEW", "SKID",
|
||||
"SKIM", "SKIN", "SKIT", "SLAB", "SLAM", "SLAT", "SLAY", "SLED", "SLEW",
|
||||
"SLID", "SLIM", "SLIT", "SLOB", "SLOG", "SLOT", "SLOW", "SLUG", "SLUM",
|
||||
"SLUR", "SMOG", "SMUG", "SNAG", "SNOB", "SNOW", "SNUB", "SNUG", "SOAK",
|
||||
"SOAR", "SOCK", "SODA", "SOFA", "SOFT", "SOIL", "SOLD", "SOME", "SONG",
|
||||
"SOON", "SOOT", "SORE", "SORT", "SOUL", "SOUR", "SOWN", "STAB", "STAG",
|
||||
"STAN", "STAR", "STAY", "STEM", "STEW", "STIR", "STOW", "STUB", "STUN",
|
||||
"SUCH", "SUDS", "SUIT", "SULK", "SUMS", "SUNG", "SUNK", "SURE", "SURF",
|
||||
"SWAB", "SWAG", "SWAM", "SWAN", "SWAT", "SWAY", "SWIM", "SWUM", "TACK",
|
||||
"TACT", "TAIL", "TAKE", "TALE", "TALK", "TALL", "TANK", "TASK", "TATE",
|
||||
"TAUT", "TEAL", "TEAM", "TEAR", "TECH", "TEEM", "TEEN", "TEET", "TELL",
|
||||
"TEND", "TENT", "TERM", "TERN", "TESS", "TEST", "THAN", "THAT", "THEE",
|
||||
"THEM", "THEN", "THEY", "THIN", "THIS", "THUD", "THUG", "TICK", "TIDE",
|
||||
"TIDY", "TIED", "TIER", "TILE", "TILL", "TILT", "TIME", "TINA", "TINE",
|
||||
"TINT", "TINY", "TIRE", "TOAD", "TOGO", "TOIL", "TOLD", "TOLL", "TONE",
|
||||
"TONG", "TONY", "TOOK", "TOOL", "TOOT", "TORE", "TORN", "TOTE", "TOUR",
|
||||
"TOUT", "TOWN", "TRAG", "TRAM", "TRAY", "TREE", "TREK", "TRIG", "TRIM",
|
||||
"TRIO", "TROD", "TROT", "TROY", "TRUE", "TUBA", "TUBE", "TUCK", "TUFT",
|
||||
"TUNA", "TUNE", "TUNG", "TURF", "TURN", "TUSK", "TWIG", "TWIN", "TWIT",
|
||||
"ULAN", "UNIT", "URGE", "USED", "USER", "USES", "UTAH", "VAIL", "VAIN",
|
||||
"VALE", "VARY", "VASE", "VAST", "VEAL", "VEDA", "VEIL", "VEIN", "VEND",
|
||||
"VENT", "VERB", "VERY", "VETO", "VICE", "VIEW", "VINE", "VISE", "VOID",
|
||||
"VOLT", "VOTE", "WACK", "WADE", "WAGE", "WAIL", "WAIT", "WAKE", "WALE",
|
||||
"WALK", "WALL", "WALT", "WAND", "WANE", "WANG", "WANT", "WARD", "WARM",
|
||||
"WARN", "WART", "WASH", "WAST", "WATS", "WATT", "WAVE", "WAVY", "WAYS",
|
||||
"WEAK", "WEAL", "WEAN", "WEAR", "WEED", "WEEK", "WEIR", "WELD", "WELL",
|
||||
"WELT", "WENT", "WERE", "WERT", "WEST", "WHAM", "WHAT", "WHEE", "WHEN",
|
||||
"WHET", "WHOA", "WHOM", "WICK", "WIFE", "WILD", "WILL", "WIND", "WINE",
|
||||
"WING", "WINK", "WINO", "WIRE", "WISE", "WISH", "WITH", "WOLF", "WONT",
|
||||
"WOOD", "WOOL", "WORD", "WORE", "WORK", "WORM", "WORN", "WOVE", "WRIT",
|
||||
"WYNN", "YALE", "YANG", "YANK", "YARD", "YARN", "YAWL", "YAWN", "YEAH",
|
||||
"YEAR", "YELL", "YOGA", "YOKE"
|
||||
};
|
||||
|
||||
/* Extract 'length' bits from the char array 's'
|
||||
starting with bit 'start' */
|
||||
unsigned long RFC1751::extract(char *s, int start, int length)
|
||||
unsigned long RFC1751::extract (char* s, int start, int length)
|
||||
{
|
||||
unsigned char cl;
|
||||
unsigned char cc;
|
||||
unsigned char cr;
|
||||
unsigned long x;
|
||||
unsigned char cl;
|
||||
unsigned char cc;
|
||||
unsigned char cr;
|
||||
unsigned long x;
|
||||
|
||||
assert(length <= 11);
|
||||
assert(start >= 0);
|
||||
assert(length >= 0);
|
||||
assert(start+length <= 66);
|
||||
assert (length <= 11);
|
||||
assert (start >= 0);
|
||||
assert (length >= 0);
|
||||
assert (start + length <= 66);
|
||||
|
||||
cl = s[start/8]; // get components
|
||||
cc = s[start/8 +1];
|
||||
cr = s[start/8 +2];
|
||||
cl = s[start / 8]; // get components
|
||||
cc = s[start / 8 + 1];
|
||||
cr = s[start / 8 + 2];
|
||||
|
||||
x = ((long)(cl<<8 | cc) <<8 | cr) ; // Put bits together
|
||||
x = x >> (24 - (length + (start%8))); // Right justify number
|
||||
x = ( x & (0xffff >> (16-length) ) ); // Trim extra bits.
|
||||
x = ((long) (cl << 8 | cc) << 8 | cr) ; // Put bits together
|
||||
x = x >> (24 - (length + (start % 8))); // Right justify number
|
||||
x = ( x & (0xffff >> (16 - length) ) ); // Trim extra bits.
|
||||
|
||||
return x;
|
||||
return x;
|
||||
}
|
||||
|
||||
// Encode 8 bytes in 'c' as a string of English words.
|
||||
// Returns a pointer to a static buffer
|
||||
void RFC1751::btoe(std::string& strHuman, const std::string& strData)
|
||||
void RFC1751::btoe (std::string& strHuman, const std::string& strData)
|
||||
{
|
||||
char caBuffer[9]; /* add in room for the parity 2 bits*/
|
||||
int p, i;
|
||||
char caBuffer[9]; /* add in room for the parity 2 bits*/
|
||||
int p, i;
|
||||
|
||||
memcpy(caBuffer, strData.c_str(), 8);
|
||||
memcpy (caBuffer, strData.c_str (), 8);
|
||||
|
||||
// compute parity: merely add groups of two bits.
|
||||
for(p = 0, i = 0; i < 64; i += 2)
|
||||
p += extract(caBuffer, i, 2);
|
||||
// compute parity: merely add groups of two bits.
|
||||
for (p = 0, i = 0; i < 64; i += 2)
|
||||
p += extract (caBuffer, i, 2);
|
||||
|
||||
caBuffer[8] = char(p) << 6;
|
||||
caBuffer[8] = char (p) << 6;
|
||||
|
||||
strHuman = std::string()
|
||||
+ s_dictionary[extract(caBuffer, 0, 11)] + " "
|
||||
+ s_dictionary[extract(caBuffer, 11, 11)] + " "
|
||||
+ s_dictionary[extract(caBuffer, 22, 11)] + " "
|
||||
+ s_dictionary[extract(caBuffer, 33, 11)] + " "
|
||||
+ s_dictionary[extract(caBuffer, 44, 11)] + " "
|
||||
+ s_dictionary[extract(caBuffer, 55, 11)];
|
||||
strHuman = std::string ()
|
||||
+ s_dictionary[extract (caBuffer, 0, 11)] + " "
|
||||
+ s_dictionary[extract (caBuffer, 11, 11)] + " "
|
||||
+ s_dictionary[extract (caBuffer, 22, 11)] + " "
|
||||
+ s_dictionary[extract (caBuffer, 33, 11)] + " "
|
||||
+ s_dictionary[extract (caBuffer, 44, 11)] + " "
|
||||
+ s_dictionary[extract (caBuffer, 55, 11)];
|
||||
}
|
||||
|
||||
void RFC1751::insert(char *s, int x, int start, int length)
|
||||
void RFC1751::insert (char* s, int x, int start, int length)
|
||||
{
|
||||
unsigned char cl;
|
||||
unsigned char cc;
|
||||
unsigned char cr;
|
||||
unsigned long y;
|
||||
int shift;
|
||||
unsigned char cl;
|
||||
unsigned char cc;
|
||||
unsigned char cr;
|
||||
unsigned long y;
|
||||
int shift;
|
||||
|
||||
assert(length <= 11);
|
||||
assert(start >= 0);
|
||||
assert(length >= 0);
|
||||
assert(start+length <= 66);
|
||||
assert (length <= 11);
|
||||
assert (start >= 0);
|
||||
assert (length >= 0);
|
||||
assert (start + length <= 66);
|
||||
|
||||
shift = ((8 -(( start + length) % 8))%8);
|
||||
y = (long) x << shift;
|
||||
cl = (y >> 16) & 0xff;
|
||||
cc = (y >> 8) & 0xff;
|
||||
cr = y & 0xff;
|
||||
if(shift + length > 16){
|
||||
s[start /8] |= cl;
|
||||
s[start/8 +1] |= cc;
|
||||
s[start/8 +2] |= cr;
|
||||
} else if(shift +length > 8){
|
||||
s[start/8] |= cc;
|
||||
s[start/8 + 1] |= cr;
|
||||
} else {
|
||||
s[start/8] |= cr;
|
||||
}
|
||||
shift = ((8 - (( start + length) % 8)) % 8);
|
||||
y = (long) x << shift;
|
||||
cl = (y >> 16) & 0xff;
|
||||
cc = (y >> 8) & 0xff;
|
||||
cr = y & 0xff;
|
||||
|
||||
if (shift + length > 16)
|
||||
{
|
||||
s[start / 8] |= cl;
|
||||
s[start / 8 + 1] |= cc;
|
||||
s[start / 8 + 2] |= cr;
|
||||
}
|
||||
else if (shift + length > 8)
|
||||
{
|
||||
s[start / 8] |= cc;
|
||||
s[start / 8 + 1] |= cr;
|
||||
}
|
||||
else
|
||||
{
|
||||
s[start / 8] |= cr;
|
||||
}
|
||||
}
|
||||
|
||||
void RFC1751::standard(std::string& strWord)
|
||||
void RFC1751::standard (std::string& strWord)
|
||||
{
|
||||
BOOST_FOREACH(char cLetter, strWord)
|
||||
{
|
||||
if(!isascii(cLetter))
|
||||
{
|
||||
; // nothing
|
||||
}
|
||||
else if(islower(cLetter))
|
||||
{
|
||||
cLetter = toupper(cLetter);
|
||||
}
|
||||
else if(cLetter == '1')
|
||||
{
|
||||
cLetter = 'L';
|
||||
}
|
||||
else if(cLetter == '0')
|
||||
{
|
||||
cLetter = 'O';
|
||||
}
|
||||
else if(cLetter == '5')
|
||||
{
|
||||
cLetter = 'S';
|
||||
}
|
||||
}
|
||||
BOOST_FOREACH (char cLetter, strWord)
|
||||
{
|
||||
if (!isascii (cLetter))
|
||||
{
|
||||
; // nothing
|
||||
}
|
||||
else if (islower (cLetter))
|
||||
{
|
||||
cLetter = toupper (cLetter);
|
||||
}
|
||||
else if (cLetter == '1')
|
||||
{
|
||||
cLetter = 'L';
|
||||
}
|
||||
else if (cLetter == '0')
|
||||
{
|
||||
cLetter = 'O';
|
||||
}
|
||||
else if (cLetter == '5')
|
||||
{
|
||||
cLetter = 'S';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Binary search of dictionary.
|
||||
int RFC1751::wsrch (const std::string& strWord, int iMin, int iMax)
|
||||
{
|
||||
int iResult = -1;
|
||||
int iResult = -1;
|
||||
|
||||
while (iResult < 0 && iMin != iMax)
|
||||
{
|
||||
// Have a range to search.
|
||||
int iMid = iMin+(iMax-iMin)/2;
|
||||
int iDir = strWord.compare(s_dictionary[iMid]);
|
||||
while (iResult < 0 && iMin != iMax)
|
||||
{
|
||||
// Have a range to search.
|
||||
int iMid = iMin + (iMax - iMin) / 2;
|
||||
int iDir = strWord.compare (s_dictionary[iMid]);
|
||||
|
||||
if (!iDir)
|
||||
{
|
||||
iResult = iMid; // Found it.
|
||||
}
|
||||
else if (iDir < 0)
|
||||
{
|
||||
iMax = iMid; // key < middle, middle is new max.
|
||||
}
|
||||
else
|
||||
{
|
||||
iMin = iMid+1; // key > middle, new min is past the middle.
|
||||
}
|
||||
}
|
||||
if (!iDir)
|
||||
{
|
||||
iResult = iMid; // Found it.
|
||||
}
|
||||
else if (iDir < 0)
|
||||
{
|
||||
iMax = iMid; // key < middle, middle is new max.
|
||||
}
|
||||
else
|
||||
{
|
||||
iMin = iMid + 1; // key > middle, new min is past the middle.
|
||||
}
|
||||
}
|
||||
|
||||
return iResult;
|
||||
return iResult;
|
||||
}
|
||||
|
||||
// Convert 6 words to binary.
|
||||
@@ -379,91 +386,92 @@ int RFC1751::wsrch (const std::string& strWord, int iMin, int iMax)
|
||||
// -2 words OK but parity is wrong
|
||||
int RFC1751::etob (std::string& strData, std::vector<std::string> vsHuman)
|
||||
{
|
||||
int i, p, v,l;
|
||||
char b[9];
|
||||
int i, p, v, l;
|
||||
char b[9];
|
||||
|
||||
if (6 != vsHuman.size())
|
||||
return -1;
|
||||
if (6 != vsHuman.size ())
|
||||
return -1;
|
||||
|
||||
memset(b, 0, sizeof(b));
|
||||
memset (b, 0, sizeof (b));
|
||||
|
||||
p=0;
|
||||
BOOST_FOREACH(std::string& strWord, vsHuman)
|
||||
{
|
||||
l = strWord.length();
|
||||
if(l > 4 || l < 1)
|
||||
return -1;
|
||||
p = 0;
|
||||
BOOST_FOREACH (std::string & strWord, vsHuman)
|
||||
{
|
||||
l = strWord.length ();
|
||||
|
||||
standard (strWord);
|
||||
if (l > 4 || l < 1)
|
||||
return -1;
|
||||
|
||||
v = wsrch(strWord,
|
||||
l < 4 ? 0 : 571,
|
||||
l < 4 ? 570 : 2048);
|
||||
standard (strWord);
|
||||
|
||||
if(v < 0 )
|
||||
return 0;
|
||||
v = wsrch (strWord,
|
||||
l < 4 ? 0 : 571,
|
||||
l < 4 ? 570 : 2048);
|
||||
|
||||
insert(b, v, p, 11);
|
||||
p +=11;
|
||||
}
|
||||
if (v < 0 )
|
||||
return 0;
|
||||
|
||||
/* now check the parity of what we got */
|
||||
for(p = 0, i = 0; i < 64; i +=2)
|
||||
p += extract(b, i, 2);
|
||||
insert (b, v, p, 11);
|
||||
p += 11;
|
||||
}
|
||||
|
||||
if( (p & 3) != extract(b, 64,2) )
|
||||
return -2;
|
||||
/* now check the parity of what we got */
|
||||
for (p = 0, i = 0; i < 64; i += 2)
|
||||
p += extract (b, i, 2);
|
||||
|
||||
strData.assign(b, 8);
|
||||
if ( (p & 3) != extract (b, 64, 2) )
|
||||
return -2;
|
||||
|
||||
return 1;
|
||||
strData.assign (b, 8);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** Convert words seperated by spaces into a 128 bit key in big-endian format.
|
||||
/** Convert words seperated by spaces into a 128 bit key in big-endian format.
|
||||
|
||||
@return
|
||||
1 if succeeded
|
||||
0 if word not in dictionary
|
||||
-1 if badly formed string
|
||||
-2 if words are okay but parity is wrong.
|
||||
@return
|
||||
1 if succeeded
|
||||
0 if word not in dictionary
|
||||
-1 if badly formed string
|
||||
-2 if words are okay but parity is wrong.
|
||||
*/
|
||||
int RFC1751::getKeyFromEnglish (std::string& strKey, const std::string& strHuman)
|
||||
{
|
||||
std::vector<std::string> vWords;
|
||||
std::string strFirst, strSecond;
|
||||
int rc=0;
|
||||
std::string strFirst, strSecond;
|
||||
int rc = 0;
|
||||
|
||||
std::string strTrimmed(strHuman);
|
||||
std::string strTrimmed (strHuman);
|
||||
|
||||
boost::algorithm::trim(strTrimmed);
|
||||
boost::algorithm::trim (strTrimmed);
|
||||
|
||||
boost::algorithm::split(vWords, strTrimmed,
|
||||
boost::algorithm::is_space(), boost::algorithm::token_compress_on);
|
||||
boost::algorithm::split (vWords, strTrimmed,
|
||||
boost::algorithm::is_space (), boost::algorithm::token_compress_on);
|
||||
|
||||
rc = 12 == vWords.size() ? 1 : -1;
|
||||
|
||||
if (1 == rc)
|
||||
rc = etob(strFirst, vWords | boost::adaptors::copied(0, 6));
|
||||
|
||||
if (1 == rc)
|
||||
rc = etob(strSecond, vWords | boost::adaptors::copied(6, 12));
|
||||
rc = 12 == vWords.size () ? 1 : -1;
|
||||
|
||||
if (1 == rc)
|
||||
strKey = strFirst + strSecond;
|
||||
rc = etob (strFirst, vWords | boost::adaptors::copied (0, 6));
|
||||
|
||||
return rc;
|
||||
if (1 == rc)
|
||||
rc = etob (strSecond, vWords | boost::adaptors::copied (6, 12));
|
||||
|
||||
if (1 == rc)
|
||||
strKey = strFirst + strSecond;
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/** Convert to human from a 128 bit key in big-endian format
|
||||
*/
|
||||
void RFC1751::getEnglishFromKey (std::string& strHuman, const std::string& strKey)
|
||||
{
|
||||
std::string strFirst, strSecond;
|
||||
std::string strFirst, strSecond;
|
||||
|
||||
btoe(strFirst, strKey.substr(0, 8));
|
||||
btoe(strSecond, strKey.substr(8, 8));
|
||||
btoe (strFirst, strKey.substr (0, 8));
|
||||
btoe (strSecond, strKey.substr (8, 8));
|
||||
|
||||
strHuman = strFirst + " " + strSecond;
|
||||
strHuman = strFirst + " " + strSecond;
|
||||
}
|
||||
|
||||
// vim:ts=4
|
||||
|
||||
@@ -4,19 +4,19 @@
|
||||
class RFC1751
|
||||
{
|
||||
public:
|
||||
static int getKeyFromEnglish (std::string& strKey, const std::string& strHuman);
|
||||
static int getKeyFromEnglish (std::string& strKey, const std::string& strHuman);
|
||||
|
||||
static void getEnglishFromKey (std::string& strHuman, const std::string& strKey);
|
||||
static void getEnglishFromKey (std::string& strHuman, const std::string& strKey);
|
||||
|
||||
private:
|
||||
static unsigned long extract (char *s, int start, int length);
|
||||
static void btoe (std::string& strHuman, const std::string& strData);
|
||||
static void insert (char *s, int x, int start, int length);
|
||||
static void standard (std::string& strWord);
|
||||
static int wsrch (const std::string& strWord, int iMin, int iMax);
|
||||
static int etob (std::string& strData, std::vector<std::string> vsHuman);
|
||||
static unsigned long extract (char* s, int start, int length);
|
||||
static void btoe (std::string& strHuman, const std::string& strData);
|
||||
static void insert (char* s, int x, int start, int length);
|
||||
static void standard (std::string& strWord);
|
||||
static int wsrch (const std::string& strWord, int iMin, int iMax);
|
||||
static int etob (std::string& strData, std::vector<std::string> vsHuman);
|
||||
|
||||
static char const* s_dictionary [];
|
||||
static char const* s_dictionary [];
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -5,12 +5,12 @@ std::map<int, SField::ptr> SField::codeToField;
|
||||
boost::mutex SField::mapMutex;
|
||||
int SField::num = 0;
|
||||
|
||||
SField sfInvalid(-1), sfGeneric(0);
|
||||
SField sfLedgerEntry(STI_LEDGERENTRY, 1, "LedgerEntry");
|
||||
SField sfTransaction(STI_TRANSACTION, 1, "Transaction");
|
||||
SField sfValidation(STI_VALIDATION, 1, "Validation");
|
||||
SField sfHash(STI_HASH256, 257, "hash");
|
||||
SField sfIndex(STI_HASH256, 258, "index");
|
||||
SField sfInvalid (-1), sfGeneric (0);
|
||||
SField sfLedgerEntry (STI_LEDGERENTRY, 1, "LedgerEntry");
|
||||
SField sfTransaction (STI_TRANSACTION, 1, "Transaction");
|
||||
SField sfValidation (STI_VALIDATION, 1, "Validation");
|
||||
SField sfHash (STI_HASH256, 257, "hash");
|
||||
SField sfIndex (STI_HASH256, 258, "index");
|
||||
|
||||
#define FIELD(name, type, index) SField sf##name(FIELD_CODE(STI_##type, index), STI_##type, index, #name);
|
||||
#define TYPE(name, type, index)
|
||||
@@ -18,50 +18,53 @@ SField sfIndex(STI_HASH256, 258, "index");
|
||||
#undef FIELD
|
||||
#undef TYPE
|
||||
|
||||
static int initFields()
|
||||
static int initFields ()
|
||||
{
|
||||
sfTxnSignature.notSigningField();
|
||||
sfTxnSignatures.notSigningField();
|
||||
sfSignature.notSigningField();
|
||||
sfTxnSignature.notSigningField ();
|
||||
sfTxnSignatures.notSigningField ();
|
||||
sfSignature.notSigningField ();
|
||||
|
||||
sfIndexes.setMeta(SField::sMD_Never);
|
||||
sfPreviousTxnID.setMeta(SField::sMD_DeleteFinal);
|
||||
sfPreviousTxnLgrSeq.setMeta(SField::sMD_DeleteFinal);
|
||||
sfLedgerEntryType.setMeta(SField::sMD_Never);
|
||||
sfRootIndex.setMeta(SField::sMD_Always);
|
||||
sfIndexes.setMeta (SField::sMD_Never);
|
||||
sfPreviousTxnID.setMeta (SField::sMD_DeleteFinal);
|
||||
sfPreviousTxnLgrSeq.setMeta (SField::sMD_DeleteFinal);
|
||||
sfLedgerEntryType.setMeta (SField::sMD_Never);
|
||||
sfRootIndex.setMeta (SField::sMD_Always);
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
static const int f = initFields();
|
||||
static const int f = initFields ();
|
||||
|
||||
|
||||
SField::SField(SerializedTypeID tid, int fv) : fieldCode(FIELD_CODE(tid, fv)), fieldType(tid), fieldValue(fv),
|
||||
fieldMeta(sMD_Default), fieldNum(++num), signingField(true)
|
||||
{ // call with the map mutex
|
||||
fieldName = lexical_cast_i(tid) + "/" + lexical_cast_i(fv);
|
||||
codeToField[fieldCode] = this;
|
||||
assert((fv != 1) || ((tid != STI_ARRAY) && (tid!=STI_OBJECT)));
|
||||
SField::SField (SerializedTypeID tid, int fv) : fieldCode (FIELD_CODE (tid, fv)), fieldType (tid), fieldValue (fv),
|
||||
fieldMeta (sMD_Default), fieldNum (++num), signingField (true)
|
||||
{
|
||||
// call with the map mutex
|
||||
fieldName = lexical_cast_i (tid) + "/" + lexical_cast_i (fv);
|
||||
codeToField[fieldCode] = this;
|
||||
assert ((fv != 1) || ((tid != STI_ARRAY) && (tid != STI_OBJECT)));
|
||||
}
|
||||
|
||||
SField::ref SField::getField(int code)
|
||||
SField::ref SField::getField (int code)
|
||||
{
|
||||
int type = code >> 16;
|
||||
int field = code % 0xffff;
|
||||
int type = code >> 16;
|
||||
int field = code % 0xffff;
|
||||
|
||||
if ((type <= 0) || (field <= 0))
|
||||
return sfInvalid;
|
||||
if ((type <= 0) || (field <= 0))
|
||||
return sfInvalid;
|
||||
|
||||
boost::mutex::scoped_lock sl(mapMutex);
|
||||
boost::mutex::scoped_lock sl (mapMutex);
|
||||
|
||||
std::map<int, SField::ptr>::iterator it = codeToField.find(code);
|
||||
if (it != codeToField.end())
|
||||
return *(it->second);
|
||||
std::map<int, SField::ptr>::iterator it = codeToField.find (code);
|
||||
|
||||
if (field > 255) // don't dynamically extend types that have no binary encoding
|
||||
return sfInvalid;
|
||||
if (it != codeToField.end ())
|
||||
return * (it->second);
|
||||
|
||||
switch (type)
|
||||
{ // types we are willing to dynamically extend
|
||||
if (field > 255) // don't dynamically extend types that have no binary encoding
|
||||
return sfInvalid;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
// types we are willing to dynamically extend
|
||||
|
||||
#define FIELD(name, type, index)
|
||||
#define TYPE(name, type, index) case STI_##type:
|
||||
@@ -69,56 +72,62 @@ SField::ref SField::getField(int code)
|
||||
#undef FIELD
|
||||
#undef TYPE
|
||||
|
||||
break;
|
||||
default:
|
||||
return sfInvalid;
|
||||
}
|
||||
break;
|
||||
|
||||
return *(new SField(static_cast<SerializedTypeID>(type), field));
|
||||
default:
|
||||
return sfInvalid;
|
||||
}
|
||||
|
||||
return * (new SField (static_cast<SerializedTypeID> (type), field));
|
||||
}
|
||||
|
||||
int SField::compare(SField::ref f1, SField::ref f2)
|
||||
{ // -1 = f1 comes before f2, 0 = illegal combination, 1 = f1 comes after f2
|
||||
if ((f1.fieldCode <= 0) || (f2.fieldCode <= 0))
|
||||
return 0;
|
||||
|
||||
if (f1.fieldCode < f2.fieldCode)
|
||||
return -1;
|
||||
|
||||
if (f2.fieldCode < f1.fieldCode)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::string SField::getName() const
|
||||
int SField::compare (SField::ref f1, SField::ref f2)
|
||||
{
|
||||
if (!fieldName.empty())
|
||||
return fieldName;
|
||||
if (fieldValue == 0)
|
||||
return "";
|
||||
return boost::lexical_cast<std::string>(static_cast<int>(fieldType)) + "/" +
|
||||
boost::lexical_cast<std::string>(fieldValue);
|
||||
// -1 = f1 comes before f2, 0 = illegal combination, 1 = f1 comes after f2
|
||||
if ((f1.fieldCode <= 0) || (f2.fieldCode <= 0))
|
||||
return 0;
|
||||
|
||||
if (f1.fieldCode < f2.fieldCode)
|
||||
return -1;
|
||||
|
||||
if (f2.fieldCode < f1.fieldCode)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
SField::ref SField::getField(const std::string& fieldName)
|
||||
{ // OPTIMIZEME me with a map. CHECKME this is case sensitive
|
||||
boost::mutex::scoped_lock sl(mapMutex);
|
||||
typedef std::map<int, SField::ptr>::value_type int_sfref_pair;
|
||||
BOOST_FOREACH(const int_sfref_pair& fieldPair, codeToField)
|
||||
{
|
||||
if (fieldPair.second->fieldName == fieldName)
|
||||
return *(fieldPair.second);
|
||||
}
|
||||
return sfInvalid;
|
||||
}
|
||||
|
||||
SField::~SField()
|
||||
std::string SField::getName () const
|
||||
{
|
||||
boost::mutex::scoped_lock sl(mapMutex);
|
||||
std::map<int, ptr>::iterator it = codeToField.find(fieldCode);
|
||||
if ((it != codeToField.end()) && (it->second == this))
|
||||
codeToField.erase(it);
|
||||
if (!fieldName.empty ())
|
||||
return fieldName;
|
||||
|
||||
if (fieldValue == 0)
|
||||
return "";
|
||||
|
||||
return boost::lexical_cast<std::string> (static_cast<int> (fieldType)) + "/" +
|
||||
boost::lexical_cast<std::string> (fieldValue);
|
||||
}
|
||||
|
||||
SField::ref SField::getField (const std::string& fieldName)
|
||||
{
|
||||
// OPTIMIZEME me with a map. CHECKME this is case sensitive
|
||||
boost::mutex::scoped_lock sl (mapMutex);
|
||||
typedef std::map<int, SField::ptr>::value_type int_sfref_pair;
|
||||
BOOST_FOREACH (const int_sfref_pair & fieldPair, codeToField)
|
||||
{
|
||||
if (fieldPair.second->fieldName == fieldName)
|
||||
return * (fieldPair.second);
|
||||
}
|
||||
return sfInvalid;
|
||||
}
|
||||
|
||||
SField::~SField ()
|
||||
{
|
||||
boost::mutex::scoped_lock sl (mapMutex);
|
||||
std::map<int, ptr>::iterator it = codeToField.find (fieldCode);
|
||||
|
||||
if ((it != codeToField.end ()) && (it->second == this))
|
||||
codeToField.erase (it);
|
||||
}
|
||||
|
||||
// vim:ts=4
|
||||
|
||||
@@ -6,10 +6,10 @@
|
||||
|
||||
enum SerializedTypeID
|
||||
{
|
||||
// special types
|
||||
STI_UNKNOWN = -2,
|
||||
STI_DONE = -1,
|
||||
STI_NOTPRESENT = 0,
|
||||
// special types
|
||||
STI_UNKNOWN = -2,
|
||||
STI_DONE = -1,
|
||||
STI_NOTPRESENT = 0,
|
||||
|
||||
#define TYPE(name, field, value) STI_##field = value,
|
||||
#define FIELD(name, field, value)
|
||||
@@ -17,10 +17,10 @@ enum SerializedTypeID
|
||||
#undef TYPE
|
||||
#undef FIELD
|
||||
|
||||
// high level types
|
||||
STI_TRANSACTION = 10001,
|
||||
STI_LEDGERENTRY = 10002,
|
||||
STI_VALIDATION = 10003,
|
||||
// high level types
|
||||
STI_TRANSACTION = 10001,
|
||||
STI_LEDGERENTRY = 10002,
|
||||
STI_VALIDATION = 10003,
|
||||
};
|
||||
|
||||
/** Identifies fields.
|
||||
@@ -32,112 +32,168 @@ enum SerializedTypeID
|
||||
class SField
|
||||
{
|
||||
public:
|
||||
typedef const SField& ref;
|
||||
typedef SField const * ptr;
|
||||
typedef const SField& ref;
|
||||
typedef SField const* ptr;
|
||||
|
||||
static const int sMD_Never = 0x00;
|
||||
static const int sMD_ChangeOrig = 0x01; // original value when it changes
|
||||
static const int sMD_ChangeNew = 0x02; // new value when it changes
|
||||
static const int sMD_DeleteFinal = 0x04; // final value when it is deleted
|
||||
static const int sMD_Create = 0x08; // value when it's created
|
||||
static const int sMD_Always = 0x10; // value when node containing it is affected at all
|
||||
static const int sMD_Default = sMD_ChangeOrig | sMD_ChangeNew | sMD_DeleteFinal | sMD_Create;
|
||||
static const int sMD_Never = 0x00;
|
||||
static const int sMD_ChangeOrig = 0x01; // original value when it changes
|
||||
static const int sMD_ChangeNew = 0x02; // new value when it changes
|
||||
static const int sMD_DeleteFinal = 0x04; // final value when it is deleted
|
||||
static const int sMD_Create = 0x08; // value when it's created
|
||||
static const int sMD_Always = 0x10; // value when node containing it is affected at all
|
||||
static const int sMD_Default = sMD_ChangeOrig | sMD_ChangeNew | sMD_DeleteFinal | sMD_Create;
|
||||
|
||||
public:
|
||||
|
||||
const int fieldCode; // (type<<16)|index
|
||||
const SerializedTypeID fieldType; // STI_*
|
||||
const int fieldValue; // Code number for protocol
|
||||
std::string fieldName;
|
||||
int fieldMeta;
|
||||
int fieldNum;
|
||||
bool signingField;
|
||||
const int fieldCode; // (type<<16)|index
|
||||
const SerializedTypeID fieldType; // STI_*
|
||||
const int fieldValue; // Code number for protocol
|
||||
std::string fieldName;
|
||||
int fieldMeta;
|
||||
int fieldNum;
|
||||
bool signingField;
|
||||
|
||||
SField (int fc, SerializedTypeID tid, int fv, const char* fn)
|
||||
SField (int fc, SerializedTypeID tid, int fv, const char* fn)
|
||||
: fieldCode (fc)
|
||||
, fieldType (tid)
|
||||
, fieldValue (fv)
|
||||
, fieldName (fn)
|
||||
, fieldMeta (sMD_Default)
|
||||
, signingField (true)
|
||||
{
|
||||
boost::mutex::scoped_lock sl(mapMutex);
|
||||
{
|
||||
boost::mutex::scoped_lock sl (mapMutex);
|
||||
|
||||
codeToField[fieldCode] = this;
|
||||
|
||||
fieldNum = ++num;
|
||||
}
|
||||
}
|
||||
|
||||
SField (SerializedTypeID tid, int fv, const char *fn)
|
||||
SField (SerializedTypeID tid, int fv, const char* fn)
|
||||
: fieldCode (FIELD_CODE (tid, fv))
|
||||
, fieldType (tid)
|
||||
, fieldValue (fv)
|
||||
, fieldName (fn)
|
||||
, fieldMeta (sMD_Default)
|
||||
, signingField (true)
|
||||
{
|
||||
boost::mutex::scoped_lock sl(mapMutex);
|
||||
{
|
||||
boost::mutex::scoped_lock sl (mapMutex);
|
||||
|
||||
codeToField[fieldCode] = this;
|
||||
|
||||
fieldNum = ++num;
|
||||
}
|
||||
}
|
||||
|
||||
explicit SField (int fc)
|
||||
explicit SField (int fc)
|
||||
: fieldCode (fc)
|
||||
, fieldType (STI_UNKNOWN)
|
||||
, fieldValue (0)
|
||||
, fieldMeta (sMD_Never)
|
||||
, signingField (true)
|
||||
{
|
||||
boost::mutex::scoped_lock sl(mapMutex);
|
||||
fieldNum = ++num;
|
||||
}
|
||||
{
|
||||
boost::mutex::scoped_lock sl (mapMutex);
|
||||
fieldNum = ++num;
|
||||
}
|
||||
|
||||
~SField ();
|
||||
~SField ();
|
||||
|
||||
static SField::ref getField (int fieldCode);
|
||||
static SField::ref getField (const std::string& fieldName);
|
||||
static SField::ref getField (int type, int value) { return getField(FIELD_CODE(type, value)); }
|
||||
static SField::ref getField (SerializedTypeID type, int value) { return getField(FIELD_CODE(type, value)); }
|
||||
static SField::ref getField (int fieldCode);
|
||||
static SField::ref getField (const std::string& fieldName);
|
||||
static SField::ref getField (int type, int value)
|
||||
{
|
||||
return getField (FIELD_CODE (type, value));
|
||||
}
|
||||
static SField::ref getField (SerializedTypeID type, int value)
|
||||
{
|
||||
return getField (FIELD_CODE (type, value));
|
||||
}
|
||||
|
||||
std::string getName() const;
|
||||
bool hasName() const { return !fieldName.empty(); }
|
||||
std::string getName () const;
|
||||
bool hasName () const
|
||||
{
|
||||
return !fieldName.empty ();
|
||||
}
|
||||
|
||||
bool isGeneric() const { return fieldCode == 0; }
|
||||
bool isInvalid() const { return fieldCode == -1; }
|
||||
bool isUseful() const { return fieldCode > 0; }
|
||||
bool isKnown() const { return fieldType != STI_UNKNOWN; }
|
||||
bool isBinary() const { return fieldValue < 256; }
|
||||
bool isGeneric () const
|
||||
{
|
||||
return fieldCode == 0;
|
||||
}
|
||||
bool isInvalid () const
|
||||
{
|
||||
return fieldCode == -1;
|
||||
}
|
||||
bool isUseful () const
|
||||
{
|
||||
return fieldCode > 0;
|
||||
}
|
||||
bool isKnown () const
|
||||
{
|
||||
return fieldType != STI_UNKNOWN;
|
||||
}
|
||||
bool isBinary () const
|
||||
{
|
||||
return fieldValue < 256;
|
||||
}
|
||||
|
||||
// VFALCO NOTE What is a discardable field?
|
||||
bool isDiscardable() const { return fieldValue > 256; }
|
||||
bool isDiscardable () const
|
||||
{
|
||||
return fieldValue > 256;
|
||||
}
|
||||
|
||||
int getCode() const { return fieldCode; }
|
||||
int getNum() const { return fieldNum; }
|
||||
static int getNumFields() { return num; }
|
||||
int getCode () const
|
||||
{
|
||||
return fieldCode;
|
||||
}
|
||||
int getNum () const
|
||||
{
|
||||
return fieldNum;
|
||||
}
|
||||
static int getNumFields ()
|
||||
{
|
||||
return num;
|
||||
}
|
||||
|
||||
bool isSigningField() const { return signingField; }
|
||||
void notSigningField() { signingField = false; }
|
||||
bool shouldMeta(int c) const { return (fieldMeta & c) != 0; }
|
||||
void setMeta(int c) { fieldMeta = c; }
|
||||
bool isSigningField () const
|
||||
{
|
||||
return signingField;
|
||||
}
|
||||
void notSigningField ()
|
||||
{
|
||||
signingField = false;
|
||||
}
|
||||
bool shouldMeta (int c) const
|
||||
{
|
||||
return (fieldMeta & c) != 0;
|
||||
}
|
||||
void setMeta (int c)
|
||||
{
|
||||
fieldMeta = c;
|
||||
}
|
||||
|
||||
bool shouldInclude(bool withSigningField) const
|
||||
{ return (fieldValue < 256) && (withSigningField || signingField); }
|
||||
bool shouldInclude (bool withSigningField) const
|
||||
{
|
||||
return (fieldValue < 256) && (withSigningField || signingField);
|
||||
}
|
||||
|
||||
bool operator== (const SField& f) const { return fieldCode == f.fieldCode; }
|
||||
bool operator== (const SField& f) const
|
||||
{
|
||||
return fieldCode == f.fieldCode;
|
||||
}
|
||||
|
||||
bool operator!= (const SField& f) const { return fieldCode != f.fieldCode; }
|
||||
bool operator!= (const SField& f) const
|
||||
{
|
||||
return fieldCode != f.fieldCode;
|
||||
}
|
||||
|
||||
static int compare(SField::ref f1, SField::ref f2);
|
||||
static int compare (SField::ref f1, SField::ref f2);
|
||||
|
||||
// VFALCO TODO make these private
|
||||
protected:
|
||||
static std::map<int, ptr> codeToField;
|
||||
static boost::mutex mapMutex;
|
||||
static int num;
|
||||
static std::map<int, ptr> codeToField;
|
||||
static boost::mutex mapMutex;
|
||||
static int num;
|
||||
|
||||
SField (SerializedTypeID id, int val);
|
||||
SField (SerializedTypeID id, int val);
|
||||
};
|
||||
|
||||
extern SField sfInvalid, sfGeneric, sfLedgerEntry, sfTransaction, sfValidation;
|
||||
|
||||
@@ -3,137 +3,143 @@ std::map <int, LedgerEntryFormat*> LedgerEntryFormat::byType;
|
||||
|
||||
std::map <std::string, LedgerEntryFormat*> LedgerEntryFormat::byName;
|
||||
|
||||
#define LEF_BASE \
|
||||
<< SOElement(sfLedgerIndex, SOE_OPTIONAL) \
|
||||
<< SOElement(sfLedgerEntryType, SOE_REQUIRED) \
|
||||
<< SOElement(sfFlags, SOE_REQUIRED)
|
||||
#define LEF_BASE \
|
||||
<< SOElement(sfLedgerIndex, SOE_OPTIONAL) \
|
||||
<< SOElement(sfLedgerEntryType, SOE_REQUIRED) \
|
||||
<< SOElement(sfFlags, SOE_REQUIRED)
|
||||
|
||||
#define DECLARE_LEF(name, type) lef = new LedgerEntryFormat(#name, type); (*lef) LEF_BASE
|
||||
|
||||
void LEFInit()
|
||||
void LEFInit ()
|
||||
{
|
||||
LedgerEntryFormat* lef;
|
||||
LedgerEntryFormat* lef;
|
||||
|
||||
DECLARE_LEF(AccountRoot, ltACCOUNT_ROOT)
|
||||
<< SOElement(sfAccount, SOE_REQUIRED)
|
||||
<< SOElement(sfSequence, SOE_REQUIRED)
|
||||
<< SOElement(sfBalance, SOE_REQUIRED)
|
||||
<< SOElement(sfOwnerCount, SOE_REQUIRED)
|
||||
<< SOElement(sfPreviousTxnID, SOE_REQUIRED)
|
||||
<< SOElement(sfPreviousTxnLgrSeq, SOE_REQUIRED)
|
||||
<< SOElement(sfRegularKey, SOE_OPTIONAL)
|
||||
<< SOElement(sfEmailHash, SOE_OPTIONAL)
|
||||
<< SOElement(sfWalletLocator, SOE_OPTIONAL)
|
||||
<< SOElement(sfWalletSize, SOE_OPTIONAL)
|
||||
<< SOElement(sfMessageKey, SOE_OPTIONAL)
|
||||
<< SOElement(sfTransferRate, SOE_OPTIONAL)
|
||||
<< SOElement(sfDomain, SOE_OPTIONAL)
|
||||
;
|
||||
DECLARE_LEF (AccountRoot, ltACCOUNT_ROOT)
|
||||
<< SOElement (sfAccount, SOE_REQUIRED)
|
||||
<< SOElement (sfSequence, SOE_REQUIRED)
|
||||
<< SOElement (sfBalance, SOE_REQUIRED)
|
||||
<< SOElement (sfOwnerCount, SOE_REQUIRED)
|
||||
<< SOElement (sfPreviousTxnID, SOE_REQUIRED)
|
||||
<< SOElement (sfPreviousTxnLgrSeq, SOE_REQUIRED)
|
||||
<< SOElement (sfRegularKey, SOE_OPTIONAL)
|
||||
<< SOElement (sfEmailHash, SOE_OPTIONAL)
|
||||
<< SOElement (sfWalletLocator, SOE_OPTIONAL)
|
||||
<< SOElement (sfWalletSize, SOE_OPTIONAL)
|
||||
<< SOElement (sfMessageKey, SOE_OPTIONAL)
|
||||
<< SOElement (sfTransferRate, SOE_OPTIONAL)
|
||||
<< SOElement (sfDomain, SOE_OPTIONAL)
|
||||
;
|
||||
|
||||
DECLARE_LEF(Contract, ltCONTRACT)
|
||||
<< SOElement(sfAccount, SOE_REQUIRED)
|
||||
<< SOElement(sfBalance, SOE_REQUIRED)
|
||||
<< SOElement(sfPreviousTxnID, SOE_REQUIRED)
|
||||
<< SOElement(sfPreviousTxnLgrSeq, SOE_REQUIRED)
|
||||
<< SOElement(sfIssuer, SOE_REQUIRED)
|
||||
<< SOElement(sfOwner, SOE_REQUIRED)
|
||||
<< SOElement(sfExpiration, SOE_REQUIRED)
|
||||
<< SOElement(sfBondAmount, SOE_REQUIRED)
|
||||
<< SOElement(sfCreateCode, SOE_OPTIONAL)
|
||||
<< SOElement(sfFundCode, SOE_OPTIONAL)
|
||||
<< SOElement(sfRemoveCode, SOE_OPTIONAL)
|
||||
<< SOElement(sfExpireCode, SOE_OPTIONAL)
|
||||
;
|
||||
DECLARE_LEF (Contract, ltCONTRACT)
|
||||
<< SOElement (sfAccount, SOE_REQUIRED)
|
||||
<< SOElement (sfBalance, SOE_REQUIRED)
|
||||
<< SOElement (sfPreviousTxnID, SOE_REQUIRED)
|
||||
<< SOElement (sfPreviousTxnLgrSeq, SOE_REQUIRED)
|
||||
<< SOElement (sfIssuer, SOE_REQUIRED)
|
||||
<< SOElement (sfOwner, SOE_REQUIRED)
|
||||
<< SOElement (sfExpiration, SOE_REQUIRED)
|
||||
<< SOElement (sfBondAmount, SOE_REQUIRED)
|
||||
<< SOElement (sfCreateCode, SOE_OPTIONAL)
|
||||
<< SOElement (sfFundCode, SOE_OPTIONAL)
|
||||
<< SOElement (sfRemoveCode, SOE_OPTIONAL)
|
||||
<< SOElement (sfExpireCode, SOE_OPTIONAL)
|
||||
;
|
||||
|
||||
DECLARE_LEF(DirectoryNode, ltDIR_NODE)
|
||||
<< SOElement(sfOwner, SOE_OPTIONAL) // for owner directories
|
||||
<< SOElement(sfTakerPaysCurrency, SOE_OPTIONAL) // for order book directories
|
||||
<< SOElement(sfTakerPaysIssuer, SOE_OPTIONAL) // for order book directories
|
||||
<< SOElement(sfTakerGetsCurrency, SOE_OPTIONAL) // for order book directories
|
||||
<< SOElement(sfTakerGetsIssuer, SOE_OPTIONAL) // for order book directories
|
||||
<< SOElement(sfExchangeRate, SOE_OPTIONAL) // for order book directories
|
||||
<< SOElement(sfIndexes, SOE_REQUIRED)
|
||||
<< SOElement(sfRootIndex, SOE_REQUIRED)
|
||||
<< SOElement(sfIndexNext, SOE_OPTIONAL)
|
||||
<< SOElement(sfIndexPrevious, SOE_OPTIONAL)
|
||||
;
|
||||
DECLARE_LEF (DirectoryNode, ltDIR_NODE)
|
||||
<< SOElement (sfOwner, SOE_OPTIONAL) // for owner directories
|
||||
<< SOElement (sfTakerPaysCurrency, SOE_OPTIONAL) // for order book directories
|
||||
<< SOElement (sfTakerPaysIssuer, SOE_OPTIONAL) // for order book directories
|
||||
<< SOElement (sfTakerGetsCurrency, SOE_OPTIONAL) // for order book directories
|
||||
<< SOElement (sfTakerGetsIssuer, SOE_OPTIONAL) // for order book directories
|
||||
<< SOElement (sfExchangeRate, SOE_OPTIONAL) // for order book directories
|
||||
<< SOElement (sfIndexes, SOE_REQUIRED)
|
||||
<< SOElement (sfRootIndex, SOE_REQUIRED)
|
||||
<< SOElement (sfIndexNext, SOE_OPTIONAL)
|
||||
<< SOElement (sfIndexPrevious, SOE_OPTIONAL)
|
||||
;
|
||||
|
||||
DECLARE_LEF(GeneratorMap, ltGENERATOR_MAP)
|
||||
<< SOElement(sfGenerator, SOE_REQUIRED)
|
||||
;
|
||||
DECLARE_LEF (GeneratorMap, ltGENERATOR_MAP)
|
||||
<< SOElement (sfGenerator, SOE_REQUIRED)
|
||||
;
|
||||
|
||||
DECLARE_LEF(Nickname, ltNICKNAME)
|
||||
<< SOElement(sfAccount, SOE_REQUIRED)
|
||||
<< SOElement(sfMinimumOffer, SOE_OPTIONAL)
|
||||
;
|
||||
DECLARE_LEF (Nickname, ltNICKNAME)
|
||||
<< SOElement (sfAccount, SOE_REQUIRED)
|
||||
<< SOElement (sfMinimumOffer, SOE_OPTIONAL)
|
||||
;
|
||||
|
||||
DECLARE_LEF(Offer, ltOFFER)
|
||||
<< SOElement(sfAccount, SOE_REQUIRED)
|
||||
<< SOElement(sfSequence, SOE_REQUIRED)
|
||||
<< SOElement(sfTakerPays, SOE_REQUIRED)
|
||||
<< SOElement(sfTakerGets, SOE_REQUIRED)
|
||||
<< SOElement(sfBookDirectory, SOE_REQUIRED)
|
||||
<< SOElement(sfBookNode, SOE_REQUIRED)
|
||||
<< SOElement(sfOwnerNode, SOE_REQUIRED)
|
||||
<< SOElement(sfPreviousTxnID, SOE_REQUIRED)
|
||||
<< SOElement(sfPreviousTxnLgrSeq, SOE_REQUIRED)
|
||||
<< SOElement(sfExpiration, SOE_OPTIONAL)
|
||||
;
|
||||
DECLARE_LEF (Offer, ltOFFER)
|
||||
<< SOElement (sfAccount, SOE_REQUIRED)
|
||||
<< SOElement (sfSequence, SOE_REQUIRED)
|
||||
<< SOElement (sfTakerPays, SOE_REQUIRED)
|
||||
<< SOElement (sfTakerGets, SOE_REQUIRED)
|
||||
<< SOElement (sfBookDirectory, SOE_REQUIRED)
|
||||
<< SOElement (sfBookNode, SOE_REQUIRED)
|
||||
<< SOElement (sfOwnerNode, SOE_REQUIRED)
|
||||
<< SOElement (sfPreviousTxnID, SOE_REQUIRED)
|
||||
<< SOElement (sfPreviousTxnLgrSeq, SOE_REQUIRED)
|
||||
<< SOElement (sfExpiration, SOE_OPTIONAL)
|
||||
;
|
||||
|
||||
DECLARE_LEF(RippleState, ltRIPPLE_STATE)
|
||||
<< SOElement(sfBalance, SOE_REQUIRED)
|
||||
<< SOElement(sfLowLimit, SOE_REQUIRED)
|
||||
<< SOElement(sfHighLimit, SOE_REQUIRED)
|
||||
<< SOElement(sfPreviousTxnID, SOE_REQUIRED)
|
||||
<< SOElement(sfPreviousTxnLgrSeq, SOE_REQUIRED)
|
||||
<< SOElement(sfLowNode, SOE_OPTIONAL)
|
||||
<< SOElement(sfLowQualityIn, SOE_OPTIONAL)
|
||||
<< SOElement(sfLowQualityOut, SOE_OPTIONAL)
|
||||
<< SOElement(sfHighNode, SOE_OPTIONAL)
|
||||
<< SOElement(sfHighQualityIn, SOE_OPTIONAL)
|
||||
<< SOElement(sfHighQualityOut, SOE_OPTIONAL)
|
||||
;
|
||||
DECLARE_LEF (RippleState, ltRIPPLE_STATE)
|
||||
<< SOElement (sfBalance, SOE_REQUIRED)
|
||||
<< SOElement (sfLowLimit, SOE_REQUIRED)
|
||||
<< SOElement (sfHighLimit, SOE_REQUIRED)
|
||||
<< SOElement (sfPreviousTxnID, SOE_REQUIRED)
|
||||
<< SOElement (sfPreviousTxnLgrSeq, SOE_REQUIRED)
|
||||
<< SOElement (sfLowNode, SOE_OPTIONAL)
|
||||
<< SOElement (sfLowQualityIn, SOE_OPTIONAL)
|
||||
<< SOElement (sfLowQualityOut, SOE_OPTIONAL)
|
||||
<< SOElement (sfHighNode, SOE_OPTIONAL)
|
||||
<< SOElement (sfHighQualityIn, SOE_OPTIONAL)
|
||||
<< SOElement (sfHighQualityOut, SOE_OPTIONAL)
|
||||
;
|
||||
|
||||
DECLARE_LEF(LedgerHashes, ltLEDGER_HASHES)
|
||||
<< SOElement(sfFirstLedgerSequence, SOE_OPTIONAL) // Remove if we do a ledger restart
|
||||
<< SOElement(sfLastLedgerSequence, SOE_OPTIONAL)
|
||||
<< SOElement(sfHashes, SOE_REQUIRED)
|
||||
;
|
||||
DECLARE_LEF (LedgerHashes, ltLEDGER_HASHES)
|
||||
<< SOElement (sfFirstLedgerSequence, SOE_OPTIONAL) // Remove if we do a ledger restart
|
||||
<< SOElement (sfLastLedgerSequence, SOE_OPTIONAL)
|
||||
<< SOElement (sfHashes, SOE_REQUIRED)
|
||||
;
|
||||
|
||||
DECLARE_LEF(EnabledFeatures, ltFEATURES)
|
||||
<< SOElement(sfFeatures, SOE_REQUIRED)
|
||||
;
|
||||
DECLARE_LEF (EnabledFeatures, ltFEATURES)
|
||||
<< SOElement (sfFeatures, SOE_REQUIRED)
|
||||
;
|
||||
|
||||
DECLARE_LEF(FeeSettings, ltFEE_SETTINGS)
|
||||
<< SOElement(sfBaseFee, SOE_REQUIRED)
|
||||
<< SOElement(sfReferenceFeeUnits, SOE_REQUIRED)
|
||||
<< SOElement(sfReserveBase, SOE_REQUIRED)
|
||||
<< SOElement(sfReserveIncrement, SOE_REQUIRED)
|
||||
;
|
||||
DECLARE_LEF (FeeSettings, ltFEE_SETTINGS)
|
||||
<< SOElement (sfBaseFee, SOE_REQUIRED)
|
||||
<< SOElement (sfReferenceFeeUnits, SOE_REQUIRED)
|
||||
<< SOElement (sfReserveBase, SOE_REQUIRED)
|
||||
<< SOElement (sfReserveIncrement, SOE_REQUIRED)
|
||||
;
|
||||
}
|
||||
|
||||
LedgerEntryFormat* LedgerEntryFormat::getLgrFormat(LedgerEntryType t)
|
||||
LedgerEntryFormat* LedgerEntryFormat::getLgrFormat (LedgerEntryType t)
|
||||
{
|
||||
std::map<int, LedgerEntryFormat*>::iterator it = byType.find(static_cast<int>(t));
|
||||
if (it == byType.end())
|
||||
return NULL;
|
||||
return it->second;
|
||||
std::map<int, LedgerEntryFormat*>::iterator it = byType.find (static_cast<int> (t));
|
||||
|
||||
if (it == byType.end ())
|
||||
return NULL;
|
||||
|
||||
return it->second;
|
||||
}
|
||||
|
||||
LedgerEntryFormat* LedgerEntryFormat::getLgrFormat(int t)
|
||||
LedgerEntryFormat* LedgerEntryFormat::getLgrFormat (int t)
|
||||
{
|
||||
std::map<int, LedgerEntryFormat*>::iterator it = byType.find((t));
|
||||
if (it == byType.end())
|
||||
return NULL;
|
||||
return it->second;
|
||||
std::map<int, LedgerEntryFormat*>::iterator it = byType.find ((t));
|
||||
|
||||
if (it == byType.end ())
|
||||
return NULL;
|
||||
|
||||
return it->second;
|
||||
}
|
||||
|
||||
LedgerEntryFormat* LedgerEntryFormat::getLgrFormat(const std::string& t)
|
||||
LedgerEntryFormat* LedgerEntryFormat::getLgrFormat (const std::string& t)
|
||||
{
|
||||
std::map<std::string, LedgerEntryFormat*>::iterator it = byName.find((t));
|
||||
if (it == byName.end())
|
||||
return NULL;
|
||||
return it->second;
|
||||
std::map<std::string, LedgerEntryFormat*>::iterator it = byName.find ((t));
|
||||
|
||||
if (it == byName.end ())
|
||||
return NULL;
|
||||
|
||||
return it->second;
|
||||
}
|
||||
|
||||
// vim:ts=4
|
||||
|
||||
@@ -4,79 +4,79 @@
|
||||
// Used as the type of a transaction or the type of a ledger entry.
|
||||
enum LedgerEntryType
|
||||
{
|
||||
ltINVALID = -1,
|
||||
ltACCOUNT_ROOT = 'a',
|
||||
ltDIR_NODE = 'd',
|
||||
ltGENERATOR_MAP = 'g',
|
||||
ltRIPPLE_STATE = 'r',
|
||||
ltNICKNAME = 'n',
|
||||
ltOFFER = 'o',
|
||||
ltCONTRACT = 'c',
|
||||
ltLEDGER_HASHES = 'h',
|
||||
ltFEATURES = 'f',
|
||||
ltFEE_SETTINGS = 's',
|
||||
ltINVALID = -1,
|
||||
ltACCOUNT_ROOT = 'a',
|
||||
ltDIR_NODE = 'd',
|
||||
ltGENERATOR_MAP = 'g',
|
||||
ltRIPPLE_STATE = 'r',
|
||||
ltNICKNAME = 'n',
|
||||
ltOFFER = 'o',
|
||||
ltCONTRACT = 'c',
|
||||
ltLEDGER_HASHES = 'h',
|
||||
ltFEATURES = 'f',
|
||||
ltFEE_SETTINGS = 's',
|
||||
};
|
||||
|
||||
// Used as a prefix for computing ledger indexes (keys).
|
||||
enum LedgerNameSpace
|
||||
{
|
||||
spaceAccount = 'a',
|
||||
spaceDirNode = 'd',
|
||||
spaceGenerator = 'g',
|
||||
spaceNickname = 'n',
|
||||
spaceRipple = 'r',
|
||||
spaceOffer = 'o', // Entry for an offer.
|
||||
spaceOwnerDir = 'O', // Directory of things owned by an account.
|
||||
spaceBookDir = 'B', // Directory of order books.
|
||||
spaceContract = 'c',
|
||||
spaceSkipList = 's',
|
||||
spaceFeature = 'f',
|
||||
spaceFee = 'e',
|
||||
spaceAccount = 'a',
|
||||
spaceDirNode = 'd',
|
||||
spaceGenerator = 'g',
|
||||
spaceNickname = 'n',
|
||||
spaceRipple = 'r',
|
||||
spaceOffer = 'o', // Entry for an offer.
|
||||
spaceOwnerDir = 'O', // Directory of things owned by an account.
|
||||
spaceBookDir = 'B', // Directory of order books.
|
||||
spaceContract = 'c',
|
||||
spaceSkipList = 's',
|
||||
spaceFeature = 'f',
|
||||
spaceFee = 'e',
|
||||
};
|
||||
|
||||
enum LedgerSpecificFlags
|
||||
{
|
||||
// ltACCOUNT_ROOT
|
||||
lsfPasswordSpent = 0x00010000, // True, if password set fee is spent.
|
||||
lsfRequireDestTag = 0x00020000, // True, to require a DestinationTag for payments.
|
||||
lsfRequireAuth = 0x00040000, // True, to require a authorization to hold IOUs.
|
||||
lsfDisallowXRP = 0x00080000, // True, to disallow sending XRP.
|
||||
// ltACCOUNT_ROOT
|
||||
lsfPasswordSpent = 0x00010000, // True, if password set fee is spent.
|
||||
lsfRequireDestTag = 0x00020000, // True, to require a DestinationTag for payments.
|
||||
lsfRequireAuth = 0x00040000, // True, to require a authorization to hold IOUs.
|
||||
lsfDisallowXRP = 0x00080000, // True, to disallow sending XRP.
|
||||
|
||||
// ltOFFER
|
||||
lsfPassive = 0x00010000,
|
||||
lsfSell = 0x00020000, // True, offer was placed as a sell.
|
||||
// ltOFFER
|
||||
lsfPassive = 0x00010000,
|
||||
lsfSell = 0x00020000, // True, offer was placed as a sell.
|
||||
|
||||
// ltRIPPLE_STATE
|
||||
lsfLowReserve = 0x00010000, // True, if entry counts toward reserve.
|
||||
lsfHighReserve = 0x00020000,
|
||||
lsfLowAuth = 0x00040000,
|
||||
lsfHighAuth = 0x00080000,
|
||||
// ltRIPPLE_STATE
|
||||
lsfLowReserve = 0x00010000, // True, if entry counts toward reserve.
|
||||
lsfHighReserve = 0x00020000,
|
||||
lsfLowAuth = 0x00040000,
|
||||
lsfHighAuth = 0x00080000,
|
||||
};
|
||||
|
||||
class LedgerEntryFormat
|
||||
{
|
||||
public:
|
||||
std::string t_name;
|
||||
LedgerEntryType t_type;
|
||||
SOTemplate elements;
|
||||
std::string t_name;
|
||||
LedgerEntryType t_type;
|
||||
SOTemplate elements;
|
||||
|
||||
static std::map<int, LedgerEntryFormat*> byType;
|
||||
static std::map<std::string, LedgerEntryFormat*> byName;
|
||||
static std::map<int, LedgerEntryFormat*> byType;
|
||||
static std::map<std::string, LedgerEntryFormat*> byName;
|
||||
|
||||
LedgerEntryFormat(const char *name, LedgerEntryType type) : t_name(name), t_type(type)
|
||||
{
|
||||
byName[name] = this;
|
||||
byType[type] = this;
|
||||
}
|
||||
LedgerEntryFormat& operator<<(const SOElement& el)
|
||||
{
|
||||
elements.push_back(el);
|
||||
return *this;
|
||||
}
|
||||
LedgerEntryFormat (const char* name, LedgerEntryType type) : t_name (name), t_type (type)
|
||||
{
|
||||
byName[name] = this;
|
||||
byType[type] = this;
|
||||
}
|
||||
LedgerEntryFormat& operator<< (const SOElement& el)
|
||||
{
|
||||
elements.push_back (el);
|
||||
return *this;
|
||||
}
|
||||
|
||||
static LedgerEntryFormat* getLgrFormat(LedgerEntryType t);
|
||||
static LedgerEntryFormat* getLgrFormat(const std::string& t);
|
||||
static LedgerEntryFormat* getLgrFormat(int t);
|
||||
static LedgerEntryFormat* getLgrFormat (LedgerEntryType t);
|
||||
static LedgerEntryFormat* getLgrFormat (const std::string& t);
|
||||
static LedgerEntryFormat* getLgrFormat (int t);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
PackedMessage::PackedMessage (::google::protobuf::Message const& message, int type)
|
||||
{
|
||||
unsigned const messageBytes = message.ByteSize ();
|
||||
unsigned const messageBytes = message.ByteSize ();
|
||||
|
||||
assert (messageBytes != 0);
|
||||
|
||||
@@ -11,30 +11,33 @@ PackedMessage::PackedMessage (::google::protobuf::Message const& message, int ty
|
||||
encodeHeader (messageBytes, type);
|
||||
|
||||
if (messageBytes != 0)
|
||||
{
|
||||
message.SerializeToArray (&mBuffer [PackedMessage::kHeaderBytes], messageBytes);
|
||||
{
|
||||
message.SerializeToArray (&mBuffer [PackedMessage::kHeaderBytes], messageBytes);
|
||||
|
||||
#ifdef DEBUG
|
||||
// std::cerr << "PackedMessage: type=" << type << ", datalen=" << msg_size << std::endl;
|
||||
// std::cerr << "PackedMessage: type=" << type << ", datalen=" << msg_size << std::endl;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool PackedMessage::operator== (PackedMessage const& other) const
|
||||
{
|
||||
return mBuffer == other.mBuffer;
|
||||
return mBuffer == other.mBuffer;
|
||||
}
|
||||
|
||||
unsigned PackedMessage::getLength (std::vector <uint8_t> const& buf)
|
||||
{
|
||||
unsigned result;
|
||||
|
||||
if (buf.size() >= PackedMessage::kHeaderBytes)
|
||||
if (buf.size () >= PackedMessage::kHeaderBytes)
|
||||
{
|
||||
result = buf [0];
|
||||
result <<= 8; result |= buf [1];
|
||||
result <<= 8; result |= buf [2];
|
||||
result <<= 8; result |= buf [3];
|
||||
result = buf [0];
|
||||
result <<= 8;
|
||||
result |= buf [1];
|
||||
result <<= 8;
|
||||
result |= buf [2];
|
||||
result <<= 8;
|
||||
result |= buf [3];
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -46,21 +49,22 @@ unsigned PackedMessage::getLength (std::vector <uint8_t> const& buf)
|
||||
|
||||
int PackedMessage::getType (std::vector<uint8_t> const& buf)
|
||||
{
|
||||
if(buf.size() < PackedMessage::kHeaderBytes)
|
||||
return 0;
|
||||
if (buf.size () < PackedMessage::kHeaderBytes)
|
||||
return 0;
|
||||
|
||||
int ret = buf[4];
|
||||
ret <<= 8; ret |= buf[5];
|
||||
return ret;
|
||||
int ret = buf[4];
|
||||
ret <<= 8;
|
||||
ret |= buf[5];
|
||||
return ret;
|
||||
}
|
||||
|
||||
void PackedMessage::encodeHeader (unsigned size, int type)
|
||||
{
|
||||
assert(mBuffer.size() >= PackedMessage::kHeaderBytes);
|
||||
mBuffer[0] = static_cast<boost::uint8_t>((size >> 24) & 0xFF);
|
||||
mBuffer[1] = static_cast<boost::uint8_t>((size >> 16) & 0xFF);
|
||||
mBuffer[2] = static_cast<boost::uint8_t>((size >> 8) & 0xFF);
|
||||
mBuffer[3] = static_cast<boost::uint8_t>(size & 0xFF);
|
||||
mBuffer[4] = static_cast<boost::uint8_t>((type >> 8) & 0xFF);
|
||||
mBuffer[5] = static_cast<boost::uint8_t>(type & 0xFF);
|
||||
assert (mBuffer.size () >= PackedMessage::kHeaderBytes);
|
||||
mBuffer[0] = static_cast<boost::uint8_t> ((size >> 24) & 0xFF);
|
||||
mBuffer[1] = static_cast<boost::uint8_t> ((size >> 16) & 0xFF);
|
||||
mBuffer[2] = static_cast<boost::uint8_t> ((size >> 8) & 0xFF);
|
||||
mBuffer[3] = static_cast<boost::uint8_t> (size & 0xFF);
|
||||
mBuffer[4] = static_cast<boost::uint8_t> ((type >> 8) & 0xFF);
|
||||
mBuffer[5] = static_cast<boost::uint8_t> (type & 0xFF);
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@ class PackedMessage : public boost::enable_shared_from_this <PackedMessage>
|
||||
{
|
||||
public:
|
||||
typedef boost::shared_ptr< ::google::protobuf::Message > MessagePointer;
|
||||
typedef boost::shared_ptr<PackedMessage> pointer;
|
||||
typedef boost::shared_ptr<PackedMessage> pointer;
|
||||
|
||||
public:
|
||||
/** Number of bytes in a message header.
|
||||
@@ -26,27 +26,27 @@ public:
|
||||
/** Retrieve the packed message data.
|
||||
*/
|
||||
// VFALCO TODO shouldn't this be const?
|
||||
std::vector <uint8_t>& getBuffer()
|
||||
std::vector <uint8_t>& getBuffer ()
|
||||
{
|
||||
return mBuffer;
|
||||
}
|
||||
|
||||
/** Determine bytewise equality.
|
||||
*/
|
||||
bool operator == (PackedMessage const& other) const;
|
||||
bool operator == (PackedMessage const& other) const;
|
||||
|
||||
/** Calculate the length of a packed message.
|
||||
*/
|
||||
static unsigned getLength (std::vector <uint8_t> const& buf);
|
||||
static unsigned getLength (std::vector <uint8_t> const& buf);
|
||||
|
||||
/** Determine the type of a packed message.
|
||||
*/
|
||||
static int getType (std::vector <uint8_t> const& buf);
|
||||
|
||||
private:
|
||||
// Encodes the size and type into a header at the beginning of buf
|
||||
//
|
||||
void encodeHeader (unsigned size, int type);
|
||||
// Encodes the size and type into a header at the beginning of buf
|
||||
//
|
||||
void encodeHeader (unsigned size, int type);
|
||||
|
||||
std::vector <uint8_t> mBuffer;
|
||||
};
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -8,180 +8,194 @@
|
||||
class RippleAddress : public CBase58Data
|
||||
{
|
||||
private:
|
||||
typedef enum {
|
||||
VER_NONE = 1,
|
||||
VER_NODE_PUBLIC = 28,
|
||||
VER_NODE_PRIVATE = 32,
|
||||
VER_ACCOUNT_ID = 0,
|
||||
VER_ACCOUNT_PUBLIC = 35,
|
||||
VER_ACCOUNT_PRIVATE = 34,
|
||||
VER_FAMILY_GENERATOR = 41,
|
||||
VER_FAMILY_SEED = 33,
|
||||
} VersionEncoding;
|
||||
typedef enum
|
||||
{
|
||||
VER_NONE = 1,
|
||||
VER_NODE_PUBLIC = 28,
|
||||
VER_NODE_PRIVATE = 32,
|
||||
VER_ACCOUNT_ID = 0,
|
||||
VER_ACCOUNT_PUBLIC = 35,
|
||||
VER_ACCOUNT_PRIVATE = 34,
|
||||
VER_FAMILY_GENERATOR = 41,
|
||||
VER_FAMILY_SEED = 33,
|
||||
} VersionEncoding;
|
||||
|
||||
bool mIsValid;
|
||||
bool mIsValid;
|
||||
|
||||
public:
|
||||
RippleAddress();
|
||||
RippleAddress ();
|
||||
|
||||
// For public and private key, checks if they are legal.
|
||||
bool isValid() const { return mIsValid; }
|
||||
// For public and private key, checks if they are legal.
|
||||
bool isValid () const
|
||||
{
|
||||
return mIsValid;
|
||||
}
|
||||
|
||||
void clear();
|
||||
bool isSet() const;
|
||||
void clear ();
|
||||
bool isSet () const;
|
||||
|
||||
std::string humanAddressType() const;
|
||||
std::string humanAddressType () const;
|
||||
|
||||
//
|
||||
// Node Public - Also used for Validators
|
||||
//
|
||||
uint160 getNodeID() const;
|
||||
Blob const& getNodePublic() const;
|
||||
//
|
||||
// Node Public - Also used for Validators
|
||||
//
|
||||
uint160 getNodeID () const;
|
||||
Blob const& getNodePublic () const;
|
||||
|
||||
std::string humanNodePublic() const;
|
||||
std::string humanNodePublic () const;
|
||||
|
||||
bool setNodePublic(const std::string& strPublic);
|
||||
void setNodePublic(Blob const& vPublic);
|
||||
bool verifyNodePublic(uint256 const& hash, Blob const& vchSig) const;
|
||||
bool verifyNodePublic(uint256 const& hash, const std::string& strSig) const;
|
||||
bool setNodePublic (const std::string& strPublic);
|
||||
void setNodePublic (Blob const& vPublic);
|
||||
bool verifyNodePublic (uint256 const& hash, Blob const& vchSig) const;
|
||||
bool verifyNodePublic (uint256 const& hash, const std::string& strSig) const;
|
||||
|
||||
static RippleAddress createNodePublic(const RippleAddress& naSeed);
|
||||
static RippleAddress createNodePublic(Blob const& vPublic);
|
||||
static RippleAddress createNodePublic(const std::string& strPublic);
|
||||
static RippleAddress createNodePublic (const RippleAddress& naSeed);
|
||||
static RippleAddress createNodePublic (Blob const& vPublic);
|
||||
static RippleAddress createNodePublic (const std::string& strPublic);
|
||||
|
||||
//
|
||||
// Node Private
|
||||
//
|
||||
Blob const& getNodePrivateData() const;
|
||||
uint256 getNodePrivate() const;
|
||||
//
|
||||
// Node Private
|
||||
//
|
||||
Blob const& getNodePrivateData () const;
|
||||
uint256 getNodePrivate () const;
|
||||
|
||||
std::string humanNodePrivate() const;
|
||||
std::string humanNodePrivate () const;
|
||||
|
||||
bool setNodePrivate(const std::string& strPrivate);
|
||||
void setNodePrivate(Blob const& vPrivate);
|
||||
void setNodePrivate(uint256 hash256);
|
||||
void signNodePrivate(uint256 const& hash, Blob& vchSig) const;
|
||||
bool setNodePrivate (const std::string& strPrivate);
|
||||
void setNodePrivate (Blob const& vPrivate);
|
||||
void setNodePrivate (uint256 hash256);
|
||||
void signNodePrivate (uint256 const& hash, Blob& vchSig) const;
|
||||
|
||||
static RippleAddress createNodePrivate(const RippleAddress& naSeed);
|
||||
static RippleAddress createNodePrivate (const RippleAddress& naSeed);
|
||||
|
||||
//
|
||||
// Accounts IDs
|
||||
//
|
||||
uint160 getAccountID() const;
|
||||
//
|
||||
// Accounts IDs
|
||||
//
|
||||
uint160 getAccountID () const;
|
||||
|
||||
std::string humanAccountID() const;
|
||||
std::string humanAccountID () const;
|
||||
|
||||
bool setAccountID(const std::string& strAccountID, const char* pAlphabet=Base58::getCurrentAlphabet ());
|
||||
void setAccountID(const uint160& hash160In);
|
||||
bool setAccountID (const std::string& strAccountID, const char* pAlphabet = Base58::getCurrentAlphabet ());
|
||||
void setAccountID (const uint160& hash160In);
|
||||
|
||||
static RippleAddress createAccountID(const std::string& strAccountID)
|
||||
{ RippleAddress na; na.setAccountID(strAccountID); return na; }
|
||||
static RippleAddress createAccountID (const std::string& strAccountID)
|
||||
{
|
||||
RippleAddress na;
|
||||
na.setAccountID (strAccountID);
|
||||
return na;
|
||||
}
|
||||
|
||||
static RippleAddress createAccountID(const uint160& uiAccountID);
|
||||
static RippleAddress createAccountID (const uint160& uiAccountID);
|
||||
|
||||
static std::string createHumanAccountID(const uint160& uiAccountID)
|
||||
{ return createAccountID(uiAccountID).humanAccountID(); }
|
||||
static std::string createHumanAccountID (const uint160& uiAccountID)
|
||||
{
|
||||
return createAccountID (uiAccountID).humanAccountID ();
|
||||
}
|
||||
|
||||
static std::string createHumanAccountID(Blob const& vPrivate)
|
||||
{ return createAccountPrivate(vPrivate).humanAccountID(); }
|
||||
static std::string createHumanAccountID (Blob const& vPrivate)
|
||||
{
|
||||
return createAccountPrivate (vPrivate).humanAccountID ();
|
||||
}
|
||||
|
||||
//
|
||||
// Accounts Public
|
||||
//
|
||||
Blob const& getAccountPublic() const;
|
||||
//
|
||||
// Accounts Public
|
||||
//
|
||||
Blob const& getAccountPublic () const;
|
||||
|
||||
std::string humanAccountPublic() const;
|
||||
std::string humanAccountPublic () const;
|
||||
|
||||
bool setAccountPublic(const std::string& strPublic);
|
||||
void setAccountPublic(Blob const& vPublic);
|
||||
void setAccountPublic(const RippleAddress& generator, int seq);
|
||||
bool setAccountPublic (const std::string& strPublic);
|
||||
void setAccountPublic (Blob const& vPublic);
|
||||
void setAccountPublic (const RippleAddress& generator, int seq);
|
||||
|
||||
bool accountPublicVerify(uint256 const& uHash, Blob const& vucSig) const;
|
||||
bool accountPublicVerify (uint256 const& uHash, Blob const& vucSig) const;
|
||||
|
||||
static RippleAddress createAccountPublic(Blob const& vPublic)
|
||||
{
|
||||
RippleAddress naNew;
|
||||
static RippleAddress createAccountPublic (Blob const& vPublic)
|
||||
{
|
||||
RippleAddress naNew;
|
||||
|
||||
naNew.setAccountPublic(vPublic);
|
||||
naNew.setAccountPublic (vPublic);
|
||||
|
||||
return naNew;
|
||||
}
|
||||
return naNew;
|
||||
}
|
||||
|
||||
static std::string createHumanAccountPublic(Blob const& vPublic) {
|
||||
return createAccountPublic(vPublic).humanAccountPublic();
|
||||
}
|
||||
static std::string createHumanAccountPublic (Blob const& vPublic)
|
||||
{
|
||||
return createAccountPublic (vPublic).humanAccountPublic ();
|
||||
}
|
||||
|
||||
// Create a deterministic public key from a public generator.
|
||||
static RippleAddress createAccountPublic(const RippleAddress& naGenerator, int iSeq);
|
||||
// Create a deterministic public key from a public generator.
|
||||
static RippleAddress createAccountPublic (const RippleAddress& naGenerator, int iSeq);
|
||||
|
||||
//
|
||||
// Accounts Private
|
||||
//
|
||||
uint256 getAccountPrivate() const;
|
||||
//
|
||||
// Accounts Private
|
||||
//
|
||||
uint256 getAccountPrivate () const;
|
||||
|
||||
std::string humanAccountPrivate() const;
|
||||
std::string humanAccountPrivate () const;
|
||||
|
||||
bool setAccountPrivate(const std::string& strPrivate);
|
||||
void setAccountPrivate(Blob const& vPrivate);
|
||||
void setAccountPrivate(uint256 hash256);
|
||||
void setAccountPrivate(const RippleAddress& naGenerator, const RippleAddress& naSeed, int seq);
|
||||
bool setAccountPrivate (const std::string& strPrivate);
|
||||
void setAccountPrivate (Blob const& vPrivate);
|
||||
void setAccountPrivate (uint256 hash256);
|
||||
void setAccountPrivate (const RippleAddress& naGenerator, const RippleAddress& naSeed, int seq);
|
||||
|
||||
bool accountPrivateSign(uint256 const& uHash, Blob& vucSig) const;
|
||||
// bool accountPrivateVerify(uint256 const& uHash, Blob const& vucSig) const;
|
||||
bool accountPrivateSign (uint256 const& uHash, Blob& vucSig) const;
|
||||
// bool accountPrivateVerify(uint256 const& uHash, Blob const& vucSig) const;
|
||||
|
||||
// Encrypt a message.
|
||||
Blob accountPrivateEncrypt(const RippleAddress& naPublicTo, Blob const& vucPlainText) const;
|
||||
// Encrypt a message.
|
||||
Blob accountPrivateEncrypt (const RippleAddress& naPublicTo, Blob const& vucPlainText) const;
|
||||
|
||||
// Decrypt a message.
|
||||
Blob accountPrivateDecrypt(const RippleAddress& naPublicFrom, Blob const& vucCipherText) const;
|
||||
// Decrypt a message.
|
||||
Blob accountPrivateDecrypt (const RippleAddress& naPublicFrom, Blob const& vucCipherText) const;
|
||||
|
||||
static RippleAddress createAccountPrivate(const RippleAddress& naGenerator, const RippleAddress& naSeed, int iSeq);
|
||||
static RippleAddress createAccountPrivate (const RippleAddress& naGenerator, const RippleAddress& naSeed, int iSeq);
|
||||
|
||||
static RippleAddress createAccountPrivate(Blob const& vPrivate)
|
||||
{
|
||||
RippleAddress naNew;
|
||||
static RippleAddress createAccountPrivate (Blob const& vPrivate)
|
||||
{
|
||||
RippleAddress naNew;
|
||||
|
||||
naNew.setAccountPrivate(vPrivate);
|
||||
naNew.setAccountPrivate (vPrivate);
|
||||
|
||||
return naNew;
|
||||
}
|
||||
return naNew;
|
||||
}
|
||||
|
||||
static std::string createHumanAccountPrivate(Blob const& vPrivate) {
|
||||
return createAccountPrivate(vPrivate).humanAccountPrivate();
|
||||
}
|
||||
static std::string createHumanAccountPrivate (Blob const& vPrivate)
|
||||
{
|
||||
return createAccountPrivate (vPrivate).humanAccountPrivate ();
|
||||
}
|
||||
|
||||
//
|
||||
// Generators
|
||||
// Use to generate a master or regular family.
|
||||
//
|
||||
BIGNUM* getGeneratorBN() const; // DEPRECATED
|
||||
Blob const& getGenerator() const;
|
||||
//
|
||||
// Generators
|
||||
// Use to generate a master or regular family.
|
||||
//
|
||||
BIGNUM* getGeneratorBN () const; // DEPRECATED
|
||||
Blob const& getGenerator () const;
|
||||
|
||||
std::string humanGenerator() const;
|
||||
std::string humanGenerator () const;
|
||||
|
||||
bool setGenerator(const std::string& strGenerator);
|
||||
void setGenerator(Blob const& vPublic);
|
||||
// void setGenerator(const RippleAddress& seed);
|
||||
bool setGenerator (const std::string& strGenerator);
|
||||
void setGenerator (Blob const& vPublic);
|
||||
// void setGenerator(const RippleAddress& seed);
|
||||
|
||||
// Create generator for making public deterministic keys.
|
||||
static RippleAddress createGeneratorPublic(const RippleAddress& naSeed);
|
||||
// Create generator for making public deterministic keys.
|
||||
static RippleAddress createGeneratorPublic (const RippleAddress& naSeed);
|
||||
|
||||
//
|
||||
// Seeds
|
||||
// Clients must disallow reconizable entries from being seeds.
|
||||
uint128 getSeed() const;
|
||||
//
|
||||
// Seeds
|
||||
// Clients must disallow reconizable entries from being seeds.
|
||||
uint128 getSeed () const;
|
||||
|
||||
std::string humanSeed() const;
|
||||
std::string humanSeed1751() const;
|
||||
std::string humanSeed () const;
|
||||
std::string humanSeed1751 () const;
|
||||
|
||||
bool setSeed(const std::string& strSeed);
|
||||
int setSeed1751(const std::string& strHuman1751);
|
||||
bool setSeedGeneric(const std::string& strText);
|
||||
void setSeed(uint128 hash128);
|
||||
void setSeedRandom();
|
||||
bool setSeed (const std::string& strSeed);
|
||||
int setSeed1751 (const std::string& strHuman1751);
|
||||
bool setSeedGeneric (const std::string& strText);
|
||||
void setSeed (uint128 hash128);
|
||||
void setSeedRandom ();
|
||||
|
||||
static RippleAddress createSeedRandom();
|
||||
static RippleAddress createSeedGeneric(const std::string& strText);
|
||||
static RippleAddress createSeedRandom ();
|
||||
static RippleAddress createSeedGeneric (const std::string& strText);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -33,9 +33,9 @@ public:
|
||||
// the point of call, i.e. "User-agent:" SYSTEM_NAME
|
||||
// It will be necessary to rewrite some of them to use string streams.
|
||||
//
|
||||
#define SYSTEM_NAME "ripple"
|
||||
#define SYSTEM_CURRENCY_CODE "XRP"
|
||||
#define SYSTEM_CURRENCY_PRECISION 6
|
||||
#define SYSTEM_CURRENCY_CODE_RIPPLE "XRR"
|
||||
#define SYSTEM_NAME "ripple"
|
||||
#define SYSTEM_CURRENCY_CODE "XRP"
|
||||
#define SYSTEM_CURRENCY_PRECISION 6
|
||||
#define SYSTEM_CURRENCY_CODE_RIPPLE "XRR"
|
||||
|
||||
#endif
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,324 +1,348 @@
|
||||
|
||||
// CAUTION: This is early code and is *NOT* ready for real use yet.
|
||||
|
||||
static void canonicalizeRound(bool isNative, uint64& value, int& offset, bool roundUp)
|
||||
static void canonicalizeRound (bool isNative, uint64& value, int& offset, bool roundUp)
|
||||
{
|
||||
if (!roundUp) // canonicalize already rounds down
|
||||
return;
|
||||
if (!roundUp) // canonicalize already rounds down
|
||||
return;
|
||||
|
||||
WriteLog (lsTRACE, STAmount) << "canonicalize< " << value << ":" << offset << (roundUp ? " up" : " down");
|
||||
if (isNative)
|
||||
{
|
||||
if (offset < 0)
|
||||
{
|
||||
int loops = 0;
|
||||
while (offset < -1)
|
||||
{
|
||||
value /= 10;
|
||||
++offset;
|
||||
++loops;
|
||||
}
|
||||
value += (loops >= 2) ? 9 : 10; // add before last divide
|
||||
value /= 10;
|
||||
++offset;
|
||||
}
|
||||
}
|
||||
else if (value > STAmount::cMaxValue)
|
||||
{
|
||||
while (value > (10 * STAmount::cMaxValue))
|
||||
{
|
||||
value /= 10;
|
||||
++offset;
|
||||
}
|
||||
value += 9; // add before last divide
|
||||
value /= 10;
|
||||
++offset;
|
||||
}
|
||||
WriteLog (lsTRACE, STAmount) << "canonicalize> " << value << ":" << offset << (roundUp ? " up" : " down");
|
||||
WriteLog (lsTRACE, STAmount) << "canonicalize< " << value << ":" << offset << (roundUp ? " up" : " down");
|
||||
|
||||
if (isNative)
|
||||
{
|
||||
if (offset < 0)
|
||||
{
|
||||
int loops = 0;
|
||||
|
||||
while (offset < -1)
|
||||
{
|
||||
value /= 10;
|
||||
++offset;
|
||||
++loops;
|
||||
}
|
||||
|
||||
value += (loops >= 2) ? 9 : 10; // add before last divide
|
||||
value /= 10;
|
||||
++offset;
|
||||
}
|
||||
}
|
||||
else if (value > STAmount::cMaxValue)
|
||||
{
|
||||
while (value > (10 * STAmount::cMaxValue))
|
||||
{
|
||||
value /= 10;
|
||||
++offset;
|
||||
}
|
||||
|
||||
value += 9; // add before last divide
|
||||
value /= 10;
|
||||
++offset;
|
||||
}
|
||||
|
||||
WriteLog (lsTRACE, STAmount) << "canonicalize> " << value << ":" << offset << (roundUp ? " up" : " down");
|
||||
}
|
||||
|
||||
STAmount STAmount::addRound(const STAmount& v1, const STAmount& v2, bool roundUp)
|
||||
STAmount STAmount::addRound (const STAmount& v1, const STAmount& v2, bool roundUp)
|
||||
{
|
||||
v1.throwComparable(v2);
|
||||
v1.throwComparable (v2);
|
||||
|
||||
if (v2.mValue == 0)
|
||||
return v1;
|
||||
if (v2.mValue == 0)
|
||||
return v1;
|
||||
|
||||
if (v1.mValue == 0)
|
||||
return STAmount(v1.getFName(), v1.mCurrency, v1.mIssuer, v2.mValue, v2.mOffset, v2.mIsNegative);
|
||||
if (v1.mValue == 0)
|
||||
return STAmount (v1.getFName (), v1.mCurrency, v1.mIssuer, v2.mValue, v2.mOffset, v2.mIsNegative);
|
||||
|
||||
if (v1.mIsNative)
|
||||
return STAmount(v1.getFName(), v1.getSNValue() + v2.getSNValue());
|
||||
if (v1.mIsNative)
|
||||
return STAmount (v1.getFName (), v1.getSNValue () + v2.getSNValue ());
|
||||
|
||||
int ov1 = v1.mOffset, ov2 = v2.mOffset;
|
||||
int64 vv1 = static_cast<int64>(v1.mValue), vv2 = static_cast<uint64>(v2.mValue);
|
||||
if (v1.mIsNegative)
|
||||
vv1 = -vv1;
|
||||
if (v2.mIsNegative)
|
||||
vv2 = -vv2;
|
||||
int ov1 = v1.mOffset, ov2 = v2.mOffset;
|
||||
int64 vv1 = static_cast<int64> (v1.mValue), vv2 = static_cast<uint64> (v2.mValue);
|
||||
|
||||
if (ov1 < ov2)
|
||||
{
|
||||
while (ov1 < (ov2 - 1))
|
||||
{
|
||||
vv1 /= 10;
|
||||
++ov1;
|
||||
}
|
||||
if (roundUp)
|
||||
vv1 += 9;
|
||||
vv1 /= 10;
|
||||
++ov1;
|
||||
}
|
||||
if (v1.mIsNegative)
|
||||
vv1 = -vv1;
|
||||
|
||||
if (ov2 < ov1)
|
||||
{
|
||||
while (ov2 < (ov1 - 1))
|
||||
{
|
||||
vv2 /= 10;
|
||||
++ov2;
|
||||
}
|
||||
if (roundUp)
|
||||
vv2 += 9;
|
||||
vv2 /= 10;
|
||||
++ov2;
|
||||
}
|
||||
if (v2.mIsNegative)
|
||||
vv2 = -vv2;
|
||||
|
||||
int64 fv = vv1 + vv2;
|
||||
if ((fv >= -10) && (fv <= 10))
|
||||
return STAmount(v1.getFName(), v1.mCurrency, v1.mIssuer);
|
||||
else if (fv >= 0)
|
||||
{
|
||||
uint64 v = static_cast<uint64>(fv);
|
||||
canonicalizeRound(false, v, ov1, roundUp);
|
||||
return STAmount(v1.getFName(), v1.mCurrency, v1.mIssuer, v, ov1, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
uint64 v = static_cast<uint64>(-fv);
|
||||
canonicalizeRound(false, v, ov1, !roundUp);
|
||||
return STAmount(v1.getFName(), v1.mCurrency, v1.mIssuer, v, ov1, true);
|
||||
}
|
||||
if (ov1 < ov2)
|
||||
{
|
||||
while (ov1 < (ov2 - 1))
|
||||
{
|
||||
vv1 /= 10;
|
||||
++ov1;
|
||||
}
|
||||
|
||||
if (roundUp)
|
||||
vv1 += 9;
|
||||
|
||||
vv1 /= 10;
|
||||
++ov1;
|
||||
}
|
||||
|
||||
if (ov2 < ov1)
|
||||
{
|
||||
while (ov2 < (ov1 - 1))
|
||||
{
|
||||
vv2 /= 10;
|
||||
++ov2;
|
||||
}
|
||||
|
||||
if (roundUp)
|
||||
vv2 += 9;
|
||||
|
||||
vv2 /= 10;
|
||||
++ov2;
|
||||
}
|
||||
|
||||
int64 fv = vv1 + vv2;
|
||||
|
||||
if ((fv >= -10) && (fv <= 10))
|
||||
return STAmount (v1.getFName (), v1.mCurrency, v1.mIssuer);
|
||||
else if (fv >= 0)
|
||||
{
|
||||
uint64 v = static_cast<uint64> (fv);
|
||||
canonicalizeRound (false, v, ov1, roundUp);
|
||||
return STAmount (v1.getFName (), v1.mCurrency, v1.mIssuer, v, ov1, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
uint64 v = static_cast<uint64> (-fv);
|
||||
canonicalizeRound (false, v, ov1, !roundUp);
|
||||
return STAmount (v1.getFName (), v1.mCurrency, v1.mIssuer, v, ov1, true);
|
||||
}
|
||||
}
|
||||
|
||||
STAmount STAmount::subRound(const STAmount& v1, const STAmount& v2, bool roundUp)
|
||||
STAmount STAmount::subRound (const STAmount& v1, const STAmount& v2, bool roundUp)
|
||||
{
|
||||
v1.throwComparable(v2);
|
||||
v1.throwComparable (v2);
|
||||
|
||||
if (v2.mValue == 0)
|
||||
return v1;
|
||||
if (v2.mValue == 0)
|
||||
return v1;
|
||||
|
||||
if (v1.mValue == 0)
|
||||
return STAmount(v1.getFName(), v1.mCurrency, v1.mIssuer, v2.mValue, v2.mOffset, !v2.mIsNegative);
|
||||
if (v1.mValue == 0)
|
||||
return STAmount (v1.getFName (), v1.mCurrency, v1.mIssuer, v2.mValue, v2.mOffset, !v2.mIsNegative);
|
||||
|
||||
if (v1.mIsNative)
|
||||
return STAmount(v1.getFName(), v1.getSNValue() - v2.getSNValue());
|
||||
if (v1.mIsNative)
|
||||
return STAmount (v1.getFName (), v1.getSNValue () - v2.getSNValue ());
|
||||
|
||||
int ov1 = v1.mOffset, ov2 = v2.mOffset;
|
||||
int64 vv1 = static_cast<int64>(v1.mValue), vv2 = static_cast<uint64>(v2.mValue);
|
||||
int ov1 = v1.mOffset, ov2 = v2.mOffset;
|
||||
int64 vv1 = static_cast<int64> (v1.mValue), vv2 = static_cast<uint64> (v2.mValue);
|
||||
|
||||
if (v1.mIsNegative)
|
||||
vv1 = -vv1;
|
||||
if (v1.mIsNegative)
|
||||
vv1 = -vv1;
|
||||
|
||||
if (!v2.mIsNegative)
|
||||
vv2 = -vv2;
|
||||
if (!v2.mIsNegative)
|
||||
vv2 = -vv2;
|
||||
|
||||
if (ov1 < ov2)
|
||||
{
|
||||
while (ov1 < (ov2 - 1))
|
||||
{
|
||||
vv1 /= 10;
|
||||
++ov1;
|
||||
}
|
||||
if (roundUp)
|
||||
vv1 += 9;
|
||||
vv1 /= 10;
|
||||
++ov1;
|
||||
}
|
||||
if (ov1 < ov2)
|
||||
{
|
||||
while (ov1 < (ov2 - 1))
|
||||
{
|
||||
vv1 /= 10;
|
||||
++ov1;
|
||||
}
|
||||
|
||||
if (ov2 < ov1)
|
||||
{
|
||||
while (ov2 < (ov1 - 1))
|
||||
{
|
||||
vv2 /= 10;
|
||||
++ov2;
|
||||
}
|
||||
if (roundUp)
|
||||
vv2 += 9;
|
||||
vv2 /= 10;
|
||||
++ov2;
|
||||
}
|
||||
if (roundUp)
|
||||
vv1 += 9;
|
||||
|
||||
int64 fv = vv1 + vv2;
|
||||
if ((fv >= -10) && (fv <= 10))
|
||||
return STAmount(v1.getFName(), v1.mCurrency, v1.mIssuer);
|
||||
else if (fv >= 0)
|
||||
{
|
||||
uint64 v = static_cast<uint64>(fv);
|
||||
canonicalizeRound(false, v, ov1, roundUp);
|
||||
return STAmount(v1.getFName(), v1.mCurrency, v1.mIssuer, v, ov1, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
uint64 v = static_cast<uint64>(-fv);
|
||||
canonicalizeRound(false, v, ov1, !roundUp);
|
||||
return STAmount(v1.getFName(), v1.mCurrency, v1.mIssuer, v, ov1, true);
|
||||
}
|
||||
vv1 /= 10;
|
||||
++ov1;
|
||||
}
|
||||
|
||||
if (ov2 < ov1)
|
||||
{
|
||||
while (ov2 < (ov1 - 1))
|
||||
{
|
||||
vv2 /= 10;
|
||||
++ov2;
|
||||
}
|
||||
|
||||
if (roundUp)
|
||||
vv2 += 9;
|
||||
|
||||
vv2 /= 10;
|
||||
++ov2;
|
||||
}
|
||||
|
||||
int64 fv = vv1 + vv2;
|
||||
|
||||
if ((fv >= -10) && (fv <= 10))
|
||||
return STAmount (v1.getFName (), v1.mCurrency, v1.mIssuer);
|
||||
else if (fv >= 0)
|
||||
{
|
||||
uint64 v = static_cast<uint64> (fv);
|
||||
canonicalizeRound (false, v, ov1, roundUp);
|
||||
return STAmount (v1.getFName (), v1.mCurrency, v1.mIssuer, v, ov1, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
uint64 v = static_cast<uint64> (-fv);
|
||||
canonicalizeRound (false, v, ov1, !roundUp);
|
||||
return STAmount (v1.getFName (), v1.mCurrency, v1.mIssuer, v, ov1, true);
|
||||
}
|
||||
}
|
||||
|
||||
STAmount STAmount::mulRound(const STAmount& v1, const STAmount& v2,
|
||||
const uint160& uCurrencyID, const uint160& uIssuerID, bool roundUp)
|
||||
STAmount STAmount::mulRound (const STAmount& v1, const STAmount& v2,
|
||||
const uint160& uCurrencyID, const uint160& uIssuerID, bool roundUp)
|
||||
{
|
||||
if (v1.isZero() || v2.isZero())
|
||||
return STAmount(uCurrencyID, uIssuerID);
|
||||
if (v1.isZero () || v2.isZero ())
|
||||
return STAmount (uCurrencyID, uIssuerID);
|
||||
|
||||
if (v1.mIsNative && v2.mIsNative && uCurrencyID.isZero())
|
||||
{
|
||||
uint64 minV = (v1.getSNValue() < v2.getSNValue()) ? v1.getSNValue() : v2.getSNValue();
|
||||
uint64 maxV = (v1.getSNValue() < v2.getSNValue()) ? v2.getSNValue() : v1.getSNValue();
|
||||
if (minV > 3000000000ull) // sqrt(cMaxNative)
|
||||
throw std::runtime_error("Native value overflow");
|
||||
if (((maxV >> 32) * minV) > 2095475792ull) // cMaxNative / 2^32
|
||||
throw std::runtime_error("Native value overflow");
|
||||
return STAmount(v1.getFName(), minV * maxV);
|
||||
}
|
||||
if (v1.mIsNative && v2.mIsNative && uCurrencyID.isZero ())
|
||||
{
|
||||
uint64 minV = (v1.getSNValue () < v2.getSNValue ()) ? v1.getSNValue () : v2.getSNValue ();
|
||||
uint64 maxV = (v1.getSNValue () < v2.getSNValue ()) ? v2.getSNValue () : v1.getSNValue ();
|
||||
|
||||
uint64 value1 = v1.mValue, value2 = v2.mValue;
|
||||
int offset1 = v1.mOffset, offset2 = v2.mOffset;
|
||||
if (minV > 3000000000ull) // sqrt(cMaxNative)
|
||||
throw std::runtime_error ("Native value overflow");
|
||||
|
||||
if (v1.mIsNative)
|
||||
{
|
||||
while (value1 < STAmount::cMinValue)
|
||||
{
|
||||
value1 *= 10;
|
||||
--offset1;
|
||||
}
|
||||
}
|
||||
if (((maxV >> 32) * minV) > 2095475792ull) // cMaxNative / 2^32
|
||||
throw std::runtime_error ("Native value overflow");
|
||||
|
||||
if (v2.mIsNative)
|
||||
{
|
||||
while (value2 < STAmount::cMinValue)
|
||||
{
|
||||
value2 *= 10;
|
||||
--offset2;
|
||||
}
|
||||
}
|
||||
return STAmount (v1.getFName (), minV * maxV);
|
||||
}
|
||||
|
||||
bool resultNegative = v1.mIsNegative != v2.mIsNegative;
|
||||
// Compute (numerator * denominator) / 10^14 with rounding
|
||||
// 10^16 <= result <= 10^18
|
||||
CBigNum v;
|
||||
if ((BN_add_word64(&v, value1) != 1) || (BN_mul_word64(&v, value2) != 1))
|
||||
throw std::runtime_error("internal bn error");
|
||||
uint64 value1 = v1.mValue, value2 = v2.mValue;
|
||||
int offset1 = v1.mOffset, offset2 = v2.mOffset;
|
||||
|
||||
if (resultNegative != roundUp) // rounding down is automatic when we divide
|
||||
BN_add_word64(&v, tenTo14m1);
|
||||
if (v1.mIsNative)
|
||||
{
|
||||
while (value1 < STAmount::cMinValue)
|
||||
{
|
||||
value1 *= 10;
|
||||
--offset1;
|
||||
}
|
||||
}
|
||||
|
||||
if (BN_div_word64(&v, tenTo14) == ((uint64) -1))
|
||||
throw std::runtime_error("internal bn error");
|
||||
if (v2.mIsNative)
|
||||
{
|
||||
while (value2 < STAmount::cMinValue)
|
||||
{
|
||||
value2 *= 10;
|
||||
--offset2;
|
||||
}
|
||||
}
|
||||
|
||||
// 10^16 <= product <= 10^18
|
||||
assert(BN_num_bytes(&v) <= 64);
|
||||
bool resultNegative = v1.mIsNegative != v2.mIsNegative;
|
||||
// Compute (numerator * denominator) / 10^14 with rounding
|
||||
// 10^16 <= result <= 10^18
|
||||
CBigNum v;
|
||||
|
||||
uint64 amount = v.getuint64();
|
||||
int offset = offset1 + offset2 + 14;
|
||||
canonicalizeRound(uCurrencyID.isZero(), amount, offset, resultNegative != roundUp);
|
||||
return STAmount(uCurrencyID, uIssuerID, amount, offset, resultNegative);
|
||||
if ((BN_add_word64 (&v, value1) != 1) || (BN_mul_word64 (&v, value2) != 1))
|
||||
throw std::runtime_error ("internal bn error");
|
||||
|
||||
if (resultNegative != roundUp) // rounding down is automatic when we divide
|
||||
BN_add_word64 (&v, tenTo14m1);
|
||||
|
||||
if (BN_div_word64 (&v, tenTo14) == ((uint64) - 1))
|
||||
throw std::runtime_error ("internal bn error");
|
||||
|
||||
// 10^16 <= product <= 10^18
|
||||
assert (BN_num_bytes (&v) <= 64);
|
||||
|
||||
uint64 amount = v.getuint64 ();
|
||||
int offset = offset1 + offset2 + 14;
|
||||
canonicalizeRound (uCurrencyID.isZero (), amount, offset, resultNegative != roundUp);
|
||||
return STAmount (uCurrencyID, uIssuerID, amount, offset, resultNegative);
|
||||
}
|
||||
|
||||
STAmount STAmount::divRound(const STAmount& num, const STAmount& den,
|
||||
const uint160& uCurrencyID, const uint160& uIssuerID, bool roundUp)
|
||||
STAmount STAmount::divRound (const STAmount& num, const STAmount& den,
|
||||
const uint160& uCurrencyID, const uint160& uIssuerID, bool roundUp)
|
||||
{
|
||||
if (den.isZero())
|
||||
throw std::runtime_error("division by zero");
|
||||
if (num.isZero())
|
||||
return STAmount(uCurrencyID, uIssuerID);
|
||||
if (den.isZero ())
|
||||
throw std::runtime_error ("division by zero");
|
||||
|
||||
uint64 numVal = num.mValue, denVal = den.mValue;
|
||||
int numOffset = num.mOffset, denOffset = den.mOffset;
|
||||
if (num.isZero ())
|
||||
return STAmount (uCurrencyID, uIssuerID);
|
||||
|
||||
if (num.mIsNative)
|
||||
while (numVal < STAmount::cMinValue)
|
||||
{ // Need to bring into range
|
||||
numVal *= 10;
|
||||
--numOffset;
|
||||
}
|
||||
uint64 numVal = num.mValue, denVal = den.mValue;
|
||||
int numOffset = num.mOffset, denOffset = den.mOffset;
|
||||
|
||||
if (den.mIsNative)
|
||||
while (denVal < STAmount::cMinValue)
|
||||
{
|
||||
denVal *= 10;
|
||||
--denOffset;
|
||||
}
|
||||
if (num.mIsNative)
|
||||
while (numVal < STAmount::cMinValue)
|
||||
{
|
||||
// Need to bring into range
|
||||
numVal *= 10;
|
||||
--numOffset;
|
||||
}
|
||||
|
||||
bool resultNegative = num.mIsNegative != den.mIsNegative;
|
||||
// Compute (numerator * 10^17) / denominator
|
||||
CBigNum v;
|
||||
if ((BN_add_word64(&v, numVal) != 1) || (BN_mul_word64(&v, tenTo17) != 1))
|
||||
throw std::runtime_error("internal bn error");
|
||||
if (den.mIsNative)
|
||||
while (denVal < STAmount::cMinValue)
|
||||
{
|
||||
denVal *= 10;
|
||||
--denOffset;
|
||||
}
|
||||
|
||||
if (resultNegative != roundUp) // Rounding down is automatic when we divide
|
||||
BN_add_word64(&v, denVal - 1);
|
||||
bool resultNegative = num.mIsNegative != den.mIsNegative;
|
||||
// Compute (numerator * 10^17) / denominator
|
||||
CBigNum v;
|
||||
|
||||
if (BN_div_word64(&v, denVal) == ((uint64) -1))
|
||||
throw std::runtime_error("internal bn error");
|
||||
if ((BN_add_word64 (&v, numVal) != 1) || (BN_mul_word64 (&v, tenTo17) != 1))
|
||||
throw std::runtime_error ("internal bn error");
|
||||
|
||||
// 10^16 <= quotient <= 10^18
|
||||
assert(BN_num_bytes(&v) <= 64);
|
||||
if (resultNegative != roundUp) // Rounding down is automatic when we divide
|
||||
BN_add_word64 (&v, denVal - 1);
|
||||
|
||||
uint64 amount = v.getuint64();
|
||||
int offset = numOffset - denOffset - 17;
|
||||
canonicalizeRound(uCurrencyID.isZero(), amount, offset, resultNegative != roundUp);
|
||||
return STAmount(uCurrencyID, uIssuerID, amount, offset, resultNegative);
|
||||
if (BN_div_word64 (&v, denVal) == ((uint64) - 1))
|
||||
throw std::runtime_error ("internal bn error");
|
||||
|
||||
// 10^16 <= quotient <= 10^18
|
||||
assert (BN_num_bytes (&v) <= 64);
|
||||
|
||||
uint64 amount = v.getuint64 ();
|
||||
int offset = numOffset - denOffset - 17;
|
||||
canonicalizeRound (uCurrencyID.isZero (), amount, offset, resultNegative != roundUp);
|
||||
return STAmount (uCurrencyID, uIssuerID, amount, offset, resultNegative);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE(amountRound)
|
||||
BOOST_AUTO_TEST_SUITE (amountRound)
|
||||
|
||||
BOOST_AUTO_TEST_CASE( amountRound_test )
|
||||
BOOST_AUTO_TEST_CASE ( amountRound_test )
|
||||
{
|
||||
uint64 value = 25000000000000000ull;
|
||||
int offset = -14;
|
||||
canonicalizeRound(false, value, offset, true);
|
||||
uint64 value = 25000000000000000ull;
|
||||
int offset = -14;
|
||||
canonicalizeRound (false, value, offset, true);
|
||||
|
||||
STAmount one(CURRENCY_ONE, ACCOUNT_ONE, 1);
|
||||
STAmount two(CURRENCY_ONE, ACCOUNT_ONE, 2);
|
||||
STAmount three(CURRENCY_ONE, ACCOUNT_ONE, 3);
|
||||
STAmount one (CURRENCY_ONE, ACCOUNT_ONE, 1);
|
||||
STAmount two (CURRENCY_ONE, ACCOUNT_ONE, 2);
|
||||
STAmount three (CURRENCY_ONE, ACCOUNT_ONE, 3);
|
||||
|
||||
STAmount oneThird1 = STAmount::divRound(one, three, CURRENCY_ONE, ACCOUNT_ONE, false);
|
||||
STAmount oneThird2 = STAmount::divide(one, three, CURRENCY_ONE, ACCOUNT_ONE);
|
||||
STAmount oneThird3 = STAmount::divRound(one, three, CURRENCY_ONE, ACCOUNT_ONE, true);
|
||||
WriteLog (lsINFO, STAmount) << oneThird1;
|
||||
WriteLog (lsINFO, STAmount) << oneThird2;
|
||||
WriteLog (lsINFO, STAmount) << oneThird3;
|
||||
STAmount oneThird1 = STAmount::divRound (one, three, CURRENCY_ONE, ACCOUNT_ONE, false);
|
||||
STAmount oneThird2 = STAmount::divide (one, three, CURRENCY_ONE, ACCOUNT_ONE);
|
||||
STAmount oneThird3 = STAmount::divRound (one, three, CURRENCY_ONE, ACCOUNT_ONE, true);
|
||||
WriteLog (lsINFO, STAmount) << oneThird1;
|
||||
WriteLog (lsINFO, STAmount) << oneThird2;
|
||||
WriteLog (lsINFO, STAmount) << oneThird3;
|
||||
|
||||
STAmount twoThird1 = STAmount::divRound(two, three, CURRENCY_ONE, ACCOUNT_ONE, false);
|
||||
STAmount twoThird2 = STAmount::divide(two, three, CURRENCY_ONE, ACCOUNT_ONE);
|
||||
STAmount twoThird3 = STAmount::divRound(two, three, CURRENCY_ONE, ACCOUNT_ONE, true);
|
||||
WriteLog (lsINFO, STAmount) << twoThird1;
|
||||
WriteLog (lsINFO, STAmount) << twoThird2;
|
||||
WriteLog (lsINFO, STAmount) << twoThird3;
|
||||
STAmount twoThird1 = STAmount::divRound (two, three, CURRENCY_ONE, ACCOUNT_ONE, false);
|
||||
STAmount twoThird2 = STAmount::divide (two, three, CURRENCY_ONE, ACCOUNT_ONE);
|
||||
STAmount twoThird3 = STAmount::divRound (two, three, CURRENCY_ONE, ACCOUNT_ONE, true);
|
||||
WriteLog (lsINFO, STAmount) << twoThird1;
|
||||
WriteLog (lsINFO, STAmount) << twoThird2;
|
||||
WriteLog (lsINFO, STAmount) << twoThird3;
|
||||
|
||||
STAmount oneA = STAmount::mulRound(oneThird1, three, CURRENCY_ONE, ACCOUNT_ONE, false);
|
||||
STAmount oneB = STAmount::multiply(oneThird2, three, CURRENCY_ONE, ACCOUNT_ONE);
|
||||
STAmount oneC = STAmount::mulRound(oneThird3, three, CURRENCY_ONE, ACCOUNT_ONE, true);
|
||||
WriteLog (lsINFO, STAmount) << oneA;
|
||||
WriteLog (lsINFO, STAmount) << oneB;
|
||||
WriteLog (lsINFO, STAmount) << oneC;
|
||||
STAmount oneA = STAmount::mulRound (oneThird1, three, CURRENCY_ONE, ACCOUNT_ONE, false);
|
||||
STAmount oneB = STAmount::multiply (oneThird2, three, CURRENCY_ONE, ACCOUNT_ONE);
|
||||
STAmount oneC = STAmount::mulRound (oneThird3, three, CURRENCY_ONE, ACCOUNT_ONE, true);
|
||||
WriteLog (lsINFO, STAmount) << oneA;
|
||||
WriteLog (lsINFO, STAmount) << oneB;
|
||||
WriteLog (lsINFO, STAmount) << oneC;
|
||||
|
||||
STAmount fourThirdsA = STAmount::addRound(twoThird2, twoThird2, false);
|
||||
STAmount fourThirdsB = twoThird2 + twoThird2;
|
||||
STAmount fourThirdsC = STAmount::addRound(twoThird2, twoThird2, true);
|
||||
WriteLog (lsINFO, STAmount) << fourThirdsA;
|
||||
WriteLog (lsINFO, STAmount) << fourThirdsB;
|
||||
WriteLog (lsINFO, STAmount) << fourThirdsC;
|
||||
STAmount fourThirdsA = STAmount::addRound (twoThird2, twoThird2, false);
|
||||
STAmount fourThirdsB = twoThird2 + twoThird2;
|
||||
STAmount fourThirdsC = STAmount::addRound (twoThird2, twoThird2, true);
|
||||
WriteLog (lsINFO, STAmount) << fourThirdsA;
|
||||
WriteLog (lsINFO, STAmount) << fourThirdsB;
|
||||
WriteLog (lsINFO, STAmount) << fourThirdsC;
|
||||
|
||||
STAmount dripTest1 = STAmount::mulRound(twoThird2, two, uint160(), uint160(), false);
|
||||
STAmount dripTest2 = STAmount::multiply(twoThird2, two, uint160(), uint160());
|
||||
STAmount dripTest3 = STAmount::mulRound(twoThird2, two, uint160(), uint160(), true);
|
||||
WriteLog (lsINFO, STAmount) << dripTest1;
|
||||
WriteLog (lsINFO, STAmount) << dripTest2;
|
||||
WriteLog (lsINFO, STAmount) << dripTest3;
|
||||
STAmount dripTest1 = STAmount::mulRound (twoThird2, two, uint160 (), uint160 (), false);
|
||||
STAmount dripTest2 = STAmount::multiply (twoThird2, two, uint160 (), uint160 ());
|
||||
STAmount dripTest3 = STAmount::mulRound (twoThird2, two, uint160 (), uint160 (), true);
|
||||
WriteLog (lsINFO, STAmount) << dripTest1;
|
||||
WriteLog (lsINFO, STAmount) << dripTest2;
|
||||
WriteLog (lsINFO, STAmount) << dripTest3;
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
||||
BOOST_AUTO_TEST_SUITE_END ()
|
||||
|
||||
// vim:ts=4
|
||||
|
||||
@@ -10,169 +10,169 @@
|
||||
This is done to reduce the average size of the messages.
|
||||
*/
|
||||
|
||||
// types (common)
|
||||
TYPE(Int16, UINT16, 1)
|
||||
TYPE(Int32, UINT32, 2)
|
||||
TYPE(Int64, UINT64, 3)
|
||||
TYPE(Hash128, HASH128, 4)
|
||||
TYPE(Hash256, HASH256, 5)
|
||||
TYPE(Amount, AMOUNT, 6)
|
||||
TYPE(VariableLength, VL, 7)
|
||||
TYPE(Account, ACCOUNT, 8)
|
||||
// 9-13 are reserved
|
||||
TYPE(Object, OBJECT, 14)
|
||||
TYPE(Array, ARRAY, 15)
|
||||
// types (common)
|
||||
TYPE (Int16, UINT16, 1)
|
||||
TYPE (Int32, UINT32, 2)
|
||||
TYPE (Int64, UINT64, 3)
|
||||
TYPE (Hash128, HASH128, 4)
|
||||
TYPE (Hash256, HASH256, 5)
|
||||
TYPE (Amount, AMOUNT, 6)
|
||||
TYPE (VariableLength, VL, 7)
|
||||
TYPE (Account, ACCOUNT, 8)
|
||||
// 9-13 are reserved
|
||||
TYPE (Object, OBJECT, 14)
|
||||
TYPE (Array, ARRAY, 15)
|
||||
|
||||
// types (uncommon)
|
||||
TYPE(Int8, UINT8, 16)
|
||||
TYPE(Hash160, HASH160, 17)
|
||||
TYPE(PathSet, PATHSET, 18)
|
||||
TYPE(Vector256, VECTOR256, 19)
|
||||
// types (uncommon)
|
||||
TYPE (Int8, UINT8, 16)
|
||||
TYPE (Hash160, HASH160, 17)
|
||||
TYPE (PathSet, PATHSET, 18)
|
||||
TYPE (Vector256, VECTOR256, 19)
|
||||
|
||||
|
||||
|
||||
// 8-bit integers
|
||||
FIELD(CloseResolution, UINT8, 1)
|
||||
FIELD(TemplateEntryType, UINT8, 2)
|
||||
FIELD(TransactionResult, UINT8, 3)
|
||||
// 8-bit integers
|
||||
FIELD (CloseResolution, UINT8, 1)
|
||||
FIELD (TemplateEntryType, UINT8, 2)
|
||||
FIELD (TransactionResult, UINT8, 3)
|
||||
|
||||
// 16-bit integers
|
||||
FIELD(LedgerEntryType, UINT16, 1)
|
||||
FIELD(TransactionType, UINT16, 2)
|
||||
// 16-bit integers
|
||||
FIELD (LedgerEntryType, UINT16, 1)
|
||||
FIELD (TransactionType, UINT16, 2)
|
||||
|
||||
// 32-bit integers (common)
|
||||
FIELD(Flags, UINT32, 2)
|
||||
FIELD(SourceTag, UINT32, 3)
|
||||
FIELD(Sequence, UINT32, 4)
|
||||
FIELD(PreviousTxnLgrSeq, UINT32, 5)
|
||||
FIELD(LedgerSequence, UINT32, 6)
|
||||
FIELD(CloseTime, UINT32, 7)
|
||||
FIELD(ParentCloseTime, UINT32, 8)
|
||||
FIELD(SigningTime, UINT32, 9)
|
||||
FIELD(Expiration, UINT32, 10)
|
||||
FIELD(TransferRate, UINT32, 11)
|
||||
FIELD(WalletSize, UINT32, 12)
|
||||
FIELD(OwnerCount, UINT32, 13)
|
||||
FIELD(DestinationTag, UINT32, 14)
|
||||
// 32-bit integers (common)
|
||||
FIELD (Flags, UINT32, 2)
|
||||
FIELD (SourceTag, UINT32, 3)
|
||||
FIELD (Sequence, UINT32, 4)
|
||||
FIELD (PreviousTxnLgrSeq, UINT32, 5)
|
||||
FIELD (LedgerSequence, UINT32, 6)
|
||||
FIELD (CloseTime, UINT32, 7)
|
||||
FIELD (ParentCloseTime, UINT32, 8)
|
||||
FIELD (SigningTime, UINT32, 9)
|
||||
FIELD (Expiration, UINT32, 10)
|
||||
FIELD (TransferRate, UINT32, 11)
|
||||
FIELD (WalletSize, UINT32, 12)
|
||||
FIELD (OwnerCount, UINT32, 13)
|
||||
FIELD (DestinationTag, UINT32, 14)
|
||||
|
||||
// 32-bit integers (uncommon)
|
||||
FIELD(HighQualityIn, UINT32, 16)
|
||||
FIELD(HighQualityOut, UINT32, 17)
|
||||
FIELD(LowQualityIn, UINT32, 18)
|
||||
FIELD(LowQualityOut, UINT32, 19)
|
||||
FIELD(QualityIn, UINT32, 20)
|
||||
FIELD(QualityOut, UINT32, 21)
|
||||
FIELD(StampEscrow, UINT32, 22)
|
||||
FIELD(BondAmount, UINT32, 23)
|
||||
FIELD(LoadFee, UINT32, 24)
|
||||
FIELD(OfferSequence, UINT32, 25)
|
||||
FIELD(FirstLedgerSequence, UINT32, 26) // Deprecated: do not use
|
||||
FIELD(LastLedgerSequence, UINT32, 27)
|
||||
FIELD(TransactionIndex, UINT32, 28)
|
||||
FIELD(OperationLimit, UINT32, 29)
|
||||
FIELD(ReferenceFeeUnits, UINT32, 30)
|
||||
FIELD(ReserveBase, UINT32, 31)
|
||||
FIELD(ReserveIncrement, UINT32, 32)
|
||||
// 32-bit integers (uncommon)
|
||||
FIELD (HighQualityIn, UINT32, 16)
|
||||
FIELD (HighQualityOut, UINT32, 17)
|
||||
FIELD (LowQualityIn, UINT32, 18)
|
||||
FIELD (LowQualityOut, UINT32, 19)
|
||||
FIELD (QualityIn, UINT32, 20)
|
||||
FIELD (QualityOut, UINT32, 21)
|
||||
FIELD (StampEscrow, UINT32, 22)
|
||||
FIELD (BondAmount, UINT32, 23)
|
||||
FIELD (LoadFee, UINT32, 24)
|
||||
FIELD (OfferSequence, UINT32, 25)
|
||||
FIELD (FirstLedgerSequence, UINT32, 26) // Deprecated: do not use
|
||||
FIELD (LastLedgerSequence, UINT32, 27)
|
||||
FIELD (TransactionIndex, UINT32, 28)
|
||||
FIELD (OperationLimit, UINT32, 29)
|
||||
FIELD (ReferenceFeeUnits, UINT32, 30)
|
||||
FIELD (ReserveBase, UINT32, 31)
|
||||
FIELD (ReserveIncrement, UINT32, 32)
|
||||
|
||||
// 64-bit integers
|
||||
FIELD(IndexNext, UINT64, 1)
|
||||
FIELD(IndexPrevious, UINT64, 2)
|
||||
FIELD(BookNode, UINT64, 3)
|
||||
FIELD(OwnerNode, UINT64, 4)
|
||||
FIELD(BaseFee, UINT64, 5)
|
||||
FIELD(ExchangeRate, UINT64, 6)
|
||||
FIELD(LowNode, UINT64, 7)
|
||||
FIELD(HighNode, UINT64, 8)
|
||||
// 64-bit integers
|
||||
FIELD (IndexNext, UINT64, 1)
|
||||
FIELD (IndexPrevious, UINT64, 2)
|
||||
FIELD (BookNode, UINT64, 3)
|
||||
FIELD (OwnerNode, UINT64, 4)
|
||||
FIELD (BaseFee, UINT64, 5)
|
||||
FIELD (ExchangeRate, UINT64, 6)
|
||||
FIELD (LowNode, UINT64, 7)
|
||||
FIELD (HighNode, UINT64, 8)
|
||||
|
||||
|
||||
// 128-bit
|
||||
FIELD(EmailHash, HASH128, 1)
|
||||
// 128-bit
|
||||
FIELD (EmailHash, HASH128, 1)
|
||||
|
||||
// 256-bit (common)
|
||||
FIELD(LedgerHash, HASH256, 1)
|
||||
FIELD(ParentHash, HASH256, 2)
|
||||
FIELD(TransactionHash, HASH256, 3)
|
||||
FIELD(AccountHash, HASH256, 4)
|
||||
FIELD(PreviousTxnID, HASH256, 5)
|
||||
FIELD(LedgerIndex, HASH256, 6)
|
||||
FIELD(WalletLocator, HASH256, 7)
|
||||
FIELD(RootIndex, HASH256, 8)
|
||||
// 256-bit (common)
|
||||
FIELD (LedgerHash, HASH256, 1)
|
||||
FIELD (ParentHash, HASH256, 2)
|
||||
FIELD (TransactionHash, HASH256, 3)
|
||||
FIELD (AccountHash, HASH256, 4)
|
||||
FIELD (PreviousTxnID, HASH256, 5)
|
||||
FIELD (LedgerIndex, HASH256, 6)
|
||||
FIELD (WalletLocator, HASH256, 7)
|
||||
FIELD (RootIndex, HASH256, 8)
|
||||
|
||||
// 256-bit (uncommon)
|
||||
FIELD(BookDirectory, HASH256, 16)
|
||||
FIELD(InvoiceID, HASH256, 17)
|
||||
FIELD(Nickname, HASH256, 18)
|
||||
FIELD(Feature, HASH256, 19)
|
||||
// 256-bit (uncommon)
|
||||
FIELD (BookDirectory, HASH256, 16)
|
||||
FIELD (InvoiceID, HASH256, 17)
|
||||
FIELD (Nickname, HASH256, 18)
|
||||
FIELD (Feature, HASH256, 19)
|
||||
|
||||
// 160-bit (common)
|
||||
FIELD(TakerPaysCurrency, HASH160, 1)
|
||||
FIELD(TakerPaysIssuer, HASH160, 2)
|
||||
FIELD(TakerGetsCurrency, HASH160, 3)
|
||||
FIELD(TakerGetsIssuer, HASH160, 4)
|
||||
// 160-bit (common)
|
||||
FIELD (TakerPaysCurrency, HASH160, 1)
|
||||
FIELD (TakerPaysIssuer, HASH160, 2)
|
||||
FIELD (TakerGetsCurrency, HASH160, 3)
|
||||
FIELD (TakerGetsIssuer, HASH160, 4)
|
||||
|
||||
// currency amount (common)
|
||||
FIELD(Amount, AMOUNT, 1)
|
||||
FIELD(Balance, AMOUNT, 2)
|
||||
FIELD(LimitAmount, AMOUNT, 3)
|
||||
FIELD(TakerPays, AMOUNT, 4)
|
||||
FIELD(TakerGets, AMOUNT, 5)
|
||||
FIELD(LowLimit, AMOUNT, 6)
|
||||
FIELD(HighLimit, AMOUNT, 7)
|
||||
FIELD(Fee, AMOUNT, 8)
|
||||
FIELD(SendMax, AMOUNT, 9)
|
||||
// currency amount (common)
|
||||
FIELD (Amount, AMOUNT, 1)
|
||||
FIELD (Balance, AMOUNT, 2)
|
||||
FIELD (LimitAmount, AMOUNT, 3)
|
||||
FIELD (TakerPays, AMOUNT, 4)
|
||||
FIELD (TakerGets, AMOUNT, 5)
|
||||
FIELD (LowLimit, AMOUNT, 6)
|
||||
FIELD (HighLimit, AMOUNT, 7)
|
||||
FIELD (Fee, AMOUNT, 8)
|
||||
FIELD (SendMax, AMOUNT, 9)
|
||||
|
||||
// currency amount (uncommon)
|
||||
FIELD(MinimumOffer, AMOUNT, 16)
|
||||
FIELD(RippleEscrow, AMOUNT, 17)
|
||||
// currency amount (uncommon)
|
||||
FIELD (MinimumOffer, AMOUNT, 16)
|
||||
FIELD (RippleEscrow, AMOUNT, 17)
|
||||
|
||||
// variable length
|
||||
FIELD(PublicKey, VL, 1)
|
||||
FIELD(MessageKey, VL, 2)
|
||||
FIELD(SigningPubKey, VL, 3)
|
||||
FIELD(TxnSignature, VL, 4)
|
||||
FIELD(Generator, VL, 5)
|
||||
FIELD(Signature, VL, 6)
|
||||
FIELD(Domain, VL, 7)
|
||||
FIELD(FundCode, VL, 8)
|
||||
FIELD(RemoveCode, VL, 9)
|
||||
FIELD(ExpireCode, VL, 10)
|
||||
FIELD(CreateCode, VL, 11)
|
||||
// variable length
|
||||
FIELD (PublicKey, VL, 1)
|
||||
FIELD (MessageKey, VL, 2)
|
||||
FIELD (SigningPubKey, VL, 3)
|
||||
FIELD (TxnSignature, VL, 4)
|
||||
FIELD (Generator, VL, 5)
|
||||
FIELD (Signature, VL, 6)
|
||||
FIELD (Domain, VL, 7)
|
||||
FIELD (FundCode, VL, 8)
|
||||
FIELD (RemoveCode, VL, 9)
|
||||
FIELD (ExpireCode, VL, 10)
|
||||
FIELD (CreateCode, VL, 11)
|
||||
|
||||
// account
|
||||
FIELD(Account, ACCOUNT, 1)
|
||||
FIELD(Owner, ACCOUNT, 2)
|
||||
FIELD(Destination, ACCOUNT, 3)
|
||||
FIELD(Issuer, ACCOUNT, 4)
|
||||
FIELD(Target, ACCOUNT, 7)
|
||||
FIELD(RegularKey, ACCOUNT, 8)
|
||||
// account
|
||||
FIELD (Account, ACCOUNT, 1)
|
||||
FIELD (Owner, ACCOUNT, 2)
|
||||
FIELD (Destination, ACCOUNT, 3)
|
||||
FIELD (Issuer, ACCOUNT, 4)
|
||||
FIELD (Target, ACCOUNT, 7)
|
||||
FIELD (RegularKey, ACCOUNT, 8)
|
||||
|
||||
// path set
|
||||
FIELD(Paths, PATHSET, 1)
|
||||
// path set
|
||||
FIELD (Paths, PATHSET, 1)
|
||||
|
||||
// vector of 256-bit
|
||||
FIELD(Indexes, VECTOR256, 1)
|
||||
FIELD(Hashes, VECTOR256, 2)
|
||||
FIELD(Features, VECTOR256, 3)
|
||||
// vector of 256-bit
|
||||
FIELD (Indexes, VECTOR256, 1)
|
||||
FIELD (Hashes, VECTOR256, 2)
|
||||
FIELD (Features, VECTOR256, 3)
|
||||
|
||||
// inner object
|
||||
// OBJECT/1 is reserved for end of object
|
||||
FIELD(TransactionMetaData, OBJECT, 2)
|
||||
FIELD(CreatedNode, OBJECT, 3)
|
||||
FIELD(DeletedNode, OBJECT, 4)
|
||||
FIELD(ModifiedNode, OBJECT, 5)
|
||||
FIELD(PreviousFields, OBJECT, 6)
|
||||
FIELD(FinalFields, OBJECT, 7)
|
||||
FIELD(NewFields, OBJECT, 8)
|
||||
FIELD(TemplateEntry, OBJECT, 9)
|
||||
// inner object
|
||||
// OBJECT/1 is reserved for end of object
|
||||
FIELD (TransactionMetaData, OBJECT, 2)
|
||||
FIELD (CreatedNode, OBJECT, 3)
|
||||
FIELD (DeletedNode, OBJECT, 4)
|
||||
FIELD (ModifiedNode, OBJECT, 5)
|
||||
FIELD (PreviousFields, OBJECT, 6)
|
||||
FIELD (FinalFields, OBJECT, 7)
|
||||
FIELD (NewFields, OBJECT, 8)
|
||||
FIELD (TemplateEntry, OBJECT, 9)
|
||||
|
||||
// array of objects
|
||||
// ARRAY/1 is reserved for end of array
|
||||
FIELD(SigningAccounts, ARRAY, 2)
|
||||
FIELD(TxnSignatures, ARRAY, 3)
|
||||
FIELD(Signatures, ARRAY, 4)
|
||||
FIELD(Template, ARRAY, 5)
|
||||
FIELD(Necessary, ARRAY, 6)
|
||||
FIELD(Sufficient, ARRAY, 7)
|
||||
FIELD(AffectedNodes, ARRAY, 8)
|
||||
// array of objects
|
||||
// ARRAY/1 is reserved for end of array
|
||||
FIELD (SigningAccounts, ARRAY, 2)
|
||||
FIELD (TxnSignatures, ARRAY, 3)
|
||||
FIELD (Signatures, ARRAY, 4)
|
||||
FIELD (Template, ARRAY, 5)
|
||||
FIELD (Necessary, ARRAY, 6)
|
||||
FIELD (Sufficient, ARRAY, 7)
|
||||
FIELD (AffectedNodes, ARRAY, 8)
|
||||
|
||||
// vim:ts=4
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,256 +1,488 @@
|
||||
#ifndef RIPPLE_SERIALIZEDOBJECT_H
|
||||
#define RIPPLE_SERIALIZEDOBJECT_H
|
||||
|
||||
DEFINE_INSTANCE(SerializedObject);
|
||||
DEFINE_INSTANCE(SerializedArray);
|
||||
DEFINE_INSTANCE (SerializedObject);
|
||||
DEFINE_INSTANCE (SerializedArray);
|
||||
|
||||
class STObject : public SerializedType, private IS_INSTANCE(SerializedObject)
|
||||
class STObject : public SerializedType, private IS_INSTANCE (SerializedObject)
|
||||
{
|
||||
public:
|
||||
STObject() : mType(NULL) { ; }
|
||||
STObject () : mType (NULL)
|
||||
{
|
||||
;
|
||||
}
|
||||
|
||||
explicit STObject(SField::ref name) : SerializedType(name), mType(NULL) { ; }
|
||||
explicit STObject (SField::ref name) : SerializedType (name), mType (NULL)
|
||||
{
|
||||
;
|
||||
}
|
||||
|
||||
STObject (const SOTemplate& type, SField::ref name) : SerializedType(name)
|
||||
{ set(type); }
|
||||
STObject (const SOTemplate & type, SField::ref name) : SerializedType (name)
|
||||
{
|
||||
set (type);
|
||||
}
|
||||
|
||||
STObject (const SOTemplate& type, SerializerIterator& sit, SField::ref name) : SerializedType(name)
|
||||
{ set(sit); setType(type); }
|
||||
STObject (const SOTemplate & type, SerializerIterator & sit, SField::ref name) : SerializedType (name)
|
||||
{
|
||||
set (sit);
|
||||
setType (type);
|
||||
}
|
||||
|
||||
UPTR_T<STObject> oClone() const { return UPTR_T<STObject>(new STObject(*this)); }
|
||||
UPTR_T<STObject> oClone () const
|
||||
{
|
||||
return UPTR_T<STObject> (new STObject (*this));
|
||||
}
|
||||
|
||||
static UPTR_T<STObject> parseJson(const Json::Value& value, SField::ref name = sfGeneric, int depth = 0);
|
||||
static UPTR_T<STObject> parseJson (const Json::Value & value, SField::ref name = sfGeneric, int depth = 0);
|
||||
|
||||
virtual ~STObject() { ; }
|
||||
virtual ~STObject ()
|
||||
{
|
||||
;
|
||||
}
|
||||
|
||||
static UPTR_T<SerializedType> deserialize(SerializerIterator& sit, SField::ref name);
|
||||
static UPTR_T<SerializedType> deserialize (SerializerIterator & sit, SField::ref name);
|
||||
|
||||
bool setType(const SOTemplate& type);
|
||||
bool isValidForType();
|
||||
bool isFieldAllowed(SField::ref);
|
||||
bool isFree() const { return mType == NULL; }
|
||||
bool setType (const SOTemplate & type);
|
||||
bool isValidForType ();
|
||||
bool isFieldAllowed (SField::ref);
|
||||
bool isFree () const
|
||||
{
|
||||
return mType == NULL;
|
||||
}
|
||||
|
||||
void set(const SOTemplate&);
|
||||
bool set(SerializerIterator& u, int depth = 0);
|
||||
void set (const SOTemplate&);
|
||||
bool set (SerializerIterator & u, int depth = 0);
|
||||
|
||||
virtual SerializedTypeID getSType() const { return STI_OBJECT; }
|
||||
virtual bool isEquivalent(const SerializedType& t) const;
|
||||
virtual bool isDefault() const { return mData.empty(); }
|
||||
virtual SerializedTypeID getSType () const
|
||||
{
|
||||
return STI_OBJECT;
|
||||
}
|
||||
virtual bool isEquivalent (const SerializedType & t) const;
|
||||
virtual bool isDefault () const
|
||||
{
|
||||
return mData.empty ();
|
||||
}
|
||||
|
||||
virtual void add(Serializer& s) const { add(s, true); } // just inner elements
|
||||
virtual void add (Serializer & s) const
|
||||
{
|
||||
add (s, true); // just inner elements
|
||||
}
|
||||
|
||||
void add(Serializer& s, bool withSignature) const;
|
||||
void add (Serializer & s, bool withSignature) const;
|
||||
|
||||
// VFALCO NOTE does this return an expensive copy of an object with a dynamic buffer?
|
||||
// VFALCO TODO Remove this function and fix the few callers.
|
||||
Serializer getSerializer() const { Serializer s; add(s); return s; }
|
||||
Serializer getSerializer () const
|
||||
{
|
||||
Serializer s;
|
||||
add (s);
|
||||
return s;
|
||||
}
|
||||
|
||||
std::string getFullText() const;
|
||||
std::string getText() const;
|
||||
virtual Json::Value getJson(int options) const;
|
||||
std::string getFullText () const;
|
||||
std::string getText () const;
|
||||
virtual Json::Value getJson (int options) const;
|
||||
|
||||
int addObject(const SerializedType& t) { mData.push_back(t.clone().release()); return mData.size() - 1; }
|
||||
int giveObject(UPTR_T<SerializedType> t) { mData.push_back(t.release()); return mData.size() - 1; }
|
||||
int giveObject(SerializedType* t) { mData.push_back(t); return mData.size() - 1; }
|
||||
const boost::ptr_vector<SerializedType>& peekData() const { return mData; }
|
||||
boost::ptr_vector<SerializedType>& peekData() { return mData; }
|
||||
SerializedType& front() { return mData.front(); }
|
||||
const SerializedType& front() const { return mData.front(); }
|
||||
SerializedType& back() { return mData.back(); }
|
||||
const SerializedType& back() const { return mData.back(); }
|
||||
int addObject (const SerializedType & t)
|
||||
{
|
||||
mData.push_back (t.clone ().release ());
|
||||
return mData.size () - 1;
|
||||
}
|
||||
int giveObject (UPTR_T<SerializedType> t)
|
||||
{
|
||||
mData.push_back (t.release ());
|
||||
return mData.size () - 1;
|
||||
}
|
||||
int giveObject (SerializedType * t)
|
||||
{
|
||||
mData.push_back (t);
|
||||
return mData.size () - 1;
|
||||
}
|
||||
const boost::ptr_vector<SerializedType>& peekData () const
|
||||
{
|
||||
return mData;
|
||||
}
|
||||
boost::ptr_vector<SerializedType>& peekData ()
|
||||
{
|
||||
return mData;
|
||||
}
|
||||
SerializedType& front ()
|
||||
{
|
||||
return mData.front ();
|
||||
}
|
||||
const SerializedType& front () const
|
||||
{
|
||||
return mData.front ();
|
||||
}
|
||||
SerializedType& back ()
|
||||
{
|
||||
return mData.back ();
|
||||
}
|
||||
const SerializedType& back () const
|
||||
{
|
||||
return mData.back ();
|
||||
}
|
||||
|
||||
int getCount() const { return mData.size(); }
|
||||
int getCount () const
|
||||
{
|
||||
return mData.size ();
|
||||
}
|
||||
|
||||
bool setFlag(uint32);
|
||||
bool clearFlag(uint32);
|
||||
uint32 getFlags() const;
|
||||
bool setFlag (uint32);
|
||||
bool clearFlag (uint32);
|
||||
uint32 getFlags () const;
|
||||
|
||||
uint256 getHash(uint32 prefix) const;
|
||||
uint256 getSigningHash(uint32 prefix) const;
|
||||
uint256 getHash (uint32 prefix) const;
|
||||
uint256 getSigningHash (uint32 prefix) const;
|
||||
|
||||
const SerializedType& peekAtIndex(int offset) const { return mData[offset]; }
|
||||
SerializedType& getIndex(int offset) { return mData[offset]; }
|
||||
const SerializedType* peekAtPIndex(int offset) const { return &(mData[offset]); }
|
||||
SerializedType* getPIndex(int offset) { return &(mData[offset]); }
|
||||
const SerializedType& peekAtIndex (int offset) const
|
||||
{
|
||||
return mData[offset];
|
||||
}
|
||||
SerializedType& getIndex (int offset)
|
||||
{
|
||||
return mData[offset];
|
||||
}
|
||||
const SerializedType* peekAtPIndex (int offset) const
|
||||
{
|
||||
return & (mData[offset]);
|
||||
}
|
||||
SerializedType* getPIndex (int offset)
|
||||
{
|
||||
return & (mData[offset]);
|
||||
}
|
||||
|
||||
int getFieldIndex(SField::ref field) const;
|
||||
SField::ref getFieldSType(int index) const;
|
||||
int getFieldIndex (SField::ref field) const;
|
||||
SField::ref getFieldSType (int index) const;
|
||||
|
||||
const SerializedType& peekAtField(SField::ref field) const;
|
||||
SerializedType& getField(SField::ref field);
|
||||
const SerializedType* peekAtPField(SField::ref field) const;
|
||||
SerializedType* getPField(SField::ref field, bool createOkay = false);
|
||||
const SerializedType& peekAtField (SField::ref field) const;
|
||||
SerializedType& getField (SField::ref field);
|
||||
const SerializedType* peekAtPField (SField::ref field) const;
|
||||
SerializedType* getPField (SField::ref field, bool createOkay = false);
|
||||
|
||||
// these throw if the field type doesn't match, or return default values if the
|
||||
// field is optional but not present
|
||||
std::string getFieldString(SField::ref field) const;
|
||||
unsigned char getFieldU8(SField::ref field) const;
|
||||
uint16 getFieldU16(SField::ref field) const;
|
||||
uint32 getFieldU32(SField::ref field) const;
|
||||
uint64 getFieldU64(SField::ref field) const;
|
||||
uint128 getFieldH128(SField::ref field) const;
|
||||
uint160 getFieldH160(SField::ref field) const;
|
||||
uint256 getFieldH256(SField::ref field) const;
|
||||
RippleAddress getFieldAccount(SField::ref field) const;
|
||||
uint160 getFieldAccount160(SField::ref field) const;
|
||||
Blob getFieldVL(SField::ref field) const;
|
||||
const STAmount& getFieldAmount(SField::ref field) const;
|
||||
const STPathSet& getFieldPathSet(SField::ref field) const;
|
||||
const STVector256& getFieldV256(SField::ref field) const;
|
||||
// these throw if the field type doesn't match, or return default values if the
|
||||
// field is optional but not present
|
||||
std::string getFieldString (SField::ref field) const;
|
||||
unsigned char getFieldU8 (SField::ref field) const;
|
||||
uint16 getFieldU16 (SField::ref field) const;
|
||||
uint32 getFieldU32 (SField::ref field) const;
|
||||
uint64 getFieldU64 (SField::ref field) const;
|
||||
uint128 getFieldH128 (SField::ref field) const;
|
||||
uint160 getFieldH160 (SField::ref field) const;
|
||||
uint256 getFieldH256 (SField::ref field) const;
|
||||
RippleAddress getFieldAccount (SField::ref field) const;
|
||||
uint160 getFieldAccount160 (SField::ref field) const;
|
||||
Blob getFieldVL (SField::ref field) const;
|
||||
const STAmount& getFieldAmount (SField::ref field) const;
|
||||
const STPathSet& getFieldPathSet (SField::ref field) const;
|
||||
const STVector256& getFieldV256 (SField::ref field) const;
|
||||
|
||||
void setFieldU8(SField::ref field, unsigned char);
|
||||
void setFieldU16(SField::ref field, uint16);
|
||||
void setFieldU32(SField::ref field, uint32);
|
||||
void setFieldU64(SField::ref field, uint64);
|
||||
void setFieldH128(SField::ref field, const uint128&);
|
||||
void setFieldH160(SField::ref field, const uint160&);
|
||||
void setFieldH256(SField::ref field, uint256 const& );
|
||||
void setFieldVL(SField::ref field, Blob const&);
|
||||
void setFieldAccount(SField::ref field, const uint160&);
|
||||
void setFieldAccount(SField::ref field, const RippleAddress& addr)
|
||||
{ setFieldAccount(field, addr.getAccountID()); }
|
||||
void setFieldAmount(SField::ref field, const STAmount&);
|
||||
void setFieldPathSet(SField::ref field, const STPathSet&);
|
||||
void setFieldV256(SField::ref field, const STVector256& v);
|
||||
void setFieldU8 (SField::ref field, unsigned char);
|
||||
void setFieldU16 (SField::ref field, uint16);
|
||||
void setFieldU32 (SField::ref field, uint32);
|
||||
void setFieldU64 (SField::ref field, uint64);
|
||||
void setFieldH128 (SField::ref field, const uint128&);
|
||||
void setFieldH160 (SField::ref field, const uint160&);
|
||||
void setFieldH256 (SField::ref field, uint256 const& );
|
||||
void setFieldVL (SField::ref field, Blob const&);
|
||||
void setFieldAccount (SField::ref field, const uint160&);
|
||||
void setFieldAccount (SField::ref field, const RippleAddress & addr)
|
||||
{
|
||||
setFieldAccount (field, addr.getAccountID ());
|
||||
}
|
||||
void setFieldAmount (SField::ref field, const STAmount&);
|
||||
void setFieldPathSet (SField::ref field, const STPathSet&);
|
||||
void setFieldV256 (SField::ref field, const STVector256 & v);
|
||||
|
||||
STObject& peekFieldObject(SField::ref field);
|
||||
STObject& peekFieldObject (SField::ref field);
|
||||
|
||||
bool isFieldPresent(SField::ref field) const;
|
||||
SerializedType* makeFieldPresent(SField::ref field);
|
||||
void makeFieldAbsent(SField::ref field);
|
||||
bool delField(SField::ref field);
|
||||
void delField(int index);
|
||||
bool isFieldPresent (SField::ref field) const;
|
||||
SerializedType* makeFieldPresent (SField::ref field);
|
||||
void makeFieldAbsent (SField::ref field);
|
||||
bool delField (SField::ref field);
|
||||
void delField (int index);
|
||||
|
||||
static UPTR_T <SerializedType> makeDefaultObject(SerializedTypeID id, SField::ref name);
|
||||
static UPTR_T <SerializedType> makeDefaultObject (SerializedTypeID id, SField::ref name);
|
||||
|
||||
// VFALCO TODO remove the 'depth' parameter
|
||||
static UPTR_T<SerializedType> makeDeserializedObject (
|
||||
SerializedTypeID id,
|
||||
SField::ref name,
|
||||
SerializerIterator &,
|
||||
SerializerIterator&,
|
||||
int depth);
|
||||
|
||||
static UPTR_T<SerializedType> makeNonPresentObject (SField::ref name)
|
||||
{
|
||||
return makeDefaultObject(STI_NOTPRESENT, name);
|
||||
static UPTR_T<SerializedType> makeNonPresentObject (SField::ref name)
|
||||
{
|
||||
return makeDefaultObject (STI_NOTPRESENT, name);
|
||||
}
|
||||
|
||||
static UPTR_T<SerializedType> makeDefaultObject (SField::ref name)
|
||||
{
|
||||
return makeDefaultObject(name.fieldType, name);
|
||||
{
|
||||
return makeDefaultObject (name.fieldType, name);
|
||||
}
|
||||
|
||||
// field iterator stuff
|
||||
typedef boost::ptr_vector<SerializedType>::iterator iterator;
|
||||
typedef boost::ptr_vector<SerializedType>::const_iterator const_iterator;
|
||||
iterator begin() { return mData.begin(); }
|
||||
iterator end() { return mData.end(); }
|
||||
const_iterator begin() const { return mData.begin(); }
|
||||
const_iterator end() const { return mData.end(); }
|
||||
bool empty() const { return mData.empty(); }
|
||||
// field iterator stuff
|
||||
typedef boost::ptr_vector<SerializedType>::iterator iterator;
|
||||
typedef boost::ptr_vector<SerializedType>::const_iterator const_iterator;
|
||||
iterator begin ()
|
||||
{
|
||||
return mData.begin ();
|
||||
}
|
||||
iterator end ()
|
||||
{
|
||||
return mData.end ();
|
||||
}
|
||||
const_iterator begin () const
|
||||
{
|
||||
return mData.begin ();
|
||||
}
|
||||
const_iterator end () const
|
||||
{
|
||||
return mData.end ();
|
||||
}
|
||||
bool empty () const
|
||||
{
|
||||
return mData.empty ();
|
||||
}
|
||||
|
||||
bool hasMatchingEntry(const SerializedType&);
|
||||
bool hasMatchingEntry (const SerializedType&);
|
||||
|
||||
bool operator==(const STObject& o) const;
|
||||
bool operator!=(const STObject& o) const { return ! (*this == o); }
|
||||
bool operator== (const STObject & o) const;
|
||||
bool operator!= (const STObject & o) const
|
||||
{
|
||||
return ! (*this == o);
|
||||
}
|
||||
|
||||
private:
|
||||
boost::ptr_vector<SerializedType> mData;
|
||||
const SOTemplate* mType;
|
||||
boost::ptr_vector<SerializedType> mData;
|
||||
const SOTemplate* mType;
|
||||
|
||||
STObject* duplicate() const { return new STObject(*this); }
|
||||
STObject(SField::ref name, boost::ptr_vector<SerializedType>& data) : SerializedType(name), mType(NULL)
|
||||
{ mData.swap(data); }
|
||||
STObject* duplicate () const
|
||||
{
|
||||
return new STObject (*this);
|
||||
}
|
||||
STObject (SField::ref name, boost::ptr_vector<SerializedType>& data) : SerializedType (name), mType (NULL)
|
||||
{
|
||||
mData.swap (data);
|
||||
}
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
inline STObject::iterator range_begin(STObject& x) { return x.begin(); }
|
||||
inline STObject::iterator range_end(STObject &x) { return x.end(); }
|
||||
inline STObject::iterator range_begin (STObject& x)
|
||||
{
|
||||
return x.begin ();
|
||||
}
|
||||
inline STObject::iterator range_end (STObject& x)
|
||||
{
|
||||
return x.end ();
|
||||
}
|
||||
namespace boost
|
||||
{
|
||||
template<> struct range_mutable_iterator<STObject> { typedef STObject::iterator type; };
|
||||
template<> struct range_const_iterator<STObject> { typedef STObject::const_iterator type; };
|
||||
template<> struct range_mutable_iterator<STObject>
|
||||
{
|
||||
typedef STObject::iterator type;
|
||||
};
|
||||
template<> struct range_const_iterator<STObject>
|
||||
{
|
||||
typedef STObject::const_iterator type;
|
||||
};
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
class STArray : public SerializedType, private IS_INSTANCE(SerializedArray)
|
||||
class STArray : public SerializedType, private IS_INSTANCE (SerializedArray)
|
||||
{
|
||||
public:
|
||||
typedef boost::ptr_vector<STObject> vector;
|
||||
typedef boost::ptr_vector<STObject>::iterator iterator;
|
||||
typedef boost::ptr_vector<STObject>::const_iterator const_iterator;
|
||||
typedef boost::ptr_vector<STObject>::reverse_iterator reverse_iterator;
|
||||
typedef boost::ptr_vector<STObject>::const_reverse_iterator const_reverse_iterator;
|
||||
typedef boost::ptr_vector<STObject>::size_type size_type;
|
||||
typedef boost::ptr_vector<STObject> vector;
|
||||
typedef boost::ptr_vector<STObject>::iterator iterator;
|
||||
typedef boost::ptr_vector<STObject>::const_iterator const_iterator;
|
||||
typedef boost::ptr_vector<STObject>::reverse_iterator reverse_iterator;
|
||||
typedef boost::ptr_vector<STObject>::const_reverse_iterator const_reverse_iterator;
|
||||
typedef boost::ptr_vector<STObject>::size_type size_type;
|
||||
|
||||
public:
|
||||
STArray () { ; }
|
||||
explicit STArray(int n) { value.reserve(n); }
|
||||
explicit STArray(SField::ref f) : SerializedType(f) { ; }
|
||||
STArray(SField::ref f, int n) : SerializedType(f) { value.reserve(n); }
|
||||
STArray(SField::ref f, const vector& v) : SerializedType(f), value(v) { ; }
|
||||
explicit STArray(vector& v) : value(v) { ; }
|
||||
STArray ()
|
||||
{
|
||||
;
|
||||
}
|
||||
explicit STArray (int n)
|
||||
{
|
||||
value.reserve (n);
|
||||
}
|
||||
explicit STArray (SField::ref f) : SerializedType (f)
|
||||
{
|
||||
;
|
||||
}
|
||||
STArray (SField::ref f, int n) : SerializedType (f)
|
||||
{
|
||||
value.reserve (n);
|
||||
}
|
||||
STArray (SField::ref f, const vector & v) : SerializedType (f), value (v)
|
||||
{
|
||||
;
|
||||
}
|
||||
explicit STArray (vector & v) : value (v)
|
||||
{
|
||||
;
|
||||
}
|
||||
|
||||
static UPTR_T<SerializedType> deserialize(SerializerIterator& sit, SField::ref name)
|
||||
{ return UPTR_T<SerializedType>(construct(sit, name)); }
|
||||
static UPTR_T<SerializedType> deserialize (SerializerIterator & sit, SField::ref name)
|
||||
{
|
||||
return UPTR_T<SerializedType> (construct (sit, name));
|
||||
}
|
||||
|
||||
const vector& getValue() const { return value; }
|
||||
vector& getValue() { return value; }
|
||||
const vector& getValue () const
|
||||
{
|
||||
return value;
|
||||
}
|
||||
vector& getValue ()
|
||||
{
|
||||
return value;
|
||||
}
|
||||
|
||||
// VFALCO NOTE as long as we're married to boost why not use boost::iterator_facade?
|
||||
//
|
||||
// vector-like functions
|
||||
void push_back(const STObject& object) { value.push_back(object.oClone().release()); }
|
||||
STObject& operator[](int j) { return value[j]; }
|
||||
const STObject& operator[](int j) const { return value[j]; }
|
||||
iterator begin() { return value.begin(); }
|
||||
const_iterator begin() const { return value.begin(); }
|
||||
iterator end() { return value.end(); }
|
||||
const_iterator end() const { return value.end(); }
|
||||
size_type size() const { return value.size(); }
|
||||
reverse_iterator rbegin() { return value.rbegin(); }
|
||||
const_reverse_iterator rbegin() const { return value.rbegin(); }
|
||||
reverse_iterator rend() { return value.rend(); }
|
||||
const_reverse_iterator rend() const { return value.rend(); }
|
||||
iterator erase(iterator pos) { return value.erase(pos); }
|
||||
STObject& front() { return value.front(); }
|
||||
const STObject& front() const { return value.front(); }
|
||||
STObject& back() { return value.back(); }
|
||||
const STObject& back() const { return value.back(); }
|
||||
void pop_back() { value.pop_back(); }
|
||||
bool empty() const { return value.empty(); }
|
||||
void clear() { value.clear(); }
|
||||
void swap(STArray& a) { value.swap(a.value); }
|
||||
void push_back (const STObject & object)
|
||||
{
|
||||
value.push_back (object.oClone ().release ());
|
||||
}
|
||||
STObject& operator[] (int j)
|
||||
{
|
||||
return value[j];
|
||||
}
|
||||
const STObject& operator[] (int j) const
|
||||
{
|
||||
return value[j];
|
||||
}
|
||||
iterator begin ()
|
||||
{
|
||||
return value.begin ();
|
||||
}
|
||||
const_iterator begin () const
|
||||
{
|
||||
return value.begin ();
|
||||
}
|
||||
iterator end ()
|
||||
{
|
||||
return value.end ();
|
||||
}
|
||||
const_iterator end () const
|
||||
{
|
||||
return value.end ();
|
||||
}
|
||||
size_type size () const
|
||||
{
|
||||
return value.size ();
|
||||
}
|
||||
reverse_iterator rbegin ()
|
||||
{
|
||||
return value.rbegin ();
|
||||
}
|
||||
const_reverse_iterator rbegin () const
|
||||
{
|
||||
return value.rbegin ();
|
||||
}
|
||||
reverse_iterator rend ()
|
||||
{
|
||||
return value.rend ();
|
||||
}
|
||||
const_reverse_iterator rend () const
|
||||
{
|
||||
return value.rend ();
|
||||
}
|
||||
iterator erase (iterator pos)
|
||||
{
|
||||
return value.erase (pos);
|
||||
}
|
||||
STObject& front ()
|
||||
{
|
||||
return value.front ();
|
||||
}
|
||||
const STObject& front () const
|
||||
{
|
||||
return value.front ();
|
||||
}
|
||||
STObject& back ()
|
||||
{
|
||||
return value.back ();
|
||||
}
|
||||
const STObject& back () const
|
||||
{
|
||||
return value.back ();
|
||||
}
|
||||
void pop_back ()
|
||||
{
|
||||
value.pop_back ();
|
||||
}
|
||||
bool empty () const
|
||||
{
|
||||
return value.empty ();
|
||||
}
|
||||
void clear ()
|
||||
{
|
||||
value.clear ();
|
||||
}
|
||||
void swap (STArray & a)
|
||||
{
|
||||
value.swap (a.value);
|
||||
}
|
||||
|
||||
virtual std::string getFullText() const;
|
||||
virtual std::string getText() const;
|
||||
virtual Json::Value getJson(int) const;
|
||||
virtual void add(Serializer& s) const;
|
||||
virtual std::string getFullText () const;
|
||||
virtual std::string getText () const;
|
||||
virtual Json::Value getJson (int) const;
|
||||
virtual void add (Serializer & s) const;
|
||||
|
||||
void sort(bool (*compare)(const STObject& o1, const STObject& o2));
|
||||
void sort (bool (*compare) (const STObject & o1, const STObject & o2));
|
||||
|
||||
bool operator==(const STArray &s) { return value == s.value; }
|
||||
bool operator!=(const STArray &s) { return value != s.value; }
|
||||
bool operator== (const STArray & s)
|
||||
{
|
||||
return value == s.value;
|
||||
}
|
||||
bool operator!= (const STArray & s)
|
||||
{
|
||||
return value != s.value;
|
||||
}
|
||||
|
||||
virtual SerializedTypeID getSType() const { return STI_ARRAY; }
|
||||
virtual bool isEquivalent(const SerializedType& t) const;
|
||||
virtual bool isDefault() const { return value.empty(); }
|
||||
virtual SerializedTypeID getSType () const
|
||||
{
|
||||
return STI_ARRAY;
|
||||
}
|
||||
virtual bool isEquivalent (const SerializedType & t) const;
|
||||
virtual bool isDefault () const
|
||||
{
|
||||
return value.empty ();
|
||||
}
|
||||
|
||||
private:
|
||||
vector value;
|
||||
vector value;
|
||||
|
||||
STArray* duplicate() const { return new STArray(*this); }
|
||||
static STArray* construct(SerializerIterator&, SField::ref);
|
||||
STArray* duplicate () const
|
||||
{
|
||||
return new STArray (*this);
|
||||
}
|
||||
static STArray* construct (SerializerIterator&, SField::ref);
|
||||
};
|
||||
|
||||
inline STArray::iterator range_begin(STArray& x) { return x.begin(); }
|
||||
inline STArray::iterator range_end(STArray &x) { return x.end(); }
|
||||
inline STArray::iterator range_begin (STArray& x)
|
||||
{
|
||||
return x.begin ();
|
||||
}
|
||||
inline STArray::iterator range_end (STArray& x)
|
||||
{
|
||||
return x.end ();
|
||||
}
|
||||
namespace boost
|
||||
{
|
||||
template<> struct range_mutable_iterator<STArray> { typedef STArray::iterator type; };
|
||||
template<> struct range_const_iterator<STArray> { typedef STArray::const_iterator type; };
|
||||
template<> struct range_mutable_iterator<STArray>
|
||||
{
|
||||
typedef STArray::iterator type;
|
||||
};
|
||||
template<> struct range_const_iterator<STArray>
|
||||
{
|
||||
typedef STArray::const_iterator type;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -8,24 +8,24 @@ void SOTemplate::push_back (SOElement const& r)
|
||||
// Ensure there is the enough space in the index mapping
|
||||
// table for all possible fields.
|
||||
//
|
||||
if (mIndex.empty())
|
||||
if (mIndex.empty ())
|
||||
{
|
||||
// Unmapped indices will be set to -1
|
||||
//
|
||||
mIndex.resize (SField::getNumFields() + 1, -1);
|
||||
mIndex.resize (SField::getNumFields () + 1, -1);
|
||||
}
|
||||
|
||||
// Make sure the field's index is in range
|
||||
//
|
||||
assert (r.e_field.getNum() < mIndex.size());
|
||||
assert (r.e_field.getNum () < mIndex.size ());
|
||||
|
||||
// Make sure that this field hasn't already been assigned
|
||||
//
|
||||
assert(getIndex(r.e_field) == -1);
|
||||
assert (getIndex (r.e_field) == -1);
|
||||
|
||||
// Add the field to the index mapping table
|
||||
//
|
||||
mIndex [r.e_field.getNum ()] = mTypes.size();
|
||||
mIndex [r.e_field.getNum ()] = mTypes.size ();
|
||||
|
||||
// Append the new element.
|
||||
//
|
||||
@@ -36,7 +36,7 @@ int SOTemplate::getIndex (SField::ref f) const
|
||||
{
|
||||
// The mapping table should be large enough for any possible field
|
||||
//
|
||||
assert (f.getNum() < mIndex.size());
|
||||
assert (f.getNum () < mIndex.size ());
|
||||
|
||||
return mIndex[f.getNum()];
|
||||
return mIndex[f.getNum ()];
|
||||
}
|
||||
|
||||
@@ -8,10 +8,10 @@
|
||||
// VFALCO NOTE these don't look like bit-flags...
|
||||
enum SOE_Flags
|
||||
{
|
||||
SOE_INVALID = -1,
|
||||
SOE_REQUIRED = 0, // required
|
||||
SOE_OPTIONAL = 1, // optional, may be present with default value
|
||||
SOE_DEFAULT = 2, // optional, if present, must not have default value
|
||||
SOE_INVALID = -1,
|
||||
SOE_REQUIRED = 0, // required
|
||||
SOE_OPTIONAL = 1, // optional, may be present with default value
|
||||
SOE_DEFAULT = 2, // optional, if present, must not have default value
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
@@ -21,10 +21,10 @@ enum SOE_Flags
|
||||
class SOElement
|
||||
{
|
||||
public:
|
||||
SField::ref const e_field;
|
||||
SOE_Flags const flags;
|
||||
SField::ref const e_field;
|
||||
SOE_Flags const flags;
|
||||
|
||||
SOElement (SField::ref fieldName, SOE_Flags flags)
|
||||
SOElement (SField::ref fieldName, SOE_Flags flags)
|
||||
: e_field (fieldName)
|
||||
, flags (flags)
|
||||
{
|
||||
@@ -48,12 +48,12 @@ public:
|
||||
|
||||
@see push_back
|
||||
*/
|
||||
SOTemplate ();
|
||||
SOTemplate ();
|
||||
|
||||
// VFALCO NOTE Why do we even bother with the 'private' keyword if
|
||||
// this function is present?
|
||||
//
|
||||
std::vector <SOElement const*> const& peek() const
|
||||
std::vector <SOElement const*> const& peek () const
|
||||
{
|
||||
return mTypes;
|
||||
}
|
||||
@@ -67,9 +67,9 @@ public:
|
||||
int getIndex (SField::ref) const;
|
||||
|
||||
private:
|
||||
std::vector <SOElement const*> mTypes;
|
||||
std::vector <SOElement const*> mTypes;
|
||||
|
||||
std::vector <int> mIndex; // field num -> index
|
||||
std::vector <int> mIndex; // field num -> index
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,265 +1,291 @@
|
||||
|
||||
SETUP_LOG (SerializedType)
|
||||
|
||||
const STAmount saZero(CURRENCY_ONE, ACCOUNT_ONE, 0);
|
||||
const STAmount saOne(CURRENCY_ONE, ACCOUNT_ONE, 1);
|
||||
const STAmount saZero (CURRENCY_ONE, ACCOUNT_ONE, 0);
|
||||
const STAmount saOne (CURRENCY_ONE, ACCOUNT_ONE, 1);
|
||||
|
||||
SerializedType& SerializedType::operator=(const SerializedType& t)
|
||||
SerializedType& SerializedType::operator= (const SerializedType& t)
|
||||
{
|
||||
if ((t.fName != fName) && fName->isUseful() && t.fName->isUseful())
|
||||
{
|
||||
WriteLog ((t.getSType() == STI_AMOUNT) ? lsDEBUG : lsWARNING, SerializedType) // This is common for amounts
|
||||
<< "Caution: " << t.fName->getName() << " not replacing " << fName->getName();
|
||||
}
|
||||
if (!fName->isUseful()) fName = t.fName;
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
void STPathSet::printDebug() {
|
||||
for (int i = 0; i < value.size(); i++) {
|
||||
std::cerr << i << ": ";
|
||||
for (int j = 0; j < value[i].mPath.size(); j++) {
|
||||
//STPathElement pe = value[i].mPath[j];
|
||||
RippleAddress nad;
|
||||
nad.setAccountID(value[i].mPath[j].mAccountID);
|
||||
std::cerr << " " << nad.humanAccountID();
|
||||
//std::cerr << " " << pe.mAccountID.GetHex();
|
||||
if ((t.fName != fName) && fName->isUseful () && t.fName->isUseful ())
|
||||
{
|
||||
WriteLog ((t.getSType () == STI_AMOUNT) ? lsDEBUG : lsWARNING, SerializedType) // This is common for amounts
|
||||
<< "Caution: " << t.fName->getName () << " not replacing " << fName->getName ();
|
||||
}
|
||||
std::cerr << std::endl;
|
||||
}
|
||||
|
||||
if (!fName->isUseful ()) fName = t.fName;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
void STPath::printDebug() {
|
||||
std::cerr << "STPath:" << std::endl;
|
||||
for(int i =0; i < mPath.size(); i++) {
|
||||
RippleAddress nad;
|
||||
nad.setAccountID(mPath[i].mAccountID);
|
||||
std::cerr << " " << i << ": " << nad.humanAccountID() << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
std::string SerializedType::getFullText() const
|
||||
void STPathSet::printDebug ()
|
||||
{
|
||||
std::string ret;
|
||||
if (getSType() != STI_NOTPRESENT)
|
||||
{
|
||||
if(fName->hasName())
|
||||
{
|
||||
ret = fName->fieldName;
|
||||
ret += " = ";
|
||||
}
|
||||
ret += getText();
|
||||
}
|
||||
return ret;
|
||||
for (int i = 0; i < value.size (); i++)
|
||||
{
|
||||
std::cerr << i << ": ";
|
||||
|
||||
for (int j = 0; j < value[i].mPath.size (); j++)
|
||||
{
|
||||
//STPathElement pe = value[i].mPath[j];
|
||||
RippleAddress nad;
|
||||
nad.setAccountID (value[i].mPath[j].mAccountID);
|
||||
std::cerr << " " << nad.humanAccountID ();
|
||||
//std::cerr << " " << pe.mAccountID.GetHex();
|
||||
}
|
||||
|
||||
std::cerr << std::endl;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
STUInt8* STUInt8::construct(SerializerIterator& u, SField::ref name)
|
||||
void STPath::printDebug ()
|
||||
{
|
||||
return new STUInt8(name, u.get8());
|
||||
std::cerr << "STPath:" << std::endl;
|
||||
|
||||
for (int i = 0; i < mPath.size (); i++)
|
||||
{
|
||||
RippleAddress nad;
|
||||
nad.setAccountID (mPath[i].mAccountID);
|
||||
std::cerr << " " << i << ": " << nad.humanAccountID () << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
std::string STUInt8::getText() const
|
||||
std::string SerializedType::getFullText () const
|
||||
{
|
||||
if (getFName() == sfTransactionResult)
|
||||
{
|
||||
std::string token, human;
|
||||
if (transResultInfo(static_cast<TER>(value), token, human))
|
||||
return human;
|
||||
}
|
||||
return boost::lexical_cast<std::string>(value);
|
||||
std::string ret;
|
||||
|
||||
if (getSType () != STI_NOTPRESENT)
|
||||
{
|
||||
if (fName->hasName ())
|
||||
{
|
||||
ret = fName->fieldName;
|
||||
ret += " = ";
|
||||
}
|
||||
|
||||
ret += getText ();
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
Json::Value STUInt8::getJson(int) const
|
||||
STUInt8* STUInt8::construct (SerializerIterator& u, SField::ref name)
|
||||
{
|
||||
if (getFName() == sfTransactionResult)
|
||||
{
|
||||
std::string token, human;
|
||||
if (transResultInfo(static_cast<TER>(value), token, human))
|
||||
return token;
|
||||
else
|
||||
WriteLog (lsWARNING, SerializedType) << "Unknown result code in metadata: " << value;
|
||||
}
|
||||
return value;
|
||||
return new STUInt8 (name, u.get8 ());
|
||||
}
|
||||
|
||||
bool STUInt8::isEquivalent(const SerializedType& t) const
|
||||
std::string STUInt8::getText () const
|
||||
{
|
||||
const STUInt8* v = dynamic_cast<const STUInt8*>(&t);
|
||||
return v && (value == v->value);
|
||||
if (getFName () == sfTransactionResult)
|
||||
{
|
||||
std::string token, human;
|
||||
|
||||
if (transResultInfo (static_cast<TER> (value), token, human))
|
||||
return human;
|
||||
}
|
||||
|
||||
return boost::lexical_cast<std::string> (value);
|
||||
}
|
||||
|
||||
STUInt16* STUInt16::construct(SerializerIterator& u, SField::ref name)
|
||||
Json::Value STUInt8::getJson (int) const
|
||||
{
|
||||
return new STUInt16(name, u.get16());
|
||||
if (getFName () == sfTransactionResult)
|
||||
{
|
||||
std::string token, human;
|
||||
|
||||
if (transResultInfo (static_cast<TER> (value), token, human))
|
||||
return token;
|
||||
else
|
||||
WriteLog (lsWARNING, SerializedType) << "Unknown result code in metadata: " << value;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
std::string STUInt16::getText() const
|
||||
bool STUInt8::isEquivalent (const SerializedType& t) const
|
||||
{
|
||||
if (getFName() == sfLedgerEntryType)
|
||||
{
|
||||
LedgerEntryFormat *f = LedgerEntryFormat::getLgrFormat(value);
|
||||
if (f != NULL)
|
||||
return f->t_name;
|
||||
}
|
||||
if (getFName() == sfTransactionType)
|
||||
{
|
||||
TransactionFormat *f = TransactionFormat::getTxnFormat(value);
|
||||
if (f != NULL)
|
||||
return f->t_name;
|
||||
}
|
||||
return boost::lexical_cast<std::string>(value);
|
||||
const STUInt8* v = dynamic_cast<const STUInt8*> (&t);
|
||||
return v && (value == v->value);
|
||||
}
|
||||
|
||||
Json::Value STUInt16::getJson(int) const
|
||||
STUInt16* STUInt16::construct (SerializerIterator& u, SField::ref name)
|
||||
{
|
||||
if (getFName() == sfLedgerEntryType)
|
||||
{
|
||||
LedgerEntryFormat *f = LedgerEntryFormat::getLgrFormat(value);
|
||||
if (f != NULL)
|
||||
return f->t_name;
|
||||
}
|
||||
if (getFName() == sfTransactionType)
|
||||
{
|
||||
TransactionFormat *f = TransactionFormat::getTxnFormat(value);
|
||||
if (f != NULL)
|
||||
return f->t_name;
|
||||
}
|
||||
return value;
|
||||
return new STUInt16 (name, u.get16 ());
|
||||
}
|
||||
|
||||
bool STUInt16::isEquivalent(const SerializedType& t) const
|
||||
std::string STUInt16::getText () const
|
||||
{
|
||||
const STUInt16* v = dynamic_cast<const STUInt16*>(&t);
|
||||
return v && (value == v->value);
|
||||
if (getFName () == sfLedgerEntryType)
|
||||
{
|
||||
LedgerEntryFormat* f = LedgerEntryFormat::getLgrFormat (value);
|
||||
|
||||
if (f != NULL)
|
||||
return f->t_name;
|
||||
}
|
||||
|
||||
if (getFName () == sfTransactionType)
|
||||
{
|
||||
TransactionFormat* f = TransactionFormat::getTxnFormat (value);
|
||||
|
||||
if (f != NULL)
|
||||
return f->t_name;
|
||||
}
|
||||
|
||||
return boost::lexical_cast<std::string> (value);
|
||||
}
|
||||
|
||||
STUInt32* STUInt32::construct(SerializerIterator& u, SField::ref name)
|
||||
{
|
||||
return new STUInt32(name, u.get32());
|
||||
}
|
||||
|
||||
std::string STUInt32::getText() const
|
||||
Json::Value STUInt16::getJson (int) const
|
||||
{
|
||||
return boost::lexical_cast<std::string>(value);
|
||||
if (getFName () == sfLedgerEntryType)
|
||||
{
|
||||
LedgerEntryFormat* f = LedgerEntryFormat::getLgrFormat (value);
|
||||
|
||||
if (f != NULL)
|
||||
return f->t_name;
|
||||
}
|
||||
|
||||
if (getFName () == sfTransactionType)
|
||||
{
|
||||
TransactionFormat* f = TransactionFormat::getTxnFormat (value);
|
||||
|
||||
if (f != NULL)
|
||||
return f->t_name;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
Json::Value STUInt32::getJson(int) const
|
||||
bool STUInt16::isEquivalent (const SerializedType& t) const
|
||||
{
|
||||
return value;
|
||||
const STUInt16* v = dynamic_cast<const STUInt16*> (&t);
|
||||
return v && (value == v->value);
|
||||
}
|
||||
|
||||
bool STUInt32::isEquivalent(const SerializedType& t) const
|
||||
STUInt32* STUInt32::construct (SerializerIterator& u, SField::ref name)
|
||||
{
|
||||
const STUInt32* v = dynamic_cast<const STUInt32*>(&t);
|
||||
return v && (value == v->value);
|
||||
return new STUInt32 (name, u.get32 ());
|
||||
}
|
||||
|
||||
STUInt64* STUInt64::construct(SerializerIterator& u, SField::ref name)
|
||||
std::string STUInt32::getText () const
|
||||
{
|
||||
return new STUInt64(name, u.get64());
|
||||
return boost::lexical_cast<std::string> (value);
|
||||
}
|
||||
|
||||
std::string STUInt64::getText() const
|
||||
Json::Value STUInt32::getJson (int) const
|
||||
{
|
||||
return boost::lexical_cast<std::string>(value);
|
||||
return value;
|
||||
}
|
||||
|
||||
Json::Value STUInt64::getJson(int) const
|
||||
bool STUInt32::isEquivalent (const SerializedType& t) const
|
||||
{
|
||||
return strHex(value);
|
||||
const STUInt32* v = dynamic_cast<const STUInt32*> (&t);
|
||||
return v && (value == v->value);
|
||||
}
|
||||
|
||||
bool STUInt64::isEquivalent(const SerializedType& t) const
|
||||
STUInt64* STUInt64::construct (SerializerIterator& u, SField::ref name)
|
||||
{
|
||||
const STUInt64* v = dynamic_cast<const STUInt64*>(&t);
|
||||
return v && (value == v->value);
|
||||
return new STUInt64 (name, u.get64 ());
|
||||
}
|
||||
|
||||
STHash128* STHash128::construct(SerializerIterator& u, SField::ref name)
|
||||
std::string STUInt64::getText () const
|
||||
{
|
||||
return new STHash128(name, u.get128());
|
||||
return boost::lexical_cast<std::string> (value);
|
||||
}
|
||||
|
||||
std::string STHash128::getText() const
|
||||
Json::Value STUInt64::getJson (int) const
|
||||
{
|
||||
return value.GetHex();
|
||||
return strHex (value);
|
||||
}
|
||||
|
||||
bool STHash128::isEquivalent(const SerializedType& t) const
|
||||
bool STUInt64::isEquivalent (const SerializedType& t) const
|
||||
{
|
||||
const STHash128* v = dynamic_cast<const STHash128*>(&t);
|
||||
return v && (value == v->value);
|
||||
const STUInt64* v = dynamic_cast<const STUInt64*> (&t);
|
||||
return v && (value == v->value);
|
||||
}
|
||||
|
||||
STHash160* STHash160::construct(SerializerIterator& u, SField::ref name)
|
||||
STHash128* STHash128::construct (SerializerIterator& u, SField::ref name)
|
||||
{
|
||||
return new STHash160(name, u.get160());
|
||||
return new STHash128 (name, u.get128 ());
|
||||
}
|
||||
|
||||
std::string STHash160::getText() const
|
||||
std::string STHash128::getText () const
|
||||
{
|
||||
return value.GetHex();
|
||||
return value.GetHex ();
|
||||
}
|
||||
|
||||
bool STHash160::isEquivalent(const SerializedType& t) const
|
||||
bool STHash128::isEquivalent (const SerializedType& t) const
|
||||
{
|
||||
const STHash160* v = dynamic_cast<const STHash160*>(&t);
|
||||
return v && (value == v->value);
|
||||
const STHash128* v = dynamic_cast<const STHash128*> (&t);
|
||||
return v && (value == v->value);
|
||||
}
|
||||
|
||||
STHash256* STHash256::construct(SerializerIterator& u, SField::ref name)
|
||||
STHash160* STHash160::construct (SerializerIterator& u, SField::ref name)
|
||||
{
|
||||
return new STHash256(name, u.get256());
|
||||
return new STHash160 (name, u.get160 ());
|
||||
}
|
||||
|
||||
std::string STHash256::getText() const
|
||||
std::string STHash160::getText () const
|
||||
{
|
||||
return value.GetHex();
|
||||
return value.GetHex ();
|
||||
}
|
||||
|
||||
bool STHash256::isEquivalent(const SerializedType& t) const
|
||||
bool STHash160::isEquivalent (const SerializedType& t) const
|
||||
{
|
||||
const STHash256* v = dynamic_cast<const STHash256*>(&t);
|
||||
return v && (value == v->value);
|
||||
const STHash160* v = dynamic_cast<const STHash160*> (&t);
|
||||
return v && (value == v->value);
|
||||
}
|
||||
|
||||
STVariableLength::STVariableLength(SerializerIterator& st, SField::ref name) : SerializedType(name)
|
||||
STHash256* STHash256::construct (SerializerIterator& u, SField::ref name)
|
||||
{
|
||||
value = st.getVL();
|
||||
return new STHash256 (name, u.get256 ());
|
||||
}
|
||||
|
||||
std::string STVariableLength::getText() const
|
||||
std::string STHash256::getText () const
|
||||
{
|
||||
return strHex(value);
|
||||
return value.GetHex ();
|
||||
}
|
||||
|
||||
STVariableLength* STVariableLength::construct(SerializerIterator& u, SField::ref name)
|
||||
bool STHash256::isEquivalent (const SerializedType& t) const
|
||||
{
|
||||
return new STVariableLength(name, u.getVL());
|
||||
const STHash256* v = dynamic_cast<const STHash256*> (&t);
|
||||
return v && (value == v->value);
|
||||
}
|
||||
|
||||
bool STVariableLength::isEquivalent(const SerializedType& t) const
|
||||
STVariableLength::STVariableLength (SerializerIterator& st, SField::ref name) : SerializedType (name)
|
||||
{
|
||||
const STVariableLength* v = dynamic_cast<const STVariableLength*>(&t);
|
||||
return v && (value == v->value);
|
||||
value = st.getVL ();
|
||||
}
|
||||
|
||||
std::string STAccount::getText() const
|
||||
std::string STVariableLength::getText () const
|
||||
{
|
||||
uint160 u;
|
||||
RippleAddress a;
|
||||
|
||||
if (!getValueH160(u))
|
||||
return STVariableLength::getText();
|
||||
a.setAccountID(u);
|
||||
return a.humanAccountID();
|
||||
return strHex (value);
|
||||
}
|
||||
|
||||
STAccount* STAccount::construct(SerializerIterator& u, SField::ref name)
|
||||
STVariableLength* STVariableLength::construct (SerializerIterator& u, SField::ref name)
|
||||
{
|
||||
return new STAccount(name, u.getVL());
|
||||
return new STVariableLength (name, u.getVL ());
|
||||
}
|
||||
|
||||
bool STVariableLength::isEquivalent (const SerializedType& t) const
|
||||
{
|
||||
const STVariableLength* v = dynamic_cast<const STVariableLength*> (&t);
|
||||
return v && (value == v->value);
|
||||
}
|
||||
|
||||
std::string STAccount::getText () const
|
||||
{
|
||||
uint160 u;
|
||||
RippleAddress a;
|
||||
|
||||
if (!getValueH160 (u))
|
||||
return STVariableLength::getText ();
|
||||
|
||||
a.setAccountID (u);
|
||||
return a.humanAccountID ();
|
||||
}
|
||||
|
||||
STAccount* STAccount::construct (SerializerIterator& u, SField::ref name)
|
||||
{
|
||||
return new STAccount (name, u.getVL ());
|
||||
}
|
||||
|
||||
//
|
||||
@@ -267,287 +293,298 @@ STAccount* STAccount::construct(SerializerIterator& u, SField::ref name)
|
||||
//
|
||||
|
||||
// Return a new object from a SerializerIterator.
|
||||
STVector256* STVector256::construct(SerializerIterator& u, SField::ref name)
|
||||
STVector256* STVector256::construct (SerializerIterator& u, SField::ref name)
|
||||
{
|
||||
Blob data = u.getVL();
|
||||
Blob ::iterator begin = data.begin();
|
||||
Blob data = u.getVL ();
|
||||
Blob ::iterator begin = data.begin ();
|
||||
|
||||
UPTR_T<STVector256> vec(new STVector256(name));
|
||||
UPTR_T<STVector256> vec (new STVector256 (name));
|
||||
|
||||
int count = data.size() / (256 / 8);
|
||||
vec->mValue.reserve(count);
|
||||
int count = data.size () / (256 / 8);
|
||||
vec->mValue.reserve (count);
|
||||
|
||||
unsigned int uStart = 0;
|
||||
for (unsigned int i = 0; i != count; i++)
|
||||
{
|
||||
unsigned int uEnd = uStart + (256 / 8);
|
||||
unsigned int uStart = 0;
|
||||
|
||||
// This next line could be optimized to construct a default uint256 in the vector and then copy into it
|
||||
vec->mValue.push_back(uint256(Blob (begin + uStart, begin + uEnd)));
|
||||
uStart = uEnd;
|
||||
}
|
||||
for (unsigned int i = 0; i != count; i++)
|
||||
{
|
||||
unsigned int uEnd = uStart + (256 / 8);
|
||||
|
||||
return vec.release();
|
||||
// This next line could be optimized to construct a default uint256 in the vector and then copy into it
|
||||
vec->mValue.push_back (uint256 (Blob (begin + uStart, begin + uEnd)));
|
||||
uStart = uEnd;
|
||||
}
|
||||
|
||||
return vec.release ();
|
||||
}
|
||||
|
||||
void STVector256::add(Serializer& s) const
|
||||
void STVector256::add (Serializer& s) const
|
||||
{
|
||||
s.addVL(mValue.empty() ? NULL : mValue[0].begin(), mValue.size() * (256 / 8));
|
||||
s.addVL (mValue.empty () ? NULL : mValue[0].begin (), mValue.size () * (256 / 8));
|
||||
}
|
||||
|
||||
bool STVector256::isEquivalent(const SerializedType& t) const
|
||||
bool STVector256::isEquivalent (const SerializedType& t) const
|
||||
{
|
||||
const STVector256* v = dynamic_cast<const STVector256*>(&t);
|
||||
return v && (mValue == v->mValue);
|
||||
const STVector256* v = dynamic_cast<const STVector256*> (&t);
|
||||
return v && (mValue == v->mValue);
|
||||
}
|
||||
|
||||
bool STVector256::hasValue(uint256 const& v) const
|
||||
bool STVector256::hasValue (uint256 const& v) const
|
||||
{
|
||||
BOOST_FOREACH(uint256 const& hash, mValue)
|
||||
{
|
||||
if (hash == v)
|
||||
return true;
|
||||
}
|
||||
BOOST_FOREACH (uint256 const & hash, mValue)
|
||||
{
|
||||
if (hash == v)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
return false;
|
||||
}
|
||||
|
||||
//
|
||||
// STAccount
|
||||
//
|
||||
|
||||
STAccount::STAccount(SField::ref n, const uint160& v) : STVariableLength(n)
|
||||
STAccount::STAccount (SField::ref n, const uint160& v) : STVariableLength (n)
|
||||
{
|
||||
peekValue().insert(peekValue().end(), v.begin(), v.end());
|
||||
peekValue ().insert (peekValue ().end (), v.begin (), v.end ());
|
||||
}
|
||||
|
||||
bool STAccount::isValueH160() const
|
||||
bool STAccount::isValueH160 () const
|
||||
{
|
||||
return peekValue().size() == (160 / 8);
|
||||
return peekValue ().size () == (160 / 8);
|
||||
}
|
||||
|
||||
void STAccount::setValueH160(const uint160& v)
|
||||
void STAccount::setValueH160 (const uint160& v)
|
||||
{
|
||||
peekValue().clear();
|
||||
peekValue().insert(peekValue().end(), v.begin(), v.end());
|
||||
assert(peekValue().size() == (160/8));
|
||||
peekValue ().clear ();
|
||||
peekValue ().insert (peekValue ().end (), v.begin (), v.end ());
|
||||
assert (peekValue ().size () == (160 / 8));
|
||||
}
|
||||
|
||||
bool STAccount::getValueH160(uint160& v) const
|
||||
bool STAccount::getValueH160 (uint160& v) const
|
||||
{
|
||||
if (!isValueH160()) return false;
|
||||
memcpy(v.begin(), &(peekValue().front()), (160/8));
|
||||
return true;
|
||||
if (!isValueH160 ()) return false;
|
||||
|
||||
memcpy (v.begin (), & (peekValue ().front ()), (160 / 8));
|
||||
return true;
|
||||
}
|
||||
|
||||
RippleAddress STAccount::getValueNCA() const
|
||||
RippleAddress STAccount::getValueNCA () const
|
||||
{
|
||||
RippleAddress a;
|
||||
uint160 v;
|
||||
if (getValueH160(v))
|
||||
a.setAccountID(v);
|
||||
return a;
|
||||
RippleAddress a;
|
||||
uint160 v;
|
||||
|
||||
if (getValueH160 (v))
|
||||
a.setAccountID (v);
|
||||
|
||||
return a;
|
||||
}
|
||||
|
||||
void STAccount::setValueNCA(const RippleAddress& nca)
|
||||
void STAccount::setValueNCA (const RippleAddress& nca)
|
||||
{
|
||||
setValueH160(nca.getAccountID());
|
||||
setValueH160 (nca.getAccountID ());
|
||||
}
|
||||
|
||||
STPathSet* STPathSet::construct(SerializerIterator& s, SField::ref name)
|
||||
STPathSet* STPathSet::construct (SerializerIterator& s, SField::ref name)
|
||||
{
|
||||
std::vector<STPath> paths;
|
||||
std::vector<STPathElement> path;
|
||||
std::vector<STPath> paths;
|
||||
std::vector<STPathElement> path;
|
||||
|
||||
do
|
||||
{
|
||||
int iType = s.get8();
|
||||
do
|
||||
{
|
||||
int iType = s.get8 ();
|
||||
|
||||
if (iType == STPathElement::typeEnd || iType == STPathElement::typeBoundary)
|
||||
{
|
||||
if (path.empty())
|
||||
{
|
||||
WriteLog (lsINFO, SerializedType) << "STPathSet: Empty path.";
|
||||
if (iType == STPathElement::typeEnd || iType == STPathElement::typeBoundary)
|
||||
{
|
||||
if (path.empty ())
|
||||
{
|
||||
WriteLog (lsINFO, SerializedType) << "STPathSet: Empty path.";
|
||||
|
||||
throw std::runtime_error("empty path");
|
||||
}
|
||||
throw std::runtime_error ("empty path");
|
||||
}
|
||||
|
||||
paths.push_back(path);
|
||||
path.clear();
|
||||
paths.push_back (path);
|
||||
path.clear ();
|
||||
|
||||
if (iType == STPathElement::typeEnd)
|
||||
{
|
||||
return new STPathSet(name, paths);
|
||||
}
|
||||
}
|
||||
else if (iType & ~STPathElement::typeValidBits)
|
||||
{
|
||||
WriteLog (lsINFO, SerializedType) << "STPathSet: Bad path element: " << iType;
|
||||
if (iType == STPathElement::typeEnd)
|
||||
{
|
||||
return new STPathSet (name, paths);
|
||||
}
|
||||
}
|
||||
else if (iType & ~STPathElement::typeValidBits)
|
||||
{
|
||||
WriteLog (lsINFO, SerializedType) << "STPathSet: Bad path element: " << iType;
|
||||
|
||||
throw std::runtime_error("bad path element");
|
||||
}
|
||||
else
|
||||
{
|
||||
const bool bAccount = !!(iType & STPathElement::typeAccount);
|
||||
const bool bCurrency = !!(iType & STPathElement::typeCurrency);
|
||||
const bool bIssuer = !!(iType & STPathElement::typeIssuer);
|
||||
throw std::runtime_error ("bad path element");
|
||||
}
|
||||
else
|
||||
{
|
||||
const bool bAccount = !! (iType & STPathElement::typeAccount);
|
||||
const bool bCurrency = !! (iType & STPathElement::typeCurrency);
|
||||
const bool bIssuer = !! (iType & STPathElement::typeIssuer);
|
||||
|
||||
uint160 uAccountID;
|
||||
uint160 uCurrency;
|
||||
uint160 uIssuerID;
|
||||
uint160 uAccountID;
|
||||
uint160 uCurrency;
|
||||
uint160 uIssuerID;
|
||||
|
||||
if (bAccount)
|
||||
uAccountID = s.get160();
|
||||
if (bAccount)
|
||||
uAccountID = s.get160 ();
|
||||
|
||||
if (bCurrency)
|
||||
uCurrency = s.get160();
|
||||
if (bCurrency)
|
||||
uCurrency = s.get160 ();
|
||||
|
||||
if (bIssuer)
|
||||
uIssuerID = s.get160();
|
||||
if (bIssuer)
|
||||
uIssuerID = s.get160 ();
|
||||
|
||||
path.push_back(STPathElement(uAccountID, uCurrency, uIssuerID, bCurrency));
|
||||
}
|
||||
} while(1);
|
||||
path.push_back (STPathElement (uAccountID, uCurrency, uIssuerID, bCurrency));
|
||||
}
|
||||
}
|
||||
while (1);
|
||||
}
|
||||
|
||||
bool STPathSet::isEquivalent(const SerializedType& t) const
|
||||
bool STPathSet::isEquivalent (const SerializedType& t) const
|
||||
{
|
||||
const STPathSet* v = dynamic_cast<const STPathSet*>(&t);
|
||||
return v && (value == v->value);
|
||||
const STPathSet* v = dynamic_cast<const STPathSet*> (&t);
|
||||
return v && (value == v->value);
|
||||
}
|
||||
|
||||
bool STPath::hasSeen(const uint160 &uAccountId, const uint160& uCurrencyID, const uint160& uIssuerID)
|
||||
bool STPath::hasSeen (const uint160& uAccountId, const uint160& uCurrencyID, const uint160& uIssuerID)
|
||||
{
|
||||
for (int i = 0; i < mPath.size(); ++i)
|
||||
{
|
||||
const STPathElement& ele = getElement(i);
|
||||
if (ele.getAccountID() == uAccountId
|
||||
&& ele.getCurrency() == uCurrencyID
|
||||
&& ele.getIssuerID() == uIssuerID)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
for (int i = 0; i < mPath.size (); ++i)
|
||||
{
|
||||
const STPathElement& ele = getElement (i);
|
||||
|
||||
if (ele.getAccountID () == uAccountId
|
||||
&& ele.getCurrency () == uCurrencyID
|
||||
&& ele.getIssuerID () == uIssuerID)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
Json::Value STPath::getJson(int) const
|
||||
Json::Value STPath::getJson (int) const
|
||||
{
|
||||
Json::Value ret(Json::arrayValue);
|
||||
Json::Value ret (Json::arrayValue);
|
||||
|
||||
BOOST_FOREACH(std::vector<STPathElement>::const_iterator::value_type it, mPath)
|
||||
{
|
||||
Json::Value elem(Json::objectValue);
|
||||
int iType = it.getNodeType();
|
||||
BOOST_FOREACH (std::vector<STPathElement>::const_iterator::value_type it, mPath)
|
||||
{
|
||||
Json::Value elem (Json::objectValue);
|
||||
int iType = it.getNodeType ();
|
||||
|
||||
elem["type"] = iType;
|
||||
elem["type_hex"] = strHex(iType);
|
||||
elem["type"] = iType;
|
||||
elem["type_hex"] = strHex (iType);
|
||||
|
||||
if (iType & STPathElement::typeAccount)
|
||||
elem["account"] = RippleAddress::createHumanAccountID(it.getAccountID());
|
||||
if (iType & STPathElement::typeAccount)
|
||||
elem["account"] = RippleAddress::createHumanAccountID (it.getAccountID ());
|
||||
|
||||
if (iType & STPathElement::typeCurrency)
|
||||
elem["currency"] = STAmount::createHumanCurrency(it.getCurrency());
|
||||
if (iType & STPathElement::typeCurrency)
|
||||
elem["currency"] = STAmount::createHumanCurrency (it.getCurrency ());
|
||||
|
||||
if (iType & STPathElement::typeIssuer)
|
||||
elem["issuer"] = RippleAddress::createHumanAccountID(it.getIssuerID());
|
||||
if (iType & STPathElement::typeIssuer)
|
||||
elem["issuer"] = RippleAddress::createHumanAccountID (it.getIssuerID ());
|
||||
|
||||
ret.append(elem);
|
||||
}
|
||||
ret.append (elem);
|
||||
}
|
||||
|
||||
return ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
Json::Value STPathSet::getJson(int options) const
|
||||
Json::Value STPathSet::getJson (int options) const
|
||||
{
|
||||
Json::Value ret(Json::arrayValue);
|
||||
Json::Value ret (Json::arrayValue);
|
||||
|
||||
BOOST_FOREACH(std::vector<STPath>::const_iterator::value_type it, value)
|
||||
ret.append(it.getJson(options));
|
||||
BOOST_FOREACH (std::vector<STPath>::const_iterator::value_type it, value)
|
||||
ret.append (it.getJson (options));
|
||||
|
||||
return ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
#if 0
|
||||
std::string STPath::getText() const
|
||||
std::string STPath::getText () const
|
||||
{
|
||||
std::string ret("[");
|
||||
bool first = true;
|
||||
std::string ret ("[");
|
||||
bool first = true;
|
||||
|
||||
BOOST_FOREACH(const STPathElement& it, mPath)
|
||||
{
|
||||
if (!first) ret += ", ";
|
||||
switch (it.getNodeType())
|
||||
{
|
||||
case STPathElement::typeAccount:
|
||||
{
|
||||
ret += RippleAddress::createHumanAccountID(it.getNode());
|
||||
break;
|
||||
}
|
||||
BOOST_FOREACH (const STPathElement & it, mPath)
|
||||
{
|
||||
if (!first) ret += ", ";
|
||||
|
||||
case STPathElement::typeOffer:
|
||||
{
|
||||
ret += "Offer(";
|
||||
ret += it.getNode().GetHex();
|
||||
ret += ")";
|
||||
break;
|
||||
}
|
||||
switch (it.getNodeType ())
|
||||
{
|
||||
case STPathElement::typeAccount:
|
||||
{
|
||||
ret += RippleAddress::createHumanAccountID (it.getNode ());
|
||||
break;
|
||||
}
|
||||
|
||||
default: throw std::runtime_error("Unknown path element");
|
||||
}
|
||||
first = false;
|
||||
}
|
||||
case STPathElement::typeOffer:
|
||||
{
|
||||
ret += "Offer(";
|
||||
ret += it.getNode ().GetHex ();
|
||||
ret += ")";
|
||||
break;
|
||||
}
|
||||
|
||||
return ret + "]";
|
||||
default:
|
||||
throw std::runtime_error ("Unknown path element");
|
||||
}
|
||||
|
||||
first = false;
|
||||
}
|
||||
|
||||
return ret + "]";
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
std::string STPathSet::getText() const
|
||||
std::string STPathSet::getText () const
|
||||
{
|
||||
std::string ret("{");
|
||||
bool firstPath = true;
|
||||
std::string ret ("{");
|
||||
bool firstPath = true;
|
||||
|
||||
BOOST_FOREACH(std::vector<STPath>::const_iterator::value_type it, value)
|
||||
{
|
||||
if (!firstPath)
|
||||
{
|
||||
ret += ", ";
|
||||
firstPath = false;
|
||||
}
|
||||
ret += it.getText();
|
||||
}
|
||||
return ret + "}";
|
||||
BOOST_FOREACH (std::vector<STPath>::const_iterator::value_type it, value)
|
||||
{
|
||||
if (!firstPath)
|
||||
{
|
||||
ret += ", ";
|
||||
firstPath = false;
|
||||
}
|
||||
|
||||
ret += it.getText ();
|
||||
}
|
||||
return ret + "}";
|
||||
}
|
||||
#endif
|
||||
|
||||
void STPathSet::add(Serializer& s) const
|
||||
void STPathSet::add (Serializer& s) const
|
||||
{
|
||||
bool bFirst = true;
|
||||
bool bFirst = true;
|
||||
|
||||
BOOST_FOREACH(const STPath& spPath, value)
|
||||
{
|
||||
if (!bFirst)
|
||||
{
|
||||
s.add8(STPathElement::typeBoundary);
|
||||
}
|
||||
BOOST_FOREACH (const STPath & spPath, value)
|
||||
{
|
||||
if (!bFirst)
|
||||
{
|
||||
s.add8 (STPathElement::typeBoundary);
|
||||
}
|
||||
|
||||
BOOST_FOREACH(const STPathElement& speElement, spPath)
|
||||
{
|
||||
int iType = speElement.getNodeType();
|
||||
BOOST_FOREACH (const STPathElement & speElement, spPath)
|
||||
{
|
||||
int iType = speElement.getNodeType ();
|
||||
|
||||
s.add8(iType);
|
||||
s.add8 (iType);
|
||||
|
||||
if (iType & STPathElement::typeAccount)
|
||||
s.add160(speElement.getAccountID());
|
||||
if (iType & STPathElement::typeAccount)
|
||||
s.add160 (speElement.getAccountID ());
|
||||
|
||||
if (iType & STPathElement::typeCurrency)
|
||||
s.add160(speElement.getCurrency());
|
||||
if (iType & STPathElement::typeCurrency)
|
||||
s.add160 (speElement.getCurrency ());
|
||||
|
||||
if (iType & STPathElement::typeIssuer)
|
||||
s.add160(speElement.getIssuerID());
|
||||
}
|
||||
if (iType & STPathElement::typeIssuer)
|
||||
s.add160 (speElement.getIssuerID ());
|
||||
}
|
||||
|
||||
bFirst = false;
|
||||
}
|
||||
s.add8(STPathElement::typeEnd);
|
||||
bFirst = false;
|
||||
}
|
||||
s.add8 (STPathElement::typeEnd);
|
||||
}
|
||||
// vim:ts=4
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -6,155 +6,270 @@ class CKey; // forward declaration
|
||||
class Serializer
|
||||
{
|
||||
public:
|
||||
typedef boost::shared_ptr<Serializer> pointer;
|
||||
typedef boost::shared_ptr<Serializer> pointer;
|
||||
|
||||
protected:
|
||||
Blob mData;
|
||||
Blob mData;
|
||||
|
||||
public:
|
||||
Serializer(int n = 256) { mData.reserve(n); }
|
||||
Serializer(Blob const& data) : mData(data) { ; }
|
||||
Serializer(const std::string& data) : mData(data.data(), (data.data()) + data.size()) { ; }
|
||||
Serializer(Blob ::iterator begin, Blob ::iterator end) :
|
||||
mData(begin, end) { ; }
|
||||
Serializer(Blob ::const_iterator begin, Blob ::const_iterator end) :
|
||||
mData(begin, end) { ; }
|
||||
Serializer (int n = 256)
|
||||
{
|
||||
mData.reserve (n);
|
||||
}
|
||||
Serializer (Blob const& data) : mData (data)
|
||||
{
|
||||
;
|
||||
}
|
||||
Serializer (const std::string& data) : mData (data.data (), (data.data ()) + data.size ())
|
||||
{
|
||||
;
|
||||
}
|
||||
Serializer (Blob ::iterator begin, Blob ::iterator end) :
|
||||
mData (begin, end)
|
||||
{
|
||||
;
|
||||
}
|
||||
Serializer (Blob ::const_iterator begin, Blob ::const_iterator end) :
|
||||
mData (begin, end)
|
||||
{
|
||||
;
|
||||
}
|
||||
|
||||
// assemble functions
|
||||
int add8(unsigned char byte);
|
||||
int add16(uint16);
|
||||
int add32(uint32); // ledger indexes, account sequence, timestamps
|
||||
int add64(uint64); // native currency amounts
|
||||
int add128(const uint128&); // private key generators
|
||||
int add160(const uint160&); // account names, hankos
|
||||
int add256(uint256 const& ); // transaction and ledger hashes
|
||||
int addRaw(Blob const& vector);
|
||||
int addRaw(const void *ptr, int len);
|
||||
int addRaw(const Serializer& s);
|
||||
int addZeros(size_t uBytes);
|
||||
// assemble functions
|
||||
int add8 (unsigned char byte);
|
||||
int add16 (uint16);
|
||||
int add32 (uint32); // ledger indexes, account sequence, timestamps
|
||||
int add64 (uint64); // native currency amounts
|
||||
int add128 (const uint128&); // private key generators
|
||||
int add160 (const uint160&); // account names, hankos
|
||||
int add256 (uint256 const& ); // transaction and ledger hashes
|
||||
int addRaw (Blob const& vector);
|
||||
int addRaw (const void* ptr, int len);
|
||||
int addRaw (const Serializer& s);
|
||||
int addZeros (size_t uBytes);
|
||||
|
||||
int addVL(Blob const& vector);
|
||||
int addVL(const std::string& string);
|
||||
int addVL(const void *ptr, int len);
|
||||
int addVL (Blob const& vector);
|
||||
int addVL (const std::string& string);
|
||||
int addVL (const void* ptr, int len);
|
||||
|
||||
// disassemble functions
|
||||
bool get8(int&, int offset) const;
|
||||
bool get8(unsigned char&, int offset) const;
|
||||
bool get16(uint16&, int offset) const;
|
||||
bool get32(uint32&, int offset) const;
|
||||
bool get64(uint64&, int offset) const;
|
||||
bool get128(uint128&, int offset) const;
|
||||
bool get160(uint160&, int offset) const;
|
||||
bool get256(uint256&, int offset) const;
|
||||
uint256 get256(int offset) const;
|
||||
bool getRaw(Blob&, int offset, int length) const;
|
||||
Blob getRaw(int offset, int length) const;
|
||||
// disassemble functions
|
||||
bool get8 (int&, int offset) const;
|
||||
bool get8 (unsigned char&, int offset) const;
|
||||
bool get16 (uint16&, int offset) const;
|
||||
bool get32 (uint32&, int offset) const;
|
||||
bool get64 (uint64&, int offset) const;
|
||||
bool get128 (uint128&, int offset) const;
|
||||
bool get160 (uint160&, int offset) const;
|
||||
bool get256 (uint256&, int offset) const;
|
||||
uint256 get256 (int offset) const;
|
||||
bool getRaw (Blob&, int offset, int length) const;
|
||||
Blob getRaw (int offset, int length) const;
|
||||
|
||||
bool getVL(Blob& objectVL, int offset, int& length) const;
|
||||
bool getVLLength(int& length, int offset) const;
|
||||
bool getVL (Blob& objectVL, int offset, int& length) const;
|
||||
bool getVLLength (int& length, int offset) const;
|
||||
|
||||
bool getFieldID(int& type, int& name, int offset) const;
|
||||
int addFieldID(int type, int name);
|
||||
int addFieldID(SerializedTypeID type, int name) { return addFieldID(static_cast<int>(type), name); }
|
||||
bool getFieldID (int& type, int& name, int offset) const;
|
||||
int addFieldID (int type, int name);
|
||||
int addFieldID (SerializedTypeID type, int name)
|
||||
{
|
||||
return addFieldID (static_cast<int> (type), name);
|
||||
}
|
||||
|
||||
// normal hash functions
|
||||
uint160 getRIPEMD160(int size=-1) const;
|
||||
uint256 getSHA256(int size=-1) const;
|
||||
uint256 getSHA512Half(int size=-1) const;
|
||||
static uint256 getSHA512Half(Blob const& data, int size=-1);
|
||||
static uint256 getSHA512Half(const unsigned char *data, int len);
|
||||
static uint256 getSHA512Half(const std::string& strData);
|
||||
// normal hash functions
|
||||
uint160 getRIPEMD160 (int size = -1) const;
|
||||
uint256 getSHA256 (int size = -1) const;
|
||||
uint256 getSHA512Half (int size = -1) const;
|
||||
static uint256 getSHA512Half (Blob const& data, int size = -1);
|
||||
static uint256 getSHA512Half (const unsigned char* data, int len);
|
||||
static uint256 getSHA512Half (const std::string& strData);
|
||||
|
||||
// prefix hash functions
|
||||
static uint256 getPrefixHash(uint32 prefix, const unsigned char *data, int len);
|
||||
uint256 getPrefixHash(uint32 prefix) const
|
||||
{ return getPrefixHash(prefix, &(mData.front()), mData.size()); }
|
||||
static uint256 getPrefixHash(uint32 prefix, Blob const& data)
|
||||
{ return getPrefixHash(prefix, &(data.front()), data.size()); }
|
||||
static uint256 getPrefixHash(uint32 prefix, const std::string& strData)
|
||||
{ return getPrefixHash(prefix, reinterpret_cast<const unsigned char *>(strData.data()), strData.size()); }
|
||||
// prefix hash functions
|
||||
static uint256 getPrefixHash (uint32 prefix, const unsigned char* data, int len);
|
||||
uint256 getPrefixHash (uint32 prefix) const
|
||||
{
|
||||
return getPrefixHash (prefix, & (mData.front ()), mData.size ());
|
||||
}
|
||||
static uint256 getPrefixHash (uint32 prefix, Blob const& data)
|
||||
{
|
||||
return getPrefixHash (prefix, & (data.front ()), data.size ());
|
||||
}
|
||||
static uint256 getPrefixHash (uint32 prefix, const std::string& strData)
|
||||
{
|
||||
return getPrefixHash (prefix, reinterpret_cast<const unsigned char*> (strData.data ()), strData.size ());
|
||||
}
|
||||
|
||||
// totality functions
|
||||
Blob const& peekData() const { return mData; }
|
||||
Blob getData() const { return mData; }
|
||||
Blob& modData() { return mData; }
|
||||
int getCapacity() const { return mData.capacity(); }
|
||||
int getDataLength() const { return mData.size(); }
|
||||
const void* getDataPtr() const { return &mData.front(); }
|
||||
void* getDataPtr() { return &mData.front(); }
|
||||
int getLength() const { return mData.size(); }
|
||||
std::string getString() const { return std::string(static_cast<const char *>(getDataPtr()), size()); }
|
||||
void secureErase() { memset(&(mData.front()), 0, mData.size()); erase(); }
|
||||
void erase() { mData.clear(); }
|
||||
int removeLastByte();
|
||||
bool chop(int num);
|
||||
// totality functions
|
||||
Blob const& peekData () const
|
||||
{
|
||||
return mData;
|
||||
}
|
||||
Blob getData () const
|
||||
{
|
||||
return mData;
|
||||
}
|
||||
Blob& modData ()
|
||||
{
|
||||
return mData;
|
||||
}
|
||||
int getCapacity () const
|
||||
{
|
||||
return mData.capacity ();
|
||||
}
|
||||
int getDataLength () const
|
||||
{
|
||||
return mData.size ();
|
||||
}
|
||||
const void* getDataPtr () const
|
||||
{
|
||||
return &mData.front ();
|
||||
}
|
||||
void* getDataPtr ()
|
||||
{
|
||||
return &mData.front ();
|
||||
}
|
||||
int getLength () const
|
||||
{
|
||||
return mData.size ();
|
||||
}
|
||||
std::string getString () const
|
||||
{
|
||||
return std::string (static_cast<const char*> (getDataPtr ()), size ());
|
||||
}
|
||||
void secureErase ()
|
||||
{
|
||||
memset (& (mData.front ()), 0, mData.size ());
|
||||
erase ();
|
||||
}
|
||||
void erase ()
|
||||
{
|
||||
mData.clear ();
|
||||
}
|
||||
int removeLastByte ();
|
||||
bool chop (int num);
|
||||
|
||||
// vector-like functions
|
||||
Blob ::iterator begin() { return mData.begin(); }
|
||||
Blob ::iterator end() { return mData.end(); }
|
||||
Blob ::const_iterator begin() const { return mData.begin(); }
|
||||
Blob ::const_iterator end() const { return mData.end(); }
|
||||
Blob ::size_type size() const { return mData.size(); }
|
||||
void reserve(size_t n) { mData.reserve(n); }
|
||||
void resize(size_t n) { mData.resize(n); }
|
||||
size_t capacity() const { return mData.capacity(); }
|
||||
// vector-like functions
|
||||
Blob ::iterator begin ()
|
||||
{
|
||||
return mData.begin ();
|
||||
}
|
||||
Blob ::iterator end ()
|
||||
{
|
||||
return mData.end ();
|
||||
}
|
||||
Blob ::const_iterator begin () const
|
||||
{
|
||||
return mData.begin ();
|
||||
}
|
||||
Blob ::const_iterator end () const
|
||||
{
|
||||
return mData.end ();
|
||||
}
|
||||
Blob ::size_type size () const
|
||||
{
|
||||
return mData.size ();
|
||||
}
|
||||
void reserve (size_t n)
|
||||
{
|
||||
mData.reserve (n);
|
||||
}
|
||||
void resize (size_t n)
|
||||
{
|
||||
mData.resize (n);
|
||||
}
|
||||
size_t capacity () const
|
||||
{
|
||||
return mData.capacity ();
|
||||
}
|
||||
|
||||
bool operator==(Blob const& v) { return v == mData; }
|
||||
bool operator!=(Blob const& v) { return v != mData; }
|
||||
bool operator==(const Serializer& v) { return v.mData == mData; }
|
||||
bool operator!=(const Serializer& v) { return v.mData != mData; }
|
||||
bool operator== (Blob const& v)
|
||||
{
|
||||
return v == mData;
|
||||
}
|
||||
bool operator!= (Blob const& v)
|
||||
{
|
||||
return v != mData;
|
||||
}
|
||||
bool operator== (const Serializer& v)
|
||||
{
|
||||
return v.mData == mData;
|
||||
}
|
||||
bool operator!= (const Serializer& v)
|
||||
{
|
||||
return v.mData != mData;
|
||||
}
|
||||
|
||||
// signature functions
|
||||
bool checkSignature(int pubkeyOffset, int signatureOffset) const;
|
||||
bool checkSignature(Blob const& signature, CKey& rkey) const;
|
||||
bool makeSignature(Blob& signature, CKey& rkey) const;
|
||||
bool addSignature(CKey& rkey);
|
||||
// signature functions
|
||||
bool checkSignature (int pubkeyOffset, int signatureOffset) const;
|
||||
bool checkSignature (Blob const& signature, CKey& rkey) const;
|
||||
bool makeSignature (Blob& signature, CKey& rkey) const;
|
||||
bool addSignature (CKey& rkey);
|
||||
|
||||
// low-level VL length encode/decode functions
|
||||
static Blob encodeVL(int length);
|
||||
static int lengthVL(int length) { return length + encodeLengthLength(length); }
|
||||
static int encodeLengthLength(int length); // length to encode length
|
||||
static int decodeLengthLength(int b1);
|
||||
static int decodeVLLength(int b1);
|
||||
static int decodeVLLength(int b1, int b2);
|
||||
static int decodeVLLength(int b1, int b2, int b3);
|
||||
// low-level VL length encode/decode functions
|
||||
static Blob encodeVL (int length);
|
||||
static int lengthVL (int length)
|
||||
{
|
||||
return length + encodeLengthLength (length);
|
||||
}
|
||||
static int encodeLengthLength (int length); // length to encode length
|
||||
static int decodeLengthLength (int b1);
|
||||
static int decodeVLLength (int b1);
|
||||
static int decodeVLLength (int b1, int b2);
|
||||
static int decodeVLLength (int b1, int b2, int b3);
|
||||
|
||||
static void TestSerializer();
|
||||
static void TestSerializer ();
|
||||
};
|
||||
|
||||
class SerializerIterator
|
||||
{
|
||||
protected:
|
||||
const Serializer& mSerializer;
|
||||
int mPos;
|
||||
const Serializer& mSerializer;
|
||||
int mPos;
|
||||
|
||||
public:
|
||||
|
||||
// Reference is not const because we don't want to bind to a temporary
|
||||
SerializerIterator(Serializer& s) : mSerializer(s), mPos(0) { ; }
|
||||
// Reference is not const because we don't want to bind to a temporary
|
||||
SerializerIterator (Serializer& s) : mSerializer (s), mPos (0)
|
||||
{
|
||||
;
|
||||
}
|
||||
|
||||
const Serializer& operator*(void) { return mSerializer; }
|
||||
void reset(void) { mPos = 0; }
|
||||
void setPos(int p) { mPos = p; }
|
||||
const Serializer& operator* (void)
|
||||
{
|
||||
return mSerializer;
|
||||
}
|
||||
void reset (void)
|
||||
{
|
||||
mPos = 0;
|
||||
}
|
||||
void setPos (int p)
|
||||
{
|
||||
mPos = p;
|
||||
}
|
||||
|
||||
int getPos(void) { return mPos; }
|
||||
bool empty() { return mPos == mSerializer.getLength(); }
|
||||
int getBytesLeft();
|
||||
int getPos (void)
|
||||
{
|
||||
return mPos;
|
||||
}
|
||||
bool empty ()
|
||||
{
|
||||
return mPos == mSerializer.getLength ();
|
||||
}
|
||||
int getBytesLeft ();
|
||||
|
||||
// get functions throw on error
|
||||
unsigned char get8();
|
||||
uint16 get16();
|
||||
uint32 get32();
|
||||
uint64 get64();
|
||||
uint128 get128();
|
||||
uint160 get160();
|
||||
uint256 get256();
|
||||
// get functions throw on error
|
||||
unsigned char get8 ();
|
||||
uint16 get16 ();
|
||||
uint32 get32 ();
|
||||
uint64 get64 ();
|
||||
uint128 get128 ();
|
||||
uint160 get160 ();
|
||||
uint256 get256 ();
|
||||
|
||||
void getFieldID(int& type, int& field);
|
||||
void getFieldID (int& type, int& field);
|
||||
|
||||
Blob getRaw(int iLength);
|
||||
Blob getRaw (int iLength);
|
||||
|
||||
Blob getVL();
|
||||
Blob getVL ();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,125 +1,127 @@
|
||||
|
||||
bool transResultInfo(TER terCode, std::string& strToken, std::string& strHuman)
|
||||
bool transResultInfo (TER terCode, std::string& strToken, std::string& strHuman)
|
||||
{
|
||||
static struct {
|
||||
TER terCode;
|
||||
const char* cpToken;
|
||||
const char* cpHuman;
|
||||
} transResultInfoA[] = {
|
||||
{ tecCLAIM, "tecCLAIM", "Fee claimed. Sequence used. No action." },
|
||||
{ tecDIR_FULL, "tecDIR_FULL", "Can not add entry to full directory." },
|
||||
{ tecFAILED_PROCESSING, "tecFAILED_PROCESSING", "Failed to correctly process transaction." },
|
||||
{ tecINSUF_RESERVE_LINE, "tecINSUF_RESERVE_LINE", "Insufficient reserve to add trust line." },
|
||||
{ tecINSUF_RESERVE_OFFER, "tecINSUF_RESERVE_OFFER", "Insufficient reserve to create offer." },
|
||||
{ tecNO_DST, "tecNO_DST", "Destination does not exist. Send XRP to create it." },
|
||||
{ tecNO_DST_INSUF_XRP, "tecNO_DST_INSUF_XRP", "Destination does not exist. Too little XRP sent to create it." },
|
||||
{ tecNO_LINE_INSUF_RESERVE, "tecNO_LINE_INSUF_RESERVE", "No such line. Too little reserve to create it." },
|
||||
{ tecNO_LINE_REDUNDANT, "tecNO_LINE_REDUNDANT", "Can't set non-existant line to default." },
|
||||
{ tecPATH_DRY, "tecPATH_DRY", "Path could not send partial amount." },
|
||||
{ tecPATH_PARTIAL, "tecPATH_PARTIAL", "Path could not send full amount." },
|
||||
static struct
|
||||
{
|
||||
TER terCode;
|
||||
const char* cpToken;
|
||||
const char* cpHuman;
|
||||
} transResultInfoA[] =
|
||||
{
|
||||
{ tecCLAIM, "tecCLAIM", "Fee claimed. Sequence used. No action." },
|
||||
{ tecDIR_FULL, "tecDIR_FULL", "Can not add entry to full directory." },
|
||||
{ tecFAILED_PROCESSING, "tecFAILED_PROCESSING", "Failed to correctly process transaction." },
|
||||
{ tecINSUF_RESERVE_LINE, "tecINSUF_RESERVE_LINE", "Insufficient reserve to add trust line." },
|
||||
{ tecINSUF_RESERVE_OFFER, "tecINSUF_RESERVE_OFFER", "Insufficient reserve to create offer." },
|
||||
{ tecNO_DST, "tecNO_DST", "Destination does not exist. Send XRP to create it." },
|
||||
{ tecNO_DST_INSUF_XRP, "tecNO_DST_INSUF_XRP", "Destination does not exist. Too little XRP sent to create it." },
|
||||
{ tecNO_LINE_INSUF_RESERVE, "tecNO_LINE_INSUF_RESERVE", "No such line. Too little reserve to create it." },
|
||||
{ tecNO_LINE_REDUNDANT, "tecNO_LINE_REDUNDANT", "Can't set non-existant line to default." },
|
||||
{ tecPATH_DRY, "tecPATH_DRY", "Path could not send partial amount." },
|
||||
{ tecPATH_PARTIAL, "tecPATH_PARTIAL", "Path could not send full amount." },
|
||||
|
||||
{ tecUNFUNDED, "tecUNFUNDED", "One of _ADD, _OFFER, or _SEND. Deprecated." },
|
||||
{ tecUNFUNDED_ADD, "tecUNFUNDED_ADD", "Insufficient XRP balance for WalletAdd." },
|
||||
{ tecUNFUNDED_OFFER, "tecUNFUNDED_OFFER", "Insufficient balance to fund created offer." },
|
||||
{ tecUNFUNDED_PAYMENT, "tecUNFUNDED_PAYMENT", "Insufficient XRP balance to send." },
|
||||
{ tecUNFUNDED, "tecUNFUNDED", "One of _ADD, _OFFER, or _SEND. Deprecated." },
|
||||
{ tecUNFUNDED_ADD, "tecUNFUNDED_ADD", "Insufficient XRP balance for WalletAdd." },
|
||||
{ tecUNFUNDED_OFFER, "tecUNFUNDED_OFFER", "Insufficient balance to fund created offer." },
|
||||
{ tecUNFUNDED_PAYMENT, "tecUNFUNDED_PAYMENT", "Insufficient XRP balance to send." },
|
||||
|
||||
{ tefFAILURE, "tefFAILURE", "Failed to apply." },
|
||||
{ tefALREADY, "tefALREADY", "The exact transaction was already in this ledger." },
|
||||
{ tefBAD_ADD_AUTH, "tefBAD_ADD_AUTH", "Not authorized to add account." },
|
||||
{ tefBAD_AUTH, "tefBAD_AUTH", "Transaction's public key is not authorized." },
|
||||
{ tefBAD_CLAIM_ID, "tefBAD_CLAIM_ID", "Malformed: Bad claim id." },
|
||||
{ tefBAD_GEN_AUTH, "tefBAD_GEN_AUTH", "Not authorized to claim generator." },
|
||||
{ tefBAD_LEDGER, "tefBAD_LEDGER", "Ledger in unexpected state." },
|
||||
{ tefCLAIMED, "tefCLAIMED", "Can not claim a previously claimed account." },
|
||||
{ tefCREATED, "tefCREATED", "Can't add an already created account." },
|
||||
{ tefDST_TAG_NEEDED, "tefDST_TAG_NEEDED", "Destination tag required." },
|
||||
{ tefEXCEPTION, "tefEXCEPTION", "Unexpected program state." },
|
||||
{ tefGEN_IN_USE, "tefGEN_IN_USE", "Generator already in use." },
|
||||
{ tefINTERNAL, "tefINTERNAL", "Internal error." },
|
||||
{ tefNO_AUTH_REQUIRED, "tefNO_AUTH_REQUIRED", "Auth is not required." },
|
||||
{ tefPAST_SEQ, "tefPAST_SEQ", "This sequence number has already past." },
|
||||
{ tefWRONG_PRIOR, "tefWRONG_PRIOR", "This previous transaction does not match." },
|
||||
{ tefFAILURE, "tefFAILURE", "Failed to apply." },
|
||||
{ tefALREADY, "tefALREADY", "The exact transaction was already in this ledger." },
|
||||
{ tefBAD_ADD_AUTH, "tefBAD_ADD_AUTH", "Not authorized to add account." },
|
||||
{ tefBAD_AUTH, "tefBAD_AUTH", "Transaction's public key is not authorized." },
|
||||
{ tefBAD_CLAIM_ID, "tefBAD_CLAIM_ID", "Malformed: Bad claim id." },
|
||||
{ tefBAD_GEN_AUTH, "tefBAD_GEN_AUTH", "Not authorized to claim generator." },
|
||||
{ tefBAD_LEDGER, "tefBAD_LEDGER", "Ledger in unexpected state." },
|
||||
{ tefCLAIMED, "tefCLAIMED", "Can not claim a previously claimed account." },
|
||||
{ tefCREATED, "tefCREATED", "Can't add an already created account." },
|
||||
{ tefDST_TAG_NEEDED, "tefDST_TAG_NEEDED", "Destination tag required." },
|
||||
{ tefEXCEPTION, "tefEXCEPTION", "Unexpected program state." },
|
||||
{ tefGEN_IN_USE, "tefGEN_IN_USE", "Generator already in use." },
|
||||
{ tefINTERNAL, "tefINTERNAL", "Internal error." },
|
||||
{ tefNO_AUTH_REQUIRED, "tefNO_AUTH_REQUIRED", "Auth is not required." },
|
||||
{ tefPAST_SEQ, "tefPAST_SEQ", "This sequence number has already past." },
|
||||
{ tefWRONG_PRIOR, "tefWRONG_PRIOR", "This previous transaction does not match." },
|
||||
|
||||
{ telLOCAL_ERROR, "telLOCAL_ERROR", "Local failure." },
|
||||
{ telBAD_DOMAIN, "telBAD_DOMAIN", "Domain too long." },
|
||||
{ telBAD_PATH_COUNT, "telBAD_PATH_COUNT", "Malformed: Too many paths." },
|
||||
{ telBAD_PUBLIC_KEY, "telBAD_PUBLIC_KEY", "Public key too long." },
|
||||
{ telFAILED_PROCESSING, "telFAILED_PROCESSING", "Failed to correctly process transaction." },
|
||||
{ telINSUF_FEE_P, "telINSUF_FEE_P", "Fee insufficient." },
|
||||
{ telNO_DST_PARTIAL, "telNO_DST_PARTIAL", "Partial payment to create account not allowed." },
|
||||
{ telLOCAL_ERROR, "telLOCAL_ERROR", "Local failure." },
|
||||
{ telBAD_DOMAIN, "telBAD_DOMAIN", "Domain too long." },
|
||||
{ telBAD_PATH_COUNT, "telBAD_PATH_COUNT", "Malformed: Too many paths." },
|
||||
{ telBAD_PUBLIC_KEY, "telBAD_PUBLIC_KEY", "Public key too long." },
|
||||
{ telFAILED_PROCESSING, "telFAILED_PROCESSING", "Failed to correctly process transaction." },
|
||||
{ telINSUF_FEE_P, "telINSUF_FEE_P", "Fee insufficient." },
|
||||
{ telNO_DST_PARTIAL, "telNO_DST_PARTIAL", "Partial payment to create account not allowed." },
|
||||
|
||||
{ temMALFORMED, "temMALFORMED", "Malformed transaction." },
|
||||
{ temBAD_AMOUNT, "temBAD_AMOUNT", "Can only send positive amounts." },
|
||||
{ temBAD_AUTH_MASTER, "temBAD_AUTH_MASTER", "Auth for unclaimed account needs correct master key." },
|
||||
{ temBAD_CURRENCY, "temBAD_CURRENCY", "Malformed: Bad currency." },
|
||||
{ temBAD_FEE, "temBAD_FEE", "Invalid fee, negative or not XRP." },
|
||||
{ temBAD_EXPIRATION, "temBAD_EXPIRATION", "Malformed: Bad expiration." },
|
||||
{ temBAD_ISSUER, "temBAD_ISSUER", "Malformed: Bad issuer." },
|
||||
{ temBAD_LIMIT, "temBAD_LIMIT", "Limits must be non-negative." },
|
||||
{ temBAD_OFFER, "temBAD_OFFER", "Malformed: Bad offer." },
|
||||
{ temBAD_PATH, "temBAD_PATH", "Malformed: Bad path." },
|
||||
{ temBAD_PATH_LOOP, "temBAD_PATH_LOOP", "Malformed: Loop in path." },
|
||||
{ temBAD_PUBLISH, "temBAD_PUBLISH", "Malformed: Bad publish." },
|
||||
{ temBAD_SIGNATURE, "temBAD_SIGNATURE", "Malformed: Bad signature." },
|
||||
{ temBAD_SRC_ACCOUNT, "temBAD_SRC_ACCOUNT", "Malformed: Bad source account." },
|
||||
{ temBAD_TRANSFER_RATE, "temBAD_TRANSFER_RATE", "Malformed: Transfer rate must be >= 1.0" },
|
||||
{ temBAD_SEQUENCE, "temBAD_SEQUENCE", "Malformed: Sequence is not in the past." },
|
||||
{ temBAD_SEND_XRP_LIMIT, "temBAD_SEND_XRP_LIMIT", "Malformed: Limit quality is not allowed for XRP to XRP." },
|
||||
{ temBAD_SEND_XRP_MAX, "temBAD_SEND_XRP_MAX", "Malformed: Send max is not allowed for XRP to XRP." },
|
||||
{ temBAD_SEND_XRP_NO_DIRECT, "temBAD_SEND_XRP_NO_DIRECT", "Malformed: No Ripple direct is not allowed for XRP to XRP." },
|
||||
{ temBAD_SEND_XRP_PARTIAL, "temBAD_SEND_XRP_PARTIAL", "Malformed: Partial payment is not allowed for XRP to XRP." },
|
||||
{ temBAD_SEND_XRP_PATHS, "temBAD_SEND_XRP_PATHS", "Malformed: Paths are not allowed for XRP to XRP." },
|
||||
{ temDST_IS_SRC, "temDST_IS_SRC", "Destination may not be source." },
|
||||
{ temDST_NEEDED, "temDST_NEEDED", "Destination not specified." },
|
||||
{ temINVALID, "temINVALID", "The transaction is ill-formed." },
|
||||
{ temINVALID_FLAG, "temINVALID_FLAG", "The transaction has an invalid flag." },
|
||||
{ temREDUNDANT, "temREDUNDANT", "Sends same currency to self." },
|
||||
{ temREDUNDANT_SEND_MAX, "temREDUNDANT_SEND_MAX", "Send max is redundant." },
|
||||
{ temRIPPLE_EMPTY, "temRIPPLE_EMPTY", "PathSet with no paths." },
|
||||
{ temUNCERTAIN, "temUNCERTAIN", "In process of determining result. Never returned." },
|
||||
{ temUNKNOWN, "temUNKNOWN", "The transactions requires logic not implemented yet." },
|
||||
{ temMALFORMED, "temMALFORMED", "Malformed transaction." },
|
||||
{ temBAD_AMOUNT, "temBAD_AMOUNT", "Can only send positive amounts." },
|
||||
{ temBAD_AUTH_MASTER, "temBAD_AUTH_MASTER", "Auth for unclaimed account needs correct master key." },
|
||||
{ temBAD_CURRENCY, "temBAD_CURRENCY", "Malformed: Bad currency." },
|
||||
{ temBAD_FEE, "temBAD_FEE", "Invalid fee, negative or not XRP." },
|
||||
{ temBAD_EXPIRATION, "temBAD_EXPIRATION", "Malformed: Bad expiration." },
|
||||
{ temBAD_ISSUER, "temBAD_ISSUER", "Malformed: Bad issuer." },
|
||||
{ temBAD_LIMIT, "temBAD_LIMIT", "Limits must be non-negative." },
|
||||
{ temBAD_OFFER, "temBAD_OFFER", "Malformed: Bad offer." },
|
||||
{ temBAD_PATH, "temBAD_PATH", "Malformed: Bad path." },
|
||||
{ temBAD_PATH_LOOP, "temBAD_PATH_LOOP", "Malformed: Loop in path." },
|
||||
{ temBAD_PUBLISH, "temBAD_PUBLISH", "Malformed: Bad publish." },
|
||||
{ temBAD_SIGNATURE, "temBAD_SIGNATURE", "Malformed: Bad signature." },
|
||||
{ temBAD_SRC_ACCOUNT, "temBAD_SRC_ACCOUNT", "Malformed: Bad source account." },
|
||||
{ temBAD_TRANSFER_RATE, "temBAD_TRANSFER_RATE", "Malformed: Transfer rate must be >= 1.0" },
|
||||
{ temBAD_SEQUENCE, "temBAD_SEQUENCE", "Malformed: Sequence is not in the past." },
|
||||
{ temBAD_SEND_XRP_LIMIT, "temBAD_SEND_XRP_LIMIT", "Malformed: Limit quality is not allowed for XRP to XRP." },
|
||||
{ temBAD_SEND_XRP_MAX, "temBAD_SEND_XRP_MAX", "Malformed: Send max is not allowed for XRP to XRP." },
|
||||
{ temBAD_SEND_XRP_NO_DIRECT, "temBAD_SEND_XRP_NO_DIRECT", "Malformed: No Ripple direct is not allowed for XRP to XRP." },
|
||||
{ temBAD_SEND_XRP_PARTIAL, "temBAD_SEND_XRP_PARTIAL", "Malformed: Partial payment is not allowed for XRP to XRP." },
|
||||
{ temBAD_SEND_XRP_PATHS, "temBAD_SEND_XRP_PATHS", "Malformed: Paths are not allowed for XRP to XRP." },
|
||||
{ temDST_IS_SRC, "temDST_IS_SRC", "Destination may not be source." },
|
||||
{ temDST_NEEDED, "temDST_NEEDED", "Destination not specified." },
|
||||
{ temINVALID, "temINVALID", "The transaction is ill-formed." },
|
||||
{ temINVALID_FLAG, "temINVALID_FLAG", "The transaction has an invalid flag." },
|
||||
{ temREDUNDANT, "temREDUNDANT", "Sends same currency to self." },
|
||||
{ temREDUNDANT_SEND_MAX, "temREDUNDANT_SEND_MAX", "Send max is redundant." },
|
||||
{ temRIPPLE_EMPTY, "temRIPPLE_EMPTY", "PathSet with no paths." },
|
||||
{ temUNCERTAIN, "temUNCERTAIN", "In process of determining result. Never returned." },
|
||||
{ temUNKNOWN, "temUNKNOWN", "The transactions requires logic not implemented yet." },
|
||||
|
||||
{ terRETRY, "terRETRY", "Retry transaction." },
|
||||
{ terFUNDS_SPENT, "terFUNDS_SPENT", "Can't set password, password set funds already spent." },
|
||||
{ terINSUF_FEE_B, "terINSUF_FEE_B", "Account balance can't pay fee." },
|
||||
{ terLAST, "terLAST", "Process last." },
|
||||
{ terNO_ACCOUNT, "terNO_ACCOUNT", "The source account does not exist." },
|
||||
{ terNO_AUTH, "terNO_AUTH", "Not authorized to hold IOUs." },
|
||||
{ terNO_LINE, "terNO_LINE", "No such line." },
|
||||
{ terPRE_SEQ, "terPRE_SEQ", "Missing/inapplicable prior transaction." },
|
||||
{ terOWNERS, "terOWNERS", "Non-zero owner count." },
|
||||
{ terRETRY, "terRETRY", "Retry transaction." },
|
||||
{ terFUNDS_SPENT, "terFUNDS_SPENT", "Can't set password, password set funds already spent." },
|
||||
{ terINSUF_FEE_B, "terINSUF_FEE_B", "Account balance can't pay fee." },
|
||||
{ terLAST, "terLAST", "Process last." },
|
||||
{ terNO_ACCOUNT, "terNO_ACCOUNT", "The source account does not exist." },
|
||||
{ terNO_AUTH, "terNO_AUTH", "Not authorized to hold IOUs." },
|
||||
{ terNO_LINE, "terNO_LINE", "No such line." },
|
||||
{ terPRE_SEQ, "terPRE_SEQ", "Missing/inapplicable prior transaction." },
|
||||
{ terOWNERS, "terOWNERS", "Non-zero owner count." },
|
||||
|
||||
{ tesSUCCESS, "tesSUCCESS", "The transaction was applied." },
|
||||
};
|
||||
{ tesSUCCESS, "tesSUCCESS", "The transaction was applied." },
|
||||
};
|
||||
|
||||
int iIndex = NUMBER(transResultInfoA);
|
||||
int iIndex = NUMBER (transResultInfoA);
|
||||
|
||||
while (iIndex-- && transResultInfoA[iIndex].terCode != terCode)
|
||||
;
|
||||
while (iIndex-- && transResultInfoA[iIndex].terCode != terCode)
|
||||
;
|
||||
|
||||
if (iIndex >= 0)
|
||||
{
|
||||
strToken = transResultInfoA[iIndex].cpToken;
|
||||
strHuman = transResultInfoA[iIndex].cpHuman;
|
||||
}
|
||||
if (iIndex >= 0)
|
||||
{
|
||||
strToken = transResultInfoA[iIndex].cpToken;
|
||||
strHuman = transResultInfoA[iIndex].cpHuman;
|
||||
}
|
||||
|
||||
return iIndex >= 0;
|
||||
return iIndex >= 0;
|
||||
}
|
||||
|
||||
std::string transToken(TER terCode)
|
||||
std::string transToken (TER terCode)
|
||||
{
|
||||
std::string strToken;
|
||||
std::string strHuman;
|
||||
std::string strToken;
|
||||
std::string strHuman;
|
||||
|
||||
return transResultInfo(terCode, strToken, strHuman) ? strToken : "-";
|
||||
return transResultInfo (terCode, strToken, strHuman) ? strToken : "-";
|
||||
}
|
||||
|
||||
std::string transHuman(TER terCode)
|
||||
std::string transHuman (TER terCode)
|
||||
{
|
||||
std::string strToken;
|
||||
std::string strHuman;
|
||||
std::string strToken;
|
||||
std::string strHuman;
|
||||
|
||||
return transResultInfo(terCode, strToken, strHuman) ? strHuman : "-";
|
||||
return transResultInfo (terCode, strToken, strHuman) ? strHuman : "-";
|
||||
}
|
||||
|
||||
// vim:ts=4
|
||||
|
||||
@@ -7,149 +7,149 @@
|
||||
//
|
||||
// VFALCO TODO consider renaming TER to TxErr or TxResult for clarity.
|
||||
//
|
||||
enum TER // aka TransactionEngineResult
|
||||
enum TER // aka TransactionEngineResult
|
||||
{
|
||||
// Note: Range is stable. Exact numbers are currently unstable. Use tokens.
|
||||
// Note: Range is stable. Exact numbers are currently unstable. Use tokens.
|
||||
|
||||
// -399 .. -300: L Local error (transaction fee inadequate, exceeds local limit)
|
||||
// Only valid during non-consensus processing.
|
||||
// Implications:
|
||||
// - Not forwarded
|
||||
// - No fee check
|
||||
telLOCAL_ERROR = -399,
|
||||
telBAD_DOMAIN, // VFALCO TODO should read "telBAD_DOMAIN = -398," etc...
|
||||
telBAD_PATH_COUNT,
|
||||
telBAD_PUBLIC_KEY,
|
||||
telFAILED_PROCESSING,
|
||||
telINSUF_FEE_P,
|
||||
telNO_DST_PARTIAL,
|
||||
// -399 .. -300: L Local error (transaction fee inadequate, exceeds local limit)
|
||||
// Only valid during non-consensus processing.
|
||||
// Implications:
|
||||
// - Not forwarded
|
||||
// - No fee check
|
||||
telLOCAL_ERROR = -399,
|
||||
telBAD_DOMAIN, // VFALCO TODO should read "telBAD_DOMAIN = -398," etc...
|
||||
telBAD_PATH_COUNT,
|
||||
telBAD_PUBLIC_KEY,
|
||||
telFAILED_PROCESSING,
|
||||
telINSUF_FEE_P,
|
||||
telNO_DST_PARTIAL,
|
||||
|
||||
// -299 .. -200: M Malformed (bad signature)
|
||||
// Causes:
|
||||
// - Transaction corrupt.
|
||||
// Implications:
|
||||
// - Not applied
|
||||
// - Not forwarded
|
||||
// - Reject
|
||||
// - Can not succeed in any imagined ledger.
|
||||
temMALFORMED = -299,
|
||||
temBAD_AMOUNT,
|
||||
temBAD_AUTH_MASTER,
|
||||
temBAD_CURRENCY,
|
||||
temBAD_FEE,
|
||||
temBAD_EXPIRATION,
|
||||
temBAD_ISSUER,
|
||||
temBAD_LIMIT,
|
||||
temBAD_OFFER,
|
||||
temBAD_PATH,
|
||||
temBAD_PATH_LOOP,
|
||||
temBAD_PUBLISH,
|
||||
temBAD_TRANSFER_RATE,
|
||||
temBAD_SEND_XRP_LIMIT,
|
||||
temBAD_SEND_XRP_MAX,
|
||||
temBAD_SEND_XRP_NO_DIRECT,
|
||||
temBAD_SEND_XRP_PARTIAL,
|
||||
temBAD_SEND_XRP_PATHS,
|
||||
temBAD_SIGNATURE,
|
||||
temBAD_SRC_ACCOUNT,
|
||||
temBAD_SEQUENCE,
|
||||
temDST_IS_SRC,
|
||||
temDST_NEEDED,
|
||||
temINVALID,
|
||||
temINVALID_FLAG,
|
||||
temREDUNDANT,
|
||||
temREDUNDANT_SEND_MAX,
|
||||
temRIPPLE_EMPTY,
|
||||
temUNCERTAIN, // An intermediate result used internally, should never be returned.
|
||||
temUNKNOWN,
|
||||
// -299 .. -200: M Malformed (bad signature)
|
||||
// Causes:
|
||||
// - Transaction corrupt.
|
||||
// Implications:
|
||||
// - Not applied
|
||||
// - Not forwarded
|
||||
// - Reject
|
||||
// - Can not succeed in any imagined ledger.
|
||||
temMALFORMED = -299,
|
||||
temBAD_AMOUNT,
|
||||
temBAD_AUTH_MASTER,
|
||||
temBAD_CURRENCY,
|
||||
temBAD_FEE,
|
||||
temBAD_EXPIRATION,
|
||||
temBAD_ISSUER,
|
||||
temBAD_LIMIT,
|
||||
temBAD_OFFER,
|
||||
temBAD_PATH,
|
||||
temBAD_PATH_LOOP,
|
||||
temBAD_PUBLISH,
|
||||
temBAD_TRANSFER_RATE,
|
||||
temBAD_SEND_XRP_LIMIT,
|
||||
temBAD_SEND_XRP_MAX,
|
||||
temBAD_SEND_XRP_NO_DIRECT,
|
||||
temBAD_SEND_XRP_PARTIAL,
|
||||
temBAD_SEND_XRP_PATHS,
|
||||
temBAD_SIGNATURE,
|
||||
temBAD_SRC_ACCOUNT,
|
||||
temBAD_SEQUENCE,
|
||||
temDST_IS_SRC,
|
||||
temDST_NEEDED,
|
||||
temINVALID,
|
||||
temINVALID_FLAG,
|
||||
temREDUNDANT,
|
||||
temREDUNDANT_SEND_MAX,
|
||||
temRIPPLE_EMPTY,
|
||||
temUNCERTAIN, // An intermediate result used internally, should never be returned.
|
||||
temUNKNOWN,
|
||||
|
||||
// -199 .. -100: F Failure (sequence number previously used)
|
||||
// Causes:
|
||||
// - Transaction cannot succeed because of ledger state.
|
||||
// - Unexpected ledger state.
|
||||
// - C++ exception.
|
||||
// Implications:
|
||||
// - Not applied
|
||||
// - Not forwarded
|
||||
// - Could succeed in an imagined ledger.
|
||||
tefFAILURE = -199,
|
||||
tefALREADY,
|
||||
tefBAD_ADD_AUTH,
|
||||
tefBAD_AUTH,
|
||||
tefBAD_CLAIM_ID,
|
||||
tefBAD_GEN_AUTH,
|
||||
tefBAD_LEDGER,
|
||||
tefCLAIMED,
|
||||
tefCREATED,
|
||||
tefDST_TAG_NEEDED,
|
||||
tefEXCEPTION,
|
||||
tefGEN_IN_USE,
|
||||
tefINTERNAL,
|
||||
tefNO_AUTH_REQUIRED, // Can't set auth if auth is not required.
|
||||
tefPAST_SEQ,
|
||||
tefWRONG_PRIOR,
|
||||
// -199 .. -100: F Failure (sequence number previously used)
|
||||
// Causes:
|
||||
// - Transaction cannot succeed because of ledger state.
|
||||
// - Unexpected ledger state.
|
||||
// - C++ exception.
|
||||
// Implications:
|
||||
// - Not applied
|
||||
// - Not forwarded
|
||||
// - Could succeed in an imagined ledger.
|
||||
tefFAILURE = -199,
|
||||
tefALREADY,
|
||||
tefBAD_ADD_AUTH,
|
||||
tefBAD_AUTH,
|
||||
tefBAD_CLAIM_ID,
|
||||
tefBAD_GEN_AUTH,
|
||||
tefBAD_LEDGER,
|
||||
tefCLAIMED,
|
||||
tefCREATED,
|
||||
tefDST_TAG_NEEDED,
|
||||
tefEXCEPTION,
|
||||
tefGEN_IN_USE,
|
||||
tefINTERNAL,
|
||||
tefNO_AUTH_REQUIRED, // Can't set auth if auth is not required.
|
||||
tefPAST_SEQ,
|
||||
tefWRONG_PRIOR,
|
||||
|
||||
// -99 .. -1: R Retry (sequence too high, no funds for txn fee, originating account non-existent)
|
||||
// Causes:
|
||||
// - Prior application of another, possibly non-existant, another transaction could allow this transaction to succeed.
|
||||
// Implications:
|
||||
// - Not applied
|
||||
// - Not forwarded
|
||||
// - Might succeed later
|
||||
// - Hold
|
||||
// - Makes hole in sequence which jams transactions.
|
||||
terRETRY = -99,
|
||||
terFUNDS_SPENT, // This is a free transaction, therefore don't burden network.
|
||||
terINSUF_FEE_B, // Can't pay fee, therefore don't burden network.
|
||||
terNO_ACCOUNT, // Can't pay fee, therefore don't burden network.
|
||||
terNO_AUTH, // Not authorized to hold IOUs.
|
||||
terNO_LINE, // Internal flag.
|
||||
terOWNERS, // Can't succeed with non-zero owner count.
|
||||
terPRE_SEQ, // Can't pay fee, no point in forwarding, therefore don't burden network.
|
||||
terLAST, // Process after all other transactions
|
||||
// -99 .. -1: R Retry (sequence too high, no funds for txn fee, originating account non-existent)
|
||||
// Causes:
|
||||
// - Prior application of another, possibly non-existant, another transaction could allow this transaction to succeed.
|
||||
// Implications:
|
||||
// - Not applied
|
||||
// - Not forwarded
|
||||
// - Might succeed later
|
||||
// - Hold
|
||||
// - Makes hole in sequence which jams transactions.
|
||||
terRETRY = -99,
|
||||
terFUNDS_SPENT, // This is a free transaction, therefore don't burden network.
|
||||
terINSUF_FEE_B, // Can't pay fee, therefore don't burden network.
|
||||
terNO_ACCOUNT, // Can't pay fee, therefore don't burden network.
|
||||
terNO_AUTH, // Not authorized to hold IOUs.
|
||||
terNO_LINE, // Internal flag.
|
||||
terOWNERS, // Can't succeed with non-zero owner count.
|
||||
terPRE_SEQ, // Can't pay fee, no point in forwarding, therefore don't burden network.
|
||||
terLAST, // Process after all other transactions
|
||||
|
||||
// 0: S Success (success)
|
||||
// Causes:
|
||||
// - Success.
|
||||
// Implications:
|
||||
// - Applied
|
||||
// - Forwarded
|
||||
tesSUCCESS = 0,
|
||||
// 0: S Success (success)
|
||||
// Causes:
|
||||
// - Success.
|
||||
// Implications:
|
||||
// - Applied
|
||||
// - Forwarded
|
||||
tesSUCCESS = 0,
|
||||
|
||||
// 100 .. 129 C Claim fee only (ripple transaction with no good paths, pay to non-existent account, no path)
|
||||
// Causes:
|
||||
// - Success, but does not achieve optimal result.
|
||||
// - Invalid transaction or no effect, but claim fee to use the sequence number.
|
||||
// Implications:
|
||||
// - Applied
|
||||
// - Forwarded
|
||||
// Only allowed as a return code of appliedTransaction when !tapRetry. Otherwise, treated as terRETRY.
|
||||
//
|
||||
// DO NOT CHANGE THESE NUMBERS: They appear in ledger meta data.
|
||||
tecCLAIM = 100,
|
||||
tecPATH_PARTIAL = 101,
|
||||
tecUNFUNDED_ADD = 102,
|
||||
tecUNFUNDED_OFFER = 103,
|
||||
tecUNFUNDED_PAYMENT = 104,
|
||||
tecFAILED_PROCESSING = 105,
|
||||
tecDIR_FULL = 121,
|
||||
tecINSUF_RESERVE_LINE = 122,
|
||||
tecINSUF_RESERVE_OFFER = 123,
|
||||
tecNO_DST = 124,
|
||||
tecNO_DST_INSUF_XRP = 125,
|
||||
tecNO_LINE_INSUF_RESERVE = 126,
|
||||
tecNO_LINE_REDUNDANT = 127,
|
||||
tecPATH_DRY = 128,
|
||||
tecUNFUNDED = 129, // Deprecated, old ambiguous unfunded.
|
||||
// 100 .. 129 C Claim fee only (ripple transaction with no good paths, pay to non-existent account, no path)
|
||||
// Causes:
|
||||
// - Success, but does not achieve optimal result.
|
||||
// - Invalid transaction or no effect, but claim fee to use the sequence number.
|
||||
// Implications:
|
||||
// - Applied
|
||||
// - Forwarded
|
||||
// Only allowed as a return code of appliedTransaction when !tapRetry. Otherwise, treated as terRETRY.
|
||||
//
|
||||
// DO NOT CHANGE THESE NUMBERS: They appear in ledger meta data.
|
||||
tecCLAIM = 100,
|
||||
tecPATH_PARTIAL = 101,
|
||||
tecUNFUNDED_ADD = 102,
|
||||
tecUNFUNDED_OFFER = 103,
|
||||
tecUNFUNDED_PAYMENT = 104,
|
||||
tecFAILED_PROCESSING = 105,
|
||||
tecDIR_FULL = 121,
|
||||
tecINSUF_RESERVE_LINE = 122,
|
||||
tecINSUF_RESERVE_OFFER = 123,
|
||||
tecNO_DST = 124,
|
||||
tecNO_DST_INSUF_XRP = 125,
|
||||
tecNO_LINE_INSUF_RESERVE = 126,
|
||||
tecNO_LINE_REDUNDANT = 127,
|
||||
tecPATH_DRY = 128,
|
||||
tecUNFUNDED = 129, // Deprecated, old ambiguous unfunded.
|
||||
};
|
||||
|
||||
// VFALCO TODO change these to normal functions.
|
||||
#define isTelLocal(x) ((x) >= telLOCAL_ERROR && (x) < temMALFORMED)
|
||||
#define isTemMalformed(x) ((x) >= temMALFORMED && (x) < tefFAILURE)
|
||||
#define isTefFailure(x) ((x) >= tefFAILURE && (x) < terRETRY)
|
||||
#define isTerRetry(x) ((x) >= terRETRY && (x) < tesSUCCESS)
|
||||
#define isTesSuccess(x) ((x) == tesSUCCESS)
|
||||
#define isTecClaim(x) ((x) >= tecCLAIM)
|
||||
#define isTelLocal(x) ((x) >= telLOCAL_ERROR && (x) < temMALFORMED)
|
||||
#define isTemMalformed(x) ((x) >= temMALFORMED && (x) < tefFAILURE)
|
||||
#define isTefFailure(x) ((x) >= tefFAILURE && (x) < terRETRY)
|
||||
#define isTerRetry(x) ((x) >= terRETRY && (x) < tesSUCCESS)
|
||||
#define isTesSuccess(x) ((x) == tesSUCCESS)
|
||||
#define isTecClaim(x) ((x) >= tecCLAIM)
|
||||
|
||||
// VFALCO TODO group these into a shell class along with the defines above.
|
||||
extern bool transResultInfo (TER terCode, std::string& strToken, std::string& strHuman);
|
||||
|
||||
@@ -4,111 +4,117 @@ std::map<int, TransactionFormat*> TransactionFormat::byType;
|
||||
std::map<std::string, TransactionFormat*> TransactionFormat::byName;
|
||||
|
||||
// VFALCO TODO surely we can think of a better way than to use macros??
|
||||
#define TF_BASE \
|
||||
<< SOElement(sfTransactionType, SOE_REQUIRED) \
|
||||
<< SOElement(sfFlags, SOE_OPTIONAL) \
|
||||
<< SOElement(sfSourceTag, SOE_OPTIONAL) \
|
||||
<< SOElement(sfAccount, SOE_REQUIRED) \
|
||||
<< SOElement(sfSequence, SOE_REQUIRED) \
|
||||
<< SOElement(sfPreviousTxnID, SOE_OPTIONAL) \
|
||||
<< SOElement(sfFee, SOE_REQUIRED) \
|
||||
<< SOElement(sfOperationLimit, SOE_OPTIONAL) \
|
||||
<< SOElement(sfSigningPubKey, SOE_REQUIRED) \
|
||||
<< SOElement(sfTxnSignature, SOE_OPTIONAL)
|
||||
#define TF_BASE \
|
||||
<< SOElement(sfTransactionType, SOE_REQUIRED) \
|
||||
<< SOElement(sfFlags, SOE_OPTIONAL) \
|
||||
<< SOElement(sfSourceTag, SOE_OPTIONAL) \
|
||||
<< SOElement(sfAccount, SOE_REQUIRED) \
|
||||
<< SOElement(sfSequence, SOE_REQUIRED) \
|
||||
<< SOElement(sfPreviousTxnID, SOE_OPTIONAL) \
|
||||
<< SOElement(sfFee, SOE_REQUIRED) \
|
||||
<< SOElement(sfOperationLimit, SOE_OPTIONAL) \
|
||||
<< SOElement(sfSigningPubKey, SOE_REQUIRED) \
|
||||
<< SOElement(sfTxnSignature, SOE_OPTIONAL)
|
||||
|
||||
#define DECLARE_TF(name, type) tf = new TransactionFormat(#name, type); (*tf) TF_BASE
|
||||
|
||||
void TFInit()
|
||||
void TFInit ()
|
||||
{
|
||||
TransactionFormat* tf;
|
||||
TransactionFormat* tf;
|
||||
|
||||
DECLARE_TF(AccountSet, ttACCOUNT_SET)
|
||||
<< SOElement(sfEmailHash, SOE_OPTIONAL)
|
||||
<< SOElement(sfWalletLocator, SOE_OPTIONAL)
|
||||
<< SOElement(sfWalletSize, SOE_OPTIONAL)
|
||||
<< SOElement(sfMessageKey, SOE_OPTIONAL)
|
||||
<< SOElement(sfDomain, SOE_OPTIONAL)
|
||||
<< SOElement(sfTransferRate, SOE_OPTIONAL)
|
||||
;
|
||||
DECLARE_TF (AccountSet, ttACCOUNT_SET)
|
||||
<< SOElement (sfEmailHash, SOE_OPTIONAL)
|
||||
<< SOElement (sfWalletLocator, SOE_OPTIONAL)
|
||||
<< SOElement (sfWalletSize, SOE_OPTIONAL)
|
||||
<< SOElement (sfMessageKey, SOE_OPTIONAL)
|
||||
<< SOElement (sfDomain, SOE_OPTIONAL)
|
||||
<< SOElement (sfTransferRate, SOE_OPTIONAL)
|
||||
;
|
||||
|
||||
DECLARE_TF(TrustSet, ttTRUST_SET)
|
||||
<< SOElement(sfLimitAmount, SOE_OPTIONAL)
|
||||
<< SOElement(sfQualityIn, SOE_OPTIONAL)
|
||||
<< SOElement(sfQualityOut, SOE_OPTIONAL)
|
||||
;
|
||||
DECLARE_TF (TrustSet, ttTRUST_SET)
|
||||
<< SOElement (sfLimitAmount, SOE_OPTIONAL)
|
||||
<< SOElement (sfQualityIn, SOE_OPTIONAL)
|
||||
<< SOElement (sfQualityOut, SOE_OPTIONAL)
|
||||
;
|
||||
|
||||
DECLARE_TF(OfferCreate, ttOFFER_CREATE)
|
||||
<< SOElement(sfTakerPays, SOE_REQUIRED)
|
||||
<< SOElement(sfTakerGets, SOE_REQUIRED)
|
||||
<< SOElement(sfExpiration, SOE_OPTIONAL)
|
||||
;
|
||||
DECLARE_TF (OfferCreate, ttOFFER_CREATE)
|
||||
<< SOElement (sfTakerPays, SOE_REQUIRED)
|
||||
<< SOElement (sfTakerGets, SOE_REQUIRED)
|
||||
<< SOElement (sfExpiration, SOE_OPTIONAL)
|
||||
;
|
||||
|
||||
DECLARE_TF(OfferCancel, ttOFFER_CANCEL)
|
||||
<< SOElement(sfOfferSequence, SOE_REQUIRED)
|
||||
;
|
||||
DECLARE_TF (OfferCancel, ttOFFER_CANCEL)
|
||||
<< SOElement (sfOfferSequence, SOE_REQUIRED)
|
||||
;
|
||||
|
||||
DECLARE_TF(SetRegularKey, ttREGULAR_KEY_SET)
|
||||
<< SOElement(sfRegularKey, SOE_REQUIRED)
|
||||
;
|
||||
DECLARE_TF (SetRegularKey, ttREGULAR_KEY_SET)
|
||||
<< SOElement (sfRegularKey, SOE_REQUIRED)
|
||||
;
|
||||
|
||||
DECLARE_TF(Payment, ttPAYMENT)
|
||||
<< SOElement(sfDestination, SOE_REQUIRED)
|
||||
<< SOElement(sfAmount, SOE_REQUIRED)
|
||||
<< SOElement(sfSendMax, SOE_OPTIONAL)
|
||||
<< SOElement(sfPaths, SOE_DEFAULT)
|
||||
<< SOElement(sfInvoiceID, SOE_OPTIONAL)
|
||||
<< SOElement(sfDestinationTag, SOE_OPTIONAL)
|
||||
;
|
||||
DECLARE_TF (Payment, ttPAYMENT)
|
||||
<< SOElement (sfDestination, SOE_REQUIRED)
|
||||
<< SOElement (sfAmount, SOE_REQUIRED)
|
||||
<< SOElement (sfSendMax, SOE_OPTIONAL)
|
||||
<< SOElement (sfPaths, SOE_DEFAULT)
|
||||
<< SOElement (sfInvoiceID, SOE_OPTIONAL)
|
||||
<< SOElement (sfDestinationTag, SOE_OPTIONAL)
|
||||
;
|
||||
|
||||
DECLARE_TF(Contract, ttCONTRACT)
|
||||
<< SOElement(sfExpiration, SOE_REQUIRED)
|
||||
<< SOElement(sfBondAmount, SOE_REQUIRED)
|
||||
<< SOElement(sfStampEscrow, SOE_REQUIRED)
|
||||
<< SOElement(sfRippleEscrow, SOE_REQUIRED)
|
||||
<< SOElement(sfCreateCode, SOE_OPTIONAL)
|
||||
<< SOElement(sfFundCode, SOE_OPTIONAL)
|
||||
<< SOElement(sfRemoveCode, SOE_OPTIONAL)
|
||||
<< SOElement(sfExpireCode, SOE_OPTIONAL)
|
||||
;
|
||||
DECLARE_TF (Contract, ttCONTRACT)
|
||||
<< SOElement (sfExpiration, SOE_REQUIRED)
|
||||
<< SOElement (sfBondAmount, SOE_REQUIRED)
|
||||
<< SOElement (sfStampEscrow, SOE_REQUIRED)
|
||||
<< SOElement (sfRippleEscrow, SOE_REQUIRED)
|
||||
<< SOElement (sfCreateCode, SOE_OPTIONAL)
|
||||
<< SOElement (sfFundCode, SOE_OPTIONAL)
|
||||
<< SOElement (sfRemoveCode, SOE_OPTIONAL)
|
||||
<< SOElement (sfExpireCode, SOE_OPTIONAL)
|
||||
;
|
||||
|
||||
DECLARE_TF(RemoveContract, ttCONTRACT_REMOVE)
|
||||
<< SOElement(sfTarget, SOE_REQUIRED)
|
||||
;
|
||||
DECLARE_TF (RemoveContract, ttCONTRACT_REMOVE)
|
||||
<< SOElement (sfTarget, SOE_REQUIRED)
|
||||
;
|
||||
|
||||
DECLARE_TF(EnableFeature, ttFEATURE)
|
||||
<< SOElement(sfFeature, SOE_REQUIRED)
|
||||
;
|
||||
DECLARE_TF (EnableFeature, ttFEATURE)
|
||||
<< SOElement (sfFeature, SOE_REQUIRED)
|
||||
;
|
||||
|
||||
DECLARE_TF(SetFee, ttFEE)
|
||||
<< SOElement(sfBaseFee, SOE_REQUIRED)
|
||||
<< SOElement(sfReferenceFeeUnits, SOE_REQUIRED)
|
||||
<< SOElement(sfReserveBase, SOE_REQUIRED)
|
||||
<< SOElement(sfReserveIncrement, SOE_REQUIRED)
|
||||
;
|
||||
DECLARE_TF (SetFee, ttFEE)
|
||||
<< SOElement (sfBaseFee, SOE_REQUIRED)
|
||||
<< SOElement (sfReferenceFeeUnits, SOE_REQUIRED)
|
||||
<< SOElement (sfReserveBase, SOE_REQUIRED)
|
||||
<< SOElement (sfReserveIncrement, SOE_REQUIRED)
|
||||
;
|
||||
}
|
||||
|
||||
TransactionFormat* TransactionFormat::getTxnFormat(TransactionType t)
|
||||
TransactionFormat* TransactionFormat::getTxnFormat (TransactionType t)
|
||||
{
|
||||
std::map<int, TransactionFormat*>::iterator it = byType.find(static_cast<int>(t));
|
||||
if (it == byType.end())
|
||||
return NULL;
|
||||
return it->second;
|
||||
std::map<int, TransactionFormat*>::iterator it = byType.find (static_cast<int> (t));
|
||||
|
||||
if (it == byType.end ())
|
||||
return NULL;
|
||||
|
||||
return it->second;
|
||||
}
|
||||
|
||||
TransactionFormat* TransactionFormat::getTxnFormat(int t)
|
||||
TransactionFormat* TransactionFormat::getTxnFormat (int t)
|
||||
{
|
||||
std::map<int, TransactionFormat*>::iterator it = byType.find((t));
|
||||
if (it == byType.end())
|
||||
return NULL;
|
||||
return it->second;
|
||||
std::map<int, TransactionFormat*>::iterator it = byType.find ((t));
|
||||
|
||||
if (it == byType.end ())
|
||||
return NULL;
|
||||
|
||||
return it->second;
|
||||
}
|
||||
|
||||
TransactionFormat* TransactionFormat::getTxnFormat(const std::string& t)
|
||||
TransactionFormat* TransactionFormat::getTxnFormat (const std::string& t)
|
||||
{
|
||||
std::map<std::string, TransactionFormat*>::iterator it = byName.find((t));
|
||||
if (it == byName.end())
|
||||
return NULL;
|
||||
return it->second;
|
||||
std::map<std::string, TransactionFormat*>::iterator it = byName.find ((t));
|
||||
|
||||
if (it == byName.end ())
|
||||
return NULL;
|
||||
|
||||
return it->second;
|
||||
}
|
||||
|
||||
// vim:ts=4
|
||||
// vim:ts=4
|
||||
|
||||
@@ -3,86 +3,86 @@
|
||||
|
||||
enum TransactionType
|
||||
{
|
||||
ttINVALID = -1,
|
||||
ttINVALID = -1,
|
||||
|
||||
ttPAYMENT = 0,
|
||||
ttCLAIM = 1, // open
|
||||
ttWALLET_ADD = 2,
|
||||
ttACCOUNT_SET = 3,
|
||||
ttPASSWORD_FUND = 4, // open
|
||||
ttREGULAR_KEY_SET = 5,
|
||||
ttNICKNAME_SET = 6, // open
|
||||
ttOFFER_CREATE = 7,
|
||||
ttOFFER_CANCEL = 8,
|
||||
ttCONTRACT = 9,
|
||||
ttCONTRACT_REMOVE = 10, // can we use the same msg as offer cancel
|
||||
ttPAYMENT = 0,
|
||||
ttCLAIM = 1, // open
|
||||
ttWALLET_ADD = 2,
|
||||
ttACCOUNT_SET = 3,
|
||||
ttPASSWORD_FUND = 4, // open
|
||||
ttREGULAR_KEY_SET = 5,
|
||||
ttNICKNAME_SET = 6, // open
|
||||
ttOFFER_CREATE = 7,
|
||||
ttOFFER_CANCEL = 8,
|
||||
ttCONTRACT = 9,
|
||||
ttCONTRACT_REMOVE = 10, // can we use the same msg as offer cancel
|
||||
|
||||
ttTRUST_SET = 20,
|
||||
ttTRUST_SET = 20,
|
||||
|
||||
ttFEATURE = 100,
|
||||
ttFEE = 101,
|
||||
ttFEATURE = 100,
|
||||
ttFEE = 101,
|
||||
};
|
||||
|
||||
class TransactionFormat
|
||||
{
|
||||
public:
|
||||
std::string t_name;
|
||||
TransactionType t_type;
|
||||
SOTemplate elements;
|
||||
std::string t_name;
|
||||
TransactionType t_type;
|
||||
SOTemplate elements;
|
||||
|
||||
static std::map<int, TransactionFormat*> byType;
|
||||
static std::map<std::string, TransactionFormat*> byName;
|
||||
static std::map<int, TransactionFormat*> byType;
|
||||
static std::map<std::string, TransactionFormat*> byName;
|
||||
|
||||
TransactionFormat(const char *name, TransactionType type) : t_name(name), t_type(type)
|
||||
TransactionFormat (const char* name, TransactionType type) : t_name (name), t_type (type)
|
||||
{
|
||||
byName[name] = this;
|
||||
byType[type] = this;
|
||||
byName[name] = this;
|
||||
byType[type] = this;
|
||||
}
|
||||
TransactionFormat& operator<<(const SOElement& el)
|
||||
TransactionFormat& operator<< (const SOElement& el)
|
||||
{
|
||||
elements.push_back(el);
|
||||
return *this;
|
||||
elements.push_back (el);
|
||||
return *this;
|
||||
}
|
||||
|
||||
static TransactionFormat* getTxnFormat(TransactionType t);
|
||||
static TransactionFormat* getTxnFormat(const std::string& t);
|
||||
static TransactionFormat* getTxnFormat(int t);
|
||||
static TransactionFormat* getTxnFormat (TransactionType t);
|
||||
static TransactionFormat* getTxnFormat (const std::string& t);
|
||||
static TransactionFormat* getTxnFormat (int t);
|
||||
};
|
||||
|
||||
const int TransactionMinLen = 32;
|
||||
const int TransactionMaxLen = 1048576;
|
||||
const int TransactionMinLen = 32;
|
||||
const int TransactionMaxLen = 1048576;
|
||||
|
||||
//
|
||||
// Transaction flags.
|
||||
//
|
||||
|
||||
// AccountSet flags:
|
||||
const uint32 tfRequireDestTag = 0x00010000;
|
||||
const uint32 tfOptionalDestTag = 0x00020000;
|
||||
const uint32 tfRequireAuth = 0x00040000;
|
||||
const uint32 tfOptionalAuth = 0x00080000;
|
||||
const uint32 tfDisallowXRP = 0x00100000;
|
||||
const uint32 tfAllowXRP = 0x00200000;
|
||||
const uint32 tfAccountSetMask = ~(tfRequireDestTag|tfOptionalDestTag
|
||||
|tfRequireAuth|tfOptionalAuth
|
||||
|tfDisallowXRP|tfAllowXRP);
|
||||
const uint32 tfRequireDestTag = 0x00010000;
|
||||
const uint32 tfOptionalDestTag = 0x00020000;
|
||||
const uint32 tfRequireAuth = 0x00040000;
|
||||
const uint32 tfOptionalAuth = 0x00080000;
|
||||
const uint32 tfDisallowXRP = 0x00100000;
|
||||
const uint32 tfAllowXRP = 0x00200000;
|
||||
const uint32 tfAccountSetMask = ~ (tfRequireDestTag | tfOptionalDestTag
|
||||
| tfRequireAuth | tfOptionalAuth
|
||||
| tfDisallowXRP | tfAllowXRP);
|
||||
|
||||
// OfferCreate flags:
|
||||
const uint32 tfPassive = 0x00010000;
|
||||
const uint32 tfImmediateOrCancel = 0x00020000;
|
||||
const uint32 tfFillOrKill = 0x00040000;
|
||||
const uint32 tfSell = 0x00080000;
|
||||
const uint32 tfOfferCreateMask = ~(tfPassive|tfImmediateOrCancel|tfFillOrKill|tfSell);
|
||||
const uint32 tfPassive = 0x00010000;
|
||||
const uint32 tfImmediateOrCancel = 0x00020000;
|
||||
const uint32 tfFillOrKill = 0x00040000;
|
||||
const uint32 tfSell = 0x00080000;
|
||||
const uint32 tfOfferCreateMask = ~ (tfPassive | tfImmediateOrCancel | tfFillOrKill | tfSell);
|
||||
|
||||
// Payment flags:
|
||||
const uint32 tfNoRippleDirect = 0x00010000;
|
||||
const uint32 tfPartialPayment = 0x00020000;
|
||||
const uint32 tfLimitQuality = 0x00040000;
|
||||
const uint32 tfPaymentMask = ~(tfPartialPayment|tfLimitQuality|tfNoRippleDirect);
|
||||
const uint32 tfNoRippleDirect = 0x00010000;
|
||||
const uint32 tfPartialPayment = 0x00020000;
|
||||
const uint32 tfLimitQuality = 0x00040000;
|
||||
const uint32 tfPaymentMask = ~ (tfPartialPayment | tfLimitQuality | tfNoRippleDirect);
|
||||
|
||||
// TrustSet flags:
|
||||
const uint32 tfSetfAuth = 0x00010000;
|
||||
const uint32 tfTrustSetMask = ~(tfSetfAuth);
|
||||
const uint32 tfSetfAuth = 0x00010000;
|
||||
const uint32 tfTrustSetMask = ~ (tfSetfAuth);
|
||||
|
||||
#endif
|
||||
// vim:ts=4
|
||||
|
||||
@@ -1,22 +1,22 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
Copyright (c) 2011-2013, OpenCoin, Inc.
|
||||
Copyright (c) 2011-2013, OpenCoin, Inc.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
/** Add this to get the @ref ripple_data module.
|
||||
/** Add this to get the @ref ripple_data module.
|
||||
|
||||
@file ripple_data.cpp
|
||||
@ingroup ripple_data
|
||||
|
||||
@@ -1,32 +1,32 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
Copyright (c) 2011-2013, OpenCoin, Inc.
|
||||
Copyright (c) 2011-2013, OpenCoin, Inc.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
/** Include this to get the @ref ripple_data module.
|
||||
/** Include this to get the @ref ripple_data module.
|
||||
|
||||
@file ripple_data.h
|
||||
@ingroup ripple_data
|
||||
*/
|
||||
|
||||
/** Ripple specific data representation and manipulation.
|
||||
/** Ripple specific data representation and manipulation.
|
||||
|
||||
These form the building blocks of Ripple data.
|
||||
These form the building blocks of Ripple data.
|
||||
|
||||
@defgroup ripple_data
|
||||
@defgroup ripple_data
|
||||
*/
|
||||
|
||||
#ifndef RIPPLE_DATA_H
|
||||
|
||||
@@ -17,22 +17,48 @@ JSONCache::Key::Key (int op, uint256 const& ledger, uint160 const& object, int l
|
||||
int JSONCache::Key::compare (Key const& other) const
|
||||
{
|
||||
if (mHash < other.mHash) return -1;
|
||||
|
||||
if (mHash > other.mHash) return 1;
|
||||
|
||||
if (mOperation < other.mOperation) return -1;
|
||||
|
||||
if (mOperation > other.mOperation) return 1;
|
||||
|
||||
if (mLedger < other.mLedger) return -1;
|
||||
|
||||
if (mLedger > other.mLedger) return 1;
|
||||
|
||||
if (mObject < other.mObject) return -1;
|
||||
|
||||
if (mObject > other.mObject) return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool JSONCache::Key::operator< (Key const& rhs) const { return compare (rhs) < 0; }
|
||||
bool JSONCache::Key::operator> (Key const& rhs) const { return compare (rhs) > 0; }
|
||||
bool JSONCache::Key::operator<= (Key const& rhs) const { return compare (rhs) <= 0; }
|
||||
bool JSONCache::Key::operator>= (Key const& rhs) const { return compare (rhs) >= 0; }
|
||||
bool JSONCache::Key::operator!= (Key const& rhs) const { return compare (rhs) != 0; }
|
||||
bool JSONCache::Key::operator== (Key const& rhs) const { return compare (rhs) == 0; }
|
||||
bool JSONCache::Key::operator< (Key const& rhs) const
|
||||
{
|
||||
return compare (rhs) < 0;
|
||||
}
|
||||
bool JSONCache::Key::operator> (Key const& rhs) const
|
||||
{
|
||||
return compare (rhs) > 0;
|
||||
}
|
||||
bool JSONCache::Key::operator<= (Key const& rhs) const
|
||||
{
|
||||
return compare (rhs) <= 0;
|
||||
}
|
||||
bool JSONCache::Key::operator>= (Key const& rhs) const
|
||||
{
|
||||
return compare (rhs) >= 0;
|
||||
}
|
||||
bool JSONCache::Key::operator!= (Key const& rhs) const
|
||||
{
|
||||
return compare (rhs) != 0;
|
||||
}
|
||||
bool JSONCache::Key::operator== (Key const& rhs) const
|
||||
{
|
||||
return compare (rhs) == 0;
|
||||
}
|
||||
|
||||
void JSONCache::Key::touch (Key const& key) const
|
||||
{
|
||||
@@ -85,7 +111,7 @@ JSONCache::data_t JSONCache::getEntry (Kind kind, LedgerHash const& ledger, uint
|
||||
Key key (kind, ledger, object, getUptime ());
|
||||
|
||||
{
|
||||
boost::recursive_mutex::scoped_lock sl(m_lock);
|
||||
boost::recursive_mutex::scoped_lock sl (m_lock);
|
||||
|
||||
boost::unordered_map <Key, data_t>::iterator it = m_cache.find (key);
|
||||
|
||||
@@ -113,7 +139,7 @@ void JSONCache::storeEntry (Kind kind, uint256 const& ledger, uint160 const& obj
|
||||
Key key (kind, ledger, object, getUptime ());
|
||||
|
||||
{
|
||||
boost::recursive_mutex::scoped_lock sl(m_lock);
|
||||
boost::recursive_mutex::scoped_lock sl (m_lock);
|
||||
|
||||
m_cache.insert (std::pair <Key, data_t> (key, data));
|
||||
}
|
||||
@@ -130,15 +156,15 @@ void JSONCache::sweep ()
|
||||
sweepTime -= m_expirationTime;
|
||||
|
||||
{
|
||||
boost::recursive_mutex::scoped_lock sl(m_lock);
|
||||
boost::recursive_mutex::scoped_lock sl (m_lock);
|
||||
|
||||
boost::unordered_map <Key, data_t>::iterator it = m_cache.begin();
|
||||
boost::unordered_map <Key, data_t>::iterator it = m_cache.begin ();
|
||||
|
||||
while (it != m_cache.end ())
|
||||
{
|
||||
if (it->first.isExpired (sweepTime))
|
||||
{
|
||||
it = m_cache.erase(it);
|
||||
it = m_cache.erase (it);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -153,5 +179,5 @@ void JSONCache::sweep ()
|
||||
|
||||
int JSONCache::getUptime () const
|
||||
{
|
||||
return UptimeTimer::getInstance().getElapsedSeconds();
|
||||
return UptimeTimer::getInstance ().getElapsedSeconds ();
|
||||
}
|
||||
|
||||
@@ -12,13 +12,13 @@ public:
|
||||
{
|
||||
public:
|
||||
Key (int op, const uint256& ledger, const uint160& object, int lastUse);
|
||||
int compare(const Key& k) const;
|
||||
bool operator<(const Key &k) const;
|
||||
bool operator>(const Key &k) const;
|
||||
bool operator<=(const Key &k) const;
|
||||
bool operator>=(const Key &k) const;
|
||||
bool operator!=(const Key &k) const;
|
||||
bool operator==(const Key &k) const;
|
||||
int compare (const Key& k) const;
|
||||
bool operator< (const Key& k) const;
|
||||
bool operator> (const Key& k) const;
|
||||
bool operator<= (const Key& k) const;
|
||||
bool operator>= (const Key& k) const;
|
||||
bool operator!= (const Key& k) const;
|
||||
bool operator== (const Key& k) const;
|
||||
|
||||
void touch (Key const& key) const;
|
||||
bool isExpired (int expireTime) const;
|
||||
|
||||
@@ -5,10 +5,10 @@
|
||||
*/
|
||||
struct UptimeTimerAdapter
|
||||
{
|
||||
inline static int getElapsedSeconds ()
|
||||
{
|
||||
return UptimeTimer::getInstance().getElapsedSeconds ();
|
||||
}
|
||||
inline static int getElapsedSeconds ()
|
||||
{
|
||||
return UptimeTimer::getInstance ().getElapsedSeconds ();
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,22 +1,22 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
Copyright (c) 2011-2013, OpenCoin, Inc.
|
||||
Copyright (c) 2011-2013, OpenCoin, Inc.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
/** Add this to get the @ref ripple_db module.
|
||||
/** Add this to get the @ref ripple_db module.
|
||||
|
||||
@file ripple_db.cpp
|
||||
@ingroup ripple_db
|
||||
|
||||
@@ -1,32 +1,32 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
Copyright (c) 2011-2013, OpenCoin, Inc.
|
||||
Copyright (c) 2011-2013, OpenCoin, Inc.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
/** Include this to get the @ref ripple_db module.
|
||||
/** Include this to get the @ref ripple_db module.
|
||||
|
||||
@file ripple_db.h
|
||||
@ingroup ripple_db
|
||||
*/
|
||||
|
||||
/** Basic classes.
|
||||
/** Basic classes.
|
||||
|
||||
This module provides persistent storage facilities.
|
||||
This module provides persistent storage facilities.
|
||||
|
||||
@defgroup ripple_db
|
||||
@defgroup ripple_db
|
||||
*/
|
||||
|
||||
#ifndef RIPPLE_DB_H
|
||||
|
||||
Binary file not shown.
@@ -3,7 +3,8 @@
|
||||
|
||||
# ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION
|
||||
|
||||
namespace Json {
|
||||
namespace Json
|
||||
{
|
||||
|
||||
/* Fast memory allocator.
|
||||
*
|
||||
@@ -17,100 +18,103 @@ namespace Json {
|
||||
* The in-place new operator must be used to construct the object using the pointer
|
||||
* returned by allocate.
|
||||
*/
|
||||
template<typename AllocatedType
|
||||
,const unsigned int objectPerAllocation>
|
||||
template < typename AllocatedType
|
||||
, const unsigned int objectPerAllocation >
|
||||
class BatchAllocator
|
||||
{
|
||||
public:
|
||||
typedef AllocatedType Type;
|
||||
typedef AllocatedType Type;
|
||||
|
||||
BatchAllocator( unsigned int objectsPerPage = 255 )
|
||||
: freeHead_( 0 )
|
||||
, objectsPerPage_( objectsPerPage )
|
||||
{
|
||||
// printf( "Size: %d => %s\n", sizeof(AllocatedType), typeid(AllocatedType).name() );
|
||||
assert( sizeof(AllocatedType) * objectPerAllocation >= sizeof(AllocatedType *) ); // We must be able to store a slist in the object free space.
|
||||
assert( objectsPerPage >= 16 );
|
||||
batches_ = allocateBatch( 0 ); // allocated a dummy page
|
||||
currentBatch_ = batches_;
|
||||
}
|
||||
BatchAllocator ( unsigned int objectsPerPage = 255 )
|
||||
: freeHead_ ( 0 )
|
||||
, objectsPerPage_ ( objectsPerPage )
|
||||
{
|
||||
// printf( "Size: %d => %s\n", sizeof(AllocatedType), typeid(AllocatedType).name() );
|
||||
assert ( sizeof (AllocatedType) * objectPerAllocation >= sizeof (AllocatedType*) ); // We must be able to store a slist in the object free space.
|
||||
assert ( objectsPerPage >= 16 );
|
||||
batches_ = allocateBatch ( 0 ); // allocated a dummy page
|
||||
currentBatch_ = batches_;
|
||||
}
|
||||
|
||||
~BatchAllocator()
|
||||
{
|
||||
for ( BatchInfo *batch = batches_; batch; )
|
||||
{
|
||||
BatchInfo *nextBatch = batch->next_;
|
||||
free( batch );
|
||||
batch = nextBatch;
|
||||
}
|
||||
}
|
||||
~BatchAllocator ()
|
||||
{
|
||||
for ( BatchInfo* batch = batches_; batch; )
|
||||
{
|
||||
BatchInfo* nextBatch = batch->next_;
|
||||
free ( batch );
|
||||
batch = nextBatch;
|
||||
}
|
||||
}
|
||||
|
||||
/// allocate space for an array of objectPerAllocation object.
|
||||
/// @warning it is the responsability of the caller to call objects constructors.
|
||||
AllocatedType *allocate()
|
||||
{
|
||||
if ( freeHead_ ) // returns node from free list.
|
||||
{
|
||||
AllocatedType *object = freeHead_;
|
||||
freeHead_ = *(AllocatedType **)object;
|
||||
return object;
|
||||
}
|
||||
if ( currentBatch_->used_ == currentBatch_->end_ )
|
||||
{
|
||||
currentBatch_ = currentBatch_->next_;
|
||||
while ( currentBatch_ && currentBatch_->used_ == currentBatch_->end_ )
|
||||
/// allocate space for an array of objectPerAllocation object.
|
||||
/// @warning it is the responsability of the caller to call objects constructors.
|
||||
AllocatedType* allocate ()
|
||||
{
|
||||
if ( freeHead_ ) // returns node from free list.
|
||||
{
|
||||
AllocatedType* object = freeHead_;
|
||||
freeHead_ = * (AllocatedType**)object;
|
||||
return object;
|
||||
}
|
||||
|
||||
if ( currentBatch_->used_ == currentBatch_->end_ )
|
||||
{
|
||||
currentBatch_ = currentBatch_->next_;
|
||||
|
||||
if ( !currentBatch_ ) // no free batch found, allocate a new one
|
||||
{
|
||||
currentBatch_ = allocateBatch( objectsPerPage_ );
|
||||
currentBatch_->next_ = batches_; // insert at the head of the list
|
||||
batches_ = currentBatch_;
|
||||
}
|
||||
}
|
||||
AllocatedType *allocated = currentBatch_->used_;
|
||||
currentBatch_->used_ += objectPerAllocation;
|
||||
return allocated;
|
||||
}
|
||||
while ( currentBatch_ && currentBatch_->used_ == currentBatch_->end_ )
|
||||
currentBatch_ = currentBatch_->next_;
|
||||
|
||||
/// Release the object.
|
||||
/// @warning it is the responsability of the caller to actually destruct the object.
|
||||
void release( AllocatedType *object )
|
||||
{
|
||||
assert( object != 0 );
|
||||
*(AllocatedType **)object = freeHead_;
|
||||
freeHead_ = object;
|
||||
}
|
||||
if ( !currentBatch_ ) // no free batch found, allocate a new one
|
||||
{
|
||||
currentBatch_ = allocateBatch ( objectsPerPage_ );
|
||||
currentBatch_->next_ = batches_; // insert at the head of the list
|
||||
batches_ = currentBatch_;
|
||||
}
|
||||
}
|
||||
|
||||
AllocatedType* allocated = currentBatch_->used_;
|
||||
currentBatch_->used_ += objectPerAllocation;
|
||||
return allocated;
|
||||
}
|
||||
|
||||
/// Release the object.
|
||||
/// @warning it is the responsability of the caller to actually destruct the object.
|
||||
void release ( AllocatedType* object )
|
||||
{
|
||||
assert ( object != 0 );
|
||||
* (AllocatedType**)object = freeHead_;
|
||||
freeHead_ = object;
|
||||
}
|
||||
|
||||
private:
|
||||
struct BatchInfo
|
||||
{
|
||||
BatchInfo *next_;
|
||||
AllocatedType *used_;
|
||||
AllocatedType *end_;
|
||||
AllocatedType buffer_[objectPerAllocation];
|
||||
};
|
||||
struct BatchInfo
|
||||
{
|
||||
BatchInfo* next_;
|
||||
AllocatedType* used_;
|
||||
AllocatedType* end_;
|
||||
AllocatedType buffer_[objectPerAllocation];
|
||||
};
|
||||
|
||||
// disabled copy constructor and assignement operator.
|
||||
BatchAllocator( const BatchAllocator & );
|
||||
void operator =( const BatchAllocator &);
|
||||
// disabled copy constructor and assignement operator.
|
||||
BatchAllocator ( const BatchAllocator& );
|
||||
void operator = ( const BatchAllocator&);
|
||||
|
||||
static BatchInfo *allocateBatch( unsigned int objectsPerPage )
|
||||
{
|
||||
const unsigned int mallocSize = sizeof(BatchInfo) - sizeof(AllocatedType)* objectPerAllocation
|
||||
+ sizeof(AllocatedType) * objectPerAllocation * objectsPerPage;
|
||||
BatchInfo *batch = static_cast<BatchInfo*>( malloc( mallocSize ) );
|
||||
batch->next_ = 0;
|
||||
batch->used_ = batch->buffer_;
|
||||
batch->end_ = batch->buffer_ + objectsPerPage;
|
||||
return batch;
|
||||
}
|
||||
static BatchInfo* allocateBatch ( unsigned int objectsPerPage )
|
||||
{
|
||||
const unsigned int mallocSize = sizeof (BatchInfo) - sizeof (AllocatedType) * objectPerAllocation
|
||||
+ sizeof (AllocatedType) * objectPerAllocation * objectsPerPage;
|
||||
BatchInfo* batch = static_cast<BatchInfo*> ( malloc ( mallocSize ) );
|
||||
batch->next_ = 0;
|
||||
batch->used_ = batch->buffer_;
|
||||
batch->end_ = batch->buffer_ + objectsPerPage;
|
||||
return batch;
|
||||
}
|
||||
|
||||
BatchInfo *batches_;
|
||||
BatchInfo *currentBatch_;
|
||||
/// Head of a single linked list within the allocated space of freeed object
|
||||
AllocatedType *freeHead_;
|
||||
unsigned int objectsPerPage_;
|
||||
BatchInfo* batches_;
|
||||
BatchInfo* currentBatch_;
|
||||
/// Head of a single linked list within the allocated space of freeed object
|
||||
AllocatedType* freeHead_;
|
||||
unsigned int objectsPerPage_;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -1,39 +1,40 @@
|
||||
#ifndef CPPTL_JSON_FEATURES_H_INCLUDED
|
||||
#define CPPTL_JSON_FEATURES_H_INCLUDED
|
||||
|
||||
namespace Json {
|
||||
namespace Json
|
||||
{
|
||||
|
||||
/** \brief Configuration passed to reader and writer.
|
||||
* This configuration object can be used to force the Reader or Writer
|
||||
* to behave in a standard conforming way.
|
||||
*/
|
||||
class JSON_API Features
|
||||
{
|
||||
public:
|
||||
/** \brief A configuration that allows all features and assumes all strings are UTF-8.
|
||||
* - C & C++ comments are allowed
|
||||
* - Root object can be any JSON value
|
||||
* - Assumes Value strings are encoded in UTF-8
|
||||
*/
|
||||
static Features all();
|
||||
/** \brief Configuration passed to reader and writer.
|
||||
* This configuration object can be used to force the Reader or Writer
|
||||
* to behave in a standard conforming way.
|
||||
*/
|
||||
class JSON_API Features
|
||||
{
|
||||
public:
|
||||
/** \brief A configuration that allows all features and assumes all strings are UTF-8.
|
||||
* - C & C++ comments are allowed
|
||||
* - Root object can be any JSON value
|
||||
* - Assumes Value strings are encoded in UTF-8
|
||||
*/
|
||||
static Features all ();
|
||||
|
||||
/** \brief A configuration that is strictly compatible with the JSON specification.
|
||||
* - Comments are forbidden.
|
||||
* - Root object must be either an array or an object value.
|
||||
* - Assumes Value strings are encoded in UTF-8
|
||||
*/
|
||||
static Features strictMode();
|
||||
/** \brief A configuration that is strictly compatible with the JSON specification.
|
||||
* - Comments are forbidden.
|
||||
* - Root object must be either an array or an object value.
|
||||
* - Assumes Value strings are encoded in UTF-8
|
||||
*/
|
||||
static Features strictMode ();
|
||||
|
||||
/** \brief Initialize the configuration like JsonConfig::allFeatures;
|
||||
*/
|
||||
Features();
|
||||
/** \brief Initialize the configuration like JsonConfig::allFeatures;
|
||||
*/
|
||||
Features ();
|
||||
|
||||
/// \c true if comments are allowed. Default: \c true.
|
||||
bool allowComments_;
|
||||
/// \c true if comments are allowed. Default: \c true.
|
||||
bool allowComments_;
|
||||
|
||||
/// \c true if root must be either an array or an object value. Default: \c false.
|
||||
bool strictRoot_;
|
||||
};
|
||||
/// \c true if root must be either an array or an object value. Default: \c false.
|
||||
bool strictRoot_;
|
||||
};
|
||||
|
||||
} // namespace Json
|
||||
|
||||
|
||||
@@ -1,34 +1,35 @@
|
||||
#ifndef JSON_FORWARDS_H_INCLUDED
|
||||
#define JSON_FORWARDS_H_INCLUDED
|
||||
|
||||
namespace Json {
|
||||
namespace Json
|
||||
{
|
||||
|
||||
// writer.h
|
||||
class FastWriter;
|
||||
class StyledWriter;
|
||||
// writer.h
|
||||
class FastWriter;
|
||||
class StyledWriter;
|
||||
|
||||
// reader.h
|
||||
class Reader;
|
||||
// reader.h
|
||||
class Reader;
|
||||
|
||||
// features.h
|
||||
class Features;
|
||||
// features.h
|
||||
class Features;
|
||||
|
||||
// value.h
|
||||
typedef int Int;
|
||||
typedef unsigned int UInt;
|
||||
class StaticString;
|
||||
class Path;
|
||||
class PathArgument;
|
||||
class Value;
|
||||
class ValueIteratorBase;
|
||||
class ValueIterator;
|
||||
class ValueConstIterator;
|
||||
// value.h
|
||||
typedef int Int;
|
||||
typedef unsigned int UInt;
|
||||
class StaticString;
|
||||
class Path;
|
||||
class PathArgument;
|
||||
class Value;
|
||||
class ValueIteratorBase;
|
||||
class ValueIterator;
|
||||
class ValueConstIterator;
|
||||
#ifdef JSON_VALUE_USE_INTERNAL_MAP
|
||||
class ValueAllocator;
|
||||
class ValueMapAllocator;
|
||||
class ValueInternalLink;
|
||||
class ValueInternalArray;
|
||||
class ValueInternalMap;
|
||||
class ValueAllocator;
|
||||
class ValueMapAllocator;
|
||||
class ValueInternalLink;
|
||||
class ValueInternalArray;
|
||||
class ValueInternalMap;
|
||||
#endif // #ifdef JSON_VALUE_USE_INTERNAL_MAP
|
||||
|
||||
} // namespace Json
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
// //////////////////////////////////////////////////////////////////
|
||||
// //////////////////////////////////////////////////////////////////
|
||||
|
||||
ValueArrayAllocator::~ValueArrayAllocator()
|
||||
ValueArrayAllocator::~ValueArrayAllocator ()
|
||||
{
|
||||
}
|
||||
|
||||
@@ -20,55 +20,59 @@ ValueArrayAllocator::~ValueArrayAllocator()
|
||||
class DefaultValueArrayAllocator : public ValueArrayAllocator
|
||||
{
|
||||
public: // overridden from ValueArrayAllocator
|
||||
virtual ~DefaultValueArrayAllocator()
|
||||
{
|
||||
}
|
||||
virtual ~DefaultValueArrayAllocator ()
|
||||
{
|
||||
}
|
||||
|
||||
virtual ValueInternalArray *newArray()
|
||||
{
|
||||
return new ValueInternalArray();
|
||||
}
|
||||
virtual ValueInternalArray* newArray ()
|
||||
{
|
||||
return new ValueInternalArray ();
|
||||
}
|
||||
|
||||
virtual ValueInternalArray *newArrayCopy( const ValueInternalArray &other )
|
||||
{
|
||||
return new ValueInternalArray( other );
|
||||
}
|
||||
virtual ValueInternalArray* newArrayCopy ( const ValueInternalArray& other )
|
||||
{
|
||||
return new ValueInternalArray ( other );
|
||||
}
|
||||
|
||||
virtual void destructArray( ValueInternalArray *array )
|
||||
{
|
||||
delete array;
|
||||
}
|
||||
virtual void destructArray ( ValueInternalArray* array )
|
||||
{
|
||||
delete array;
|
||||
}
|
||||
|
||||
virtual void reallocateArrayPageIndex( Value **&indexes,
|
||||
ValueInternalArray::PageIndex &indexCount,
|
||||
ValueInternalArray::PageIndex minNewIndexCount )
|
||||
{
|
||||
ValueInternalArray::PageIndex newIndexCount = (indexCount*3)/2 + 1;
|
||||
if ( minNewIndexCount > newIndexCount )
|
||||
newIndexCount = minNewIndexCount;
|
||||
void *newIndexes = realloc( indexes, sizeof(Value*) * newIndexCount );
|
||||
if ( !newIndexes )
|
||||
throw std::bad_alloc();
|
||||
indexCount = newIndexCount;
|
||||
indexes = static_cast<Value **>( newIndexes );
|
||||
}
|
||||
virtual void releaseArrayPageIndex( Value **indexes,
|
||||
ValueInternalArray::PageIndex indexCount )
|
||||
{
|
||||
if ( indexes )
|
||||
free( indexes );
|
||||
}
|
||||
virtual void reallocateArrayPageIndex ( Value**& indexes,
|
||||
ValueInternalArray::PageIndex& indexCount,
|
||||
ValueInternalArray::PageIndex minNewIndexCount )
|
||||
{
|
||||
ValueInternalArray::PageIndex newIndexCount = (indexCount * 3) / 2 + 1;
|
||||
|
||||
virtual Value *allocateArrayPage()
|
||||
{
|
||||
return static_cast<Value *>( malloc( sizeof(Value) * ValueInternalArray::itemsPerPage ) );
|
||||
}
|
||||
if ( minNewIndexCount > newIndexCount )
|
||||
newIndexCount = minNewIndexCount;
|
||||
|
||||
virtual void releaseArrayPage( Value *value )
|
||||
{
|
||||
if ( value )
|
||||
free( value );
|
||||
}
|
||||
void* newIndexes = realloc ( indexes, sizeof (Value*) * newIndexCount );
|
||||
|
||||
if ( !newIndexes )
|
||||
throw std::bad_alloc ();
|
||||
|
||||
indexCount = newIndexCount;
|
||||
indexes = static_cast<Value**> ( newIndexes );
|
||||
}
|
||||
virtual void releaseArrayPageIndex ( Value** indexes,
|
||||
ValueInternalArray::PageIndex indexCount )
|
||||
{
|
||||
if ( indexes )
|
||||
free ( indexes );
|
||||
}
|
||||
|
||||
virtual Value* allocateArrayPage ()
|
||||
{
|
||||
return static_cast<Value*> ( malloc ( sizeof (Value) * ValueInternalArray::itemsPerPage ) );
|
||||
}
|
||||
|
||||
virtual void releaseArrayPage ( Value* value )
|
||||
{
|
||||
if ( value )
|
||||
free ( value );
|
||||
}
|
||||
};
|
||||
|
||||
#else // #ifdef JSON_USE_SIMPLE_INTERNAL_ALLOCATOR
|
||||
@@ -76,373 +80,399 @@ public: // overridden from ValueArrayAllocator
|
||||
class DefaultValueArrayAllocator : public ValueArrayAllocator
|
||||
{
|
||||
public: // overridden from ValueArrayAllocator
|
||||
virtual ~DefaultValueArrayAllocator()
|
||||
{
|
||||
}
|
||||
virtual ~DefaultValueArrayAllocator ()
|
||||
{
|
||||
}
|
||||
|
||||
virtual ValueInternalArray *newArray()
|
||||
{
|
||||
ValueInternalArray *array = arraysAllocator_.allocate();
|
||||
new (array) ValueInternalArray(); // placement new
|
||||
return array;
|
||||
}
|
||||
virtual ValueInternalArray* newArray ()
|
||||
{
|
||||
ValueInternalArray* array = arraysAllocator_.allocate ();
|
||||
new (array) ValueInternalArray (); // placement new
|
||||
return array;
|
||||
}
|
||||
|
||||
virtual ValueInternalArray *newArrayCopy( const ValueInternalArray &other )
|
||||
{
|
||||
ValueInternalArray *array = arraysAllocator_.allocate();
|
||||
new (array) ValueInternalArray( other ); // placement new
|
||||
return array;
|
||||
}
|
||||
virtual ValueInternalArray* newArrayCopy ( const ValueInternalArray& other )
|
||||
{
|
||||
ValueInternalArray* array = arraysAllocator_.allocate ();
|
||||
new (array) ValueInternalArray ( other ); // placement new
|
||||
return array;
|
||||
}
|
||||
|
||||
virtual void destructArray( ValueInternalArray *array )
|
||||
{
|
||||
if ( array )
|
||||
{
|
||||
array->~ValueInternalArray();
|
||||
arraysAllocator_.release( array );
|
||||
}
|
||||
}
|
||||
virtual void destructArray ( ValueInternalArray* array )
|
||||
{
|
||||
if ( array )
|
||||
{
|
||||
array->~ValueInternalArray ();
|
||||
arraysAllocator_.release ( array );
|
||||
}
|
||||
}
|
||||
|
||||
virtual void reallocateArrayPageIndex( Value **&indexes,
|
||||
ValueInternalArray::PageIndex &indexCount,
|
||||
ValueInternalArray::PageIndex minNewIndexCount )
|
||||
{
|
||||
ValueInternalArray::PageIndex newIndexCount = (indexCount*3)/2 + 1;
|
||||
if ( minNewIndexCount > newIndexCount )
|
||||
newIndexCount = minNewIndexCount;
|
||||
void *newIndexes = realloc( indexes, sizeof(Value*) * newIndexCount );
|
||||
if ( !newIndexes )
|
||||
throw std::bad_alloc();
|
||||
indexCount = newIndexCount;
|
||||
indexes = static_cast<Value **>( newIndexes );
|
||||
}
|
||||
virtual void releaseArrayPageIndex( Value **indexes,
|
||||
ValueInternalArray::PageIndex indexCount )
|
||||
{
|
||||
if ( indexes )
|
||||
free( indexes );
|
||||
}
|
||||
virtual void reallocateArrayPageIndex ( Value**& indexes,
|
||||
ValueInternalArray::PageIndex& indexCount,
|
||||
ValueInternalArray::PageIndex minNewIndexCount )
|
||||
{
|
||||
ValueInternalArray::PageIndex newIndexCount = (indexCount * 3) / 2 + 1;
|
||||
|
||||
virtual Value *allocateArrayPage()
|
||||
{
|
||||
return static_cast<Value *>( pagesAllocator_.allocate() );
|
||||
}
|
||||
if ( minNewIndexCount > newIndexCount )
|
||||
newIndexCount = minNewIndexCount;
|
||||
|
||||
virtual void releaseArrayPage( Value *value )
|
||||
{
|
||||
if ( value )
|
||||
pagesAllocator_.release( value );
|
||||
}
|
||||
void* newIndexes = realloc ( indexes, sizeof (Value*) * newIndexCount );
|
||||
|
||||
if ( !newIndexes )
|
||||
throw std::bad_alloc ();
|
||||
|
||||
indexCount = newIndexCount;
|
||||
indexes = static_cast<Value**> ( newIndexes );
|
||||
}
|
||||
virtual void releaseArrayPageIndex ( Value** indexes,
|
||||
ValueInternalArray::PageIndex indexCount )
|
||||
{
|
||||
if ( indexes )
|
||||
free ( indexes );
|
||||
}
|
||||
|
||||
virtual Value* allocateArrayPage ()
|
||||
{
|
||||
return static_cast<Value*> ( pagesAllocator_.allocate () );
|
||||
}
|
||||
|
||||
virtual void releaseArrayPage ( Value* value )
|
||||
{
|
||||
if ( value )
|
||||
pagesAllocator_.release ( value );
|
||||
}
|
||||
private:
|
||||
BatchAllocator<ValueInternalArray,1> arraysAllocator_;
|
||||
BatchAllocator<Value,ValueInternalArray::itemsPerPage> pagesAllocator_;
|
||||
BatchAllocator<ValueInternalArray, 1> arraysAllocator_;
|
||||
BatchAllocator<Value, ValueInternalArray::itemsPerPage> pagesAllocator_;
|
||||
};
|
||||
#endif // #ifdef JSON_USE_SIMPLE_INTERNAL_ALLOCATOR
|
||||
|
||||
static ValueArrayAllocator *&arrayAllocator()
|
||||
static ValueArrayAllocator*& arrayAllocator ()
|
||||
{
|
||||
static DefaultValueArrayAllocator defaultAllocator;
|
||||
static ValueArrayAllocator *arrayAllocator = &defaultAllocator;
|
||||
return arrayAllocator;
|
||||
static DefaultValueArrayAllocator defaultAllocator;
|
||||
static ValueArrayAllocator* arrayAllocator = &defaultAllocator;
|
||||
return arrayAllocator;
|
||||
}
|
||||
|
||||
static struct DummyArrayAllocatorInitializer {
|
||||
DummyArrayAllocatorInitializer()
|
||||
{
|
||||
arrayAllocator(); // ensure arrayAllocator() statics are initialized before main().
|
||||
}
|
||||
static struct DummyArrayAllocatorInitializer
|
||||
{
|
||||
DummyArrayAllocatorInitializer ()
|
||||
{
|
||||
arrayAllocator (); // ensure arrayAllocator() statics are initialized before main().
|
||||
}
|
||||
} dummyArrayAllocatorInitializer;
|
||||
|
||||
// //////////////////////////////////////////////////////////////////
|
||||
// class ValueInternalArray
|
||||
// //////////////////////////////////////////////////////////////////
|
||||
bool
|
||||
ValueInternalArray::equals( const IteratorState &x,
|
||||
const IteratorState &other )
|
||||
ValueInternalArray::equals ( const IteratorState& x,
|
||||
const IteratorState& other )
|
||||
{
|
||||
return x.array_ == other.array_
|
||||
&& x.currentItemIndex_ == other.currentItemIndex_
|
||||
&& x.currentPageIndex_ == other.currentPageIndex_;
|
||||
return x.array_ == other.array_
|
||||
&& x.currentItemIndex_ == other.currentItemIndex_
|
||||
&& x.currentPageIndex_ == other.currentPageIndex_;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ValueInternalArray::increment( IteratorState &it )
|
||||
ValueInternalArray::increment ( IteratorState& it )
|
||||
{
|
||||
JSON_ASSERT_MESSAGE( it.array_ &&
|
||||
(it.currentPageIndex_ - it.array_->pages_)*itemsPerPage + it.currentItemIndex_
|
||||
!= it.array_->size_,
|
||||
"ValueInternalArray::increment(): moving iterator beyond end" );
|
||||
++(it.currentItemIndex_);
|
||||
if ( it.currentItemIndex_ == itemsPerPage )
|
||||
{
|
||||
it.currentItemIndex_ = 0;
|
||||
++(it.currentPageIndex_);
|
||||
}
|
||||
JSON_ASSERT_MESSAGE ( it.array_ &&
|
||||
(it.currentPageIndex_ - it.array_->pages_)*itemsPerPage + it.currentItemIndex_
|
||||
!= it.array_->size_,
|
||||
"ValueInternalArray::increment(): moving iterator beyond end" );
|
||||
++ (it.currentItemIndex_);
|
||||
|
||||
if ( it.currentItemIndex_ == itemsPerPage )
|
||||
{
|
||||
it.currentItemIndex_ = 0;
|
||||
++ (it.currentPageIndex_);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ValueInternalArray::decrement( IteratorState &it )
|
||||
ValueInternalArray::decrement ( IteratorState& it )
|
||||
{
|
||||
JSON_ASSERT_MESSAGE( it.array_ && it.currentPageIndex_ == it.array_->pages_
|
||||
&& it.currentItemIndex_ == 0,
|
||||
"ValueInternalArray::decrement(): moving iterator beyond end" );
|
||||
if ( it.currentItemIndex_ == 0 )
|
||||
{
|
||||
it.currentItemIndex_ = itemsPerPage-1;
|
||||
--(it.currentPageIndex_);
|
||||
}
|
||||
else
|
||||
{
|
||||
--(it.currentItemIndex_);
|
||||
}
|
||||
JSON_ASSERT_MESSAGE ( it.array_ && it.currentPageIndex_ == it.array_->pages_
|
||||
&& it.currentItemIndex_ == 0,
|
||||
"ValueInternalArray::decrement(): moving iterator beyond end" );
|
||||
|
||||
if ( it.currentItemIndex_ == 0 )
|
||||
{
|
||||
it.currentItemIndex_ = itemsPerPage - 1;
|
||||
-- (it.currentPageIndex_);
|
||||
}
|
||||
else
|
||||
{
|
||||
-- (it.currentItemIndex_);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Value &
|
||||
ValueInternalArray::unsafeDereference( const IteratorState &it )
|
||||
Value&
|
||||
ValueInternalArray::unsafeDereference ( const IteratorState& it )
|
||||
{
|
||||
return (*(it.currentPageIndex_))[it.currentItemIndex_];
|
||||
return (* (it.currentPageIndex_))[it.currentItemIndex_];
|
||||
}
|
||||
|
||||
|
||||
Value &
|
||||
ValueInternalArray::dereference( const IteratorState &it )
|
||||
Value&
|
||||
ValueInternalArray::dereference ( const IteratorState& it )
|
||||
{
|
||||
JSON_ASSERT_MESSAGE( it.array_ &&
|
||||
(it.currentPageIndex_ - it.array_->pages_)*itemsPerPage + it.currentItemIndex_
|
||||
< it.array_->size_,
|
||||
"ValueInternalArray::dereference(): dereferencing invalid iterator" );
|
||||
return unsafeDereference( it );
|
||||
JSON_ASSERT_MESSAGE ( it.array_ &&
|
||||
(it.currentPageIndex_ - it.array_->pages_)*itemsPerPage + it.currentItemIndex_
|
||||
< it.array_->size_,
|
||||
"ValueInternalArray::dereference(): dereferencing invalid iterator" );
|
||||
return unsafeDereference ( it );
|
||||
}
|
||||
|
||||
void
|
||||
ValueInternalArray::makeBeginIterator( IteratorState &it ) const
|
||||
ValueInternalArray::makeBeginIterator ( IteratorState& it ) const
|
||||
{
|
||||
it.array_ = const_cast<ValueInternalArray *>( this );
|
||||
it.currentItemIndex_ = 0;
|
||||
it.currentPageIndex_ = pages_;
|
||||
it.array_ = const_cast<ValueInternalArray*> ( this );
|
||||
it.currentItemIndex_ = 0;
|
||||
it.currentPageIndex_ = pages_;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ValueInternalArray::makeIterator( IteratorState &it, ArrayIndex index ) const
|
||||
ValueInternalArray::makeIterator ( IteratorState& it, ArrayIndex index ) const
|
||||
{
|
||||
it.array_ = const_cast<ValueInternalArray *>( this );
|
||||
it.currentItemIndex_ = index % itemsPerPage;
|
||||
it.currentPageIndex_ = pages_ + index / itemsPerPage;
|
||||
it.array_ = const_cast<ValueInternalArray*> ( this );
|
||||
it.currentItemIndex_ = index % itemsPerPage;
|
||||
it.currentPageIndex_ = pages_ + index / itemsPerPage;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ValueInternalArray::makeEndIterator( IteratorState &it ) const
|
||||
ValueInternalArray::makeEndIterator ( IteratorState& it ) const
|
||||
{
|
||||
makeIterator( it, size_ );
|
||||
makeIterator ( it, size_ );
|
||||
}
|
||||
|
||||
|
||||
ValueInternalArray::ValueInternalArray()
|
||||
: pages_( 0 )
|
||||
, size_( 0 )
|
||||
, pageCount_( 0 )
|
||||
ValueInternalArray::ValueInternalArray ()
|
||||
: pages_ ( 0 )
|
||||
, size_ ( 0 )
|
||||
, pageCount_ ( 0 )
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
ValueInternalArray::ValueInternalArray( const ValueInternalArray &other )
|
||||
: pages_( 0 )
|
||||
, pageCount_( 0 )
|
||||
, size_( other.size_ )
|
||||
ValueInternalArray::ValueInternalArray ( const ValueInternalArray& other )
|
||||
: pages_ ( 0 )
|
||||
, pageCount_ ( 0 )
|
||||
, size_ ( other.size_ )
|
||||
{
|
||||
PageIndex minNewPages = other.size_ / itemsPerPage;
|
||||
arrayAllocator()->reallocateArrayPageIndex( pages_, pageCount_, minNewPages );
|
||||
JSON_ASSERT_MESSAGE( pageCount_ >= minNewPages,
|
||||
"ValueInternalArray::reserve(): bad reallocation" );
|
||||
IteratorState itOther;
|
||||
other.makeBeginIterator( itOther );
|
||||
Value *value;
|
||||
for ( ArrayIndex index = 0; index < size_; ++index, increment(itOther) )
|
||||
{
|
||||
if ( index % itemsPerPage == 0 )
|
||||
{
|
||||
PageIndex pageIndex = index / itemsPerPage;
|
||||
value = arrayAllocator()->allocateArrayPage();
|
||||
pages_[pageIndex] = value;
|
||||
}
|
||||
new (value) Value( dereference( itOther ) );
|
||||
}
|
||||
PageIndex minNewPages = other.size_ / itemsPerPage;
|
||||
arrayAllocator ()->reallocateArrayPageIndex ( pages_, pageCount_, minNewPages );
|
||||
JSON_ASSERT_MESSAGE ( pageCount_ >= minNewPages,
|
||||
"ValueInternalArray::reserve(): bad reallocation" );
|
||||
IteratorState itOther;
|
||||
other.makeBeginIterator ( itOther );
|
||||
Value* value;
|
||||
|
||||
for ( ArrayIndex index = 0; index < size_; ++index, increment (itOther) )
|
||||
{
|
||||
if ( index % itemsPerPage == 0 )
|
||||
{
|
||||
PageIndex pageIndex = index / itemsPerPage;
|
||||
value = arrayAllocator ()->allocateArrayPage ();
|
||||
pages_[pageIndex] = value;
|
||||
}
|
||||
|
||||
new (value) Value ( dereference ( itOther ) );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ValueInternalArray &
|
||||
ValueInternalArray::operator =( const ValueInternalArray &other )
|
||||
ValueInternalArray&
|
||||
ValueInternalArray::operator = ( const ValueInternalArray& other )
|
||||
{
|
||||
ValueInternalArray temp( other );
|
||||
swap( temp );
|
||||
return *this;
|
||||
ValueInternalArray temp ( other );
|
||||
swap ( temp );
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
ValueInternalArray::~ValueInternalArray()
|
||||
ValueInternalArray::~ValueInternalArray ()
|
||||
{
|
||||
// destroy all constructed items
|
||||
IteratorState it;
|
||||
IteratorState itEnd;
|
||||
makeBeginIterator( it);
|
||||
makeEndIterator( itEnd );
|
||||
for ( ; !equals(it,itEnd); increment(it) )
|
||||
{
|
||||
Value *value = &dereference(it);
|
||||
value->~Value();
|
||||
}
|
||||
// release all pages
|
||||
PageIndex lastPageIndex = size_ / itemsPerPage;
|
||||
for ( PageIndex pageIndex = 0; pageIndex < lastPageIndex; ++pageIndex )
|
||||
arrayAllocator()->releaseArrayPage( pages_[pageIndex] );
|
||||
// release pages index
|
||||
arrayAllocator()->releaseArrayPageIndex( pages_, pageCount_ );
|
||||
// destroy all constructed items
|
||||
IteratorState it;
|
||||
IteratorState itEnd;
|
||||
makeBeginIterator ( it);
|
||||
makeEndIterator ( itEnd );
|
||||
|
||||
for ( ; !equals (it, itEnd); increment (it) )
|
||||
{
|
||||
Value* value = &dereference (it);
|
||||
value->~Value ();
|
||||
}
|
||||
|
||||
// release all pages
|
||||
PageIndex lastPageIndex = size_ / itemsPerPage;
|
||||
|
||||
for ( PageIndex pageIndex = 0; pageIndex < lastPageIndex; ++pageIndex )
|
||||
arrayAllocator ()->releaseArrayPage ( pages_[pageIndex] );
|
||||
|
||||
// release pages index
|
||||
arrayAllocator ()->releaseArrayPageIndex ( pages_, pageCount_ );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ValueInternalArray::swap( ValueInternalArray &other )
|
||||
ValueInternalArray::swap ( ValueInternalArray& other )
|
||||
{
|
||||
Value **tempPages = pages_;
|
||||
pages_ = other.pages_;
|
||||
other.pages_ = tempPages;
|
||||
ArrayIndex tempSize = size_;
|
||||
size_ = other.size_;
|
||||
other.size_ = tempSize;
|
||||
PageIndex tempPageCount = pageCount_;
|
||||
pageCount_ = other.pageCount_;
|
||||
other.pageCount_ = tempPageCount;
|
||||
Value** tempPages = pages_;
|
||||
pages_ = other.pages_;
|
||||
other.pages_ = tempPages;
|
||||
ArrayIndex tempSize = size_;
|
||||
size_ = other.size_;
|
||||
other.size_ = tempSize;
|
||||
PageIndex tempPageCount = pageCount_;
|
||||
pageCount_ = other.pageCount_;
|
||||
other.pageCount_ = tempPageCount;
|
||||
}
|
||||
|
||||
void
|
||||
ValueInternalArray::clear()
|
||||
ValueInternalArray::clear ()
|
||||
{
|
||||
ValueInternalArray dummy;
|
||||
swap( dummy );
|
||||
ValueInternalArray dummy;
|
||||
swap ( dummy );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ValueInternalArray::resize( ArrayIndex newSize )
|
||||
ValueInternalArray::resize ( ArrayIndex newSize )
|
||||
{
|
||||
if ( newSize == 0 )
|
||||
clear();
|
||||
else if ( newSize < size_ )
|
||||
{
|
||||
IteratorState it;
|
||||
IteratorState itEnd;
|
||||
makeIterator( it, newSize );
|
||||
makeIterator( itEnd, size_ );
|
||||
for ( ; !equals(it,itEnd); increment(it) )
|
||||
{
|
||||
Value *value = &dereference(it);
|
||||
value->~Value();
|
||||
}
|
||||
PageIndex pageIndex = (newSize + itemsPerPage - 1) / itemsPerPage;
|
||||
PageIndex lastPageIndex = size_ / itemsPerPage;
|
||||
for ( ; pageIndex < lastPageIndex; ++pageIndex )
|
||||
arrayAllocator()->releaseArrayPage( pages_[pageIndex] );
|
||||
size_ = newSize;
|
||||
}
|
||||
else if ( newSize > size_ )
|
||||
resolveReference( newSize );
|
||||
if ( newSize == 0 )
|
||||
clear ();
|
||||
else if ( newSize < size_ )
|
||||
{
|
||||
IteratorState it;
|
||||
IteratorState itEnd;
|
||||
makeIterator ( it, newSize );
|
||||
makeIterator ( itEnd, size_ );
|
||||
|
||||
for ( ; !equals (it, itEnd); increment (it) )
|
||||
{
|
||||
Value* value = &dereference (it);
|
||||
value->~Value ();
|
||||
}
|
||||
|
||||
PageIndex pageIndex = (newSize + itemsPerPage - 1) / itemsPerPage;
|
||||
PageIndex lastPageIndex = size_ / itemsPerPage;
|
||||
|
||||
for ( ; pageIndex < lastPageIndex; ++pageIndex )
|
||||
arrayAllocator ()->releaseArrayPage ( pages_[pageIndex] );
|
||||
|
||||
size_ = newSize;
|
||||
}
|
||||
else if ( newSize > size_ )
|
||||
resolveReference ( newSize );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ValueInternalArray::makeIndexValid( ArrayIndex index )
|
||||
ValueInternalArray::makeIndexValid ( ArrayIndex index )
|
||||
{
|
||||
// Need to enlarge page index ?
|
||||
if ( index >= pageCount_ * itemsPerPage )
|
||||
{
|
||||
PageIndex minNewPages = (index + 1) / itemsPerPage;
|
||||
arrayAllocator()->reallocateArrayPageIndex( pages_, pageCount_, minNewPages );
|
||||
JSON_ASSERT_MESSAGE( pageCount_ >= minNewPages, "ValueInternalArray::reserve(): bad reallocation" );
|
||||
}
|
||||
// Need to enlarge page index ?
|
||||
if ( index >= pageCount_ * itemsPerPage )
|
||||
{
|
||||
PageIndex minNewPages = (index + 1) / itemsPerPage;
|
||||
arrayAllocator ()->reallocateArrayPageIndex ( pages_, pageCount_, minNewPages );
|
||||
JSON_ASSERT_MESSAGE ( pageCount_ >= minNewPages, "ValueInternalArray::reserve(): bad reallocation" );
|
||||
}
|
||||
|
||||
// Need to allocate new pages ?
|
||||
ArrayIndex nextPageIndex =
|
||||
(size_ % itemsPerPage) != 0 ? size_ - (size_%itemsPerPage) + itemsPerPage
|
||||
: size_;
|
||||
if ( nextPageIndex <= index )
|
||||
{
|
||||
PageIndex pageIndex = nextPageIndex / itemsPerPage;
|
||||
PageIndex pageToAllocate = (index - nextPageIndex) / itemsPerPage + 1;
|
||||
for ( ; pageToAllocate-- > 0; ++pageIndex )
|
||||
pages_[pageIndex] = arrayAllocator()->allocateArrayPage();
|
||||
}
|
||||
// Need to allocate new pages ?
|
||||
ArrayIndex nextPageIndex =
|
||||
(size_ % itemsPerPage) != 0 ? size_ - (size_ % itemsPerPage) + itemsPerPage
|
||||
: size_;
|
||||
|
||||
// Initialize all new entries
|
||||
IteratorState it;
|
||||
IteratorState itEnd;
|
||||
makeIterator( it, size_ );
|
||||
size_ = index + 1;
|
||||
makeIterator( itEnd, size_ );
|
||||
for ( ; !equals(it,itEnd); increment(it) )
|
||||
{
|
||||
Value *value = &dereference(it);
|
||||
new (value) Value(); // Construct a default value using placement new
|
||||
}
|
||||
if ( nextPageIndex <= index )
|
||||
{
|
||||
PageIndex pageIndex = nextPageIndex / itemsPerPage;
|
||||
PageIndex pageToAllocate = (index - nextPageIndex) / itemsPerPage + 1;
|
||||
|
||||
for ( ; pageToAllocate-- > 0; ++pageIndex )
|
||||
pages_[pageIndex] = arrayAllocator ()->allocateArrayPage ();
|
||||
}
|
||||
|
||||
// Initialize all new entries
|
||||
IteratorState it;
|
||||
IteratorState itEnd;
|
||||
makeIterator ( it, size_ );
|
||||
size_ = index + 1;
|
||||
makeIterator ( itEnd, size_ );
|
||||
|
||||
for ( ; !equals (it, itEnd); increment (it) )
|
||||
{
|
||||
Value* value = &dereference (it);
|
||||
new (value) Value (); // Construct a default value using placement new
|
||||
}
|
||||
}
|
||||
|
||||
Value &
|
||||
ValueInternalArray::resolveReference( ArrayIndex index )
|
||||
Value&
|
||||
ValueInternalArray::resolveReference ( ArrayIndex index )
|
||||
{
|
||||
if ( index >= size_ )
|
||||
makeIndexValid( index );
|
||||
return pages_[index/itemsPerPage][index%itemsPerPage];
|
||||
if ( index >= size_ )
|
||||
makeIndexValid ( index );
|
||||
|
||||
return pages_[index / itemsPerPage][index % itemsPerPage];
|
||||
}
|
||||
|
||||
Value *
|
||||
ValueInternalArray::find( ArrayIndex index ) const
|
||||
Value*
|
||||
ValueInternalArray::find ( ArrayIndex index ) const
|
||||
{
|
||||
if ( index >= size_ )
|
||||
return 0;
|
||||
return &(pages_[index/itemsPerPage][index%itemsPerPage]);
|
||||
if ( index >= size_ )
|
||||
return 0;
|
||||
|
||||
return & (pages_[index / itemsPerPage][index % itemsPerPage]);
|
||||
}
|
||||
|
||||
ValueInternalArray::ArrayIndex
|
||||
ValueInternalArray::size() const
|
||||
ValueInternalArray::size () const
|
||||
{
|
||||
return size_;
|
||||
return size_;
|
||||
}
|
||||
|
||||
int
|
||||
ValueInternalArray::distance( const IteratorState &x, const IteratorState &y )
|
||||
ValueInternalArray::distance ( const IteratorState& x, const IteratorState& y )
|
||||
{
|
||||
return indexOf(y) - indexOf(x);
|
||||
return indexOf (y) - indexOf (x);
|
||||
}
|
||||
|
||||
|
||||
ValueInternalArray::ArrayIndex
|
||||
ValueInternalArray::indexOf( const IteratorState &iterator )
|
||||
ValueInternalArray::indexOf ( const IteratorState& iterator )
|
||||
{
|
||||
if ( !iterator.array_ )
|
||||
return ArrayIndex(-1);
|
||||
return ArrayIndex(
|
||||
(iterator.currentPageIndex_ - iterator.array_->pages_) * itemsPerPage
|
||||
+ iterator.currentItemIndex_ );
|
||||
if ( !iterator.array_ )
|
||||
return ArrayIndex (-1);
|
||||
|
||||
return ArrayIndex (
|
||||
(iterator.currentPageIndex_ - iterator.array_->pages_) * itemsPerPage
|
||||
+ iterator.currentItemIndex_ );
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
ValueInternalArray::compare( const ValueInternalArray &other ) const
|
||||
ValueInternalArray::compare ( const ValueInternalArray& other ) const
|
||||
{
|
||||
int sizeDiff( size_ - other.size_ );
|
||||
if ( sizeDiff != 0 )
|
||||
return sizeDiff;
|
||||
int sizeDiff ( size_ - other.size_ );
|
||||
|
||||
for ( ArrayIndex index =0; index < size_; ++index )
|
||||
{
|
||||
int diff = pages_[index/itemsPerPage][index%itemsPerPage].compare(
|
||||
other.pages_[index/itemsPerPage][index%itemsPerPage] );
|
||||
if ( diff != 0 )
|
||||
return diff;
|
||||
}
|
||||
return 0;
|
||||
if ( sizeDiff != 0 )
|
||||
return sizeDiff;
|
||||
|
||||
for ( ArrayIndex index = 0; index < size_; ++index )
|
||||
{
|
||||
int diff = pages_[index / itemsPerPage][index % itemsPerPage].compare (
|
||||
other.pages_[index / itemsPerPage][index % itemsPerPage] );
|
||||
|
||||
if ( diff != 0 )
|
||||
return diff;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,188 +1,189 @@
|
||||
#ifndef CPPTL_JSON_READER_H_INCLUDED
|
||||
# define CPPTL_JSON_READER_H_INCLUDED
|
||||
|
||||
namespace Json {
|
||||
namespace Json
|
||||
{
|
||||
|
||||
/** \brief Unserialize a <a HREF="http://www.json.org">JSON</a> document into a Value.
|
||||
*
|
||||
*/
|
||||
class JSON_API Reader
|
||||
{
|
||||
public:
|
||||
typedef char Char;
|
||||
typedef const Char *Location;
|
||||
/** \brief Unserialize a <a HREF="http://www.json.org">JSON</a> document into a Value.
|
||||
*
|
||||
*/
|
||||
class JSON_API Reader
|
||||
{
|
||||
public:
|
||||
typedef char Char;
|
||||
typedef const Char* Location;
|
||||
|
||||
/** \brief Constructs a Reader allowing all features
|
||||
* for parsing.
|
||||
*/
|
||||
Reader();
|
||||
/** \brief Constructs a Reader allowing all features
|
||||
* for parsing.
|
||||
*/
|
||||
Reader ();
|
||||
|
||||
/** \brief Constructs a Reader allowing the specified feature set
|
||||
* for parsing.
|
||||
*/
|
||||
Reader( const Features &features );
|
||||
/** \brief Constructs a Reader allowing the specified feature set
|
||||
* for parsing.
|
||||
*/
|
||||
Reader ( const Features& features );
|
||||
|
||||
/** \brief Read a Value from a <a HREF="http://www.json.org">JSON</a> document.
|
||||
* \param document UTF-8 encoded string containing the document to read.
|
||||
* \param root [out] Contains the root value of the document if it was
|
||||
* successfully parsed.
|
||||
* \param collectComments \c true to collect comment and allow writing them back during
|
||||
* serialization, \c false to discard comments.
|
||||
* This parameter is ignored if Features::allowComments_
|
||||
* is \c false.
|
||||
* \return \c true if the document was successfully parsed, \c false if an error occurred.
|
||||
*/
|
||||
bool parse( const std::string &document,
|
||||
Value &root,
|
||||
bool collectComments = true );
|
||||
/** \brief Read a Value from a <a HREF="http://www.json.org">JSON</a> document.
|
||||
* \param document UTF-8 encoded string containing the document to read.
|
||||
* \param root [out] Contains the root value of the document if it was
|
||||
* successfully parsed.
|
||||
* \param collectComments \c true to collect comment and allow writing them back during
|
||||
* serialization, \c false to discard comments.
|
||||
* This parameter is ignored if Features::allowComments_
|
||||
* is \c false.
|
||||
* \return \c true if the document was successfully parsed, \c false if an error occurred.
|
||||
*/
|
||||
bool parse ( const std::string& document,
|
||||
Value& root,
|
||||
bool collectComments = true );
|
||||
|
||||
/** \brief Read a Value from a <a HREF="http://www.json.org">JSON</a> document.
|
||||
* \param document UTF-8 encoded string containing the document to read.
|
||||
* \param root [out] Contains the root value of the document if it was
|
||||
* successfully parsed.
|
||||
* \param collectComments \c true to collect comment and allow writing them back during
|
||||
* serialization, \c false to discard comments.
|
||||
* This parameter is ignored if Features::allowComments_
|
||||
* is \c false.
|
||||
* \return \c true if the document was successfully parsed, \c false if an error occurred.
|
||||
*/
|
||||
bool parse( const char *beginDoc, const char *endDoc,
|
||||
Value &root,
|
||||
bool collectComments = true );
|
||||
/** \brief Read a Value from a <a HREF="http://www.json.org">JSON</a> document.
|
||||
* \param document UTF-8 encoded string containing the document to read.
|
||||
* \param root [out] Contains the root value of the document if it was
|
||||
* successfully parsed.
|
||||
* \param collectComments \c true to collect comment and allow writing them back during
|
||||
* serialization, \c false to discard comments.
|
||||
* This parameter is ignored if Features::allowComments_
|
||||
* is \c false.
|
||||
* \return \c true if the document was successfully parsed, \c false if an error occurred.
|
||||
*/
|
||||
bool parse ( const char* beginDoc, const char* endDoc,
|
||||
Value& root,
|
||||
bool collectComments = true );
|
||||
|
||||
/// \brief Parse from input stream.
|
||||
/// \see Json::operator>>(std::istream&, Json::Value&).
|
||||
bool parse( std::istream &is,
|
||||
Value &root,
|
||||
bool collectComments = true );
|
||||
/// \brief Parse from input stream.
|
||||
/// \see Json::operator>>(std::istream&, Json::Value&).
|
||||
bool parse ( std::istream& is,
|
||||
Value& root,
|
||||
bool collectComments = true );
|
||||
|
||||
/** \brief Returns a user friendly string that list errors in the parsed document.
|
||||
* \return Formatted error message with the list of errors with their location in
|
||||
* the parsed document. An empty string is returned if no error occurred
|
||||
* during parsing.
|
||||
*/
|
||||
std::string getFormatedErrorMessages() const;
|
||||
/** \brief Returns a user friendly string that list errors in the parsed document.
|
||||
* \return Formatted error message with the list of errors with their location in
|
||||
* the parsed document. An empty string is returned if no error occurred
|
||||
* during parsing.
|
||||
*/
|
||||
std::string getFormatedErrorMessages () const;
|
||||
|
||||
private:
|
||||
enum TokenType
|
||||
{
|
||||
tokenEndOfStream = 0,
|
||||
tokenObjectBegin,
|
||||
tokenObjectEnd,
|
||||
tokenArrayBegin,
|
||||
tokenArrayEnd,
|
||||
tokenString,
|
||||
tokenNumber,
|
||||
tokenTrue,
|
||||
tokenFalse,
|
||||
tokenNull,
|
||||
tokenArraySeparator,
|
||||
tokenMemberSeparator,
|
||||
tokenComment,
|
||||
tokenError
|
||||
};
|
||||
|
||||
class Token
|
||||
{
|
||||
public:
|
||||
TokenType type_;
|
||||
Location start_;
|
||||
Location end_;
|
||||
};
|
||||
|
||||
class ErrorInfo
|
||||
{
|
||||
public:
|
||||
Token token_;
|
||||
std::string message_;
|
||||
Location extra_;
|
||||
};
|
||||
|
||||
typedef std::deque<ErrorInfo> Errors;
|
||||
|
||||
bool expectToken( TokenType type, Token &token, const char *message );
|
||||
bool readToken( Token &token );
|
||||
void skipSpaces();
|
||||
bool match( Location pattern,
|
||||
int patternLength );
|
||||
bool readComment();
|
||||
bool readCStyleComment();
|
||||
bool readCppStyleComment();
|
||||
bool readString();
|
||||
void readNumber();
|
||||
bool readValue();
|
||||
bool readObject( Token &token );
|
||||
bool readArray( Token &token );
|
||||
bool decodeNumber( Token &token );
|
||||
bool decodeString( Token &token );
|
||||
bool decodeString( Token &token, std::string &decoded );
|
||||
bool decodeDouble( Token &token );
|
||||
bool decodeUnicodeCodePoint( Token &token,
|
||||
Location ¤t,
|
||||
Location end,
|
||||
unsigned int &unicode );
|
||||
bool decodeUnicodeEscapeSequence( Token &token,
|
||||
Location ¤t,
|
||||
Location end,
|
||||
unsigned int &unicode );
|
||||
bool addError( const std::string &message,
|
||||
Token &token,
|
||||
Location extra = 0 );
|
||||
bool recoverFromError( TokenType skipUntilToken );
|
||||
bool addErrorAndRecover( const std::string &message,
|
||||
Token &token,
|
||||
TokenType skipUntilToken );
|
||||
void skipUntilSpace();
|
||||
Value ¤tValue();
|
||||
Char getNextChar();
|
||||
void getLocationLineAndColumn( Location location,
|
||||
int &line,
|
||||
int &column ) const;
|
||||
std::string getLocationLineAndColumn( Location location ) const;
|
||||
void addComment( Location begin,
|
||||
Location end,
|
||||
CommentPlacement placement );
|
||||
void skipCommentTokens( Token &token );
|
||||
|
||||
typedef std::stack<Value *> Nodes;
|
||||
Nodes nodes_;
|
||||
Errors errors_;
|
||||
std::string document_;
|
||||
Location begin_;
|
||||
Location end_;
|
||||
Location current_;
|
||||
Location lastValueEnd_;
|
||||
Value *lastValue_;
|
||||
std::string commentsBefore_;
|
||||
Features features_;
|
||||
bool collectComments_;
|
||||
};
|
||||
|
||||
/** \brief Read from 'sin' into 'root'.
|
||||
|
||||
Always keep comments from the input JSON.
|
||||
|
||||
This can be used to read a file into a particular sub-object.
|
||||
For example:
|
||||
\code
|
||||
Json::Value root;
|
||||
cin >> root["dir"]["file"];
|
||||
cout << root;
|
||||
\endcode
|
||||
Result:
|
||||
\verbatim
|
||||
private:
|
||||
enum TokenType
|
||||
{
|
||||
"dir": {
|
||||
"file": {
|
||||
// The input stream JSON would be nested here.
|
||||
}
|
||||
}
|
||||
tokenEndOfStream = 0,
|
||||
tokenObjectBegin,
|
||||
tokenObjectEnd,
|
||||
tokenArrayBegin,
|
||||
tokenArrayEnd,
|
||||
tokenString,
|
||||
tokenNumber,
|
||||
tokenTrue,
|
||||
tokenFalse,
|
||||
tokenNull,
|
||||
tokenArraySeparator,
|
||||
tokenMemberSeparator,
|
||||
tokenComment,
|
||||
tokenError
|
||||
};
|
||||
|
||||
class Token
|
||||
{
|
||||
public:
|
||||
TokenType type_;
|
||||
Location start_;
|
||||
Location end_;
|
||||
};
|
||||
|
||||
class ErrorInfo
|
||||
{
|
||||
public:
|
||||
Token token_;
|
||||
std::string message_;
|
||||
Location extra_;
|
||||
};
|
||||
|
||||
typedef std::deque<ErrorInfo> Errors;
|
||||
|
||||
bool expectToken ( TokenType type, Token& token, const char* message );
|
||||
bool readToken ( Token& token );
|
||||
void skipSpaces ();
|
||||
bool match ( Location pattern,
|
||||
int patternLength );
|
||||
bool readComment ();
|
||||
bool readCStyleComment ();
|
||||
bool readCppStyleComment ();
|
||||
bool readString ();
|
||||
void readNumber ();
|
||||
bool readValue ();
|
||||
bool readObject ( Token& token );
|
||||
bool readArray ( Token& token );
|
||||
bool decodeNumber ( Token& token );
|
||||
bool decodeString ( Token& token );
|
||||
bool decodeString ( Token& token, std::string& decoded );
|
||||
bool decodeDouble ( Token& token );
|
||||
bool decodeUnicodeCodePoint ( Token& token,
|
||||
Location& current,
|
||||
Location end,
|
||||
unsigned int& unicode );
|
||||
bool decodeUnicodeEscapeSequence ( Token& token,
|
||||
Location& current,
|
||||
Location end,
|
||||
unsigned int& unicode );
|
||||
bool addError ( const std::string& message,
|
||||
Token& token,
|
||||
Location extra = 0 );
|
||||
bool recoverFromError ( TokenType skipUntilToken );
|
||||
bool addErrorAndRecover ( const std::string& message,
|
||||
Token& token,
|
||||
TokenType skipUntilToken );
|
||||
void skipUntilSpace ();
|
||||
Value& currentValue ();
|
||||
Char getNextChar ();
|
||||
void getLocationLineAndColumn ( Location location,
|
||||
int& line,
|
||||
int& column ) const;
|
||||
std::string getLocationLineAndColumn ( Location location ) const;
|
||||
void addComment ( Location begin,
|
||||
Location end,
|
||||
CommentPlacement placement );
|
||||
void skipCommentTokens ( Token& token );
|
||||
|
||||
typedef std::stack<Value*> Nodes;
|
||||
Nodes nodes_;
|
||||
Errors errors_;
|
||||
std::string document_;
|
||||
Location begin_;
|
||||
Location end_;
|
||||
Location current_;
|
||||
Location lastValueEnd_;
|
||||
Value* lastValue_;
|
||||
std::string commentsBefore_;
|
||||
Features features_;
|
||||
bool collectComments_;
|
||||
};
|
||||
|
||||
/** \brief Read from 'sin' into 'root'.
|
||||
|
||||
Always keep comments from the input JSON.
|
||||
|
||||
This can be used to read a file into a particular sub-object.
|
||||
For example:
|
||||
\code
|
||||
Json::Value root;
|
||||
cin >> root["dir"]["file"];
|
||||
cout << root;
|
||||
\endcode
|
||||
Result:
|
||||
\verbatim
|
||||
{
|
||||
"dir": {
|
||||
"file": {
|
||||
// The input stream JSON would be nested here.
|
||||
}
|
||||
\endverbatim
|
||||
\throw std::exception on parse error.
|
||||
\see Json::operator<<()
|
||||
*/
|
||||
std::istream& operator>>( std::istream&, Value& );
|
||||
}
|
||||
}
|
||||
\endverbatim
|
||||
\throw std::exception on parse error.
|
||||
\see Json::operator<<()
|
||||
*/
|
||||
std::istream& operator>> ( std::istream&, Value& );
|
||||
|
||||
} // namespace Json
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -10,198 +10,229 @@
|
||||
// //////////////////////////////////////////////////////////////////
|
||||
// //////////////////////////////////////////////////////////////////
|
||||
|
||||
ValueIteratorBase::ValueIteratorBase()
|
||||
ValueIteratorBase::ValueIteratorBase ()
|
||||
#ifndef JSON_VALUE_USE_INTERNAL_MAP
|
||||
: current_()
|
||||
, isNull_( true )
|
||||
: current_ ()
|
||||
, isNull_ ( true )
|
||||
{
|
||||
}
|
||||
#else
|
||||
: isArray_( true )
|
||||
, isNull_( true )
|
||||
:
|
||||
isArray_ ( true )
|
||||
, isNull_ ( true )
|
||||
{
|
||||
iterator_.array_ = ValueInternalArray::IteratorState();
|
||||
iterator_.array_ = ValueInternalArray::IteratorState ();
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef JSON_VALUE_USE_INTERNAL_MAP
|
||||
ValueIteratorBase::ValueIteratorBase( const Value::ObjectValues::iterator ¤t )
|
||||
: current_( current )
|
||||
, isNull_( false )
|
||||
ValueIteratorBase::ValueIteratorBase ( const Value::ObjectValues::iterator& current )
|
||||
: current_ ( current )
|
||||
, isNull_ ( false )
|
||||
{
|
||||
}
|
||||
#else
|
||||
ValueIteratorBase::ValueIteratorBase( const ValueInternalArray::IteratorState &state )
|
||||
: isArray_( true )
|
||||
ValueIteratorBase::ValueIteratorBase ( const ValueInternalArray::IteratorState& state )
|
||||
: isArray_ ( true )
|
||||
{
|
||||
iterator_.array_ = state;
|
||||
iterator_.array_ = state;
|
||||
}
|
||||
|
||||
|
||||
ValueIteratorBase::ValueIteratorBase( const ValueInternalMap::IteratorState &state )
|
||||
: isArray_( false )
|
||||
ValueIteratorBase::ValueIteratorBase ( const ValueInternalMap::IteratorState& state )
|
||||
: isArray_ ( false )
|
||||
{
|
||||
iterator_.map_ = state;
|
||||
iterator_.map_ = state;
|
||||
}
|
||||
#endif
|
||||
|
||||
Value &
|
||||
ValueIteratorBase::deref() const
|
||||
Value&
|
||||
ValueIteratorBase::deref () const
|
||||
{
|
||||
#ifndef JSON_VALUE_USE_INTERNAL_MAP
|
||||
return current_->second;
|
||||
return current_->second;
|
||||
#else
|
||||
if ( isArray_ )
|
||||
return ValueInternalArray::dereference( iterator_.array_ );
|
||||
return ValueInternalMap::value( iterator_.map_ );
|
||||
|
||||
if ( isArray_ )
|
||||
return ValueInternalArray::dereference ( iterator_.array_ );
|
||||
|
||||
return ValueInternalMap::value ( iterator_.map_ );
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ValueIteratorBase::increment()
|
||||
ValueIteratorBase::increment ()
|
||||
{
|
||||
#ifndef JSON_VALUE_USE_INTERNAL_MAP
|
||||
++current_;
|
||||
++current_;
|
||||
#else
|
||||
if ( isArray_ )
|
||||
ValueInternalArray::increment( iterator_.array_ );
|
||||
ValueInternalMap::increment( iterator_.map_ );
|
||||
|
||||
if ( isArray_ )
|
||||
ValueInternalArray::increment ( iterator_.array_ );
|
||||
|
||||
ValueInternalMap::increment ( iterator_.map_ );
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ValueIteratorBase::decrement()
|
||||
ValueIteratorBase::decrement ()
|
||||
{
|
||||
#ifndef JSON_VALUE_USE_INTERNAL_MAP
|
||||
--current_;
|
||||
--current_;
|
||||
#else
|
||||
if ( isArray_ )
|
||||
ValueInternalArray::decrement( iterator_.array_ );
|
||||
ValueInternalMap::decrement( iterator_.map_ );
|
||||
|
||||
if ( isArray_ )
|
||||
ValueInternalArray::decrement ( iterator_.array_ );
|
||||
|
||||
ValueInternalMap::decrement ( iterator_.map_ );
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
ValueIteratorBase::difference_type
|
||||
ValueIteratorBase::computeDistance( const SelfType &other ) const
|
||||
ValueIteratorBase::computeDistance ( const SelfType& other ) const
|
||||
{
|
||||
#ifndef JSON_VALUE_USE_INTERNAL_MAP
|
||||
# ifdef JSON_USE_CPPTL_SMALLMAP
|
||||
return current_ - other.current_;
|
||||
return current_ - other.current_;
|
||||
# else
|
||||
// Iterator for null value are initialized using the default
|
||||
// constructor, which initialize current_ to the default
|
||||
// std::map::iterator. As begin() and end() are two instance
|
||||
// of the default std::map::iterator, they can not be compared.
|
||||
// To allow this, we handle this comparison specifically.
|
||||
if ( isNull_ && other.isNull_ )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Iterator for null value are initialized using the default
|
||||
// constructor, which initialize current_ to the default
|
||||
// std::map::iterator. As begin() and end() are two instance
|
||||
// of the default std::map::iterator, they can not be compared.
|
||||
// To allow this, we handle this comparison specifically.
|
||||
if ( isNull_ && other.isNull_ )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// Usage of std::distance is not portable (does not compile with Sun Studio 12 RogueWave STL,
|
||||
// which is the one used by default).
|
||||
// Using a portable hand-made version for non random iterator instead:
|
||||
// return difference_type( std::distance( current_, other.current_ ) );
|
||||
difference_type myDistance = 0;
|
||||
for ( Value::ObjectValues::iterator it = current_; it != other.current_; ++it )
|
||||
{
|
||||
++myDistance;
|
||||
}
|
||||
return myDistance;
|
||||
// Usage of std::distance is not portable (does not compile with Sun Studio 12 RogueWave STL,
|
||||
// which is the one used by default).
|
||||
// Using a portable hand-made version for non random iterator instead:
|
||||
// return difference_type( std::distance( current_, other.current_ ) );
|
||||
difference_type myDistance = 0;
|
||||
|
||||
for ( Value::ObjectValues::iterator it = current_; it != other.current_; ++it )
|
||||
{
|
||||
++myDistance;
|
||||
}
|
||||
|
||||
return myDistance;
|
||||
# endif
|
||||
#else
|
||||
if ( isArray_ )
|
||||
return ValueInternalArray::distance( iterator_.array_, other.iterator_.array_ );
|
||||
return ValueInternalMap::distance( iterator_.map_, other.iterator_.map_ );
|
||||
|
||||
if ( isArray_ )
|
||||
return ValueInternalArray::distance ( iterator_.array_, other.iterator_.array_ );
|
||||
|
||||
return ValueInternalMap::distance ( iterator_.map_, other.iterator_.map_ );
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
ValueIteratorBase::isEqual( const SelfType &other ) const
|
||||
ValueIteratorBase::isEqual ( const SelfType& other ) const
|
||||
{
|
||||
#ifndef JSON_VALUE_USE_INTERNAL_MAP
|
||||
if ( isNull_ )
|
||||
{
|
||||
return other.isNull_;
|
||||
}
|
||||
return current_ == other.current_;
|
||||
|
||||
if ( isNull_ )
|
||||
{
|
||||
return other.isNull_;
|
||||
}
|
||||
|
||||
return current_ == other.current_;
|
||||
#else
|
||||
if ( isArray_ )
|
||||
return ValueInternalArray::equals( iterator_.array_, other.iterator_.array_ );
|
||||
return ValueInternalMap::equals( iterator_.map_, other.iterator_.map_ );
|
||||
|
||||
if ( isArray_ )
|
||||
return ValueInternalArray::equals ( iterator_.array_, other.iterator_.array_ );
|
||||
|
||||
return ValueInternalMap::equals ( iterator_.map_, other.iterator_.map_ );
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ValueIteratorBase::copy( const SelfType &other )
|
||||
ValueIteratorBase::copy ( const SelfType& other )
|
||||
{
|
||||
#ifndef JSON_VALUE_USE_INTERNAL_MAP
|
||||
current_ = other.current_;
|
||||
current_ = other.current_;
|
||||
#else
|
||||
if ( isArray_ )
|
||||
iterator_.array_ = other.iterator_.array_;
|
||||
iterator_.map_ = other.iterator_.map_;
|
||||
|
||||
if ( isArray_ )
|
||||
iterator_.array_ = other.iterator_.array_;
|
||||
|
||||
iterator_.map_ = other.iterator_.map_;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
Value
|
||||
ValueIteratorBase::key() const
|
||||
ValueIteratorBase::key () const
|
||||
{
|
||||
#ifndef JSON_VALUE_USE_INTERNAL_MAP
|
||||
const Value::CZString czstring = (*current_).first;
|
||||
if ( czstring.c_str() )
|
||||
{
|
||||
if ( czstring.isStaticString() )
|
||||
return Value( StaticString( czstring.c_str() ) );
|
||||
return Value( czstring.c_str() );
|
||||
}
|
||||
return Value( czstring.index() );
|
||||
const Value::CZString czstring = (*current_).first;
|
||||
|
||||
if ( czstring.c_str () )
|
||||
{
|
||||
if ( czstring.isStaticString () )
|
||||
return Value ( StaticString ( czstring.c_str () ) );
|
||||
|
||||
return Value ( czstring.c_str () );
|
||||
}
|
||||
|
||||
return Value ( czstring.index () );
|
||||
#else
|
||||
if ( isArray_ )
|
||||
return Value( ValueInternalArray::indexOf( iterator_.array_ ) );
|
||||
bool isStatic;
|
||||
const char *memberName = ValueInternalMap::key( iterator_.map_, isStatic );
|
||||
if ( isStatic )
|
||||
return Value( StaticString( memberName ) );
|
||||
return Value( memberName );
|
||||
|
||||
if ( isArray_ )
|
||||
return Value ( ValueInternalArray::indexOf ( iterator_.array_ ) );
|
||||
|
||||
bool isStatic;
|
||||
const char* memberName = ValueInternalMap::key ( iterator_.map_, isStatic );
|
||||
|
||||
if ( isStatic )
|
||||
return Value ( StaticString ( memberName ) );
|
||||
|
||||
return Value ( memberName );
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
UInt
|
||||
ValueIteratorBase::index() const
|
||||
ValueIteratorBase::index () const
|
||||
{
|
||||
#ifndef JSON_VALUE_USE_INTERNAL_MAP
|
||||
const Value::CZString czstring = (*current_).first;
|
||||
if ( !czstring.c_str() )
|
||||
return czstring.index();
|
||||
return Value::UInt( -1 );
|
||||
const Value::CZString czstring = (*current_).first;
|
||||
|
||||
if ( !czstring.c_str () )
|
||||
return czstring.index ();
|
||||
|
||||
return Value::UInt ( -1 );
|
||||
#else
|
||||
if ( isArray_ )
|
||||
return Value::UInt( ValueInternalArray::indexOf( iterator_.array_ ) );
|
||||
return Value::UInt( -1 );
|
||||
|
||||
if ( isArray_ )
|
||||
return Value::UInt ( ValueInternalArray::indexOf ( iterator_.array_ ) );
|
||||
|
||||
return Value::UInt ( -1 );
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
const char *
|
||||
ValueIteratorBase::memberName() const
|
||||
const char*
|
||||
ValueIteratorBase::memberName () const
|
||||
{
|
||||
#ifndef JSON_VALUE_USE_INTERNAL_MAP
|
||||
const char *name = (*current_).first.c_str();
|
||||
return name ? name : "";
|
||||
const char* name = (*current_).first.c_str ();
|
||||
return name ? name : "";
|
||||
#else
|
||||
if ( !isArray_ )
|
||||
return ValueInternalMap::key( iterator_.map_ );
|
||||
return "";
|
||||
|
||||
if ( !isArray_ )
|
||||
return ValueInternalMap::key ( iterator_.map_ );
|
||||
|
||||
return "";
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -214,33 +245,33 @@ ValueIteratorBase::memberName() const
|
||||
// //////////////////////////////////////////////////////////////////
|
||||
// //////////////////////////////////////////////////////////////////
|
||||
|
||||
ValueConstIterator::ValueConstIterator()
|
||||
ValueConstIterator::ValueConstIterator ()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
#ifndef JSON_VALUE_USE_INTERNAL_MAP
|
||||
ValueConstIterator::ValueConstIterator( const Value::ObjectValues::iterator ¤t )
|
||||
: ValueIteratorBase( current )
|
||||
ValueConstIterator::ValueConstIterator ( const Value::ObjectValues::iterator& current )
|
||||
: ValueIteratorBase ( current )
|
||||
{
|
||||
}
|
||||
#else
|
||||
ValueConstIterator::ValueConstIterator( const ValueInternalArray::IteratorState &state )
|
||||
: ValueIteratorBase( state )
|
||||
ValueConstIterator::ValueConstIterator ( const ValueInternalArray::IteratorState& state )
|
||||
: ValueIteratorBase ( state )
|
||||
{
|
||||
}
|
||||
|
||||
ValueConstIterator::ValueConstIterator( const ValueInternalMap::IteratorState &state )
|
||||
: ValueIteratorBase( state )
|
||||
ValueConstIterator::ValueConstIterator ( const ValueInternalMap::IteratorState& state )
|
||||
: ValueIteratorBase ( state )
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
ValueConstIterator &
|
||||
ValueConstIterator::operator =( const ValueIteratorBase &other )
|
||||
ValueConstIterator&
|
||||
ValueConstIterator::operator = ( const ValueIteratorBase& other )
|
||||
{
|
||||
copy( other );
|
||||
return *this;
|
||||
copy ( other );
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
@@ -252,41 +283,41 @@ ValueConstIterator::operator =( const ValueIteratorBase &other )
|
||||
// //////////////////////////////////////////////////////////////////
|
||||
// //////////////////////////////////////////////////////////////////
|
||||
|
||||
ValueIterator::ValueIterator()
|
||||
ValueIterator::ValueIterator ()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
#ifndef JSON_VALUE_USE_INTERNAL_MAP
|
||||
ValueIterator::ValueIterator( const Value::ObjectValues::iterator ¤t )
|
||||
: ValueIteratorBase( current )
|
||||
ValueIterator::ValueIterator ( const Value::ObjectValues::iterator& current )
|
||||
: ValueIteratorBase ( current )
|
||||
{
|
||||
}
|
||||
#else
|
||||
ValueIterator::ValueIterator( const ValueInternalArray::IteratorState &state )
|
||||
: ValueIteratorBase( state )
|
||||
ValueIterator::ValueIterator ( const ValueInternalArray::IteratorState& state )
|
||||
: ValueIteratorBase ( state )
|
||||
{
|
||||
}
|
||||
|
||||
ValueIterator::ValueIterator( const ValueInternalMap::IteratorState &state )
|
||||
: ValueIteratorBase( state )
|
||||
ValueIterator::ValueIterator ( const ValueInternalMap::IteratorState& state )
|
||||
: ValueIteratorBase ( state )
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
ValueIterator::ValueIterator( const ValueConstIterator &other )
|
||||
: ValueIteratorBase( other )
|
||||
ValueIterator::ValueIterator ( const ValueConstIterator& other )
|
||||
: ValueIteratorBase ( other )
|
||||
{
|
||||
}
|
||||
|
||||
ValueIterator::ValueIterator( const ValueIterator &other )
|
||||
: ValueIteratorBase( other )
|
||||
ValueIterator::ValueIterator ( const ValueIterator& other )
|
||||
: ValueIteratorBase ( other )
|
||||
{
|
||||
}
|
||||
|
||||
ValueIterator &
|
||||
ValueIterator::operator =( const SelfType &other )
|
||||
ValueIterator&
|
||||
ValueIterator::operator = ( const SelfType& other )
|
||||
{
|
||||
copy( other );
|
||||
return *this;
|
||||
copy ( other );
|
||||
return *this;
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,166 +1,167 @@
|
||||
#ifndef JSON_WRITER_H_INCLUDED
|
||||
# define JSON_WRITER_H_INCLUDED
|
||||
|
||||
namespace Json {
|
||||
namespace Json
|
||||
{
|
||||
|
||||
class Value;
|
||||
class Value;
|
||||
|
||||
/** \brief Abstract class for writers.
|
||||
*/
|
||||
class JSON_API Writer
|
||||
{
|
||||
public:
|
||||
virtual ~Writer();
|
||||
/** \brief Abstract class for writers.
|
||||
*/
|
||||
class JSON_API Writer
|
||||
{
|
||||
public:
|
||||
virtual ~Writer ();
|
||||
|
||||
virtual std::string write( const Value &root ) = 0;
|
||||
};
|
||||
virtual std::string write ( const Value& root ) = 0;
|
||||
};
|
||||
|
||||
/** \brief Outputs a Value in <a HREF="http://www.json.org">JSON</a> format without formatting (not human friendly).
|
||||
*
|
||||
* The JSON document is written in a single line. It is not intended for 'human' consumption,
|
||||
* but may be usefull to support feature such as RPC where bandwith is limited.
|
||||
* \sa Reader, Value
|
||||
*/
|
||||
class JSON_API FastWriter : public Writer
|
||||
{
|
||||
public:
|
||||
FastWriter();
|
||||
virtual ~FastWriter(){}
|
||||
/** \brief Outputs a Value in <a HREF="http://www.json.org">JSON</a> format without formatting (not human friendly).
|
||||
*
|
||||
* The JSON document is written in a single line. It is not intended for 'human' consumption,
|
||||
* but may be usefull to support feature such as RPC where bandwith is limited.
|
||||
* \sa Reader, Value
|
||||
*/
|
||||
class JSON_API FastWriter : public Writer
|
||||
{
|
||||
public:
|
||||
FastWriter ();
|
||||
virtual ~FastWriter () {}
|
||||
|
||||
void enableYAMLCompatibility();
|
||||
void enableYAMLCompatibility ();
|
||||
|
||||
public: // overridden from Writer
|
||||
virtual std::string write( const Value &root );
|
||||
public: // overridden from Writer
|
||||
virtual std::string write ( const Value& root );
|
||||
|
||||
private:
|
||||
void writeValue( const Value &value );
|
||||
private:
|
||||
void writeValue ( const Value& value );
|
||||
|
||||
std::string document_;
|
||||
bool yamlCompatiblityEnabled_;
|
||||
};
|
||||
std::string document_;
|
||||
bool yamlCompatiblityEnabled_;
|
||||
};
|
||||
|
||||
/** \brief Writes a Value in <a HREF="http://www.json.org">JSON</a> format in a human friendly way.
|
||||
*
|
||||
* The rules for line break and indent are as follow:
|
||||
* - Object value:
|
||||
* - if empty then print {} without indent and line break
|
||||
* - if not empty the print '{', line break & indent, print one value per line
|
||||
* and then unindent and line break and print '}'.
|
||||
* - Array value:
|
||||
* - if empty then print [] without indent and line break
|
||||
* - if the array contains no object value, empty array or some other value types,
|
||||
* and all the values fit on one lines, then print the array on a single line.
|
||||
* - otherwise, it the values do not fit on one line, or the array contains
|
||||
* object or non empty array, then print one value per line.
|
||||
*
|
||||
* If the Value have comments then they are outputed according to their #CommentPlacement.
|
||||
*
|
||||
* \sa Reader, Value, Value::setComment()
|
||||
*/
|
||||
class JSON_API StyledWriter: public Writer
|
||||
{
|
||||
public:
|
||||
StyledWriter();
|
||||
virtual ~StyledWriter(){}
|
||||
/** \brief Writes a Value in <a HREF="http://www.json.org">JSON</a> format in a human friendly way.
|
||||
*
|
||||
* The rules for line break and indent are as follow:
|
||||
* - Object value:
|
||||
* - if empty then print {} without indent and line break
|
||||
* - if not empty the print '{', line break & indent, print one value per line
|
||||
* and then unindent and line break and print '}'.
|
||||
* - Array value:
|
||||
* - if empty then print [] without indent and line break
|
||||
* - if the array contains no object value, empty array or some other value types,
|
||||
* and all the values fit on one lines, then print the array on a single line.
|
||||
* - otherwise, it the values do not fit on one line, or the array contains
|
||||
* object or non empty array, then print one value per line.
|
||||
*
|
||||
* If the Value have comments then they are outputed according to their #CommentPlacement.
|
||||
*
|
||||
* \sa Reader, Value, Value::setComment()
|
||||
*/
|
||||
class JSON_API StyledWriter: public Writer
|
||||
{
|
||||
public:
|
||||
StyledWriter ();
|
||||
virtual ~StyledWriter () {}
|
||||
|
||||
public: // overridden from Writer
|
||||
/** \brief Serialize a Value in <a HREF="http://www.json.org">JSON</a> format.
|
||||
* \param root Value to serialize.
|
||||
* \return String containing the JSON document that represents the root value.
|
||||
*/
|
||||
virtual std::string write( const Value &root );
|
||||
public: // overridden from Writer
|
||||
/** \brief Serialize a Value in <a HREF="http://www.json.org">JSON</a> format.
|
||||
* \param root Value to serialize.
|
||||
* \return String containing the JSON document that represents the root value.
|
||||
*/
|
||||
virtual std::string write ( const Value& root );
|
||||
|
||||
private:
|
||||
void writeValue( const Value &value );
|
||||
void writeArrayValue( const Value &value );
|
||||
bool isMultineArray( const Value &value );
|
||||
void pushValue( const std::string &value );
|
||||
void writeIndent();
|
||||
void writeWithIndent( const std::string &value );
|
||||
void indent();
|
||||
void unindent();
|
||||
void writeCommentBeforeValue( const Value &root );
|
||||
void writeCommentAfterValueOnSameLine( const Value &root );
|
||||
bool hasCommentForValue( const Value &value );
|
||||
static std::string normalizeEOL( const std::string &text );
|
||||
private:
|
||||
void writeValue ( const Value& value );
|
||||
void writeArrayValue ( const Value& value );
|
||||
bool isMultineArray ( const Value& value );
|
||||
void pushValue ( const std::string& value );
|
||||
void writeIndent ();
|
||||
void writeWithIndent ( const std::string& value );
|
||||
void indent ();
|
||||
void unindent ();
|
||||
void writeCommentBeforeValue ( const Value& root );
|
||||
void writeCommentAfterValueOnSameLine ( const Value& root );
|
||||
bool hasCommentForValue ( const Value& value );
|
||||
static std::string normalizeEOL ( const std::string& text );
|
||||
|
||||
typedef std::vector<std::string> ChildValues;
|
||||
typedef std::vector<std::string> ChildValues;
|
||||
|
||||
ChildValues childValues_;
|
||||
std::string document_;
|
||||
std::string indentString_;
|
||||
int rightMargin_;
|
||||
int indentSize_;
|
||||
bool addChildValues_;
|
||||
};
|
||||
ChildValues childValues_;
|
||||
std::string document_;
|
||||
std::string indentString_;
|
||||
int rightMargin_;
|
||||
int indentSize_;
|
||||
bool addChildValues_;
|
||||
};
|
||||
|
||||
/** \brief Writes a Value in <a HREF="http://www.json.org">JSON</a> format in a human friendly way,
|
||||
to a stream rather than to a string.
|
||||
*
|
||||
* The rules for line break and indent are as follow:
|
||||
* - Object value:
|
||||
* - if empty then print {} without indent and line break
|
||||
* - if not empty the print '{', line break & indent, print one value per line
|
||||
* and then unindent and line break and print '}'.
|
||||
* - Array value:
|
||||
* - if empty then print [] without indent and line break
|
||||
* - if the array contains no object value, empty array or some other value types,
|
||||
* and all the values fit on one lines, then print the array on a single line.
|
||||
* - otherwise, it the values do not fit on one line, or the array contains
|
||||
* object or non empty array, then print one value per line.
|
||||
*
|
||||
* If the Value have comments then they are outputed according to their #CommentPlacement.
|
||||
*
|
||||
* \param indentation Each level will be indented by this amount extra.
|
||||
* \sa Reader, Value, Value::setComment()
|
||||
*/
|
||||
class JSON_API StyledStreamWriter
|
||||
{
|
||||
public:
|
||||
StyledStreamWriter( std::string indentation="\t" );
|
||||
~StyledStreamWriter(){}
|
||||
/** \brief Writes a Value in <a HREF="http://www.json.org">JSON</a> format in a human friendly way,
|
||||
to a stream rather than to a string.
|
||||
*
|
||||
* The rules for line break and indent are as follow:
|
||||
* - Object value:
|
||||
* - if empty then print {} without indent and line break
|
||||
* - if not empty the print '{', line break & indent, print one value per line
|
||||
* and then unindent and line break and print '}'.
|
||||
* - Array value:
|
||||
* - if empty then print [] without indent and line break
|
||||
* - if the array contains no object value, empty array or some other value types,
|
||||
* and all the values fit on one lines, then print the array on a single line.
|
||||
* - otherwise, it the values do not fit on one line, or the array contains
|
||||
* object or non empty array, then print one value per line.
|
||||
*
|
||||
* If the Value have comments then they are outputed according to their #CommentPlacement.
|
||||
*
|
||||
* \param indentation Each level will be indented by this amount extra.
|
||||
* \sa Reader, Value, Value::setComment()
|
||||
*/
|
||||
class JSON_API StyledStreamWriter
|
||||
{
|
||||
public:
|
||||
StyledStreamWriter ( std::string indentation = "\t" );
|
||||
~StyledStreamWriter () {}
|
||||
|
||||
public:
|
||||
/** \brief Serialize a Value in <a HREF="http://www.json.org">JSON</a> format.
|
||||
* \param out Stream to write to. (Can be ostringstream, e.g.)
|
||||
* \param root Value to serialize.
|
||||
* \note There is no point in deriving from Writer, since write() should not return a value.
|
||||
*/
|
||||
void write( std::ostream &out, const Value &root );
|
||||
public:
|
||||
/** \brief Serialize a Value in <a HREF="http://www.json.org">JSON</a> format.
|
||||
* \param out Stream to write to. (Can be ostringstream, e.g.)
|
||||
* \param root Value to serialize.
|
||||
* \note There is no point in deriving from Writer, since write() should not return a value.
|
||||
*/
|
||||
void write ( std::ostream& out, const Value& root );
|
||||
|
||||
private:
|
||||
void writeValue( const Value &value );
|
||||
void writeArrayValue( const Value &value );
|
||||
bool isMultineArray( const Value &value );
|
||||
void pushValue( const std::string &value );
|
||||
void writeIndent();
|
||||
void writeWithIndent( const std::string &value );
|
||||
void indent();
|
||||
void unindent();
|
||||
void writeCommentBeforeValue( const Value &root );
|
||||
void writeCommentAfterValueOnSameLine( const Value &root );
|
||||
bool hasCommentForValue( const Value &value );
|
||||
static std::string normalizeEOL( const std::string &text );
|
||||
private:
|
||||
void writeValue ( const Value& value );
|
||||
void writeArrayValue ( const Value& value );
|
||||
bool isMultineArray ( const Value& value );
|
||||
void pushValue ( const std::string& value );
|
||||
void writeIndent ();
|
||||
void writeWithIndent ( const std::string& value );
|
||||
void indent ();
|
||||
void unindent ();
|
||||
void writeCommentBeforeValue ( const Value& root );
|
||||
void writeCommentAfterValueOnSameLine ( const Value& root );
|
||||
bool hasCommentForValue ( const Value& value );
|
||||
static std::string normalizeEOL ( const std::string& text );
|
||||
|
||||
typedef std::vector<std::string> ChildValues;
|
||||
typedef std::vector<std::string> ChildValues;
|
||||
|
||||
ChildValues childValues_;
|
||||
std::ostream* document_;
|
||||
std::string indentString_;
|
||||
int rightMargin_;
|
||||
std::string indentation_;
|
||||
bool addChildValues_;
|
||||
};
|
||||
ChildValues childValues_;
|
||||
std::ostream* document_;
|
||||
std::string indentString_;
|
||||
int rightMargin_;
|
||||
std::string indentation_;
|
||||
bool addChildValues_;
|
||||
};
|
||||
|
||||
std::string JSON_API valueToString( Int value );
|
||||
std::string JSON_API valueToString( UInt value );
|
||||
std::string JSON_API valueToString( double value );
|
||||
std::string JSON_API valueToString( bool value );
|
||||
std::string JSON_API valueToQuotedString( const char *value );
|
||||
std::string JSON_API valueToString ( Int value );
|
||||
std::string JSON_API valueToString ( UInt value );
|
||||
std::string JSON_API valueToString ( double value );
|
||||
std::string JSON_API valueToString ( bool value );
|
||||
std::string JSON_API valueToQuotedString ( const char* value );
|
||||
|
||||
/// \brief Output using the StyledStreamWriter.
|
||||
/// \see Json::operator>>()
|
||||
std::ostream& operator<<( std::ostream&, const Value &root );
|
||||
/// \brief Output using the StyledStreamWriter.
|
||||
/// \see Json::operator>>()
|
||||
std::ostream& operator<< ( std::ostream&, const Value& root );
|
||||
|
||||
} // namespace Json
|
||||
|
||||
|
||||
@@ -1,22 +1,22 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
Copyright (c) 2011-2013, OpenCoin, Inc.
|
||||
Copyright (c) 2011-2013, OpenCoin, Inc.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
/** Add this to get the @ref ripple_json module.
|
||||
/** Add this to get the @ref ripple_json module.
|
||||
|
||||
@file ripple_json.cpp
|
||||
@ingroup ripple_json
|
||||
|
||||
@@ -1,32 +1,32 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
Copyright (c) 2011-2013, OpenCoin, Inc.
|
||||
Copyright (c) 2011-2013, OpenCoin, Inc.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
/** Include this to get the @ref ripple_json module.
|
||||
/** Include this to get the @ref ripple_json module.
|
||||
|
||||
@file ripple_json.h
|
||||
@ingroup ripple_json
|
||||
*/
|
||||
|
||||
/** JSON parsiing and output support.
|
||||
/** JSON parsiing and output support.
|
||||
|
||||
A simple set of JSON manipulation classes.
|
||||
A simple set of JSON manipulation classes.
|
||||
|
||||
@defgroup ripple_json
|
||||
@defgroup ripple_json
|
||||
*/
|
||||
|
||||
#ifndef RIPPLE_JSON_H
|
||||
|
||||
@@ -1,22 +1,22 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
Copyright (c) 2011-2013, OpenCoin, Inc.
|
||||
Copyright (c) 2011-2013, OpenCoin, Inc.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
/** Add this to get the @ref ripple_ledger module.
|
||||
/** Add this to get the @ref ripple_ledger module.
|
||||
|
||||
@file ripple_ledger.cpp
|
||||
@ingroup ripple_ledger
|
||||
|
||||
@@ -1,32 +1,32 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
Copyright (c) 2011-2013, OpenCoin, Inc.
|
||||
Copyright (c) 2011-2013, OpenCoin, Inc.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
/** Include this to get the @ref ripple_ledger module.
|
||||
/** Include this to get the @ref ripple_ledger module.
|
||||
|
||||
@file ripple_ledger.h
|
||||
@ingroup ripple_ledger
|
||||
*/
|
||||
|
||||
/** Ledger classes.
|
||||
/** Ledger classes.
|
||||
|
||||
This module exposes functionality for accessing and processing the ledger.
|
||||
This module exposes functionality for accessing and processing the ledger.
|
||||
|
||||
@defgroup ripple_ledger
|
||||
@defgroup ripple_ledger
|
||||
*/
|
||||
|
||||
#ifndef RIPPLE_LEDGER_H
|
||||
|
||||
@@ -1,22 +1,22 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
Copyright (c) 2011-2013, OpenCoin, Inc.
|
||||
Copyright (c) 2011-2013, OpenCoin, Inc.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
/** Add this to get the @ref ripple_main module.
|
||||
/** Add this to get the @ref ripple_main module.
|
||||
|
||||
@file ripple_main.cpp
|
||||
@ingroup ripple_main
|
||||
@@ -308,10 +308,10 @@ static const uint64 tenTo17m1 = tenTo17 - 1;
|
||||
|
||||
// This is for PeerDoor and WSDoor
|
||||
// Generate DH for SSL connection.
|
||||
static DH* handleTmpDh(SSL* ssl, int is_export, int iKeyLength)
|
||||
static DH* handleTmpDh (SSL* ssl, int is_export, int iKeyLength)
|
||||
{
|
||||
// VFALCO TODO eliminate this horrendous dependency on theApp and Wallet
|
||||
return 512 == iKeyLength ? theApp->getWallet().getDh512() : theApp->getWallet().getDh1024();
|
||||
// VFALCO TODO eliminate this horrendous dependency on theApp and Wallet
|
||||
return 512 == iKeyLength ? theApp->getWallet ().getDh512 () : theApp->getWallet ().getDh1024 ();
|
||||
}
|
||||
|
||||
#include "src/cpp/ripple/ParameterTable.cpp" // no log
|
||||
|
||||
@@ -1,32 +1,32 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
Copyright (c) 2011-2013, OpenCoin, Inc.
|
||||
Copyright (c) 2011-2013, OpenCoin, Inc.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
/** Include this to get the @ref ripple_main module.
|
||||
/** Include this to get the @ref ripple_main module.
|
||||
|
||||
@file ripple_main.h
|
||||
@ingroup ripple_main
|
||||
*/
|
||||
|
||||
/** Core classes.
|
||||
/** Core classes.
|
||||
|
||||
This module contains the Ripple core instance object and related objects.
|
||||
This module contains the Ripple core instance object and related objects.
|
||||
|
||||
@defgroup ripple_main
|
||||
@defgroup ripple_main
|
||||
*/
|
||||
|
||||
#ifndef RIPPLE_MAIN_H
|
||||
|
||||
@@ -1,22 +1,22 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
Copyright (c) 2011-2013, OpenCoin, Inc.
|
||||
Copyright (c) 2011-2013, OpenCoin, Inc.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
/** Add this to get the @ref ripple_mess module.
|
||||
/** Add this to get the @ref ripple_mess module.
|
||||
|
||||
@file ripple_mess.cpp
|
||||
@ingroup ripple_mess
|
||||
|
||||
@@ -1,32 +1,32 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
Copyright (c) 2011-2013, OpenCoin, Inc.
|
||||
Copyright (c) 2011-2013, OpenCoin, Inc.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
/** Include this to get the @ref ripple_mess module.
|
||||
/** Include this to get the @ref ripple_mess module.
|
||||
|
||||
@file ripple_mess.h
|
||||
@ingroup ripple_mess
|
||||
*/
|
||||
|
||||
/** Messy classes.
|
||||
/** Messy classes.
|
||||
|
||||
Stuff I haven't gotten to cleaning up yet.
|
||||
Stuff I haven't gotten to cleaning up yet.
|
||||
|
||||
@defgroup ripple_mess
|
||||
@defgroup ripple_mess
|
||||
*/
|
||||
|
||||
#ifndef RIPPLE_MESS_H
|
||||
|
||||
@@ -1,22 +1,22 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
Copyright (c) 2011-2013, OpenCoin, Inc.
|
||||
Copyright (c) 2011-2013, OpenCoin, Inc.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
/** Add this to get the @ref ripple_net module.
|
||||
/** Add this to get the @ref ripple_net module.
|
||||
|
||||
@file ripple_net.cpp
|
||||
@ingroup ripple_net
|
||||
|
||||
@@ -1,32 +1,32 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
Copyright (c) 2011-2013, OpenCoin, Inc.
|
||||
Copyright (c) 2011-2013, OpenCoin, Inc.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
/** Include this to get the @ref ripple_net module.
|
||||
/** Include this to get the @ref ripple_net module.
|
||||
|
||||
@file ripple_net.h
|
||||
@ingroup ripple_net
|
||||
*/
|
||||
|
||||
/** Peer to peer overlay classes.
|
||||
/** Peer to peer overlay classes.
|
||||
|
||||
Contains classes that support the peer to peer overlay.
|
||||
Contains classes that support the peer to peer overlay.
|
||||
|
||||
@defgroup ripple_net
|
||||
@defgroup ripple_net
|
||||
*/
|
||||
|
||||
#ifndef RIPPLE_NET_H
|
||||
|
||||
@@ -13,408 +13,432 @@ SETUP_LOG (SqliteDatabase)
|
||||
|
||||
using namespace std;
|
||||
|
||||
SqliteDatabase::SqliteDatabase(const char* host) : Database(host,"",""), mWalQ(NULL), walRunning(false)
|
||||
SqliteDatabase::SqliteDatabase (const char* host) : Database (host, "", ""), mWalQ (NULL), walRunning (false)
|
||||
{
|
||||
mConnection = NULL;
|
||||
mAuxConnection = NULL;
|
||||
mCurrentStmt = NULL;
|
||||
mConnection = NULL;
|
||||
mAuxConnection = NULL;
|
||||
mCurrentStmt = NULL;
|
||||
}
|
||||
|
||||
void SqliteDatabase::connect()
|
||||
void SqliteDatabase::connect ()
|
||||
{
|
||||
int rc = sqlite3_open(mHost.c_str(), &mConnection);
|
||||
if (rc)
|
||||
{
|
||||
WriteLog (lsFATAL, SqliteDatabase) << "Can't open " << mHost << " " << rc;
|
||||
sqlite3_close(mConnection);
|
||||
assert((rc != SQLITE_BUSY) && (rc != SQLITE_LOCKED));
|
||||
}
|
||||
int rc = sqlite3_open (mHost.c_str (), &mConnection);
|
||||
|
||||
if (rc)
|
||||
{
|
||||
WriteLog (lsFATAL, SqliteDatabase) << "Can't open " << mHost << " " << rc;
|
||||
sqlite3_close (mConnection);
|
||||
assert ((rc != SQLITE_BUSY) && (rc != SQLITE_LOCKED));
|
||||
}
|
||||
}
|
||||
|
||||
sqlite3* SqliteDatabase::getAuxConnection()
|
||||
sqlite3* SqliteDatabase::getAuxConnection ()
|
||||
{
|
||||
boost::mutex::scoped_lock sl(walMutex);
|
||||
if (mAuxConnection == NULL)
|
||||
{
|
||||
int rc = sqlite3_open(mHost.c_str(), &mAuxConnection);
|
||||
if (rc)
|
||||
{
|
||||
WriteLog (lsFATAL, SqliteDatabase) << "Can't aux open " << mHost << " " << rc;
|
||||
assert((rc != SQLITE_BUSY) && (rc != SQLITE_LOCKED));
|
||||
if (mAuxConnection != NULL)
|
||||
{
|
||||
sqlite3_close(mConnection);
|
||||
mAuxConnection = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
return mAuxConnection;
|
||||
boost::mutex::scoped_lock sl (walMutex);
|
||||
|
||||
if (mAuxConnection == NULL)
|
||||
{
|
||||
int rc = sqlite3_open (mHost.c_str (), &mAuxConnection);
|
||||
|
||||
if (rc)
|
||||
{
|
||||
WriteLog (lsFATAL, SqliteDatabase) << "Can't aux open " << mHost << " " << rc;
|
||||
assert ((rc != SQLITE_BUSY) && (rc != SQLITE_LOCKED));
|
||||
|
||||
if (mAuxConnection != NULL)
|
||||
{
|
||||
sqlite3_close (mConnection);
|
||||
mAuxConnection = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return mAuxConnection;
|
||||
}
|
||||
|
||||
void SqliteDatabase::disconnect()
|
||||
void SqliteDatabase::disconnect ()
|
||||
{
|
||||
sqlite3_finalize(mCurrentStmt);
|
||||
sqlite3_close(mConnection);
|
||||
if (mAuxConnection != NULL)
|
||||
sqlite3_close(mAuxConnection);
|
||||
sqlite3_finalize (mCurrentStmt);
|
||||
sqlite3_close (mConnection);
|
||||
|
||||
if (mAuxConnection != NULL)
|
||||
sqlite3_close (mAuxConnection);
|
||||
}
|
||||
|
||||
// returns true if the query went ok
|
||||
bool SqliteDatabase::executeSQL(const char* sql, bool fail_ok)
|
||||
bool SqliteDatabase::executeSQL (const char* sql, bool fail_ok)
|
||||
{
|
||||
#ifdef DEBUG_HANGING_LOCKS
|
||||
assert(fail_ok || (mCurrentStmt == NULL));
|
||||
assert (fail_ok || (mCurrentStmt == NULL));
|
||||
#endif
|
||||
|
||||
sqlite3_finalize(mCurrentStmt);
|
||||
sqlite3_finalize (mCurrentStmt);
|
||||
|
||||
int rc = sqlite3_prepare_v2(mConnection, sql, -1, &mCurrentStmt, NULL);
|
||||
int rc = sqlite3_prepare_v2 (mConnection, sql, -1, &mCurrentStmt, NULL);
|
||||
|
||||
if (SQLITE_OK != rc)
|
||||
{
|
||||
if (!fail_ok)
|
||||
{
|
||||
if (SQLITE_OK != rc)
|
||||
{
|
||||
if (!fail_ok)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
WriteLog (lsWARNING, SqliteDatabase) << "Perror:" << mHost << ": " << rc;
|
||||
WriteLog (lsWARNING, SqliteDatabase) << "Statement: " << sql;
|
||||
WriteLog (lsWARNING, SqliteDatabase) << "Error: " << sqlite3_errmsg(mConnection);
|
||||
WriteLog (lsWARNING, SqliteDatabase) << "Perror:" << mHost << ": " << rc;
|
||||
WriteLog (lsWARNING, SqliteDatabase) << "Statement: " << sql;
|
||||
WriteLog (lsWARNING, SqliteDatabase) << "Error: " << sqlite3_errmsg (mConnection);
|
||||
#endif
|
||||
}
|
||||
endIterRows();
|
||||
return false;
|
||||
}
|
||||
rc = sqlite3_step(mCurrentStmt);
|
||||
if (rc == SQLITE_ROW)
|
||||
{
|
||||
mMoreRows = true;
|
||||
}
|
||||
else if (rc == SQLITE_DONE)
|
||||
{
|
||||
endIterRows();
|
||||
mMoreRows = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((rc != SQLITE_BUSY) && (rc != SQLITE_LOCKED))
|
||||
{
|
||||
WriteLog (lsFATAL, SqliteDatabase) << mHost << " returns error " << rc << ": " << sqlite3_errmsg(mConnection);
|
||||
assert(false);
|
||||
}
|
||||
mMoreRows = false;
|
||||
}
|
||||
|
||||
if (!fail_ok)
|
||||
{
|
||||
endIterRows ();
|
||||
return false;
|
||||
}
|
||||
|
||||
rc = sqlite3_step (mCurrentStmt);
|
||||
|
||||
if (rc == SQLITE_ROW)
|
||||
{
|
||||
mMoreRows = true;
|
||||
}
|
||||
else if (rc == SQLITE_DONE)
|
||||
{
|
||||
endIterRows ();
|
||||
mMoreRows = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((rc != SQLITE_BUSY) && (rc != SQLITE_LOCKED))
|
||||
{
|
||||
WriteLog (lsFATAL, SqliteDatabase) << mHost << " returns error " << rc << ": " << sqlite3_errmsg (mConnection);
|
||||
assert (false);
|
||||
}
|
||||
|
||||
mMoreRows = false;
|
||||
|
||||
if (!fail_ok)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
WriteLog (lsWARNING, SqliteDatabase) << "SQL Serror:" << mHost << ": " << rc;
|
||||
WriteLog (lsWARNING, SqliteDatabase) << "Statement: " << sql;
|
||||
WriteLog (lsWARNING, SqliteDatabase) << "Error: " << sqlite3_errmsg(mConnection);
|
||||
WriteLog (lsWARNING, SqliteDatabase) << "SQL Serror:" << mHost << ": " << rc;
|
||||
WriteLog (lsWARNING, SqliteDatabase) << "Statement: " << sql;
|
||||
WriteLog (lsWARNING, SqliteDatabase) << "Error: " << sqlite3_errmsg (mConnection);
|
||||
#endif
|
||||
}
|
||||
endIterRows();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
endIterRows ();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// returns false if there are no results
|
||||
bool SqliteDatabase::startIterRows(bool finalize)
|
||||
bool SqliteDatabase::startIterRows (bool finalize)
|
||||
{
|
||||
mColNameTable.clear();
|
||||
mColNameTable.resize(sqlite3_column_count(mCurrentStmt));
|
||||
for(unsigned n=0; n<mColNameTable.size(); n++)
|
||||
{
|
||||
mColNameTable[n]=sqlite3_column_name(mCurrentStmt,n);
|
||||
}
|
||||
mColNameTable.clear ();
|
||||
mColNameTable.resize (sqlite3_column_count (mCurrentStmt));
|
||||
|
||||
if (!mMoreRows && finalize)
|
||||
endIterRows();
|
||||
for (unsigned n = 0; n < mColNameTable.size (); n++)
|
||||
{
|
||||
mColNameTable[n] = sqlite3_column_name (mCurrentStmt, n);
|
||||
}
|
||||
|
||||
return(mMoreRows);
|
||||
if (!mMoreRows && finalize)
|
||||
endIterRows ();
|
||||
|
||||
return (mMoreRows);
|
||||
}
|
||||
|
||||
void SqliteDatabase::endIterRows()
|
||||
void SqliteDatabase::endIterRows ()
|
||||
{
|
||||
sqlite3_finalize(mCurrentStmt);
|
||||
mCurrentStmt=NULL;
|
||||
sqlite3_finalize (mCurrentStmt);
|
||||
mCurrentStmt = NULL;
|
||||
}
|
||||
|
||||
// call this after you executeSQL
|
||||
// will return false if there are no more rows
|
||||
bool SqliteDatabase::getNextRow(bool finalize)
|
||||
bool SqliteDatabase::getNextRow (bool finalize)
|
||||
{
|
||||
if (mMoreRows)
|
||||
{
|
||||
int rc=sqlite3_step(mCurrentStmt);
|
||||
if (rc==SQLITE_ROW)
|
||||
return(true);
|
||||
assert((rc != SQLITE_BUSY) && (rc != SQLITE_LOCKED));
|
||||
CondLog ((rc != SQLITE_DONE), lsWARNING, SqliteDatabase) << "Rerror: " << mHost << ": " << rc;
|
||||
}
|
||||
if (mMoreRows)
|
||||
{
|
||||
int rc = sqlite3_step (mCurrentStmt);
|
||||
|
||||
if (finalize)
|
||||
endIterRows();
|
||||
return false;
|
||||
if (rc == SQLITE_ROW)
|
||||
return (true);
|
||||
|
||||
assert ((rc != SQLITE_BUSY) && (rc != SQLITE_LOCKED));
|
||||
CondLog ((rc != SQLITE_DONE), lsWARNING, SqliteDatabase) << "Rerror: " << mHost << ": " << rc;
|
||||
}
|
||||
|
||||
if (finalize)
|
||||
endIterRows ();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool SqliteDatabase::getNull(int colIndex)
|
||||
bool SqliteDatabase::getNull (int colIndex)
|
||||
{
|
||||
return(SQLITE_NULL == sqlite3_column_type(mCurrentStmt, colIndex));
|
||||
return (SQLITE_NULL == sqlite3_column_type (mCurrentStmt, colIndex));
|
||||
}
|
||||
|
||||
char* SqliteDatabase::getStr(int colIndex,std::string& retStr)
|
||||
char* SqliteDatabase::getStr (int colIndex, std::string& retStr)
|
||||
{
|
||||
const char *text = reinterpret_cast<const char *>(sqlite3_column_text(mCurrentStmt, colIndex));
|
||||
retStr = (text == NULL) ? "" : text;
|
||||
return const_cast<char*>(retStr.c_str());
|
||||
const char* text = reinterpret_cast<const char*> (sqlite3_column_text (mCurrentStmt, colIndex));
|
||||
retStr = (text == NULL) ? "" : text;
|
||||
return const_cast<char*> (retStr.c_str ());
|
||||
}
|
||||
|
||||
int32 SqliteDatabase::getInt(int colIndex)
|
||||
int32 SqliteDatabase::getInt (int colIndex)
|
||||
{
|
||||
return(sqlite3_column_int(mCurrentStmt, colIndex));
|
||||
return (sqlite3_column_int (mCurrentStmt, colIndex));
|
||||
}
|
||||
|
||||
float SqliteDatabase::getFloat(int colIndex)
|
||||
float SqliteDatabase::getFloat (int colIndex)
|
||||
{
|
||||
return(static_cast <float> (sqlite3_column_double(mCurrentStmt, colIndex)));
|
||||
return (static_cast <float> (sqlite3_column_double (mCurrentStmt, colIndex)));
|
||||
}
|
||||
|
||||
bool SqliteDatabase::getBool(int colIndex)
|
||||
bool SqliteDatabase::getBool (int colIndex)
|
||||
{
|
||||
return(sqlite3_column_int(mCurrentStmt, colIndex) ? true : false);
|
||||
return (sqlite3_column_int (mCurrentStmt, colIndex) ? true : false);
|
||||
}
|
||||
|
||||
int SqliteDatabase::getBinary(int colIndex,unsigned char* buf,int maxSize)
|
||||
int SqliteDatabase::getBinary (int colIndex, unsigned char* buf, int maxSize)
|
||||
{
|
||||
const void* blob=sqlite3_column_blob(mCurrentStmt, colIndex);
|
||||
int size=sqlite3_column_bytes(mCurrentStmt, colIndex);
|
||||
if(size<maxSize) maxSize=size;
|
||||
memcpy(buf,blob,maxSize);
|
||||
return(size);
|
||||
const void* blob = sqlite3_column_blob (mCurrentStmt, colIndex);
|
||||
int size = sqlite3_column_bytes (mCurrentStmt, colIndex);
|
||||
|
||||
if (size < maxSize) maxSize = size;
|
||||
|
||||
memcpy (buf, blob, maxSize);
|
||||
return (size);
|
||||
}
|
||||
|
||||
Blob SqliteDatabase::getBinary(int colIndex)
|
||||
Blob SqliteDatabase::getBinary (int colIndex)
|
||||
{
|
||||
const unsigned char* blob = reinterpret_cast<const unsigned char*>(sqlite3_column_blob(mCurrentStmt, colIndex));
|
||||
size_t iSize = sqlite3_column_bytes(mCurrentStmt, colIndex);
|
||||
Blob vucResult;
|
||||
const unsigned char* blob = reinterpret_cast<const unsigned char*> (sqlite3_column_blob (mCurrentStmt, colIndex));
|
||||
size_t iSize = sqlite3_column_bytes (mCurrentStmt, colIndex);
|
||||
Blob vucResult;
|
||||
|
||||
vucResult.resize(iSize);
|
||||
std::copy(blob, blob+iSize, vucResult.begin());
|
||||
vucResult.resize (iSize);
|
||||
std::copy (blob, blob + iSize, vucResult.begin ());
|
||||
|
||||
return vucResult;
|
||||
return vucResult;
|
||||
}
|
||||
|
||||
uint64 SqliteDatabase::getBigInt(int colIndex)
|
||||
uint64 SqliteDatabase::getBigInt (int colIndex)
|
||||
{
|
||||
return(sqlite3_column_int64(mCurrentStmt, colIndex));
|
||||
return (sqlite3_column_int64 (mCurrentStmt, colIndex));
|
||||
}
|
||||
|
||||
int SqliteDatabase::getKBUsedAll()
|
||||
int SqliteDatabase::getKBUsedAll ()
|
||||
{
|
||||
return static_cast<int>(sqlite3_memory_used() / 1024);
|
||||
return static_cast<int> (sqlite3_memory_used () / 1024);
|
||||
}
|
||||
|
||||
int SqliteDatabase::getKBUsedDB()
|
||||
int SqliteDatabase::getKBUsedDB ()
|
||||
{
|
||||
int cur = 0, hiw = 0;
|
||||
sqlite3_db_status(mConnection, SQLITE_DBSTATUS_CACHE_USED, &cur, &hiw, 0);
|
||||
return cur / 1024;
|
||||
int cur = 0, hiw = 0;
|
||||
sqlite3_db_status (mConnection, SQLITE_DBSTATUS_CACHE_USED, &cur, &hiw, 0);
|
||||
return cur / 1024;
|
||||
}
|
||||
|
||||
static int SqliteWALHook(void *s, sqlite3* dbCon, const char *dbName, int walSize)
|
||||
static int SqliteWALHook (void* s, sqlite3* dbCon, const char* dbName, int walSize)
|
||||
{
|
||||
(reinterpret_cast<SqliteDatabase*>(s))->doHook(dbName, walSize);
|
||||
return SQLITE_OK;
|
||||
(reinterpret_cast<SqliteDatabase*> (s))->doHook (dbName, walSize);
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
bool SqliteDatabase::setupCheckpointing(JobQueue *q)
|
||||
bool SqliteDatabase::setupCheckpointing (JobQueue* q)
|
||||
{
|
||||
mWalQ = q;
|
||||
sqlite3_wal_hook(mConnection, SqliteWALHook, this);
|
||||
return true;
|
||||
mWalQ = q;
|
||||
sqlite3_wal_hook (mConnection, SqliteWALHook, this);
|
||||
return true;
|
||||
}
|
||||
|
||||
void SqliteDatabase::doHook(const char *db, int pages)
|
||||
void SqliteDatabase::doHook (const char* db, int pages)
|
||||
{
|
||||
if (pages < 1000)
|
||||
return;
|
||||
{
|
||||
boost::mutex::scoped_lock sl(walMutex);
|
||||
if (walRunning)
|
||||
return;
|
||||
walRunning = true;
|
||||
}
|
||||
if (mWalQ)
|
||||
mWalQ->addJob(jtWAL, std::string("WAL:") + mHost, boost::bind(&SqliteDatabase::runWal, this));
|
||||
else
|
||||
boost::thread(boost::bind(&SqliteDatabase::runWal, this)).detach();
|
||||
if (pages < 1000)
|
||||
return;
|
||||
|
||||
{
|
||||
boost::mutex::scoped_lock sl (walMutex);
|
||||
|
||||
if (walRunning)
|
||||
return;
|
||||
|
||||
walRunning = true;
|
||||
}
|
||||
|
||||
if (mWalQ)
|
||||
mWalQ->addJob (jtWAL, std::string ("WAL:") + mHost, boost::bind (&SqliteDatabase::runWal, this));
|
||||
else
|
||||
boost::thread (boost::bind (&SqliteDatabase::runWal, this)).detach ();
|
||||
}
|
||||
|
||||
void SqliteDatabase::runWal()
|
||||
void SqliteDatabase::runWal ()
|
||||
{
|
||||
int log = 0, ckpt = 0;
|
||||
int ret = sqlite3_wal_checkpoint_v2(mConnection, NULL, SQLITE_CHECKPOINT_PASSIVE, &log, &ckpt);
|
||||
if (ret != SQLITE_OK)
|
||||
{
|
||||
WriteLog ((ret == SQLITE_LOCKED) ? lsTRACE : lsWARNING, SqliteDatabase) << "WAL("
|
||||
<< sqlite3_db_filename(mConnection, "main") << "): error " << ret;
|
||||
}
|
||||
else
|
||||
WriteLog (lsTRACE, SqliteDatabase) << "WAL(" << sqlite3_db_filename(mConnection, "main") <<
|
||||
"): frames=" << log << ", written=" << ckpt;
|
||||
int log = 0, ckpt = 0;
|
||||
int ret = sqlite3_wal_checkpoint_v2 (mConnection, NULL, SQLITE_CHECKPOINT_PASSIVE, &log, &ckpt);
|
||||
|
||||
{
|
||||
boost::mutex::scoped_lock sl(walMutex);
|
||||
walRunning = false;
|
||||
}
|
||||
if (ret != SQLITE_OK)
|
||||
{
|
||||
WriteLog ((ret == SQLITE_LOCKED) ? lsTRACE : lsWARNING, SqliteDatabase) << "WAL("
|
||||
<< sqlite3_db_filename (mConnection, "main") << "): error " << ret;
|
||||
}
|
||||
else
|
||||
WriteLog (lsTRACE, SqliteDatabase) << "WAL(" << sqlite3_db_filename (mConnection, "main") <<
|
||||
"): frames=" << log << ", written=" << ckpt;
|
||||
|
||||
{
|
||||
boost::mutex::scoped_lock sl (walMutex);
|
||||
walRunning = false;
|
||||
}
|
||||
}
|
||||
|
||||
SqliteStatement::SqliteStatement(SqliteDatabase* db, const char *sql, bool aux)
|
||||
SqliteStatement::SqliteStatement (SqliteDatabase* db, const char* sql, bool aux)
|
||||
{
|
||||
assert(db);
|
||||
assert (db);
|
||||
|
||||
sqlite3* conn = aux ? db->getAuxConnection() : db->peekConnection();
|
||||
int j = sqlite3_prepare_v2(conn, sql, strlen(sql) + 1, &statement, NULL);
|
||||
if (j != SQLITE_OK)
|
||||
throw j;
|
||||
sqlite3* conn = aux ? db->getAuxConnection () : db->peekConnection ();
|
||||
int j = sqlite3_prepare_v2 (conn, sql, strlen (sql) + 1, &statement, NULL);
|
||||
|
||||
if (j != SQLITE_OK)
|
||||
throw j;
|
||||
}
|
||||
|
||||
SqliteStatement::SqliteStatement(SqliteDatabase* db, const std::string& sql, bool aux)
|
||||
SqliteStatement::SqliteStatement (SqliteDatabase* db, const std::string& sql, bool aux)
|
||||
{
|
||||
assert(db);
|
||||
assert (db);
|
||||
|
||||
sqlite3* conn = aux ? db->getAuxConnection() : db->peekConnection();
|
||||
int j = sqlite3_prepare_v2(conn, sql.c_str(), sql.size() + 1, &statement, NULL);
|
||||
if (j != SQLITE_OK)
|
||||
throw j;
|
||||
sqlite3* conn = aux ? db->getAuxConnection () : db->peekConnection ();
|
||||
int j = sqlite3_prepare_v2 (conn, sql.c_str (), sql.size () + 1, &statement, NULL);
|
||||
|
||||
if (j != SQLITE_OK)
|
||||
throw j;
|
||||
}
|
||||
|
||||
SqliteStatement::~SqliteStatement()
|
||||
SqliteStatement::~SqliteStatement ()
|
||||
{
|
||||
sqlite3_finalize(statement);
|
||||
sqlite3_finalize (statement);
|
||||
}
|
||||
|
||||
sqlite3_stmt* SqliteStatement::peekStatement()
|
||||
sqlite3_stmt* SqliteStatement::peekStatement ()
|
||||
{
|
||||
return statement;
|
||||
return statement;
|
||||
}
|
||||
|
||||
int SqliteStatement::bind(int position, const void *data, int length)
|
||||
int SqliteStatement::bind (int position, const void* data, int length)
|
||||
{
|
||||
return sqlite3_bind_blob(statement, position, data, length, SQLITE_TRANSIENT);
|
||||
return sqlite3_bind_blob (statement, position, data, length, SQLITE_TRANSIENT);
|
||||
}
|
||||
|
||||
int SqliteStatement::bindStatic(int position, const void *data, int length)
|
||||
int SqliteStatement::bindStatic (int position, const void* data, int length)
|
||||
{
|
||||
return sqlite3_bind_blob(statement, position, data, length, SQLITE_STATIC);
|
||||
return sqlite3_bind_blob (statement, position, data, length, SQLITE_STATIC);
|
||||
}
|
||||
|
||||
int SqliteStatement::bindStatic(int position, Blob const& value)
|
||||
int SqliteStatement::bindStatic (int position, Blob const& value)
|
||||
{
|
||||
return sqlite3_bind_blob(statement, position, &value.front(), value.size(), SQLITE_STATIC);
|
||||
return sqlite3_bind_blob (statement, position, &value.front (), value.size (), SQLITE_STATIC);
|
||||
}
|
||||
|
||||
int SqliteStatement::bind(int position, uint32 value)
|
||||
int SqliteStatement::bind (int position, uint32 value)
|
||||
{
|
||||
return sqlite3_bind_int64(statement, position, static_cast<sqlite3_int64>(value));
|
||||
return sqlite3_bind_int64 (statement, position, static_cast<sqlite3_int64> (value));
|
||||
}
|
||||
|
||||
int SqliteStatement::bind(int position, const std::string& value)
|
||||
int SqliteStatement::bind (int position, const std::string& value)
|
||||
{
|
||||
return sqlite3_bind_text(statement, position, value.data(), value.size(), SQLITE_TRANSIENT);
|
||||
return sqlite3_bind_text (statement, position, value.data (), value.size (), SQLITE_TRANSIENT);
|
||||
}
|
||||
|
||||
int SqliteStatement::bindStatic(int position, const std::string& value)
|
||||
int SqliteStatement::bindStatic (int position, const std::string& value)
|
||||
{
|
||||
return sqlite3_bind_text(statement, position, value.data(), value.size(), SQLITE_STATIC);
|
||||
return sqlite3_bind_text (statement, position, value.data (), value.size (), SQLITE_STATIC);
|
||||
}
|
||||
|
||||
int SqliteStatement::bind(int position)
|
||||
int SqliteStatement::bind (int position)
|
||||
{
|
||||
return sqlite3_bind_null(statement, position);
|
||||
return sqlite3_bind_null (statement, position);
|
||||
}
|
||||
|
||||
int SqliteStatement::size(int column)
|
||||
int SqliteStatement::size (int column)
|
||||
{
|
||||
return sqlite3_column_bytes(statement, column);
|
||||
return sqlite3_column_bytes (statement, column);
|
||||
}
|
||||
|
||||
const void* SqliteStatement::peekBlob(int column)
|
||||
const void* SqliteStatement::peekBlob (int column)
|
||||
{
|
||||
return sqlite3_column_blob(statement, column);
|
||||
return sqlite3_column_blob (statement, column);
|
||||
}
|
||||
|
||||
Blob SqliteStatement::getBlob(int column)
|
||||
Blob SqliteStatement::getBlob (int column)
|
||||
{
|
||||
int size = sqlite3_column_bytes(statement, column);
|
||||
Blob ret(size);
|
||||
memcpy(&(ret.front()), sqlite3_column_blob(statement, column), size);
|
||||
return ret;
|
||||
int size = sqlite3_column_bytes (statement, column);
|
||||
Blob ret (size);
|
||||
memcpy (& (ret.front ()), sqlite3_column_blob (statement, column), size);
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::string SqliteStatement::getString(int column)
|
||||
std::string SqliteStatement::getString (int column)
|
||||
{
|
||||
return reinterpret_cast<const char *>(sqlite3_column_text(statement, column));
|
||||
return reinterpret_cast<const char*> (sqlite3_column_text (statement, column));
|
||||
}
|
||||
|
||||
const char* SqliteStatement::peekString(int column)
|
||||
const char* SqliteStatement::peekString (int column)
|
||||
{
|
||||
return reinterpret_cast<const char *>(sqlite3_column_text(statement, column));
|
||||
return reinterpret_cast<const char*> (sqlite3_column_text (statement, column));
|
||||
}
|
||||
|
||||
uint32 SqliteStatement::getUInt32(int column)
|
||||
uint32 SqliteStatement::getUInt32 (int column)
|
||||
{
|
||||
return static_cast<uint32>(sqlite3_column_int64(statement, column));
|
||||
return static_cast<uint32> (sqlite3_column_int64 (statement, column));
|
||||
}
|
||||
|
||||
int64 SqliteStatement::getInt64(int column)
|
||||
int64 SqliteStatement::getInt64 (int column)
|
||||
{
|
||||
return sqlite3_column_int64(statement, column);
|
||||
return sqlite3_column_int64 (statement, column);
|
||||
}
|
||||
|
||||
int SqliteStatement::step()
|
||||
int SqliteStatement::step ()
|
||||
{
|
||||
return sqlite3_step(statement);
|
||||
return sqlite3_step (statement);
|
||||
}
|
||||
|
||||
int SqliteStatement::reset()
|
||||
int SqliteStatement::reset ()
|
||||
{
|
||||
return sqlite3_reset(statement);
|
||||
return sqlite3_reset (statement);
|
||||
}
|
||||
|
||||
bool SqliteStatement::isOk(int j)
|
||||
bool SqliteStatement::isOk (int j)
|
||||
{
|
||||
return j == SQLITE_OK;
|
||||
return j == SQLITE_OK;
|
||||
}
|
||||
|
||||
bool SqliteStatement::isDone(int j)
|
||||
bool SqliteStatement::isDone (int j)
|
||||
{
|
||||
return j == SQLITE_DONE;
|
||||
return j == SQLITE_DONE;
|
||||
}
|
||||
|
||||
bool SqliteStatement::isRow(int j)
|
||||
bool SqliteStatement::isRow (int j)
|
||||
{
|
||||
return j == SQLITE_ROW;
|
||||
return j == SQLITE_ROW;
|
||||
}
|
||||
|
||||
bool SqliteStatement::isError(int j)
|
||||
bool SqliteStatement::isError (int j)
|
||||
{
|
||||
switch (j)
|
||||
{
|
||||
case SQLITE_OK:
|
||||
case SQLITE_ROW:
|
||||
case SQLITE_DONE:
|
||||
return true;
|
||||
switch (j)
|
||||
{
|
||||
case SQLITE_OK:
|
||||
case SQLITE_ROW:
|
||||
case SQLITE_DONE:
|
||||
return true;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
std::string SqliteStatement::getError(int j)
|
||||
std::string SqliteStatement::getError (int j)
|
||||
{
|
||||
return sqlite3_errstr(j);
|
||||
return sqlite3_errstr (j);
|
||||
}
|
||||
|
||||
// vim:ts=4
|
||||
|
||||
@@ -7,104 +7,110 @@ struct sqlite3_stmt;
|
||||
|
||||
class SqliteDatabase : public Database
|
||||
{
|
||||
sqlite3* mConnection;
|
||||
sqlite3* mAuxConnection;
|
||||
sqlite3_stmt* mCurrentStmt;
|
||||
bool mMoreRows;
|
||||
sqlite3* mConnection;
|
||||
sqlite3* mAuxConnection;
|
||||
sqlite3_stmt* mCurrentStmt;
|
||||
bool mMoreRows;
|
||||
|
||||
boost::mutex walMutex;
|
||||
JobQueue* mWalQ;
|
||||
bool walRunning;
|
||||
boost::mutex walMutex;
|
||||
JobQueue* mWalQ;
|
||||
bool walRunning;
|
||||
|
||||
public:
|
||||
SqliteDatabase(const char* host);
|
||||
SqliteDatabase (const char* host);
|
||||
|
||||
void connect();
|
||||
void disconnect();
|
||||
void connect ();
|
||||
void disconnect ();
|
||||
|
||||
// returns true if the query went ok
|
||||
bool executeSQL(const char* sql, bool fail_okay);
|
||||
// returns true if the query went ok
|
||||
bool executeSQL (const char* sql, bool fail_okay);
|
||||
|
||||
// tells you how many rows were changed by an update or insert
|
||||
int getNumRowsAffected();
|
||||
// tells you how many rows were changed by an update or insert
|
||||
int getNumRowsAffected ();
|
||||
|
||||
// returns false if there are no results
|
||||
bool startIterRows(bool finalize);
|
||||
void endIterRows();
|
||||
// returns false if there are no results
|
||||
bool startIterRows (bool finalize);
|
||||
void endIterRows ();
|
||||
|
||||
// call this after you executeSQL
|
||||
// will return false if there are no more rows
|
||||
bool getNextRow(bool finalize);
|
||||
// call this after you executeSQL
|
||||
// will return false if there are no more rows
|
||||
bool getNextRow (bool finalize);
|
||||
|
||||
bool getNull(int colIndex);
|
||||
char* getStr(int colIndex,std::string& retStr);
|
||||
int32 getInt(int colIndex);
|
||||
float getFloat(int colIndex);
|
||||
bool getBool(int colIndex);
|
||||
// returns amount stored in buf
|
||||
int getBinary(int colIndex,unsigned char* buf,int maxSize);
|
||||
Blob getBinary(int colIndex);
|
||||
uint64 getBigInt(int colIndex);
|
||||
bool getNull (int colIndex);
|
||||
char* getStr (int colIndex, std::string& retStr);
|
||||
int32 getInt (int colIndex);
|
||||
float getFloat (int colIndex);
|
||||
bool getBool (int colIndex);
|
||||
// returns amount stored in buf
|
||||
int getBinary (int colIndex, unsigned char* buf, int maxSize);
|
||||
Blob getBinary (int colIndex);
|
||||
uint64 getBigInt (int colIndex);
|
||||
|
||||
sqlite3* peekConnection() { return mConnection; }
|
||||
sqlite3* getAuxConnection();
|
||||
virtual bool setupCheckpointing(JobQueue*);
|
||||
virtual SqliteDatabase* getSqliteDB() { return this; }
|
||||
sqlite3* peekConnection ()
|
||||
{
|
||||
return mConnection;
|
||||
}
|
||||
sqlite3* getAuxConnection ();
|
||||
virtual bool setupCheckpointing (JobQueue*);
|
||||
virtual SqliteDatabase* getSqliteDB ()
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
void runWal();
|
||||
void doHook(const char *db, int walSize);
|
||||
void runWal ();
|
||||
void doHook (const char* db, int walSize);
|
||||
|
||||
int getKBUsedDB();
|
||||
int getKBUsedAll();
|
||||
int getKBUsedDB ();
|
||||
int getKBUsedAll ();
|
||||
};
|
||||
|
||||
class SqliteStatement
|
||||
{
|
||||
private:
|
||||
SqliteStatement(const SqliteStatement&); // no implementation
|
||||
SqliteStatement& operator=(const SqliteStatement&); // no implementation
|
||||
SqliteStatement (const SqliteStatement&); // no implementation
|
||||
SqliteStatement& operator= (const SqliteStatement&); // no implementation
|
||||
|
||||
protected:
|
||||
sqlite3_stmt* statement;
|
||||
sqlite3_stmt* statement;
|
||||
|
||||
public:
|
||||
SqliteStatement(SqliteDatabase* db, const char *statement, bool aux = false);
|
||||
SqliteStatement(SqliteDatabase* db, const std::string& statement, bool aux = false);
|
||||
~SqliteStatement();
|
||||
SqliteStatement (SqliteDatabase* db, const char* statement, bool aux = false);
|
||||
SqliteStatement (SqliteDatabase* db, const std::string& statement, bool aux = false);
|
||||
~SqliteStatement ();
|
||||
|
||||
sqlite3_stmt* peekStatement();
|
||||
sqlite3_stmt* peekStatement ();
|
||||
|
||||
// positions start at 1
|
||||
int bind(int position, const void *data, int length);
|
||||
int bindStatic(int position, const void *data, int length);
|
||||
int bindStatic(int position, Blob const& value);
|
||||
// positions start at 1
|
||||
int bind (int position, const void* data, int length);
|
||||
int bindStatic (int position, const void* data, int length);
|
||||
int bindStatic (int position, Blob const& value);
|
||||
|
||||
int bind(int position, const std::string& value);
|
||||
int bindStatic(int position, const std::string& value);
|
||||
int bind (int position, const std::string& value);
|
||||
int bindStatic (int position, const std::string& value);
|
||||
|
||||
int bind(int position, uint32 value);
|
||||
int bind(int position);
|
||||
int bind (int position, uint32 value);
|
||||
int bind (int position);
|
||||
|
||||
// columns start at 0
|
||||
int size(int column);
|
||||
// columns start at 0
|
||||
int size (int column);
|
||||
|
||||
const void* peekBlob(int column);
|
||||
Blob getBlob(int column);
|
||||
const void* peekBlob (int column);
|
||||
Blob getBlob (int column);
|
||||
|
||||
std::string getString(int column);
|
||||
const char* peekString(int column);
|
||||
uint32 getUInt32(int column);
|
||||
int64 getInt64(int column);
|
||||
std::string getString (int column);
|
||||
const char* peekString (int column);
|
||||
uint32 getUInt32 (int column);
|
||||
int64 getInt64 (int column);
|
||||
|
||||
int step();
|
||||
int reset();
|
||||
int step ();
|
||||
int reset ();
|
||||
|
||||
// translate return values of step and reset
|
||||
bool isOk(int);
|
||||
bool isDone(int);
|
||||
bool isRow(int);
|
||||
bool isError(int);
|
||||
std::string getError(int);
|
||||
// translate return values of step and reset
|
||||
bool isOk (int);
|
||||
bool isDone (int);
|
||||
bool isRow (int);
|
||||
bool isError (int);
|
||||
std::string getError (int);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user