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. /** Maintains a cache of keys with no associated data.
The cache has a target size and an expiration time. When cached items become 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 older than the maximum age they are eligible for removal during a
call to @ref sweep. call to @ref sweep.
@note @note
Timer must provide this function: Timer must provide this function:
@code @code
static int getElapsedSeconds (); static int getElapsedSeconds ();
@endcode @endcode
file vf_db.h file vf_db.h
@ingroup ripple_basics @ingroup ripple_basics
*/ */
template <class Key, class Timer> template <class Key, class Timer>
class KeyCache class KeyCache
{ {
public: public:
/** Provides a type for the key. /** Provides a type for the key.
*/ */
typedef Key key_type; typedef Key key_type;
/** Construct with the specified name. /** Construct with the specified name.
@param size The initial target size. @param size The initial target size.
@param age The initial expiration time. @param age The initial expiration time.
*/ */
KeyCache (const std::string& name, KeyCache (const std::string& name,
int size = 0, int size = 0,
int age = 120) : mName(name), mTargetSize(size), mTargetAge(age) int age = 120) : mName (name), mTargetSize (size), mTargetAge (age)
{ {
assert((size >= 0) && (age > 2)); assert ((size >= 0) && (age > 2));
} }
/** Returns the current size. /** Returns the current size.
*/ */
unsigned int getSize () unsigned int getSize ()
{ {
boost::mutex::scoped_lock sl(mNCLock); boost::mutex::scoped_lock sl (mNCLock);
return mCache.size(); return mCache.size ();
} }
/** Returns the desired target size. /** Returns the desired target size.
*/ */
unsigned int getTargetSize () unsigned int getTargetSize ()
{ {
boost::mutex::scoped_lock sl(mNCLock); boost::mutex::scoped_lock sl (mNCLock);
return mTargetSize; return mTargetSize;
} }
/** Returns the desired target age. /** Returns the desired target age.
*/ */
unsigned int getTargetAge () unsigned int getTargetAge ()
{ {
boost::mutex::scoped_lock sl(mNCLock); boost::mutex::scoped_lock sl (mNCLock);
return mTargetAge; return mTargetAge;
} }
/** Simultaneously set the target size and age. /** Simultaneously set the target size and age.
@param size The target size. @param size The target size.
@param age The target age. @param age The target age.
*/ */
void setTargets(int size, int age) void setTargets (int size, int age)
{ {
boost::mutex::scoped_lock sl(mNCLock); boost::mutex::scoped_lock sl (mNCLock);
mTargetSize = size; mTargetSize = size;
mTargetAge = age; mTargetAge = age;
assert((mTargetSize >= 0) && (mTargetAge > 2)); assert ((mTargetSize >= 0) && (mTargetAge > 2));
} }
/** Retrieve the name of this object. /** Retrieve the name of this object.
*/ */
const std::string& getName() const std::string& getName ()
{ {
return mName; 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 key The key to check
@param refresh Whether or not to refresh the entry. @param refresh Whether or not to refresh the entry.
@return `true` if the key was found. @return `true` if the key was found.
*/ */
bool isPresent(const key_type& key, bool refresh = true) bool isPresent (const key_type& key, bool refresh = true)
{ {
boost::mutex::scoped_lock sl(mNCLock); boost::mutex::scoped_lock sl (mNCLock);
map_iterator it = mCache.find(key); map_iterator it = mCache.find (key);
if (it == mCache.end())
return false;
if (refresh)
it->second = Timer::getElapsedSeconds ();
return true;
}
/** Remove the specified cache entry. if (it == mCache.end ())
return false;
@param key The key to remove. if (refresh)
@return `false` if the key was not found. it->second = Timer::getElapsedSeconds ();
*/
bool del(const key_type& key)
{
boost::mutex::scoped_lock sl(mNCLock);
map_iterator it = mCache.find(key); return true;
if (it == mCache.end()) }
return false;
mCache.erase(it); /** Remove the specified cache entry.
return true;
}
/** 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. map_iterator it = mCache.find (key);
@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 ())
if (it != mCache.end()) return false;
{
it->second = Timer::getElapsedSeconds ();
return false;
}
mCache.insert(std::make_pair(key, Timer::getElapsedSeconds ()));
return true;
}
/** Remove stale entries from the cache. mCache.erase (it);
*/ return true;
void sweep () }
{
int now = Timer::getElapsedSeconds ();
boost::mutex::scoped_lock sl(mNCLock);
int target; /** Add the specified cache entry.
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(); @param key The key to add.
while (it != mCache.end()) @return `true` if the key did not previously exist.
{ */
if (it->second > now) bool add (const key_type& key)
{ {
it->second = now; boost::mutex::scoped_lock sl (mNCLock);
++it;
} map_iterator it = mCache.find (key);
else if (it->second < target)
{ if (it != mCache.end ())
it = mCache.erase(it); {
} it->second = Timer::getElapsedSeconds ();
else return false;
{ }
++it;
} 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: protected:
/** Provides a type for the underlying map. /** Provides a type for the underlying map.
*/ */
typedef boost::unordered_map<key_type, int> map_type; typedef boost::unordered_map<key_type, int> map_type;
/** The type of the iterator used for traversals. /** The type of the iterator used for traversals.
*/ */
typedef typename map_type::iterator map_iterator; typedef typename map_type::iterator map_iterator;
std::string const mName; std::string const mName;
boost::mutex mNCLock; boost::mutex mNCLock;
map_type mCache; map_type mCache;
unsigned int mTargetSize, mTargetAge; unsigned int mTargetSize, mTargetAge;
}; };
#endif #endif

View File

@@ -1,180 +1,206 @@
SETUP_LOG (RangeSet) SETUP_LOG (RangeSet)
inline uint32 min(uint32 x, uint32 y) { return (x < y) ? x : y; } inline uint32 min (uint32 x, uint32 y)
inline uint32 max(uint32 x, uint32 y) { return (x > y) ? x : y; }
bool RangeSet::hasValue(uint32 v) const
{ {
BOOST_FOREACH(const value_type& it, mRanges) return (x < y) ? x : y;
{
if (contains(it, v))
return true;
}
return false;
} }
inline uint32 max (uint32 x, uint32 y)
uint32 RangeSet::getFirst() const
{ {
const_iterator it = mRanges.begin(); return (x > y) ? x : y;
if (it == mRanges.end())
return RangeSetAbsent;
return it->first;
} }
uint32 RangeSet::getNext(uint32 v) const bool RangeSet::hasValue (uint32 v) const
{ {
BOOST_FOREACH(const value_type& it, mRanges) BOOST_FOREACH (const value_type & it, mRanges)
{ {
if (it.first > v) if (contains (it, v))
return it.first; return true;
if (contains(it, v + 1)) }
return v + 1; return false;
}
return RangeSetAbsent;
} }
uint32 RangeSet::getLast() const uint32 RangeSet::getFirst () const
{ {
const_reverse_iterator it = mRanges.rbegin(); const_iterator it = mRanges.begin ();
if (it == mRanges.rend())
return RangeSetAbsent; if (it == mRanges.end ())
return it->second; 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) BOOST_FOREACH (const value_type & it, mRanges)
{ {
if (it.second < v) if (it.first > v)
return it.second; return it.first;
if (contains(it, v + 1))
return v - 1; if (contains (it, v + 1))
} return v + 1;
return RangeSetAbsent; }
return RangeSetAbsent;
} }
uint32 RangeSet::prevMissing(uint32 v) const uint32 RangeSet::getLast () 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)
{ {
if (!hasValue(v)) const_reverse_iterator it = mRanges.rbegin ();
{
mRanges[v] = v; if (it == mRanges.rend ())
simplify(); return RangeSetAbsent;
}
return it->second;
} }
void RangeSet::setRange(uint32 minV, uint32 maxV) uint32 RangeSet::getPrev (uint32 v) const
{ {
while (hasValue(minV)) BOOST_REVERSE_FOREACH (const value_type & it, mRanges)
{ {
++minV; if (it.second < v)
if (minV >= maxV) return it.second;
return;
} if (contains (it, v + 1))
mRanges[minV] = maxV; return v - 1;
simplify(); }
return RangeSetAbsent;
} }
void RangeSet::clearValue(uint32 v) uint32 RangeSet::prevMissing (uint32 v) const
{ {
for (iterator it = mRanges.begin(); it != mRanges.end(); ++it) // largest number not in the set that is less than the given number
{ BOOST_FOREACH (const value_type & it, mRanges)
if (contains(*it, v)) {
{ if (contains (it, v))
if (it->first == v) return it.first - 1;
{
if (it->second == v) if (it.first > v)
mRanges.erase(it); return v + 1;
else }
{ return RangeSetAbsent;
mRanges[v + 1] = it->second;
it->second = v - 1;
}
}
else if (it->second == v)
--(it->second);
else
{
uint32 oldEnd = it->second;
it->second = v - 1;
mRanges[v + 1] = oldEnd;
}
return;
}
}
} }
std::string RangeSet::toString() const void RangeSet::setValue (uint32 v)
{ {
std::string ret; if (!hasValue (v))
BOOST_FOREACH(value_type const& it, mRanges) {
{ mRanges[v] = v;
if (!ret.empty()) simplify ();
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() void RangeSet::setRange (uint32 minV, uint32 maxV)
{ {
iterator it = mRanges.begin(); while (hasValue (minV))
while (1) {
{ ++minV;
iterator nit = it;
if (++nit == mRanges.end()) if (minV >= maxV)
return; return;
if (it->second >= (nit->first - 1)) }
{ // ranges overlap
it->second = nit->second; mRanges[minV] = maxV;
mRanges.erase(nit); simplify ();
}
else
it = nit;
}
} }
BOOST_AUTO_TEST_SUITE(RangeSet_suite) void RangeSet::clearValue (uint32 v)
BOOST_AUTO_TEST_CASE(RangeSet_test)
{ {
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; return;
}
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() 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 // vim:ts=4

View File

@@ -4,47 +4,48 @@
class RangeSet class RangeSet
{ {
public: public:
static const uint32 RangeSetAbsent = static_cast<uint32>(-1); static const uint32 RangeSetAbsent = static_cast<uint32> (-1);
protected: 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_iterator const_iterator;
typedef std::map<uint32, uint32>::const_reverse_iterator const_reverse_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>::value_type value_type;
typedef std::map<uint32, uint32>::iterator iterator; typedef std::map<uint32, uint32>::iterator iterator;
static bool contains(value_type const& it, uint32 v) static bool contains (value_type const& it, uint32 v)
{ {
return (it.first <= v) && (it.second >= v); return (it.first <= v) && (it.second >= v);
} }
void simplify(); void simplify ();
public: public:
RangeSet () { } RangeSet () { }
bool hasValue(uint32) const; bool hasValue (uint32) const;
uint32 getFirst() const; uint32 getFirst () const;
uint32 getNext(uint32) const; uint32 getNext (uint32) const;
uint32 getLast() const; uint32 getLast () const;
uint32 getPrev(uint32) 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 setValue (uint32);
void setRange(uint32, uint32); void setRange (uint32, uint32);
void clearValue(uint32); void clearValue (uint32);
std::string toString() const; std::string toString () const;
}; };
// VFALCO TODO these parameters should not be const references. // VFALCO TODO these parameters should not be const references.
template<typename T, typename U> T range_check_cast(const U& value, const T& minimum, const T& maximum) template<typename T, typename U> T range_check_cast (const U& value, const T& minimum, const T& maximum)
{ {
if ((value < minimum) || (value > maximum)) if ((value < minimum) || (value > maximum))
throw std::runtime_error("Value out of range"); throw std::runtime_error ("Value out of range");
return static_cast<T>(value);
return static_cast<T> (value);
} }

View File

@@ -9,41 +9,46 @@
template<typename T> template<typename T>
struct secure_allocator : public std::allocator<T> struct secure_allocator : public std::allocator<T>
{ {
// MSVC8 default copy constructor is broken // MSVC8 default copy constructor is broken
typedef std::allocator<T> base; typedef std::allocator<T> base;
typedef typename base::size_type size_type; typedef typename base::size_type size_type;
typedef typename base::difference_type difference_type; typedef typename base::difference_type difference_type;
typedef typename base::pointer pointer; typedef typename base::pointer pointer;
typedef typename base::const_pointer const_pointer; typedef typename base::const_pointer const_pointer;
typedef typename base::reference reference; typedef typename base::reference reference;
typedef typename base::const_reference const_reference; typedef typename base::const_reference const_reference;
typedef typename base::value_type value_type; typedef typename base::value_type value_type;
secure_allocator() throw() {} secure_allocator () throw () {}
secure_allocator(const secure_allocator& a) throw() : base(a) {} secure_allocator (const secure_allocator& a) throw () : base (a) {}
template <typename U> template <typename U>
secure_allocator(const secure_allocator<U>& a) throw() : base(a) {} secure_allocator (const secure_allocator<U>& a) throw () : base (a) {}
~secure_allocator() throw() {} ~secure_allocator () throw () {}
template<typename _Other> struct rebind template<typename _Other> struct rebind
{ typedef secure_allocator<_Other> other; }; {
typedef secure_allocator<_Other> other;
};
T* allocate(std::size_t n, const void *hint = 0) T* allocate (std::size_t n, const void* hint = 0)
{ {
T *p; T* p;
p = std::allocator<T>::allocate(n, hint); p = std::allocator<T>::allocate (n, hint);
if (p != NULL)
mlock(p, sizeof(T) * n);
return p;
}
void deallocate(T* p, std::size_t n) if (p != NULL)
{ mlock (p, sizeof (T) * n);
if (p != NULL)
{ return p;
memset(p, 0, sizeof(T) * n); }
munlock(p, sizeof(T) * n);
} void deallocate (T* p, std::size_t n)
std::allocator<T>::deallocate(p, n); {
} if (p != NULL)
{
memset (p, 0, sizeof (T) * n);
munlock (p, sizeof (T) * n);
}
std::allocator<T>::deallocate (p, n);
}
}; };
#endif #endif

View File

@@ -16,367 +16,423 @@ struct TaggedCacheLog;
/** Combination cache/map container. /** 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> template <typename c_Key, typename c_Data, class Timer>
class TaggedCache class TaggedCache
{ {
public: public:
typedef c_Key key_type; typedef c_Key key_type;
typedef c_Data data_type; typedef c_Data data_type;
typedef boost::weak_ptr<data_type> weak_data_ptr; typedef boost::weak_ptr<data_type> weak_data_ptr;
typedef boost::shared_ptr<data_type> data_ptr; typedef boost::shared_ptr<data_type> data_ptr;
public: public:
TaggedCache(const char *name, int size, int age) TaggedCache (const char* name, int size, int age)
: mName(name) : mName (name)
, mTargetSize(size) , mTargetSize (size)
, mTargetAge(age) , mTargetAge (age)
, mCacheCount(0) , mCacheCount (0)
, mLastSweep(Timer::getElapsedSeconds()) , mLastSweep (Timer::getElapsedSeconds ())
, mHits(0) , mHits (0)
, mMisses(0) , mMisses (0)
{ {
} }
int getTargetSize() const; int getTargetSize () const;
int getTargetAge() const; int getTargetAge () const;
int getCacheSize(); int getCacheSize ();
int getTrackSize(); int getTrackSize ();
float getHitRate(); float getHitRate ();
void clearStats(); void clearStats ();
void setTargetSize(int size); void setTargetSize (int size);
void setTargetAge(int age); void setTargetAge (int age);
void sweep(); void sweep ();
void clear(); void clear ();
bool touch(const key_type& key); bool touch (const key_type& key);
bool del(const key_type& key, bool valid); bool del (const key_type& key, bool valid);
bool canonicalize(const key_type& key, boost::shared_ptr<c_Data>& data, bool replace = false); 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); bool store (const key_type& key, const c_Data& data);
boost::shared_ptr<c_Data> fetch(const key_type& key); boost::shared_ptr<c_Data> fetch (const key_type& key);
bool retrieve(const key_type& key, c_Data& data); bool retrieve (const key_type& key, c_Data& data);
boost::recursive_mutex& peekMutex() { return mLock; } boost::recursive_mutex& peekMutex ()
{
return mLock;
}
private: private:
class cache_entry class cache_entry
{ {
public: public:
int last_use; int last_use;
data_ptr ptr; data_ptr ptr;
weak_data_ptr weak_ptr; weak_data_ptr weak_ptr;
cache_entry(int l, const data_ptr& d) : last_use(l), ptr(d), weak_ptr(d) { ; } 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(); } bool isWeak ()
void touch() { last_use = Timer::getElapsedSeconds (); } {
}; 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 std::pair<key_type, cache_entry> cache_pair;
typedef boost::unordered_map<key_type, cache_entry> cache_type; typedef boost::unordered_map<key_type, cache_entry> cache_type;
typedef typename cache_type::iterator cache_iterator; typedef typename cache_type::iterator cache_iterator;
mutable boost::recursive_mutex mLock; mutable boost::recursive_mutex mLock;
std::string mName; // Used for logging std::string mName; // Used for logging
int mTargetSize; // Desired number of cache entries (0 = ignore) int mTargetSize; // Desired number of cache entries (0 = ignore)
int mTargetAge; // Desired maximum cache age int mTargetAge; // Desired maximum cache age
int mCacheCount; // Number of items cached int mCacheCount; // Number of items cached
cache_type mCache; // Hold strong reference to recent objects cache_type mCache; // Hold strong reference to recent objects
int mLastSweep; int mLastSweep;
uint64 mHits, mMisses; uint64 mHits, mMisses;
}; };
template<typename c_Key, typename c_Data, class Timer> 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); boost::recursive_mutex::scoped_lock sl (mLock);
return mTargetSize; return mTargetSize;
} }
template<typename c_Key, typename c_Data, class Timer> 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); boost::recursive_mutex::scoped_lock sl (mLock);
mTargetSize = s; mTargetSize = s;
if (s > 0)
mCache.rehash(static_cast<std::size_t>((s + (s >> 2)) / mCache.max_load_factor() + 1)); if (s > 0)
WriteLog (lsDEBUG, TaggedCacheLog) << mName << " target size set to " << s; 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> 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); boost::recursive_mutex::scoped_lock sl (mLock);
return mTargetAge; return mTargetAge;
} }
template<typename c_Key, typename c_Data, class Timer> 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); boost::recursive_mutex::scoped_lock sl (mLock);
mTargetAge = s; mTargetAge = s;
WriteLog (lsDEBUG, TaggedCacheLog) << mName << " target age set to " << s; WriteLog (lsDEBUG, TaggedCacheLog) << mName << " target age set to " << s;
} }
template<typename c_Key, typename c_Data, class Timer> 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); boost::recursive_mutex::scoped_lock sl (mLock);
return mCacheCount; return mCacheCount;
} }
template<typename c_Key, typename c_Data, class Timer> 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); boost::recursive_mutex::scoped_lock sl (mLock);
return mCache.size(); return mCache.size ();
} }
template<typename c_Key, typename c_Data, class Timer> 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); boost::recursive_mutex::scoped_lock sl (mLock);
return (static_cast<float>(mHits) * 100) / (1.0f + mHits + mMisses); return (static_cast<float> (mHits) * 100) / (1.0f + mHits + mMisses);
} }
template<typename c_Key, typename c_Data, class Timer> 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); boost::recursive_mutex::scoped_lock sl (mLock);
mHits = 0; mHits = 0;
mMisses = 0; mMisses = 0;
} }
template<typename c_Key, typename c_Data, class Timer> 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); boost::recursive_mutex::scoped_lock sl (mLock);
mCache.clear(); mCache.clear ();
mCacheCount = 0; mCacheCount = 0;
} }
template<typename c_Key, typename c_Data, class Timer> 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 mLastSweep = Timer::getElapsedSeconds ();
int target = mLastSweep - mTargetAge; int target = mLastSweep - mTargetAge;
int cacheRemovals = 0, mapRemovals = 0, cc = 0; int cacheRemovals = 0, mapRemovals = 0, cc = 0;
if ((mTargetSize != 0) && (static_cast<int>(mCache.size()) > mTargetSize)) if ((mTargetSize != 0) && (static_cast<int> (mCache.size ()) > mTargetSize))
{ {
target = mLastSweep - (mTargetAge * mTargetSize / mCache.size()); 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;
}
cache_iterator cit = mCache.begin(); if (target > (mLastSweep - 2))
while (cit != mCache.end()) target = mLastSweep - 2;
{
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); WriteLog (lsINFO, TaggedCacheLog) << mName << " is growing fast " <<
if (ShouldLog (lsTRACE, TaggedCacheLog) && (mapRemovals || cacheRemovals)) mCache.size () << " of " << mTargetSize <<
{ " aging at " << (mLastSweep - target) << " of " << mTargetAge;
WriteLog (lsTRACE, TaggedCacheLog) << mName << ": cache = " << mCache.size() << "-" << cacheRemovals << }
", map-=" << mapRemovals;
} 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> template<typename c_Key, typename c_Data, class Timer>
bool TaggedCache<c_Key, c_Data, Timer>::touch(const key_type& key) 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)
{ {
data_ptr d = boost::make_shared<c_Data>(boost::cref(data)); // If present, make current in cache
return canonicalize(key, d); 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> template<typename c_Key, typename c_Data, class Timer>
bool TaggedCache<c_Key, c_Data, Timer>::retrieve(const key_type& key, c_Data& data) bool TaggedCache<c_Key, c_Data, Timer>::del (const key_type& key, bool valid)
{ // retrieve the value of the stored data {
data_ptr entry = fetch(key); // Remove from cache, if !valid, remove from map too. Returns true if removed from cache
if (!entry) boost::recursive_mutex::scoped_lock sl (mLock);
return false;
data = *entry; cache_iterator cit = mCache.find (key);
return true;
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 #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 Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies. copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 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 @file ripple_basics.cpp
@ingroup ripple_basics @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 Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies. copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 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 @file ripple_basics.h
@ingroup ripple_basics @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 #ifndef RIPPLE_BASICS_H
@@ -57,9 +57,9 @@
// Forward declaration // Forward declaration
/* /*
namespace boost { namespace boost {
namespace filesystem { namespace filesystem {
class path; class path;
} }
} }
*/ */
#include <boost/filesystem.hpp> // VFALCO TODO try to eliminate thie dependency #include <boost/filesystem.hpp> // VFALCO TODO try to eliminate thie dependency
@@ -97,7 +97,7 @@ namespace boost {
// ByteOrder // ByteOrder
#ifdef WIN32 #ifdef WIN32
// (nothing) // (nothing)
#elif __APPLE__ #elif __APPLE__
# include <libkern/OSByteOrder.h> # include <libkern/OSByteOrder.h>
#elif defined(__FreeBSD__) || defined(__NetBSD__) #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> //#include <windows.h>
// from: http://stackoverflow.com/questions/3022552/is-there-any-standard-htonl-like-function-for-64-bits-integers-in-c // 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 // 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 // The answer is 42
//static const int num = 42; //static const int num = 42;
// Check the endianness // Check the endianness
//if (*reinterpret_cast<const char*>(&num) == num) //if (*reinterpret_cast<const char*>(&num) == num)
//{ //{
const uint32_t high_part = htonl(static_cast<uint32_t>(value >> 32)); const uint32_t high_part = htonl (static_cast<uint32_t> (value >> 32));
const uint32_t low_part = htonl(static_cast<uint32_t>(value & 0xFFFFFFFFLL)); const uint32_t low_part = htonl (static_cast<uint32_t> (value & 0xFFFFFFFFLL));
return (static_cast<uint64_t>(low_part) << 32) | high_part; return (static_cast<uint64_t> (low_part) << 32) | high_part;
//} else //} else
//{ //{
// return value; // 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 #endif

View File

@@ -7,10 +7,10 @@
// VFALCO TODO use VFLIB_* platform macros instead of hard-coded compiler specific ones // VFALCO TODO use VFLIB_* platform macros instead of hard-coded compiler specific ones
#ifdef WIN32 #ifdef WIN32
extern uint64_t htobe64(uint64_t value); extern uint64_t htobe64 (uint64_t value);
extern uint64_t be64toh(uint64_t value); extern uint64_t be64toh (uint64_t value);
extern uint32_t htobe32(uint32_t value); extern uint32_t htobe32 (uint32_t value);
extern uint32_t be32toh(uint32_t value); extern uint32_t be32toh (uint32_t value);
#elif __APPLE__ #elif __APPLE__
#include <libkern/OSByteOrder.h> #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; DH* dh = 0;
int iCodes; int iCodes;
std::string strDer; std::string strDer;
do { do
dh = DH_generate_parameters(iKeyLength, DH_GENERATOR_5, NULL, NULL); {
iCodes = 0; dh = DH_generate_parameters (iKeyLength, DH_GENERATOR_5, NULL, NULL);
DH_check(dh, &iCodes); iCodes = 0;
} while (iCodes & (DH_CHECK_P_NOT_PRIME|DH_CHECK_P_NOT_SAFE_PRIME|DH_UNABLE_TO_CHECK_GENERATOR|DH_NOT_SUITABLE_GENERATOR)); 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 // vim:ts=4

View File

@@ -4,60 +4,60 @@
// VFALCO NOTE these came from BitcoinUtil.h // VFALCO NOTE these came from BitcoinUtil.h
// VFALCO TODO Rewrite the callers so we don't need templates, // 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> 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]; static unsigned char pblank[1];
uint256 hash1; uint256 hash1;
SHA256((pbegin == pend ? pblank : (unsigned char*)&pbegin[0]), (pend - pbegin) * sizeof(pbegin[0]), (unsigned char*)&hash1); SHA256 ((pbegin == pend ? pblank : (unsigned char*)&pbegin[0]), (pend - pbegin) * sizeof (pbegin[0]), (unsigned char*)&hash1);
uint256 hash2; uint256 hash2;
SHA256((unsigned char*)&hash1, sizeof(hash1), (unsigned char*)&hash2); SHA256 ((unsigned char*)&hash1, sizeof (hash1), (unsigned char*)&hash2);
return hash2; return hash2;
} }
template<typename T1, typename T2> template<typename T1, typename T2>
inline uint256 SHA256Hash(const T1 p1begin, const T1 p1end, inline uint256 SHA256Hash (const T1 p1begin, const T1 p1end,
const T2 p2begin, const T2 p2end) const T2 p2begin, const T2 p2end)
{ {
static unsigned char pblank[1]; static unsigned char pblank[1];
uint256 hash1; uint256 hash1;
SHA256_CTX ctx; SHA256_CTX ctx;
SHA256_Init(&ctx); SHA256_Init (&ctx);
SHA256_Update(&ctx, (p1begin == p1end ? pblank : (unsigned char*)&p1begin[0]), (p1end - p1begin) * sizeof(p1begin[0])); 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, (p2begin == p2end ? pblank : (unsigned char*)&p2begin[0]), (p2end - p2begin) * sizeof (p2begin[0]));
SHA256_Final((unsigned char*)&hash1, &ctx); SHA256_Final ((unsigned char*)&hash1, &ctx);
uint256 hash2; uint256 hash2;
SHA256((unsigned char*)&hash1, sizeof(hash1), (unsigned char*)&hash2); SHA256 ((unsigned char*)&hash1, sizeof (hash1), (unsigned char*)&hash2);
return hash2; return hash2;
} }
template<typename T1, typename T2, typename T3> template<typename T1, typename T2, typename T3>
inline uint256 SHA256Hash(const T1 p1begin, const T1 p1end, inline uint256 SHA256Hash (const T1 p1begin, const T1 p1end,
const T2 p2begin, const T2 p2end, const T2 p2begin, const T2 p2end,
const T3 p3begin, const T3 p3end) const T3 p3begin, const T3 p3end)
{ {
static unsigned char pblank[1]; static unsigned char pblank[1];
uint256 hash1; uint256 hash1;
SHA256_CTX ctx; SHA256_CTX ctx;
SHA256_Init(&ctx); SHA256_Init (&ctx);
SHA256_Update(&ctx, (p1begin == p1end ? pblank : (unsigned char*)&p1begin[0]), (p1end - p1begin) * sizeof(p1begin[0])); 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, (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_Update (&ctx, (p3begin == p3end ? pblank : (unsigned char*)&p3begin[0]), (p3end - p3begin) * sizeof (p3begin[0]));
SHA256_Final((unsigned char*)&hash1, &ctx); SHA256_Final ((unsigned char*)&hash1, &ctx);
uint256 hash2; uint256 hash2;
SHA256((unsigned char*)&hash1, sizeof(hash1), (unsigned char*)&hash2); SHA256 ((unsigned char*)&hash1, sizeof (hash1), (unsigned char*)&hash2);
return hash2; return hash2;
} }
inline uint160 Hash160(Blob const& vch) inline uint160 Hash160 (Blob const& vch)
{ {
uint256 hash1; uint256 hash1;
SHA256(&vch[0], vch.size(), (unsigned char*)&hash1); SHA256 (&vch[0], vch.size (), (unsigned char*)&hash1);
uint160 hash2; uint160 hash2;
RIPEMD160((unsigned char*)&hash1, sizeof(hash1), (unsigned char*)&hash2); RIPEMD160 ((unsigned char*)&hash1, sizeof (hash1), (unsigned char*)&hash2);
return hash2; return hash2;
} }
/* /*
@@ -78,11 +78,11 @@ inline uint160 Hash160(Blob const& vch)
#define PAGESIZE sysconf(_SC_PAGESIZE) #define PAGESIZE sysconf(_SC_PAGESIZE)
#endif #endif
#define mlock(a,b) \ #define mlock(a,b) \
mlock(((void *)(((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)))) (((((size_t)(a)) + (b) - 1) | ((PAGESIZE) - 1)) + 1) - (((size_t)(a)) & (~((PAGESIZE) - 1))))
#define munlock(a,b) \ #define munlock(a,b) \
munlock(((void *)(((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)))) (((((size_t)(a)) + (b) - 1) | ((PAGESIZE) - 1)) + 1) - (((size_t)(a)) & (~((PAGESIZE) - 1))))
#endif #endif
*/ */

View File

@@ -2,14 +2,17 @@
InstanceType* InstanceType::sHeadInstance = NULL; InstanceType* InstanceType::sHeadInstance = NULL;
bool InstanceType::sMultiThreaded = false; bool InstanceType::sMultiThreaded = false;
std::vector<InstanceType::InstanceCount> InstanceType::getInstanceCounts(int min) std::vector<InstanceType::InstanceCount> InstanceType::getInstanceCounts (int min)
{ {
std::vector<InstanceCount> ret; std::vector<InstanceCount> ret;
for (InstanceType* i = sHeadInstance; i != NULL; i = i->mNextInstance)
{ for (InstanceType* i = sHeadInstance; i != NULL; i = i->mNextInstance)
int c = i->getCount(); {
if (c >= min) int c = i->getCount ();
ret.push_back(InstanceCount(i->getName(), c));
} if (c >= min)
return ret; ret.push_back (InstanceCount (i->getName (), c));
}
return ret;
} }

View File

@@ -2,24 +2,24 @@
#define RIPPLE_INSTANCECOUNTER_H #define RIPPLE_INSTANCECOUNTER_H
// VFALCO TODO Clean this up, remove the macros, replace // 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!!! // VFALCO TODO swap these. Declaration means header, definition means .cpp!!!
#define DEFINE_INSTANCE(x) \ #define DEFINE_INSTANCE(x) \
extern InstanceType IT_##x; \ extern InstanceType IT_##x; \
class Instance_##x : private Instance \ class Instance_##x : private Instance \
{ \ { \
protected: \ protected: \
Instance_##x() : Instance(IT_##x) { ; } \ Instance_##x() : Instance(IT_##x) { ; } \
Instance_##x(const Instance_##x &) : \ Instance_##x(const Instance_##x &) : \
Instance(IT_##x) { ; } \ Instance(IT_##x) { ; } \
Instance_##x& operator=(const Instance_##x&) \ Instance_##x& operator=(const Instance_##x&) \
{ return *this; } \ { return *this; } \
} }
#define DECLARE_INSTANCE(x) \ #define DECLARE_INSTANCE(x) \
InstanceType IT_##x(#x); InstanceType IT_##x(#x);
#define IS_INSTANCE(x) Instance_##x #define IS_INSTANCE(x) Instance_##x
@@ -27,84 +27,93 @@
class InstanceType class InstanceType
{ {
protected: protected:
int mInstances; int mInstances;
std::string mName; std::string mName;
boost::mutex mLock; boost::mutex mLock;
InstanceType* mNextInstance; InstanceType* mNextInstance;
static InstanceType* sHeadInstance; static InstanceType* sHeadInstance;
static bool sMultiThreaded; static bool sMultiThreaded;
public: public:
typedef std::pair<std::string, int> InstanceCount; typedef std::pair<std::string, int> InstanceCount;
explicit InstanceType (const char *n) : mInstances(0), mName(n) explicit InstanceType (const char* n) : mInstances (0), mName (n)
{ {
mNextInstance = sHeadInstance; mNextInstance = sHeadInstance;
sHeadInstance = this; sHeadInstance = this;
} }
static void multiThread() static void multiThread ()
{ {
// We can support global objects and multi-threaded code, but not both // We can support global objects and multi-threaded code, but not both
// at the same time. Switch to multi-threaded. // at the same time. Switch to multi-threaded.
sMultiThreaded = true; sMultiThreaded = true;
} }
static void shutdown() static void shutdown ()
{ {
sMultiThreaded = false; sMultiThreaded = false;
} }
static bool isMultiThread() static bool isMultiThread ()
{ {
return sMultiThreaded; return sMultiThreaded;
} }
void addInstance() void addInstance ()
{ {
if (sMultiThreaded) if (sMultiThreaded)
{ {
// VFALCO NOTE This will go away with atomics // VFALCO NOTE This will go away with atomics
mLock.lock(); mLock.lock ();
++mInstances; ++mInstances;
mLock.unlock(); mLock.unlock ();
} }
else ++mInstances; else ++mInstances;
} }
void decInstance() void decInstance ()
{ {
if (sMultiThreaded) if (sMultiThreaded)
{ {
mLock.lock(); mLock.lock ();
--mInstances; --mInstances;
mLock.unlock(); mLock.unlock ();
} }
else --mInstances; else --mInstances;
} }
int getCount() int getCount ()
{ {
boost::mutex::scoped_lock sl(mLock); boost::mutex::scoped_lock sl (mLock);
return mInstances; return mInstances;
} }
const std::string& getName() const std::string& getName ()
{ {
return mName; return mName;
} }
static std::vector<InstanceCount> getInstanceCounts(int min = 1); static std::vector<InstanceCount> getInstanceCounts (int min = 1);
}; };
class Instance class Instance
{ {
protected: protected:
static bool running; static bool running;
InstanceType& mType; InstanceType& mType;
public: public:
Instance(InstanceType& t) : mType(t) { mType.addInstance(); } Instance (InstanceType& t) : mType (t)
~Instance() { if (running) mType.decInstance(); } {
static void shutdown() { running = false; } mType.addInstance ();
}
~Instance ()
{
if (running) mType.decInstance ();
}
static void shutdown ()
{
running = false;
}
}; };
#endif #endif

View File

@@ -4,7 +4,7 @@ boost::recursive_mutex Log::sLock;
LogSeverity Log::sMinSeverity = lsINFO; LogSeverity Log::sMinSeverity = lsINFO;
std::ofstream* Log::outStream = NULL; std::ofstream* Log::outStream = NULL;
boost::filesystem::path *Log::pathToLog = NULL; boost::filesystem::path* Log::pathToLog = NULL;
uint32 Log::logRotateCounter = 0; uint32 Log::logRotateCounter = 0;
#ifndef LOG_MAX_MESSAGE #ifndef LOG_MAX_MESSAGE
@@ -13,26 +13,27 @@ uint32 Log::logRotateCounter = 0;
LogPartition* LogPartition::headLog = NULL; 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, '/'); const char* ptr = strrchr (name, '/');
mName = (ptr == NULL) ? name : (ptr + 1); mName = (ptr == NULL) ? name : (ptr + 1);
size_t p = mName.find(".cpp"); size_t p = mName.find (".cpp");
if (p != std::string::npos)
mName.erase(mName.begin() + p, mName.end());
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) for (LogPartition* l = headLog; l != NULL; l = l->mNextLog)
sevs.push_back(std::make_pair(l->mName, Log::severityToString(l->mMinSeverity))); 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\""); size_t s = ls.find("\"secret\"");
if (s != std::string::npos) if (s != std::string::npos)
{ {
s += 8; s += 8;
size_t sEnd = ls.size() - 1; size_t sEnd = ls.size() - 1;
if (sEnd > (s + 35)) if (sEnd > (s + 35))
sEnd = s + 35; sEnd = s + 35;
for (int i = s; i < sEnd; ++i) for (int i = s; i < sEnd; ++i)
ls[i] = '*'; ls[i] = '*';
} }
logMsg += ls; 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()); std::string logMsg = boost::posix_time::to_simple_string (boost::posix_time::second_clock::universal_time ());
if (!mPartitionName.empty())
logMsg += " " + mPartitionName + ":";
else
logMsg += " ";
switch (mSeverity) if (!mPartitionName.empty ())
{ logMsg += " " + mPartitionName + ":";
case lsTRACE: logMsg += "TRC "; break; else
case lsDEBUG: logMsg += "DBG "; break; logMsg += " ";
case lsINFO: logMsg += "NFO "; break;
case lsWARNING: logMsg += "WRN "; break; switch (mSeverity)
case lsERROR: logMsg += "ERR "; break; {
case lsFATAL: logMsg += "FTL "; break; case lsTRACE:
case lsINVALID: assert(false); return; 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 ()); logMsg += replaceFirstSecretWithAsterisks (oss.str ());
if (logMsg.size() > LOG_MAX_MESSAGE) if (logMsg.size () > LOG_MAX_MESSAGE)
{ {
logMsg.resize(LOG_MAX_MESSAGE); logMsg.resize (LOG_MAX_MESSAGE);
logMsg += "..."; 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!";
} }
abs_path = boost::filesystem::absolute("");
abs_path /= *pathToLog;
abs_path_str = abs_path.parent_path().string();
out << logRotateCounter; boost::recursive_mutex::scoped_lock sl (sLock);
s = out.str();
abs_new_path_str = abs_path_str + "/" + s + "_" + pathToLog->filename().string(); if (mSeverity >= sMinSeverity)
std::cerr << logMsg << std::endl;
logRotateCounter++; if (outStream != NULL)
(*outStream) << logMsg << std::endl;
} 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;
} }
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; uint32 failsafe = 0;
if (all)
LogPartition::setSeverity(s); 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) boost::recursive_mutex::scoped_lock sl (sLock);
{
case lsTRACE: return "Trace"; return sMinSeverity;
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";
}
} }
LogSeverity Log::stringToSeverity(const std::string& s) std::string Log::severityToString (LogSeverity s)
{ {
if (boost::iequals(s, "trace")) switch (s)
return lsTRACE; {
if (boost::iequals(s, "debug")) case lsTRACE:
return lsDEBUG; return "Trace";
if (boost::iequals(s, "info") || boost::iequals(s, "information"))
return lsINFO; case lsDEBUG:
if (boost::iequals(s, "warn") || boost::iequals(s, "warning") || boost::iequals(s, "warnings")) return "Debug";
return lsWARNING;
if (boost::iequals(s, "error") || boost::iequals(s, "errors")) case lsINFO:
return lsERROR; return "Info";
if (boost::iequals(s, "fatal") || boost::iequals(s, "fatals"))
return lsFATAL; case lsWARNING:
return lsINVALID; 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 (boost::iequals (s, "trace"))
if (!newStream->good()) return lsTRACE;
{
Log(lsFATAL) << "Unable to open logfile " << path;
delete newStream;
newStream = NULL;
}
boost::recursive_mutex::scoped_lock sl(sLock); if (boost::iequals (s, "debug"))
if (outStream != NULL) return lsDEBUG;
delete outStream;
outStream = newStream;
if (pathToLog != NULL) if (boost::iequals (s, "info") || boost::iequals (s, "information"))
delete pathToLog; return lsINFO;
pathToLog = new boost::filesystem::path(path);
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) std::ofstream* newStream = new std::ofstream (path.c_str (), std::fstream::app);
if (boost::iequals(p->mName, partition))
{ if (!newStream->good ())
p->mMinSeverity = severity; {
return true; Log (lsFATAL) << "Unable to open logfile " << path;
} delete newStream;
return false; 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) for (LogPartition* p = headLog; p != NULL; p = p->mNextLog)
p->mMinSeverity = severity; 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 // vim:ts=4

View File

@@ -3,13 +3,13 @@
enum LogSeverity enum LogSeverity
{ {
lsINVALID = -1, // used to indicate an invalid severity lsINVALID = -1, // used to indicate an invalid severity
lsTRACE = 0, // Very low-level progress information, details inside an operation lsTRACE = 0, // Very low-level progress information, details inside an operation
lsDEBUG = 1, // Function-level progress information, operations lsDEBUG = 1, // Function-level progress information, operations
lsINFO = 2, // Server-level progress information, major operations lsINFO = 2, // Server-level progress information, major operations
lsWARNING = 3, // Conditions that warrant human attention, may indicate a problem lsWARNING = 3, // Conditions that warrant human attention, may indicate a problem
lsERROR = 4, // A condition that indicates a problem lsERROR = 4, // A condition that indicates a problem
lsFATAL = 5 // A severe condition that indicates a server problem lsFATAL = 5 // A severe condition that indicates a server problem
}; };
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
@@ -18,80 +18,86 @@ enum LogSeverity
class LogPartition class LogPartition
{ {
protected: protected:
static LogPartition* headLog; static LogPartition* headLog;
LogPartition* mNextLog; LogPartition* mNextLog;
LogSeverity mMinSeverity; LogSeverity mMinSeverity;
std::string mName; std::string mName;
public: public:
LogPartition(const char *name); LogPartition (const char* name);
bool doLog(LogSeverity s) const { return s >= mMinSeverity; } bool doLog (LogSeverity s) const
const std::string& getName() const { return mName; } {
return s >= mMinSeverity;
}
const std::string& getName () const
{
return mName;
}
static bool setSeverity(const std::string& partition, LogSeverity severity); static bool setSeverity (const std::string& partition, LogSeverity severity);
static void setSeverity(LogSeverity severity); static void setSeverity (LogSeverity severity);
static std::vector< std::pair<std::string, std::string> > getSeverities(); static std::vector< std::pair<std::string, std::string> > getSeverities ();
private: private:
/** Retrieve file name from a log partition. /** Retrieve file name from a log partition.
*/ */
template <class Key> template <class Key>
static char const* getFileName (); static char const* getFileName ();
/* /*
{ {
static_vfassert (false); static_vfassert (false);
} }
*/ */
public: public:
template <class Key> template <class Key>
static LogPartition const& get () static LogPartition const& get ()
{ {
static LogPartition logPartition (getFileName <Key> ()); static LogPartition logPartition (getFileName <Key> ());
return logPartition; return logPartition;
} }
}; };
#define SETUP_LOG(k) \ #define SETUP_LOG(k) \
template <> char const* LogPartition::getFileName <k> () { return __FILE__; } \ template <> char const* LogPartition::getFileName <k> () { return __FILE__; } \
struct k##Instantiator { k##Instantiator () { LogPartition::get <k> (); } }; \ struct k##Instantiator { k##Instantiator () { LogPartition::get <k> (); } }; \
static k##Instantiator k##Instantiator_instance; static k##Instantiator k##Instantiator_instance;
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
class Log class Log
{ {
public: 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) : mSeverity (s)
, mPartitionName (p.getName()) , mPartitionName (p.getName ())
{ {
} }
~Log (); ~Log ();
template <class T> template <class T>
std::ostream& operator<< (const T& t) const std::ostream& operator<< (const T& t) const
{ {
return oss << t; return oss << t;
} }
std::ostringstream& ref () const std::ostringstream& ref () const
{ {
return oss; return oss;
} }
static std::string severityToString (LogSeverity); static std::string severityToString (LogSeverity);
static LogSeverity stringToSeverity (std::string const&); static LogSeverity stringToSeverity (std::string const&);
static LogSeverity getMinSeverity (); static LogSeverity getMinSeverity ();
static void setMinSeverity (LogSeverity, bool all); static void setMinSeverity (LogSeverity, bool all);
@@ -101,24 +107,24 @@ public:
private: private:
// VFALCO TODO derive from beast::Uncopyable // VFALCO TODO derive from beast::Uncopyable
Log (const Log&); // no implementation Log (const Log&); // no implementation
Log& operator= (const Log&); // no implementation Log& operator= (const Log&); // no implementation
// VFALCO TODO looks like there are really TWO classes in here. // VFALCO TODO looks like there are really TWO classes in here.
// One is a stream target for '<<' operator and the other // One is a stream target for '<<' operator and the other
// is a singleton. Split the singleton out to a new class. // is a singleton. Split the singleton out to a new class.
// //
static boost::recursive_mutex sLock; static boost::recursive_mutex sLock;
static LogSeverity sMinSeverity; static LogSeverity sMinSeverity;
static std::ofstream* outStream; static std::ofstream* outStream;
static boost::filesystem::path *pathToLog; static boost::filesystem::path* pathToLog;
static uint32 logRotateCounter; static uint32 logRotateCounter;
static std::string replaceFirstSecretWithAsterisks (std::string s); static std::string replaceFirstSecretWithAsterisks (std::string s);
mutable std::ostringstream oss; mutable std::ostringstream oss;
LogSeverity mSeverity; LogSeverity mSeverity;
std::string mPartitionName; std::string mPartitionName;
}; };
// Manually test for whether we should log // 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 Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies. copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/ */
//============================================================================== //==============================================================================
@@ -26,33 +26,33 @@
// VFALCO TODO replace BIND_TYPE with a namespace lift // VFALCO TODO replace BIND_TYPE with a namespace lift
#define C11X #define C11X
#include <functional> #include <functional>
#define UPTR_T std::unique_ptr #define UPTR_T std::unique_ptr
#define MOVE_P(p) std::move(p) #define MOVE_P(p) std::move(p)
#define BIND_TYPE std::bind #define BIND_TYPE std::bind
#define FUNCTION_TYPE std::function #define FUNCTION_TYPE std::function
#define P_1 std::placeholders::_1 #define P_1 std::placeholders::_1
#define P_2 std::placeholders::_2 #define P_2 std::placeholders::_2
#define P_3 std::placeholders::_3 #define P_3 std::placeholders::_3
#define P_4 std::placeholders::_4 #define P_4 std::placeholders::_4
#else #else
#define UPTR_T std::auto_ptr #define UPTR_T std::auto_ptr
#define MOVE_P(p) (p) #define MOVE_P(p) (p)
#define BIND_TYPE boost::bind #define BIND_TYPE boost::bind
#define FUNCTION_TYPE boost::function #define FUNCTION_TYPE boost::function
#define P_1 _1 #define P_1 _1
#define P_2 _2 #define P_2 _2
#define P_3 _3 #define P_3 _3
#define P_4 _4 #define P_4 _4
#endif #endif
// VFALCO TODO Clean this junk up // VFALCO TODO Clean this junk up
#define nothing() do {} while (0) #define nothing() do {} while (0)
#define fallthru() do {} while (0) #define fallthru() do {} while (0)
#define NUMBER(x) (sizeof(x)/sizeof((x)[0])) #define NUMBER(x) (sizeof(x)/sizeof((x)[0]))
#define isSetBit(x,y) (!!((x) & (y))) #define isSetBit(x,y) (!!((x) & (y)))
#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 Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies. copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/ */
//============================================================================== //==============================================================================
@@ -55,15 +55,15 @@ void RandomNumbers::fillBytes (void* destinationBuffer, int numberOfBytes)
} }
#ifdef PURIFY #ifdef PURIFY
memset (destinationBuffer, 0, numberOfBytes); memset (destinationBuffer, 0, numberOfBytes);
#endif #endif
if (RAND_bytes (reinterpret_cast <unsigned char*> (destinationBuffer), numberOfBytes) != 1) if (RAND_bytes (reinterpret_cast <unsigned char*> (destinationBuffer), numberOfBytes) != 1)
{ {
assert(false); assert (false);
throw std::runtime_error ("Entropy pool not seeded"); throw std::runtime_error ("Entropy pool not seeded");
} }
} }
RandomNumbers& RandomNumbers::getInstance () RandomNumbers& RandomNumbers::getInstance ()
@@ -82,68 +82,72 @@ RandomNumbers& RandomNumbers::getInstance ()
// Get entropy from the Windows crypto provider // Get entropy from the Windows crypto provider
bool RandomNumbers::platformAddEntropy () bool RandomNumbers::platformAddEntropy ()
{ {
char name[512], rand[128]; char name[512], rand[128];
DWORD count = 500; DWORD count = 500;
HCRYPTPROV cryptoHandle; 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 #ifdef DEBUG
std::cerr << "Unable to get default crypto provider" << std::endl; std::cerr << "Unable to get default crypto provider" << std::endl;
#endif #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 #ifdef DEBUG
std::cerr << "Unable to acquire crypto provider" << std::endl; std::cerr << "Unable to acquire crypto provider" << std::endl;
#endif #endif
return false; return false;
} }
if(!CryptGenRandom(cryptoHandle, 128, reinterpret_cast<BYTE*>(rand))) if (!CryptGenRandom (cryptoHandle, 128, reinterpret_cast<BYTE*> (rand)))
{ {
#ifdef DEBUG #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 #endif
CryptReleaseContext(cryptoHandle, 0); CryptReleaseContext (cryptoHandle, 0);
return false; return false;
} }
CryptReleaseContext(cryptoHandle, 0); CryptReleaseContext (cryptoHandle, 0);
RAND_seed(rand, 128); RAND_seed (rand, 128);
return true; return true;
} }
#else #else
bool RandomNumbers::platformAddEntropy () bool RandomNumbers::platformAddEntropy ()
{ {
char rand[128]; char rand[128];
std::ifstream reader; std::ifstream reader;
reader.open("/dev/urandom", std::ios::in | std::ios::binary); 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);
int bytesRead = reader.gcount(); if (!reader.is_open ())
if (bytesRead == 0) {
{
#ifdef DEBUG #ifdef DEBUG
std::cerr << "Unable to read from random source" << std::endl; std::cerr << "Unable to open random source" << std::endl;
#endif #endif
return false; return false;
} }
RAND_seed(rand, bytesRead);
return bytesRead >= 64; 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 #endif
@@ -161,63 +165,67 @@ bool RandomNumbers::platformAddEntropy ()
void RandomNumbers::platformAddPerformanceMonitorEntropy () void RandomNumbers::platformAddPerformanceMonitorEntropy ()
{ {
// VFALCO TODO Remove all this fancy stuff // VFALCO TODO Remove all this fancy stuff
struct struct
{ {
int64 operator() () const int64 operator () () const
{ {
return time (NULL); return time (NULL);
} }
} GetTime; } GetTime;
struct struct
{ {
void operator() () void operator () ()
{ {
struct struct
{ {
// VFALCO TODO clean this up // VFALCO TODO clean this up
int64 operator() () const int64 operator () () const
{ {
int64 nCounter = 0; int64 nCounter = 0;
#if defined(WIN32) || defined(WIN64) #if defined(WIN32) || defined(WIN64)
QueryPerformanceCounter((LARGE_INTEGER*)&nCounter); QueryPerformanceCounter ((LARGE_INTEGER*)&nCounter);
#else #else
timeval t; timeval t;
gettimeofday(&t, NULL); gettimeofday (&t, NULL);
nCounter = t.tv_sec * 1000000 + t.tv_usec; nCounter = t.tv_sec * 1000000 + t.tv_usec;
#endif #endif
return nCounter; return nCounter;
} }
} GetPerformanceCounter; } GetPerformanceCounter;
// Seed with CPU performance counter // Seed with CPU performance counter
int64 nCounter = GetPerformanceCounter(); int64 nCounter = GetPerformanceCounter ();
RAND_add(&nCounter, sizeof(nCounter), 1.5); RAND_add (&nCounter, sizeof (nCounter), 1.5);
memset(&nCounter, 0, sizeof(nCounter)); memset (&nCounter, 0, sizeof (nCounter));
} }
} RandAddSeed; } RandAddSeed;
RandAddSeed(); RandAddSeed ();
// This can take up to 2 seconds, so only do it every 10 minutes // This can take up to 2 seconds, so only do it every 10 minutes
static int64 nLastPerfmon; static int64 nLastPerfmon;
if (GetTime () < nLastPerfmon + 10 * 60)
return; if (GetTime () < nLastPerfmon + 10 * 60)
nLastPerfmon = GetTime (); return;
nLastPerfmon = GetTime ();
#ifdef WIN32 #ifdef WIN32
// Don't need this on Linux, OpenSSL automatically uses /dev/urandom // Don't need this on Linux, OpenSSL automatically uses /dev/urandom
// Seed with the entire set of perfmon data // Seed with the entire set of perfmon data
unsigned char pdata[250000]; unsigned char pdata[250000];
memset(pdata, 0, sizeof(pdata)); memset (pdata, 0, sizeof (pdata));
unsigned long nSize = sizeof(pdata); unsigned long nSize = sizeof (pdata);
long ret = RegQueryValueExA(HKEY_PERFORMANCE_DATA, "Global", NULL, NULL, pdata, &nSize); long ret = RegQueryValueExA (HKEY_PERFORMANCE_DATA, "Global", NULL, NULL, pdata, &nSize);
RegCloseKey(HKEY_PERFORMANCE_DATA); RegCloseKey (HKEY_PERFORMANCE_DATA);
if (ret == ERROR_SUCCESS)
{ if (ret == ERROR_SUCCESS)
RAND_add(pdata, nSize, nSize/100.0); {
memset(pdata, 0, nSize); RAND_add (pdata, nSize, nSize / 100.0);
//printf("%s RandAddSeed() %d bytes\n", DateTimeStrFormat("%x %H:%M", GetTime()).c_str(), nSize); memset (pdata, 0, nSize);
} //printf("%s RandAddSeed() %d bytes\n", DateTimeStrFormat("%x %H:%M", GetTime()).c_str(), nSize);
}
#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 Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies. copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 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 class SharedScopedLock
{ {
protected: protected:
mutable boost::shared_ptr<boost::recursive_mutex::scoped_lock> mHolder; mutable boost::shared_ptr<boost::recursive_mutex::scoped_lock> mHolder;
public: public:
SharedScopedLock(boost::recursive_mutex& mutex) : SharedScopedLock (boost::recursive_mutex& mutex) :
mHolder(boost::make_shared<boost::recursive_mutex::scoped_lock>(boost::ref(mutex))) { ; } mHolder (boost::make_shared<boost::recursive_mutex::scoped_lock> (boost::ref (mutex)))
{
;
}
void lock() const { mHolder->lock(); } void lock () const
void unlock() const { mHolder->unlock(); } {
mHolder->lock ();
}
void unlock () const
{
mHolder->unlock ();
}
}; };
// A class that unlocks on construction and locks on destruction // A class that unlocks on construction and locks on destruction
@@ -26,44 +35,44 @@ public:
class ScopedUnlock class ScopedUnlock
{ {
protected: protected:
bool mUnlocked; bool mUnlocked;
boost::recursive_mutex& mMutex; boost::recursive_mutex& mMutex;
public: public:
// VFALCO TODO get rid of this unlock parameter to restore sanity // VFALCO TODO get rid of this unlock parameter to restore sanity
ScopedUnlock(boost::recursive_mutex& mutex, bool unlock = true) : mUnlocked(unlock), mMutex(mutex) ScopedUnlock (boost::recursive_mutex& mutex, bool unlock = true) : mUnlocked (unlock), mMutex (mutex)
{ {
if (unlock) if (unlock)
mMutex.unlock(); mMutex.unlock ();
} }
~ScopedUnlock() ~ScopedUnlock ()
{ {
if (mUnlocked) if (mUnlocked)
mMutex.lock(); mMutex.lock ();
} }
void lock() void lock ()
{ {
if (mUnlocked) if (mUnlocked)
{ {
mMutex.lock(); mMutex.lock ();
mUnlocked = false; mUnlocked = false;
} }
} }
void unlock() void unlock ()
{ {
if (!mUnlocked) if (!mUnlocked)
{ {
mUnlocked = true; mUnlocked = true;
mMutex.unlock(); mMutex.unlock ();
} }
} }
private: private:
ScopedUnlock(const ScopedUnlock&); // no implementation ScopedUnlock (const ScopedUnlock&); // no implementation
ScopedUnlock& operator=(const ScopedUnlock&); // no implementation ScopedUnlock& operator= (const ScopedUnlock&); // no implementation
}; };
#endif #endif

View File

@@ -3,293 +3,304 @@
#define _vsnprintf(a,b,c,d) vsnprintf(a,b,c,d) #define _vsnprintf(a,b,c,d) vsnprintf(a,b,c,d)
#endif #endif
std::string strprintf(const char* format, ...) std::string strprintf (const char* format, ...)
{ {
char buffer[50000]; char buffer[50000];
char* p = buffer; char* p = buffer;
int limit = sizeof(buffer); int limit = sizeof (buffer);
int ret; int ret;
for (;;)
{ for (;;)
va_list arg_ptr; {
va_start(arg_ptr, format); va_list arg_ptr;
ret = _vsnprintf(p, limit, format, arg_ptr); va_start (arg_ptr, format);
va_end(arg_ptr); ret = _vsnprintf (p, limit, format, arg_ptr);
if (ret >= 0 && ret < limit) va_end (arg_ptr);
break;
if (p != buffer) if (ret >= 0 && ret < limit)
delete[] p; break;
limit *= 2;
p = new char[limit]; if (p != buffer)
if (p == NULL) delete[] p;
throw std::bad_alloc();
} limit *= 2;
std::string str(p, p+ret); p = new char[limit];
if (p != buffer)
delete[] p; if (p == NULL)
return str; 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' return cDigit >= '0' && cDigit <= '9'
? cDigit - '0' ? cDigit - '0'
: cDigit >= 'A' && cDigit <= 'F' : cDigit >= 'A' && cDigit <= 'F'
? cDigit - 'A' + 10 ? cDigit - 'A' + 10
: cDigit >= 'a' && cDigit <= 'f' : cDigit >= 'a' && cDigit <= 'f'
? cDigit - 'a' + 10 ? cDigit - 'a' + 10
: -1; : -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]; const char* pSrc = &strSrc[0];
char* pDst = &strDst[0]; char* pDst = &strDst[0];
if (strSrc.size() & 1) if (strSrc.size () & 1)
{ {
int c = charUnHex(*pSrc++); int c = charUnHex (*pSrc++);
if (c < 0) if (c < 0)
{ {
iBytes = -1; iBytes = -1;
} }
else else
{ {
*pDst++ = c; *pDst++ = c;
} }
} }
for (int i=0; iBytes >= 0 && i != iBytes; i++) for (int i = 0; iBytes >= 0 && i != iBytes; i++)
{ {
int cHigh = charUnHex(*pSrc++); int cHigh = charUnHex (*pSrc++);
int cLow = charUnHex(*pSrc++); int cLow = charUnHex (*pSrc++);
if (cHigh < 0 || cLow < 0) if (cHigh < 0 || cLow < 0)
{ {
iBytes = -1; iBytes = -1;
} }
else else
{ {
strDst[i] = (cHigh << 4) | cLow; strDst[i] = (cHigh << 4) | cLow;
} }
} }
if (iBytes < 0) if (iBytes < 0)
strDst.clear(); 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) BOOST_FOREACH (char c, strSrc)
uValue = (uValue << 4) | charUnHex(c); uValue = (uValue << 4) | charUnHex (c);
return uValue; return uValue;
} }
// //
// Misc string // 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; std::string strDst;
int iOutput = 0; int iOutput = 0;
int iSize = strSrc.length(); int iSize = strSrc.length ();
strDst.resize(iSize*3); strDst.resize (iSize * 3);
for (int iInput = 0; iInput < iSize; iInput++) { for (int iInput = 0; iInput < iSize; iInput++)
unsigned char c = strSrc[iInput]; {
unsigned char c = strSrc[iInput];
if (c == ' ') if (c == ' ')
{ {
strDst[iOutput++] = '+'; strDst[iOutput++] = '+';
} }
else if (isalnum(c)) else if (isalnum (c))
{ {
strDst[iOutput++] = c; strDst[iOutput++] = c;
} }
else else
{ {
strDst[iOutput++] = '%'; strDst[iOutput++] = '%';
strDst[iOutput++] = charHex(c >> 4); strDst[iOutput++] = charHex (c >> 4);
strDst[iOutput++] = charHex(c & 15); strDst[iOutput++] = charHex (c & 15);
} }
} }
strDst.resize(iOutput); strDst.resize (iOutput);
return strDst; return strDst;
} }
// //
// IP Port parsing // IP Port parsing
// //
// <-- iPort: "" = -1 // <-- 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; boost::smatch smMatch;
bool bValid = false; 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)) if (boost::regex_match (strSource, smMatch, reEndpoint))
{ {
boost::system::error_code err; boost::system::error_code err;
std::string strIPRaw = smMatch[1]; std::string strIPRaw = smMatch[1];
std::string strPortRaw = smMatch[2]; 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; bValid = !err;
if (bValid)
{
strIP = addrIP.to_string();
iPort = strPortRaw.empty() ? -1 : boost::lexical_cast<int>(strPortRaw);
}
}
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 // scheme://username:password@hostname:port/rest
static boost::regex reUrl("(?i)\\`\\s*([[:alpha:]][-+.[:alpha:][:digit:]]*)://([^:/]+)(?::(\\d+))?(/.*)?\\s*?\\'"); static boost::regex reUrl ("(?i)\\`\\s*([[:alpha:]][-+.[:alpha:][:digit:]]*)://([^:/]+)(?::(\\d+))?(/.*)?\\s*?\\'");
boost::smatch smMatch; 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) if (bMatch)
{ {
std::string strPort; std::string strPort;
strScheme = smMatch[1]; strScheme = smMatch[1];
strDomain = smMatch[2]; strDomain = smMatch[2];
strPort = smMatch[3]; strPort = smMatch[3];
strPath = smMatch[4]; strPath = smMatch[4];
boost::algorithm::to_lower(strScheme); boost::algorithm::to_lower (strScheme);
iPort = strPort.empty() ? -1 : lexical_cast_s<int>(strPort); iPort = strPort.empty () ? -1 : lexical_cast_s<int> (strPort);
// std::cerr << strUrl << " : " << bMatch << " : '" << strDomain << "' : '" << strPort << "' : " << iPort << " : '" << strPath << "'" << std::endl; // std::cerr << strUrl << " : " << bMatch << " : '" << strDomain << "' : '" << strPort << "' : " << iPort << " : '" << strPath << "'" << std::endl;
} }
// std::cerr << strUrl << " : " << bMatch << " : '" << strDomain << "' : '" << strPath << "'" << std::endl;
return bMatch; // std::cerr << strUrl << " : " << bMatch << " : '" << strDomain << "' : '" << strPath << "'" << std::endl;
return bMatch;
} }
// //
// Quality parsing // Quality parsing
// - integers as is. // - integers as is.
// - floats multiplied by a billion // - 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) if (!uQuality)
{ {
float fQuality = lexical_cast_s<float>(strSource); float fQuality = lexical_cast_s<float> (strSource);
if (fQuality) if (fQuality)
uQuality = (uint32)(QUALITY_ONE*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 strScheme;
std::string strDomain; std::string strDomain;
int iPort; int iPort;
std::string strPath; std::string strPath;
if (!parseUrl("lower://domain", strScheme, strDomain, iPort, strPath)) if (!parseUrl ("lower://domain", strScheme, strDomain, iPort, strPath))
BOOST_FAIL("parseUrl: lower://domain failed"); BOOST_FAIL ("parseUrl: lower://domain failed");
if (strScheme != "lower") if (strScheme != "lower")
BOOST_FAIL("parseUrl: lower://domain : scheme failed"); BOOST_FAIL ("parseUrl: lower://domain : scheme failed");
if (strDomain != "domain") if (strDomain != "domain")
BOOST_FAIL("parseUrl: lower://domain : domain failed"); BOOST_FAIL ("parseUrl: lower://domain : domain failed");
if (iPort != -1) if (iPort != -1)
BOOST_FAIL("parseUrl: lower://domain : port failed"); BOOST_FAIL ("parseUrl: lower://domain : port failed");
if (strPath != "") if (strPath != "")
BOOST_FAIL("parseUrl: lower://domain : path failed"); BOOST_FAIL ("parseUrl: lower://domain : path failed");
if (!parseUrl("UPPER://domain:234/", strScheme, strDomain, iPort, strPath)) if (!parseUrl ("UPPER://domain:234/", strScheme, strDomain, iPort, strPath))
BOOST_FAIL("parseUrl: UPPER://domain:234/ failed"); BOOST_FAIL ("parseUrl: UPPER://domain:234/ failed");
if (strScheme != "upper") if (strScheme != "upper")
BOOST_FAIL("parseUrl: UPPER://domain:234/ : scheme failed"); BOOST_FAIL ("parseUrl: UPPER://domain:234/ : scheme failed");
if (iPort != 234) if (iPort != 234)
BOOST_FAIL(boost::str(boost::format("parseUrl: UPPER://domain:234/ : port failed: %d") % iPort)); BOOST_FAIL (boost::str (boost::format ("parseUrl: UPPER://domain:234/ : port failed: %d") % iPort));
if (strPath != "/") if (strPath != "/")
BOOST_FAIL("parseUrl: UPPER://domain:234/ : path failed"); BOOST_FAIL ("parseUrl: UPPER://domain:234/ : path failed");
if (!parseUrl("Mixed://domain/path", strScheme, strDomain, iPort, strPath)) if (!parseUrl ("Mixed://domain/path", strScheme, strDomain, iPort, strPath))
BOOST_FAIL("parseUrl: Mixed://domain/path failed"); BOOST_FAIL ("parseUrl: Mixed://domain/path failed");
if (strScheme != "mixed") if (strScheme != "mixed")
BOOST_FAIL("parseUrl: Mixed://domain/path tolower failed"); BOOST_FAIL ("parseUrl: Mixed://domain/path tolower failed");
if (strPath != "/path") if (strPath != "/path")
BOOST_FAIL("parseUrl: Mixed://domain/path path failed"); BOOST_FAIL ("parseUrl: Mixed://domain/path path failed");
} }
BOOST_AUTO_TEST_SUITE_END() BOOST_AUTO_TEST_SUITE_END ()
// vim:ts=4 // vim:ts=4

View File

@@ -8,7 +8,7 @@
// Ripple specific constant used for parsing qualities and other things // 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> 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++) for (Iterator start = first; first != last; first++)
{ {
ossValues << str(boost::format("%s%s") % (start == first ? "" : strSeperator) % *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> 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++) { for (int i = 0; i < iSize; i++)
unsigned char c = *first++; {
unsigned char c = *first++;
strDst[i*2] = charHex(c >> 4); strDst[i * 2] = charHex (c >> 4);
strDst[i*2+1] = charHex(c & 15); 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'"); static boost::format f ("X'%s'");
return str(boost::format(f) % strHex(strSrc)); 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(); size_t size = vecSrc.size ();
if (size == 0)
return "X''";
std::string j(size * 2 + 3, 0); if (size == 0)
return "X''";
unsigned char *oPtr = reinterpret_cast<unsigned char *>(&*j.begin()); std::string j (size * 2 + 3, 0);
const unsigned char *iPtr = &vecSrc[0];
*oPtr++ = 'X'; unsigned char* oPtr = reinterpret_cast<unsigned char*> (&*j.begin ());
*oPtr++ = '\''; const unsigned char* iPtr = &vecSrc[0];
for (int i = size; i != 0; --i) *oPtr++ = 'X';
{ *oPtr++ = '\'';
unsigned char c = *iPtr++;
*oPtr++ = charHex(c >> 4);
*oPtr++ = charHex(c & 15);
}
*oPtr++ = '\''; for (int i = size; i != 0; --i)
return j; {
unsigned char c = *iPtr++;
*oPtr++ = charHex (c >> 4);
*oPtr++ = charHex (c & 15);
}
*oPtr++ = '\'';
return j;
} }
template<class Iterator> template<class Iterator>
bool isZero(Iterator first, int iSize) bool isZero (Iterator first, int iSize)
{ {
while (iSize && !*first++) while (iSize && !*first++)
--iSize; --iSize;
return !iSize; return !iSize;
} }
int charUnHex(char cDigit); int charUnHex (char cDigit);
int strUnHex(std::string& strDst, const std::string& strSrc); 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); Blob strCopy (const std::string& strSrc);
std::string strCopy(Blob const& vucSrc); std::string strCopy (Blob const& vucSrc);
bool parseIpPort(const std::string& strSource, std::string& strIP, int& iPort); bool parseIpPort (const std::string& strSource, std::string& strIP, int& iPort);
bool parseQuality(const std::string& strSource, uint32& uQuality); 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) template<typename T> T lexical_cast_s (const std::string& string)
{ // lexically cast a string to the selected type. Does not throw {
try // lexically cast a string to the selected type. Does not throw
{ try
return boost::lexical_cast<T>(string); {
} return boost::lexical_cast<T> (string);
catch (...) }
{ catch (...)
return 0; {
} return 0;
}
} }
template<typename T> std::string lexical_cast_i(const T& t) template<typename T> std::string lexical_cast_i (const T& t)
{ // lexicaly cast the selected type to a string. Does not throw {
try // lexicaly cast the selected type to a string. Does not throw
{ try
return boost::lexical_cast<std::string>(t); {
} return boost::lexical_cast<std::string> (t);
catch (...) }
{ catch (...)
return ""; {
} return "";
}
} }
template<typename T> T lexical_cast_st(const std::string& 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); // 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) 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); // 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 #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 Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies. copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/ */
//============================================================================== //==============================================================================
#ifdef __unix__ #ifdef __unix__
static pid_t pManager = static_cast<pid_t>(0); static pid_t pManager = static_cast<pid_t> (0);
static pid_t pChild = 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); kill (pChild, SIGINT);
_exit(0); _exit (0);
} }
bool HaveSustain() bool HaveSustain ()
{ {
return true; return true;
} }
std::string StopSustain() std::string StopSustain ()
{ {
if (getppid() != pManager) if (getppid () != pManager)
return std::string(); return std::string ();
kill(pManager, SIGHUP);
return "Terminating monitor"; kill (pManager, SIGHUP);
return "Terminating monitor";
} }
std::string DoSustain() std::string DoSustain ()
{ {
int childCount = 0; int childCount = 0;
pManager = getpid(); pManager = getpid ();
signal(SIGINT, stop_manager); signal (SIGINT, stop_manager);
signal(SIGHUP, stop_manager); signal (SIGHUP, stop_manager);
signal(SIGUSR1, pass_signal); signal (SIGUSR1, pass_signal);
signal(SIGUSR2, pass_signal); signal (SIGUSR2, pass_signal);
while (1)
{ while (1)
++childCount; {
pChild = fork(); ++childCount;
if (pChild == -1) pChild = fork ();
_exit(0);
if (pChild == 0) if (pChild == -1)
{ _exit (0);
setCallingThreadName("main");
signal(SIGINT, SIG_DFL); if (pChild == 0)
signal(SIGHUP, SIG_DFL); {
signal(SIGUSR1, SIG_DFL); setCallingThreadName ("main");
signal(SIGUSR2, SIG_DFL); signal (SIGINT, SIG_DFL);
return str(boost::format("Launching child %d") % childCount);; signal (SIGHUP, SIG_DFL);
} signal (SIGUSR1, SIG_DFL);
setCallingThreadName(boost::str(boost::format("#%d") % childCount).c_str()); signal (SIGUSR2, SIG_DFL);
do return str (boost::format ("Launching child %d") % childCount);;
{ }
int i;
sleep(10); setCallingThreadName (boost::str (boost::format ("#%d") % childCount).c_str ());
waitpid(-1, &i, 0);
} do
while (kill(pChild, 0) == 0); {
rename("core", boost::str(boost::format("core.%d") % static_cast<int>(pChild)).c_str()); int i;
rename("debug.log", boost::str(boost::format("debug.log.%d") % static_cast<int>(pChild)).c_str()); 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 #else
bool HaveSustain() { return false; } bool HaveSustain ()
std::string DoSustain() { return std::string(); } {
std::string StopSustain() { return std::string(); } return false;
}
std::string DoSustain ()
{
return std::string ();
}
std::string StopSustain ()
{
return std::string ();
}
#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 Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies. copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/ */
//============================================================================== //==============================================================================
@@ -23,8 +23,8 @@
// and relaunches it on a fault. // and relaunches it on a fault.
// //
// VFALCO TODO Rename this and put it in a class. // VFALCO TODO Rename this and put it in a class.
extern bool HaveSustain(); extern bool HaveSustain ();
extern std::string StopSustain(); extern std::string StopSustain ();
extern std::string DoSustain(); extern std::string DoSustain ();
#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 Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies. copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/ */
//============================================================================== //==============================================================================
@@ -21,15 +21,15 @@
void setCallingThreadName (char const* threadName) void setCallingThreadName (char const* threadName)
{ {
struct ThreadInfo struct ThreadInfo
{ {
DWORD dwType; DWORD dwType;
LPCSTR szName; LPCSTR szName;
DWORD dwThreadID; DWORD dwThreadID;
DWORD dwFlags; DWORD dwFlags;
}; };
ThreadInfo info; ThreadInfo info;
info.dwType = 0x1000; info.dwType = 0x1000;
info.szName = threadName; info.szName = threadName;
@@ -38,45 +38,52 @@ void setCallingThreadName (char const* threadName)
__try __try
{ {
// This is a VisualStudio specific exception // This is a VisualStudio specific exception
RaiseException (0x406d1388, 0, sizeof (info) / sizeof (ULONG_PTR), (ULONG_PTR*) &info); RaiseException (0x406d1388, 0, sizeof (info) / sizeof (ULONG_PTR), (ULONG_PTR*) &info);
} }
__except (EXCEPTION_CONTINUE_EXECUTION) __except (EXCEPTION_CONTINUE_EXECUTION)
{ {
} }
} }
#else #else
#ifdef PR_SET_NAME #ifdef PR_SET_NAME
#define HAVE_NAME_THREAD #define HAVE_NAME_THREAD
extern void setCallingThreadName (const char* n) extern void setCallingThreadName (const char* n)
{ {
static std::string pName; static std::string pName;
if (pName.empty()) if (pName.empty ())
{ {
std::ifstream cLine("/proc/self/cmdline", std::ios::in); std::ifstream cLine ("/proc/self/cmdline", std::ios::in);
cLine >> pName; 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 += " ";
}
prctl(PR_SET_NAME, (pName + n).c_str(), 0, 0, 0); if (pName.empty ())
} pName = "rippled";
#endif else
{
size_t zero = pName.find_first_of ('\0');
#ifndef HAVE_NAME_THREAD if ((zero != std::string::npos) && (zero != 0))
extern void setCallingThreadName(const char*) pName = pName.substr (0, zero);
{ ; }
#endif 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 #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 Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies. copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 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 Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies. copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/ */
//============================================================================== //==============================================================================
@@ -21,34 +21,34 @@
// We have our own epoch. // 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() return ptWhen.is_not_a_date_time ()
? -1 ? -1
: (ptWhen-ptEpoch()).total_seconds(); : (ptWhen - ptEpoch ()).total_seconds ();
} }
// Convert our time in seconds to a ptime. // 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 return iSeconds < 0
? boost::posix_time::ptime(boost::posix_time::not_a_date_time) ? boost::posix_time::ptime (boost::posix_time::not_a_date_time)
: ptEpoch() + boost::posix_time::seconds(iSeconds); : ptEpoch () + boost::posix_time::seconds (iSeconds);
} }
// Convert from our time to UNIX time in seconds. // 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::time_duration tdDelta =
boost::posix_time::ptime(boost::gregorian::date(2000, boost::gregorian::Jan, 1)) 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::ptime (boost::gregorian::date (1970, boost::gregorian::Jan, 1))
+boost::posix_time::seconds(iSeconds) + 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 Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies. copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/ */
//============================================================================== //==============================================================================
#ifndef RIPPLE_TIME_H #ifndef RIPPLE_TIME_H
#define RIPPLE_TIME_H #define RIPPLE_TIME_H
boost::posix_time::ptime ptEpoch(); boost::posix_time::ptime ptEpoch ();
int iToSeconds(boost::posix_time::ptime ptWhen); int iToSeconds (boost::posix_time::ptime ptWhen);
boost::posix_time::ptime ptFromSeconds(int iSeconds); boost::posix_time::ptime ptFromSeconds (int iSeconds);
uint64_t utFromSeconds(int iSeconds); uint64_t utFromSeconds (int iSeconds);
#endif #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 Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies. copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/ */
//============================================================================== //==============================================================================
UptimeTimer::UptimeTimer () UptimeTimer::UptimeTimer ()
: m_elapsedTime (0) : m_elapsedTime (0)
, m_startTime (::time (0)) , m_startTime (::time (0))
, m_isUpdatingManually (false) , m_isUpdatingManually (false)
{ {
} }
@@ -29,45 +29,45 @@ UptimeTimer::~UptimeTimer ()
int UptimeTimer::getElapsedSeconds () const int UptimeTimer::getElapsedSeconds () const
{ {
int result; int result;
if (m_isUpdatingManually) if (m_isUpdatingManually)
{ {
// vf::memoryBarrier(); // vf::memoryBarrier();
result = m_elapsedTime; result = m_elapsedTime;
} }
else else
{ {
// VFALCO TODO use time_t instead of int return // VFALCO TODO use time_t instead of int return
result = static_cast <int> (::time (0) - m_startTime); result = static_cast <int> (::time (0) - m_startTime);
} }
return result; return result;
} }
void UptimeTimer::beginManualUpdates () void UptimeTimer::beginManualUpdates ()
{ {
//assert (!m_isUpdatingManually); //assert (!m_isUpdatingManually);
m_isUpdatingManually = true; m_isUpdatingManually = true;
} }
void UptimeTimer::endManualUpdates () void UptimeTimer::endManualUpdates ()
{ {
//assert (m_isUpdatingManually); //assert (m_isUpdatingManually);
m_isUpdatingManually = false; m_isUpdatingManually = false;
} }
void UptimeTimer::incrementElapsedTime () void UptimeTimer::incrementElapsedTime ()
{ {
//assert (m_isUpdatingManually); //assert (m_isUpdatingManually);
++m_elapsedTime; ++m_elapsedTime;
} }
UptimeTimer& UptimeTimer::getInstance () 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 Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies. copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/ */
//============================================================================== //==============================================================================
@@ -21,35 +21,35 @@
/** Tracks program uptime. /** Tracks program uptime.
The timer can be switched to a manual system of updating, to reduce The timer can be switched to a manual system of updating, to reduce
system calls. (?) system calls. (?)
*/ */
// VFALCO TODO determine if the non-manual timing is actually needed // VFALCO TODO determine if the non-manual timing is actually needed
class UptimeTimer class UptimeTimer
{ {
private: private:
UptimeTimer (); UptimeTimer ();
~UptimeTimer (); ~UptimeTimer ();
public: public:
int getElapsedSeconds () const; int getElapsedSeconds () const;
void beginManualUpdates (); void beginManualUpdates ();
void endManualUpdates (); void endManualUpdates ();
void incrementElapsedTime (); void incrementElapsedTime ();
static UptimeTimer& getInstance (); static UptimeTimer& getInstance ();
private: private:
// VFALCO DEPRECATED, Use a memory barrier instead of forcing a cache line // 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 m_pad1; // make sure m_elapsedTime fits in its own cache line
int volatile m_elapsedTime; int volatile m_elapsedTime;
int m_pad2; int m_pad2;
time_t m_startTime; time_t m_startTime;
bool m_isUpdatingManually; bool m_isUpdatingManually;
}; };
#endif #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 Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies. copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 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 @file ripple_client.cpp
@ingroup ripple_client @ingroup ripple_client
@@ -38,36 +38,36 @@
// Order and indentation reflect the hierarchy of dependencies // Order and indentation reflect the hierarchy of dependencies
// VFALCO NOTE Don't add anything here!!! // VFALCO NOTE Don't add anything here!!!
#include "src/cpp/ripple/ripple_HashedObject.h" #include "src/cpp/ripple/ripple_HashedObject.h"
#include "src/cpp/ripple/ripple_SHAMapItem.h" #include "src/cpp/ripple/ripple_SHAMapItem.h"
#include "src/cpp/ripple/ripple_SHAMapNode.h" #include "src/cpp/ripple/ripple_SHAMapNode.h"
#include "src/cpp/ripple/ripple_SHAMapAddNode.h" #include "src/cpp/ripple/ripple_SHAMapAddNode.h"
#include "src/cpp/ripple/ripple_SHAMapMissingNode.h" #include "src/cpp/ripple/ripple_SHAMapMissingNode.h"
#include "src/cpp/ripple/ripple_SHAMapTreeNode.h" #include "src/cpp/ripple/ripple_SHAMapTreeNode.h"
#include "src/cpp/ripple/ripple_SHAMapSyncFilter.h" #include "src/cpp/ripple/ripple_SHAMapSyncFilter.h"
#include "src/cpp/ripple/ripple_SHAMap.h" #include "src/cpp/ripple/ripple_SHAMap.h"
#include "src/cpp/ripple/ripple_SerializedTransaction.h" #include "src/cpp/ripple/ripple_SerializedTransaction.h"
#include "src/cpp/ripple/ripple_SerializedLedger.h" #include "src/cpp/ripple/ripple_SerializedLedger.h"
#include "src/cpp/ripple/TransactionMeta.h" #include "src/cpp/ripple/TransactionMeta.h"
#include "src/cpp/ripple/Transaction.h" #include "src/cpp/ripple/Transaction.h"
#include "src/cpp/ripple/ripple_AccountState.h" #include "src/cpp/ripple/ripple_AccountState.h"
#include "src/cpp/ripple/NicknameState.h" #include "src/cpp/ripple/NicknameState.h"
#include "src/cpp/ripple/Ledger.h" #include "src/cpp/ripple/Ledger.h"
#include "src/cpp/ripple/LedgerEntrySet.h" #include "src/cpp/ripple/LedgerEntrySet.h"
#include "src/cpp/ripple/TransactionEngine.h" #include "src/cpp/ripple/TransactionEngine.h"
#include "src/cpp/ripple/LoadManager.h" #include "src/cpp/ripple/LoadManager.h"
#include "src/cpp/ripple/ripple_Peer.h" #include "src/cpp/ripple/ripple_Peer.h"
#include "src/cpp/ripple/ripple_PeerSet.h" #include "src/cpp/ripple/ripple_PeerSet.h"
#include "src/cpp/ripple/ripple_LedgerAcquire.h" #include "src/cpp/ripple/ripple_LedgerAcquire.h"
#include "src/cpp/ripple/ripple_LedgerHistory.h" #include "src/cpp/ripple/ripple_LedgerHistory.h"
#include "src/cpp/ripple/ripple_CanonicalTXSet.h" #include "src/cpp/ripple/ripple_CanonicalTXSet.h"
#include "src/cpp/ripple/LedgerMaster.h" #include "src/cpp/ripple/LedgerMaster.h"
#include "src/cpp/ripple/ripple_InfoSub.h" #include "src/cpp/ripple/ripple_InfoSub.h"
#include "src/cpp/ripple/SerializedValidation.h" #include "src/cpp/ripple/SerializedValidation.h"
#include "src/cpp/ripple/LedgerProposal.h" #include "src/cpp/ripple/LedgerProposal.h"
#include "src/cpp/ripple/ripple_AcceptedLedgerTx.h" #include "src/cpp/ripple/ripple_AcceptedLedgerTx.h"
#include "src/cpp/ripple/NetworkOPs.h" #include "src/cpp/ripple/NetworkOPs.h"
#include "src/cpp/ripple/ripple_IApplication.h" #include "src/cpp/ripple/ripple_IApplication.h"
#include "src/cpp/ripple/ripple_InfoSub.cpp" #include "src/cpp/ripple/ripple_InfoSub.cpp"
//#include "src/cpp/ripple/NetworkOPs.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 Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies. copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 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 @file ripple_client.h
@ingroup ripple_client @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 #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 Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies. copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 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 () char const* Base58::getCurrentAlphabet ()
{ {
return s_currentAlphabet; return s_currentAlphabet;
} }
void Base58::setCurrentAlphabet (char const* alphabet) void Base58::setCurrentAlphabet (char const* alphabet)
{ {
s_currentAlphabet = alphabet; s_currentAlphabet = alphabet;
} }
char const* Base58::getBitcoinAlphabet () char const* Base58::getBitcoinAlphabet ()
{ {
return "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"; return "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
} }
char const* Base58::getRippleAlphabet () char const* Base58::getRippleAlphabet ()
{ {
return "rpshnaf39wBUDNEGHJKLM4PQRST7VWXYZ2bcdeCg65jkm8oFqi1tuvAxyz"; return "rpshnaf39wBUDNEGHJKLM4PQRST7VWXYZ2bcdeCg65jkm8oFqi1tuvAxyz";
} }
char const* Base58::getTestnetAlphabet () char const* Base58::getTestnetAlphabet ()
{ {
return "RPShNAF39wBUDnEGHJKLM4pQrsT7VWXYZ2bcdeCg65jkm8ofqi1tuvaxyz"; return "RPShNAF39wBUDnEGHJKLM4pQrsT7VWXYZ2bcdeCg65jkm8ofqi1tuvaxyz";
} }
std::string Base58::encode (const unsigned char* pbegin, const unsigned char* pend) std::string Base58::encode (const unsigned char* pbegin, const unsigned char* pend)
{ {
char const* alphabet = getCurrentAlphabet (); char const* alphabet = getCurrentAlphabet ();
CAutoBN_CTX pctx; CAutoBN_CTX pctx;
CBigNum bn58 = 58; CBigNum bn58 = 58;
CBigNum bn0 = 0; CBigNum bn0 = 0;
// Convert big endian data to little endian // Convert big endian data to little endian
// Extra zero at the end make sure bignum will interpret as a positive number // Extra zero at the end make sure bignum will interpret as a positive number
Blob vchTmp(pend-pbegin+1, 0); Blob vchTmp (pend - pbegin + 1, 0);
std::reverse_copy(pbegin, pend, vchTmp.begin()); std::reverse_copy (pbegin, pend, vchTmp.begin ());
// Convert little endian data to bignum // Convert little endian data to bignum
CBigNum bn(vchTmp); CBigNum bn (vchTmp);
// Convert bignum to std::string // Convert bignum to std::string
std::string str; std::string str;
// Expected size increase from base58 conversion is approximately 137% // Expected size increase from base58 conversion is approximately 137%
// use 138% to be safe // use 138% to be safe
str.reserve((pend - pbegin) * 138 / 100 + 1); str.reserve ((pend - pbegin) * 138 / 100 + 1);
CBigNum dv; CBigNum dv;
CBigNum rem; 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];
}
// Leading zeroes encoded as base58 zeros while (bn > bn0)
for (const unsigned char* p = pbegin; p < pend && *p == 0; p++) {
str += alphabet [0]; if (!BN_div (&dv, &rem, &bn, &bn58, pctx))
throw bignum_error ("EncodeBase58 : BN_div failed");
// Convert little endian std::string to big endian bn = dv;
reverse(str.begin(), str.end()); unsigned int c = rem.getuint ();
return str; 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) 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) std::string Base58::encodeWithCheck (Blob const& vchIn)
{ {
// add 4-byte hash check to the end // add 4-byte hash check to the end
Blob vch(vchIn); Blob vch (vchIn);
uint256 hash = SHA256Hash(vch.begin(), vch.end()); uint256 hash = SHA256Hash (vch.begin (), vch.end ());
vch.insert(vch.end(), (unsigned char*)&hash, (unsigned char*)&hash + 4); vch.insert (vch.end (), (unsigned char*)&hash, (unsigned char*)&hash + 4);
return encode (vch); return encode (vch);
} }
bool Base58::decode (const char* psz, Blob& vchRet, const char* pAlpha) bool Base58::decode (const char* psz, Blob& vchRet, const char* pAlpha)
{ {
assert (pAlpha != 0); assert (pAlpha != 0);
CAutoBN_CTX pctx; CAutoBN_CTX pctx;
vchRet.clear(); vchRet.clear ();
CBigNum bn58 = 58; CBigNum bn58 = 58;
CBigNum bn = 0; CBigNum bn = 0;
CBigNum bnChar; CBigNum bnChar;
while (isspace(*psz))
psz++;
// Convert big endian string to bignum while (isspace (*psz))
for (const char* p = psz; *p; p++) psz++;
{
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;
}
// Get bignum as little endian data // Convert big endian string to bignum
Blob vchTmp = bn.getvch(); for (const char* p = psz; *p; p++)
{
const char* p1 = strchr (pAlpha, *p);
// Trim off sign byte if present if (p1 == NULL)
if (vchTmp.size() >= 2 && vchTmp.end()[-1] == 0 && vchTmp.end()[-2] >= 0x80) {
vchTmp.erase(vchTmp.end()-1); while (isspace (*p))
p++;
// Restore leading zeros if (*p != '\0')
int nLeadingZeros = 0; return false;
for (const char* p = psz; *p == pAlpha[0]; p++)
nLeadingZeros++;
vchRet.assign(nLeadingZeros + vchTmp.size(), 0);
// Convert little endian data to big endian break;
std::reverse_copy(vchTmp.begin(), vchTmp.end(), vchRet.end() - vchTmp.size()); }
return true;
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) 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) bool Base58::decodeWithCheck (const char* psz, Blob& vchRet, const char* pAlphabet)
{ {
assert (pAlphabet != NULL); assert (pAlphabet != NULL);
if (!decode (psz, vchRet, pAlphabet)) if (!decode (psz, vchRet, pAlphabet))
return false; return false;
if (vchRet.size() < 4)
{ if (vchRet.size () < 4)
vchRet.clear(); {
return false; vchRet.clear ();
} return false;
uint256 hash = SHA256Hash(vchRet.begin(), vchRet.end()-4); }
if (memcmp(&hash, &vchRet.end()[-4], 4) != 0)
{ uint256 hash = SHA256Hash (vchRet.begin (), vchRet.end () - 4);
vchRet.clear();
return false; if (memcmp (&hash, &vchRet.end ()[-4], 4) != 0)
} {
vchRet.resize(vchRet.size()-4); vchRet.clear ();
return true; return false;
}
vchRet.resize (vchRet.size () - 4);
return true;
} }
bool Base58::decodeWithCheck (const std::string& str, Blob& vchRet, const char* pAlphabet) 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 // 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 Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies. copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/ */
//============================================================================== //==============================================================================
@@ -36,25 +36,25 @@
class Base58 class Base58
{ {
public: public:
// VFALCO TODO clean up this poor API // VFALCO TODO clean up this poor API
static char const* getCurrentAlphabet (); static char const* getCurrentAlphabet ();
static void setCurrentAlphabet (char const* alphabet); static void setCurrentAlphabet (char const* alphabet);
static char const* getBitcoinAlphabet (); static char const* getBitcoinAlphabet ();
static char const* getRippleAlphabet (); static char const* getRippleAlphabet ();
static char const* getTestnetAlphabet (); static char const* getTestnetAlphabet ();
static std::string encode (const unsigned char* pbegin, const unsigned char* pend); static std::string encode (const unsigned char* pbegin, const unsigned char* pend);
static std::string encode (Blob const& vch); static std::string encode (Blob const& vch);
static std::string encodeWithCheck (Blob const& vchIn); static std::string encodeWithCheck (Blob const& vchIn);
static bool decode (const char* psz, Blob& vchRet, const char* pAlphabet=getCurrentAlphabet ()); static bool decode (const char* psz, Blob& vchRet, const char* pAlphabet = getCurrentAlphabet ());
static bool decode (const std::string& str, Blob& vchRet); 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 char* psz, Blob& vchRet, const char* pAlphabet = getCurrentAlphabet ());
static bool decodeWithCheck (const std::string& str, Blob& vchRet, const char* pAlphabet); static bool decodeWithCheck (const std::string& str, Blob& vchRet, const char* pAlphabet);
private: private:
static char const* s_currentAlphabet; static char const* s_currentAlphabet;
}; };
#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 Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies. copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 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. // - Doubleclicking selects the whole number as one word if it's all alphanumeric.
// //
CBase58Data::CBase58Data() CBase58Data::CBase58Data ()
: nVersion(1) : nVersion (1)
{ {
} }
CBase58Data::~CBase58Data() CBase58Data::~CBase58Data ()
{ {
if (!vchData.empty()) if (!vchData.empty ())
memset(&vchData[0], 0, vchData.size()); memset (&vchData[0], 0, vchData.size ());
} }
void CBase58Data::SetData(int nVersionIn, Blob const& vchDataIn) void CBase58Data::SetData (int nVersionIn, Blob const& vchDataIn)
{ {
nVersion = nVersionIn; nVersion = nVersionIn;
vchData = vchDataIn; 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; nVersion = nVersionIn;
vchData.resize(nSize); vchData.resize (nSize);
if (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; Blob vchTemp;
Base58::decodeWithCheck (psz, vchTemp, pAlphabet); Base58::decodeWithCheck (psz, vchTemp, pAlphabet);
if (vchTemp.empty() || vchTemp[0] != version)
if (vchTemp.empty () || vchTemp[0] != version)
{ {
vchData.clear(); vchData.clear ();
nVersion = 1; nVersion = 1;
return false; return false;
} }
nVersion = vchTemp[0]; nVersion = vchTemp[0];
vchData.resize(vchTemp.size() - 1); vchData.resize (vchTemp.size () - 1);
if (!vchData.empty())
memcpy(&vchData[0], &vchTemp[1], vchData.size()); if (!vchData.empty ())
memset(&vchTemp[0], 0, vchTemp.size()); memcpy (&vchData[0], &vchTemp[1], vchData.size ());
memset (&vchTemp[0], 0, vchTemp.size ());
return true; 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); 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 (nVersion > b58.nVersion) return 1; if (nVersion > b58.nVersion) return 1;
if (vchData < b58.vchData) return -1; if (vchData < b58.vchData) return -1;
if (vchData > b58.vchData) return 1; if (vchData > b58.vchData) return 1;
return 0; return 0;
} }
bool CBase58Data::operator==(const CBase58Data& b58) const { return CompareTo(b58) == 0; } bool CBase58Data::operator== (const CBase58Data& b58) const
bool CBase58Data::operator!=(const CBase58Data& b58) const { return CompareTo(b58) != 0; } {
bool CBase58Data::operator<=(const CBase58Data& b58) const { return CompareTo(b58) <= 0; } 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
bool CBase58Data::operator> (const CBase58Data& b58) const { return CompareTo(b58) > 0; } {
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> () std::size_t seed = HashMaps::getInstance ().getNonce <size_t> ()
+ (b58.nVersion * HashMaps::goldenRatio); + (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 Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies. copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/ */
//============================================================================== //==============================================================================
@@ -37,28 +37,28 @@ protected:
unsigned char nVersion; unsigned char nVersion;
Blob vchData; Blob vchData;
CBase58Data(); CBase58Data ();
~CBase58Data(); ~CBase58Data ();
void SetData(int nVersionIn, Blob const& vchDataIn); void SetData (int nVersionIn, Blob const& vchDataIn);
void SetData(int nVersionIn, const void* pdata, size_t nSize); 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, const unsigned char* pbegin, const unsigned char* pend);
public: public:
bool SetString(const char* psz, unsigned char version, const char* pAlphabet = Base58::getCurrentAlphabet()); 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 std::string& str, unsigned char version);
std::string ToString() const; std::string ToString () const;
int CompareTo(const CBase58Data& b58) 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;
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); 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 // Distributed under the MIT/X11 software license, see the accompanying
// file license.txt or http://www.opensource.org/licenses/mit-license.php. // 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); BN_init (this);
if (!BN_copy(this, &b))
{ if (!BN_copy (this, &b))
BN_clear_free(this); {
throw bignum_error("CBigNum::CBigNum(const CBigNum&) : BN_copy failed"); 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)) if (!BN_copy (this, &b))
throw bignum_error("CBigNum::operator= : BN_copy failed"); throw bignum_error ("CBigNum::operator= : BN_copy failed");
return (*this);
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 (char 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)
{ {
BN_init(this); BN_init (this);
setvch(vch);
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); return 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);
} }
void CBigNum::setint64(int64 n) int CBigNum::getint () const
{ {
unsigned char pch[sizeof(n) + 6]; unsigned long n = BN_get_word (this);
unsigned char* p = pch + 4;
bool fNegative = false; if (!BN_is_negative (this))
if (n < (int64)0) return (n > INT_MAX ? INT_MAX : n);
{ else
n = -n; return (n > INT_MAX ? INT_MIN : - (int)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 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) #if (ULONG_MAX > UINT_MAX)
return static_cast<uint64>(getulong()); return static_cast<uint64> (getulong ());
#else #else
int len = BN_num_bytes(this); int len = BN_num_bytes (this);
if (len > 8)
throw std::runtime_error("BN getuint64 overflow");
unsigned char buf[8]; if (len > 8)
memset(buf, 0, sizeof(buf)); throw std::runtime_error ("BN getuint64 overflow");
BN_bn2bin(this, buf + 8 - len);
return unsigned char buf[8];
static_cast<uint64>(buf[0]) << 56 | static_cast<uint64>(buf[1]) << 48 | memset (buf, 0, sizeof (buf));
static_cast<uint64>(buf[2]) << 40 | static_cast<uint64>(buf[3]) << 32 | BN_bn2bin (this, buf + 8 - len);
static_cast<uint64>(buf[4]) << 24 | static_cast<uint64>(buf[5]) << 16 | return
static_cast<uint64>(buf[6]) << 8 | static_cast<uint64>(buf[7]); 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 #endif
} }
void CBigNum::setuint64(uint64 n) void CBigNum::setuint64 (uint64 n)
{ {
#if (ULONG_MAX > UINT_MAX) #if (ULONG_MAX > UINT_MAX)
setulong(static_cast<unsigned long>(n)); setulong (static_cast<unsigned long> (n));
#else #else
unsigned char buf[8]; unsigned char buf[8];
buf[0] = static_cast<unsigned char>((n >> 56) & 0xff); buf[0] = static_cast<unsigned char> ((n >> 56) & 0xff);
buf[1] = static_cast<unsigned char>((n >> 48) & 0xff); buf[1] = static_cast<unsigned char> ((n >> 48) & 0xff);
buf[2] = static_cast<unsigned char>((n >> 40) & 0xff); buf[2] = static_cast<unsigned char> ((n >> 40) & 0xff);
buf[3] = static_cast<unsigned char>((n >> 32) & 0xff); buf[3] = static_cast<unsigned char> ((n >> 32) & 0xff);
buf[4] = static_cast<unsigned char>((n >> 24) & 0xff); buf[4] = static_cast<unsigned char> ((n >> 24) & 0xff);
buf[5] = static_cast<unsigned char>((n >> 16) & 0xff); buf[5] = static_cast<unsigned char> ((n >> 16) & 0xff);
buf[6] = static_cast<unsigned char>((n >> 8) & 0xff); buf[6] = static_cast<unsigned char> ((n >> 8) & 0xff);
buf[7] = static_cast<unsigned char>((n) & 0xff); buf[7] = static_cast<unsigned char> ((n) & 0xff);
BN_bin2bn(buf, 8, this); BN_bin2bn (buf, 8, this);
#endif #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; uint256 ret;
unsigned int size = BN_num_bytes(this); unsigned int size = BN_num_bytes (this);
if (size > ret.size())
return ret; if (size > ret.size ())
BN_bn2bin(this, ret.begin() + (ret.size() - BN_num_bytes(this))); return ret;
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); Blob vch2 (vch.size () + 4);
unsigned int nSize = vch.size(); unsigned int nSize = vch.size ();
// BIGNUM's byte stream format expects 4 bytes of // BIGNUM's byte stream format expects 4 bytes of
// big endian size data info at the front // big endian size data info at the front
vch2[0] = (nSize >> 24) & 0xff; vch2[0] = (nSize >> 24) & 0xff;
vch2[1] = (nSize >> 16) & 0xff; vch2[1] = (nSize >> 16) & 0xff;
vch2[2] = (nSize >> 8) & 0xff; vch2[2] = (nSize >> 8) & 0xff;
vch2[3] = (nSize >> 0) & 0xff; vch2[3] = (nSize >> 0) & 0xff;
// swap data to big endian // swap data to big endian
std::reverse_copy(vch.begin(), vch.end(), vch2.begin() + 4); std::reverse_copy (vch.begin (), vch.end (), vch2.begin () + 4);
BN_mpi2bn(&vch2[0], vch2.size(), this); BN_mpi2bn (&vch2[0], vch2.size (), this);
} }
Blob CBigNum::getvch() const Blob CBigNum::getvch () const
{ {
unsigned int nSize = BN_bn2mpi(this, NULL); unsigned int nSize = BN_bn2mpi (this, NULL);
if (nSize < 4)
return Blob (); if (nSize < 4)
Blob vch(nSize); return Blob ();
BN_bn2mpi(this, &vch[0]);
vch.erase(vch.begin(), vch.begin() + 4); Blob vch (nSize);
reverse(vch.begin(), vch.end()); BN_bn2mpi (this, &vch[0]);
return vch; 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; unsigned int nSize = nCompact >> 24;
Blob vch(4 + nSize); Blob vch (4 + nSize);
vch[3] = nSize; vch[3] = nSize;
if (nSize >= 1) vch[4] = (nCompact >> 16) & 0xff;
if (nSize >= 2) vch[5] = (nCompact >> 8) & 0xff; if (nSize >= 1) vch[4] = (nCompact >> 16) & 0xff;
if (nSize >= 3) vch[6] = (nCompact >> 0) & 0xff;
BN_mpi2bn(&vch[0], vch.size(), this); if (nSize >= 2) vch[5] = (nCompact >> 8) & 0xff;
return *this;
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); unsigned int nSize = BN_bn2mpi (this, NULL);
Blob vch(nSize); Blob vch (nSize);
nSize -= 4; nSize -= 4;
BN_bn2mpi(this, &vch[0]); BN_bn2mpi (this, &vch[0]);
unsigned int nCompact = nSize << 24; unsigned int nCompact = nSize << 24;
if (nSize >= 1) nCompact |= (vch[4] << 16);
if (nSize >= 2) nCompact |= (vch[5] << 8); if (nSize >= 1) nCompact |= (vch[4] << 16);
if (nSize >= 3) nCompact |= (vch[6] << 0);
return nCompact; 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 // skip 0x
const char* psz = str.c_str(); 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++;
// hex string to bignum while (isspace (*psz))
static char phexdigit[256] = { psz++;
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, bool fNegative = false;
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, if (*psz == '-')
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, fNegative = true;
0,0xa,0xb,0xc,0xd,0xe,0xf,0,0,0,0,0,0,0,0,0 }; psz++;
*this = 0; }
while (isxdigit(*psz))
{ if (psz[0] == '0' && tolower (psz[1]) == 'x')
*this <<= 4; psz += 2;
int n = phexdigit[(int) *psz++];
*this += n; while (isspace (*psz))
} psz++;
if (fNegative)
*this = 0 - *this; // 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; CAutoBN_CTX pctx;
CBigNum bnBase = nBase; CBigNum bnBase = nBase;
CBigNum bn0 = 0; CBigNum bn0 = 0;
std::string str; std::string str;
CBigNum bn = *this; CBigNum bn = *this;
BN_set_negative(&bn, false); BN_set_negative (&bn, false);
CBigNum dv; CBigNum dv;
CBigNum rem; CBigNum rem;
if (BN_cmp(&bn, &bn0) == 0)
return "0"; if (BN_cmp (&bn, &bn0) == 0)
while (BN_cmp(&bn, &bn0) > 0) return "0";
{
if (!BN_div(&dv, &rem, &bn, &bnBase, pctx)) while (BN_cmp (&bn, &bn0) > 0)
throw bignum_error("CBigNum::ToString() : BN_div failed"); {
bn = dv; if (!BN_div (&dv, &rem, &bn, &bnBase, pctx))
unsigned int c = rem.getuint(); throw bignum_error ("CBigNum::ToString() : BN_div failed");
str += "0123456789abcdef"[c];
} bn = dv;
if (BN_is_negative(this)) unsigned int c = rem.getuint ();
str += "-"; str += "0123456789abcdef"[c];
reverse(str.begin(), str.end()); }
return str;
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)) if (!BN_add (this, this, &b))
throw bignum_error("CBigNum::operator+= : BN_add failed"); throw bignum_error ("CBigNum::operator+= : BN_add failed");
return *this;
return *this;
} }
CBigNum& CBigNum::operator-=(const CBigNum& b) CBigNum& CBigNum::operator-= (const CBigNum& b)
{ {
*this = *this - b; *this = *this - b;
return *this; return *this;
} }
CBigNum& CBigNum::operator*=(const CBigNum& b) CBigNum& CBigNum::operator*= (const CBigNum& b)
{ {
CAutoBN_CTX pctx; CAutoBN_CTX pctx;
if (!BN_mul(this, this, &b, pctx))
throw bignum_error("CBigNum::operator*= : BN_mul failed"); if (!BN_mul (this, this, &b, pctx))
return *this; 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; *this = *this / b;
return *this; return *this;
} }
CBigNum& CBigNum::operator%=(const CBigNum& b) CBigNum& CBigNum::operator%= (const CBigNum& b)
{ {
*this = *this % b; *this = *this % b;
return *this; return *this;
} }
CBigNum& CBigNum::operator<<=(unsigned int shift) CBigNum& CBigNum::operator<<= (unsigned int shift)
{ {
if (!BN_lshift(this, this, shift)) if (!BN_lshift (this, this, shift))
throw bignum_error("CBigNum:operator<<= : BN_lshift failed"); throw bignum_error ("CBigNum:operator<<= : BN_lshift failed");
return *this;
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 // 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 // if built on ubuntu 9.04 or 9.10, probably depends on version of openssl
CBigNum a = 1; CBigNum a = 1;
a <<= shift; a <<= shift;
if (BN_cmp(&a, this) > 0)
{
*this = 0;
return *this;
}
if (!BN_rshift(this, this, shift)) if (BN_cmp (&a, this) > 0)
throw bignum_error("CBigNum:operator>>= : BN_rshift failed"); {
return *this; *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 // prefix operator
if (!BN_add(this, this, BN_value_one())) if (!BN_add (this, this, BN_value_one ()))
throw bignum_error("CBigNum::operator++ : BN_add failed"); throw bignum_error ("CBigNum::operator++ : BN_add failed");
return *this;
return *this;
} }
const CBigNum CBigNum::operator++(int) const CBigNum CBigNum::operator++ (int)
{ {
// postfix operator // postfix operator
const CBigNum ret = *this; const CBigNum ret = *this;
++(*this); ++ (*this);
return ret; return ret;
} }
CBigNum& CBigNum::operator--() CBigNum& CBigNum::operator-- ()
{ {
// prefix operator // prefix operator
CBigNum r; CBigNum r;
if (!BN_sub(&r, this, BN_value_one()))
throw bignum_error("CBigNum::operator-- : BN_sub failed"); if (!BN_sub (&r, this, BN_value_one ()))
*this = r; throw bignum_error ("CBigNum::operator-- : BN_sub failed");
return *this;
*this = r;
return *this;
} }
const CBigNum CBigNum::operator--(int) const CBigNum CBigNum::operator-- (int)
{ {
// postfix operator // postfix operator
const CBigNum ret = *this; const CBigNum ret = *this;
--(*this); -- (*this);
return ret; return ret;
} }
void CBigNum::setulong(unsigned long n) void CBigNum::setulong (unsigned long n)
{ {
if (!BN_set_word(this, n)) if (!BN_set_word (this, n))
throw bignum_error("CBigNum conversion from unsigned long : BN_set_word failed"); 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; CBigNum r;
if (!BN_add(&r, &a, &b))
throw bignum_error("CBigNum::operator+ : BN_add failed"); if (!BN_add (&r, &a, &b))
return r; 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; CBigNum r;
if (!BN_sub(&r, &a, &b))
throw bignum_error("CBigNum::operator- : BN_sub failed"); if (!BN_sub (&r, &a, &b))
return r; 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); CBigNum r (a);
BN_set_negative(&r, !BN_is_negative(&r)); BN_set_negative (&r, !BN_is_negative (&r));
return r; return r;
} }
const CBigNum operator*(const CBigNum& a, const CBigNum& b) const CBigNum operator* (const CBigNum& a, const CBigNum& b)
{ {
CAutoBN_CTX pctx; CAutoBN_CTX pctx;
CBigNum r; CBigNum r;
if (!BN_mul(&r, &a, &b, pctx))
throw bignum_error("CBigNum::operator* : BN_mul failed"); if (!BN_mul (&r, &a, &b, pctx))
return r; 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; CAutoBN_CTX pctx;
CBigNum r; CBigNum r;
if (!BN_div(&r, NULL, &a, &b, pctx))
throw bignum_error("CBigNum::operator/ : BN_div failed"); if (!BN_div (&r, NULL, &a, &b, pctx))
return r; 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; CAutoBN_CTX pctx;
CBigNum r; CBigNum r;
if (!BN_mod(&r, &a, &b, pctx))
throw bignum_error("CBigNum::operator% : BN_div failed"); if (!BN_mod (&r, &a, &b, pctx))
return r; 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; CBigNum r;
if (!BN_lshift(&r, &a, shift))
throw bignum_error("CBigNum:operator<< : BN_lshift failed"); if (!BN_lshift (&r, &a, shift))
return r; 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; CBigNum r = a;
r >>= shift; r >>= shift;
return r; return r;
} }
bool operator== (const CBigNum& a, const CBigNum& b) 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) 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) 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) 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) 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) 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) #if (ULONG_MAX > UINT_MAX)
int BN_add_word64 (BIGNUM* bn, uint64 word) 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) 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) 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) uint64 BN_div_word64 (BIGNUM* bn, uint64 word)
{ {
return BN_div_word(bn, word); return BN_div_word (bn, word);
} }
#else #else
int BN_add_word64 (BIGNUM *a, uint64 w) int BN_add_word64 (BIGNUM* a, uint64 w)
{ {
CBigNum bn(w); CBigNum bn (w);
return BN_add(a, &bn, a); 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); CBigNum bn (w);
return BN_sub(a, &bn, a); 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); CBigNum bn (w);
CAutoBN_CTX ctx; CAutoBN_CTX ctx;
return BN_mul(a, &bn, a, 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); CBigNum bn (w);
CAutoBN_CTX ctx; CAutoBN_CTX ctx;
return (BN_div(a, NULL, a, &bn, ctx) == 1) ? 0 : ((uint64)-1); return (BN_div (a, NULL, a, &bn, ctx) == 1) ? 0 : ((uint64) - 1);
} }
#endif #endif

View File

@@ -14,7 +14,7 @@
class bignum_error : public std::runtime_error class bignum_error : public std::runtime_error
{ {
public: 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 class CAutoBN_CTX
{ {
private: private:
CAutoBN_CTX(const CAutoBN_CTX&); // no implementation CAutoBN_CTX (const CAutoBN_CTX&); // no implementation
CAutoBN_CTX& operator=(const CAutoBN_CTX&); // no implementation CAutoBN_CTX& operator= (const CAutoBN_CTX&); // no implementation
protected: protected:
BN_CTX* pctx; BN_CTX* pctx;
CAutoBN_CTX& operator=(BN_CTX* pnew) { pctx = pnew; return *this; } CAutoBN_CTX& operator= (BN_CTX* pnew)
{
pctx = pnew;
return *this;
}
public: public:
CAutoBN_CTX() CAutoBN_CTX ()
{ {
pctx = BN_CTX_new(); pctx = BN_CTX_new ();
if (pctx == NULL)
throw bignum_error("CAutoBN_CTX : BN_CTX_new() returned NULL");
}
~CAutoBN_CTX() if (pctx == NULL)
{ throw bignum_error ("CAutoBN_CTX : BN_CTX_new() returned NULL");
if (pctx != NULL) }
BN_CTX_free(pctx);
}
operator BN_CTX*() { return pctx; } ~CAutoBN_CTX ()
BN_CTX& operator*() { return *pctx; } {
BN_CTX** operator&() { return &pctx; } if (pctx != NULL)
bool operator!() { return (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 // 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 class CBigNum : public BIGNUM
{ {
public: public:
CBigNum(); CBigNum ();
CBigNum(const CBigNum& b); CBigNum (const CBigNum& b);
CBigNum& operator=(const CBigNum& b); CBigNum& operator= (const CBigNum& b);
CBigNum(char n); CBigNum (char n);
CBigNum(short n); CBigNum (short n);
CBigNum(int n); CBigNum (int n);
CBigNum(long n); CBigNum (long n);
CBigNum(int64 n); CBigNum (int64 n);
CBigNum(unsigned char n); CBigNum (unsigned char n);
CBigNum(unsigned short n); CBigNum (unsigned short n);
CBigNum(unsigned int n); CBigNum (unsigned int n);
CBigNum(uint64 n); CBigNum (uint64 n);
explicit CBigNum(uint256 n); explicit CBigNum (uint256 n);
explicit CBigNum(Blob const& vch); explicit CBigNum (Blob const& vch);
~CBigNum(); ~CBigNum ();
void setuint(unsigned int n); void setuint (unsigned int n);
unsigned int getuint() const; unsigned int getuint () const;
int getint() const; int getint () const;
void setint64(int64 n); void setint64 (int64 n);
uint64 getuint64() const; uint64 getuint64 () const;
void setuint64(uint64 n); void setuint64 (uint64 n);
void setuint256(uint256 const& n); void setuint256 (uint256 const& n);
uint256 getuint256(); uint256 getuint256 ();
void setvch(Blob const& vch); void setvch (Blob const& vch);
Blob getvch() const; Blob getvch () const;
CBigNum& SetCompact(unsigned int nCompact); CBigNum& SetCompact (unsigned int nCompact);
unsigned int GetCompact() const; unsigned int GetCompact () const;
void SetHex(const std::string& str); void SetHex (const std::string& str);
std::string ToString(int nBase=10) const; std::string ToString (int nBase = 10) const;
std::string GetHex() const; std::string GetHex () const;
bool operator!() 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*= (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>>=(unsigned int shift); CBigNum& operator>>= (unsigned int shift);
CBigNum& operator++(); CBigNum& operator++ ();
CBigNum& operator--(); CBigNum& operator-- ();
const CBigNum operator++(int); const CBigNum operator++ (int);
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:
// 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); void setulong (unsigned long n);
unsigned long getulong() const; 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& b); const CBigNum operator- (const CBigNum& a, const CBigNum& b);
const CBigNum operator-(const CBigNum& a); 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, 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, 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 //#endif
// VFALCO I believe only STAmount uses these // VFALCO I believe only STAmount uses these
extern int BN_add_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_sub_word64 (BIGNUM* a, uint64 w);
extern int BN_mul_word64 (BIGNUM *a, uint64 w); extern int BN_mul_word64 (BIGNUM* a, uint64 w);
extern uint64 BN_div_word64 (BIGNUM *a, uint64 w); extern uint64 BN_div_word64 (BIGNUM* a, uint64 w);
#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 Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies. copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 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 static inline EC_KEY_regenerate_key(EC_KEY *eckey, BIGNUM *priv_key)
{ {
int okay = 0; int okay = 0;
BN_CTX *ctx = NULL; BN_CTX *ctx = NULL;
EC_POINT *pub_key = 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) if ((ctx = BN_CTX_new()) == NULL)
goto err; goto err;
pub_key = EC_POINT_new(group); pub_key = EC_POINT_new(group);
if (pub_key == NULL) if (pub_key == NULL)
goto err; goto err;
if (!EC_POINT_mul(group, pub_key, priv_key, NULL, NULL, ctx)) if (!EC_POINT_mul(group, pub_key, priv_key, NULL, NULL, ctx))
goto err; goto err;
EC_KEY_set_conv_form(eckey, POINT_CONVERSION_COMPRESSED); EC_KEY_set_conv_form(eckey, POINT_CONVERSION_COMPRESSED);
EC_KEY_set_private_key(eckey, priv_key); EC_KEY_set_private_key(eckey, priv_key);
EC_KEY_set_public_key(eckey, pub_key); EC_KEY_set_public_key(eckey, pub_key);
okay = 1; okay = 1;
err: err:
if (pub_key) if (pub_key)
EC_POINT_free(pub_key); EC_POINT_free(pub_key);
if (ctx != NULL) if (ctx != NULL)
BN_CTX_free(ctx); BN_CTX_free(ctx);
return (okay); return (okay);
} }
*/ */
class key_error : public std::runtime_error class key_error : public std::runtime_error
{ {
public: 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 class CKey
{ {
protected: protected:
EC_KEY* pkey; EC_KEY* pkey;
bool fSet; bool fSet;
public: public:
typedef boost::shared_ptr<CKey> pointer; typedef boost::shared_ptr<CKey> pointer;
CKey() CKey ()
{ {
pkey = EC_KEY_new_by_curve_name(NID_secp256k1); pkey = EC_KEY_new_by_curve_name (NID_secp256k1);
EC_KEY_set_conv_form(pkey, POINT_CONVERSION_COMPRESSED); 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(const CKey& b) if (pkey == NULL)
{ throw key_error ("CKey::CKey() : EC_KEY_new_by_curve_name failed");
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) fSet = false;
{ }
if (!EC_KEY_copy(pkey, b.pkey))
throw key_error("CKey::operator=(const CKey&) : EC_KEY_copy failed"); CKey (const CKey& b)
fSet = b.fSet; {
return (*this); 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() ~CKey ()
{ {
EC_KEY_free(pkey); EC_KEY_free (pkey);
} }
static uint128 PassPhraseToKey(const std::string& passPhrase); static uint128 PassPhraseToKey (const std::string& passPhrase);
static EC_KEY* GenerateRootDeterministicKey(const uint128& passPhrase); static EC_KEY* GenerateRootDeterministicKey (const uint128& passPhrase);
static EC_KEY* GenerateRootPubKey(BIGNUM* pubGenerator); static EC_KEY* GenerateRootPubKey (BIGNUM* pubGenerator);
static EC_KEY* GeneratePublicDeterministicKey(const RippleAddress& generator, int n); 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, const BIGNUM* rootPriv, int n);
static EC_KEY* GeneratePrivateDeterministicKey(const RippleAddress& family, uint256 const& rootPriv, int n); static EC_KEY* GeneratePrivateDeterministicKey (const RippleAddress& family, uint256 const& rootPriv, int n);
CKey(const uint128& passPhrase) : fSet(false) CKey (const uint128& passPhrase) : fSet (false)
{ {
pkey = GenerateRootDeterministicKey(passPhrase); pkey = GenerateRootDeterministicKey (passPhrase);
fSet = true; fSet = true;
assert(pkey); assert (pkey);
} }
CKey(const RippleAddress& generator, int n) : fSet(false) CKey (const RippleAddress& generator, int n) : fSet (false)
{ // public deterministic key {
pkey = GeneratePublicDeterministicKey(generator, n); // public deterministic key
fSet = true; pkey = GeneratePublicDeterministicKey (generator, n);
assert(pkey); fSet = true;
} assert (pkey);
}
CKey(const RippleAddress& base, const BIGNUM* rootPrivKey, int n) : fSet(false) CKey (const RippleAddress& base, const BIGNUM* rootPrivKey, int n) : fSet (false)
{ // private deterministic key {
pkey = GeneratePrivateDeterministicKey(base, rootPrivKey, n); // private deterministic key
fSet = true; pkey = GeneratePrivateDeterministicKey (base, rootPrivKey, n);
assert(pkey); fSet = true;
} assert (pkey);
}
CKey(uint256 const& privateKey) : pkey(NULL), fSet(false) CKey (uint256 const& privateKey) : pkey (NULL), fSet (false)
{ {
// XXX Broken pkey is null. // XXX Broken pkey is null.
SetPrivateKeyU(privateKey); SetPrivateKeyU (privateKey);
} }
#if 0 #if 0
CKey(const RippleAddress& masterKey, int keyNum, bool isPublic) : pkey(NULL), fSet(false) CKey (const RippleAddress& masterKey, int keyNum, bool isPublic) : pkey (NULL), fSet (false)
{ {
if (isPublic) if (isPublic)
SetPubSeq(masterKey, keyNum); SetPubSeq (masterKey, keyNum);
else else
SetPrivSeq(masterKey, keyNum); // broken, need seed SetPrivSeq (masterKey, keyNum); // broken, need seed
fSet = true;
} fSet = true;
}
#endif #endif
bool IsNull() const bool IsNull () const
{ {
return !fSet; return !fSet;
} }
void MakeNewKey() void MakeNewKey ()
{ {
if (!EC_KEY_generate_key(pkey)) if (!EC_KEY_generate_key (pkey))
throw key_error("CKey::MakeNewKey() : EC_KEY_generate_key failed"); throw key_error ("CKey::MakeNewKey() : EC_KEY_generate_key failed");
EC_KEY_set_conv_form(pkey, POINT_CONVERSION_COMPRESSED);
fSet = true;
}
// XXX Still used! EC_KEY_set_conv_form (pkey, POINT_CONVERSION_COMPRESSED);
BIGNUM* GetSecretBN() const fSet = true;
{ // DEPRECATED }
return BN_dup(EC_KEY_get0_private_key(pkey));
}
void GetPrivateKeyU(uint256& privKey) // XXX Still used!
{ BIGNUM* GetSecretBN () const
const BIGNUM* bn = EC_KEY_get0_private_key(pkey); {
if (bn == NULL) // DEPRECATED
throw key_error("CKey::GetPrivateKeyU: EC_KEY_get0_private_key failed"); return BN_dup (EC_KEY_get0_private_key (pkey));
privKey.zero(); }
BN_bn2bin(bn, privKey.begin() + (privKey.size() - BN_num_bytes(bn)));
}
bool SetPrivateKeyU(uint256 const& key, bool bThrow=false) void GetPrivateKeyU (uint256& privKey)
{ {
// XXX Broken if pkey is not set. const BIGNUM* bn = EC_KEY_get0_private_key (pkey);
BIGNUM* bn = BN_bin2bn(key.begin(), key.size(), NULL);
bool bSuccess = !!EC_KEY_set_private_key(pkey, bn);
BN_clear_free(bn); if (bn == NULL)
throw key_error ("CKey::GetPrivateKeyU: EC_KEY_get0_private_key failed");
if (bSuccess) privKey.zero ();
{ BN_bn2bin (bn, privKey.begin () + (privKey.size () - BN_num_bytes (bn)));
fSet = true; }
}
else if (bThrow)
{
throw key_error("CKey::SetPrivateKeyU: EC_KEY_set_private_key failed");
}
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) BN_clear_free (bn);
{
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;
}
bool SetPubKey(Blob const& vchPubKey) if (bSuccess)
{ {
return SetPubKey(&vchPubKey[0], vchPubKey.size()); fSet = true;
} }
else if (bThrow)
{
throw key_error ("CKey::SetPrivateKeyU: EC_KEY_set_private_key failed");
}
bool SetPubKey(const std::string& pubKey) return bSuccess;
{ }
return SetPubKey(pubKey.data(), pubKey.size());
}
Blob GetPubKey() const bool SetPubKey (const void* ptr, size_t len)
{ {
unsigned int nSize = i2o_ECPublicKey(pkey, NULL); const unsigned char* pbegin = static_cast<const unsigned char*> (ptr);
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 Sign(uint256 const& hash, Blob& vchSig) if (!o2i_ECPublicKey (&pkey, &pbegin, len))
{ return false;
unsigned char pchSig[10000];
unsigned int nSize = 0;
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)) bool SetPubKey (Blob const& vchPubKey)
return false; {
return SetPubKey (&vchPubKey[0], vchPubKey.size ());
}
vchSig.resize(nSize); bool SetPubKey (const std::string& pubKey)
memcpy(&vchSig[0], pchSig, nSize); {
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 if (!nSize)
{ throw key_error ("CKey::GetPubKey() : i2o_ECPublicKey failed");
// -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 Blob vchPubKey (33, 0);
{ unsigned char* pbegin = &vchPubKey[0];
return Verify(hash, &vchSig[0], vchSig.size());
}
bool Verify(uint256 const& hash, const std::string& sig) const if (i2o_ECPublicKey (pkey, &pbegin) != nSize)
{ throw key_error ("CKey::GetPubKey() : i2o_ECPublicKey returned unexpected size");
return Verify(hash, sig.data(), sig.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. bool Sign (uint256 const& hash, Blob& vchSig)
void getECIESSecret(CKey& otherKey, uint256& enc_key, uint256& hmac_key); {
unsigned char pchSig[10000];
unsigned int nSize = 0;
// encrypt/decrypt functions with integrity checking. vchSig.clear ();
// Note that the other side must somehow know what keys to use
Blob encryptECIES(CKey& otherKey, Blob const& plaintext); if (!ECDSA_sign (0, (unsigned char*)hash.begin (), hash.size (), pchSig, &nSize, pkey))
Blob decryptECIES(CKey& otherKey, Blob const& ciphertext); 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 #endif

View File

@@ -4,328 +4,375 @@
// Functions to add CKey support for deterministic EC keys // Functions to add CKey support for deterministic EC keys
// <-- seed // <-- seed
uint128 CKey::PassPhraseToKey(const std::string& passPhrase) uint128 CKey::PassPhraseToKey (const std::string& passPhrase)
{ {
Serializer s; Serializer s;
s.addRaw(passPhrase); s.addRaw (passPhrase);
uint256 hash256 = s.getSHA512Half(); uint256 hash256 = s.getSHA512Half ();
uint128 ret(hash256); uint128 ret (hash256);
s.secureErase(); s.secureErase ();
return ret; return ret;
} }
// --> seed // --> seed
// <-- private root generator + public root generator // <-- 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(); BN_CTX* ctx = BN_CTX_new ();
if(!ctx) return NULL;
EC_KEY* pkey=EC_KEY_new_by_curve_name(NID_secp256k1); if (!ctx) return NULL;
if(!pkey)
{
BN_CTX_free(ctx);
return NULL;
}
EC_KEY_set_conv_form(pkey, POINT_CONVERSION_COMPRESSED);
BIGNUM* order=BN_new(); EC_KEY* pkey = EC_KEY_new_by_curve_name (NID_secp256k1);
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;
}
BIGNUM *privKey=NULL; if (!pkey)
int seq=0; {
do BN_CTX_free (ctx);
{ // private key must be non-zero and less than the curve's order return NULL;
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); EC_KEY_set_conv_form (pkey, POINT_CONVERSION_COMPRESSED);
if(!EC_KEY_set_private_key(pkey, privKey)) BIGNUM* order = BN_new ();
{ // 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 (!order)
if(!EC_POINT_mul(EC_KEY_get0_group(pkey), pubKey, privKey, NULL, NULL, ctx)) {
{ // compute the corresponding public key point BN_CTX_free (ctx);
assert(false); EC_KEY_free (pkey);
BN_clear_free(privKey); return NULL;
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); 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 #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 #endif
return pkey; return pkey;
} }
// Take ripple address. // Take ripple address.
// --> root public generator (consumes) // --> root public generator (consumes)
// <-- root public generator in EC format // <-- root public generator in EC format
EC_KEY* CKey::GenerateRootPubKey(BIGNUM* pubGenerator) EC_KEY* CKey::GenerateRootPubKey (BIGNUM* pubGenerator)
{ {
if (pubGenerator == NULL) if (pubGenerator == NULL)
{ {
assert(false); assert (false);
return NULL; return NULL;
} }
EC_KEY* pkey = EC_KEY_new_by_curve_name(NID_secp256k1); 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_POINT* pubPoint = EC_POINT_bn2point(EC_KEY_get0_group(pkey), pubGenerator, NULL, NULL); if (!pkey)
BN_free(pubGenerator); {
if(!pubPoint) BN_free (pubGenerator);
{ return NULL;
assert(false); }
EC_KEY_free(pkey);
return NULL;
}
if(!EC_KEY_set_public_key(pkey, pubPoint)) EC_KEY_set_conv_form (pkey, POINT_CONVERSION_COMPRESSED);
{
assert(false);
EC_POINT_free(pubPoint);
EC_KEY_free(pkey);
return NULL;
}
EC_POINT_free(pubPoint);
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 // --> 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; int subSeq = 0;
BIGNUM* ret=NULL; 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));
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 // --> public generator
EC_KEY* CKey::GeneratePublicDeterministicKey(const RippleAddress& pubGen, int seq) 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()); // publicKey(n) = rootPublicKey EC_POINT_+ Hash(pubHash|seq)*point
const EC_POINT* rootPubKey = EC_KEY_get0_public_key(rootKey); EC_KEY* rootKey = CKey::GenerateRootPubKey (pubGen.getGeneratorBN ());
BN_CTX* ctx = BN_CTX_new(); const EC_POINT* rootPubKey = EC_KEY_get0_public_key (rootKey);
EC_KEY* pkey = EC_KEY_new_by_curve_name(NID_secp256k1); BN_CTX* ctx = BN_CTX_new ();
EC_POINT* newPoint = 0; EC_KEY* pkey = EC_KEY_new_by_curve_name (NID_secp256k1);
BIGNUM* order = 0; EC_POINT* newPoint = 0;
BIGNUM* hash = 0; BIGNUM* order = 0;
bool success = true; BIGNUM* hash = 0;
bool success = true;
if (!ctx || !pkey) success = false; if (!ctx || !pkey) success = false;
if (success) if (success)
EC_KEY_set_conv_form(pkey, POINT_CONVERSION_COMPRESSED); EC_KEY_set_conv_form (pkey, POINT_CONVERSION_COMPRESSED);
if (success) { if (success)
newPoint = EC_POINT_new(EC_KEY_get0_group(pkey)); {
if(!newPoint) success = false; newPoint = EC_POINT_new (EC_KEY_get0_group (pkey));
}
if (success) { if (!newPoint) success = false;
order = BN_new(); }
if(!order || !EC_GROUP_get_order(EC_KEY_get0_group(pkey), order, ctx)) if (success)
success = false; {
} order = BN_new ();
// Calculate the private additional key. if (!order || !EC_GROUP_get_order (EC_KEY_get0_group (pkey), order, ctx))
if (success) { success = false;
hash = makeHash(pubGen, seq, order); }
if(!hash) success = false;
}
if (success) { // Calculate the private additional key.
// Calculate the corresponding public key. if (success)
EC_POINT_mul(EC_KEY_get0_group(pkey), newPoint, hash, NULL, NULL, ctx); {
hash = makeHash (pubGen, seq, order);
// Add the master public key and set. if (!hash) success = false;
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 (success)
if (hash) BN_free(hash); {
if (newPoint) EC_POINT_free(newPoint); // Calculate the corresponding public key.
if (ctx) BN_CTX_free(ctx); EC_POINT_mul (EC_KEY_get0_group (pkey), newPoint, hash, NULL, NULL, ctx);
if (rootKey) EC_KEY_free(rootKey);
if (pkey && !success) EC_KEY_free(pkey);
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); CBigNum bn (u);
return GeneratePrivateDeterministicKey(pubGen, static_cast<BIGNUM*>(&bn), seq); return GeneratePrivateDeterministicKey (pubGen, static_cast<BIGNUM*> (&bn), seq);
} }
// --> root private key // --> root private key
EC_KEY* CKey::GeneratePrivateDeterministicKey(const RippleAddress& pubGen, const BIGNUM* rootPrivKey, int seq) 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)
{ {
Log(lsDEBUG) << "Beginning deterministic key test"; // privateKey(n) = (rootPrivateKey + Hash(pubHash|seq)) % order
BN_CTX* ctx = BN_CTX_new ();
uint128 seed1, seed2; if (ctx == NULL) return NULL;
seed1.SetHex("71ED064155FFADFA38782C5E0158CB26");
seed2.SetHex("CF0C3BE4485961858C4198515AE5B965");
CKey root1(seed1), root2(seed2);
uint256 priv1, priv2; EC_KEY* pkey = EC_KEY_new_by_curve_name (NID_secp256k1);
root1.GetPrivateKeyU(priv1);
root2.GetPrivateKeyU(priv2);
if (priv1.GetHex() != "7CFBA64F771E93E817E15039215430B53F7401C34931D111EAB3510B22DBB0D8") if (pkey == NULL)
BOOST_FAIL("Incorrect private key for generator"); {
if (priv2.GetHex() != "98BC2EACB26EB021D1A6293C044D88BA2F0B6729A2772DEEBF2E21A263C1740B") BN_CTX_free (ctx);
BOOST_FAIL("Incorrect private key for generator"); return NULL;
}
RippleAddress nSeed; EC_KEY_set_conv_form (pkey, POINT_CONVERSION_COMPRESSED);
nSeed.setSeed(seed1);
if (nSeed.humanSeed() != "shHM53KPZ87Gwdqarm1bAmPeXg8Tn") BIGNUM* order = BN_new ();
BOOST_FAIL("Incorrect human seed");
if (nSeed.humanSeed1751() != "MAD BODY ACE MINT OKAY HUB WHAT DATA SACK FLAT DANA MATH") if (order == NULL)
BOOST_FAIL("Incorrect 1751 seed"); {
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 // vim:ts=4

View File

@@ -24,267 +24,288 @@
// key. They *must* be called in try/catch blocks. // key. They *must* be called in try/catch blocks.
// Algorithmic choices: // Algorithmic choices:
#define ECIES_KEY_HASH SHA512 // Hash used to expand shared secret #define ECIES_KEY_HASH SHA512 // Hash used to expand shared secret
#define ECIES_KEY_LENGTH (512/8) // Size of expanded 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_MIN_SEC (128/8) // The minimum equivalent security
#define ECIES_ENC_ALGO EVP_aes_256_cbc() // Encryption algorithm #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_TYPE uint256 // Type used to hold shared secret
#define ECIES_ENC_KEY_SIZE (256/8) // Encryption key size #define ECIES_ENC_KEY_SIZE (256/8) // Encryption key size
#define ECIES_ENC_BLK_SIZE (128/8) // Encryption block size #define ECIES_ENC_BLK_SIZE (128/8) // Encryption block size
#define ECIES_ENC_IV_TYPE uint128 // Type used to hold IV #define ECIES_ENC_IV_TYPE uint128 // Type used to hold IV
#define ECIES_HMAC_ALGO EVP_sha256() // HMAC algorithm #define ECIES_HMAC_ALGO EVP_sha256() // HMAC algorithm
#define ECIES_HMAC_KEY_TYPE uint256 // Type used to hold HMAC key #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_KEY_SIZE (256/8) // Size of HMAC key
#define ECIES_HMAC_TYPE uint256 // Type used to hold HMAC value #define ECIES_HMAC_TYPE uint256 // Type used to hold HMAC value
#define ECIES_HMAC_SIZE (256/8) // Size of 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) 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) // Retrieve a secret generated from an EC key pair. At least one private key must be known.
throw std::runtime_error("missing key"); if (!pkey || !otherKey.pkey)
throw std::runtime_error ("missing key");
EC_KEY *pubkey, *privkey; 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");
unsigned char rawbuf[512]; if (EC_KEY_get0_private_key (pkey))
int buflen = ECDH_compute_key(rawbuf, 512, EC_KEY_get0_public_key(pubkey), privkey, NULL); {
if (buflen < ECIES_MIN_SEC) privkey = pkey;
throw std::runtime_error("ecdh key failed"); 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]; unsigned char rawbuf[512];
ECIES_KEY_HASH(rawbuf, buflen, hbuf); int buflen = ECDH_compute_key (rawbuf, 512, EC_KEY_get0_public_key (pubkey), privkey, NULL);
memset(rawbuf, 0, ECIES_HMAC_KEY_SIZE);
assert((ECIES_ENC_KEY_SIZE + ECIES_HMAC_KEY_SIZE) >= ECIES_KEY_LENGTH); if (buflen < ECIES_MIN_SEC)
memcpy(enc_key.begin(), hbuf, ECIES_ENC_KEY_SIZE); throw std::runtime_error ("ecdh key failed");
memcpy(hmac_key.begin(), hbuf + ECIES_ENC_KEY_SIZE, ECIES_HMAC_KEY_SIZE);
memset(hbuf, 0, ECIES_KEY_LENGTH); 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 ctx;
HMAC_CTX_init(&ctx); HMAC_CTX_init (&ctx);
if (HMAC_Init_ex(&ctx, secret.begin(), ECIES_HMAC_KEY_SIZE, ECIES_HMAC_ALGO, NULL) != 1) if (HMAC_Init_ex (&ctx, secret.begin (), ECIES_HMAC_KEY_SIZE, ECIES_HMAC_ALGO, NULL) != 1)
{ {
HMAC_CTX_cleanup(&ctx); HMAC_CTX_cleanup (&ctx);
throw std::runtime_error("init hmac"); throw std::runtime_error ("init hmac");
} }
if (HMAC_Update(&ctx, &(data.front()), data.size()) != 1) if (HMAC_Update (&ctx, & (data.front ()), data.size ()) != 1)
{ {
HMAC_CTX_cleanup(&ctx); HMAC_CTX_cleanup (&ctx);
throw std::runtime_error("update hmac"); throw std::runtime_error ("update hmac");
} }
ECIES_HMAC_TYPE ret; ECIES_HMAC_TYPE ret;
unsigned int ml = ECIES_HMAC_SIZE; 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);
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; ECIES_ENC_IV_TYPE iv;
RandomNumbers::getInstance ().fillBytes (iv.begin (), ECIES_ENC_BLK_SIZE); RandomNumbers::getInstance ().fillBytes (iv.begin (), ECIES_ENC_BLK_SIZE);
ECIES_ENC_KEY_TYPE secret; ECIES_ENC_KEY_TYPE secret;
ECIES_HMAC_KEY_TYPE hmacKey; ECIES_HMAC_KEY_TYPE hmacKey;
getECIESSecret(otherKey, secret, hmacKey); getECIESSecret (otherKey, secret, hmacKey);
ECIES_HMAC_TYPE hmac = makeHMAC(hmacKey, plaintext); ECIES_HMAC_TYPE hmac = makeHMAC (hmacKey, plaintext);
hmacKey.zero(); hmacKey.zero ();
EVP_CIPHER_CTX ctx; EVP_CIPHER_CTX ctx;
EVP_CIPHER_CTX_init(&ctx); EVP_CIPHER_CTX_init (&ctx);
if (EVP_EncryptInit_ex(&ctx, ECIES_ENC_ALGO, NULL, secret.begin(), iv.begin()) != 1) if (EVP_EncryptInit_ex (&ctx, ECIES_ENC_ALGO, NULL, secret.begin (), iv.begin ()) != 1)
{ {
EVP_CIPHER_CTX_cleanup(&ctx); EVP_CIPHER_CTX_cleanup (&ctx);
secret.zero(); secret.zero ();
throw std::runtime_error("init cipher ctx"); throw std::runtime_error ("init cipher ctx");
} }
secret.zero();
Blob out(plaintext.size() + ECIES_HMAC_SIZE + ECIES_ENC_KEY_SIZE + ECIES_ENC_BLK_SIZE, 0); secret.zero ();
int len = 0, bytesWritten;
// output IV Blob out (plaintext.size () + ECIES_HMAC_SIZE + ECIES_ENC_KEY_SIZE + ECIES_ENC_BLK_SIZE, 0);
memcpy(&(out.front()), iv.begin(), ECIES_ENC_BLK_SIZE); int len = 0, bytesWritten;
len = ECIES_ENC_BLK_SIZE;
// Encrypt/output HMAC // output IV
bytesWritten = out.capacity() - len; memcpy (& (out.front ()), iv.begin (), ECIES_ENC_BLK_SIZE);
assert(bytesWritten>0); len = ECIES_ENC_BLK_SIZE;
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;
// encrypt/output plaintext // Encrypt/output HMAC
bytesWritten = out.capacity() - len; bytesWritten = out.capacity () - len;
assert(bytesWritten>0); 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 if (EVP_EncryptUpdate (&ctx, & (out.front ()) + len, &bytesWritten, hmac.begin (), ECIES_HMAC_SIZE) < 0)
bytesWritten = out.capacity() - len; {
if (EVP_EncryptFinal_ex(&ctx, &(out.front()) + len, &bytesWritten) < 0) EVP_CIPHER_CTX_cleanup (&ctx);
{ throw std::runtime_error ("");
EVP_CIPHER_CTX_cleanup(&ctx); }
throw std::runtime_error("encryption error");
}
len += bytesWritten;
// Output contains: IV, encrypted HMAC, encrypted data, encrypted padding len += bytesWritten;
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 // encrypt/output plaintext
out.resize(len); bytesWritten = out.capacity () - len;
EVP_CIPHER_CTX_cleanup(&ctx); assert (bytesWritten > 0);
return out;
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 // minimum ciphertext = IV + HMAC + 1 block
if (ciphertext.size() < ((2 * ECIES_ENC_BLK_SIZE) + ECIES_HMAC_SIZE) ) if (ciphertext.size () < ((2 * ECIES_ENC_BLK_SIZE) + ECIES_HMAC_SIZE) )
throw std::runtime_error("ciphertext too short"); throw std::runtime_error ("ciphertext too short");
// extract IV // extract IV
ECIES_ENC_IV_TYPE iv; ECIES_ENC_IV_TYPE iv;
memcpy(iv.begin(), &(ciphertext.front()), ECIES_ENC_BLK_SIZE); memcpy (iv.begin (), & (ciphertext.front ()), ECIES_ENC_BLK_SIZE);
// begin decrypting // begin decrypting
EVP_CIPHER_CTX ctx; EVP_CIPHER_CTX ctx;
EVP_CIPHER_CTX_init(&ctx); EVP_CIPHER_CTX_init (&ctx);
ECIES_ENC_KEY_TYPE secret; ECIES_ENC_KEY_TYPE secret;
ECIES_HMAC_KEY_TYPE hmacKey; ECIES_HMAC_KEY_TYPE hmacKey;
getECIESSecret(otherKey, secret, hmacKey); getECIESSecret (otherKey, secret, hmacKey);
if (EVP_DecryptInit_ex(&ctx, ECIES_ENC_ALGO, NULL, secret.begin(), iv.begin()) != 1) if (EVP_DecryptInit_ex (&ctx, ECIES_ENC_ALGO, NULL, secret.begin (), iv.begin ()) != 1)
{ {
secret.zero(); secret.zero ();
hmacKey.zero(); hmacKey.zero ();
EVP_CIPHER_CTX_cleanup(&ctx); EVP_CIPHER_CTX_cleanup (&ctx);
throw std::runtime_error("unable to init cipher"); throw std::runtime_error ("unable to init cipher");
} }
// decrypt mac // decrypt mac
ECIES_HMAC_TYPE hmac; ECIES_HMAC_TYPE hmac;
int outlen = ECIES_HMAC_SIZE; 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 plaintext (after IV and encrypted mac) if ( (EVP_DecryptUpdate (&ctx, hmac.begin (), &outlen,
Blob plaintext(ciphertext.size() - ECIES_HMAC_SIZE - ECIES_ENC_BLK_SIZE); & (ciphertext.front ()) + ECIES_ENC_BLK_SIZE, ECIES_HMAC_SIZE + 1) != 1) || (outlen != ECIES_HMAC_SIZE) )
outlen = plaintext.size(); {
if (EVP_DecryptUpdate(&ctx, &(plaintext.front()), &outlen, secret.zero ();
&(ciphertext.front()) + ECIES_ENC_BLK_SIZE + ECIES_HMAC_SIZE + 1, hmacKey.zero ();
ciphertext.size() - ECIES_ENC_BLK_SIZE - ECIES_HMAC_SIZE - 1) != 1) EVP_CIPHER_CTX_cleanup (&ctx);
{ throw std::runtime_error ("unable to extract hmac");
secret.zero(); }
hmacKey.zero();
EVP_CIPHER_CTX_cleanup(&ctx);
throw std::runtime_error("unable to extract plaintext");
}
// decrypt padding // decrypt plaintext (after IV and encrypted mac)
int flen = 0; Blob plaintext (ciphertext.size () - ECIES_HMAC_SIZE - ECIES_ENC_BLK_SIZE);
if (EVP_DecryptFinal(&ctx, &(plaintext.front()) + outlen, &flen) != 1) outlen = plaintext.size ();
{
secret.zero();
hmacKey.zero();
EVP_CIPHER_CTX_cleanup(&ctx);
throw std::runtime_error("plaintext had bad padding");
}
plaintext.resize(flen + outlen);
// verify integrity if (EVP_DecryptUpdate (&ctx, & (plaintext.front ()), &outlen,
if (hmac != makeHMAC(hmacKey, plaintext)) & (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(); secret.zero ();
EVP_CIPHER_CTX_cleanup(&ctx); hmacKey.zero ();
throw std::runtime_error("plaintext had bad hmac"); EVP_CIPHER_CTX_cleanup (&ctx);
} throw std::runtime_error ("unable to extract plaintext");
secret.zero(); }
hmacKey.zero();
EVP_CIPHER_CTX_cleanup(&ctx); // decrypt padding
return plaintext; 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) for (int i = 0; i < 30000; ++i)
{ {
if ((i % 100) == 0) if ((i % 100) == 0)
{ // generate new keys every 100 times {
// std::cerr << "new keys" << std::endl; // generate new keys every 100 times
senderPriv.MakeNewKey(); // std::cerr << "new keys" << std::endl;
recipientPriv.MakeNewKey(); senderPriv.MakeNewKey ();
recipientPriv.MakeNewKey ();
if (!senderPub.SetPubKey(senderPriv.GetPubKey())) if (!senderPub.SetPubKey (senderPriv.GetPubKey ()))
throw std::runtime_error("key error"); throw std::runtime_error ("key error");
if (!recipientPub.SetPubKey(recipientPriv.GetPubKey()))
throw std::runtime_error("key error");
}
// generate message if (!recipientPub.SetPubKey (recipientPriv.GetPubKey ()))
Blob message(4096); throw std::runtime_error ("key error");
int msglen = i%3000; }
RandomNumbers::getInstance ().fillBytes (&message.front(), msglen); // generate message
message.resize(msglen); Blob message (4096);
int msglen = i % 3000;
// encrypt message with sender's private key and recipient's public key RandomNumbers::getInstance ().fillBytes (&message.front (), msglen);
Blob ciphertext = senderPriv.encryptECIES(recipientPub, message); message.resize (msglen);
// decrypt message with recipient's private key and sender's public key // encrypt message with sender's private key and recipient's public key
Blob decrypt = recipientPriv.decryptECIES(senderPub, ciphertext); Blob ciphertext = senderPriv.encryptECIES (recipientPub, message);
if (decrypt != message) // decrypt message with recipient's private key and sender's public key
{ Blob decrypt = recipientPriv.decryptECIES (senderPub, ciphertext);
assert(false);
return false; if (decrypt != message)
} {
// std::cerr << "Msg(" << msglen << ") ok " << ciphertext.size() << std::endl; assert (false);
} return false;
return true; }
// std::cerr << "Msg(" << msglen << ") ok " << ciphertext.size() << std::endl;
}
return true;
} }
// vim:ts=4 // vim:ts=4

View File

@@ -12,363 +12,370 @@
#include <string> #include <string>
#include <vector> #include <vector>
char const* RFC1751::s_dictionary [2048] = { char const* RFC1751::s_dictionary [2048] =
"A", "ABE", "ACE", "ACT", "AD", "ADA", "ADD", {
"AGO", "AID", "AIM", "AIR", "ALL", "ALP", "AM", "AMY", "AN", "ANA", "A", "ABE", "ACE", "ACT", "AD", "ADA", "ADD",
"AND", "ANN", "ANT", "ANY", "APE", "APS", "APT", "ARC", "ARE", "ARK", "AGO", "AID", "AIM", "AIR", "ALL", "ALP", "AM", "AMY", "AN", "ANA",
"ARM", "ART", "AS", "ASH", "ASK", "AT", "ATE", "AUG", "AUK", "AVE", "AND", "ANN", "ANT", "ANY", "APE", "APS", "APT", "ARC", "ARE", "ARK",
"AWE", "AWK", "AWL", "AWN", "AX", "AYE", "BAD", "BAG", "BAH", "BAM", "ARM", "ART", "AS", "ASH", "ASK", "AT", "ATE", "AUG", "AUK", "AVE",
"BAN", "BAR", "BAT", "BAY", "BE", "BED", "BEE", "BEG", "BEN", "BET", "AWE", "AWK", "AWL", "AWN", "AX", "AYE", "BAD", "BAG", "BAH", "BAM",
"BEY", "BIB", "BID", "BIG", "BIN", "BIT", "BOB", "BOG", "BON", "BOO", "BAN", "BAR", "BAT", "BAY", "BE", "BED", "BEE", "BEG", "BEN", "BET",
"BOP", "BOW", "BOY", "BUB", "BUD", "BUG", "BUM", "BUN", "BUS", "BUT", "BEY", "BIB", "BID", "BIG", "BIN", "BIT", "BOB", "BOG", "BON", "BOO",
"BUY", "BY", "BYE", "CAB", "CAL", "CAM", "CAN", "CAP", "CAR", "CAT", "BOP", "BOW", "BOY", "BUB", "BUD", "BUG", "BUM", "BUN", "BUS", "BUT",
"CAW", "COD", "COG", "COL", "CON", "COO", "COP", "COT", "COW", "COY", "BUY", "BY", "BYE", "CAB", "CAL", "CAM", "CAN", "CAP", "CAR", "CAT",
"CRY", "CUB", "CUE", "CUP", "CUR", "CUT", "DAB", "DAD", "DAM", "DAN", "CAW", "COD", "COG", "COL", "CON", "COO", "COP", "COT", "COW", "COY",
"DAR", "DAY", "DEE", "DEL", "DEN", "DES", "DEW", "DID", "DIE", "DIG", "CRY", "CUB", "CUE", "CUP", "CUR", "CUT", "DAB", "DAD", "DAM", "DAN",
"DIN", "DIP", "DO", "DOE", "DOG", "DON", "DOT", "DOW", "DRY", "DUB", "DAR", "DAY", "DEE", "DEL", "DEN", "DES", "DEW", "DID", "DIE", "DIG",
"DUD", "DUE", "DUG", "DUN", "EAR", "EAT", "ED", "EEL", "EGG", "EGO", "DIN", "DIP", "DO", "DOE", "DOG", "DON", "DOT", "DOW", "DRY", "DUB",
"ELI", "ELK", "ELM", "ELY", "EM", "END", "EST", "ETC", "EVA", "EVE", "DUD", "DUE", "DUG", "DUN", "EAR", "EAT", "ED", "EEL", "EGG", "EGO",
"EWE", "EYE", "FAD", "FAN", "FAR", "FAT", "FAY", "FED", "FEE", "FEW", "ELI", "ELK", "ELM", "ELY", "EM", "END", "EST", "ETC", "EVA", "EVE",
"FIB", "FIG", "FIN", "FIR", "FIT", "FLO", "FLY", "FOE", "FOG", "FOR", "EWE", "EYE", "FAD", "FAN", "FAR", "FAT", "FAY", "FED", "FEE", "FEW",
"FRY", "FUM", "FUN", "FUR", "GAB", "GAD", "GAG", "GAL", "GAM", "GAP", "FIB", "FIG", "FIN", "FIR", "FIT", "FLO", "FLY", "FOE", "FOG", "FOR",
"GAS", "GAY", "GEE", "GEL", "GEM", "GET", "GIG", "GIL", "GIN", "GO", "FRY", "FUM", "FUN", "FUR", "GAB", "GAD", "GAG", "GAL", "GAM", "GAP",
"GOT", "GUM", "GUN", "GUS", "GUT", "GUY", "GYM", "GYP", "HA", "HAD", "GAS", "GAY", "GEE", "GEL", "GEM", "GET", "GIG", "GIL", "GIN", "GO",
"HAL", "HAM", "HAN", "HAP", "HAS", "HAT", "HAW", "HAY", "HE", "HEM", "GOT", "GUM", "GUN", "GUS", "GUT", "GUY", "GYM", "GYP", "HA", "HAD",
"HEN", "HER", "HEW", "HEY", "HI", "HID", "HIM", "HIP", "HIS", "HIT", "HAL", "HAM", "HAN", "HAP", "HAS", "HAT", "HAW", "HAY", "HE", "HEM",
"HO", "HOB", "HOC", "HOE", "HOG", "HOP", "HOT", "HOW", "HUB", "HUE", "HEN", "HER", "HEW", "HEY", "HI", "HID", "HIM", "HIP", "HIS", "HIT",
"HUG", "HUH", "HUM", "HUT", "I", "ICY", "IDA", "IF", "IKE", "ILL", "HO", "HOB", "HOC", "HOE", "HOG", "HOP", "HOT", "HOW", "HUB", "HUE",
"INK", "INN", "IO", "ION", "IQ", "IRA", "IRE", "IRK", "IS", "IT", "ITS", "HUG", "HUH", "HUM", "HUT", "I", "ICY", "IDA", "IF", "IKE", "ILL",
"IVY", "JAB", "JAG", "JAM", "JAN", "JAR", "JAW", "JAY", "JET", "JIG", "INK", "INN", "IO", "ION", "IQ", "IRA", "IRE", "IRK", "IS", "IT", "ITS",
"JIM", "JO", "JOB", "JOE", "JOG", "JOT", "JOY", "JUG", "JUT", "KAY", "IVY", "JAB", "JAG", "JAM", "JAN", "JAR", "JAW", "JAY", "JET", "JIG",
"KEG", "KEN", "KEY", "KID", "KIM", "KIN", "KIT", "LA", "LAB", "LAC", "JIM", "JO", "JOB", "JOE", "JOG", "JOT", "JOY", "JUG", "JUT", "KAY",
"LAD", "LAG", "LAM", "LAP", "LAW", "LAY", "LEA", "LED", "LEE", "LEG", "KEG", "KEN", "KEY", "KID", "KIM", "KIN", "KIT", "LA", "LAB", "LAC",
"LEN", "LEO", "LET", "LEW", "LID", "LIE", "LIN", "LIP", "LIT", "LO", "LAD", "LAG", "LAM", "LAP", "LAW", "LAY", "LEA", "LED", "LEE", "LEG",
"LOB", "LOG", "LOP", "LOS", "LOT", "LOU", "LOW", "LOY", "LUG", "LYE", "LEN", "LEO", "LET", "LEW", "LID", "LIE", "LIN", "LIP", "LIT", "LO",
"MA", "MAC", "MAD", "MAE", "MAN", "MAO", "MAP", "MAT", "MAW", "MAY", "LOB", "LOG", "LOP", "LOS", "LOT", "LOU", "LOW", "LOY", "LUG", "LYE",
"ME", "MEG", "MEL", "MEN", "MET", "MEW", "MID", "MIN", "MIT", "MOB", "MA", "MAC", "MAD", "MAE", "MAN", "MAO", "MAP", "MAT", "MAW", "MAY",
"MOD", "MOE", "MOO", "MOP", "MOS", "MOT", "MOW", "MUD", "MUG", "MUM", "ME", "MEG", "MEL", "MEN", "MET", "MEW", "MID", "MIN", "MIT", "MOB",
"MY", "NAB", "NAG", "NAN", "NAP", "NAT", "NAY", "NE", "NED", "NEE", "MOD", "MOE", "MOO", "MOP", "MOS", "MOT", "MOW", "MUD", "MUG", "MUM",
"NET", "NEW", "NIB", "NIL", "NIP", "NIT", "NO", "NOB", "NOD", "NON", "MY", "NAB", "NAG", "NAN", "NAP", "NAT", "NAY", "NE", "NED", "NEE",
"NOR", "NOT", "NOV", "NOW", "NU", "NUN", "NUT", "O", "OAF", "OAK", "NET", "NEW", "NIB", "NIL", "NIP", "NIT", "NO", "NOB", "NOD", "NON",
"OAR", "OAT", "ODD", "ODE", "OF", "OFF", "OFT", "OH", "OIL", "OK", "NOR", "NOT", "NOV", "NOW", "NU", "NUN", "NUT", "O", "OAF", "OAK",
"OLD", "ON", "ONE", "OR", "ORB", "ORE", "ORR", "OS", "OTT", "OUR", "OAR", "OAT", "ODD", "ODE", "OF", "OFF", "OFT", "OH", "OIL", "OK",
"OUT", "OVA", "OW", "OWE", "OWL", "OWN", "OX", "PA", "PAD", "PAL", "OLD", "ON", "ONE", "OR", "ORB", "ORE", "ORR", "OS", "OTT", "OUR",
"PAM", "PAN", "PAP", "PAR", "PAT", "PAW", "PAY", "PEA", "PEG", "PEN", "OUT", "OVA", "OW", "OWE", "OWL", "OWN", "OX", "PA", "PAD", "PAL",
"PEP", "PER", "PET", "PEW", "PHI", "PI", "PIE", "PIN", "PIT", "PLY", "PAM", "PAN", "PAP", "PAR", "PAT", "PAW", "PAY", "PEA", "PEG", "PEN",
"PO", "POD", "POE", "POP", "POT", "POW", "PRO", "PRY", "PUB", "PUG", "PEP", "PER", "PET", "PEW", "PHI", "PI", "PIE", "PIN", "PIT", "PLY",
"PUN", "PUP", "PUT", "QUO", "RAG", "RAM", "RAN", "RAP", "RAT", "RAW", "PO", "POD", "POE", "POP", "POT", "POW", "PRO", "PRY", "PUB", "PUG",
"RAY", "REB", "RED", "REP", "RET", "RIB", "RID", "RIG", "RIM", "RIO", "PUN", "PUP", "PUT", "QUO", "RAG", "RAM", "RAN", "RAP", "RAT", "RAW",
"RIP", "ROB", "ROD", "ROE", "RON", "ROT", "ROW", "ROY", "RUB", "RUE", "RAY", "REB", "RED", "REP", "RET", "RIB", "RID", "RIG", "RIM", "RIO",
"RUG", "RUM", "RUN", "RYE", "SAC", "SAD", "SAG", "SAL", "SAM", "SAN", "RIP", "ROB", "ROD", "ROE", "RON", "ROT", "ROW", "ROY", "RUB", "RUE",
"SAP", "SAT", "SAW", "SAY", "SEA", "SEC", "SEE", "SEN", "SET", "SEW", "RUG", "RUM", "RUN", "RYE", "SAC", "SAD", "SAG", "SAL", "SAM", "SAN",
"SHE", "SHY", "SIN", "SIP", "SIR", "SIS", "SIT", "SKI", "SKY", "SLY", "SAP", "SAT", "SAW", "SAY", "SEA", "SEC", "SEE", "SEN", "SET", "SEW",
"SO", "SOB", "SOD", "SON", "SOP", "SOW", "SOY", "SPA", "SPY", "SUB", "SHE", "SHY", "SIN", "SIP", "SIR", "SIS", "SIT", "SKI", "SKY", "SLY",
"SUD", "SUE", "SUM", "SUN", "SUP", "TAB", "TAD", "TAG", "TAN", "TAP", "SO", "SOB", "SOD", "SON", "SOP", "SOW", "SOY", "SPA", "SPY", "SUB",
"TAR", "TEA", "TED", "TEE", "TEN", "THE", "THY", "TIC", "TIE", "TIM", "SUD", "SUE", "SUM", "SUN", "SUP", "TAB", "TAD", "TAG", "TAN", "TAP",
"TIN", "TIP", "TO", "TOE", "TOG", "TOM", "TON", "TOO", "TOP", "TOW", "TAR", "TEA", "TED", "TEE", "TEN", "THE", "THY", "TIC", "TIE", "TIM",
"TOY", "TRY", "TUB", "TUG", "TUM", "TUN", "TWO", "UN", "UP", "US", "TIN", "TIP", "TO", "TOE", "TOG", "TOM", "TON", "TOO", "TOP", "TOW",
"USE", "VAN", "VAT", "VET", "VIE", "WAD", "WAG", "WAR", "WAS", "WAY", "TOY", "TRY", "TUB", "TUG", "TUM", "TUN", "TWO", "UN", "UP", "US",
"WE", "WEB", "WED", "WEE", "WET", "WHO", "WHY", "WIN", "WIT", "WOK", "USE", "VAN", "VAT", "VET", "VIE", "WAD", "WAG", "WAR", "WAS", "WAY",
"WON", "WOO", "WOW", "WRY", "WU", "YAM", "YAP", "YAW", "YE", "YEA", "WE", "WEB", "WED", "WEE", "WET", "WHO", "WHY", "WIN", "WIT", "WOK",
"YES", "YET", "YOU", "ABED", "ABEL", "ABET", "ABLE", "ABUT", "ACHE", "WON", "WOO", "WOW", "WRY", "WU", "YAM", "YAP", "YAW", "YE", "YEA",
"ACID", "ACME", "ACRE", "ACTA", "ACTS", "ADAM", "ADDS", "ADEN", "AFAR", "YES", "YET", "YOU", "ABED", "ABEL", "ABET", "ABLE", "ABUT", "ACHE",
"AFRO", "AGEE", "AHEM", "AHOY", "AIDA", "AIDE", "AIDS", "AIRY", "AJAR", "ACID", "ACME", "ACRE", "ACTA", "ACTS", "ADAM", "ADDS", "ADEN", "AFAR",
"AKIN", "ALAN", "ALEC", "ALGA", "ALIA", "ALLY", "ALMA", "ALOE", "ALSO", "AFRO", "AGEE", "AHEM", "AHOY", "AIDA", "AIDE", "AIDS", "AIRY", "AJAR",
"ALTO", "ALUM", "ALVA", "AMEN", "AMES", "AMID", "AMMO", "AMOK", "AMOS", "AKIN", "ALAN", "ALEC", "ALGA", "ALIA", "ALLY", "ALMA", "ALOE", "ALSO",
"AMRA", "ANDY", "ANEW", "ANNA", "ANNE", "ANTE", "ANTI", "AQUA", "ARAB", "ALTO", "ALUM", "ALVA", "AMEN", "AMES", "AMID", "AMMO", "AMOK", "AMOS",
"ARCH", "AREA", "ARGO", "ARID", "ARMY", "ARTS", "ARTY", "ASIA", "ASKS", "AMRA", "ANDY", "ANEW", "ANNA", "ANNE", "ANTE", "ANTI", "AQUA", "ARAB",
"ATOM", "AUNT", "AURA", "AUTO", "AVER", "AVID", "AVIS", "AVON", "AVOW", "ARCH", "AREA", "ARGO", "ARID", "ARMY", "ARTS", "ARTY", "ASIA", "ASKS",
"AWAY", "AWRY", "BABE", "BABY", "BACH", "BACK", "BADE", "BAIL", "BAIT", "ATOM", "AUNT", "AURA", "AUTO", "AVER", "AVID", "AVIS", "AVON", "AVOW",
"BAKE", "BALD", "BALE", "BALI", "BALK", "BALL", "BALM", "BAND", "BANE", "AWAY", "AWRY", "BABE", "BABY", "BACH", "BACK", "BADE", "BAIL", "BAIT",
"BANG", "BANK", "BARB", "BARD", "BARE", "BARK", "BARN", "BARR", "BASE", "BAKE", "BALD", "BALE", "BALI", "BALK", "BALL", "BALM", "BAND", "BANE",
"BASH", "BASK", "BASS", "BATE", "BATH", "BAWD", "BAWL", "BEAD", "BEAK", "BANG", "BANK", "BARB", "BARD", "BARE", "BARK", "BARN", "BARR", "BASE",
"BEAM", "BEAN", "BEAR", "BEAT", "BEAU", "BECK", "BEEF", "BEEN", "BEER", "BASH", "BASK", "BASS", "BATE", "BATH", "BAWD", "BAWL", "BEAD", "BEAK",
"BEET", "BELA", "BELL", "BELT", "BEND", "BENT", "BERG", "BERN", "BERT", "BEAM", "BEAN", "BEAR", "BEAT", "BEAU", "BECK", "BEEF", "BEEN", "BEER",
"BESS", "BEST", "BETA", "BETH", "BHOY", "BIAS", "BIDE", "BIEN", "BILE", "BEET", "BELA", "BELL", "BELT", "BEND", "BENT", "BERG", "BERN", "BERT",
"BILK", "BILL", "BIND", "BING", "BIRD", "BITE", "BITS", "BLAB", "BLAT", "BESS", "BEST", "BETA", "BETH", "BHOY", "BIAS", "BIDE", "BIEN", "BILE",
"BLED", "BLEW", "BLOB", "BLOC", "BLOT", "BLOW", "BLUE", "BLUM", "BLUR", "BILK", "BILL", "BIND", "BING", "BIRD", "BITE", "BITS", "BLAB", "BLAT",
"BOAR", "BOAT", "BOCA", "BOCK", "BODE", "BODY", "BOGY", "BOHR", "BOIL", "BLED", "BLEW", "BLOB", "BLOC", "BLOT", "BLOW", "BLUE", "BLUM", "BLUR",
"BOLD", "BOLO", "BOLT", "BOMB", "BONA", "BOND", "BONE", "BONG", "BONN", "BOAR", "BOAT", "BOCA", "BOCK", "BODE", "BODY", "BOGY", "BOHR", "BOIL",
"BONY", "BOOK", "BOOM", "BOON", "BOOT", "BORE", "BORG", "BORN", "BOSE", "BOLD", "BOLO", "BOLT", "BOMB", "BONA", "BOND", "BONE", "BONG", "BONN",
"BOSS", "BOTH", "BOUT", "BOWL", "BOYD", "BRAD", "BRAE", "BRAG", "BRAN", "BONY", "BOOK", "BOOM", "BOON", "BOOT", "BORE", "BORG", "BORN", "BOSE",
"BRAY", "BRED", "BREW", "BRIG", "BRIM", "BROW", "BUCK", "BUDD", "BUFF", "BOSS", "BOTH", "BOUT", "BOWL", "BOYD", "BRAD", "BRAE", "BRAG", "BRAN",
"BULB", "BULK", "BULL", "BUNK", "BUNT", "BUOY", "BURG", "BURL", "BURN", "BRAY", "BRED", "BREW", "BRIG", "BRIM", "BROW", "BUCK", "BUDD", "BUFF",
"BURR", "BURT", "BURY", "BUSH", "BUSS", "BUST", "BUSY", "BYTE", "CADY", "BULB", "BULK", "BULL", "BUNK", "BUNT", "BUOY", "BURG", "BURL", "BURN",
"CAFE", "CAGE", "CAIN", "CAKE", "CALF", "CALL", "CALM", "CAME", "CANE", "BURR", "BURT", "BURY", "BUSH", "BUSS", "BUST", "BUSY", "BYTE", "CADY",
"CANT", "CARD", "CARE", "CARL", "CARR", "CART", "CASE", "CASH", "CASK", "CAFE", "CAGE", "CAIN", "CAKE", "CALF", "CALL", "CALM", "CAME", "CANE",
"CAST", "CAVE", "CEIL", "CELL", "CENT", "CERN", "CHAD", "CHAR", "CHAT", "CANT", "CARD", "CARE", "CARL", "CARR", "CART", "CASE", "CASH", "CASK",
"CHAW", "CHEF", "CHEN", "CHEW", "CHIC", "CHIN", "CHOU", "CHOW", "CHUB", "CAST", "CAVE", "CEIL", "CELL", "CENT", "CERN", "CHAD", "CHAR", "CHAT",
"CHUG", "CHUM", "CITE", "CITY", "CLAD", "CLAM", "CLAN", "CLAW", "CLAY", "CHAW", "CHEF", "CHEN", "CHEW", "CHIC", "CHIN", "CHOU", "CHOW", "CHUB",
"CLOD", "CLOG", "CLOT", "CLUB", "CLUE", "COAL", "COAT", "COCA", "COCK", "CHUG", "CHUM", "CITE", "CITY", "CLAD", "CLAM", "CLAN", "CLAW", "CLAY",
"COCO", "CODA", "CODE", "CODY", "COED", "COIL", "COIN", "COKE", "COLA", "CLOD", "CLOG", "CLOT", "CLUB", "CLUE", "COAL", "COAT", "COCA", "COCK",
"COLD", "COLT", "COMA", "COMB", "COME", "COOK", "COOL", "COON", "COOT", "COCO", "CODA", "CODE", "CODY", "COED", "COIL", "COIN", "COKE", "COLA",
"CORD", "CORE", "CORK", "CORN", "COST", "COVE", "COWL", "CRAB", "CRAG", "COLD", "COLT", "COMA", "COMB", "COME", "COOK", "COOL", "COON", "COOT",
"CRAM", "CRAY", "CREW", "CRIB", "CROW", "CRUD", "CUBA", "CUBE", "CUFF", "CORD", "CORE", "CORK", "CORN", "COST", "COVE", "COWL", "CRAB", "CRAG",
"CULL", "CULT", "CUNY", "CURB", "CURD", "CURE", "CURL", "CURT", "CUTS", "CRAM", "CRAY", "CREW", "CRIB", "CROW", "CRUD", "CUBA", "CUBE", "CUFF",
"DADE", "DALE", "DAME", "DANA", "DANE", "DANG", "DANK", "DARE", "DARK", "CULL", "CULT", "CUNY", "CURB", "CURD", "CURE", "CURL", "CURT", "CUTS",
"DARN", "DART", "DASH", "DATA", "DATE", "DAVE", "DAVY", "DAWN", "DAYS", "DADE", "DALE", "DAME", "DANA", "DANE", "DANG", "DANK", "DARE", "DARK",
"DEAD", "DEAF", "DEAL", "DEAN", "DEAR", "DEBT", "DECK", "DEED", "DEEM", "DARN", "DART", "DASH", "DATA", "DATE", "DAVE", "DAVY", "DAWN", "DAYS",
"DEER", "DEFT", "DEFY", "DELL", "DENT", "DENY", "DESK", "DIAL", "DICE", "DEAD", "DEAF", "DEAL", "DEAN", "DEAR", "DEBT", "DECK", "DEED", "DEEM",
"DIED", "DIET", "DIME", "DINE", "DING", "DINT", "DIRE", "DIRT", "DISC", "DEER", "DEFT", "DEFY", "DELL", "DENT", "DENY", "DESK", "DIAL", "DICE",
"DISH", "DISK", "DIVE", "DOCK", "DOES", "DOLE", "DOLL", "DOLT", "DOME", "DIED", "DIET", "DIME", "DINE", "DING", "DINT", "DIRE", "DIRT", "DISC",
"DONE", "DOOM", "DOOR", "DORA", "DOSE", "DOTE", "DOUG", "DOUR", "DOVE", "DISH", "DISK", "DIVE", "DOCK", "DOES", "DOLE", "DOLL", "DOLT", "DOME",
"DOWN", "DRAB", "DRAG", "DRAM", "DRAW", "DREW", "DRUB", "DRUG", "DRUM", "DONE", "DOOM", "DOOR", "DORA", "DOSE", "DOTE", "DOUG", "DOUR", "DOVE",
"DUAL", "DUCK", "DUCT", "DUEL", "DUET", "DUKE", "DULL", "DUMB", "DUNE", "DOWN", "DRAB", "DRAG", "DRAM", "DRAW", "DREW", "DRUB", "DRUG", "DRUM",
"DUNK", "DUSK", "DUST", "DUTY", "EACH", "EARL", "EARN", "EASE", "EAST", "DUAL", "DUCK", "DUCT", "DUEL", "DUET", "DUKE", "DULL", "DUMB", "DUNE",
"EASY", "EBEN", "ECHO", "EDDY", "EDEN", "EDGE", "EDGY", "EDIT", "EDNA", "DUNK", "DUSK", "DUST", "DUTY", "EACH", "EARL", "EARN", "EASE", "EAST",
"EGAN", "ELAN", "ELBA", "ELLA", "ELSE", "EMIL", "EMIT", "EMMA", "ENDS", "EASY", "EBEN", "ECHO", "EDDY", "EDEN", "EDGE", "EDGY", "EDIT", "EDNA",
"ERIC", "EROS", "EVEN", "EVER", "EVIL", "EYED", "FACE", "FACT", "FADE", "EGAN", "ELAN", "ELBA", "ELLA", "ELSE", "EMIL", "EMIT", "EMMA", "ENDS",
"FAIL", "FAIN", "FAIR", "FAKE", "FALL", "FAME", "FANG", "FARM", "FAST", "ERIC", "EROS", "EVEN", "EVER", "EVIL", "EYED", "FACE", "FACT", "FADE",
"FATE", "FAWN", "FEAR", "FEAT", "FEED", "FEEL", "FEET", "FELL", "FELT", "FAIL", "FAIN", "FAIR", "FAKE", "FALL", "FAME", "FANG", "FARM", "FAST",
"FEND", "FERN", "FEST", "FEUD", "FIEF", "FIGS", "FILE", "FILL", "FILM", "FATE", "FAWN", "FEAR", "FEAT", "FEED", "FEEL", "FEET", "FELL", "FELT",
"FIND", "FINE", "FINK", "FIRE", "FIRM", "FISH", "FISK", "FIST", "FITS", "FEND", "FERN", "FEST", "FEUD", "FIEF", "FIGS", "FILE", "FILL", "FILM",
"FIVE", "FLAG", "FLAK", "FLAM", "FLAT", "FLAW", "FLEA", "FLED", "FLEW", "FIND", "FINE", "FINK", "FIRE", "FIRM", "FISH", "FISK", "FIST", "FITS",
"FLIT", "FLOC", "FLOG", "FLOW", "FLUB", "FLUE", "FOAL", "FOAM", "FOGY", "FIVE", "FLAG", "FLAK", "FLAM", "FLAT", "FLAW", "FLEA", "FLED", "FLEW",
"FOIL", "FOLD", "FOLK", "FOND", "FONT", "FOOD", "FOOL", "FOOT", "FORD", "FLIT", "FLOC", "FLOG", "FLOW", "FLUB", "FLUE", "FOAL", "FOAM", "FOGY",
"FORE", "FORK", "FORM", "FORT", "FOSS", "FOUL", "FOUR", "FOWL", "FRAU", "FOIL", "FOLD", "FOLK", "FOND", "FONT", "FOOD", "FOOL", "FOOT", "FORD",
"FRAY", "FRED", "FREE", "FRET", "FREY", "FROG", "FROM", "FUEL", "FULL", "FORE", "FORK", "FORM", "FORT", "FOSS", "FOUL", "FOUR", "FOWL", "FRAU",
"FUME", "FUND", "FUNK", "FURY", "FUSE", "FUSS", "GAFF", "GAGE", "GAIL", "FRAY", "FRED", "FREE", "FRET", "FREY", "FROG", "FROM", "FUEL", "FULL",
"GAIN", "GAIT", "GALA", "GALE", "GALL", "GALT", "GAME", "GANG", "GARB", "FUME", "FUND", "FUNK", "FURY", "FUSE", "FUSS", "GAFF", "GAGE", "GAIL",
"GARY", "GASH", "GATE", "GAUL", "GAUR", "GAVE", "GAWK", "GEAR", "GELD", "GAIN", "GAIT", "GALA", "GALE", "GALL", "GALT", "GAME", "GANG", "GARB",
"GENE", "GENT", "GERM", "GETS", "GIBE", "GIFT", "GILD", "GILL", "GILT", "GARY", "GASH", "GATE", "GAUL", "GAUR", "GAVE", "GAWK", "GEAR", "GELD",
"GINA", "GIRD", "GIRL", "GIST", "GIVE", "GLAD", "GLEE", "GLEN", "GLIB", "GENE", "GENT", "GERM", "GETS", "GIBE", "GIFT", "GILD", "GILL", "GILT",
"GLOB", "GLOM", "GLOW", "GLUE", "GLUM", "GLUT", "GOAD", "GOAL", "GOAT", "GINA", "GIRD", "GIRL", "GIST", "GIVE", "GLAD", "GLEE", "GLEN", "GLIB",
"GOER", "GOES", "GOLD", "GOLF", "GONE", "GONG", "GOOD", "GOOF", "GORE", "GLOB", "GLOM", "GLOW", "GLUE", "GLUM", "GLUT", "GOAD", "GOAL", "GOAT",
"GORY", "GOSH", "GOUT", "GOWN", "GRAB", "GRAD", "GRAY", "GREG", "GREW", "GOER", "GOES", "GOLD", "GOLF", "GONE", "GONG", "GOOD", "GOOF", "GORE",
"GREY", "GRID", "GRIM", "GRIN", "GRIT", "GROW", "GRUB", "GULF", "GULL", "GORY", "GOSH", "GOUT", "GOWN", "GRAB", "GRAD", "GRAY", "GREG", "GREW",
"GUNK", "GURU", "GUSH", "GUST", "GWEN", "GWYN", "HAAG", "HAAS", "HACK", "GREY", "GRID", "GRIM", "GRIN", "GRIT", "GROW", "GRUB", "GULF", "GULL",
"HAIL", "HAIR", "HALE", "HALF", "HALL", "HALO", "HALT", "HAND", "HANG", "GUNK", "GURU", "GUSH", "GUST", "GWEN", "GWYN", "HAAG", "HAAS", "HACK",
"HANK", "HANS", "HARD", "HARK", "HARM", "HART", "HASH", "HAST", "HATE", "HAIL", "HAIR", "HALE", "HALF", "HALL", "HALO", "HALT", "HAND", "HANG",
"HATH", "HAUL", "HAVE", "HAWK", "HAYS", "HEAD", "HEAL", "HEAR", "HEAT", "HANK", "HANS", "HARD", "HARK", "HARM", "HART", "HASH", "HAST", "HATE",
"HEBE", "HECK", "HEED", "HEEL", "HEFT", "HELD", "HELL", "HELM", "HERB", "HATH", "HAUL", "HAVE", "HAWK", "HAYS", "HEAD", "HEAL", "HEAR", "HEAT",
"HERD", "HERE", "HERO", "HERS", "HESS", "HEWN", "HICK", "HIDE", "HIGH", "HEBE", "HECK", "HEED", "HEEL", "HEFT", "HELD", "HELL", "HELM", "HERB",
"HIKE", "HILL", "HILT", "HIND", "HINT", "HIRE", "HISS", "HIVE", "HOBO", "HERD", "HERE", "HERO", "HERS", "HESS", "HEWN", "HICK", "HIDE", "HIGH",
"HOCK", "HOFF", "HOLD", "HOLE", "HOLM", "HOLT", "HOME", "HONE", "HONK", "HIKE", "HILL", "HILT", "HIND", "HINT", "HIRE", "HISS", "HIVE", "HOBO",
"HOOD", "HOOF", "HOOK", "HOOT", "HORN", "HOSE", "HOST", "HOUR", "HOVE", "HOCK", "HOFF", "HOLD", "HOLE", "HOLM", "HOLT", "HOME", "HONE", "HONK",
"HOWE", "HOWL", "HOYT", "HUCK", "HUED", "HUFF", "HUGE", "HUGH", "HUGO", "HOOD", "HOOF", "HOOK", "HOOT", "HORN", "HOSE", "HOST", "HOUR", "HOVE",
"HULK", "HULL", "HUNK", "HUNT", "HURD", "HURL", "HURT", "HUSH", "HYDE", "HOWE", "HOWL", "HOYT", "HUCK", "HUED", "HUFF", "HUGE", "HUGH", "HUGO",
"HYMN", "IBIS", "ICON", "IDEA", "IDLE", "IFFY", "INCA", "INCH", "INTO", "HULK", "HULL", "HUNK", "HUNT", "HURD", "HURL", "HURT", "HUSH", "HYDE",
"IONS", "IOTA", "IOWA", "IRIS", "IRMA", "IRON", "ISLE", "ITCH", "ITEM", "HYMN", "IBIS", "ICON", "IDEA", "IDLE", "IFFY", "INCA", "INCH", "INTO",
"IVAN", "JACK", "JADE", "JAIL", "JAKE", "JANE", "JAVA", "JEAN", "JEFF", "IONS", "IOTA", "IOWA", "IRIS", "IRMA", "IRON", "ISLE", "ITCH", "ITEM",
"JERK", "JESS", "JEST", "JIBE", "JILL", "JILT", "JIVE", "JOAN", "JOBS", "IVAN", "JACK", "JADE", "JAIL", "JAKE", "JANE", "JAVA", "JEAN", "JEFF",
"JOCK", "JOEL", "JOEY", "JOHN", "JOIN", "JOKE", "JOLT", "JOVE", "JUDD", "JERK", "JESS", "JEST", "JIBE", "JILL", "JILT", "JIVE", "JOAN", "JOBS",
"JUDE", "JUDO", "JUDY", "JUJU", "JUKE", "JULY", "JUNE", "JUNK", "JUNO", "JOCK", "JOEL", "JOEY", "JOHN", "JOIN", "JOKE", "JOLT", "JOVE", "JUDD",
"JURY", "JUST", "JUTE", "KAHN", "KALE", "KANE", "KANT", "KARL", "KATE", "JUDE", "JUDO", "JUDY", "JUJU", "JUKE", "JULY", "JUNE", "JUNK", "JUNO",
"KEEL", "KEEN", "KENO", "KENT", "KERN", "KERR", "KEYS", "KICK", "KILL", "JURY", "JUST", "JUTE", "KAHN", "KALE", "KANE", "KANT", "KARL", "KATE",
"KIND", "KING", "KIRK", "KISS", "KITE", "KLAN", "KNEE", "KNEW", "KNIT", "KEEL", "KEEN", "KENO", "KENT", "KERN", "KERR", "KEYS", "KICK", "KILL",
"KNOB", "KNOT", "KNOW", "KOCH", "KONG", "KUDO", "KURD", "KURT", "KYLE", "KIND", "KING", "KIRK", "KISS", "KITE", "KLAN", "KNEE", "KNEW", "KNIT",
"LACE", "LACK", "LACY", "LADY", "LAID", "LAIN", "LAIR", "LAKE", "LAMB", "KNOB", "KNOT", "KNOW", "KOCH", "KONG", "KUDO", "KURD", "KURT", "KYLE",
"LAME", "LAND", "LANE", "LANG", "LARD", "LARK", "LASS", "LAST", "LATE", "LACE", "LACK", "LACY", "LADY", "LAID", "LAIN", "LAIR", "LAKE", "LAMB",
"LAUD", "LAVA", "LAWN", "LAWS", "LAYS", "LEAD", "LEAF", "LEAK", "LEAN", "LAME", "LAND", "LANE", "LANG", "LARD", "LARK", "LASS", "LAST", "LATE",
"LEAR", "LEEK", "LEER", "LEFT", "LEND", "LENS", "LENT", "LEON", "LESK", "LAUD", "LAVA", "LAWN", "LAWS", "LAYS", "LEAD", "LEAF", "LEAK", "LEAN",
"LESS", "LEST", "LETS", "LIAR", "LICE", "LICK", "LIED", "LIEN", "LIES", "LEAR", "LEEK", "LEER", "LEFT", "LEND", "LENS", "LENT", "LEON", "LESK",
"LIEU", "LIFE", "LIFT", "LIKE", "LILA", "LILT", "LILY", "LIMA", "LIMB", "LESS", "LEST", "LETS", "LIAR", "LICE", "LICK", "LIED", "LIEN", "LIES",
"LIME", "LIND", "LINE", "LINK", "LINT", "LION", "LISA", "LIST", "LIVE", "LIEU", "LIFE", "LIFT", "LIKE", "LILA", "LILT", "LILY", "LIMA", "LIMB",
"LOAD", "LOAF", "LOAM", "LOAN", "LOCK", "LOFT", "LOGE", "LOIS", "LOLA", "LIME", "LIND", "LINE", "LINK", "LINT", "LION", "LISA", "LIST", "LIVE",
"LONE", "LONG", "LOOK", "LOON", "LOOT", "LORD", "LORE", "LOSE", "LOSS", "LOAD", "LOAF", "LOAM", "LOAN", "LOCK", "LOFT", "LOGE", "LOIS", "LOLA",
"LOST", "LOUD", "LOVE", "LOWE", "LUCK", "LUCY", "LUGE", "LUKE", "LULU", "LONE", "LONG", "LOOK", "LOON", "LOOT", "LORD", "LORE", "LOSE", "LOSS",
"LUND", "LUNG", "LURA", "LURE", "LURK", "LUSH", "LUST", "LYLE", "LYNN", "LOST", "LOUD", "LOVE", "LOWE", "LUCK", "LUCY", "LUGE", "LUKE", "LULU",
"LYON", "LYRA", "MACE", "MADE", "MAGI", "MAID", "MAIL", "MAIN", "MAKE", "LUND", "LUNG", "LURA", "LURE", "LURK", "LUSH", "LUST", "LYLE", "LYNN",
"MALE", "MALI", "MALL", "MALT", "MANA", "MANN", "MANY", "MARC", "MARE", "LYON", "LYRA", "MACE", "MADE", "MAGI", "MAID", "MAIL", "MAIN", "MAKE",
"MARK", "MARS", "MART", "MARY", "MASH", "MASK", "MASS", "MAST", "MATE", "MALE", "MALI", "MALL", "MALT", "MANA", "MANN", "MANY", "MARC", "MARE",
"MATH", "MAUL", "MAYO", "MEAD", "MEAL", "MEAN", "MEAT", "MEEK", "MEET", "MARK", "MARS", "MART", "MARY", "MASH", "MASK", "MASS", "MAST", "MATE",
"MELD", "MELT", "MEMO", "MEND", "MENU", "MERT", "MESH", "MESS", "MICE", "MATH", "MAUL", "MAYO", "MEAD", "MEAL", "MEAN", "MEAT", "MEEK", "MEET",
"MIKE", "MILD", "MILE", "MILK", "MILL", "MILT", "MIMI", "MIND", "MINE", "MELD", "MELT", "MEMO", "MEND", "MENU", "MERT", "MESH", "MESS", "MICE",
"MINI", "MINK", "MINT", "MIRE", "MISS", "MIST", "MITE", "MITT", "MOAN", "MIKE", "MILD", "MILE", "MILK", "MILL", "MILT", "MIMI", "MIND", "MINE",
"MOAT", "MOCK", "MODE", "MOLD", "MOLE", "MOLL", "MOLT", "MONA", "MONK", "MINI", "MINK", "MINT", "MIRE", "MISS", "MIST", "MITE", "MITT", "MOAN",
"MONT", "MOOD", "MOON", "MOOR", "MOOT", "MORE", "MORN", "MORT", "MOSS", "MOAT", "MOCK", "MODE", "MOLD", "MOLE", "MOLL", "MOLT", "MONA", "MONK",
"MOST", "MOTH", "MOVE", "MUCH", "MUCK", "MUDD", "MUFF", "MULE", "MULL", "MONT", "MOOD", "MOON", "MOOR", "MOOT", "MORE", "MORN", "MORT", "MOSS",
"MURK", "MUSH", "MUST", "MUTE", "MUTT", "MYRA", "MYTH", "NAGY", "NAIL", "MOST", "MOTH", "MOVE", "MUCH", "MUCK", "MUDD", "MUFF", "MULE", "MULL",
"NAIR", "NAME", "NARY", "NASH", "NAVE", "NAVY", "NEAL", "NEAR", "NEAT", "MURK", "MUSH", "MUST", "MUTE", "MUTT", "MYRA", "MYTH", "NAGY", "NAIL",
"NECK", "NEED", "NEIL", "NELL", "NEON", "NERO", "NESS", "NEST", "NEWS", "NAIR", "NAME", "NARY", "NASH", "NAVE", "NAVY", "NEAL", "NEAR", "NEAT",
"NEWT", "NIBS", "NICE", "NICK", "NILE", "NINA", "NINE", "NOAH", "NODE", "NECK", "NEED", "NEIL", "NELL", "NEON", "NERO", "NESS", "NEST", "NEWS",
"NOEL", "NOLL", "NONE", "NOOK", "NOON", "NORM", "NOSE", "NOTE", "NOUN", "NEWT", "NIBS", "NICE", "NICK", "NILE", "NINA", "NINE", "NOAH", "NODE",
"NOVA", "NUDE", "NULL", "NUMB", "OATH", "OBEY", "OBOE", "ODIN", "OHIO", "NOEL", "NOLL", "NONE", "NOOK", "NOON", "NORM", "NOSE", "NOTE", "NOUN",
"OILY", "OINT", "OKAY", "OLAF", "OLDY", "OLGA", "OLIN", "OMAN", "OMEN", "NOVA", "NUDE", "NULL", "NUMB", "OATH", "OBEY", "OBOE", "ODIN", "OHIO",
"OMIT", "ONCE", "ONES", "ONLY", "ONTO", "ONUS", "ORAL", "ORGY", "OSLO", "OILY", "OINT", "OKAY", "OLAF", "OLDY", "OLGA", "OLIN", "OMAN", "OMEN",
"OTIS", "OTTO", "OUCH", "OUST", "OUTS", "OVAL", "OVEN", "OVER", "OWLY", "OMIT", "ONCE", "ONES", "ONLY", "ONTO", "ONUS", "ORAL", "ORGY", "OSLO",
"OWNS", "QUAD", "QUIT", "QUOD", "RACE", "RACK", "RACY", "RAFT", "RAGE", "OTIS", "OTTO", "OUCH", "OUST", "OUTS", "OVAL", "OVEN", "OVER", "OWLY",
"RAID", "RAIL", "RAIN", "RAKE", "RANK", "RANT", "RARE", "RASH", "RATE", "OWNS", "QUAD", "QUIT", "QUOD", "RACE", "RACK", "RACY", "RAFT", "RAGE",
"RAVE", "RAYS", "READ", "REAL", "REAM", "REAR", "RECK", "REED", "REEF", "RAID", "RAIL", "RAIN", "RAKE", "RANK", "RANT", "RARE", "RASH", "RATE",
"REEK", "REEL", "REID", "REIN", "RENA", "REND", "RENT", "REST", "RICE", "RAVE", "RAYS", "READ", "REAL", "REAM", "REAR", "RECK", "REED", "REEF",
"RICH", "RICK", "RIDE", "RIFT", "RILL", "RIME", "RING", "RINK", "RISE", "REEK", "REEL", "REID", "REIN", "RENA", "REND", "RENT", "REST", "RICE",
"RISK", "RITE", "ROAD", "ROAM", "ROAR", "ROBE", "ROCK", "RODE", "ROIL", "RICH", "RICK", "RIDE", "RIFT", "RILL", "RIME", "RING", "RINK", "RISE",
"ROLL", "ROME", "ROOD", "ROOF", "ROOK", "ROOM", "ROOT", "ROSA", "ROSE", "RISK", "RITE", "ROAD", "ROAM", "ROAR", "ROBE", "ROCK", "RODE", "ROIL",
"ROSS", "ROSY", "ROTH", "ROUT", "ROVE", "ROWE", "ROWS", "RUBE", "RUBY", "ROLL", "ROME", "ROOD", "ROOF", "ROOK", "ROOM", "ROOT", "ROSA", "ROSE",
"RUDE", "RUDY", "RUIN", "RULE", "RUNG", "RUNS", "RUNT", "RUSE", "RUSH", "ROSS", "ROSY", "ROTH", "ROUT", "ROVE", "ROWE", "ROWS", "RUBE", "RUBY",
"RUSK", "RUSS", "RUST", "RUTH", "SACK", "SAFE", "SAGE", "SAID", "SAIL", "RUDE", "RUDY", "RUIN", "RULE", "RUNG", "RUNS", "RUNT", "RUSE", "RUSH",
"SALE", "SALK", "SALT", "SAME", "SAND", "SANE", "SANG", "SANK", "SARA", "RUSK", "RUSS", "RUST", "RUTH", "SACK", "SAFE", "SAGE", "SAID", "SAIL",
"SAUL", "SAVE", "SAYS", "SCAN", "SCAR", "SCAT", "SCOT", "SEAL", "SEAM", "SALE", "SALK", "SALT", "SAME", "SAND", "SANE", "SANG", "SANK", "SARA",
"SEAR", "SEAT", "SEED", "SEEK", "SEEM", "SEEN", "SEES", "SELF", "SELL", "SAUL", "SAVE", "SAYS", "SCAN", "SCAR", "SCAT", "SCOT", "SEAL", "SEAM",
"SEND", "SENT", "SETS", "SEWN", "SHAG", "SHAM", "SHAW", "SHAY", "SHED", "SEAR", "SEAT", "SEED", "SEEK", "SEEM", "SEEN", "SEES", "SELF", "SELL",
"SHIM", "SHIN", "SHOD", "SHOE", "SHOT", "SHOW", "SHUN", "SHUT", "SICK", "SEND", "SENT", "SETS", "SEWN", "SHAG", "SHAM", "SHAW", "SHAY", "SHED",
"SIDE", "SIFT", "SIGH", "SIGN", "SILK", "SILL", "SILO", "SILT", "SINE", "SHIM", "SHIN", "SHOD", "SHOE", "SHOT", "SHOW", "SHUN", "SHUT", "SICK",
"SING", "SINK", "SIRE", "SITE", "SITS", "SITU", "SKAT", "SKEW", "SKID", "SIDE", "SIFT", "SIGH", "SIGN", "SILK", "SILL", "SILO", "SILT", "SINE",
"SKIM", "SKIN", "SKIT", "SLAB", "SLAM", "SLAT", "SLAY", "SLED", "SLEW", "SING", "SINK", "SIRE", "SITE", "SITS", "SITU", "SKAT", "SKEW", "SKID",
"SLID", "SLIM", "SLIT", "SLOB", "SLOG", "SLOT", "SLOW", "SLUG", "SLUM", "SKIM", "SKIN", "SKIT", "SLAB", "SLAM", "SLAT", "SLAY", "SLED", "SLEW",
"SLUR", "SMOG", "SMUG", "SNAG", "SNOB", "SNOW", "SNUB", "SNUG", "SOAK", "SLID", "SLIM", "SLIT", "SLOB", "SLOG", "SLOT", "SLOW", "SLUG", "SLUM",
"SOAR", "SOCK", "SODA", "SOFA", "SOFT", "SOIL", "SOLD", "SOME", "SONG", "SLUR", "SMOG", "SMUG", "SNAG", "SNOB", "SNOW", "SNUB", "SNUG", "SOAK",
"SOON", "SOOT", "SORE", "SORT", "SOUL", "SOUR", "SOWN", "STAB", "STAG", "SOAR", "SOCK", "SODA", "SOFA", "SOFT", "SOIL", "SOLD", "SOME", "SONG",
"STAN", "STAR", "STAY", "STEM", "STEW", "STIR", "STOW", "STUB", "STUN", "SOON", "SOOT", "SORE", "SORT", "SOUL", "SOUR", "SOWN", "STAB", "STAG",
"SUCH", "SUDS", "SUIT", "SULK", "SUMS", "SUNG", "SUNK", "SURE", "SURF", "STAN", "STAR", "STAY", "STEM", "STEW", "STIR", "STOW", "STUB", "STUN",
"SWAB", "SWAG", "SWAM", "SWAN", "SWAT", "SWAY", "SWIM", "SWUM", "TACK", "SUCH", "SUDS", "SUIT", "SULK", "SUMS", "SUNG", "SUNK", "SURE", "SURF",
"TACT", "TAIL", "TAKE", "TALE", "TALK", "TALL", "TANK", "TASK", "TATE", "SWAB", "SWAG", "SWAM", "SWAN", "SWAT", "SWAY", "SWIM", "SWUM", "TACK",
"TAUT", "TEAL", "TEAM", "TEAR", "TECH", "TEEM", "TEEN", "TEET", "TELL", "TACT", "TAIL", "TAKE", "TALE", "TALK", "TALL", "TANK", "TASK", "TATE",
"TEND", "TENT", "TERM", "TERN", "TESS", "TEST", "THAN", "THAT", "THEE", "TAUT", "TEAL", "TEAM", "TEAR", "TECH", "TEEM", "TEEN", "TEET", "TELL",
"THEM", "THEN", "THEY", "THIN", "THIS", "THUD", "THUG", "TICK", "TIDE", "TEND", "TENT", "TERM", "TERN", "TESS", "TEST", "THAN", "THAT", "THEE",
"TIDY", "TIED", "TIER", "TILE", "TILL", "TILT", "TIME", "TINA", "TINE", "THEM", "THEN", "THEY", "THIN", "THIS", "THUD", "THUG", "TICK", "TIDE",
"TINT", "TINY", "TIRE", "TOAD", "TOGO", "TOIL", "TOLD", "TOLL", "TONE", "TIDY", "TIED", "TIER", "TILE", "TILL", "TILT", "TIME", "TINA", "TINE",
"TONG", "TONY", "TOOK", "TOOL", "TOOT", "TORE", "TORN", "TOTE", "TOUR", "TINT", "TINY", "TIRE", "TOAD", "TOGO", "TOIL", "TOLD", "TOLL", "TONE",
"TOUT", "TOWN", "TRAG", "TRAM", "TRAY", "TREE", "TREK", "TRIG", "TRIM", "TONG", "TONY", "TOOK", "TOOL", "TOOT", "TORE", "TORN", "TOTE", "TOUR",
"TRIO", "TROD", "TROT", "TROY", "TRUE", "TUBA", "TUBE", "TUCK", "TUFT", "TOUT", "TOWN", "TRAG", "TRAM", "TRAY", "TREE", "TREK", "TRIG", "TRIM",
"TUNA", "TUNE", "TUNG", "TURF", "TURN", "TUSK", "TWIG", "TWIN", "TWIT", "TRIO", "TROD", "TROT", "TROY", "TRUE", "TUBA", "TUBE", "TUCK", "TUFT",
"ULAN", "UNIT", "URGE", "USED", "USER", "USES", "UTAH", "VAIL", "VAIN", "TUNA", "TUNE", "TUNG", "TURF", "TURN", "TUSK", "TWIG", "TWIN", "TWIT",
"VALE", "VARY", "VASE", "VAST", "VEAL", "VEDA", "VEIL", "VEIN", "VEND", "ULAN", "UNIT", "URGE", "USED", "USER", "USES", "UTAH", "VAIL", "VAIN",
"VENT", "VERB", "VERY", "VETO", "VICE", "VIEW", "VINE", "VISE", "VOID", "VALE", "VARY", "VASE", "VAST", "VEAL", "VEDA", "VEIL", "VEIN", "VEND",
"VOLT", "VOTE", "WACK", "WADE", "WAGE", "WAIL", "WAIT", "WAKE", "WALE", "VENT", "VERB", "VERY", "VETO", "VICE", "VIEW", "VINE", "VISE", "VOID",
"WALK", "WALL", "WALT", "WAND", "WANE", "WANG", "WANT", "WARD", "WARM", "VOLT", "VOTE", "WACK", "WADE", "WAGE", "WAIL", "WAIT", "WAKE", "WALE",
"WARN", "WART", "WASH", "WAST", "WATS", "WATT", "WAVE", "WAVY", "WAYS", "WALK", "WALL", "WALT", "WAND", "WANE", "WANG", "WANT", "WARD", "WARM",
"WEAK", "WEAL", "WEAN", "WEAR", "WEED", "WEEK", "WEIR", "WELD", "WELL", "WARN", "WART", "WASH", "WAST", "WATS", "WATT", "WAVE", "WAVY", "WAYS",
"WELT", "WENT", "WERE", "WERT", "WEST", "WHAM", "WHAT", "WHEE", "WHEN", "WEAK", "WEAL", "WEAN", "WEAR", "WEED", "WEEK", "WEIR", "WELD", "WELL",
"WHET", "WHOA", "WHOM", "WICK", "WIFE", "WILD", "WILL", "WIND", "WINE", "WELT", "WENT", "WERE", "WERT", "WEST", "WHAM", "WHAT", "WHEE", "WHEN",
"WING", "WINK", "WINO", "WIRE", "WISE", "WISH", "WITH", "WOLF", "WONT", "WHET", "WHOA", "WHOM", "WICK", "WIFE", "WILD", "WILL", "WIND", "WINE",
"WOOD", "WOOL", "WORD", "WORE", "WORK", "WORM", "WORN", "WOVE", "WRIT", "WING", "WINK", "WINO", "WIRE", "WISE", "WISH", "WITH", "WOLF", "WONT",
"WYNN", "YALE", "YANG", "YANK", "YARD", "YARN", "YAWL", "YAWN", "YEAH", "WOOD", "WOOL", "WORD", "WORE", "WORK", "WORM", "WORN", "WOVE", "WRIT",
"YEAR", "YELL", "YOGA", "YOKE" "WYNN", "YALE", "YANG", "YANK", "YARD", "YARN", "YAWL", "YAWN", "YEAH",
"YEAR", "YELL", "YOGA", "YOKE"
}; };
/* Extract 'length' bits from the char array 's' /* Extract 'length' bits from the char array 's'
starting with bit 'start' */ 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 cl;
unsigned char cc; unsigned char cc;
unsigned char cr; unsigned char cr;
unsigned long x; unsigned long x;
assert(length <= 11); assert (length <= 11);
assert(start >= 0); assert (start >= 0);
assert(length >= 0); assert (length >= 0);
assert(start+length <= 66); assert (start + length <= 66);
cl = s[start/8]; // get components cl = s[start / 8]; // get components
cc = s[start/8 +1]; cc = s[start / 8 + 1];
cr = s[start/8 +2]; cr = s[start / 8 + 2];
x = ((long)(cl<<8 | cc) <<8 | cr) ; // Put bits together x = ((long) (cl << 8 | cc) << 8 | cr) ; // Put bits together
x = x >> (24 - (length + (start%8))); // Right justify number x = x >> (24 - (length + (start % 8))); // Right justify number
x = ( x & (0xffff >> (16-length) ) ); // Trim extra bits. x = ( x & (0xffff >> (16 - length) ) ); // Trim extra bits.
return x; return x;
} }
// Encode 8 bytes in 'c' as a string of English words. // Encode 8 bytes in 'c' as a string of English words.
// Returns a pointer to a static buffer // 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*/ char caBuffer[9]; /* add in room for the parity 2 bits*/
int p, i; int p, i;
memcpy(caBuffer, strData.c_str(), 8); memcpy (caBuffer, strData.c_str (), 8);
// compute parity: merely add groups of two bits. // compute parity: merely add groups of two bits.
for(p = 0, i = 0; i < 64; i += 2) for (p = 0, i = 0; i < 64; i += 2)
p += extract(caBuffer, i, 2); p += extract (caBuffer, i, 2);
caBuffer[8] = char(p) << 6; caBuffer[8] = char (p) << 6;
strHuman = std::string() strHuman = std::string ()
+ s_dictionary[extract(caBuffer, 0, 11)] + " " + s_dictionary[extract (caBuffer, 0, 11)] + " "
+ s_dictionary[extract(caBuffer, 11, 11)] + " " + s_dictionary[extract (caBuffer, 11, 11)] + " "
+ s_dictionary[extract(caBuffer, 22, 11)] + " " + s_dictionary[extract (caBuffer, 22, 11)] + " "
+ s_dictionary[extract(caBuffer, 33, 11)] + " " + s_dictionary[extract (caBuffer, 33, 11)] + " "
+ s_dictionary[extract(caBuffer, 44, 11)] + " " + s_dictionary[extract (caBuffer, 44, 11)] + " "
+ s_dictionary[extract(caBuffer, 55, 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 cl;
unsigned char cc; unsigned char cc;
unsigned char cr; unsigned char cr;
unsigned long y; unsigned long y;
int shift; int shift;
assert(length <= 11); assert (length <= 11);
assert(start >= 0); assert (start >= 0);
assert(length >= 0); assert (length >= 0);
assert(start+length <= 66); assert (start + length <= 66);
shift = ((8 -(( start + length) % 8))%8); shift = ((8 - (( start + length) % 8)) % 8);
y = (long) x << shift; y = (long) x << shift;
cl = (y >> 16) & 0xff; cl = (y >> 16) & 0xff;
cc = (y >> 8) & 0xff; cc = (y >> 8) & 0xff;
cr = y & 0xff; cr = y & 0xff;
if(shift + length > 16){
s[start /8] |= cl; if (shift + length > 16)
s[start/8 +1] |= cc; {
s[start/8 +2] |= cr; s[start / 8] |= cl;
} else if(shift +length > 8){ s[start / 8 + 1] |= cc;
s[start/8] |= cc; s[start / 8 + 2] |= cr;
s[start/8 + 1] |= cr; }
} else { else if (shift + length > 8)
s[start/8] |= cr; {
} 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) BOOST_FOREACH (char cLetter, strWord)
{ {
if(!isascii(cLetter)) if (!isascii (cLetter))
{ {
; // nothing ; // nothing
} }
else if(islower(cLetter)) else if (islower (cLetter))
{ {
cLetter = toupper(cLetter); cLetter = toupper (cLetter);
} }
else if(cLetter == '1') else if (cLetter == '1')
{ {
cLetter = 'L'; cLetter = 'L';
} }
else if(cLetter == '0') else if (cLetter == '0')
{ {
cLetter = 'O'; cLetter = 'O';
} }
else if(cLetter == '5') else if (cLetter == '5')
{ {
cLetter = 'S'; cLetter = 'S';
} }
} }
} }
// Binary search of dictionary. // Binary search of dictionary.
int RFC1751::wsrch (const std::string& strWord, int iMin, int iMax) int RFC1751::wsrch (const std::string& strWord, int iMin, int iMax)
{ {
int iResult = -1; int iResult = -1;
while (iResult < 0 && iMin != iMax) while (iResult < 0 && iMin != iMax)
{ {
// Have a range to search. // Have a range to search.
int iMid = iMin+(iMax-iMin)/2; int iMid = iMin + (iMax - iMin) / 2;
int iDir = strWord.compare(s_dictionary[iMid]); int iDir = strWord.compare (s_dictionary[iMid]);
if (!iDir) if (!iDir)
{ {
iResult = iMid; // Found it. iResult = iMid; // Found it.
} }
else if (iDir < 0) else if (iDir < 0)
{ {
iMax = iMid; // key < middle, middle is new max. iMax = iMid; // key < middle, middle is new max.
} }
else else
{ {
iMin = iMid+1; // key > middle, new min is past the middle. iMin = iMid + 1; // key > middle, new min is past the middle.
} }
} }
return iResult; return iResult;
} }
// Convert 6 words to binary. // 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 // -2 words OK but parity is wrong
int RFC1751::etob (std::string& strData, std::vector<std::string> vsHuman) int RFC1751::etob (std::string& strData, std::vector<std::string> vsHuman)
{ {
int i, p, v,l; int i, p, v, l;
char b[9]; char b[9];
if (6 != vsHuman.size()) if (6 != vsHuman.size ())
return -1; return -1;
memset(b, 0, sizeof(b)); memset (b, 0, sizeof (b));
p=0; p = 0;
BOOST_FOREACH(std::string& strWord, vsHuman) BOOST_FOREACH (std::string & strWord, vsHuman)
{ {
l = strWord.length(); l = strWord.length ();
if(l > 4 || l < 1)
return -1;
standard (strWord); if (l > 4 || l < 1)
return -1;
v = wsrch(strWord, standard (strWord);
l < 4 ? 0 : 571,
l < 4 ? 570 : 2048);
if(v < 0 ) v = wsrch (strWord,
return 0; l < 4 ? 0 : 571,
l < 4 ? 570 : 2048);
insert(b, v, p, 11); if (v < 0 )
p +=11; return 0;
}
/* now check the parity of what we got */ insert (b, v, p, 11);
for(p = 0, i = 0; i < 64; i +=2) p += 11;
p += extract(b, i, 2); }
if( (p & 3) != extract(b, 64,2) ) /* now check the parity of what we got */
return -2; 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 @return
1 if succeeded 1 if succeeded
0 if word not in dictionary 0 if word not in dictionary
-1 if badly formed string -1 if badly formed string
-2 if words are okay but parity is wrong. -2 if words are okay but parity is wrong.
*/ */
int RFC1751::getKeyFromEnglish (std::string& strKey, const std::string& strHuman) int RFC1751::getKeyFromEnglish (std::string& strKey, const std::string& strHuman)
{ {
std::vector<std::string> vWords; std::vector<std::string> vWords;
std::string strFirst, strSecond; std::string strFirst, strSecond;
int rc=0; 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::split (vWords, strTrimmed,
boost::algorithm::is_space(), boost::algorithm::token_compress_on); boost::algorithm::is_space (), boost::algorithm::token_compress_on);
rc = 12 == vWords.size() ? 1 : -1; 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));
if (1 == rc) 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 /** Convert to human from a 128 bit key in big-endian format
*/ */
void RFC1751::getEnglishFromKey (std::string& strHuman, const std::string& strKey) 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 (strFirst, strKey.substr (0, 8));
btoe(strSecond, strKey.substr(8, 8)); btoe (strSecond, strKey.substr (8, 8));
strHuman = strFirst + " " + strSecond; strHuman = strFirst + " " + strSecond;
} }
// vim:ts=4 // vim:ts=4

View File

@@ -4,19 +4,19 @@
class RFC1751 class RFC1751
{ {
public: 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: private:
static unsigned long extract (char *s, int start, int length); static unsigned long extract (char* s, int start, int length);
static void btoe (std::string& strHuman, const std::string& strData); static void btoe (std::string& strHuman, const std::string& strData);
static void insert (char *s, int x, int start, int length); static void insert (char* s, int x, int start, int length);
static void standard (std::string& strWord); static void standard (std::string& strWord);
static int wsrch (const std::string& strWord, int iMin, int iMax); static int wsrch (const std::string& strWord, int iMin, int iMax);
static int etob (std::string& strData, std::vector<std::string> vsHuman); static int etob (std::string& strData, std::vector<std::string> vsHuman);
static char const* s_dictionary []; static char const* s_dictionary [];
}; };
#endif #endif

View File

@@ -5,12 +5,12 @@ std::map<int, SField::ptr> SField::codeToField;
boost::mutex SField::mapMutex; boost::mutex SField::mapMutex;
int SField::num = 0; int SField::num = 0;
SField sfInvalid(-1), sfGeneric(0); SField sfInvalid (-1), sfGeneric (0);
SField sfLedgerEntry(STI_LEDGERENTRY, 1, "LedgerEntry"); SField sfLedgerEntry (STI_LEDGERENTRY, 1, "LedgerEntry");
SField sfTransaction(STI_TRANSACTION, 1, "Transaction"); SField sfTransaction (STI_TRANSACTION, 1, "Transaction");
SField sfValidation(STI_VALIDATION, 1, "Validation"); SField sfValidation (STI_VALIDATION, 1, "Validation");
SField sfHash(STI_HASH256, 257, "hash"); SField sfHash (STI_HASH256, 257, "hash");
SField sfIndex(STI_HASH256, 258, "index"); SField sfIndex (STI_HASH256, 258, "index");
#define FIELD(name, type, index) SField sf##name(FIELD_CODE(STI_##type, index), STI_##type, index, #name); #define FIELD(name, type, index) SField sf##name(FIELD_CODE(STI_##type, index), STI_##type, index, #name);
#define TYPE(name, type, index) #define TYPE(name, type, index)
@@ -18,50 +18,53 @@ SField sfIndex(STI_HASH256, 258, "index");
#undef FIELD #undef FIELD
#undef TYPE #undef TYPE
static int initFields() static int initFields ()
{ {
sfTxnSignature.notSigningField(); sfTxnSignature.notSigningField ();
sfTxnSignatures.notSigningField(); sfTxnSignatures.notSigningField ();
sfSignature.notSigningField(); sfSignature.notSigningField ();
sfIndexes.setMeta(SField::sMD_Never); sfIndexes.setMeta (SField::sMD_Never);
sfPreviousTxnID.setMeta(SField::sMD_DeleteFinal); sfPreviousTxnID.setMeta (SField::sMD_DeleteFinal);
sfPreviousTxnLgrSeq.setMeta(SField::sMD_DeleteFinal); sfPreviousTxnLgrSeq.setMeta (SField::sMD_DeleteFinal);
sfLedgerEntryType.setMeta(SField::sMD_Never); sfLedgerEntryType.setMeta (SField::sMD_Never);
sfRootIndex.setMeta(SField::sMD_Always); 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), SField::SField (SerializedTypeID tid, int fv) : fieldCode (FIELD_CODE (tid, fv)), fieldType (tid), fieldValue (fv),
fieldMeta(sMD_Default), fieldNum(++num), signingField(true) fieldMeta (sMD_Default), fieldNum (++num), signingField (true)
{ // call with the map mutex {
fieldName = lexical_cast_i(tid) + "/" + lexical_cast_i(fv); // call with the map mutex
codeToField[fieldCode] = this; fieldName = lexical_cast_i (tid) + "/" + lexical_cast_i (fv);
assert((fv != 1) || ((tid != STI_ARRAY) && (tid!=STI_OBJECT))); 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 type = code >> 16;
int field = code % 0xffff; int field = code % 0xffff;
if ((type <= 0) || (field <= 0)) if ((type <= 0) || (field <= 0))
return sfInvalid; return sfInvalid;
boost::mutex::scoped_lock sl(mapMutex); boost::mutex::scoped_lock sl (mapMutex);
std::map<int, SField::ptr>::iterator it = codeToField.find(code); std::map<int, SField::ptr>::iterator it = codeToField.find (code);
if (it != codeToField.end())
return *(it->second);
if (field > 255) // don't dynamically extend types that have no binary encoding if (it != codeToField.end ())
return sfInvalid; return * (it->second);
switch (type) if (field > 255) // don't dynamically extend types that have no binary encoding
{ // types we are willing to dynamically extend return sfInvalid;
switch (type)
{
// types we are willing to dynamically extend
#define FIELD(name, type, index) #define FIELD(name, type, index)
#define TYPE(name, type, index) case STI_##type: #define TYPE(name, type, index) case STI_##type:
@@ -69,56 +72,62 @@ SField::ref SField::getField(int code)
#undef FIELD #undef FIELD
#undef TYPE #undef TYPE
break; break;
default:
return sfInvalid;
}
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) 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
{ {
if (!fieldName.empty()) // -1 = f1 comes before f2, 0 = illegal combination, 1 = f1 comes after f2
return fieldName; if ((f1.fieldCode <= 0) || (f2.fieldCode <= 0))
if (fieldValue == 0) return 0;
return "";
return boost::lexical_cast<std::string>(static_cast<int>(fieldType)) + "/" + if (f1.fieldCode < f2.fieldCode)
boost::lexical_cast<std::string>(fieldValue); return -1;
if (f2.fieldCode < f1.fieldCode)
return 1;
return 0;
} }
SField::ref SField::getField(const std::string& fieldName) std::string SField::getName () const
{ // 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); if (!fieldName.empty ())
std::map<int, ptr>::iterator it = codeToField.find(fieldCode); return fieldName;
if ((it != codeToField.end()) && (it->second == this))
codeToField.erase(it); 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 // vim:ts=4

View File

@@ -6,10 +6,10 @@
enum SerializedTypeID enum SerializedTypeID
{ {
// special types // special types
STI_UNKNOWN = -2, STI_UNKNOWN = -2,
STI_DONE = -1, STI_DONE = -1,
STI_NOTPRESENT = 0, STI_NOTPRESENT = 0,
#define TYPE(name, field, value) STI_##field = value, #define TYPE(name, field, value) STI_##field = value,
#define FIELD(name, field, value) #define FIELD(name, field, value)
@@ -17,10 +17,10 @@ enum SerializedTypeID
#undef TYPE #undef TYPE
#undef FIELD #undef FIELD
// high level types // high level types
STI_TRANSACTION = 10001, STI_TRANSACTION = 10001,
STI_LEDGERENTRY = 10002, STI_LEDGERENTRY = 10002,
STI_VALIDATION = 10003, STI_VALIDATION = 10003,
}; };
/** Identifies fields. /** Identifies fields.
@@ -32,112 +32,168 @@ enum SerializedTypeID
class SField class SField
{ {
public: public:
typedef const SField& ref; typedef const SField& ref;
typedef SField const * ptr; typedef SField const* ptr;
static const int sMD_Never = 0x00; static const int sMD_Never = 0x00;
static const int sMD_ChangeOrig = 0x01; // original value when it changes 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_ChangeNew = 0x02; // new value when it changes
static const int sMD_DeleteFinal = 0x04; // final value when it is deleted 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_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_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_Default = sMD_ChangeOrig | sMD_ChangeNew | sMD_DeleteFinal | sMD_Create;
public: public:
const int fieldCode; // (type<<16)|index const int fieldCode; // (type<<16)|index
const SerializedTypeID fieldType; // STI_* const SerializedTypeID fieldType; // STI_*
const int fieldValue; // Code number for protocol const int fieldValue; // Code number for protocol
std::string fieldName; std::string fieldName;
int fieldMeta; int fieldMeta;
int fieldNum; int fieldNum;
bool signingField; bool signingField;
SField (int fc, SerializedTypeID tid, int fv, const char* fn) SField (int fc, SerializedTypeID tid, int fv, const char* fn)
: fieldCode (fc) : fieldCode (fc)
, fieldType (tid) , fieldType (tid)
, fieldValue (fv) , fieldValue (fv)
, fieldName (fn) , fieldName (fn)
, fieldMeta (sMD_Default) , fieldMeta (sMD_Default)
, signingField (true) , signingField (true)
{ {
boost::mutex::scoped_lock sl(mapMutex); boost::mutex::scoped_lock sl (mapMutex);
codeToField[fieldCode] = this; codeToField[fieldCode] = this;
fieldNum = ++num; fieldNum = ++num;
} }
SField (SerializedTypeID tid, int fv, const char *fn) SField (SerializedTypeID tid, int fv, const char* fn)
: fieldCode (FIELD_CODE (tid, fv)) : fieldCode (FIELD_CODE (tid, fv))
, fieldType (tid) , fieldType (tid)
, fieldValue (fv) , fieldValue (fv)
, fieldName (fn) , fieldName (fn)
, fieldMeta (sMD_Default) , fieldMeta (sMD_Default)
, signingField (true) , signingField (true)
{ {
boost::mutex::scoped_lock sl(mapMutex); boost::mutex::scoped_lock sl (mapMutex);
codeToField[fieldCode] = this; codeToField[fieldCode] = this;
fieldNum = ++num; fieldNum = ++num;
} }
explicit SField (int fc) explicit SField (int fc)
: fieldCode (fc) : fieldCode (fc)
, fieldType (STI_UNKNOWN) , fieldType (STI_UNKNOWN)
, fieldValue (0) , fieldValue (0)
, fieldMeta (sMD_Never) , fieldMeta (sMD_Never)
, signingField (true) , signingField (true)
{ {
boost::mutex::scoped_lock sl(mapMutex); boost::mutex::scoped_lock sl (mapMutex);
fieldNum = ++num; fieldNum = ++num;
} }
~SField (); ~SField ();
static SField::ref getField (int fieldCode); static SField::ref getField (int fieldCode);
static SField::ref getField (const std::string& fieldName); 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 (int type, int value)
static SField::ref getField (SerializedTypeID type, int value) { return getField(FIELD_CODE(type, 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; std::string getName () const;
bool hasName() const { return !fieldName.empty(); } bool hasName () const
{
return !fieldName.empty ();
}
bool isGeneric() const { return fieldCode == 0; } bool isGeneric () const
bool isInvalid() const { return fieldCode == -1; } {
bool isUseful() const { return fieldCode > 0; } return fieldCode == 0;
bool isKnown() const { return fieldType != STI_UNKNOWN; } }
bool isBinary() const { return fieldValue < 256; } 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? // 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 getCode () const
int getNum() const { return fieldNum; } {
static int getNumFields() { return num; } return fieldCode;
}
int getNum () const
{
return fieldNum;
}
static int getNumFields ()
{
return num;
}
bool isSigningField() const { return signingField; } bool isSigningField () const
void notSigningField() { signingField = false; } {
bool shouldMeta(int c) const { return (fieldMeta & c) != 0; } return signingField;
void setMeta(int c) { fieldMeta = c; } }
void notSigningField ()
{
signingField = false;
}
bool shouldMeta (int c) const
{
return (fieldMeta & c) != 0;
}
void setMeta (int c)
{
fieldMeta = c;
}
bool shouldInclude(bool withSigningField) const bool shouldInclude (bool withSigningField) const
{ return (fieldValue < 256) && (withSigningField || signingField); } {
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 // VFALCO TODO make these private
protected: protected:
static std::map<int, ptr> codeToField; static std::map<int, ptr> codeToField;
static boost::mutex mapMutex; static boost::mutex mapMutex;
static int num; static int num;
SField (SerializedTypeID id, int val); SField (SerializedTypeID id, int val);
}; };
extern SField sfInvalid, sfGeneric, sfLedgerEntry, sfTransaction, sfValidation; 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; std::map <std::string, LedgerEntryFormat*> LedgerEntryFormat::byName;
#define LEF_BASE \ #define LEF_BASE \
<< SOElement(sfLedgerIndex, SOE_OPTIONAL) \ << SOElement(sfLedgerIndex, SOE_OPTIONAL) \
<< SOElement(sfLedgerEntryType, SOE_REQUIRED) \ << SOElement(sfLedgerEntryType, SOE_REQUIRED) \
<< SOElement(sfFlags, SOE_REQUIRED) << SOElement(sfFlags, SOE_REQUIRED)
#define DECLARE_LEF(name, type) lef = new LedgerEntryFormat(#name, type); (*lef) LEF_BASE #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) DECLARE_LEF (AccountRoot, ltACCOUNT_ROOT)
<< SOElement(sfAccount, SOE_REQUIRED) << SOElement (sfAccount, SOE_REQUIRED)
<< SOElement(sfSequence, SOE_REQUIRED) << SOElement (sfSequence, SOE_REQUIRED)
<< SOElement(sfBalance, SOE_REQUIRED) << SOElement (sfBalance, SOE_REQUIRED)
<< SOElement(sfOwnerCount, SOE_REQUIRED) << SOElement (sfOwnerCount, SOE_REQUIRED)
<< SOElement(sfPreviousTxnID, SOE_REQUIRED) << SOElement (sfPreviousTxnID, SOE_REQUIRED)
<< SOElement(sfPreviousTxnLgrSeq, SOE_REQUIRED) << SOElement (sfPreviousTxnLgrSeq, SOE_REQUIRED)
<< SOElement(sfRegularKey, SOE_OPTIONAL) << SOElement (sfRegularKey, SOE_OPTIONAL)
<< SOElement(sfEmailHash, SOE_OPTIONAL) << SOElement (sfEmailHash, SOE_OPTIONAL)
<< SOElement(sfWalletLocator, SOE_OPTIONAL) << SOElement (sfWalletLocator, SOE_OPTIONAL)
<< SOElement(sfWalletSize, SOE_OPTIONAL) << SOElement (sfWalletSize, SOE_OPTIONAL)
<< SOElement(sfMessageKey, SOE_OPTIONAL) << SOElement (sfMessageKey, SOE_OPTIONAL)
<< SOElement(sfTransferRate, SOE_OPTIONAL) << SOElement (sfTransferRate, SOE_OPTIONAL)
<< SOElement(sfDomain, SOE_OPTIONAL) << SOElement (sfDomain, SOE_OPTIONAL)
; ;
DECLARE_LEF(Contract, ltCONTRACT) DECLARE_LEF (Contract, ltCONTRACT)
<< SOElement(sfAccount, SOE_REQUIRED) << SOElement (sfAccount, SOE_REQUIRED)
<< SOElement(sfBalance, SOE_REQUIRED) << SOElement (sfBalance, SOE_REQUIRED)
<< SOElement(sfPreviousTxnID, SOE_REQUIRED) << SOElement (sfPreviousTxnID, SOE_REQUIRED)
<< SOElement(sfPreviousTxnLgrSeq, SOE_REQUIRED) << SOElement (sfPreviousTxnLgrSeq, SOE_REQUIRED)
<< SOElement(sfIssuer, SOE_REQUIRED) << SOElement (sfIssuer, SOE_REQUIRED)
<< SOElement(sfOwner, SOE_REQUIRED) << SOElement (sfOwner, SOE_REQUIRED)
<< SOElement(sfExpiration, SOE_REQUIRED) << SOElement (sfExpiration, SOE_REQUIRED)
<< SOElement(sfBondAmount, SOE_REQUIRED) << SOElement (sfBondAmount, SOE_REQUIRED)
<< SOElement(sfCreateCode, SOE_OPTIONAL) << SOElement (sfCreateCode, SOE_OPTIONAL)
<< SOElement(sfFundCode, SOE_OPTIONAL) << SOElement (sfFundCode, SOE_OPTIONAL)
<< SOElement(sfRemoveCode, SOE_OPTIONAL) << SOElement (sfRemoveCode, SOE_OPTIONAL)
<< SOElement(sfExpireCode, SOE_OPTIONAL) << SOElement (sfExpireCode, SOE_OPTIONAL)
; ;
DECLARE_LEF(DirectoryNode, ltDIR_NODE) DECLARE_LEF (DirectoryNode, ltDIR_NODE)
<< SOElement(sfOwner, SOE_OPTIONAL) // for owner directories << SOElement (sfOwner, SOE_OPTIONAL) // for owner directories
<< SOElement(sfTakerPaysCurrency, SOE_OPTIONAL) // for order book directories << SOElement (sfTakerPaysCurrency, SOE_OPTIONAL) // for order book directories
<< SOElement(sfTakerPaysIssuer, SOE_OPTIONAL) // for order book directories << SOElement (sfTakerPaysIssuer, SOE_OPTIONAL) // for order book directories
<< SOElement(sfTakerGetsCurrency, SOE_OPTIONAL) // for order book directories << SOElement (sfTakerGetsCurrency, SOE_OPTIONAL) // for order book directories
<< SOElement(sfTakerGetsIssuer, SOE_OPTIONAL) // for order book directories << SOElement (sfTakerGetsIssuer, SOE_OPTIONAL) // for order book directories
<< SOElement(sfExchangeRate, SOE_OPTIONAL) // for order book directories << SOElement (sfExchangeRate, SOE_OPTIONAL) // for order book directories
<< SOElement(sfIndexes, SOE_REQUIRED) << SOElement (sfIndexes, SOE_REQUIRED)
<< SOElement(sfRootIndex, SOE_REQUIRED) << SOElement (sfRootIndex, SOE_REQUIRED)
<< SOElement(sfIndexNext, SOE_OPTIONAL) << SOElement (sfIndexNext, SOE_OPTIONAL)
<< SOElement(sfIndexPrevious, SOE_OPTIONAL) << SOElement (sfIndexPrevious, SOE_OPTIONAL)
; ;
DECLARE_LEF(GeneratorMap, ltGENERATOR_MAP) DECLARE_LEF (GeneratorMap, ltGENERATOR_MAP)
<< SOElement(sfGenerator, SOE_REQUIRED) << SOElement (sfGenerator, SOE_REQUIRED)
; ;
DECLARE_LEF(Nickname, ltNICKNAME) DECLARE_LEF (Nickname, ltNICKNAME)
<< SOElement(sfAccount, SOE_REQUIRED) << SOElement (sfAccount, SOE_REQUIRED)
<< SOElement(sfMinimumOffer, SOE_OPTIONAL) << SOElement (sfMinimumOffer, SOE_OPTIONAL)
; ;
DECLARE_LEF(Offer, ltOFFER) DECLARE_LEF (Offer, ltOFFER)
<< SOElement(sfAccount, SOE_REQUIRED) << SOElement (sfAccount, SOE_REQUIRED)
<< SOElement(sfSequence, SOE_REQUIRED) << SOElement (sfSequence, SOE_REQUIRED)
<< SOElement(sfTakerPays, SOE_REQUIRED) << SOElement (sfTakerPays, SOE_REQUIRED)
<< SOElement(sfTakerGets, SOE_REQUIRED) << SOElement (sfTakerGets, SOE_REQUIRED)
<< SOElement(sfBookDirectory, SOE_REQUIRED) << SOElement (sfBookDirectory, SOE_REQUIRED)
<< SOElement(sfBookNode, SOE_REQUIRED) << SOElement (sfBookNode, SOE_REQUIRED)
<< SOElement(sfOwnerNode, SOE_REQUIRED) << SOElement (sfOwnerNode, SOE_REQUIRED)
<< SOElement(sfPreviousTxnID, SOE_REQUIRED) << SOElement (sfPreviousTxnID, SOE_REQUIRED)
<< SOElement(sfPreviousTxnLgrSeq, SOE_REQUIRED) << SOElement (sfPreviousTxnLgrSeq, SOE_REQUIRED)
<< SOElement(sfExpiration, SOE_OPTIONAL) << SOElement (sfExpiration, SOE_OPTIONAL)
; ;
DECLARE_LEF(RippleState, ltRIPPLE_STATE) DECLARE_LEF (RippleState, ltRIPPLE_STATE)
<< SOElement(sfBalance, SOE_REQUIRED) << SOElement (sfBalance, SOE_REQUIRED)
<< SOElement(sfLowLimit, SOE_REQUIRED) << SOElement (sfLowLimit, SOE_REQUIRED)
<< SOElement(sfHighLimit, SOE_REQUIRED) << SOElement (sfHighLimit, SOE_REQUIRED)
<< SOElement(sfPreviousTxnID, SOE_REQUIRED) << SOElement (sfPreviousTxnID, SOE_REQUIRED)
<< SOElement(sfPreviousTxnLgrSeq, SOE_REQUIRED) << SOElement (sfPreviousTxnLgrSeq, SOE_REQUIRED)
<< SOElement(sfLowNode, SOE_OPTIONAL) << SOElement (sfLowNode, SOE_OPTIONAL)
<< SOElement(sfLowQualityIn, SOE_OPTIONAL) << SOElement (sfLowQualityIn, SOE_OPTIONAL)
<< SOElement(sfLowQualityOut, SOE_OPTIONAL) << SOElement (sfLowQualityOut, SOE_OPTIONAL)
<< SOElement(sfHighNode, SOE_OPTIONAL) << SOElement (sfHighNode, SOE_OPTIONAL)
<< SOElement(sfHighQualityIn, SOE_OPTIONAL) << SOElement (sfHighQualityIn, SOE_OPTIONAL)
<< SOElement(sfHighQualityOut, SOE_OPTIONAL) << SOElement (sfHighQualityOut, SOE_OPTIONAL)
; ;
DECLARE_LEF(LedgerHashes, ltLEDGER_HASHES) DECLARE_LEF (LedgerHashes, ltLEDGER_HASHES)
<< SOElement(sfFirstLedgerSequence, SOE_OPTIONAL) // Remove if we do a ledger restart << SOElement (sfFirstLedgerSequence, SOE_OPTIONAL) // Remove if we do a ledger restart
<< SOElement(sfLastLedgerSequence, SOE_OPTIONAL) << SOElement (sfLastLedgerSequence, SOE_OPTIONAL)
<< SOElement(sfHashes, SOE_REQUIRED) << SOElement (sfHashes, SOE_REQUIRED)
; ;
DECLARE_LEF(EnabledFeatures, ltFEATURES) DECLARE_LEF (EnabledFeatures, ltFEATURES)
<< SOElement(sfFeatures, SOE_REQUIRED) << SOElement (sfFeatures, SOE_REQUIRED)
; ;
DECLARE_LEF(FeeSettings, ltFEE_SETTINGS) DECLARE_LEF (FeeSettings, ltFEE_SETTINGS)
<< SOElement(sfBaseFee, SOE_REQUIRED) << SOElement (sfBaseFee, SOE_REQUIRED)
<< SOElement(sfReferenceFeeUnits, SOE_REQUIRED) << SOElement (sfReferenceFeeUnits, SOE_REQUIRED)
<< SOElement(sfReserveBase, SOE_REQUIRED) << SOElement (sfReserveBase, SOE_REQUIRED)
<< SOElement(sfReserveIncrement, 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)); std::map<int, LedgerEntryFormat*>::iterator it = byType.find (static_cast<int> (t));
if (it == byType.end())
return NULL; if (it == byType.end ())
return it->second; return NULL;
return it->second;
} }
LedgerEntryFormat* LedgerEntryFormat::getLgrFormat(int t) LedgerEntryFormat* LedgerEntryFormat::getLgrFormat (int t)
{ {
std::map<int, LedgerEntryFormat*>::iterator it = byType.find((t)); std::map<int, LedgerEntryFormat*>::iterator it = byType.find ((t));
if (it == byType.end())
return NULL; if (it == byType.end ())
return it->second; 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)); std::map<std::string, LedgerEntryFormat*>::iterator it = byName.find ((t));
if (it == byName.end())
return NULL; if (it == byName.end ())
return it->second; return NULL;
return it->second;
} }
// vim:ts=4 // vim:ts=4

View File

@@ -4,79 +4,79 @@
// Used as the type of a transaction or the type of a ledger entry. // Used as the type of a transaction or the type of a ledger entry.
enum LedgerEntryType enum LedgerEntryType
{ {
ltINVALID = -1, ltINVALID = -1,
ltACCOUNT_ROOT = 'a', ltACCOUNT_ROOT = 'a',
ltDIR_NODE = 'd', ltDIR_NODE = 'd',
ltGENERATOR_MAP = 'g', ltGENERATOR_MAP = 'g',
ltRIPPLE_STATE = 'r', ltRIPPLE_STATE = 'r',
ltNICKNAME = 'n', ltNICKNAME = 'n',
ltOFFER = 'o', ltOFFER = 'o',
ltCONTRACT = 'c', ltCONTRACT = 'c',
ltLEDGER_HASHES = 'h', ltLEDGER_HASHES = 'h',
ltFEATURES = 'f', ltFEATURES = 'f',
ltFEE_SETTINGS = 's', ltFEE_SETTINGS = 's',
}; };
// Used as a prefix for computing ledger indexes (keys). // Used as a prefix for computing ledger indexes (keys).
enum LedgerNameSpace enum LedgerNameSpace
{ {
spaceAccount = 'a', spaceAccount = 'a',
spaceDirNode = 'd', spaceDirNode = 'd',
spaceGenerator = 'g', spaceGenerator = 'g',
spaceNickname = 'n', spaceNickname = 'n',
spaceRipple = 'r', spaceRipple = 'r',
spaceOffer = 'o', // Entry for an offer. spaceOffer = 'o', // Entry for an offer.
spaceOwnerDir = 'O', // Directory of things owned by an account. spaceOwnerDir = 'O', // Directory of things owned by an account.
spaceBookDir = 'B', // Directory of order books. spaceBookDir = 'B', // Directory of order books.
spaceContract = 'c', spaceContract = 'c',
spaceSkipList = 's', spaceSkipList = 's',
spaceFeature = 'f', spaceFeature = 'f',
spaceFee = 'e', spaceFee = 'e',
}; };
enum LedgerSpecificFlags enum LedgerSpecificFlags
{ {
// ltACCOUNT_ROOT // ltACCOUNT_ROOT
lsfPasswordSpent = 0x00010000, // True, if password set fee is spent. lsfPasswordSpent = 0x00010000, // True, if password set fee is spent.
lsfRequireDestTag = 0x00020000, // True, to require a DestinationTag for payments. lsfRequireDestTag = 0x00020000, // True, to require a DestinationTag for payments.
lsfRequireAuth = 0x00040000, // True, to require a authorization to hold IOUs. lsfRequireAuth = 0x00040000, // True, to require a authorization to hold IOUs.
lsfDisallowXRP = 0x00080000, // True, to disallow sending XRP. lsfDisallowXRP = 0x00080000, // True, to disallow sending XRP.
// ltOFFER // ltOFFER
lsfPassive = 0x00010000, lsfPassive = 0x00010000,
lsfSell = 0x00020000, // True, offer was placed as a sell. lsfSell = 0x00020000, // True, offer was placed as a sell.
// ltRIPPLE_STATE // ltRIPPLE_STATE
lsfLowReserve = 0x00010000, // True, if entry counts toward reserve. lsfLowReserve = 0x00010000, // True, if entry counts toward reserve.
lsfHighReserve = 0x00020000, lsfHighReserve = 0x00020000,
lsfLowAuth = 0x00040000, lsfLowAuth = 0x00040000,
lsfHighAuth = 0x00080000, lsfHighAuth = 0x00080000,
}; };
class LedgerEntryFormat class LedgerEntryFormat
{ {
public: public:
std::string t_name; std::string t_name;
LedgerEntryType t_type; LedgerEntryType t_type;
SOTemplate elements; SOTemplate elements;
static std::map<int, LedgerEntryFormat*> byType; static std::map<int, LedgerEntryFormat*> byType;
static std::map<std::string, LedgerEntryFormat*> byName; static std::map<std::string, LedgerEntryFormat*> byName;
LedgerEntryFormat(const char *name, LedgerEntryType type) : t_name(name), t_type(type) LedgerEntryFormat (const char* name, LedgerEntryType type) : t_name (name), t_type (type)
{ {
byName[name] = this; byName[name] = this;
byType[type] = this; byType[type] = this;
} }
LedgerEntryFormat& operator<<(const SOElement& el) LedgerEntryFormat& operator<< (const SOElement& el)
{ {
elements.push_back(el); elements.push_back (el);
return *this; return *this;
} }
static LedgerEntryFormat* getLgrFormat(LedgerEntryType t); static LedgerEntryFormat* getLgrFormat (LedgerEntryType t);
static LedgerEntryFormat* getLgrFormat(const std::string& t); static LedgerEntryFormat* getLgrFormat (const std::string& t);
static LedgerEntryFormat* getLgrFormat(int t); static LedgerEntryFormat* getLgrFormat (int t);
}; };
#endif #endif

View File

@@ -2,7 +2,7 @@
PackedMessage::PackedMessage (::google::protobuf::Message const& message, int type) PackedMessage::PackedMessage (::google::protobuf::Message const& message, int type)
{ {
unsigned const messageBytes = message.ByteSize (); unsigned const messageBytes = message.ByteSize ();
assert (messageBytes != 0); assert (messageBytes != 0);
@@ -11,30 +11,33 @@ PackedMessage::PackedMessage (::google::protobuf::Message const& message, int ty
encodeHeader (messageBytes, type); encodeHeader (messageBytes, type);
if (messageBytes != 0) if (messageBytes != 0)
{ {
message.SerializeToArray (&mBuffer [PackedMessage::kHeaderBytes], messageBytes); message.SerializeToArray (&mBuffer [PackedMessage::kHeaderBytes], messageBytes);
#ifdef DEBUG #ifdef DEBUG
// std::cerr << "PackedMessage: type=" << type << ", datalen=" << msg_size << std::endl; // std::cerr << "PackedMessage: type=" << type << ", datalen=" << msg_size << std::endl;
#endif #endif
} }
} }
bool PackedMessage::operator== (PackedMessage const& other) const 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 PackedMessage::getLength (std::vector <uint8_t> const& buf)
{ {
unsigned result; unsigned result;
if (buf.size() >= PackedMessage::kHeaderBytes) if (buf.size () >= PackedMessage::kHeaderBytes)
{ {
result = buf [0]; result = buf [0];
result <<= 8; result |= buf [1]; result <<= 8;
result <<= 8; result |= buf [2]; result |= buf [1];
result <<= 8; result |= buf [3]; result <<= 8;
result |= buf [2];
result <<= 8;
result |= buf [3];
} }
else else
{ {
@@ -46,21 +49,22 @@ unsigned PackedMessage::getLength (std::vector <uint8_t> const& buf)
int PackedMessage::getType (std::vector<uint8_t> const& buf) int PackedMessage::getType (std::vector<uint8_t> const& buf)
{ {
if(buf.size() < PackedMessage::kHeaderBytes) if (buf.size () < PackedMessage::kHeaderBytes)
return 0; return 0;
int ret = buf[4]; int ret = buf[4];
ret <<= 8; ret |= buf[5]; ret <<= 8;
return ret; ret |= buf[5];
return ret;
} }
void PackedMessage::encodeHeader (unsigned size, int type) void PackedMessage::encodeHeader (unsigned size, int type)
{ {
assert(mBuffer.size() >= PackedMessage::kHeaderBytes); assert (mBuffer.size () >= PackedMessage::kHeaderBytes);
mBuffer[0] = static_cast<boost::uint8_t>((size >> 24) & 0xFF); mBuffer[0] = static_cast<boost::uint8_t> ((size >> 24) & 0xFF);
mBuffer[1] = static_cast<boost::uint8_t>((size >> 16) & 0xFF); mBuffer[1] = static_cast<boost::uint8_t> ((size >> 16) & 0xFF);
mBuffer[2] = static_cast<boost::uint8_t>((size >> 8) & 0xFF); mBuffer[2] = static_cast<boost::uint8_t> ((size >> 8) & 0xFF);
mBuffer[3] = static_cast<boost::uint8_t>(size & 0xFF); mBuffer[3] = static_cast<boost::uint8_t> (size & 0xFF);
mBuffer[4] = static_cast<boost::uint8_t>((type >> 8) & 0xFF); mBuffer[4] = static_cast<boost::uint8_t> ((type >> 8) & 0xFF);
mBuffer[5] = static_cast<boost::uint8_t>(type & 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: public:
typedef boost::shared_ptr< ::google::protobuf::Message > MessagePointer; typedef boost::shared_ptr< ::google::protobuf::Message > MessagePointer;
typedef boost::shared_ptr<PackedMessage> pointer; typedef boost::shared_ptr<PackedMessage> pointer;
public: public:
/** Number of bytes in a message header. /** Number of bytes in a message header.
@@ -26,27 +26,27 @@ public:
/** Retrieve the packed message data. /** Retrieve the packed message data.
*/ */
// VFALCO TODO shouldn't this be const? // VFALCO TODO shouldn't this be const?
std::vector <uint8_t>& getBuffer() std::vector <uint8_t>& getBuffer ()
{ {
return mBuffer; return mBuffer;
} }
/** Determine bytewise equality. /** Determine bytewise equality.
*/ */
bool operator == (PackedMessage const& other) const; bool operator == (PackedMessage const& other) const;
/** Calculate the length of a packed message. /** 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. /** Determine the type of a packed message.
*/ */
static int getType (std::vector <uint8_t> const& buf); static int getType (std::vector <uint8_t> const& buf);
private: private:
// Encodes the size and type into a header at the beginning of buf // Encodes the size and type into a header at the beginning of buf
// //
void encodeHeader (unsigned size, int type); void encodeHeader (unsigned size, int type);
std::vector <uint8_t> mBuffer; 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 class RippleAddress : public CBase58Data
{ {
private: private:
typedef enum { typedef enum
VER_NONE = 1, {
VER_NODE_PUBLIC = 28, VER_NONE = 1,
VER_NODE_PRIVATE = 32, VER_NODE_PUBLIC = 28,
VER_ACCOUNT_ID = 0, VER_NODE_PRIVATE = 32,
VER_ACCOUNT_PUBLIC = 35, VER_ACCOUNT_ID = 0,
VER_ACCOUNT_PRIVATE = 34, VER_ACCOUNT_PUBLIC = 35,
VER_FAMILY_GENERATOR = 41, VER_ACCOUNT_PRIVATE = 34,
VER_FAMILY_SEED = 33, VER_FAMILY_GENERATOR = 41,
} VersionEncoding; VER_FAMILY_SEED = 33,
} VersionEncoding;
bool mIsValid; bool mIsValid;
public: public:
RippleAddress(); RippleAddress ();
// For public and private key, checks if they are legal. // For public and private key, checks if they are legal.
bool isValid() const { return mIsValid; } bool isValid () const
{
return mIsValid;
}
void clear(); void clear ();
bool isSet() const; bool isSet () const;
std::string humanAddressType() const; std::string humanAddressType () const;
// //
// Node Public - Also used for Validators // Node Public - Also used for Validators
// //
uint160 getNodeID() const; uint160 getNodeID () const;
Blob const& getNodePublic() const; Blob const& getNodePublic () const;
std::string humanNodePublic() const; std::string humanNodePublic () const;
bool setNodePublic(const std::string& strPublic); bool setNodePublic (const std::string& strPublic);
void setNodePublic(Blob const& vPublic); void setNodePublic (Blob const& vPublic);
bool verifyNodePublic(uint256 const& hash, Blob const& vchSig) const; bool verifyNodePublic (uint256 const& hash, Blob const& vchSig) const;
bool verifyNodePublic(uint256 const& hash, const std::string& strSig) const; bool verifyNodePublic (uint256 const& hash, const std::string& strSig) const;
static RippleAddress createNodePublic(const RippleAddress& naSeed); static RippleAddress createNodePublic (const RippleAddress& naSeed);
static RippleAddress createNodePublic(Blob const& vPublic); static RippleAddress createNodePublic (Blob const& vPublic);
static RippleAddress createNodePublic(const std::string& strPublic); static RippleAddress createNodePublic (const std::string& strPublic);
// //
// Node Private // Node Private
// //
Blob const& getNodePrivateData() const; Blob const& getNodePrivateData () const;
uint256 getNodePrivate() const; uint256 getNodePrivate () const;
std::string humanNodePrivate() const; std::string humanNodePrivate () const;
bool setNodePrivate(const std::string& strPrivate); bool setNodePrivate (const std::string& strPrivate);
void setNodePrivate(Blob const& vPrivate); void setNodePrivate (Blob const& vPrivate);
void setNodePrivate(uint256 hash256); void setNodePrivate (uint256 hash256);
void signNodePrivate(uint256 const& hash, Blob& vchSig) const; void signNodePrivate (uint256 const& hash, Blob& vchSig) const;
static RippleAddress createNodePrivate(const RippleAddress& naSeed); static RippleAddress createNodePrivate (const RippleAddress& naSeed);
// //
// Accounts IDs // Accounts IDs
// //
uint160 getAccountID() const; uint160 getAccountID () const;
std::string humanAccountID() const; std::string humanAccountID () const;
bool setAccountID(const std::string& strAccountID, const char* pAlphabet=Base58::getCurrentAlphabet ()); bool setAccountID (const std::string& strAccountID, const char* pAlphabet = Base58::getCurrentAlphabet ());
void setAccountID(const uint160& hash160In); void setAccountID (const uint160& hash160In);
static RippleAddress createAccountID(const std::string& strAccountID) static RippleAddress createAccountID (const std::string& strAccountID)
{ RippleAddress na; na.setAccountID(strAccountID); return na; } {
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) static std::string createHumanAccountID (const uint160& uiAccountID)
{ return createAccountID(uiAccountID).humanAccountID(); } {
return createAccountID (uiAccountID).humanAccountID ();
}
static std::string createHumanAccountID(Blob const& vPrivate) static std::string createHumanAccountID (Blob const& vPrivate)
{ return createAccountPrivate(vPrivate).humanAccountID(); } {
return createAccountPrivate (vPrivate).humanAccountID ();
}
// //
// Accounts Public // Accounts Public
// //
Blob const& getAccountPublic() const; Blob const& getAccountPublic () const;
std::string humanAccountPublic() const; std::string humanAccountPublic () const;
bool setAccountPublic(const std::string& strPublic); bool setAccountPublic (const std::string& strPublic);
void setAccountPublic(Blob const& vPublic); void setAccountPublic (Blob const& vPublic);
void setAccountPublic(const RippleAddress& generator, int seq); 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) static RippleAddress createAccountPublic (Blob const& vPublic)
{ {
RippleAddress naNew; RippleAddress naNew;
naNew.setAccountPublic(vPublic); naNew.setAccountPublic (vPublic);
return naNew; return naNew;
} }
static std::string createHumanAccountPublic(Blob const& vPublic) { static std::string createHumanAccountPublic (Blob const& vPublic)
return createAccountPublic(vPublic).humanAccountPublic(); {
} return createAccountPublic (vPublic).humanAccountPublic ();
}
// Create a deterministic public key from a public generator. // Create a deterministic public key from a public generator.
static RippleAddress createAccountPublic(const RippleAddress& naGenerator, int iSeq); static RippleAddress createAccountPublic (const RippleAddress& naGenerator, int iSeq);
// //
// Accounts Private // Accounts Private
// //
uint256 getAccountPrivate() const; uint256 getAccountPrivate () const;
std::string humanAccountPrivate() const; std::string humanAccountPrivate () const;
bool setAccountPrivate(const std::string& strPrivate); bool setAccountPrivate (const std::string& strPrivate);
void setAccountPrivate(Blob const& vPrivate); void setAccountPrivate (Blob const& vPrivate);
void setAccountPrivate(uint256 hash256); void setAccountPrivate (uint256 hash256);
void setAccountPrivate(const RippleAddress& naGenerator, const RippleAddress& naSeed, int seq); void setAccountPrivate (const RippleAddress& naGenerator, const RippleAddress& naSeed, int seq);
bool accountPrivateSign(uint256 const& uHash, Blob& vucSig) const; bool accountPrivateSign (uint256 const& uHash, Blob& vucSig) const;
// bool accountPrivateVerify(uint256 const& uHash, Blob const& vucSig) const; // bool accountPrivateVerify(uint256 const& uHash, Blob const& vucSig) const;
// Encrypt a message. // Encrypt a message.
Blob accountPrivateEncrypt(const RippleAddress& naPublicTo, Blob const& vucPlainText) const; Blob accountPrivateEncrypt (const RippleAddress& naPublicTo, Blob const& vucPlainText) const;
// Decrypt a message. // Decrypt a message.
Blob accountPrivateDecrypt(const RippleAddress& naPublicFrom, Blob const& vucCipherText) const; 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) static RippleAddress createAccountPrivate (Blob const& vPrivate)
{ {
RippleAddress naNew; RippleAddress naNew;
naNew.setAccountPrivate(vPrivate); naNew.setAccountPrivate (vPrivate);
return naNew; return naNew;
} }
static std::string createHumanAccountPrivate(Blob const& vPrivate) { static std::string createHumanAccountPrivate (Blob const& vPrivate)
return createAccountPrivate(vPrivate).humanAccountPrivate(); {
} return createAccountPrivate (vPrivate).humanAccountPrivate ();
}
// //
// Generators // Generators
// Use to generate a master or regular family. // Use to generate a master or regular family.
// //
BIGNUM* getGeneratorBN() const; // DEPRECATED BIGNUM* getGeneratorBN () const; // DEPRECATED
Blob const& getGenerator() const; Blob const& getGenerator () const;
std::string humanGenerator() const; std::string humanGenerator () const;
bool setGenerator(const std::string& strGenerator); bool setGenerator (const std::string& strGenerator);
void setGenerator(Blob const& vPublic); void setGenerator (Blob const& vPublic);
// void setGenerator(const RippleAddress& seed); // void setGenerator(const RippleAddress& seed);
// Create generator for making public deterministic keys. // Create generator for making public deterministic keys.
static RippleAddress createGeneratorPublic(const RippleAddress& naSeed); static RippleAddress createGeneratorPublic (const RippleAddress& naSeed);
// //
// Seeds // Seeds
// Clients must disallow reconizable entries from being seeds. // Clients must disallow reconizable entries from being seeds.
uint128 getSeed() const; uint128 getSeed () const;
std::string humanSeed() const; std::string humanSeed () const;
std::string humanSeed1751() const; std::string humanSeed1751 () const;
bool setSeed(const std::string& strSeed); bool setSeed (const std::string& strSeed);
int setSeed1751(const std::string& strHuman1751); int setSeed1751 (const std::string& strHuman1751);
bool setSeedGeneric(const std::string& strText); bool setSeedGeneric (const std::string& strText);
void setSeed(uint128 hash128); void setSeed (uint128 hash128);
void setSeedRandom(); void setSeedRandom ();
static RippleAddress createSeedRandom(); static RippleAddress createSeedRandom ();
static RippleAddress createSeedGeneric(const std::string& strText); static RippleAddress createSeedGeneric (const std::string& strText);
}; };
#endif #endif

View File

@@ -33,9 +33,9 @@ public:
// the point of call, i.e. "User-agent:" SYSTEM_NAME // the point of call, i.e. "User-agent:" SYSTEM_NAME
// It will be necessary to rewrite some of them to use string streams. // It will be necessary to rewrite some of them to use string streams.
// //
#define SYSTEM_NAME "ripple" #define SYSTEM_NAME "ripple"
#define SYSTEM_CURRENCY_CODE "XRP" #define SYSTEM_CURRENCY_CODE "XRP"
#define SYSTEM_CURRENCY_PRECISION 6 #define SYSTEM_CURRENCY_PRECISION 6
#define SYSTEM_CURRENCY_CODE_RIPPLE "XRR" #define SYSTEM_CURRENCY_CODE_RIPPLE "XRR"
#endif #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. // 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 if (!roundUp) // canonicalize already rounds down
return; return;
WriteLog (lsTRACE, STAmount) << "canonicalize< " << value << ":" << offset << (roundUp ? " up" : " down"); WriteLog (lsTRACE, STAmount) << "canonicalize< " << value << ":" << offset << (roundUp ? " up" : " down");
if (isNative)
{ if (isNative)
if (offset < 0) {
{ if (offset < 0)
int loops = 0; {
while (offset < -1) int loops = 0;
{
value /= 10; while (offset < -1)
++offset; {
++loops; value /= 10;
} ++offset;
value += (loops >= 2) ? 9 : 10; // add before last divide ++loops;
value /= 10; }
++offset;
} value += (loops >= 2) ? 9 : 10; // add before last divide
} value /= 10;
else if (value > STAmount::cMaxValue) ++offset;
{ }
while (value > (10 * STAmount::cMaxValue)) }
{ else if (value > STAmount::cMaxValue)
value /= 10; {
++offset; while (value > (10 * STAmount::cMaxValue))
} {
value += 9; // add before last divide value /= 10;
value /= 10; ++offset;
++offset; }
}
WriteLog (lsTRACE, STAmount) << "canonicalize> " << value << ":" << offset << (roundUp ? " up" : " down"); 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) if (v2.mValue == 0)
return v1; return v1;
if (v1.mValue == 0) if (v1.mValue == 0)
return STAmount(v1.getFName(), v1.mCurrency, v1.mIssuer, v2.mValue, v2.mOffset, v2.mIsNegative); return STAmount (v1.getFName (), v1.mCurrency, v1.mIssuer, v2.mValue, v2.mOffset, v2.mIsNegative);
if (v1.mIsNative) if (v1.mIsNative)
return STAmount(v1.getFName(), v1.getSNValue() + v2.getSNValue()); return STAmount (v1.getFName (), v1.getSNValue () + v2.getSNValue ());
int ov1 = v1.mOffset, ov2 = v2.mOffset; int ov1 = v1.mOffset, ov2 = v2.mOffset;
int64 vv1 = static_cast<int64>(v1.mValue), vv2 = static_cast<uint64>(v2.mValue); int64 vv1 = static_cast<int64> (v1.mValue), vv2 = static_cast<uint64> (v2.mValue);
if (v1.mIsNegative)
vv1 = -vv1;
if (v2.mIsNegative)
vv2 = -vv2;
if (ov1 < ov2) if (v1.mIsNegative)
{ vv1 = -vv1;
while (ov1 < (ov2 - 1))
{
vv1 /= 10;
++ov1;
}
if (roundUp)
vv1 += 9;
vv1 /= 10;
++ov1;
}
if (ov2 < ov1) if (v2.mIsNegative)
{ vv2 = -vv2;
while (ov2 < (ov1 - 1))
{
vv2 /= 10;
++ov2;
}
if (roundUp)
vv2 += 9;
vv2 /= 10;
++ov2;
}
int64 fv = vv1 + vv2; if (ov1 < ov2)
if ((fv >= -10) && (fv <= 10)) {
return STAmount(v1.getFName(), v1.mCurrency, v1.mIssuer); while (ov1 < (ov2 - 1))
else if (fv >= 0) {
{ vv1 /= 10;
uint64 v = static_cast<uint64>(fv); ++ov1;
canonicalizeRound(false, v, ov1, roundUp); }
return STAmount(v1.getFName(), v1.mCurrency, v1.mIssuer, v, ov1, false);
} if (roundUp)
else vv1 += 9;
{
uint64 v = static_cast<uint64>(-fv); vv1 /= 10;
canonicalizeRound(false, v, ov1, !roundUp); ++ov1;
return STAmount(v1.getFName(), v1.mCurrency, v1.mIssuer, v, ov1, true); }
}
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) if (v2.mValue == 0)
return v1; return v1;
if (v1.mValue == 0) if (v1.mValue == 0)
return STAmount(v1.getFName(), v1.mCurrency, v1.mIssuer, v2.mValue, v2.mOffset, !v2.mIsNegative); return STAmount (v1.getFName (), v1.mCurrency, v1.mIssuer, v2.mValue, v2.mOffset, !v2.mIsNegative);
if (v1.mIsNative) if (v1.mIsNative)
return STAmount(v1.getFName(), v1.getSNValue() - v2.getSNValue()); return STAmount (v1.getFName (), v1.getSNValue () - v2.getSNValue ());
int ov1 = v1.mOffset, ov2 = v2.mOffset; int ov1 = v1.mOffset, ov2 = v2.mOffset;
int64 vv1 = static_cast<int64>(v1.mValue), vv2 = static_cast<uint64>(v2.mValue); int64 vv1 = static_cast<int64> (v1.mValue), vv2 = static_cast<uint64> (v2.mValue);
if (v1.mIsNegative) if (v1.mIsNegative)
vv1 = -vv1; vv1 = -vv1;
if (!v2.mIsNegative) if (!v2.mIsNegative)
vv2 = -vv2; vv2 = -vv2;
if (ov1 < ov2) if (ov1 < ov2)
{ {
while (ov1 < (ov2 - 1)) while (ov1 < (ov2 - 1))
{ {
vv1 /= 10; vv1 /= 10;
++ov1; ++ov1;
} }
if (roundUp)
vv1 += 9;
vv1 /= 10;
++ov1;
}
if (ov2 < ov1) if (roundUp)
{ vv1 += 9;
while (ov2 < (ov1 - 1))
{
vv2 /= 10;
++ov2;
}
if (roundUp)
vv2 += 9;
vv2 /= 10;
++ov2;
}
int64 fv = vv1 + vv2; vv1 /= 10;
if ((fv >= -10) && (fv <= 10)) ++ov1;
return STAmount(v1.getFName(), v1.mCurrency, v1.mIssuer); }
else if (fv >= 0)
{ if (ov2 < ov1)
uint64 v = static_cast<uint64>(fv); {
canonicalizeRound(false, v, ov1, roundUp); while (ov2 < (ov1 - 1))
return STAmount(v1.getFName(), v1.mCurrency, v1.mIssuer, v, ov1, false); {
} vv2 /= 10;
else ++ov2;
{ }
uint64 v = static_cast<uint64>(-fv);
canonicalizeRound(false, v, ov1, !roundUp); if (roundUp)
return STAmount(v1.getFName(), v1.mCurrency, v1.mIssuer, v, ov1, true); 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, STAmount STAmount::mulRound (const STAmount& v1, const STAmount& v2,
const uint160& uCurrencyID, const uint160& uIssuerID, bool roundUp) const uint160& uCurrencyID, const uint160& uIssuerID, bool roundUp)
{ {
if (v1.isZero() || v2.isZero()) if (v1.isZero () || v2.isZero ())
return STAmount(uCurrencyID, uIssuerID); return STAmount (uCurrencyID, uIssuerID);
if (v1.mIsNative && v2.mIsNative && uCurrencyID.isZero()) if (v1.mIsNative && v2.mIsNative && uCurrencyID.isZero ())
{ {
uint64 minV = (v1.getSNValue() < v2.getSNValue()) ? v1.getSNValue() : v2.getSNValue(); uint64 minV = (v1.getSNValue () < v2.getSNValue ()) ? v1.getSNValue () : v2.getSNValue ();
uint64 maxV = (v1.getSNValue() < v2.getSNValue()) ? v2.getSNValue() : v1.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);
}
uint64 value1 = v1.mValue, value2 = v2.mValue; if (minV > 3000000000ull) // sqrt(cMaxNative)
int offset1 = v1.mOffset, offset2 = v2.mOffset; throw std::runtime_error ("Native value overflow");
if (v1.mIsNative) if (((maxV >> 32) * minV) > 2095475792ull) // cMaxNative / 2^32
{ throw std::runtime_error ("Native value overflow");
while (value1 < STAmount::cMinValue)
{
value1 *= 10;
--offset1;
}
}
if (v2.mIsNative) return STAmount (v1.getFName (), minV * maxV);
{ }
while (value2 < STAmount::cMinValue)
{
value2 *= 10;
--offset2;
}
}
bool resultNegative = v1.mIsNegative != v2.mIsNegative; uint64 value1 = v1.mValue, value2 = v2.mValue;
// Compute (numerator * denominator) / 10^14 with rounding int offset1 = v1.mOffset, offset2 = v2.mOffset;
// 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");
if (resultNegative != roundUp) // rounding down is automatic when we divide if (v1.mIsNative)
BN_add_word64(&v, tenTo14m1); {
while (value1 < STAmount::cMinValue)
{
value1 *= 10;
--offset1;
}
}
if (BN_div_word64(&v, tenTo14) == ((uint64) -1)) if (v2.mIsNative)
throw std::runtime_error("internal bn error"); {
while (value2 < STAmount::cMinValue)
{
value2 *= 10;
--offset2;
}
}
// 10^16 <= product <= 10^18 bool resultNegative = v1.mIsNegative != v2.mIsNegative;
assert(BN_num_bytes(&v) <= 64); // Compute (numerator * denominator) / 10^14 with rounding
// 10^16 <= result <= 10^18
CBigNum v;
uint64 amount = v.getuint64(); if ((BN_add_word64 (&v, value1) != 1) || (BN_mul_word64 (&v, value2) != 1))
int offset = offset1 + offset2 + 14; throw std::runtime_error ("internal bn error");
canonicalizeRound(uCurrencyID.isZero(), amount, offset, resultNegative != roundUp);
return STAmount(uCurrencyID, uIssuerID, amount, offset, resultNegative); 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, STAmount STAmount::divRound (const STAmount& num, const STAmount& den,
const uint160& uCurrencyID, const uint160& uIssuerID, bool roundUp) const uint160& uCurrencyID, const uint160& uIssuerID, bool roundUp)
{ {
if (den.isZero()) if (den.isZero ())
throw std::runtime_error("division by zero"); throw std::runtime_error ("division by zero");
if (num.isZero())
return STAmount(uCurrencyID, uIssuerID);
uint64 numVal = num.mValue, denVal = den.mValue; if (num.isZero ())
int numOffset = num.mOffset, denOffset = den.mOffset; return STAmount (uCurrencyID, uIssuerID);
if (num.mIsNative) uint64 numVal = num.mValue, denVal = den.mValue;
while (numVal < STAmount::cMinValue) int numOffset = num.mOffset, denOffset = den.mOffset;
{ // Need to bring into range
numVal *= 10;
--numOffset;
}
if (den.mIsNative) if (num.mIsNative)
while (denVal < STAmount::cMinValue) while (numVal < STAmount::cMinValue)
{ {
denVal *= 10; // Need to bring into range
--denOffset; numVal *= 10;
} --numOffset;
}
bool resultNegative = num.mIsNegative != den.mIsNegative; if (den.mIsNative)
// Compute (numerator * 10^17) / denominator while (denVal < STAmount::cMinValue)
CBigNum v; {
if ((BN_add_word64(&v, numVal) != 1) || (BN_mul_word64(&v, tenTo17) != 1)) denVal *= 10;
throw std::runtime_error("internal bn error"); --denOffset;
}
if (resultNegative != roundUp) // Rounding down is automatic when we divide bool resultNegative = num.mIsNegative != den.mIsNegative;
BN_add_word64(&v, denVal - 1); // Compute (numerator * 10^17) / denominator
CBigNum v;
if (BN_div_word64(&v, denVal) == ((uint64) -1)) if ((BN_add_word64 (&v, numVal) != 1) || (BN_mul_word64 (&v, tenTo17) != 1))
throw std::runtime_error("internal bn error"); throw std::runtime_error ("internal bn error");
// 10^16 <= quotient <= 10^18 if (resultNegative != roundUp) // Rounding down is automatic when we divide
assert(BN_num_bytes(&v) <= 64); BN_add_word64 (&v, denVal - 1);
uint64 amount = v.getuint64(); if (BN_div_word64 (&v, denVal) == ((uint64) - 1))
int offset = numOffset - denOffset - 17; throw std::runtime_error ("internal bn error");
canonicalizeRound(uCurrencyID.isZero(), amount, offset, resultNegative != roundUp);
return STAmount(uCurrencyID, uIssuerID, amount, offset, resultNegative); // 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; uint64 value = 25000000000000000ull;
int offset = -14; int offset = -14;
canonicalizeRound(false, value, offset, true); canonicalizeRound (false, value, offset, true);
STAmount one(CURRENCY_ONE, ACCOUNT_ONE, 1); STAmount one (CURRENCY_ONE, ACCOUNT_ONE, 1);
STAmount two(CURRENCY_ONE, ACCOUNT_ONE, 2); STAmount two (CURRENCY_ONE, ACCOUNT_ONE, 2);
STAmount three(CURRENCY_ONE, ACCOUNT_ONE, 3); STAmount three (CURRENCY_ONE, ACCOUNT_ONE, 3);
STAmount oneThird1 = STAmount::divRound(one, three, CURRENCY_ONE, ACCOUNT_ONE, false); STAmount oneThird1 = STAmount::divRound (one, three, CURRENCY_ONE, ACCOUNT_ONE, false);
STAmount oneThird2 = STAmount::divide(one, three, CURRENCY_ONE, ACCOUNT_ONE); STAmount oneThird2 = STAmount::divide (one, three, CURRENCY_ONE, ACCOUNT_ONE);
STAmount oneThird3 = STAmount::divRound(one, three, CURRENCY_ONE, ACCOUNT_ONE, true); STAmount oneThird3 = STAmount::divRound (one, three, CURRENCY_ONE, ACCOUNT_ONE, true);
WriteLog (lsINFO, STAmount) << oneThird1; WriteLog (lsINFO, STAmount) << oneThird1;
WriteLog (lsINFO, STAmount) << oneThird2; WriteLog (lsINFO, STAmount) << oneThird2;
WriteLog (lsINFO, STAmount) << oneThird3; WriteLog (lsINFO, STAmount) << oneThird3;
STAmount twoThird1 = STAmount::divRound(two, three, CURRENCY_ONE, ACCOUNT_ONE, false); STAmount twoThird1 = STAmount::divRound (two, three, CURRENCY_ONE, ACCOUNT_ONE, false);
STAmount twoThird2 = STAmount::divide(two, three, CURRENCY_ONE, ACCOUNT_ONE); STAmount twoThird2 = STAmount::divide (two, three, CURRENCY_ONE, ACCOUNT_ONE);
STAmount twoThird3 = STAmount::divRound(two, three, CURRENCY_ONE, ACCOUNT_ONE, true); STAmount twoThird3 = STAmount::divRound (two, three, CURRENCY_ONE, ACCOUNT_ONE, true);
WriteLog (lsINFO, STAmount) << twoThird1; WriteLog (lsINFO, STAmount) << twoThird1;
WriteLog (lsINFO, STAmount) << twoThird2; WriteLog (lsINFO, STAmount) << twoThird2;
WriteLog (lsINFO, STAmount) << twoThird3; WriteLog (lsINFO, STAmount) << twoThird3;
STAmount oneA = STAmount::mulRound(oneThird1, three, CURRENCY_ONE, ACCOUNT_ONE, false); STAmount oneA = STAmount::mulRound (oneThird1, three, CURRENCY_ONE, ACCOUNT_ONE, false);
STAmount oneB = STAmount::multiply(oneThird2, three, CURRENCY_ONE, ACCOUNT_ONE); STAmount oneB = STAmount::multiply (oneThird2, three, CURRENCY_ONE, ACCOUNT_ONE);
STAmount oneC = STAmount::mulRound(oneThird3, three, CURRENCY_ONE, ACCOUNT_ONE, true); STAmount oneC = STAmount::mulRound (oneThird3, three, CURRENCY_ONE, ACCOUNT_ONE, true);
WriteLog (lsINFO, STAmount) << oneA; WriteLog (lsINFO, STAmount) << oneA;
WriteLog (lsINFO, STAmount) << oneB; WriteLog (lsINFO, STAmount) << oneB;
WriteLog (lsINFO, STAmount) << oneC; WriteLog (lsINFO, STAmount) << oneC;
STAmount fourThirdsA = STAmount::addRound(twoThird2, twoThird2, false); STAmount fourThirdsA = STAmount::addRound (twoThird2, twoThird2, false);
STAmount fourThirdsB = twoThird2 + twoThird2; STAmount fourThirdsB = twoThird2 + twoThird2;
STAmount fourThirdsC = STAmount::addRound(twoThird2, twoThird2, true); STAmount fourThirdsC = STAmount::addRound (twoThird2, twoThird2, true);
WriteLog (lsINFO, STAmount) << fourThirdsA; WriteLog (lsINFO, STAmount) << fourThirdsA;
WriteLog (lsINFO, STAmount) << fourThirdsB; WriteLog (lsINFO, STAmount) << fourThirdsB;
WriteLog (lsINFO, STAmount) << fourThirdsC; WriteLog (lsINFO, STAmount) << fourThirdsC;
STAmount dripTest1 = STAmount::mulRound(twoThird2, two, uint160(), uint160(), false); STAmount dripTest1 = STAmount::mulRound (twoThird2, two, uint160 (), uint160 (), false);
STAmount dripTest2 = STAmount::multiply(twoThird2, two, uint160(), uint160()); STAmount dripTest2 = STAmount::multiply (twoThird2, two, uint160 (), uint160 ());
STAmount dripTest3 = STAmount::mulRound(twoThird2, two, uint160(), uint160(), true); STAmount dripTest3 = STAmount::mulRound (twoThird2, two, uint160 (), uint160 (), true);
WriteLog (lsINFO, STAmount) << dripTest1; WriteLog (lsINFO, STAmount) << dripTest1;
WriteLog (lsINFO, STAmount) << dripTest2; WriteLog (lsINFO, STAmount) << dripTest2;
WriteLog (lsINFO, STAmount) << dripTest3; WriteLog (lsINFO, STAmount) << dripTest3;
} }
BOOST_AUTO_TEST_SUITE_END() BOOST_AUTO_TEST_SUITE_END ()
// vim:ts=4 // vim:ts=4

View File

@@ -10,169 +10,169 @@
This is done to reduce the average size of the messages. This is done to reduce the average size of the messages.
*/ */
// types (common) // types (common)
TYPE(Int16, UINT16, 1) TYPE (Int16, UINT16, 1)
TYPE(Int32, UINT32, 2) TYPE (Int32, UINT32, 2)
TYPE(Int64, UINT64, 3) TYPE (Int64, UINT64, 3)
TYPE(Hash128, HASH128, 4) TYPE (Hash128, HASH128, 4)
TYPE(Hash256, HASH256, 5) TYPE (Hash256, HASH256, 5)
TYPE(Amount, AMOUNT, 6) TYPE (Amount, AMOUNT, 6)
TYPE(VariableLength, VL, 7) TYPE (VariableLength, VL, 7)
TYPE(Account, ACCOUNT, 8) TYPE (Account, ACCOUNT, 8)
// 9-13 are reserved // 9-13 are reserved
TYPE(Object, OBJECT, 14) TYPE (Object, OBJECT, 14)
TYPE(Array, ARRAY, 15) TYPE (Array, ARRAY, 15)
// types (uncommon) // types (uncommon)
TYPE(Int8, UINT8, 16) TYPE (Int8, UINT8, 16)
TYPE(Hash160, HASH160, 17) TYPE (Hash160, HASH160, 17)
TYPE(PathSet, PATHSET, 18) TYPE (PathSet, PATHSET, 18)
TYPE(Vector256, VECTOR256, 19) TYPE (Vector256, VECTOR256, 19)
// 8-bit integers // 8-bit integers
FIELD(CloseResolution, UINT8, 1) FIELD (CloseResolution, UINT8, 1)
FIELD(TemplateEntryType, UINT8, 2) FIELD (TemplateEntryType, UINT8, 2)
FIELD(TransactionResult, UINT8, 3) FIELD (TransactionResult, UINT8, 3)
// 16-bit integers // 16-bit integers
FIELD(LedgerEntryType, UINT16, 1) FIELD (LedgerEntryType, UINT16, 1)
FIELD(TransactionType, UINT16, 2) FIELD (TransactionType, UINT16, 2)
// 32-bit integers (common) // 32-bit integers (common)
FIELD(Flags, UINT32, 2) FIELD (Flags, UINT32, 2)
FIELD(SourceTag, UINT32, 3) FIELD (SourceTag, UINT32, 3)
FIELD(Sequence, UINT32, 4) FIELD (Sequence, UINT32, 4)
FIELD(PreviousTxnLgrSeq, UINT32, 5) FIELD (PreviousTxnLgrSeq, UINT32, 5)
FIELD(LedgerSequence, UINT32, 6) FIELD (LedgerSequence, UINT32, 6)
FIELD(CloseTime, UINT32, 7) FIELD (CloseTime, UINT32, 7)
FIELD(ParentCloseTime, UINT32, 8) FIELD (ParentCloseTime, UINT32, 8)
FIELD(SigningTime, UINT32, 9) FIELD (SigningTime, UINT32, 9)
FIELD(Expiration, UINT32, 10) FIELD (Expiration, UINT32, 10)
FIELD(TransferRate, UINT32, 11) FIELD (TransferRate, UINT32, 11)
FIELD(WalletSize, UINT32, 12) FIELD (WalletSize, UINT32, 12)
FIELD(OwnerCount, UINT32, 13) FIELD (OwnerCount, UINT32, 13)
FIELD(DestinationTag, UINT32, 14) FIELD (DestinationTag, UINT32, 14)
// 32-bit integers (uncommon) // 32-bit integers (uncommon)
FIELD(HighQualityIn, UINT32, 16) FIELD (HighQualityIn, UINT32, 16)
FIELD(HighQualityOut, UINT32, 17) FIELD (HighQualityOut, UINT32, 17)
FIELD(LowQualityIn, UINT32, 18) FIELD (LowQualityIn, UINT32, 18)
FIELD(LowQualityOut, UINT32, 19) FIELD (LowQualityOut, UINT32, 19)
FIELD(QualityIn, UINT32, 20) FIELD (QualityIn, UINT32, 20)
FIELD(QualityOut, UINT32, 21) FIELD (QualityOut, UINT32, 21)
FIELD(StampEscrow, UINT32, 22) FIELD (StampEscrow, UINT32, 22)
FIELD(BondAmount, UINT32, 23) FIELD (BondAmount, UINT32, 23)
FIELD(LoadFee, UINT32, 24) FIELD (LoadFee, UINT32, 24)
FIELD(OfferSequence, UINT32, 25) FIELD (OfferSequence, UINT32, 25)
FIELD(FirstLedgerSequence, UINT32, 26) // Deprecated: do not use FIELD (FirstLedgerSequence, UINT32, 26) // Deprecated: do not use
FIELD(LastLedgerSequence, UINT32, 27) FIELD (LastLedgerSequence, UINT32, 27)
FIELD(TransactionIndex, UINT32, 28) FIELD (TransactionIndex, UINT32, 28)
FIELD(OperationLimit, UINT32, 29) FIELD (OperationLimit, UINT32, 29)
FIELD(ReferenceFeeUnits, UINT32, 30) FIELD (ReferenceFeeUnits, UINT32, 30)
FIELD(ReserveBase, UINT32, 31) FIELD (ReserveBase, UINT32, 31)
FIELD(ReserveIncrement, UINT32, 32) FIELD (ReserveIncrement, UINT32, 32)
// 64-bit integers // 64-bit integers
FIELD(IndexNext, UINT64, 1) FIELD (IndexNext, UINT64, 1)
FIELD(IndexPrevious, UINT64, 2) FIELD (IndexPrevious, UINT64, 2)
FIELD(BookNode, UINT64, 3) FIELD (BookNode, UINT64, 3)
FIELD(OwnerNode, UINT64, 4) FIELD (OwnerNode, UINT64, 4)
FIELD(BaseFee, UINT64, 5) FIELD (BaseFee, UINT64, 5)
FIELD(ExchangeRate, UINT64, 6) FIELD (ExchangeRate, UINT64, 6)
FIELD(LowNode, UINT64, 7) FIELD (LowNode, UINT64, 7)
FIELD(HighNode, UINT64, 8) FIELD (HighNode, UINT64, 8)
// 128-bit // 128-bit
FIELD(EmailHash, HASH128, 1) FIELD (EmailHash, HASH128, 1)
// 256-bit (common) // 256-bit (common)
FIELD(LedgerHash, HASH256, 1) FIELD (LedgerHash, HASH256, 1)
FIELD(ParentHash, HASH256, 2) FIELD (ParentHash, HASH256, 2)
FIELD(TransactionHash, HASH256, 3) FIELD (TransactionHash, HASH256, 3)
FIELD(AccountHash, HASH256, 4) FIELD (AccountHash, HASH256, 4)
FIELD(PreviousTxnID, HASH256, 5) FIELD (PreviousTxnID, HASH256, 5)
FIELD(LedgerIndex, HASH256, 6) FIELD (LedgerIndex, HASH256, 6)
FIELD(WalletLocator, HASH256, 7) FIELD (WalletLocator, HASH256, 7)
FIELD(RootIndex, HASH256, 8) FIELD (RootIndex, HASH256, 8)
// 256-bit (uncommon) // 256-bit (uncommon)
FIELD(BookDirectory, HASH256, 16) FIELD (BookDirectory, HASH256, 16)
FIELD(InvoiceID, HASH256, 17) FIELD (InvoiceID, HASH256, 17)
FIELD(Nickname, HASH256, 18) FIELD (Nickname, HASH256, 18)
FIELD(Feature, HASH256, 19) FIELD (Feature, HASH256, 19)
// 160-bit (common) // 160-bit (common)
FIELD(TakerPaysCurrency, HASH160, 1) FIELD (TakerPaysCurrency, HASH160, 1)
FIELD(TakerPaysIssuer, HASH160, 2) FIELD (TakerPaysIssuer, HASH160, 2)
FIELD(TakerGetsCurrency, HASH160, 3) FIELD (TakerGetsCurrency, HASH160, 3)
FIELD(TakerGetsIssuer, HASH160, 4) FIELD (TakerGetsIssuer, HASH160, 4)
// currency amount (common) // currency amount (common)
FIELD(Amount, AMOUNT, 1) FIELD (Amount, AMOUNT, 1)
FIELD(Balance, AMOUNT, 2) FIELD (Balance, AMOUNT, 2)
FIELD(LimitAmount, AMOUNT, 3) FIELD (LimitAmount, AMOUNT, 3)
FIELD(TakerPays, AMOUNT, 4) FIELD (TakerPays, AMOUNT, 4)
FIELD(TakerGets, AMOUNT, 5) FIELD (TakerGets, AMOUNT, 5)
FIELD(LowLimit, AMOUNT, 6) FIELD (LowLimit, AMOUNT, 6)
FIELD(HighLimit, AMOUNT, 7) FIELD (HighLimit, AMOUNT, 7)
FIELD(Fee, AMOUNT, 8) FIELD (Fee, AMOUNT, 8)
FIELD(SendMax, AMOUNT, 9) FIELD (SendMax, AMOUNT, 9)
// currency amount (uncommon) // currency amount (uncommon)
FIELD(MinimumOffer, AMOUNT, 16) FIELD (MinimumOffer, AMOUNT, 16)
FIELD(RippleEscrow, AMOUNT, 17) FIELD (RippleEscrow, AMOUNT, 17)
// variable length // variable length
FIELD(PublicKey, VL, 1) FIELD (PublicKey, VL, 1)
FIELD(MessageKey, VL, 2) FIELD (MessageKey, VL, 2)
FIELD(SigningPubKey, VL, 3) FIELD (SigningPubKey, VL, 3)
FIELD(TxnSignature, VL, 4) FIELD (TxnSignature, VL, 4)
FIELD(Generator, VL, 5) FIELD (Generator, VL, 5)
FIELD(Signature, VL, 6) FIELD (Signature, VL, 6)
FIELD(Domain, VL, 7) FIELD (Domain, VL, 7)
FIELD(FundCode, VL, 8) FIELD (FundCode, VL, 8)
FIELD(RemoveCode, VL, 9) FIELD (RemoveCode, VL, 9)
FIELD(ExpireCode, VL, 10) FIELD (ExpireCode, VL, 10)
FIELD(CreateCode, VL, 11) FIELD (CreateCode, VL, 11)
// account // account
FIELD(Account, ACCOUNT, 1) FIELD (Account, ACCOUNT, 1)
FIELD(Owner, ACCOUNT, 2) FIELD (Owner, ACCOUNT, 2)
FIELD(Destination, ACCOUNT, 3) FIELD (Destination, ACCOUNT, 3)
FIELD(Issuer, ACCOUNT, 4) FIELD (Issuer, ACCOUNT, 4)
FIELD(Target, ACCOUNT, 7) FIELD (Target, ACCOUNT, 7)
FIELD(RegularKey, ACCOUNT, 8) FIELD (RegularKey, ACCOUNT, 8)
// path set // path set
FIELD(Paths, PATHSET, 1) FIELD (Paths, PATHSET, 1)
// vector of 256-bit // vector of 256-bit
FIELD(Indexes, VECTOR256, 1) FIELD (Indexes, VECTOR256, 1)
FIELD(Hashes, VECTOR256, 2) FIELD (Hashes, VECTOR256, 2)
FIELD(Features, VECTOR256, 3) FIELD (Features, VECTOR256, 3)
// inner object // inner object
// OBJECT/1 is reserved for end of object // OBJECT/1 is reserved for end of object
FIELD(TransactionMetaData, OBJECT, 2) FIELD (TransactionMetaData, OBJECT, 2)
FIELD(CreatedNode, OBJECT, 3) FIELD (CreatedNode, OBJECT, 3)
FIELD(DeletedNode, OBJECT, 4) FIELD (DeletedNode, OBJECT, 4)
FIELD(ModifiedNode, OBJECT, 5) FIELD (ModifiedNode, OBJECT, 5)
FIELD(PreviousFields, OBJECT, 6) FIELD (PreviousFields, OBJECT, 6)
FIELD(FinalFields, OBJECT, 7) FIELD (FinalFields, OBJECT, 7)
FIELD(NewFields, OBJECT, 8) FIELD (NewFields, OBJECT, 8)
FIELD(TemplateEntry, OBJECT, 9) FIELD (TemplateEntry, OBJECT, 9)
// array of objects // array of objects
// ARRAY/1 is reserved for end of array // ARRAY/1 is reserved for end of array
FIELD(SigningAccounts, ARRAY, 2) FIELD (SigningAccounts, ARRAY, 2)
FIELD(TxnSignatures, ARRAY, 3) FIELD (TxnSignatures, ARRAY, 3)
FIELD(Signatures, ARRAY, 4) FIELD (Signatures, ARRAY, 4)
FIELD(Template, ARRAY, 5) FIELD (Template, ARRAY, 5)
FIELD(Necessary, ARRAY, 6) FIELD (Necessary, ARRAY, 6)
FIELD(Sufficient, ARRAY, 7) FIELD (Sufficient, ARRAY, 7)
FIELD(AffectedNodes, ARRAY, 8) FIELD (AffectedNodes, ARRAY, 8)
// vim:ts=4 // vim:ts=4

File diff suppressed because it is too large Load Diff

View File

@@ -1,256 +1,488 @@
#ifndef RIPPLE_SERIALIZEDOBJECT_H #ifndef RIPPLE_SERIALIZEDOBJECT_H
#define RIPPLE_SERIALIZEDOBJECT_H #define RIPPLE_SERIALIZEDOBJECT_H
DEFINE_INSTANCE(SerializedObject); DEFINE_INSTANCE (SerializedObject);
DEFINE_INSTANCE(SerializedArray); DEFINE_INSTANCE (SerializedArray);
class STObject : public SerializedType, private IS_INSTANCE(SerializedObject) class STObject : public SerializedType, private IS_INSTANCE (SerializedObject)
{ {
public: 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) STObject (const SOTemplate & type, SField::ref name) : SerializedType (name)
{ set(type); } {
set (type);
}
STObject (const SOTemplate& type, SerializerIterator& sit, SField::ref name) : SerializedType(name) STObject (const SOTemplate & type, SerializerIterator & sit, SField::ref name) : SerializedType (name)
{ set(sit); setType(type); } {
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 setType (const SOTemplate & type);
bool isValidForType(); bool isValidForType ();
bool isFieldAllowed(SField::ref); bool isFieldAllowed (SField::ref);
bool isFree() const { return mType == NULL; } bool isFree () const
{
return mType == NULL;
}
void set(const SOTemplate&); void set (const SOTemplate&);
bool set(SerializerIterator& u, int depth = 0); bool set (SerializerIterator & u, int depth = 0);
virtual SerializedTypeID getSType() const { return STI_OBJECT; } virtual SerializedTypeID getSType () const
virtual bool isEquivalent(const SerializedType& t) const; {
virtual bool isDefault() const { return mData.empty(); } 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 NOTE does this return an expensive copy of an object with a dynamic buffer?
// VFALCO TODO Remove this function and fix the few callers. // 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 getFullText () const;
std::string getText() const; std::string getText () const;
virtual Json::Value getJson(int options) const; virtual Json::Value getJson (int options) const;
int addObject(const SerializedType& t) { mData.push_back(t.clone().release()); return mData.size() - 1; } int addObject (const SerializedType & t)
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; } mData.push_back (t.clone ().release ());
const boost::ptr_vector<SerializedType>& peekData() const { return mData; } return mData.size () - 1;
boost::ptr_vector<SerializedType>& peekData() { return mData; } }
SerializedType& front() { return mData.front(); } int giveObject (UPTR_T<SerializedType> t)
const SerializedType& front() const { return mData.front(); } {
SerializedType& back() { return mData.back(); } mData.push_back (t.release ());
const SerializedType& back() const { return mData.back(); } 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 setFlag (uint32);
bool clearFlag(uint32); bool clearFlag (uint32);
uint32 getFlags() const; uint32 getFlags () const;
uint256 getHash(uint32 prefix) const; uint256 getHash (uint32 prefix) const;
uint256 getSigningHash(uint32 prefix) const; uint256 getSigningHash (uint32 prefix) const;
const SerializedType& peekAtIndex(int offset) const { return mData[offset]; } const SerializedType& peekAtIndex (int offset) const
SerializedType& getIndex(int offset) { return mData[offset]; } {
const SerializedType* peekAtPIndex(int offset) const { return &(mData[offset]); } return mData[offset];
SerializedType* getPIndex(int offset) { 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; int getFieldIndex (SField::ref field) const;
SField::ref getFieldSType(int index) const; SField::ref getFieldSType (int index) const;
const SerializedType& peekAtField(SField::ref field) const; const SerializedType& peekAtField (SField::ref field) const;
SerializedType& getField(SField::ref field); SerializedType& getField (SField::ref field);
const SerializedType* peekAtPField(SField::ref field) const; const SerializedType* peekAtPField (SField::ref field) const;
SerializedType* getPField(SField::ref field, bool createOkay = false); SerializedType* getPField (SField::ref field, bool createOkay = false);
// these throw if the field type doesn't match, or return default values if the // these throw if the field type doesn't match, or return default values if the
// field is optional but not present // field is optional but not present
std::string getFieldString(SField::ref field) const; std::string getFieldString (SField::ref field) const;
unsigned char getFieldU8(SField::ref field) const; unsigned char getFieldU8 (SField::ref field) const;
uint16 getFieldU16(SField::ref field) const; uint16 getFieldU16 (SField::ref field) const;
uint32 getFieldU32(SField::ref field) const; uint32 getFieldU32 (SField::ref field) const;
uint64 getFieldU64(SField::ref field) const; uint64 getFieldU64 (SField::ref field) const;
uint128 getFieldH128(SField::ref field) const; uint128 getFieldH128 (SField::ref field) const;
uint160 getFieldH160(SField::ref field) const; uint160 getFieldH160 (SField::ref field) const;
uint256 getFieldH256(SField::ref field) const; uint256 getFieldH256 (SField::ref field) const;
RippleAddress getFieldAccount(SField::ref field) const; RippleAddress getFieldAccount (SField::ref field) const;
uint160 getFieldAccount160(SField::ref field) const; uint160 getFieldAccount160 (SField::ref field) const;
Blob getFieldVL(SField::ref field) const; Blob getFieldVL (SField::ref field) const;
const STAmount& getFieldAmount(SField::ref field) const; const STAmount& getFieldAmount (SField::ref field) const;
const STPathSet& getFieldPathSet(SField::ref field) const; const STPathSet& getFieldPathSet (SField::ref field) const;
const STVector256& getFieldV256(SField::ref field) const; const STVector256& getFieldV256 (SField::ref field) const;
void setFieldU8(SField::ref field, unsigned char); void setFieldU8 (SField::ref field, unsigned char);
void setFieldU16(SField::ref field, uint16); void setFieldU16 (SField::ref field, uint16);
void setFieldU32(SField::ref field, uint32); void setFieldU32 (SField::ref field, uint32);
void setFieldU64(SField::ref field, uint64); void setFieldU64 (SField::ref field, uint64);
void setFieldH128(SField::ref field, const uint128&); void setFieldH128 (SField::ref field, const uint128&);
void setFieldH160(SField::ref field, const uint160&); void setFieldH160 (SField::ref field, const uint160&);
void setFieldH256(SField::ref field, uint256 const& ); void setFieldH256 (SField::ref field, uint256 const& );
void setFieldVL(SField::ref field, Blob const&); void setFieldVL (SField::ref field, Blob const&);
void setFieldAccount(SField::ref field, const uint160&); void setFieldAccount (SField::ref field, const uint160&);
void setFieldAccount(SField::ref field, const RippleAddress& addr) void setFieldAccount (SField::ref field, const RippleAddress & addr)
{ setFieldAccount(field, addr.getAccountID()); } {
void setFieldAmount(SField::ref field, const STAmount&); setFieldAccount (field, addr.getAccountID ());
void setFieldPathSet(SField::ref field, const STPathSet&); }
void setFieldV256(SField::ref field, const STVector256& v); 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; bool isFieldPresent (SField::ref field) const;
SerializedType* makeFieldPresent(SField::ref field); SerializedType* makeFieldPresent (SField::ref field);
void makeFieldAbsent(SField::ref field); void makeFieldAbsent (SField::ref field);
bool delField(SField::ref field); bool delField (SField::ref field);
void delField(int index); 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 // VFALCO TODO remove the 'depth' parameter
static UPTR_T<SerializedType> makeDeserializedObject ( static UPTR_T<SerializedType> makeDeserializedObject (
SerializedTypeID id, SerializedTypeID id,
SField::ref name, SField::ref name,
SerializerIterator &, SerializerIterator&,
int depth); int depth);
static UPTR_T<SerializedType> makeNonPresentObject (SField::ref name) static UPTR_T<SerializedType> makeNonPresentObject (SField::ref name)
{ {
return makeDefaultObject(STI_NOTPRESENT, name); return makeDefaultObject (STI_NOTPRESENT, name);
} }
static UPTR_T<SerializedType> makeDefaultObject (SField::ref name) static UPTR_T<SerializedType> makeDefaultObject (SField::ref name)
{ {
return makeDefaultObject(name.fieldType, name); return makeDefaultObject (name.fieldType, name);
} }
// field iterator stuff // field iterator stuff
typedef boost::ptr_vector<SerializedType>::iterator iterator; typedef boost::ptr_vector<SerializedType>::iterator iterator;
typedef boost::ptr_vector<SerializedType>::const_iterator const_iterator; typedef boost::ptr_vector<SerializedType>::const_iterator const_iterator;
iterator begin() { return mData.begin(); } iterator begin ()
iterator end() { return mData.end(); } {
const_iterator begin() const { return mData.begin(); } return mData.begin ();
const_iterator end() const { return mData.end(); } }
bool empty() const { return mData.empty(); } 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;
bool operator!=(const STObject& o) const { return ! (*this == o); } bool operator!= (const STObject & o) const
{
return ! (*this == o);
}
private: private:
boost::ptr_vector<SerializedType> mData; boost::ptr_vector<SerializedType> mData;
const SOTemplate* mType; const SOTemplate* mType;
STObject* duplicate() const { return new STObject(*this); } STObject* duplicate () const
STObject(SField::ref name, boost::ptr_vector<SerializedType>& data) : SerializedType(name), mType(NULL) {
{ mData.swap(data); } 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_begin (STObject& x)
inline STObject::iterator range_end(STObject &x) { return x.end(); } {
return x.begin ();
}
inline STObject::iterator range_end (STObject& x)
{
return x.end ();
}
namespace boost namespace boost
{ {
template<> struct range_mutable_iterator<STObject> { typedef STObject::iterator type; }; template<> struct range_mutable_iterator<STObject>
template<> struct range_const_iterator<STObject> { typedef STObject::const_iterator type; }; {
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: public:
typedef boost::ptr_vector<STObject> vector; typedef boost::ptr_vector<STObject> vector;
typedef boost::ptr_vector<STObject>::iterator iterator; typedef boost::ptr_vector<STObject>::iterator iterator;
typedef boost::ptr_vector<STObject>::const_iterator const_iterator; typedef boost::ptr_vector<STObject>::const_iterator const_iterator;
typedef boost::ptr_vector<STObject>::reverse_iterator reverse_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>::const_reverse_iterator const_reverse_iterator;
typedef boost::ptr_vector<STObject>::size_type size_type; typedef boost::ptr_vector<STObject>::size_type size_type;
public: public:
STArray () { ; } 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 (int n)
explicit STArray(vector& v) : value(v) { ; } {
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) static UPTR_T<SerializedType> deserialize (SerializerIterator & sit, SField::ref name)
{ return UPTR_T<SerializedType>(construct(sit, name)); } {
return UPTR_T<SerializedType> (construct (sit, name));
}
const vector& getValue() const { return value; } const vector& getValue () const
vector& getValue() { return value; } {
return value;
}
vector& getValue ()
{
return value;
}
// VFALCO NOTE as long as we're married to boost why not use boost::iterator_facade? // VFALCO NOTE as long as we're married to boost why not use boost::iterator_facade?
// //
// vector-like functions // vector-like functions
void push_back(const STObject& object) { value.push_back(object.oClone().release()); } void push_back (const STObject & object)
STObject& operator[](int j) { return value[j]; } {
const STObject& operator[](int j) const { return value[j]; } value.push_back (object.oClone ().release ());
iterator begin() { return value.begin(); } }
const_iterator begin() const { return value.begin(); } STObject& operator[] (int j)
iterator end() { return value.end(); } {
const_iterator end() const { return value.end(); } return value[j];
size_type size() const { return value.size(); } }
reverse_iterator rbegin() { return value.rbegin(); } const STObject& operator[] (int j) const
const_reverse_iterator rbegin() const { return value.rbegin(); } {
reverse_iterator rend() { return value.rend(); } return value[j];
const_reverse_iterator rend() const { return value.rend(); } }
iterator erase(iterator pos) { return value.erase(pos); } iterator begin ()
STObject& front() { return value.front(); } {
const STObject& front() const { return value.front(); } return value.begin ();
STObject& back() { return value.back(); } }
const STObject& back() const { return value.back(); } const_iterator begin () const
void pop_back() { value.pop_back(); } {
bool empty() const { return value.empty(); } return value.begin ();
void clear() { value.clear(); } }
void swap(STArray& a) { value.swap(a.value); } 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 getFullText () const;
virtual std::string getText() const; virtual std::string getText () const;
virtual Json::Value getJson(int) const; virtual Json::Value getJson (int) const;
virtual void add(Serializer& s) 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)
bool operator!=(const STArray &s) { return value != s.value; } {
return value == s.value;
}
bool operator!= (const STArray & s)
{
return value != s.value;
}
virtual SerializedTypeID getSType() const { return STI_ARRAY; } virtual SerializedTypeID getSType () const
virtual bool isEquivalent(const SerializedType& t) const; {
virtual bool isDefault() const { return value.empty(); } return STI_ARRAY;
}
virtual bool isEquivalent (const SerializedType & t) const;
virtual bool isDefault () const
{
return value.empty ();
}
private: private:
vector value; vector value;
STArray* duplicate() const { return new STArray(*this); } STArray* duplicate () const
static STArray* construct(SerializerIterator&, SField::ref); {
return new STArray (*this);
}
static STArray* construct (SerializerIterator&, SField::ref);
}; };
inline STArray::iterator range_begin(STArray& x) { return x.begin(); } inline STArray::iterator range_begin (STArray& x)
inline STArray::iterator range_end(STArray &x) { return x.end(); } {
return x.begin ();
}
inline STArray::iterator range_end (STArray& x)
{
return x.end ();
}
namespace boost namespace boost
{ {
template<> struct range_mutable_iterator<STArray> { typedef STArray::iterator type; }; template<> struct range_mutable_iterator<STArray>
template<> struct range_const_iterator<STArray> { typedef STArray::const_iterator type; }; {
typedef STArray::iterator type;
};
template<> struct range_const_iterator<STArray>
{
typedef STArray::const_iterator type;
};
} }
#endif #endif

View File

@@ -8,24 +8,24 @@ void SOTemplate::push_back (SOElement const& r)
// Ensure there is the enough space in the index mapping // Ensure there is the enough space in the index mapping
// table for all possible fields. // table for all possible fields.
// //
if (mIndex.empty()) if (mIndex.empty ())
{ {
// Unmapped indices will be set to -1 // 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 // 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 // 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 // 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. // 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 // 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... // VFALCO NOTE these don't look like bit-flags...
enum SOE_Flags enum SOE_Flags
{ {
SOE_INVALID = -1, SOE_INVALID = -1,
SOE_REQUIRED = 0, // required SOE_REQUIRED = 0, // required
SOE_OPTIONAL = 1, // optional, may be present with default value SOE_OPTIONAL = 1, // optional, may be present with default value
SOE_DEFAULT = 2, // optional, if present, must not have default value SOE_DEFAULT = 2, // optional, if present, must not have default value
}; };
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
@@ -21,10 +21,10 @@ enum SOE_Flags
class SOElement class SOElement
{ {
public: public:
SField::ref const e_field; SField::ref const e_field;
SOE_Flags const flags; SOE_Flags const flags;
SOElement (SField::ref fieldName, SOE_Flags flags) SOElement (SField::ref fieldName, SOE_Flags flags)
: e_field (fieldName) : e_field (fieldName)
, flags (flags) , flags (flags)
{ {
@@ -48,12 +48,12 @@ public:
@see push_back @see push_back
*/ */
SOTemplate (); SOTemplate ();
// VFALCO NOTE Why do we even bother with the 'private' keyword if // VFALCO NOTE Why do we even bother with the 'private' keyword if
// this function is present? // this function is present?
// //
std::vector <SOElement const*> const& peek() const std::vector <SOElement const*> const& peek () const
{ {
return mTypes; return mTypes;
} }
@@ -67,9 +67,9 @@ public:
int getIndex (SField::ref) const; int getIndex (SField::ref) const;
private: 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 #endif

View File

@@ -1,265 +1,291 @@
SETUP_LOG (SerializedType) SETUP_LOG (SerializedType)
const STAmount saZero(CURRENCY_ONE, ACCOUNT_ONE, 0); const STAmount saZero (CURRENCY_ONE, ACCOUNT_ONE, 0);
const STAmount saOne(CURRENCY_ONE, ACCOUNT_ONE, 1); 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()) if ((t.fName != fName) && fName->isUseful () && t.fName->isUseful ())
{ {
WriteLog ((t.getSType() == STI_AMOUNT) ? lsDEBUG : lsWARNING, SerializedType) // This is common for amounts WriteLog ((t.getSType () == STI_AMOUNT) ? lsDEBUG : lsWARNING, SerializedType) // This is common for amounts
<< "Caution: " << t.fName->getName() << " not replacing " << fName->getName(); << "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();
} }
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; for (int i = 0; i < value.size (); i++)
if (getSType() != STI_NOTPRESENT) {
{ std::cerr << i << ": ";
if(fName->hasName())
{ for (int j = 0; j < value[i].mPath.size (); j++)
ret = fName->fieldName; {
ret += " = "; //STPathElement pe = value[i].mPath[j];
} RippleAddress nad;
ret += getText(); nad.setAccountID (value[i].mPath[j].mAccountID);
} std::cerr << " " << nad.humanAccountID ();
return ret; //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 ret;
{
std::string token, human; if (getSType () != STI_NOTPRESENT)
if (transResultInfo(static_cast<TER>(value), token, human)) {
return human; if (fName->hasName ())
} {
return boost::lexical_cast<std::string>(value); 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) return new STUInt8 (name, u.get8 ());
{
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;
} }
bool STUInt8::isEquivalent(const SerializedType& t) const std::string STUInt8::getText () const
{ {
const STUInt8* v = dynamic_cast<const STUInt8*>(&t); if (getFName () == sfTransactionResult)
return v && (value == v->value); {
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) const STUInt8* v = dynamic_cast<const STUInt8*> (&t);
{ return v && (value == v->value);
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);
} }
Json::Value STUInt16::getJson(int) const STUInt16* STUInt16::construct (SerializerIterator& u, SField::ref name)
{ {
if (getFName() == sfLedgerEntryType) return new STUInt16 (name, u.get16 ());
{
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;
} }
bool STUInt16::isEquivalent(const SerializedType& t) const std::string STUInt16::getText () const
{ {
const STUInt16* v = dynamic_cast<const STUInt16*>(&t); if (getFName () == sfLedgerEntryType)
return v && (value == v->value); {
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) Json::Value STUInt16::getJson (int) const
{
return new STUInt32(name, u.get32());
}
std::string STUInt32::getText() 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 new STUInt32 (name, u.get32 ());
return v && (value == v->value);
} }
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 new STUInt64 (name, u.get64 ());
return v && (value == v->value);
} }
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); const STUInt64* v = dynamic_cast<const STUInt64*> (&t);
return v && (value == v->value); 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); const STHash128* v = dynamic_cast<const STHash128*> (&t);
return v && (value == v->value); 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); const STHash160* v = dynamic_cast<const STHash160*> (&t);
return v && (value == v->value); 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); value = st.getVL ();
return v && (value == v->value);
} }
std::string STAccount::getText() const std::string STVariableLength::getText () const
{ {
uint160 u; return strHex (value);
RippleAddress a;
if (!getValueH160(u))
return STVariableLength::getText();
a.setAccountID(u);
return a.humanAccountID();
} }
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. // 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 data = u.getVL ();
Blob ::iterator begin = data.begin(); 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); int count = data.size () / (256 / 8);
vec->mValue.reserve(count); vec->mValue.reserve (count);
unsigned int uStart = 0; unsigned int uStart = 0;
for (unsigned int i = 0; i != count; i++)
{
unsigned int uEnd = uStart + (256 / 8);
// This next line could be optimized to construct a default uint256 in the vector and then copy into it for (unsigned int i = 0; i != count; i++)
vec->mValue.push_back(uint256(Blob (begin + uStart, begin + uEnd))); {
uStart = uEnd; 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); const STVector256* v = dynamic_cast<const STVector256*> (&t);
return v && (mValue == v->mValue); 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) BOOST_FOREACH (uint256 const & hash, mValue)
{ {
if (hash == v) if (hash == v)
return true; return true;
} }
return false; return false;
} }
// //
// STAccount // 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 ().clear ();
peekValue().insert(peekValue().end(), v.begin(), v.end()); peekValue ().insert (peekValue ().end (), v.begin (), v.end ());
assert(peekValue().size() == (160/8)); assert (peekValue ().size () == (160 / 8));
} }
bool STAccount::getValueH160(uint160& v) const bool STAccount::getValueH160 (uint160& v) const
{ {
if (!isValueH160()) return false; if (!isValueH160 ()) return false;
memcpy(v.begin(), &(peekValue().front()), (160/8));
return true; memcpy (v.begin (), & (peekValue ().front ()), (160 / 8));
return true;
} }
RippleAddress STAccount::getValueNCA() const RippleAddress STAccount::getValueNCA () const
{ {
RippleAddress a; RippleAddress a;
uint160 v; uint160 v;
if (getValueH160(v))
a.setAccountID(v); if (getValueH160 (v))
return a; 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<STPath> paths;
std::vector<STPathElement> path; std::vector<STPathElement> path;
do do
{ {
int iType = s.get8(); int iType = s.get8 ();
if (iType == STPathElement::typeEnd || iType == STPathElement::typeBoundary) if (iType == STPathElement::typeEnd || iType == STPathElement::typeBoundary)
{ {
if (path.empty()) if (path.empty ())
{ {
WriteLog (lsINFO, SerializedType) << "STPathSet: Empty path."; WriteLog (lsINFO, SerializedType) << "STPathSet: Empty path.";
throw std::runtime_error("empty path"); throw std::runtime_error ("empty path");
} }
paths.push_back(path); paths.push_back (path);
path.clear(); path.clear ();
if (iType == STPathElement::typeEnd) if (iType == STPathElement::typeEnd)
{ {
return new STPathSet(name, paths); return new STPathSet (name, paths);
} }
} }
else if (iType & ~STPathElement::typeValidBits) else if (iType & ~STPathElement::typeValidBits)
{ {
WriteLog (lsINFO, SerializedType) << "STPathSet: Bad path element: " << iType; WriteLog (lsINFO, SerializedType) << "STPathSet: Bad path element: " << iType;
throw std::runtime_error("bad path element"); throw std::runtime_error ("bad path element");
} }
else else
{ {
const bool bAccount = !!(iType & STPathElement::typeAccount); const bool bAccount = !! (iType & STPathElement::typeAccount);
const bool bCurrency = !!(iType & STPathElement::typeCurrency); const bool bCurrency = !! (iType & STPathElement::typeCurrency);
const bool bIssuer = !!(iType & STPathElement::typeIssuer); const bool bIssuer = !! (iType & STPathElement::typeIssuer);
uint160 uAccountID; uint160 uAccountID;
uint160 uCurrency; uint160 uCurrency;
uint160 uIssuerID; uint160 uIssuerID;
if (bAccount) if (bAccount)
uAccountID = s.get160(); uAccountID = s.get160 ();
if (bCurrency) if (bCurrency)
uCurrency = s.get160(); uCurrency = s.get160 ();
if (bIssuer) if (bIssuer)
uIssuerID = s.get160(); uIssuerID = s.get160 ();
path.push_back(STPathElement(uAccountID, uCurrency, uIssuerID, bCurrency)); path.push_back (STPathElement (uAccountID, uCurrency, uIssuerID, bCurrency));
} }
} while(1); }
while (1);
} }
bool STPathSet::isEquivalent(const SerializedType& t) const bool STPathSet::isEquivalent (const SerializedType& t) const
{ {
const STPathSet* v = dynamic_cast<const STPathSet*>(&t); const STPathSet* v = dynamic_cast<const STPathSet*> (&t);
return v && (value == v->value); 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) for (int i = 0; i < mPath.size (); ++i)
{ {
const STPathElement& ele = getElement(i); const STPathElement& ele = getElement (i);
if (ele.getAccountID() == uAccountId
&& ele.getCurrency() == uCurrencyID if (ele.getAccountID () == uAccountId
&& ele.getIssuerID() == uIssuerID) && ele.getCurrency () == uCurrencyID
return true; && ele.getIssuerID () == uIssuerID)
} return true;
return false; }
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) BOOST_FOREACH (std::vector<STPathElement>::const_iterator::value_type it, mPath)
{ {
Json::Value elem(Json::objectValue); Json::Value elem (Json::objectValue);
int iType = it.getNodeType(); int iType = it.getNodeType ();
elem["type"] = iType; elem["type"] = iType;
elem["type_hex"] = strHex(iType); elem["type_hex"] = strHex (iType);
if (iType & STPathElement::typeAccount) if (iType & STPathElement::typeAccount)
elem["account"] = RippleAddress::createHumanAccountID(it.getAccountID()); elem["account"] = RippleAddress::createHumanAccountID (it.getAccountID ());
if (iType & STPathElement::typeCurrency) if (iType & STPathElement::typeCurrency)
elem["currency"] = STAmount::createHumanCurrency(it.getCurrency()); elem["currency"] = STAmount::createHumanCurrency (it.getCurrency ());
if (iType & STPathElement::typeIssuer) if (iType & STPathElement::typeIssuer)
elem["issuer"] = RippleAddress::createHumanAccountID(it.getIssuerID()); 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) BOOST_FOREACH (std::vector<STPath>::const_iterator::value_type it, value)
ret.append(it.getJson(options)); ret.append (it.getJson (options));
return ret; return ret;
} }
#if 0 #if 0
std::string STPath::getText() const std::string STPath::getText () const
{ {
std::string ret("["); std::string ret ("[");
bool first = true; bool first = true;
BOOST_FOREACH(const STPathElement& it, mPath) BOOST_FOREACH (const STPathElement & it, mPath)
{ {
if (!first) ret += ", "; if (!first) ret += ", ";
switch (it.getNodeType())
{
case STPathElement::typeAccount:
{
ret += RippleAddress::createHumanAccountID(it.getNode());
break;
}
case STPathElement::typeOffer: switch (it.getNodeType ())
{ {
ret += "Offer("; case STPathElement::typeAccount:
ret += it.getNode().GetHex(); {
ret += ")"; ret += RippleAddress::createHumanAccountID (it.getNode ());
break; break;
} }
default: throw std::runtime_error("Unknown path element"); case STPathElement::typeOffer:
} {
first = false; ret += "Offer(";
} ret += it.getNode ().GetHex ();
ret += ")";
break;
}
return ret + "]"; default:
throw std::runtime_error ("Unknown path element");
}
first = false;
}
return ret + "]";
} }
#endif #endif
#if 0 #if 0
std::string STPathSet::getText() const std::string STPathSet::getText () const
{ {
std::string ret("{"); std::string ret ("{");
bool firstPath = true; bool firstPath = true;
BOOST_FOREACH(std::vector<STPath>::const_iterator::value_type it, value) BOOST_FOREACH (std::vector<STPath>::const_iterator::value_type it, value)
{ {
if (!firstPath) if (!firstPath)
{ {
ret += ", "; ret += ", ";
firstPath = false; firstPath = false;
} }
ret += it.getText();
} ret += it.getText ();
return ret + "}"; }
return ret + "}";
} }
#endif #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) BOOST_FOREACH (const STPath & spPath, value)
{ {
if (!bFirst) if (!bFirst)
{ {
s.add8(STPathElement::typeBoundary); s.add8 (STPathElement::typeBoundary);
} }
BOOST_FOREACH(const STPathElement& speElement, spPath) BOOST_FOREACH (const STPathElement & speElement, spPath)
{ {
int iType = speElement.getNodeType(); int iType = speElement.getNodeType ();
s.add8(iType); s.add8 (iType);
if (iType & STPathElement::typeAccount) if (iType & STPathElement::typeAccount)
s.add160(speElement.getAccountID()); s.add160 (speElement.getAccountID ());
if (iType & STPathElement::typeCurrency) if (iType & STPathElement::typeCurrency)
s.add160(speElement.getCurrency()); s.add160 (speElement.getCurrency ());
if (iType & STPathElement::typeIssuer) if (iType & STPathElement::typeIssuer)
s.add160(speElement.getIssuerID()); s.add160 (speElement.getIssuerID ());
} }
bFirst = false; bFirst = false;
} }
s.add8(STPathElement::typeEnd); s.add8 (STPathElement::typeEnd);
} }
// vim:ts=4 // 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 class Serializer
{ {
public: public:
typedef boost::shared_ptr<Serializer> pointer; typedef boost::shared_ptr<Serializer> pointer;
protected: protected:
Blob mData; Blob mData;
public: public:
Serializer(int n = 256) { mData.reserve(n); } Serializer (int n = 256)
Serializer(Blob const& data) : mData(data) { ; } {
Serializer(const std::string& data) : mData(data.data(), (data.data()) + data.size()) { ; } mData.reserve (n);
Serializer(Blob ::iterator begin, Blob ::iterator end) : }
mData(begin, end) { ; } Serializer (Blob const& data) : mData (data)
Serializer(Blob ::const_iterator begin, Blob ::const_iterator end) : {
mData(begin, end) { ; } ;
}
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 // assemble functions
int add8(unsigned char byte); int add8 (unsigned char byte);
int add16(uint16); int add16 (uint16);
int add32(uint32); // ledger indexes, account sequence, timestamps int add32 (uint32); // ledger indexes, account sequence, timestamps
int add64(uint64); // native currency amounts int add64 (uint64); // native currency amounts
int add128(const uint128&); // private key generators int add128 (const uint128&); // private key generators
int add160(const uint160&); // account names, hankos int add160 (const uint160&); // account names, hankos
int add256(uint256 const& ); // transaction and ledger hashes int add256 (uint256 const& ); // transaction and ledger hashes
int addRaw(Blob const& vector); int addRaw (Blob const& vector);
int addRaw(const void *ptr, int len); int addRaw (const void* ptr, int len);
int addRaw(const Serializer& s); int addRaw (const Serializer& s);
int addZeros(size_t uBytes); int addZeros (size_t uBytes);
int addVL(Blob const& vector); int addVL (Blob const& vector);
int addVL(const std::string& string); int addVL (const std::string& string);
int addVL(const void *ptr, int len); int addVL (const void* ptr, int len);
// disassemble functions // disassemble functions
bool get8(int&, int offset) const; bool get8 (int&, int offset) const;
bool get8(unsigned char&, int offset) const; bool get8 (unsigned char&, int offset) const;
bool get16(uint16&, int offset) const; bool get16 (uint16&, int offset) const;
bool get32(uint32&, int offset) const; bool get32 (uint32&, int offset) const;
bool get64(uint64&, int offset) const; bool get64 (uint64&, int offset) const;
bool get128(uint128&, int offset) const; bool get128 (uint128&, int offset) const;
bool get160(uint160&, int offset) const; bool get160 (uint160&, int offset) const;
bool get256(uint256&, int offset) const; bool get256 (uint256&, int offset) const;
uint256 get256(int offset) const; uint256 get256 (int offset) const;
bool getRaw(Blob&, int offset, int length) const; bool getRaw (Blob&, int offset, int length) const;
Blob getRaw(int offset, int length) const; Blob getRaw (int offset, int length) const;
bool getVL(Blob& objectVL, int offset, int& length) const; bool getVL (Blob& objectVL, int offset, int& length) const;
bool getVLLength(int& length, int offset) const; bool getVLLength (int& length, int offset) const;
bool getFieldID(int& type, int& name, int offset) const; bool getFieldID (int& type, int& name, int offset) const;
int addFieldID(int type, int name); int addFieldID (int type, int name);
int addFieldID(SerializedTypeID type, int name) { return addFieldID(static_cast<int>(type), name); } int addFieldID (SerializedTypeID type, int name)
{
return addFieldID (static_cast<int> (type), name);
}
// normal hash functions // normal hash functions
uint160 getRIPEMD160(int size=-1) const; uint160 getRIPEMD160 (int size = -1) const;
uint256 getSHA256(int size=-1) const; uint256 getSHA256 (int size = -1) const;
uint256 getSHA512Half(int size=-1) const; uint256 getSHA512Half (int size = -1) const;
static uint256 getSHA512Half(Blob const& data, int size=-1); static uint256 getSHA512Half (Blob const& data, int size = -1);
static uint256 getSHA512Half(const unsigned char *data, int len); static uint256 getSHA512Half (const unsigned char* data, int len);
static uint256 getSHA512Half(const std::string& strData); static uint256 getSHA512Half (const std::string& strData);
// prefix hash functions // prefix hash functions
static uint256 getPrefixHash(uint32 prefix, const unsigned char *data, int len); static uint256 getPrefixHash (uint32 prefix, const unsigned char* data, int len);
uint256 getPrefixHash(uint32 prefix) const uint256 getPrefixHash (uint32 prefix) const
{ return getPrefixHash(prefix, &(mData.front()), mData.size()); } {
static uint256 getPrefixHash(uint32 prefix, Blob const& data) return getPrefixHash (prefix, & (mData.front ()), mData.size ());
{ return getPrefixHash(prefix, &(data.front()), data.size()); } }
static uint256 getPrefixHash(uint32 prefix, const std::string& strData) static uint256 getPrefixHash (uint32 prefix, Blob const& data)
{ return getPrefixHash(prefix, reinterpret_cast<const unsigned char *>(strData.data()), strData.size()); } {
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 // totality functions
Blob const& peekData() const { return mData; } Blob const& peekData () const
Blob getData() const { return mData; } {
Blob& modData() { return mData; } return mData;
int getCapacity() const { return mData.capacity(); } }
int getDataLength() const { return mData.size(); } Blob getData () const
const void* getDataPtr() const { return &mData.front(); } {
void* getDataPtr() { return &mData.front(); } return mData;
int getLength() const { return mData.size(); } }
std::string getString() const { return std::string(static_cast<const char *>(getDataPtr()), size()); } Blob& modData ()
void secureErase() { memset(&(mData.front()), 0, mData.size()); erase(); } {
void erase() { mData.clear(); } return mData;
int removeLastByte(); }
bool chop(int num); 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 // vector-like functions
Blob ::iterator begin() { return mData.begin(); } Blob ::iterator begin ()
Blob ::iterator end() { return mData.end(); } {
Blob ::const_iterator begin() const { return mData.begin(); } return mData.begin ();
Blob ::const_iterator end() const { return mData.end(); } }
Blob ::size_type size() const { return mData.size(); } Blob ::iterator end ()
void reserve(size_t n) { mData.reserve(n); } {
void resize(size_t n) { mData.resize(n); } return mData.end ();
size_t capacity() const { return mData.capacity(); } }
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)
bool operator!=(Blob const& v) { return v != mData; } {
bool operator==(const Serializer& v) { return v.mData == mData; } return v == mData;
bool operator!=(const Serializer& v) { return v.mData != 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 // signature functions
bool checkSignature(int pubkeyOffset, int signatureOffset) const; bool checkSignature (int pubkeyOffset, int signatureOffset) const;
bool checkSignature(Blob const& signature, CKey& rkey) const; bool checkSignature (Blob const& signature, CKey& rkey) const;
bool makeSignature(Blob& signature, CKey& rkey) const; bool makeSignature (Blob& signature, CKey& rkey) const;
bool addSignature(CKey& rkey); bool addSignature (CKey& rkey);
// low-level VL length encode/decode functions // low-level VL length encode/decode functions
static Blob encodeVL(int length); static Blob encodeVL (int length);
static int lengthVL(int length) { return length + encodeLengthLength(length); } static int lengthVL (int length)
static int encodeLengthLength(int length); // length to encode length {
static int decodeLengthLength(int b1); return length + encodeLengthLength (length);
static int decodeVLLength(int b1); }
static int decodeVLLength(int b1, int b2); static int encodeLengthLength (int length); // length to encode length
static int decodeVLLength(int b1, int b2, int b3); 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 class SerializerIterator
{ {
protected: protected:
const Serializer& mSerializer; const Serializer& mSerializer;
int mPos; int mPos;
public: public:
// Reference is not const because we don't want to bind to a temporary // Reference is not const because we don't want to bind to a temporary
SerializerIterator(Serializer& s) : mSerializer(s), mPos(0) { ; } SerializerIterator (Serializer& s) : mSerializer (s), mPos (0)
{
;
}
const Serializer& operator*(void) { return mSerializer; } const Serializer& operator* (void)
void reset(void) { mPos = 0; } {
void setPos(int p) { mPos = p; } return mSerializer;
}
void reset (void)
{
mPos = 0;
}
void setPos (int p)
{
mPos = p;
}
int getPos(void) { return mPos; } int getPos (void)
bool empty() { return mPos == mSerializer.getLength(); } {
int getBytesLeft(); return mPos;
}
bool empty ()
{
return mPos == mSerializer.getLength ();
}
int getBytesLeft ();
// get functions throw on error // get functions throw on error
unsigned char get8(); unsigned char get8 ();
uint16 get16(); uint16 get16 ();
uint32 get32(); uint32 get32 ();
uint64 get64(); uint64 get64 ();
uint128 get128(); uint128 get128 ();
uint160 get160(); uint160 get160 ();
uint256 get256(); 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 #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 { static struct
TER terCode; {
const char* cpToken; TER terCode;
const char* cpHuman; const char* cpToken;
} transResultInfoA[] = { const char* cpHuman;
{ tecCLAIM, "tecCLAIM", "Fee claimed. Sequence used. No action." }, } transResultInfoA[] =
{ tecDIR_FULL, "tecDIR_FULL", "Can not add entry to full directory." }, {
{ tecFAILED_PROCESSING, "tecFAILED_PROCESSING", "Failed to correctly process transaction." }, { tecCLAIM, "tecCLAIM", "Fee claimed. Sequence used. No action." },
{ tecINSUF_RESERVE_LINE, "tecINSUF_RESERVE_LINE", "Insufficient reserve to add trust line." }, { tecDIR_FULL, "tecDIR_FULL", "Can not add entry to full directory." },
{ tecINSUF_RESERVE_OFFER, "tecINSUF_RESERVE_OFFER", "Insufficient reserve to create offer." }, { tecFAILED_PROCESSING, "tecFAILED_PROCESSING", "Failed to correctly process transaction." },
{ tecNO_DST, "tecNO_DST", "Destination does not exist. Send XRP to create it." }, { tecINSUF_RESERVE_LINE, "tecINSUF_RESERVE_LINE", "Insufficient reserve to add trust line." },
{ tecNO_DST_INSUF_XRP, "tecNO_DST_INSUF_XRP", "Destination does not exist. Too little XRP sent to create it." }, { tecINSUF_RESERVE_OFFER, "tecINSUF_RESERVE_OFFER", "Insufficient reserve to create offer." },
{ tecNO_LINE_INSUF_RESERVE, "tecNO_LINE_INSUF_RESERVE", "No such line. Too little reserve to create it." }, { tecNO_DST, "tecNO_DST", "Destination does not exist. Send XRP to create it." },
{ tecNO_LINE_REDUNDANT, "tecNO_LINE_REDUNDANT", "Can't set non-existant line to default." }, { tecNO_DST_INSUF_XRP, "tecNO_DST_INSUF_XRP", "Destination does not exist. Too little XRP sent to create it." },
{ tecPATH_DRY, "tecPATH_DRY", "Path could not send partial amount." }, { tecNO_LINE_INSUF_RESERVE, "tecNO_LINE_INSUF_RESERVE", "No such line. Too little reserve to create it." },
{ tecPATH_PARTIAL, "tecPATH_PARTIAL", "Path could not send full amount." }, { 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, "tecUNFUNDED", "One of _ADD, _OFFER, or _SEND. Deprecated." },
{ tecUNFUNDED_ADD, "tecUNFUNDED_ADD", "Insufficient XRP balance for WalletAdd." }, { tecUNFUNDED_ADD, "tecUNFUNDED_ADD", "Insufficient XRP balance for WalletAdd." },
{ tecUNFUNDED_OFFER, "tecUNFUNDED_OFFER", "Insufficient balance to fund created offer." }, { tecUNFUNDED_OFFER, "tecUNFUNDED_OFFER", "Insufficient balance to fund created offer." },
{ tecUNFUNDED_PAYMENT, "tecUNFUNDED_PAYMENT", "Insufficient XRP balance to send." }, { tecUNFUNDED_PAYMENT, "tecUNFUNDED_PAYMENT", "Insufficient XRP balance to send." },
{ tefFAILURE, "tefFAILURE", "Failed to apply." }, { tefFAILURE, "tefFAILURE", "Failed to apply." },
{ tefALREADY, "tefALREADY", "The exact transaction was already in this ledger." }, { tefALREADY, "tefALREADY", "The exact transaction was already in this ledger." },
{ tefBAD_ADD_AUTH, "tefBAD_ADD_AUTH", "Not authorized to add account." }, { tefBAD_ADD_AUTH, "tefBAD_ADD_AUTH", "Not authorized to add account." },
{ tefBAD_AUTH, "tefBAD_AUTH", "Transaction's public key is not authorized." }, { tefBAD_AUTH, "tefBAD_AUTH", "Transaction's public key is not authorized." },
{ tefBAD_CLAIM_ID, "tefBAD_CLAIM_ID", "Malformed: Bad claim id." }, { tefBAD_CLAIM_ID, "tefBAD_CLAIM_ID", "Malformed: Bad claim id." },
{ tefBAD_GEN_AUTH, "tefBAD_GEN_AUTH", "Not authorized to claim generator." }, { tefBAD_GEN_AUTH, "tefBAD_GEN_AUTH", "Not authorized to claim generator." },
{ tefBAD_LEDGER, "tefBAD_LEDGER", "Ledger in unexpected state." }, { tefBAD_LEDGER, "tefBAD_LEDGER", "Ledger in unexpected state." },
{ tefCLAIMED, "tefCLAIMED", "Can not claim a previously claimed account." }, { tefCLAIMED, "tefCLAIMED", "Can not claim a previously claimed account." },
{ tefCREATED, "tefCREATED", "Can't add an already created account." }, { tefCREATED, "tefCREATED", "Can't add an already created account." },
{ tefDST_TAG_NEEDED, "tefDST_TAG_NEEDED", "Destination tag required." }, { tefDST_TAG_NEEDED, "tefDST_TAG_NEEDED", "Destination tag required." },
{ tefEXCEPTION, "tefEXCEPTION", "Unexpected program state." }, { tefEXCEPTION, "tefEXCEPTION", "Unexpected program state." },
{ tefGEN_IN_USE, "tefGEN_IN_USE", "Generator already in use." }, { tefGEN_IN_USE, "tefGEN_IN_USE", "Generator already in use." },
{ tefINTERNAL, "tefINTERNAL", "Internal error." }, { tefINTERNAL, "tefINTERNAL", "Internal error." },
{ tefNO_AUTH_REQUIRED, "tefNO_AUTH_REQUIRED", "Auth is not required." }, { tefNO_AUTH_REQUIRED, "tefNO_AUTH_REQUIRED", "Auth is not required." },
{ tefPAST_SEQ, "tefPAST_SEQ", "This sequence number has already past." }, { tefPAST_SEQ, "tefPAST_SEQ", "This sequence number has already past." },
{ tefWRONG_PRIOR, "tefWRONG_PRIOR", "This previous transaction does not match." }, { tefWRONG_PRIOR, "tefWRONG_PRIOR", "This previous transaction does not match." },
{ telLOCAL_ERROR, "telLOCAL_ERROR", "Local failure." }, { telLOCAL_ERROR, "telLOCAL_ERROR", "Local failure." },
{ telBAD_DOMAIN, "telBAD_DOMAIN", "Domain too long." }, { telBAD_DOMAIN, "telBAD_DOMAIN", "Domain too long." },
{ telBAD_PATH_COUNT, "telBAD_PATH_COUNT", "Malformed: Too many paths." }, { telBAD_PATH_COUNT, "telBAD_PATH_COUNT", "Malformed: Too many paths." },
{ telBAD_PUBLIC_KEY, "telBAD_PUBLIC_KEY", "Public key too long." }, { telBAD_PUBLIC_KEY, "telBAD_PUBLIC_KEY", "Public key too long." },
{ telFAILED_PROCESSING, "telFAILED_PROCESSING", "Failed to correctly process transaction." }, { telFAILED_PROCESSING, "telFAILED_PROCESSING", "Failed to correctly process transaction." },
{ telINSUF_FEE_P, "telINSUF_FEE_P", "Fee insufficient." }, { telINSUF_FEE_P, "telINSUF_FEE_P", "Fee insufficient." },
{ telNO_DST_PARTIAL, "telNO_DST_PARTIAL", "Partial payment to create account not allowed." }, { telNO_DST_PARTIAL, "telNO_DST_PARTIAL", "Partial payment to create account not allowed." },
{ temMALFORMED, "temMALFORMED", "Malformed transaction." }, { temMALFORMED, "temMALFORMED", "Malformed transaction." },
{ temBAD_AMOUNT, "temBAD_AMOUNT", "Can only send positive amounts." }, { temBAD_AMOUNT, "temBAD_AMOUNT", "Can only send positive amounts." },
{ temBAD_AUTH_MASTER, "temBAD_AUTH_MASTER", "Auth for unclaimed account needs correct master key." }, { temBAD_AUTH_MASTER, "temBAD_AUTH_MASTER", "Auth for unclaimed account needs correct master key." },
{ temBAD_CURRENCY, "temBAD_CURRENCY", "Malformed: Bad currency." }, { temBAD_CURRENCY, "temBAD_CURRENCY", "Malformed: Bad currency." },
{ temBAD_FEE, "temBAD_FEE", "Invalid fee, negative or not XRP." }, { temBAD_FEE, "temBAD_FEE", "Invalid fee, negative or not XRP." },
{ temBAD_EXPIRATION, "temBAD_EXPIRATION", "Malformed: Bad expiration." }, { temBAD_EXPIRATION, "temBAD_EXPIRATION", "Malformed: Bad expiration." },
{ temBAD_ISSUER, "temBAD_ISSUER", "Malformed: Bad issuer." }, { temBAD_ISSUER, "temBAD_ISSUER", "Malformed: Bad issuer." },
{ temBAD_LIMIT, "temBAD_LIMIT", "Limits must be non-negative." }, { temBAD_LIMIT, "temBAD_LIMIT", "Limits must be non-negative." },
{ temBAD_OFFER, "temBAD_OFFER", "Malformed: Bad offer." }, { temBAD_OFFER, "temBAD_OFFER", "Malformed: Bad offer." },
{ temBAD_PATH, "temBAD_PATH", "Malformed: Bad path." }, { temBAD_PATH, "temBAD_PATH", "Malformed: Bad path." },
{ temBAD_PATH_LOOP, "temBAD_PATH_LOOP", "Malformed: Loop in path." }, { temBAD_PATH_LOOP, "temBAD_PATH_LOOP", "Malformed: Loop in path." },
{ temBAD_PUBLISH, "temBAD_PUBLISH", "Malformed: Bad publish." }, { temBAD_PUBLISH, "temBAD_PUBLISH", "Malformed: Bad publish." },
{ temBAD_SIGNATURE, "temBAD_SIGNATURE", "Malformed: Bad signature." }, { temBAD_SIGNATURE, "temBAD_SIGNATURE", "Malformed: Bad signature." },
{ temBAD_SRC_ACCOUNT, "temBAD_SRC_ACCOUNT", "Malformed: Bad source account." }, { temBAD_SRC_ACCOUNT, "temBAD_SRC_ACCOUNT", "Malformed: Bad source account." },
{ temBAD_TRANSFER_RATE, "temBAD_TRANSFER_RATE", "Malformed: Transfer rate must be >= 1.0" }, { 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_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_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_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_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_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." }, { 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_IS_SRC, "temDST_IS_SRC", "Destination may not be source." },
{ temDST_NEEDED, "temDST_NEEDED", "Destination not specified." }, { temDST_NEEDED, "temDST_NEEDED", "Destination not specified." },
{ temINVALID, "temINVALID", "The transaction is ill-formed." }, { temINVALID, "temINVALID", "The transaction is ill-formed." },
{ temINVALID_FLAG, "temINVALID_FLAG", "The transaction has an invalid flag." }, { temINVALID_FLAG, "temINVALID_FLAG", "The transaction has an invalid flag." },
{ temREDUNDANT, "temREDUNDANT", "Sends same currency to self." }, { temREDUNDANT, "temREDUNDANT", "Sends same currency to self." },
{ temREDUNDANT_SEND_MAX, "temREDUNDANT_SEND_MAX", "Send max is redundant." }, { temREDUNDANT_SEND_MAX, "temREDUNDANT_SEND_MAX", "Send max is redundant." },
{ temRIPPLE_EMPTY, "temRIPPLE_EMPTY", "PathSet with no paths." }, { temRIPPLE_EMPTY, "temRIPPLE_EMPTY", "PathSet with no paths." },
{ temUNCERTAIN, "temUNCERTAIN", "In process of determining result. Never returned." }, { temUNCERTAIN, "temUNCERTAIN", "In process of determining result. Never returned." },
{ temUNKNOWN, "temUNKNOWN", "The transactions requires logic not implemented yet." }, { temUNKNOWN, "temUNKNOWN", "The transactions requires logic not implemented yet." },
{ terRETRY, "terRETRY", "Retry transaction." }, { terRETRY, "terRETRY", "Retry transaction." },
{ terFUNDS_SPENT, "terFUNDS_SPENT", "Can't set password, password set funds already spent." }, { 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." }, { terINSUF_FEE_B, "terINSUF_FEE_B", "Account balance can't pay fee." },
{ terLAST, "terLAST", "Process last." }, { terLAST, "terLAST", "Process last." },
{ terNO_ACCOUNT, "terNO_ACCOUNT", "The source account does not exist." }, { terNO_ACCOUNT, "terNO_ACCOUNT", "The source account does not exist." },
{ terNO_AUTH, "terNO_AUTH", "Not authorized to hold IOUs." }, { terNO_AUTH, "terNO_AUTH", "Not authorized to hold IOUs." },
{ terNO_LINE, "terNO_LINE", "No such line." }, { terNO_LINE, "terNO_LINE", "No such line." },
{ terPRE_SEQ, "terPRE_SEQ", "Missing/inapplicable prior transaction." }, { terPRE_SEQ, "terPRE_SEQ", "Missing/inapplicable prior transaction." },
{ terOWNERS, "terOWNERS", "Non-zero owner count." }, { 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) if (iIndex >= 0)
{ {
strToken = transResultInfoA[iIndex].cpToken; strToken = transResultInfoA[iIndex].cpToken;
strHuman = transResultInfoA[iIndex].cpHuman; 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 strToken;
std::string strHuman; 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 strToken;
std::string strHuman; std::string strHuman;
return transResultInfo(terCode, strToken, strHuman) ? strHuman : "-"; return transResultInfo (terCode, strToken, strHuman) ? strHuman : "-";
} }
// vim:ts=4 // vim:ts=4

View File

@@ -7,149 +7,149 @@
// //
// VFALCO TODO consider renaming TER to TxErr or TxResult for clarity. // 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) // -399 .. -300: L Local error (transaction fee inadequate, exceeds local limit)
// Only valid during non-consensus processing. // Only valid during non-consensus processing.
// Implications: // Implications:
// - Not forwarded // - Not forwarded
// - No fee check // - No fee check
telLOCAL_ERROR = -399, telLOCAL_ERROR = -399,
telBAD_DOMAIN, // VFALCO TODO should read "telBAD_DOMAIN = -398," etc... telBAD_DOMAIN, // VFALCO TODO should read "telBAD_DOMAIN = -398," etc...
telBAD_PATH_COUNT, telBAD_PATH_COUNT,
telBAD_PUBLIC_KEY, telBAD_PUBLIC_KEY,
telFAILED_PROCESSING, telFAILED_PROCESSING,
telINSUF_FEE_P, telINSUF_FEE_P,
telNO_DST_PARTIAL, telNO_DST_PARTIAL,
// -299 .. -200: M Malformed (bad signature) // -299 .. -200: M Malformed (bad signature)
// Causes: // Causes:
// - Transaction corrupt. // - Transaction corrupt.
// Implications: // Implications:
// - Not applied // - Not applied
// - Not forwarded // - Not forwarded
// - Reject // - Reject
// - Can not succeed in any imagined ledger. // - Can not succeed in any imagined ledger.
temMALFORMED = -299, temMALFORMED = -299,
temBAD_AMOUNT, temBAD_AMOUNT,
temBAD_AUTH_MASTER, temBAD_AUTH_MASTER,
temBAD_CURRENCY, temBAD_CURRENCY,
temBAD_FEE, temBAD_FEE,
temBAD_EXPIRATION, temBAD_EXPIRATION,
temBAD_ISSUER, temBAD_ISSUER,
temBAD_LIMIT, temBAD_LIMIT,
temBAD_OFFER, temBAD_OFFER,
temBAD_PATH, temBAD_PATH,
temBAD_PATH_LOOP, temBAD_PATH_LOOP,
temBAD_PUBLISH, temBAD_PUBLISH,
temBAD_TRANSFER_RATE, temBAD_TRANSFER_RATE,
temBAD_SEND_XRP_LIMIT, temBAD_SEND_XRP_LIMIT,
temBAD_SEND_XRP_MAX, temBAD_SEND_XRP_MAX,
temBAD_SEND_XRP_NO_DIRECT, temBAD_SEND_XRP_NO_DIRECT,
temBAD_SEND_XRP_PARTIAL, temBAD_SEND_XRP_PARTIAL,
temBAD_SEND_XRP_PATHS, temBAD_SEND_XRP_PATHS,
temBAD_SIGNATURE, temBAD_SIGNATURE,
temBAD_SRC_ACCOUNT, temBAD_SRC_ACCOUNT,
temBAD_SEQUENCE, temBAD_SEQUENCE,
temDST_IS_SRC, temDST_IS_SRC,
temDST_NEEDED, temDST_NEEDED,
temINVALID, temINVALID,
temINVALID_FLAG, temINVALID_FLAG,
temREDUNDANT, temREDUNDANT,
temREDUNDANT_SEND_MAX, temREDUNDANT_SEND_MAX,
temRIPPLE_EMPTY, temRIPPLE_EMPTY,
temUNCERTAIN, // An intermediate result used internally, should never be returned. temUNCERTAIN, // An intermediate result used internally, should never be returned.
temUNKNOWN, temUNKNOWN,
// -199 .. -100: F Failure (sequence number previously used) // -199 .. -100: F Failure (sequence number previously used)
// Causes: // Causes:
// - Transaction cannot succeed because of ledger state. // - Transaction cannot succeed because of ledger state.
// - Unexpected ledger state. // - Unexpected ledger state.
// - C++ exception. // - C++ exception.
// Implications: // Implications:
// - Not applied // - Not applied
// - Not forwarded // - Not forwarded
// - Could succeed in an imagined ledger. // - Could succeed in an imagined ledger.
tefFAILURE = -199, tefFAILURE = -199,
tefALREADY, tefALREADY,
tefBAD_ADD_AUTH, tefBAD_ADD_AUTH,
tefBAD_AUTH, tefBAD_AUTH,
tefBAD_CLAIM_ID, tefBAD_CLAIM_ID,
tefBAD_GEN_AUTH, tefBAD_GEN_AUTH,
tefBAD_LEDGER, tefBAD_LEDGER,
tefCLAIMED, tefCLAIMED,
tefCREATED, tefCREATED,
tefDST_TAG_NEEDED, tefDST_TAG_NEEDED,
tefEXCEPTION, tefEXCEPTION,
tefGEN_IN_USE, tefGEN_IN_USE,
tefINTERNAL, tefINTERNAL,
tefNO_AUTH_REQUIRED, // Can't set auth if auth is not required. tefNO_AUTH_REQUIRED, // Can't set auth if auth is not required.
tefPAST_SEQ, tefPAST_SEQ,
tefWRONG_PRIOR, tefWRONG_PRIOR,
// -99 .. -1: R Retry (sequence too high, no funds for txn fee, originating account non-existent) // -99 .. -1: R Retry (sequence too high, no funds for txn fee, originating account non-existent)
// Causes: // Causes:
// - Prior application of another, possibly non-existant, another transaction could allow this transaction to succeed. // - Prior application of another, possibly non-existant, another transaction could allow this transaction to succeed.
// Implications: // Implications:
// - Not applied // - Not applied
// - Not forwarded // - Not forwarded
// - Might succeed later // - Might succeed later
// - Hold // - Hold
// - Makes hole in sequence which jams transactions. // - Makes hole in sequence which jams transactions.
terRETRY = -99, terRETRY = -99,
terFUNDS_SPENT, // This is a free transaction, therefore don't burden network. terFUNDS_SPENT, // This is a free transaction, therefore don't burden network.
terINSUF_FEE_B, // Can't pay fee, 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_ACCOUNT, // Can't pay fee, therefore don't burden network.
terNO_AUTH, // Not authorized to hold IOUs. terNO_AUTH, // Not authorized to hold IOUs.
terNO_LINE, // Internal flag. terNO_LINE, // Internal flag.
terOWNERS, // Can't succeed with non-zero owner count. terOWNERS, // Can't succeed with non-zero owner count.
terPRE_SEQ, // Can't pay fee, no point in forwarding, therefore don't burden network. terPRE_SEQ, // Can't pay fee, no point in forwarding, therefore don't burden network.
terLAST, // Process after all other transactions terLAST, // Process after all other transactions
// 0: S Success (success) // 0: S Success (success)
// Causes: // Causes:
// - Success. // - Success.
// Implications: // Implications:
// - Applied // - Applied
// - Forwarded // - Forwarded
tesSUCCESS = 0, tesSUCCESS = 0,
// 100 .. 129 C Claim fee only (ripple transaction with no good paths, pay to non-existent account, no path) // 100 .. 129 C Claim fee only (ripple transaction with no good paths, pay to non-existent account, no path)
// Causes: // Causes:
// - Success, but does not achieve optimal result. // - Success, but does not achieve optimal result.
// - Invalid transaction or no effect, but claim fee to use the sequence number. // - Invalid transaction or no effect, but claim fee to use the sequence number.
// Implications: // Implications:
// - Applied // - Applied
// - Forwarded // - Forwarded
// Only allowed as a return code of appliedTransaction when !tapRetry. Otherwise, treated as terRETRY. // 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. // DO NOT CHANGE THESE NUMBERS: They appear in ledger meta data.
tecCLAIM = 100, tecCLAIM = 100,
tecPATH_PARTIAL = 101, tecPATH_PARTIAL = 101,
tecUNFUNDED_ADD = 102, tecUNFUNDED_ADD = 102,
tecUNFUNDED_OFFER = 103, tecUNFUNDED_OFFER = 103,
tecUNFUNDED_PAYMENT = 104, tecUNFUNDED_PAYMENT = 104,
tecFAILED_PROCESSING = 105, tecFAILED_PROCESSING = 105,
tecDIR_FULL = 121, tecDIR_FULL = 121,
tecINSUF_RESERVE_LINE = 122, tecINSUF_RESERVE_LINE = 122,
tecINSUF_RESERVE_OFFER = 123, tecINSUF_RESERVE_OFFER = 123,
tecNO_DST = 124, tecNO_DST = 124,
tecNO_DST_INSUF_XRP = 125, tecNO_DST_INSUF_XRP = 125,
tecNO_LINE_INSUF_RESERVE = 126, tecNO_LINE_INSUF_RESERVE = 126,
tecNO_LINE_REDUNDANT = 127, tecNO_LINE_REDUNDANT = 127,
tecPATH_DRY = 128, tecPATH_DRY = 128,
tecUNFUNDED = 129, // Deprecated, old ambiguous unfunded. tecUNFUNDED = 129, // Deprecated, old ambiguous unfunded.
}; };
// VFALCO TODO change these to normal functions. // VFALCO TODO change these to normal functions.
#define isTelLocal(x) ((x) >= telLOCAL_ERROR && (x) < temMALFORMED) #define isTelLocal(x) ((x) >= telLOCAL_ERROR && (x) < temMALFORMED)
#define isTemMalformed(x) ((x) >= temMALFORMED && (x) < tefFAILURE) #define isTemMalformed(x) ((x) >= temMALFORMED && (x) < tefFAILURE)
#define isTefFailure(x) ((x) >= tefFAILURE && (x) < terRETRY) #define isTefFailure(x) ((x) >= tefFAILURE && (x) < terRETRY)
#define isTerRetry(x) ((x) >= terRETRY && (x) < tesSUCCESS) #define isTerRetry(x) ((x) >= terRETRY && (x) < tesSUCCESS)
#define isTesSuccess(x) ((x) == tesSUCCESS) #define isTesSuccess(x) ((x) == tesSUCCESS)
#define isTecClaim(x) ((x) >= tecCLAIM) #define isTecClaim(x) ((x) >= tecCLAIM)
// VFALCO TODO group these into a shell class along with the defines above. // VFALCO TODO group these into a shell class along with the defines above.
extern bool transResultInfo (TER terCode, std::string& strToken, std::string& strHuman); 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; std::map<std::string, TransactionFormat*> TransactionFormat::byName;
// VFALCO TODO surely we can think of a better way than to use macros?? // VFALCO TODO surely we can think of a better way than to use macros??
#define TF_BASE \ #define TF_BASE \
<< SOElement(sfTransactionType, SOE_REQUIRED) \ << SOElement(sfTransactionType, SOE_REQUIRED) \
<< SOElement(sfFlags, SOE_OPTIONAL) \ << SOElement(sfFlags, SOE_OPTIONAL) \
<< SOElement(sfSourceTag, SOE_OPTIONAL) \ << SOElement(sfSourceTag, SOE_OPTIONAL) \
<< SOElement(sfAccount, SOE_REQUIRED) \ << SOElement(sfAccount, SOE_REQUIRED) \
<< SOElement(sfSequence, SOE_REQUIRED) \ << SOElement(sfSequence, SOE_REQUIRED) \
<< SOElement(sfPreviousTxnID, SOE_OPTIONAL) \ << SOElement(sfPreviousTxnID, SOE_OPTIONAL) \
<< SOElement(sfFee, SOE_REQUIRED) \ << SOElement(sfFee, SOE_REQUIRED) \
<< SOElement(sfOperationLimit, SOE_OPTIONAL) \ << SOElement(sfOperationLimit, SOE_OPTIONAL) \
<< SOElement(sfSigningPubKey, SOE_REQUIRED) \ << SOElement(sfSigningPubKey, SOE_REQUIRED) \
<< SOElement(sfTxnSignature, SOE_OPTIONAL) << SOElement(sfTxnSignature, SOE_OPTIONAL)
#define DECLARE_TF(name, type) tf = new TransactionFormat(#name, type); (*tf) TF_BASE #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) DECLARE_TF (AccountSet, ttACCOUNT_SET)
<< SOElement(sfEmailHash, SOE_OPTIONAL) << SOElement (sfEmailHash, SOE_OPTIONAL)
<< SOElement(sfWalletLocator, SOE_OPTIONAL) << SOElement (sfWalletLocator, SOE_OPTIONAL)
<< SOElement(sfWalletSize, SOE_OPTIONAL) << SOElement (sfWalletSize, SOE_OPTIONAL)
<< SOElement(sfMessageKey, SOE_OPTIONAL) << SOElement (sfMessageKey, SOE_OPTIONAL)
<< SOElement(sfDomain, SOE_OPTIONAL) << SOElement (sfDomain, SOE_OPTIONAL)
<< SOElement(sfTransferRate, SOE_OPTIONAL) << SOElement (sfTransferRate, SOE_OPTIONAL)
; ;
DECLARE_TF(TrustSet, ttTRUST_SET) DECLARE_TF (TrustSet, ttTRUST_SET)
<< SOElement(sfLimitAmount, SOE_OPTIONAL) << SOElement (sfLimitAmount, SOE_OPTIONAL)
<< SOElement(sfQualityIn, SOE_OPTIONAL) << SOElement (sfQualityIn, SOE_OPTIONAL)
<< SOElement(sfQualityOut, SOE_OPTIONAL) << SOElement (sfQualityOut, SOE_OPTIONAL)
; ;
DECLARE_TF(OfferCreate, ttOFFER_CREATE) DECLARE_TF (OfferCreate, ttOFFER_CREATE)
<< SOElement(sfTakerPays, SOE_REQUIRED) << SOElement (sfTakerPays, SOE_REQUIRED)
<< SOElement(sfTakerGets, SOE_REQUIRED) << SOElement (sfTakerGets, SOE_REQUIRED)
<< SOElement(sfExpiration, SOE_OPTIONAL) << SOElement (sfExpiration, SOE_OPTIONAL)
; ;
DECLARE_TF(OfferCancel, ttOFFER_CANCEL) DECLARE_TF (OfferCancel, ttOFFER_CANCEL)
<< SOElement(sfOfferSequence, SOE_REQUIRED) << SOElement (sfOfferSequence, SOE_REQUIRED)
; ;
DECLARE_TF(SetRegularKey, ttREGULAR_KEY_SET) DECLARE_TF (SetRegularKey, ttREGULAR_KEY_SET)
<< SOElement(sfRegularKey, SOE_REQUIRED) << SOElement (sfRegularKey, SOE_REQUIRED)
; ;
DECLARE_TF(Payment, ttPAYMENT) DECLARE_TF (Payment, ttPAYMENT)
<< SOElement(sfDestination, SOE_REQUIRED) << SOElement (sfDestination, SOE_REQUIRED)
<< SOElement(sfAmount, SOE_REQUIRED) << SOElement (sfAmount, SOE_REQUIRED)
<< SOElement(sfSendMax, SOE_OPTIONAL) << SOElement (sfSendMax, SOE_OPTIONAL)
<< SOElement(sfPaths, SOE_DEFAULT) << SOElement (sfPaths, SOE_DEFAULT)
<< SOElement(sfInvoiceID, SOE_OPTIONAL) << SOElement (sfInvoiceID, SOE_OPTIONAL)
<< SOElement(sfDestinationTag, SOE_OPTIONAL) << SOElement (sfDestinationTag, SOE_OPTIONAL)
; ;
DECLARE_TF(Contract, ttCONTRACT) DECLARE_TF (Contract, ttCONTRACT)
<< SOElement(sfExpiration, SOE_REQUIRED) << SOElement (sfExpiration, SOE_REQUIRED)
<< SOElement(sfBondAmount, SOE_REQUIRED) << SOElement (sfBondAmount, SOE_REQUIRED)
<< SOElement(sfStampEscrow, SOE_REQUIRED) << SOElement (sfStampEscrow, SOE_REQUIRED)
<< SOElement(sfRippleEscrow, SOE_REQUIRED) << SOElement (sfRippleEscrow, SOE_REQUIRED)
<< SOElement(sfCreateCode, SOE_OPTIONAL) << SOElement (sfCreateCode, SOE_OPTIONAL)
<< SOElement(sfFundCode, SOE_OPTIONAL) << SOElement (sfFundCode, SOE_OPTIONAL)
<< SOElement(sfRemoveCode, SOE_OPTIONAL) << SOElement (sfRemoveCode, SOE_OPTIONAL)
<< SOElement(sfExpireCode, SOE_OPTIONAL) << SOElement (sfExpireCode, SOE_OPTIONAL)
; ;
DECLARE_TF(RemoveContract, ttCONTRACT_REMOVE) DECLARE_TF (RemoveContract, ttCONTRACT_REMOVE)
<< SOElement(sfTarget, SOE_REQUIRED) << SOElement (sfTarget, SOE_REQUIRED)
; ;
DECLARE_TF(EnableFeature, ttFEATURE) DECLARE_TF (EnableFeature, ttFEATURE)
<< SOElement(sfFeature, SOE_REQUIRED) << SOElement (sfFeature, SOE_REQUIRED)
; ;
DECLARE_TF(SetFee, ttFEE) DECLARE_TF (SetFee, ttFEE)
<< SOElement(sfBaseFee, SOE_REQUIRED) << SOElement (sfBaseFee, SOE_REQUIRED)
<< SOElement(sfReferenceFeeUnits, SOE_REQUIRED) << SOElement (sfReferenceFeeUnits, SOE_REQUIRED)
<< SOElement(sfReserveBase, SOE_REQUIRED) << SOElement (sfReserveBase, SOE_REQUIRED)
<< SOElement(sfReserveIncrement, 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)); std::map<int, TransactionFormat*>::iterator it = byType.find (static_cast<int> (t));
if (it == byType.end())
return NULL; if (it == byType.end ())
return it->second; return NULL;
return it->second;
} }
TransactionFormat* TransactionFormat::getTxnFormat(int t) TransactionFormat* TransactionFormat::getTxnFormat (int t)
{ {
std::map<int, TransactionFormat*>::iterator it = byType.find((t)); std::map<int, TransactionFormat*>::iterator it = byType.find ((t));
if (it == byType.end())
return NULL; if (it == byType.end ())
return it->second; 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)); std::map<std::string, TransactionFormat*>::iterator it = byName.find ((t));
if (it == byName.end())
return NULL; if (it == byName.end ())
return it->second; return NULL;
return it->second;
} }
// vim:ts=4 // vim:ts=4

View File

@@ -3,86 +3,86 @@
enum TransactionType enum TransactionType
{ {
ttINVALID = -1, ttINVALID = -1,
ttPAYMENT = 0, ttPAYMENT = 0,
ttCLAIM = 1, // open ttCLAIM = 1, // open
ttWALLET_ADD = 2, ttWALLET_ADD = 2,
ttACCOUNT_SET = 3, ttACCOUNT_SET = 3,
ttPASSWORD_FUND = 4, // open ttPASSWORD_FUND = 4, // open
ttREGULAR_KEY_SET = 5, ttREGULAR_KEY_SET = 5,
ttNICKNAME_SET = 6, // open ttNICKNAME_SET = 6, // open
ttOFFER_CREATE = 7, ttOFFER_CREATE = 7,
ttOFFER_CANCEL = 8, ttOFFER_CANCEL = 8,
ttCONTRACT = 9, ttCONTRACT = 9,
ttCONTRACT_REMOVE = 10, // can we use the same msg as offer cancel ttCONTRACT_REMOVE = 10, // can we use the same msg as offer cancel
ttTRUST_SET = 20, ttTRUST_SET = 20,
ttFEATURE = 100, ttFEATURE = 100,
ttFEE = 101, ttFEE = 101,
}; };
class TransactionFormat class TransactionFormat
{ {
public: public:
std::string t_name; std::string t_name;
TransactionType t_type; TransactionType t_type;
SOTemplate elements; SOTemplate elements;
static std::map<int, TransactionFormat*> byType; static std::map<int, TransactionFormat*> byType;
static std::map<std::string, TransactionFormat*> byName; 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; byName[name] = this;
byType[type] = this; byType[type] = this;
} }
TransactionFormat& operator<<(const SOElement& el) TransactionFormat& operator<< (const SOElement& el)
{ {
elements.push_back(el); elements.push_back (el);
return *this; return *this;
} }
static TransactionFormat* getTxnFormat(TransactionType t); static TransactionFormat* getTxnFormat (TransactionType t);
static TransactionFormat* getTxnFormat(const std::string& t); static TransactionFormat* getTxnFormat (const std::string& t);
static TransactionFormat* getTxnFormat(int t); static TransactionFormat* getTxnFormat (int t);
}; };
const int TransactionMinLen = 32; const int TransactionMinLen = 32;
const int TransactionMaxLen = 1048576; const int TransactionMaxLen = 1048576;
// //
// Transaction flags. // Transaction flags.
// //
// AccountSet flags: // AccountSet flags:
const uint32 tfRequireDestTag = 0x00010000; const uint32 tfRequireDestTag = 0x00010000;
const uint32 tfOptionalDestTag = 0x00020000; const uint32 tfOptionalDestTag = 0x00020000;
const uint32 tfRequireAuth = 0x00040000; const uint32 tfRequireAuth = 0x00040000;
const uint32 tfOptionalAuth = 0x00080000; const uint32 tfOptionalAuth = 0x00080000;
const uint32 tfDisallowXRP = 0x00100000; const uint32 tfDisallowXRP = 0x00100000;
const uint32 tfAllowXRP = 0x00200000; const uint32 tfAllowXRP = 0x00200000;
const uint32 tfAccountSetMask = ~(tfRequireDestTag|tfOptionalDestTag const uint32 tfAccountSetMask = ~ (tfRequireDestTag | tfOptionalDestTag
|tfRequireAuth|tfOptionalAuth | tfRequireAuth | tfOptionalAuth
|tfDisallowXRP|tfAllowXRP); | tfDisallowXRP | tfAllowXRP);
// OfferCreate flags: // OfferCreate flags:
const uint32 tfPassive = 0x00010000; const uint32 tfPassive = 0x00010000;
const uint32 tfImmediateOrCancel = 0x00020000; const uint32 tfImmediateOrCancel = 0x00020000;
const uint32 tfFillOrKill = 0x00040000; const uint32 tfFillOrKill = 0x00040000;
const uint32 tfSell = 0x00080000; const uint32 tfSell = 0x00080000;
const uint32 tfOfferCreateMask = ~(tfPassive|tfImmediateOrCancel|tfFillOrKill|tfSell); const uint32 tfOfferCreateMask = ~ (tfPassive | tfImmediateOrCancel | tfFillOrKill | tfSell);
// Payment flags: // Payment flags:
const uint32 tfNoRippleDirect = 0x00010000; const uint32 tfNoRippleDirect = 0x00010000;
const uint32 tfPartialPayment = 0x00020000; const uint32 tfPartialPayment = 0x00020000;
const uint32 tfLimitQuality = 0x00040000; const uint32 tfLimitQuality = 0x00040000;
const uint32 tfPaymentMask = ~(tfPartialPayment|tfLimitQuality|tfNoRippleDirect); const uint32 tfPaymentMask = ~ (tfPartialPayment | tfLimitQuality | tfNoRippleDirect);
// TrustSet flags: // TrustSet flags:
const uint32 tfSetfAuth = 0x00010000; const uint32 tfSetfAuth = 0x00010000;
const uint32 tfTrustSetMask = ~(tfSetfAuth); const uint32 tfTrustSetMask = ~ (tfSetfAuth);
#endif #endif
// vim:ts=4 // 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 Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies. copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 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 @file ripple_data.cpp
@ingroup ripple_data @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 Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies. copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 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 @file ripple_data.h
@ingroup ripple_data @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 #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 int JSONCache::Key::compare (Key const& other) const
{ {
if (mHash < other.mHash) return -1; if (mHash < other.mHash) return -1;
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 (mOperation > other.mOperation) return 1; if (mOperation > other.mOperation) return 1;
if (mLedger < other.mLedger) return -1; if (mLedger < other.mLedger) 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;
if (mObject > other.mObject) return 1; if (mObject > other.mObject) return 1;
return 0; return 0;
} }
bool JSONCache::Key::operator< (Key const& rhs) const { return compare (rhs) < 0; } bool JSONCache::Key::operator< (Key const& rhs) const
bool JSONCache::Key::operator> (Key const& rhs) const { return compare (rhs) > 0; } {
bool JSONCache::Key::operator<= (Key const& rhs) const { return compare (rhs) <= 0; } 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
bool JSONCache::Key::operator== (Key const& rhs) const { return compare (rhs) == 0; } {
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 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 ()); 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); 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 ()); 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)); m_cache.insert (std::pair <Key, data_t> (key, data));
} }
@@ -130,15 +156,15 @@ void JSONCache::sweep ()
sweepTime -= m_expirationTime; 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 ()) while (it != m_cache.end ())
{ {
if (it->first.isExpired (sweepTime)) if (it->first.isExpired (sweepTime))
{ {
it = m_cache.erase(it); it = m_cache.erase (it);
} }
else else
{ {
@@ -153,5 +179,5 @@ void JSONCache::sweep ()
int JSONCache::getUptime () const int JSONCache::getUptime () const
{ {
return UptimeTimer::getInstance().getElapsedSeconds(); return UptimeTimer::getInstance ().getElapsedSeconds ();
} }

View File

@@ -12,13 +12,13 @@ public:
{ {
public: public:
Key (int op, const uint256& ledger, const uint160& object, int lastUse); Key (int op, const uint256& ledger, const uint160& object, int lastUse);
int compare(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;
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; void touch (Key const& key) const;
bool isExpired (int expireTime) const; bool isExpired (int expireTime) const;

View File

@@ -5,10 +5,10 @@
*/ */
struct UptimeTimerAdapter struct UptimeTimerAdapter
{ {
inline static int getElapsedSeconds () inline static int getElapsedSeconds ()
{ {
return UptimeTimer::getInstance().getElapsedSeconds (); return UptimeTimer::getInstance ().getElapsedSeconds ();
} }
}; };
#endif #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 Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies. copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 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 @file ripple_db.cpp
@ingroup ripple_db @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 Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies. copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 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 @file ripple_db.h
@ingroup ripple_db @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 #ifndef RIPPLE_DB_H

Binary file not shown.

View File

@@ -3,7 +3,8 @@
# ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION # ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION
namespace Json { namespace Json
{
/* Fast memory allocator. /* Fast memory allocator.
* *
@@ -17,100 +18,103 @@ namespace Json {
* The in-place new operator must be used to construct the object using the pointer * The in-place new operator must be used to construct the object using the pointer
* returned by allocate. * returned by allocate.
*/ */
template<typename AllocatedType template < typename AllocatedType
,const unsigned int objectPerAllocation> , const unsigned int objectPerAllocation >
class BatchAllocator class BatchAllocator
{ {
public: public:
typedef AllocatedType Type; typedef AllocatedType Type;
BatchAllocator( unsigned int objectsPerPage = 255 ) BatchAllocator ( unsigned int objectsPerPage = 255 )
: freeHead_( 0 ) : freeHead_ ( 0 )
, objectsPerPage_( objectsPerPage ) , objectsPerPage_ ( objectsPerPage )
{ {
// printf( "Size: %d => %s\n", sizeof(AllocatedType), typeid(AllocatedType).name() ); // 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 ( sizeof (AllocatedType) * objectPerAllocation >= sizeof (AllocatedType*) ); // We must be able to store a slist in the object free space.
assert( objectsPerPage >= 16 ); assert ( objectsPerPage >= 16 );
batches_ = allocateBatch( 0 ); // allocated a dummy page batches_ = allocateBatch ( 0 ); // allocated a dummy page
currentBatch_ = batches_; currentBatch_ = batches_;
} }
~BatchAllocator() ~BatchAllocator ()
{ {
for ( BatchInfo *batch = batches_; batch; ) for ( BatchInfo* batch = batches_; batch; )
{ {
BatchInfo *nextBatch = batch->next_; BatchInfo* nextBatch = batch->next_;
free( batch ); free ( batch );
batch = nextBatch; batch = nextBatch;
} }
} }
/// allocate space for an array of objectPerAllocation object. /// allocate space for an array of objectPerAllocation object.
/// @warning it is the responsability of the caller to call objects constructors. /// @warning it is the responsability of the caller to call objects constructors.
AllocatedType *allocate() AllocatedType* allocate ()
{ {
if ( freeHead_ ) // returns node from free list. if ( freeHead_ ) // returns node from free list.
{ {
AllocatedType *object = freeHead_; AllocatedType* object = freeHead_;
freeHead_ = *(AllocatedType **)object; freeHead_ = * (AllocatedType**)object;
return object; return object;
} }
if ( currentBatch_->used_ == currentBatch_->end_ )
{ if ( currentBatch_->used_ == currentBatch_->end_ )
currentBatch_ = currentBatch_->next_; {
while ( currentBatch_ && currentBatch_->used_ == currentBatch_->end_ )
currentBatch_ = currentBatch_->next_; currentBatch_ = currentBatch_->next_;
if ( !currentBatch_ ) // no free batch found, allocate a new one while ( currentBatch_ && currentBatch_->used_ == currentBatch_->end_ )
{ currentBatch_ = currentBatch_->next_;
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. if ( !currentBatch_ ) // no free batch found, allocate a new one
/// @warning it is the responsability of the caller to actually destruct the object. {
void release( AllocatedType *object ) currentBatch_ = allocateBatch ( objectsPerPage_ );
{ currentBatch_->next_ = batches_; // insert at the head of the list
assert( object != 0 ); batches_ = currentBatch_;
*(AllocatedType **)object = freeHead_; }
freeHead_ = object; }
}
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: private:
struct BatchInfo struct BatchInfo
{ {
BatchInfo *next_; BatchInfo* next_;
AllocatedType *used_; AllocatedType* used_;
AllocatedType *end_; AllocatedType* end_;
AllocatedType buffer_[objectPerAllocation]; AllocatedType buffer_[objectPerAllocation];
}; };
// disabled copy constructor and assignement operator. // disabled copy constructor and assignement operator.
BatchAllocator( const BatchAllocator & ); BatchAllocator ( const BatchAllocator& );
void operator =( const BatchAllocator &); void operator = ( const BatchAllocator&);
static BatchInfo *allocateBatch( unsigned int objectsPerPage ) static BatchInfo* allocateBatch ( unsigned int objectsPerPage )
{ {
const unsigned int mallocSize = sizeof(BatchInfo) - sizeof(AllocatedType)* objectPerAllocation const unsigned int mallocSize = sizeof (BatchInfo) - sizeof (AllocatedType) * objectPerAllocation
+ sizeof(AllocatedType) * objectPerAllocation * objectsPerPage; + sizeof (AllocatedType) * objectPerAllocation * objectsPerPage;
BatchInfo *batch = static_cast<BatchInfo*>( malloc( mallocSize ) ); BatchInfo* batch = static_cast<BatchInfo*> ( malloc ( mallocSize ) );
batch->next_ = 0; batch->next_ = 0;
batch->used_ = batch->buffer_; batch->used_ = batch->buffer_;
batch->end_ = batch->buffer_ + objectsPerPage; batch->end_ = batch->buffer_ + objectsPerPage;
return batch; return batch;
} }
BatchInfo *batches_; BatchInfo* batches_;
BatchInfo *currentBatch_; BatchInfo* currentBatch_;
/// Head of a single linked list within the allocated space of freeed object /// Head of a single linked list within the allocated space of freeed object
AllocatedType *freeHead_; AllocatedType* freeHead_;
unsigned int objectsPerPage_; unsigned int objectsPerPage_;
}; };

View File

@@ -1,39 +1,40 @@
#ifndef CPPTL_JSON_FEATURES_H_INCLUDED #ifndef CPPTL_JSON_FEATURES_H_INCLUDED
#define CPPTL_JSON_FEATURES_H_INCLUDED #define CPPTL_JSON_FEATURES_H_INCLUDED
namespace Json { namespace Json
{
/** \brief Configuration passed to reader and writer. /** \brief Configuration passed to reader and writer.
* This configuration object can be used to force the Reader or Writer * This configuration object can be used to force the Reader or Writer
* to behave in a standard conforming way. * to behave in a standard conforming way.
*/ */
class JSON_API Features class JSON_API Features
{ {
public: public:
/** \brief A configuration that allows all features and assumes all strings are UTF-8. /** \brief A configuration that allows all features and assumes all strings are UTF-8.
* - C & C++ comments are allowed * - C & C++ comments are allowed
* - Root object can be any JSON value * - Root object can be any JSON value
* - Assumes Value strings are encoded in UTF-8 * - Assumes Value strings are encoded in UTF-8
*/ */
static Features all(); static Features all ();
/** \brief A configuration that is strictly compatible with the JSON specification. /** \brief A configuration that is strictly compatible with the JSON specification.
* - Comments are forbidden. * - Comments are forbidden.
* - Root object must be either an array or an object value. * - Root object must be either an array or an object value.
* - Assumes Value strings are encoded in UTF-8 * - Assumes Value strings are encoded in UTF-8
*/ */
static Features strictMode(); static Features strictMode ();
/** \brief Initialize the configuration like JsonConfig::allFeatures; /** \brief Initialize the configuration like JsonConfig::allFeatures;
*/ */
Features(); Features ();
/// \c true if comments are allowed. Default: \c true. /// \c true if comments are allowed. Default: \c true.
bool allowComments_; bool allowComments_;
/// \c true if root must be either an array or an object value. Default: \c false. /// \c true if root must be either an array or an object value. Default: \c false.
bool strictRoot_; bool strictRoot_;
}; };
} // namespace Json } // namespace Json

View File

@@ -1,34 +1,35 @@
#ifndef JSON_FORWARDS_H_INCLUDED #ifndef JSON_FORWARDS_H_INCLUDED
#define JSON_FORWARDS_H_INCLUDED #define JSON_FORWARDS_H_INCLUDED
namespace Json { namespace Json
{
// writer.h // writer.h
class FastWriter; class FastWriter;
class StyledWriter; class StyledWriter;
// reader.h // reader.h
class Reader; class Reader;
// features.h // features.h
class Features; class Features;
// value.h // value.h
typedef int Int; typedef int Int;
typedef unsigned int UInt; typedef unsigned int UInt;
class StaticString; class StaticString;
class Path; class Path;
class PathArgument; class PathArgument;
class Value; class Value;
class ValueIteratorBase; class ValueIteratorBase;
class ValueIterator; class ValueIterator;
class ValueConstIterator; class ValueConstIterator;
#ifdef JSON_VALUE_USE_INTERNAL_MAP #ifdef JSON_VALUE_USE_INTERNAL_MAP
class ValueAllocator; class ValueAllocator;
class ValueMapAllocator; class ValueMapAllocator;
class ValueInternalLink; class ValueInternalLink;
class ValueInternalArray; class ValueInternalArray;
class ValueInternalMap; class ValueInternalMap;
#endif // #ifdef JSON_VALUE_USE_INTERNAL_MAP #endif // #ifdef JSON_VALUE_USE_INTERNAL_MAP
} // namespace Json } // namespace Json

View File

@@ -9,7 +9,7 @@
// ////////////////////////////////////////////////////////////////// // //////////////////////////////////////////////////////////////////
// ////////////////////////////////////////////////////////////////// // //////////////////////////////////////////////////////////////////
ValueArrayAllocator::~ValueArrayAllocator() ValueArrayAllocator::~ValueArrayAllocator ()
{ {
} }
@@ -20,55 +20,59 @@ ValueArrayAllocator::~ValueArrayAllocator()
class DefaultValueArrayAllocator : public ValueArrayAllocator class DefaultValueArrayAllocator : public ValueArrayAllocator
{ {
public: // overridden from ValueArrayAllocator public: // overridden from ValueArrayAllocator
virtual ~DefaultValueArrayAllocator() virtual ~DefaultValueArrayAllocator ()
{ {
} }
virtual ValueInternalArray *newArray() virtual ValueInternalArray* newArray ()
{ {
return new ValueInternalArray(); return new ValueInternalArray ();
} }
virtual ValueInternalArray *newArrayCopy( const ValueInternalArray &other ) virtual ValueInternalArray* newArrayCopy ( const ValueInternalArray& other )
{ {
return new ValueInternalArray( other ); return new ValueInternalArray ( other );
} }
virtual void destructArray( ValueInternalArray *array ) virtual void destructArray ( ValueInternalArray* array )
{ {
delete array; delete array;
} }
virtual void reallocateArrayPageIndex( Value **&indexes, virtual void reallocateArrayPageIndex ( Value**& indexes,
ValueInternalArray::PageIndex &indexCount, ValueInternalArray::PageIndex& indexCount,
ValueInternalArray::PageIndex minNewIndexCount ) ValueInternalArray::PageIndex minNewIndexCount )
{ {
ValueInternalArray::PageIndex newIndexCount = (indexCount*3)/2 + 1; 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 Value *allocateArrayPage() if ( minNewIndexCount > newIndexCount )
{ newIndexCount = minNewIndexCount;
return static_cast<Value *>( malloc( sizeof(Value) * ValueInternalArray::itemsPerPage ) );
}
virtual void releaseArrayPage( Value *value ) void* newIndexes = realloc ( indexes, sizeof (Value*) * newIndexCount );
{
if ( value ) if ( !newIndexes )
free( value ); 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 #else // #ifdef JSON_USE_SIMPLE_INTERNAL_ALLOCATOR
@@ -76,373 +80,399 @@ public: // overridden from ValueArrayAllocator
class DefaultValueArrayAllocator : public ValueArrayAllocator class DefaultValueArrayAllocator : public ValueArrayAllocator
{ {
public: // overridden from ValueArrayAllocator public: // overridden from ValueArrayAllocator
virtual ~DefaultValueArrayAllocator() virtual ~DefaultValueArrayAllocator ()
{ {
} }
virtual ValueInternalArray *newArray() virtual ValueInternalArray* newArray ()
{ {
ValueInternalArray *array = arraysAllocator_.allocate(); ValueInternalArray* array = arraysAllocator_.allocate ();
new (array) ValueInternalArray(); // placement new new (array) ValueInternalArray (); // placement new
return array; return array;
} }
virtual ValueInternalArray *newArrayCopy( const ValueInternalArray &other ) virtual ValueInternalArray* newArrayCopy ( const ValueInternalArray& other )
{ {
ValueInternalArray *array = arraysAllocator_.allocate(); ValueInternalArray* array = arraysAllocator_.allocate ();
new (array) ValueInternalArray( other ); // placement new new (array) ValueInternalArray ( other ); // placement new
return array; return array;
} }
virtual void destructArray( ValueInternalArray *array ) virtual void destructArray ( ValueInternalArray* array )
{ {
if ( array ) if ( array )
{ {
array->~ValueInternalArray(); array->~ValueInternalArray ();
arraysAllocator_.release( array ); arraysAllocator_.release ( array );
} }
} }
virtual void reallocateArrayPageIndex( Value **&indexes, virtual void reallocateArrayPageIndex ( Value**& indexes,
ValueInternalArray::PageIndex &indexCount, ValueInternalArray::PageIndex& indexCount,
ValueInternalArray::PageIndex minNewIndexCount ) ValueInternalArray::PageIndex minNewIndexCount )
{ {
ValueInternalArray::PageIndex newIndexCount = (indexCount*3)/2 + 1; 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 Value *allocateArrayPage() if ( minNewIndexCount > newIndexCount )
{ newIndexCount = minNewIndexCount;
return static_cast<Value *>( pagesAllocator_.allocate() );
}
virtual void releaseArrayPage( Value *value ) void* newIndexes = realloc ( indexes, sizeof (Value*) * newIndexCount );
{
if ( value ) if ( !newIndexes )
pagesAllocator_.release( value ); 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: private:
BatchAllocator<ValueInternalArray,1> arraysAllocator_; BatchAllocator<ValueInternalArray, 1> arraysAllocator_;
BatchAllocator<Value,ValueInternalArray::itemsPerPage> pagesAllocator_; BatchAllocator<Value, ValueInternalArray::itemsPerPage> pagesAllocator_;
}; };
#endif // #ifdef JSON_USE_SIMPLE_INTERNAL_ALLOCATOR #endif // #ifdef JSON_USE_SIMPLE_INTERNAL_ALLOCATOR
static ValueArrayAllocator *&arrayAllocator() static ValueArrayAllocator*& arrayAllocator ()
{ {
static DefaultValueArrayAllocator defaultAllocator; static DefaultValueArrayAllocator defaultAllocator;
static ValueArrayAllocator *arrayAllocator = &defaultAllocator; static ValueArrayAllocator* arrayAllocator = &defaultAllocator;
return arrayAllocator; return arrayAllocator;
} }
static struct DummyArrayAllocatorInitializer { static struct DummyArrayAllocatorInitializer
DummyArrayAllocatorInitializer() {
{ DummyArrayAllocatorInitializer ()
arrayAllocator(); // ensure arrayAllocator() statics are initialized before main(). {
} arrayAllocator (); // ensure arrayAllocator() statics are initialized before main().
}
} dummyArrayAllocatorInitializer; } dummyArrayAllocatorInitializer;
// ////////////////////////////////////////////////////////////////// // //////////////////////////////////////////////////////////////////
// class ValueInternalArray // class ValueInternalArray
// ////////////////////////////////////////////////////////////////// // //////////////////////////////////////////////////////////////////
bool bool
ValueInternalArray::equals( const IteratorState &x, ValueInternalArray::equals ( const IteratorState& x,
const IteratorState &other ) const IteratorState& other )
{ {
return x.array_ == other.array_ return x.array_ == other.array_
&& x.currentItemIndex_ == other.currentItemIndex_ && x.currentItemIndex_ == other.currentItemIndex_
&& x.currentPageIndex_ == other.currentPageIndex_; && x.currentPageIndex_ == other.currentPageIndex_;
} }
void void
ValueInternalArray::increment( IteratorState &it ) ValueInternalArray::increment ( IteratorState& it )
{ {
JSON_ASSERT_MESSAGE( it.array_ && JSON_ASSERT_MESSAGE ( it.array_ &&
(it.currentPageIndex_ - it.array_->pages_)*itemsPerPage + it.currentItemIndex_ (it.currentPageIndex_ - it.array_->pages_)*itemsPerPage + it.currentItemIndex_
!= it.array_->size_, != it.array_->size_,
"ValueInternalArray::increment(): moving iterator beyond end" ); "ValueInternalArray::increment(): moving iterator beyond end" );
++(it.currentItemIndex_); ++ (it.currentItemIndex_);
if ( it.currentItemIndex_ == itemsPerPage )
{ if ( it.currentItemIndex_ == itemsPerPage )
it.currentItemIndex_ = 0; {
++(it.currentPageIndex_); it.currentItemIndex_ = 0;
} ++ (it.currentPageIndex_);
}
} }
void void
ValueInternalArray::decrement( IteratorState &it ) ValueInternalArray::decrement ( IteratorState& it )
{ {
JSON_ASSERT_MESSAGE( it.array_ && it.currentPageIndex_ == it.array_->pages_ JSON_ASSERT_MESSAGE ( it.array_ && it.currentPageIndex_ == it.array_->pages_
&& it.currentItemIndex_ == 0, && it.currentItemIndex_ == 0,
"ValueInternalArray::decrement(): moving iterator beyond end" ); "ValueInternalArray::decrement(): moving iterator beyond end" );
if ( it.currentItemIndex_ == 0 )
{ if ( it.currentItemIndex_ == 0 )
it.currentItemIndex_ = itemsPerPage-1; {
--(it.currentPageIndex_); it.currentItemIndex_ = itemsPerPage - 1;
} -- (it.currentPageIndex_);
else }
{ else
--(it.currentItemIndex_); {
} -- (it.currentItemIndex_);
}
} }
Value & Value&
ValueInternalArray::unsafeDereference( const IteratorState &it ) ValueInternalArray::unsafeDereference ( const IteratorState& it )
{ {
return (*(it.currentPageIndex_))[it.currentItemIndex_]; return (* (it.currentPageIndex_))[it.currentItemIndex_];
} }
Value & Value&
ValueInternalArray::dereference( const IteratorState &it ) ValueInternalArray::dereference ( const IteratorState& it )
{ {
JSON_ASSERT_MESSAGE( it.array_ && JSON_ASSERT_MESSAGE ( it.array_ &&
(it.currentPageIndex_ - it.array_->pages_)*itemsPerPage + it.currentItemIndex_ (it.currentPageIndex_ - it.array_->pages_)*itemsPerPage + it.currentItemIndex_
< it.array_->size_, < it.array_->size_,
"ValueInternalArray::dereference(): dereferencing invalid iterator" ); "ValueInternalArray::dereference(): dereferencing invalid iterator" );
return unsafeDereference( it ); return unsafeDereference ( it );
} }
void void
ValueInternalArray::makeBeginIterator( IteratorState &it ) const ValueInternalArray::makeBeginIterator ( IteratorState& it ) const
{ {
it.array_ = const_cast<ValueInternalArray *>( this ); it.array_ = const_cast<ValueInternalArray*> ( this );
it.currentItemIndex_ = 0; it.currentItemIndex_ = 0;
it.currentPageIndex_ = pages_; it.currentPageIndex_ = pages_;
} }
void void
ValueInternalArray::makeIterator( IteratorState &it, ArrayIndex index ) const ValueInternalArray::makeIterator ( IteratorState& it, ArrayIndex index ) const
{ {
it.array_ = const_cast<ValueInternalArray *>( this ); it.array_ = const_cast<ValueInternalArray*> ( this );
it.currentItemIndex_ = index % itemsPerPage; it.currentItemIndex_ = index % itemsPerPage;
it.currentPageIndex_ = pages_ + index / itemsPerPage; it.currentPageIndex_ = pages_ + index / itemsPerPage;
} }
void void
ValueInternalArray::makeEndIterator( IteratorState &it ) const ValueInternalArray::makeEndIterator ( IteratorState& it ) const
{ {
makeIterator( it, size_ ); makeIterator ( it, size_ );
} }
ValueInternalArray::ValueInternalArray() ValueInternalArray::ValueInternalArray ()
: pages_( 0 ) : pages_ ( 0 )
, size_( 0 ) , size_ ( 0 )
, pageCount_( 0 ) , pageCount_ ( 0 )
{ {
} }
ValueInternalArray::ValueInternalArray( const ValueInternalArray &other ) ValueInternalArray::ValueInternalArray ( const ValueInternalArray& other )
: pages_( 0 ) : pages_ ( 0 )
, pageCount_( 0 ) , pageCount_ ( 0 )
, size_( other.size_ ) , size_ ( other.size_ )
{ {
PageIndex minNewPages = other.size_ / itemsPerPage; PageIndex minNewPages = other.size_ / itemsPerPage;
arrayAllocator()->reallocateArrayPageIndex( pages_, pageCount_, minNewPages ); arrayAllocator ()->reallocateArrayPageIndex ( pages_, pageCount_, minNewPages );
JSON_ASSERT_MESSAGE( pageCount_ >= minNewPages, JSON_ASSERT_MESSAGE ( pageCount_ >= minNewPages,
"ValueInternalArray::reserve(): bad reallocation" ); "ValueInternalArray::reserve(): bad reallocation" );
IteratorState itOther; IteratorState itOther;
other.makeBeginIterator( itOther ); other.makeBeginIterator ( itOther );
Value *value; Value* value;
for ( ArrayIndex index = 0; index < size_; ++index, increment(itOther) )
{ for ( ArrayIndex index = 0; index < size_; ++index, increment (itOther) )
if ( index % itemsPerPage == 0 ) {
{ if ( index % itemsPerPage == 0 )
PageIndex pageIndex = index / itemsPerPage; {
value = arrayAllocator()->allocateArrayPage(); PageIndex pageIndex = index / itemsPerPage;
pages_[pageIndex] = value; value = arrayAllocator ()->allocateArrayPage ();
} pages_[pageIndex] = value;
new (value) Value( dereference( itOther ) ); }
}
new (value) Value ( dereference ( itOther ) );
}
} }
ValueInternalArray & ValueInternalArray&
ValueInternalArray::operator =( const ValueInternalArray &other ) ValueInternalArray::operator = ( const ValueInternalArray& other )
{ {
ValueInternalArray temp( other ); ValueInternalArray temp ( other );
swap( temp ); swap ( temp );
return *this; return *this;
} }
ValueInternalArray::~ValueInternalArray() ValueInternalArray::~ValueInternalArray ()
{ {
// destroy all constructed items // destroy all constructed items
IteratorState it; IteratorState it;
IteratorState itEnd; IteratorState itEnd;
makeBeginIterator( it); makeBeginIterator ( it);
makeEndIterator( itEnd ); makeEndIterator ( itEnd );
for ( ; !equals(it,itEnd); increment(it) )
{ for ( ; !equals (it, itEnd); increment (it) )
Value *value = &dereference(it); {
value->~Value(); Value* value = &dereference (it);
} value->~Value ();
// release all pages }
PageIndex lastPageIndex = size_ / itemsPerPage;
for ( PageIndex pageIndex = 0; pageIndex < lastPageIndex; ++pageIndex ) // release all pages
arrayAllocator()->releaseArrayPage( pages_[pageIndex] ); PageIndex lastPageIndex = size_ / itemsPerPage;
// release pages index
arrayAllocator()->releaseArrayPageIndex( pages_, pageCount_ ); for ( PageIndex pageIndex = 0; pageIndex < lastPageIndex; ++pageIndex )
arrayAllocator ()->releaseArrayPage ( pages_[pageIndex] );
// release pages index
arrayAllocator ()->releaseArrayPageIndex ( pages_, pageCount_ );
} }
void void
ValueInternalArray::swap( ValueInternalArray &other ) ValueInternalArray::swap ( ValueInternalArray& other )
{ {
Value **tempPages = pages_; Value** tempPages = pages_;
pages_ = other.pages_; pages_ = other.pages_;
other.pages_ = tempPages; other.pages_ = tempPages;
ArrayIndex tempSize = size_; ArrayIndex tempSize = size_;
size_ = other.size_; size_ = other.size_;
other.size_ = tempSize; other.size_ = tempSize;
PageIndex tempPageCount = pageCount_; PageIndex tempPageCount = pageCount_;
pageCount_ = other.pageCount_; pageCount_ = other.pageCount_;
other.pageCount_ = tempPageCount; other.pageCount_ = tempPageCount;
} }
void void
ValueInternalArray::clear() ValueInternalArray::clear ()
{ {
ValueInternalArray dummy; ValueInternalArray dummy;
swap( dummy ); swap ( dummy );
} }
void void
ValueInternalArray::resize( ArrayIndex newSize ) ValueInternalArray::resize ( ArrayIndex newSize )
{ {
if ( newSize == 0 ) if ( newSize == 0 )
clear(); clear ();
else if ( newSize < size_ ) else if ( newSize < size_ )
{ {
IteratorState it; IteratorState it;
IteratorState itEnd; IteratorState itEnd;
makeIterator( it, newSize ); makeIterator ( it, newSize );
makeIterator( itEnd, size_ ); makeIterator ( itEnd, size_ );
for ( ; !equals(it,itEnd); increment(it) )
{ for ( ; !equals (it, itEnd); increment (it) )
Value *value = &dereference(it); {
value->~Value(); Value* value = &dereference (it);
} value->~Value ();
PageIndex pageIndex = (newSize + itemsPerPage - 1) / itemsPerPage; }
PageIndex lastPageIndex = size_ / itemsPerPage;
for ( ; pageIndex < lastPageIndex; ++pageIndex ) PageIndex pageIndex = (newSize + itemsPerPage - 1) / itemsPerPage;
arrayAllocator()->releaseArrayPage( pages_[pageIndex] ); PageIndex lastPageIndex = size_ / itemsPerPage;
size_ = newSize;
} for ( ; pageIndex < lastPageIndex; ++pageIndex )
else if ( newSize > size_ ) arrayAllocator ()->releaseArrayPage ( pages_[pageIndex] );
resolveReference( newSize );
size_ = newSize;
}
else if ( newSize > size_ )
resolveReference ( newSize );
} }
void void
ValueInternalArray::makeIndexValid( ArrayIndex index ) ValueInternalArray::makeIndexValid ( ArrayIndex index )
{ {
// Need to enlarge page index ? // Need to enlarge page index ?
if ( index >= pageCount_ * itemsPerPage ) if ( index >= pageCount_ * itemsPerPage )
{ {
PageIndex minNewPages = (index + 1) / itemsPerPage; PageIndex minNewPages = (index + 1) / itemsPerPage;
arrayAllocator()->reallocateArrayPageIndex( pages_, pageCount_, minNewPages ); arrayAllocator ()->reallocateArrayPageIndex ( pages_, pageCount_, minNewPages );
JSON_ASSERT_MESSAGE( pageCount_ >= minNewPages, "ValueInternalArray::reserve(): bad reallocation" ); JSON_ASSERT_MESSAGE ( pageCount_ >= minNewPages, "ValueInternalArray::reserve(): bad reallocation" );
} }
// Need to allocate new pages ? // Need to allocate new pages ?
ArrayIndex nextPageIndex = ArrayIndex nextPageIndex =
(size_ % itemsPerPage) != 0 ? size_ - (size_%itemsPerPage) + itemsPerPage (size_ % itemsPerPage) != 0 ? size_ - (size_ % itemsPerPage) + itemsPerPage
: size_; : size_;
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 if ( nextPageIndex <= index )
IteratorState it; {
IteratorState itEnd; PageIndex pageIndex = nextPageIndex / itemsPerPage;
makeIterator( it, size_ ); PageIndex pageToAllocate = (index - nextPageIndex) / itemsPerPage + 1;
size_ = index + 1;
makeIterator( itEnd, size_ ); for ( ; pageToAllocate-- > 0; ++pageIndex )
for ( ; !equals(it,itEnd); increment(it) ) pages_[pageIndex] = arrayAllocator ()->allocateArrayPage ();
{ }
Value *value = &dereference(it);
new (value) Value(); // Construct a default value using placement new // 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 & Value&
ValueInternalArray::resolveReference( ArrayIndex index ) ValueInternalArray::resolveReference ( ArrayIndex index )
{ {
if ( index >= size_ ) if ( index >= size_ )
makeIndexValid( index ); makeIndexValid ( index );
return pages_[index/itemsPerPage][index%itemsPerPage];
return pages_[index / itemsPerPage][index % itemsPerPage];
} }
Value * Value*
ValueInternalArray::find( ArrayIndex index ) const ValueInternalArray::find ( ArrayIndex index ) const
{ {
if ( index >= size_ ) if ( index >= size_ )
return 0; return 0;
return &(pages_[index/itemsPerPage][index%itemsPerPage]);
return & (pages_[index / itemsPerPage][index % itemsPerPage]);
} }
ValueInternalArray::ArrayIndex ValueInternalArray::ArrayIndex
ValueInternalArray::size() const ValueInternalArray::size () const
{ {
return size_; return size_;
} }
int 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::ArrayIndex
ValueInternalArray::indexOf( const IteratorState &iterator ) ValueInternalArray::indexOf ( const IteratorState& iterator )
{ {
if ( !iterator.array_ ) if ( !iterator.array_ )
return ArrayIndex(-1); return ArrayIndex (-1);
return ArrayIndex(
(iterator.currentPageIndex_ - iterator.array_->pages_) * itemsPerPage return ArrayIndex (
+ iterator.currentItemIndex_ ); (iterator.currentPageIndex_ - iterator.array_->pages_) * itemsPerPage
+ iterator.currentItemIndex_ );
} }
int int
ValueInternalArray::compare( const ValueInternalArray &other ) const ValueInternalArray::compare ( const ValueInternalArray& other ) const
{ {
int sizeDiff( size_ - other.size_ ); int sizeDiff ( size_ - other.size_ );
if ( sizeDiff != 0 )
return sizeDiff;
for ( ArrayIndex index =0; index < size_; ++index ) if ( sizeDiff != 0 )
{ return sizeDiff;
int diff = pages_[index/itemsPerPage][index%itemsPerPage].compare(
other.pages_[index/itemsPerPage][index%itemsPerPage] ); for ( ArrayIndex index = 0; index < size_; ++index )
if ( diff != 0 ) {
return diff; int diff = pages_[index / itemsPerPage][index % itemsPerPage].compare (
} other.pages_[index / itemsPerPage][index % itemsPerPage] );
return 0;
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 #ifndef CPPTL_JSON_READER_H_INCLUDED
# define 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. /** \brief Unserialize a <a HREF="http://www.json.org">JSON</a> document into a Value.
* *
*/ */
class JSON_API Reader class JSON_API Reader
{ {
public: public:
typedef char Char; typedef char Char;
typedef const Char *Location; typedef const Char* Location;
/** \brief Constructs a Reader allowing all features /** \brief Constructs a Reader allowing all features
* for parsing. * for parsing.
*/ */
Reader(); Reader ();
/** \brief Constructs a Reader allowing the specified feature set /** \brief Constructs a Reader allowing the specified feature set
* for parsing. * for parsing.
*/ */
Reader( const Features &features ); Reader ( const Features& features );
/** \brief Read a Value from a <a HREF="http://www.json.org">JSON</a> document. /** \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 document UTF-8 encoded string containing the document to read.
* \param root [out] Contains the root value of the document if it was * \param root [out] Contains the root value of the document if it was
* successfully parsed. * successfully parsed.
* \param collectComments \c true to collect comment and allow writing them back during * \param collectComments \c true to collect comment and allow writing them back during
* serialization, \c false to discard comments. * serialization, \c false to discard comments.
* This parameter is ignored if Features::allowComments_ * This parameter is ignored if Features::allowComments_
* is \c false. * is \c false.
* \return \c true if the document was successfully parsed, \c false if an error occurred. * \return \c true if the document was successfully parsed, \c false if an error occurred.
*/ */
bool parse( const std::string &document, bool parse ( const std::string& document,
Value &root, Value& root,
bool collectComments = true ); bool collectComments = true );
/** \brief Read a Value from a <a HREF="http://www.json.org">JSON</a> document. /** \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 document UTF-8 encoded string containing the document to read.
* \param root [out] Contains the root value of the document if it was * \param root [out] Contains the root value of the document if it was
* successfully parsed. * successfully parsed.
* \param collectComments \c true to collect comment and allow writing them back during * \param collectComments \c true to collect comment and allow writing them back during
* serialization, \c false to discard comments. * serialization, \c false to discard comments.
* This parameter is ignored if Features::allowComments_ * This parameter is ignored if Features::allowComments_
* is \c false. * is \c false.
* \return \c true if the document was successfully parsed, \c false if an error occurred. * \return \c true if the document was successfully parsed, \c false if an error occurred.
*/ */
bool parse( const char *beginDoc, const char *endDoc, bool parse ( const char* beginDoc, const char* endDoc,
Value &root, Value& root,
bool collectComments = true ); bool collectComments = true );
/// \brief Parse from input stream. /// \brief Parse from input stream.
/// \see Json::operator>>(std::istream&, Json::Value&). /// \see Json::operator>>(std::istream&, Json::Value&).
bool parse( std::istream &is, bool parse ( std::istream& is,
Value &root, Value& root,
bool collectComments = true ); bool collectComments = true );
/** \brief Returns a user friendly string that list errors in the parsed document. /** \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 * \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 * the parsed document. An empty string is returned if no error occurred
* during parsing. * during parsing.
*/ */
std::string getFormatedErrorMessages() const; std::string getFormatedErrorMessages () const;
private: private:
enum TokenType 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
{ {
"dir": { tokenEndOfStream = 0,
"file": { tokenObjectBegin,
// The input stream JSON would be nested here. 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<<() \endverbatim
*/ \throw std::exception on parse error.
std::istream& operator>>( std::istream&, Value& ); \see Json::operator<<()
*/
std::istream& operator>> ( std::istream&, Value& );
} // namespace Json } // 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 #ifndef JSON_VALUE_USE_INTERNAL_MAP
: current_() : current_ ()
, isNull_( true ) , isNull_ ( true )
{ {
} }
#else #else
: isArray_( true ) :
, isNull_( true ) isArray_ ( true )
, isNull_ ( true )
{ {
iterator_.array_ = ValueInternalArray::IteratorState(); iterator_.array_ = ValueInternalArray::IteratorState ();
} }
#endif #endif
#ifndef JSON_VALUE_USE_INTERNAL_MAP #ifndef JSON_VALUE_USE_INTERNAL_MAP
ValueIteratorBase::ValueIteratorBase( const Value::ObjectValues::iterator &current ) ValueIteratorBase::ValueIteratorBase ( const Value::ObjectValues::iterator& current )
: current_( current ) : current_ ( current )
, isNull_( false ) , isNull_ ( false )
{ {
} }
#else #else
ValueIteratorBase::ValueIteratorBase( const ValueInternalArray::IteratorState &state ) ValueIteratorBase::ValueIteratorBase ( const ValueInternalArray::IteratorState& state )
: isArray_( true ) : isArray_ ( true )
{ {
iterator_.array_ = state; iterator_.array_ = state;
} }
ValueIteratorBase::ValueIteratorBase( const ValueInternalMap::IteratorState &state ) ValueIteratorBase::ValueIteratorBase ( const ValueInternalMap::IteratorState& state )
: isArray_( false ) : isArray_ ( false )
{ {
iterator_.map_ = state; iterator_.map_ = state;
} }
#endif #endif
Value & Value&
ValueIteratorBase::deref() const ValueIteratorBase::deref () const
{ {
#ifndef JSON_VALUE_USE_INTERNAL_MAP #ifndef JSON_VALUE_USE_INTERNAL_MAP
return current_->second; return current_->second;
#else #else
if ( isArray_ )
return ValueInternalArray::dereference( iterator_.array_ ); if ( isArray_ )
return ValueInternalMap::value( iterator_.map_ ); return ValueInternalArray::dereference ( iterator_.array_ );
return ValueInternalMap::value ( iterator_.map_ );
#endif #endif
} }
void void
ValueIteratorBase::increment() ValueIteratorBase::increment ()
{ {
#ifndef JSON_VALUE_USE_INTERNAL_MAP #ifndef JSON_VALUE_USE_INTERNAL_MAP
++current_; ++current_;
#else #else
if ( isArray_ )
ValueInternalArray::increment( iterator_.array_ ); if ( isArray_ )
ValueInternalMap::increment( iterator_.map_ ); ValueInternalArray::increment ( iterator_.array_ );
ValueInternalMap::increment ( iterator_.map_ );
#endif #endif
} }
void void
ValueIteratorBase::decrement() ValueIteratorBase::decrement ()
{ {
#ifndef JSON_VALUE_USE_INTERNAL_MAP #ifndef JSON_VALUE_USE_INTERNAL_MAP
--current_; --current_;
#else #else
if ( isArray_ )
ValueInternalArray::decrement( iterator_.array_ ); if ( isArray_ )
ValueInternalMap::decrement( iterator_.map_ ); ValueInternalArray::decrement ( iterator_.array_ );
ValueInternalMap::decrement ( iterator_.map_ );
#endif #endif
} }
ValueIteratorBase::difference_type ValueIteratorBase::difference_type
ValueIteratorBase::computeDistance( const SelfType &other ) const ValueIteratorBase::computeDistance ( const SelfType& other ) const
{ {
#ifndef JSON_VALUE_USE_INTERNAL_MAP #ifndef JSON_VALUE_USE_INTERNAL_MAP
# ifdef JSON_USE_CPPTL_SMALLMAP # ifdef JSON_USE_CPPTL_SMALLMAP
return current_ - other.current_; return current_ - other.current_;
# else # else
// Iterator for null value are initialized using the default
// constructor, which initialize current_ to the default // Iterator for null value are initialized using the default
// std::map::iterator. As begin() and end() are two instance // constructor, which initialize current_ to the default
// of the default std::map::iterator, they can not be compared. // std::map::iterator. As begin() and end() are two instance
// To allow this, we handle this comparison specifically. // of the default std::map::iterator, they can not be compared.
if ( isNull_ && other.isNull_ ) // To allow this, we handle this comparison specifically.
{ if ( isNull_ && other.isNull_ )
return 0; {
} return 0;
}
// Usage of std::distance is not portable (does not compile with Sun Studio 12 RogueWave STL, // Usage of std::distance is not portable (does not compile with Sun Studio 12 RogueWave STL,
// which is the one used by default). // which is the one used by default).
// Using a portable hand-made version for non random iterator instead: // Using a portable hand-made version for non random iterator instead:
// return difference_type( std::distance( current_, other.current_ ) ); // return difference_type( std::distance( current_, other.current_ ) );
difference_type myDistance = 0; difference_type myDistance = 0;
for ( Value::ObjectValues::iterator it = current_; it != other.current_; ++it )
{ for ( Value::ObjectValues::iterator it = current_; it != other.current_; ++it )
++myDistance; {
} ++myDistance;
return myDistance; }
return myDistance;
# endif # endif
#else #else
if ( isArray_ )
return ValueInternalArray::distance( iterator_.array_, other.iterator_.array_ ); if ( isArray_ )
return ValueInternalMap::distance( iterator_.map_, other.iterator_.map_ ); return ValueInternalArray::distance ( iterator_.array_, other.iterator_.array_ );
return ValueInternalMap::distance ( iterator_.map_, other.iterator_.map_ );
#endif #endif
} }
bool bool
ValueIteratorBase::isEqual( const SelfType &other ) const ValueIteratorBase::isEqual ( const SelfType& other ) const
{ {
#ifndef JSON_VALUE_USE_INTERNAL_MAP #ifndef JSON_VALUE_USE_INTERNAL_MAP
if ( isNull_ )
{ if ( isNull_ )
return other.isNull_; {
} return other.isNull_;
return current_ == other.current_; }
return current_ == other.current_;
#else #else
if ( isArray_ )
return ValueInternalArray::equals( iterator_.array_, other.iterator_.array_ ); if ( isArray_ )
return ValueInternalMap::equals( iterator_.map_, other.iterator_.map_ ); return ValueInternalArray::equals ( iterator_.array_, other.iterator_.array_ );
return ValueInternalMap::equals ( iterator_.map_, other.iterator_.map_ );
#endif #endif
} }
void void
ValueIteratorBase::copy( const SelfType &other ) ValueIteratorBase::copy ( const SelfType& other )
{ {
#ifndef JSON_VALUE_USE_INTERNAL_MAP #ifndef JSON_VALUE_USE_INTERNAL_MAP
current_ = other.current_; current_ = other.current_;
#else #else
if ( isArray_ )
iterator_.array_ = other.iterator_.array_; if ( isArray_ )
iterator_.map_ = other.iterator_.map_; iterator_.array_ = other.iterator_.array_;
iterator_.map_ = other.iterator_.map_;
#endif #endif
} }
Value Value
ValueIteratorBase::key() const ValueIteratorBase::key () const
{ {
#ifndef JSON_VALUE_USE_INTERNAL_MAP #ifndef JSON_VALUE_USE_INTERNAL_MAP
const Value::CZString czstring = (*current_).first; const Value::CZString czstring = (*current_).first;
if ( czstring.c_str() )
{ if ( czstring.c_str () )
if ( czstring.isStaticString() ) {
return Value( StaticString( czstring.c_str() ) ); if ( czstring.isStaticString () )
return Value( czstring.c_str() ); return Value ( StaticString ( czstring.c_str () ) );
}
return Value( czstring.index() ); return Value ( czstring.c_str () );
}
return Value ( czstring.index () );
#else #else
if ( isArray_ )
return Value( ValueInternalArray::indexOf( iterator_.array_ ) ); if ( isArray_ )
bool isStatic; return Value ( ValueInternalArray::indexOf ( iterator_.array_ ) );
const char *memberName = ValueInternalMap::key( iterator_.map_, isStatic );
if ( isStatic ) bool isStatic;
return Value( StaticString( memberName ) ); const char* memberName = ValueInternalMap::key ( iterator_.map_, isStatic );
return Value( memberName );
if ( isStatic )
return Value ( StaticString ( memberName ) );
return Value ( memberName );
#endif #endif
} }
UInt UInt
ValueIteratorBase::index() const ValueIteratorBase::index () const
{ {
#ifndef JSON_VALUE_USE_INTERNAL_MAP #ifndef JSON_VALUE_USE_INTERNAL_MAP
const Value::CZString czstring = (*current_).first; const Value::CZString czstring = (*current_).first;
if ( !czstring.c_str() )
return czstring.index(); if ( !czstring.c_str () )
return Value::UInt( -1 ); return czstring.index ();
return Value::UInt ( -1 );
#else #else
if ( isArray_ )
return Value::UInt( ValueInternalArray::indexOf( iterator_.array_ ) ); if ( isArray_ )
return Value::UInt( -1 ); return Value::UInt ( ValueInternalArray::indexOf ( iterator_.array_ ) );
return Value::UInt ( -1 );
#endif #endif
} }
const char * const char*
ValueIteratorBase::memberName() const ValueIteratorBase::memberName () const
{ {
#ifndef JSON_VALUE_USE_INTERNAL_MAP #ifndef JSON_VALUE_USE_INTERNAL_MAP
const char *name = (*current_).first.c_str(); const char* name = (*current_).first.c_str ();
return name ? name : ""; return name ? name : "";
#else #else
if ( !isArray_ )
return ValueInternalMap::key( iterator_.map_ ); if ( !isArray_ )
return ""; return ValueInternalMap::key ( iterator_.map_ );
return "";
#endif #endif
} }
@@ -214,33 +245,33 @@ ValueIteratorBase::memberName() const
// ////////////////////////////////////////////////////////////////// // //////////////////////////////////////////////////////////////////
// ////////////////////////////////////////////////////////////////// // //////////////////////////////////////////////////////////////////
ValueConstIterator::ValueConstIterator() ValueConstIterator::ValueConstIterator ()
{ {
} }
#ifndef JSON_VALUE_USE_INTERNAL_MAP #ifndef JSON_VALUE_USE_INTERNAL_MAP
ValueConstIterator::ValueConstIterator( const Value::ObjectValues::iterator &current ) ValueConstIterator::ValueConstIterator ( const Value::ObjectValues::iterator& current )
: ValueIteratorBase( current ) : ValueIteratorBase ( current )
{ {
} }
#else #else
ValueConstIterator::ValueConstIterator( const ValueInternalArray::IteratorState &state ) ValueConstIterator::ValueConstIterator ( const ValueInternalArray::IteratorState& state )
: ValueIteratorBase( state ) : ValueIteratorBase ( state )
{ {
} }
ValueConstIterator::ValueConstIterator( const ValueInternalMap::IteratorState &state ) ValueConstIterator::ValueConstIterator ( const ValueInternalMap::IteratorState& state )
: ValueIteratorBase( state ) : ValueIteratorBase ( state )
{ {
} }
#endif #endif
ValueConstIterator & ValueConstIterator&
ValueConstIterator::operator =( const ValueIteratorBase &other ) ValueConstIterator::operator = ( const ValueIteratorBase& other )
{ {
copy( other ); copy ( other );
return *this; return *this;
} }
@@ -252,41 +283,41 @@ ValueConstIterator::operator =( const ValueIteratorBase &other )
// ////////////////////////////////////////////////////////////////// // //////////////////////////////////////////////////////////////////
// ////////////////////////////////////////////////////////////////// // //////////////////////////////////////////////////////////////////
ValueIterator::ValueIterator() ValueIterator::ValueIterator ()
{ {
} }
#ifndef JSON_VALUE_USE_INTERNAL_MAP #ifndef JSON_VALUE_USE_INTERNAL_MAP
ValueIterator::ValueIterator( const Value::ObjectValues::iterator &current ) ValueIterator::ValueIterator ( const Value::ObjectValues::iterator& current )
: ValueIteratorBase( current ) : ValueIteratorBase ( current )
{ {
} }
#else #else
ValueIterator::ValueIterator( const ValueInternalArray::IteratorState &state ) ValueIterator::ValueIterator ( const ValueInternalArray::IteratorState& state )
: ValueIteratorBase( state ) : ValueIteratorBase ( state )
{ {
} }
ValueIterator::ValueIterator( const ValueInternalMap::IteratorState &state ) ValueIterator::ValueIterator ( const ValueInternalMap::IteratorState& state )
: ValueIteratorBase( state ) : ValueIteratorBase ( state )
{ {
} }
#endif #endif
ValueIterator::ValueIterator( const ValueConstIterator &other ) ValueIterator::ValueIterator ( const ValueConstIterator& other )
: ValueIteratorBase( other ) : ValueIteratorBase ( other )
{ {
} }
ValueIterator::ValueIterator( const ValueIterator &other ) ValueIterator::ValueIterator ( const ValueIterator& other )
: ValueIteratorBase( other ) : ValueIteratorBase ( other )
{ {
} }
ValueIterator & ValueIterator&
ValueIterator::operator =( const SelfType &other ) ValueIterator::operator = ( const SelfType& other )
{ {
copy( other ); copy ( other );
return *this; return *this;
} }

File diff suppressed because it is too large Load Diff

View File

@@ -1,166 +1,167 @@
#ifndef JSON_WRITER_H_INCLUDED #ifndef JSON_WRITER_H_INCLUDED
# define JSON_WRITER_H_INCLUDED # define JSON_WRITER_H_INCLUDED
namespace Json { namespace Json
{
class Value; class Value;
/** \brief Abstract class for writers. /** \brief Abstract class for writers.
*/ */
class JSON_API Writer class JSON_API Writer
{ {
public: public:
virtual ~Writer(); 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). /** \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, * 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. * but may be usefull to support feature such as RPC where bandwith is limited.
* \sa Reader, Value * \sa Reader, Value
*/ */
class JSON_API FastWriter : public Writer class JSON_API FastWriter : public Writer
{ {
public: public:
FastWriter(); FastWriter ();
virtual ~FastWriter(){} virtual ~FastWriter () {}
void enableYAMLCompatibility(); void enableYAMLCompatibility ();
public: // overridden from Writer public: // overridden from Writer
virtual std::string write( const Value &root ); virtual std::string write ( const Value& root );
private: private:
void writeValue( const Value &value ); void writeValue ( const Value& value );
std::string document_; std::string document_;
bool yamlCompatiblityEnabled_; bool yamlCompatiblityEnabled_;
}; };
/** \brief Writes a Value in <a HREF="http://www.json.org">JSON</a> format in a human friendly way. /** \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: * The rules for line break and indent are as follow:
* - Object value: * - Object value:
* - if empty then print {} without indent and line break * - if empty then print {} without indent and line break
* - if not empty the print '{', line break & indent, print one value per line * - if not empty the print '{', line break & indent, print one value per line
* and then unindent and line break and print '}'. * and then unindent and line break and print '}'.
* - Array value: * - Array value:
* - if empty then print [] without indent and line break * - if empty then print [] without indent and line break
* - if the array contains no object value, empty array or some other value types, * - 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. * 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 * - 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. * object or non empty array, then print one value per line.
* *
* If the Value have comments then they are outputed according to their #CommentPlacement. * If the Value have comments then they are outputed according to their #CommentPlacement.
* *
* \sa Reader, Value, Value::setComment() * \sa Reader, Value, Value::setComment()
*/ */
class JSON_API StyledWriter: public Writer class JSON_API StyledWriter: public Writer
{ {
public: public:
StyledWriter(); StyledWriter ();
virtual ~StyledWriter(){} virtual ~StyledWriter () {}
public: // overridden from Writer public: // overridden from Writer
/** \brief Serialize a Value in <a HREF="http://www.json.org">JSON</a> format. /** \brief Serialize a Value in <a HREF="http://www.json.org">JSON</a> format.
* \param root Value to serialize. * \param root Value to serialize.
* \return String containing the JSON document that represents the root value. * \return String containing the JSON document that represents the root value.
*/ */
virtual std::string write( const Value &root ); virtual std::string write ( const Value& root );
private: private:
void writeValue( const Value &value ); void writeValue ( const Value& value );
void writeArrayValue( const Value &value ); void writeArrayValue ( const Value& value );
bool isMultineArray( const Value &value ); bool isMultineArray ( const Value& value );
void pushValue( const std::string &value ); void pushValue ( const std::string& value );
void writeIndent(); void writeIndent ();
void writeWithIndent( const std::string &value ); void writeWithIndent ( const std::string& value );
void indent(); void indent ();
void unindent(); void unindent ();
void writeCommentBeforeValue( const Value &root ); void writeCommentBeforeValue ( const Value& root );
void writeCommentAfterValueOnSameLine( const Value &root ); void writeCommentAfterValueOnSameLine ( const Value& root );
bool hasCommentForValue( const Value &value ); bool hasCommentForValue ( const Value& value );
static std::string normalizeEOL( const std::string &text ); static std::string normalizeEOL ( const std::string& text );
typedef std::vector<std::string> ChildValues; typedef std::vector<std::string> ChildValues;
ChildValues childValues_; ChildValues childValues_;
std::string document_; std::string document_;
std::string indentString_; std::string indentString_;
int rightMargin_; int rightMargin_;
int indentSize_; int indentSize_;
bool addChildValues_; bool addChildValues_;
}; };
/** \brief Writes a Value in <a HREF="http://www.json.org">JSON</a> format in a human friendly way, /** \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. to a stream rather than to a string.
* *
* The rules for line break and indent are as follow: * The rules for line break and indent are as follow:
* - Object value: * - Object value:
* - if empty then print {} without indent and line break * - if empty then print {} without indent and line break
* - if not empty the print '{', line break & indent, print one value per line * - if not empty the print '{', line break & indent, print one value per line
* and then unindent and line break and print '}'. * and then unindent and line break and print '}'.
* - Array value: * - Array value:
* - if empty then print [] without indent and line break * - if empty then print [] without indent and line break
* - if the array contains no object value, empty array or some other value types, * - 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. * 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 * - 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. * object or non empty array, then print one value per line.
* *
* If the Value have comments then they are outputed according to their #CommentPlacement. * If the Value have comments then they are outputed according to their #CommentPlacement.
* *
* \param indentation Each level will be indented by this amount extra. * \param indentation Each level will be indented by this amount extra.
* \sa Reader, Value, Value::setComment() * \sa Reader, Value, Value::setComment()
*/ */
class JSON_API StyledStreamWriter class JSON_API StyledStreamWriter
{ {
public: public:
StyledStreamWriter( std::string indentation="\t" ); StyledStreamWriter ( std::string indentation = "\t" );
~StyledStreamWriter(){} ~StyledStreamWriter () {}
public: public:
/** \brief Serialize a Value in <a HREF="http://www.json.org">JSON</a> format. /** \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 out Stream to write to. (Can be ostringstream, e.g.)
* \param root Value to serialize. * \param root Value to serialize.
* \note There is no point in deriving from Writer, since write() should not return a value. * \note There is no point in deriving from Writer, since write() should not return a value.
*/ */
void write( std::ostream &out, const Value &root ); void write ( std::ostream& out, const Value& root );
private: private:
void writeValue( const Value &value ); void writeValue ( const Value& value );
void writeArrayValue( const Value &value ); void writeArrayValue ( const Value& value );
bool isMultineArray( const Value &value ); bool isMultineArray ( const Value& value );
void pushValue( const std::string &value ); void pushValue ( const std::string& value );
void writeIndent(); void writeIndent ();
void writeWithIndent( const std::string &value ); void writeWithIndent ( const std::string& value );
void indent(); void indent ();
void unindent(); void unindent ();
void writeCommentBeforeValue( const Value &root ); void writeCommentBeforeValue ( const Value& root );
void writeCommentAfterValueOnSameLine( const Value &root ); void writeCommentAfterValueOnSameLine ( const Value& root );
bool hasCommentForValue( const Value &value ); bool hasCommentForValue ( const Value& value );
static std::string normalizeEOL( const std::string &text ); static std::string normalizeEOL ( const std::string& text );
typedef std::vector<std::string> ChildValues; typedef std::vector<std::string> ChildValues;
ChildValues childValues_; ChildValues childValues_;
std::ostream* document_; std::ostream* document_;
std::string indentString_; std::string indentString_;
int rightMargin_; int rightMargin_;
std::string indentation_; std::string indentation_;
bool addChildValues_; bool addChildValues_;
}; };
std::string JSON_API valueToString( Int value ); std::string JSON_API valueToString ( Int value );
std::string JSON_API valueToString( UInt value ); std::string JSON_API valueToString ( UInt value );
std::string JSON_API valueToString( double value ); std::string JSON_API valueToString ( double value );
std::string JSON_API valueToString( bool value ); std::string JSON_API valueToString ( bool value );
std::string JSON_API valueToQuotedString( const char *value ); std::string JSON_API valueToQuotedString ( const char* value );
/// \brief Output using the StyledStreamWriter. /// \brief Output using the StyledStreamWriter.
/// \see Json::operator>>() /// \see Json::operator>>()
std::ostream& operator<<( std::ostream&, const Value &root ); std::ostream& operator<< ( std::ostream&, const Value& root );
} // namespace Json } // 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 Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies. copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 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 @file ripple_json.cpp
@ingroup ripple_json @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 Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies. copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 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 @file ripple_json.h
@ingroup ripple_json @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 #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 Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies. copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 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 @file ripple_ledger.cpp
@ingroup ripple_ledger @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 Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies. copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 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 @file ripple_ledger.h
@ingroup ripple_ledger @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 #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 Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies. copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 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 @file ripple_main.cpp
@ingroup ripple_main @ingroup ripple_main
@@ -308,10 +308,10 @@ static const uint64 tenTo17m1 = tenTo17 - 1;
// This is for PeerDoor and WSDoor // This is for PeerDoor and WSDoor
// Generate DH for SSL connection. // 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 // VFALCO TODO eliminate this horrendous dependency on theApp and Wallet
return 512 == iKeyLength ? theApp->getWallet().getDh512() : theApp->getWallet().getDh1024(); return 512 == iKeyLength ? theApp->getWallet ().getDh512 () : theApp->getWallet ().getDh1024 ();
} }
#include "src/cpp/ripple/ParameterTable.cpp" // no log #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 Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies. copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 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 @file ripple_main.h
@ingroup ripple_main @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 #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 Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies. copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 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 @file ripple_mess.cpp
@ingroup ripple_mess @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 Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies. copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 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 @file ripple_mess.h
@ingroup ripple_mess @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 #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 Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies. copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 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 @file ripple_net.cpp
@ingroup ripple_net @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 Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies. copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 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 @file ripple_net.h
@ingroup ripple_net @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 #ifndef RIPPLE_NET_H

View File

@@ -13,408 +13,432 @@ SETUP_LOG (SqliteDatabase)
using namespace std; 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; mConnection = NULL;
mAuxConnection = NULL; mAuxConnection = NULL;
mCurrentStmt = NULL; mCurrentStmt = NULL;
} }
void SqliteDatabase::connect() void SqliteDatabase::connect ()
{ {
int rc = sqlite3_open(mHost.c_str(), &mConnection); int rc = sqlite3_open (mHost.c_str (), &mConnection);
if (rc)
{ if (rc)
WriteLog (lsFATAL, SqliteDatabase) << "Can't open " << mHost << " " << rc; {
sqlite3_close(mConnection); WriteLog (lsFATAL, SqliteDatabase) << "Can't open " << mHost << " " << rc;
assert((rc != SQLITE_BUSY) && (rc != SQLITE_LOCKED)); sqlite3_close (mConnection);
} assert ((rc != SQLITE_BUSY) && (rc != SQLITE_LOCKED));
}
} }
sqlite3* SqliteDatabase::getAuxConnection() sqlite3* SqliteDatabase::getAuxConnection ()
{ {
boost::mutex::scoped_lock sl(walMutex); boost::mutex::scoped_lock sl (walMutex);
if (mAuxConnection == NULL)
{ if (mAuxConnection == NULL)
int rc = sqlite3_open(mHost.c_str(), &mAuxConnection); {
if (rc) int rc = sqlite3_open (mHost.c_str (), &mAuxConnection);
{
WriteLog (lsFATAL, SqliteDatabase) << "Can't aux open " << mHost << " " << rc; if (rc)
assert((rc != SQLITE_BUSY) && (rc != SQLITE_LOCKED)); {
if (mAuxConnection != NULL) WriteLog (lsFATAL, SqliteDatabase) << "Can't aux open " << mHost << " " << rc;
{ assert ((rc != SQLITE_BUSY) && (rc != SQLITE_LOCKED));
sqlite3_close(mConnection);
mAuxConnection = NULL; if (mAuxConnection != NULL)
} {
} sqlite3_close (mConnection);
} mAuxConnection = NULL;
return mAuxConnection; }
}
}
return mAuxConnection;
} }
void SqliteDatabase::disconnect() void SqliteDatabase::disconnect ()
{ {
sqlite3_finalize(mCurrentStmt); sqlite3_finalize (mCurrentStmt);
sqlite3_close(mConnection); sqlite3_close (mConnection);
if (mAuxConnection != NULL)
sqlite3_close(mAuxConnection); if (mAuxConnection != NULL)
sqlite3_close (mAuxConnection);
} }
// returns true if the query went ok // 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 #ifdef DEBUG_HANGING_LOCKS
assert(fail_ok || (mCurrentStmt == NULL)); assert (fail_ok || (mCurrentStmt == NULL));
#endif #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 (SQLITE_OK != rc)
{ {
if (!fail_ok) if (!fail_ok)
{ {
#ifdef DEBUG #ifdef DEBUG
WriteLog (lsWARNING, SqliteDatabase) << "Perror:" << mHost << ": " << rc; WriteLog (lsWARNING, SqliteDatabase) << "Perror:" << mHost << ": " << rc;
WriteLog (lsWARNING, SqliteDatabase) << "Statement: " << sql; WriteLog (lsWARNING, SqliteDatabase) << "Statement: " << sql;
WriteLog (lsWARNING, SqliteDatabase) << "Error: " << sqlite3_errmsg(mConnection); WriteLog (lsWARNING, SqliteDatabase) << "Error: " << sqlite3_errmsg (mConnection);
#endif #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 #ifdef DEBUG
WriteLog (lsWARNING, SqliteDatabase) << "SQL Serror:" << mHost << ": " << rc; WriteLog (lsWARNING, SqliteDatabase) << "SQL Serror:" << mHost << ": " << rc;
WriteLog (lsWARNING, SqliteDatabase) << "Statement: " << sql; WriteLog (lsWARNING, SqliteDatabase) << "Statement: " << sql;
WriteLog (lsWARNING, SqliteDatabase) << "Error: " << sqlite3_errmsg(mConnection); WriteLog (lsWARNING, SqliteDatabase) << "Error: " << sqlite3_errmsg (mConnection);
#endif #endif
} }
endIterRows();
return false;
}
return true; endIterRows ();
return false;
}
return true;
} }
// returns false if there are no results // returns false if there are no results
bool SqliteDatabase::startIterRows(bool finalize) bool SqliteDatabase::startIterRows (bool finalize)
{ {
mColNameTable.clear(); mColNameTable.clear ();
mColNameTable.resize(sqlite3_column_count(mCurrentStmt)); mColNameTable.resize (sqlite3_column_count (mCurrentStmt));
for(unsigned n=0; n<mColNameTable.size(); n++)
{
mColNameTable[n]=sqlite3_column_name(mCurrentStmt,n);
}
if (!mMoreRows && finalize) for (unsigned n = 0; n < mColNameTable.size (); n++)
endIterRows(); {
mColNameTable[n] = sqlite3_column_name (mCurrentStmt, n);
}
return(mMoreRows); if (!mMoreRows && finalize)
endIterRows ();
return (mMoreRows);
} }
void SqliteDatabase::endIterRows() void SqliteDatabase::endIterRows ()
{ {
sqlite3_finalize(mCurrentStmt); sqlite3_finalize (mCurrentStmt);
mCurrentStmt=NULL; mCurrentStmt = NULL;
} }
// call this after you executeSQL // call this after you executeSQL
// will return false if there are no more rows // will return false if there are no more rows
bool SqliteDatabase::getNextRow(bool finalize) bool SqliteDatabase::getNextRow (bool finalize)
{ {
if (mMoreRows) if (mMoreRows)
{ {
int rc=sqlite3_step(mCurrentStmt); 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 (finalize) if (rc == SQLITE_ROW)
endIterRows(); return (true);
return false;
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)); const char* text = reinterpret_cast<const char*> (sqlite3_column_text (mCurrentStmt, colIndex));
retStr = (text == NULL) ? "" : text; retStr = (text == NULL) ? "" : text;
return const_cast<char*>(retStr.c_str()); 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); const void* blob = sqlite3_column_blob (mCurrentStmt, colIndex);
int size=sqlite3_column_bytes(mCurrentStmt, colIndex); int size = sqlite3_column_bytes (mCurrentStmt, colIndex);
if(size<maxSize) maxSize=size;
memcpy(buf,blob,maxSize); if (size < maxSize) maxSize = size;
return(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)); const unsigned char* blob = reinterpret_cast<const unsigned char*> (sqlite3_column_blob (mCurrentStmt, colIndex));
size_t iSize = sqlite3_column_bytes(mCurrentStmt, colIndex); size_t iSize = sqlite3_column_bytes (mCurrentStmt, colIndex);
Blob vucResult; Blob vucResult;
vucResult.resize(iSize); vucResult.resize (iSize);
std::copy(blob, blob+iSize, vucResult.begin()); 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; int cur = 0, hiw = 0;
sqlite3_db_status(mConnection, SQLITE_DBSTATUS_CACHE_USED, &cur, &hiw, 0); sqlite3_db_status (mConnection, SQLITE_DBSTATUS_CACHE_USED, &cur, &hiw, 0);
return cur / 1024; 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); (reinterpret_cast<SqliteDatabase*> (s))->doHook (dbName, walSize);
return SQLITE_OK; return SQLITE_OK;
} }
bool SqliteDatabase::setupCheckpointing(JobQueue *q) bool SqliteDatabase::setupCheckpointing (JobQueue* q)
{ {
mWalQ = q; mWalQ = q;
sqlite3_wal_hook(mConnection, SqliteWALHook, this); sqlite3_wal_hook (mConnection, SqliteWALHook, this);
return true; return true;
} }
void SqliteDatabase::doHook(const char *db, int pages) void SqliteDatabase::doHook (const char* db, int pages)
{ {
if (pages < 1000) if (pages < 1000)
return; return;
{
boost::mutex::scoped_lock sl(walMutex); {
if (walRunning) boost::mutex::scoped_lock sl (walMutex);
return;
walRunning = true; if (walRunning)
} return;
if (mWalQ)
mWalQ->addJob(jtWAL, std::string("WAL:") + mHost, boost::bind(&SqliteDatabase::runWal, this)); walRunning = true;
else }
boost::thread(boost::bind(&SqliteDatabase::runWal, this)).detach();
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 log = 0, ckpt = 0;
int ret = sqlite3_wal_checkpoint_v2(mConnection, NULL, SQLITE_CHECKPOINT_PASSIVE, &log, &ckpt); 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;
{ if (ret != SQLITE_OK)
boost::mutex::scoped_lock sl(walMutex); {
walRunning = false; 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(); sqlite3* conn = aux ? db->getAuxConnection () : db->peekConnection ();
int j = sqlite3_prepare_v2(conn, sql, strlen(sql) + 1, &statement, NULL); int j = sqlite3_prepare_v2 (conn, sql, strlen (sql) + 1, &statement, NULL);
if (j != SQLITE_OK)
throw j; 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(); sqlite3* conn = aux ? db->getAuxConnection () : db->peekConnection ();
int j = sqlite3_prepare_v2(conn, sql.c_str(), sql.size() + 1, &statement, NULL); int j = sqlite3_prepare_v2 (conn, sql.c_str (), sql.size () + 1, &statement, NULL);
if (j != SQLITE_OK)
throw j; 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); int size = sqlite3_column_bytes (statement, column);
Blob ret(size); Blob ret (size);
memcpy(&(ret.front()), sqlite3_column_blob(statement, column), size); memcpy (& (ret.front ()), sqlite3_column_blob (statement, column), size);
return ret; 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) switch (j)
{ {
case SQLITE_OK: case SQLITE_OK:
case SQLITE_ROW: case SQLITE_ROW:
case SQLITE_DONE: case SQLITE_DONE:
return true; return true;
default: default:
return false; 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 // vim:ts=4

View File

@@ -7,104 +7,110 @@ struct sqlite3_stmt;
class SqliteDatabase : public Database class SqliteDatabase : public Database
{ {
sqlite3* mConnection; sqlite3* mConnection;
sqlite3* mAuxConnection; sqlite3* mAuxConnection;
sqlite3_stmt* mCurrentStmt; sqlite3_stmt* mCurrentStmt;
bool mMoreRows; bool mMoreRows;
boost::mutex walMutex; boost::mutex walMutex;
JobQueue* mWalQ; JobQueue* mWalQ;
bool walRunning; bool walRunning;
public: public:
SqliteDatabase(const char* host); SqliteDatabase (const char* host);
void connect(); void connect ();
void disconnect(); void disconnect ();
// returns true if the query went ok // returns true if the query went ok
bool executeSQL(const char* sql, bool fail_okay); bool executeSQL (const char* sql, bool fail_okay);
// tells you how many rows were changed by an update or insert // tells you how many rows were changed by an update or insert
int getNumRowsAffected(); int getNumRowsAffected ();
// returns false if there are no results // returns false if there are no results
bool startIterRows(bool finalize); bool startIterRows (bool finalize);
void endIterRows(); void endIterRows ();
// call this after you executeSQL // call this after you executeSQL
// will return false if there are no more rows // will return false if there are no more rows
bool getNextRow(bool finalize); bool getNextRow (bool finalize);
bool getNull(int colIndex); bool getNull (int colIndex);
char* getStr(int colIndex,std::string& retStr); char* getStr (int colIndex, std::string& retStr);
int32 getInt(int colIndex); int32 getInt (int colIndex);
float getFloat(int colIndex); float getFloat (int colIndex);
bool getBool(int colIndex); bool getBool (int colIndex);
// returns amount stored in buf // returns amount stored in buf
int getBinary(int colIndex,unsigned char* buf,int maxSize); int getBinary (int colIndex, unsigned char* buf, int maxSize);
Blob getBinary(int colIndex); Blob getBinary (int colIndex);
uint64 getBigInt(int colIndex); uint64 getBigInt (int colIndex);
sqlite3* peekConnection() { return mConnection; } sqlite3* peekConnection ()
sqlite3* getAuxConnection(); {
virtual bool setupCheckpointing(JobQueue*); return mConnection;
virtual SqliteDatabase* getSqliteDB() { return this; } }
sqlite3* getAuxConnection ();
virtual bool setupCheckpointing (JobQueue*);
virtual SqliteDatabase* getSqliteDB ()
{
return this;
}
void runWal(); void runWal ();
void doHook(const char *db, int walSize); void doHook (const char* db, int walSize);
int getKBUsedDB(); int getKBUsedDB ();
int getKBUsedAll(); int getKBUsedAll ();
}; };
class SqliteStatement class SqliteStatement
{ {
private: private:
SqliteStatement(const SqliteStatement&); // no implementation SqliteStatement (const SqliteStatement&); // no implementation
SqliteStatement& operator=(const SqliteStatement&); // no implementation SqliteStatement& operator= (const SqliteStatement&); // no implementation
protected: protected:
sqlite3_stmt* statement; sqlite3_stmt* statement;
public: public:
SqliteStatement(SqliteDatabase* db, const char *statement, bool aux = false); SqliteStatement (SqliteDatabase* db, const char* statement, bool aux = false);
SqliteStatement(SqliteDatabase* db, const std::string& statement, bool aux = false); SqliteStatement (SqliteDatabase* db, const std::string& statement, bool aux = false);
~SqliteStatement(); ~SqliteStatement ();
sqlite3_stmt* peekStatement(); sqlite3_stmt* peekStatement ();
// positions start at 1 // positions start at 1
int bind(int position, const void *data, int length); int bind (int position, const void* data, int length);
int bindStatic(int position, const void *data, int length); int bindStatic (int position, const void* data, int length);
int bindStatic(int position, Blob const& value); int bindStatic (int position, Blob const& value);
int bind(int position, const std::string& value); int bind (int position, const std::string& value);
int bindStatic(int position, const std::string& value); int bindStatic (int position, const std::string& value);
int bind(int position, uint32 value); int bind (int position, uint32 value);
int bind(int position); int bind (int position);
// columns start at 0 // columns start at 0
int size(int column); int size (int column);
const void* peekBlob(int column); const void* peekBlob (int column);
Blob getBlob(int column); Blob getBlob (int column);
std::string getString(int column); std::string getString (int column);
const char* peekString(int column); const char* peekString (int column);
uint32 getUInt32(int column); uint32 getUInt32 (int column);
int64 getInt64(int column); int64 getInt64 (int column);
int step(); int step ();
int reset(); int reset ();
// translate return values of step and reset // translate return values of step and reset
bool isOk(int); bool isOk (int);
bool isDone(int); bool isDone (int);
bool isRow(int); bool isRow (int);
bool isError(int); bool isError (int);
std::string getError(int); std::string getError (int);
}; };
#endif #endif

Some files were not shown because too many files have changed in this diff Show More