Reformatting using AStyle

This commit is contained in:
Vinnie Falco
2013-06-14 08:45:13 -07:00
parent 36bd8f7173
commit 521e812fc4
294 changed files with 54609 additions and 47598 deletions

View File

@@ -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

View File

@@ -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

View File

@@ -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);
}

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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__)

View File

@@ -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

View File

@@ -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

View File

@@ -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>

View File

@@ -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

View File

@@ -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
*/

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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
}

View File

@@ -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.
*/
//==============================================================================

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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.
*/
//==============================================================================

View File

@@ -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 ();
}

View File

@@ -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

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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"

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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);

View File

@@ -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);

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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;

View File

@@ -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

View File

@@ -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

View File

@@ -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);
}

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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 ()];
}

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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);

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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 ();
}

View File

@@ -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;

View File

@@ -5,10 +5,10 @@
*/
struct UptimeTimerAdapter
{
inline static int getElapsedSeconds ()
{
return UptimeTimer::getInstance().getElapsedSeconds ();
}
inline static int getElapsedSeconds ()
{
return UptimeTimer::getInstance ().getElapsedSeconds ();
}
};
#endif

View File

@@ -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

View File

@@ -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.

View File

@@ -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_;
};

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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 &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
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

View File

@@ -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 &current )
: 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 &current )
: 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 &current )
: 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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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