Improve regularity of STObject and STArray (RIPD-448, RIPD-544):

* reduce duplicated code using templates
* replace BOOST_FOREACH with C++11 for loops
* remove most direct calls to new
* limit line length to 80 characters
* clearly identify virtual and overridden methods
* split STObject and STArray into their own files
* name files after the class they contain
This commit is contained in:
Scott Schurr
2014-08-29 09:34:26 -07:00
committed by Nik Bougalis
parent c55777738f
commit b5224a2227
8 changed files with 661 additions and 754 deletions

View File

@@ -20,7 +20,7 @@
#ifndef RIPPLE_CORE_AMOUNT_H_INCLUDED
#define RIPPLE_CORE_AMOUNT_H_INCLUDED
#include <ripple/module/data/protocol/SerializedObject.h>
#include <ripple/module/data/protocol/STObject.h>
#include <beast/utility/noexcept.h>
#include <beast/cxx14/type_traits.h> // <type_traits>

View File

@@ -0,0 +1,148 @@
//------------------------------------------------------------------------------
/*
This file is part of rippled: https://github.com/ripple/rippled
Copyright (c) 2012, 2013 Ripple Labs Inc.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
namespace ripple {
std::unique_ptr<SerializedType>
STArray::deserialize (SerializerIterator& sit, SField::ref field)
{
std::unique_ptr <STArray> ret (std::make_unique <STArray> (field));
vector& value (ret->getValue ());
while (!sit.empty ())
{
int type, field;
sit.getFieldID (type, field);
if ((type == STI_ARRAY) && (field == 1))
break;
if ((type == STI_OBJECT) && (field == 1))
{
WriteLog (lsWARNING, STObject) <<
"Encountered array with end of object marker";
throw std::runtime_error ("Illegal terminator in array");
}
SField::ref fn = SField::getField (type, field);
if (fn.isInvalid ())
{
WriteLog (lsTRACE, STObject) <<
"Unknown field: " << type << "/" << field;
throw std::runtime_error ("Unknown field");
}
if (fn.fieldType != STI_OBJECT)
{
WriteLog (lsTRACE, STObject) << "Array contains non-object";
throw std::runtime_error ("Non-object in array");
}
value.push_back (new STObject (fn));
value.rbegin ()->set (sit, 1);
}
return std::move (ret);
}
std::string STArray::getFullText () const
{
std::string r = "[";
bool first = true;
for (STObject const& o : value)
{
if (!first)
r += ",";
r += o.getFullText ();
first = false;
}
r += "]";
return r;
}
std::string STArray::getText () const
{
std::string r = "[";
bool first = true;
for (STObject const& o : value)
{
if (!first)
r += ",";
r += o.getText ();
first = false;
}
r += "]";
return r;
}
Json::Value STArray::getJson (int p) const
{
Json::Value v = Json::arrayValue;
int index = 1;
for (auto const& object: value)
{
if (object.getSType () != STI_NOTPRESENT)
{
Json::Value inner = Json::objectValue;
auto const& fname = object.getFName ();
auto k = fname.hasName () ? fname.fieldName : std::to_string(index);
inner[k] = object.getJson (p);
v.append (inner);
index++;
}
}
return v;
}
void STArray::add (Serializer& s) const
{
for (STObject const& object : value)
{
object.addFieldID (s);
object.add (s);
s.addFieldID (STI_OBJECT, 1);
}
}
bool STArray::isEquivalent (const SerializedType& t) const
{
const STArray* v = dynamic_cast<const STArray*> (&t);
if (!v)
{
WriteLog (lsDEBUG, STObject) <<
"notEquiv " << getFullText() << " not array";
return false;
}
return value == v->value;
}
void STArray::sort (bool (*compare) (const STObject&, const STObject&))
{
value.sort (compare);
}
} // ripple

View File

@@ -0,0 +1,211 @@
//------------------------------------------------------------------------------
/*
This file is part of rippled: https://github.com/ripple/rippled
Copyright (c) 2012, 2013 Ripple Labs Inc.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
#ifndef RIPPLE_STARRAY_H
#define RIPPLE_STARRAY_H
#include <ripple/module/data/protocol/STObject.h>
#include <boost/ptr_container/ptr_vector.hpp>
namespace ripple {
class STArray final
: public SerializedType
, public CountedObject <STArray>
{
public:
static char const* getCountedObjectName () { return "STArray"; }
typedef boost::ptr_vector<STObject> vector;
typedef vector::iterator iterator;
typedef vector::const_iterator const_iterator;
typedef vector::reverse_iterator reverse_iterator;
typedef vector::const_reverse_iterator const_reverse_iterator;
typedef vector::size_type size_type;
public:
STArray ()
{
;
}
explicit STArray (int n)
{
value.reserve (n);
}
explicit STArray (SField::ref f) : SerializedType (f)
{
;
}
STArray (SField::ref f, int n) : SerializedType (f)
{
value.reserve (n);
}
STArray (SField::ref f, const vector & v) : SerializedType (f), value (v)
{
;
}
explicit STArray (vector & v) : value (v)
{
;
}
virtual ~STArray () { }
static std::unique_ptr<SerializedType>
deserialize (SerializerIterator & sit, SField::ref name);
const vector& getValue () const
{
return value;
}
vector& getValue ()
{
return value;
}
// VFALCO NOTE as long as we're married to boost why not use
// boost::iterator_facade?
//
// vector-like functions
void push_back (const STObject & object)
{
value.push_back (object.oClone ().release ());
}
STObject& operator[] (int j)
{
return value[j];
}
const STObject& operator[] (int j) const
{
return value[j];
}
iterator begin ()
{
return value.begin ();
}
const_iterator begin () const
{
return value.begin ();
}
iterator end ()
{
return value.end ();
}
const_iterator end () const
{
return value.end ();
}
size_type size () const
{
return value.size ();
}
reverse_iterator rbegin ()
{
return value.rbegin ();
}
const_reverse_iterator rbegin () const
{
return value.rbegin ();
}
reverse_iterator rend ()
{
return value.rend ();
}
const_reverse_iterator rend () const
{
return value.rend ();
}
iterator erase (iterator pos)
{
return value.erase (pos);
}
STObject& front ()
{
return value.front ();
}
const STObject& front () const
{
return value.front ();
}
STObject& back ()
{
return value.back ();
}
const STObject& back () const
{
return value.back ();
}
void pop_back ()
{
value.pop_back ();
}
bool empty () const
{
return value.empty ();
}
void clear ()
{
value.clear ();
}
void swap (STArray & a)
{
value.swap (a.value);
}
virtual std::string getFullText () const override;
virtual std::string getText () const override;
virtual Json::Value getJson (int index) const override;
virtual void add (Serializer & s) const override;
void sort (bool (*compare) (const STObject & o1, const STObject & o2));
bool operator== (const STArray & s)
{
return value == s.value;
}
bool operator!= (const STArray & s)
{
return value != s.value;
}
virtual SerializedTypeID getSType () const override
{
return STI_ARRAY;
}
virtual bool isEquivalent (const SerializedType & t) const override;
virtual bool isDefault () const override
{
return value.empty ();
}
private:
virtual STArray* duplicate () const override
{
return new STArray (*this);
}
private:
vector value;
};
} // ripple
#endif

View File

@@ -17,68 +17,73 @@
*/
//==============================================================================
#include <beast/cxx14/memory.h> // <memory>
namespace ripple {
std::unique_ptr<SerializedType> STObject::makeDefaultObject (SerializedTypeID id, SField::ref name)
std::unique_ptr<SerializedType>
STObject::makeDefaultObject (SerializedTypeID id, SField::ref name)
{
assert ((id == STI_NOTPRESENT) || (id == name.fieldType));
switch (id)
{
case STI_NOTPRESENT:
return std::unique_ptr<SerializedType> (new SerializedType (name));
return std::make_unique <SerializedType> (name);
case STI_UINT8:
return std::unique_ptr<SerializedType> (new STUInt8 (name));
return std::make_unique <STUInt8> (name);
case STI_UINT16:
return std::unique_ptr<SerializedType> (new STUInt16 (name));
return std::make_unique <STUInt16> (name);
case STI_UINT32:
return std::unique_ptr<SerializedType> (new STUInt32 (name));
return std::make_unique <STUInt32> (name);
case STI_UINT64:
return std::unique_ptr<SerializedType> (new STUInt64 (name));
return std::make_unique <STUInt64> (name);
case STI_AMOUNT:
return std::unique_ptr<SerializedType> (new STAmount (name));
return std::make_unique <STAmount> (name);
case STI_HASH128:
return std::unique_ptr<SerializedType> (new STHash128 (name));
return std::make_unique <STHash128> (name);
case STI_HASH160:
return std::unique_ptr<SerializedType> (new STHash160 (name));
return std::make_unique <STHash160> (name);
case STI_HASH256:
return std::unique_ptr<SerializedType> (new STHash256 (name));
return std::make_unique <STHash256> (name);
case STI_VECTOR256:
return std::unique_ptr<SerializedType> (new STVector256 (name));
return std::make_unique <STVector256> (name);
case STI_VL:
return std::unique_ptr<SerializedType> (new STVariableLength (name));
return std::make_unique <STVariableLength> (name);
case STI_ACCOUNT:
return std::unique_ptr<SerializedType> (new STAccount (name));
return std::make_unique <STAccount> (name);
case STI_PATHSET:
return std::unique_ptr<SerializedType> (new STPathSet (name));
return std::make_unique <STPathSet> (name);
case STI_OBJECT:
return std::unique_ptr<SerializedType> (new STObject (name));
return std::make_unique <STObject> (name);
case STI_ARRAY:
return std::unique_ptr<SerializedType> (new STArray (name));
return std::make_unique <STArray> (name);
default:
WriteLog (lsFATAL, STObject) << "Object type: " << beast::lexicalCast <std::string> (id);
WriteLog (lsFATAL, STObject) <<
"Object type: " << beast::lexicalCast <std::string> (id);
assert (false);
throw std::runtime_error ("Unknown object type");
}
}
// VFALCO TODO Remove the 'depth' parameter
std::unique_ptr<SerializedType> STObject::makeDeserializedObject (SerializedTypeID id, SField::ref name,
std::unique_ptr<SerializedType>
STObject::makeDeserializedObject (SerializedTypeID id, SField::ref name,
SerializerIterator& sit, int depth)
{
switch (id)
@@ -163,15 +168,17 @@ bool STObject::setType (const SOTemplate& type)
bool match = false;
for (std::size_t i = 0; i < count; ++i)
if ((array[i] != nullptr) && (array[i]->getFName () == elem->e_field))
if ((array[i] != nullptr) &&
(array[i]->getFName () == elem->e_field))
{
// matching entry in the object, move to new vector
match = true;
if ((elem->flags == SOE_DEFAULT) && array[i]->isDefault ())
{
WriteLog (lsWARNING, STObject) << "setType( " << getFName ().getName () << ") invalid default "
<< elem->e_field.fieldName;
WriteLog (lsWARNING, STObject) <<
"setType( " << getFName ().getName () <<
") invalid default " << elem->e_field.fieldName;
valid = false;
}
@@ -185,8 +192,9 @@ bool STObject::setType (const SOTemplate& type)
// no match found in the object for an entry in the template
if (elem->flags == SOE_REQUIRED)
{
WriteLog (lsWARNING, STObject) << "setType( " << getFName ().getName () << ") invalid missing "
<< elem->e_field.fieldName;
WriteLog (lsWARNING, STObject) <<
"setType( " << getFName ().getName () <<
") invalid missing " << elem->e_field.fieldName;
valid = false;
}
@@ -200,8 +208,9 @@ bool STObject::setType (const SOTemplate& type)
// Anything left over in the object must be discardable
if ((array[i] != nullptr) && !array[i]->getFName ().isDiscardable ())
{
WriteLog (lsWARNING, STObject) << "setType( " << getFName ().getName () << ") invalid leftover "
<< array[i]->getFName ().getName ();
WriteLog (lsWARNING, STObject) <<
"setType( " << getFName ().getName () <<
") invalid leftover " << array[i]->getFName ().getName ();
valid = false;
}
}
@@ -239,29 +248,6 @@ bool STObject::isFieldAllowed (SField::ref field)
return mType->getIndex (field) != -1;
}
// OLD
/*
bool STObject::set(SerializerIterator& sit, int depth)
{ // return true = terminated with end-of-object
mData.clear();
while (!sit.empty())
{
int type, field;
sit.getFieldID(type, field);
if ((type == STI_OBJECT) && (field == 1)) // end of object indicator
return true;
SField::ref fn = SField::getField(type, field);
if (fn.isInvalid())
{
WriteLog (lsWARNING, STObject) << "Unknown field: field_type=" << type << ", field_name=" << field;
throw std::runtime_error("Unknown field");
}
giveObject(makeDeserializedObject(fn.fieldType, fn, sit, depth + 1));
}
return false;
}
*/
// return true = terminated with end-of-object
bool STObject::set (SerializerIterator& sit, int depth)
{
@@ -286,7 +272,8 @@ bool STObject::set (SerializerIterator& sit, int depth)
if ((type == STI_ARRAY) && (field == 1))
{
WriteLog (lsWARNING, STObject) << "Encountered object with end of array marker";
WriteLog (lsWARNING, STObject) <<
"Encountered object with end of array marker";
throw std::runtime_error ("Illegal terminator in object");
}
@@ -298,13 +285,16 @@ bool STObject::set (SerializerIterator& sit, int depth)
if (fn.isInvalid ())
{
WriteLog (lsWARNING, STObject) << "Unknown field: field_type=" << type << ", field_name=" << field;
WriteLog (lsWARNING, STObject) <<
"Unknown field: field_type=" << type <<
", field_name=" << field;
throw std::runtime_error ("Unknown field");
}
// Unflatten the field
//
giveObject (makeDeserializedObject (fn.fieldType, fn, sit, depth + 1));
giveObject (
makeDeserializedObject (fn.fieldType, fn, sit, depth + 1));
}
}
@@ -312,12 +302,12 @@ bool STObject::set (SerializerIterator& sit, int depth)
}
std::unique_ptr<SerializedType> STObject::deserialize (SerializerIterator& sit, SField::ref name)
std::unique_ptr<SerializedType>
STObject::deserialize (SerializerIterator& sit, SField::ref name)
{
STObject* o;
std::unique_ptr<SerializedType> object (o = new STObject (name));
o->set (sit, 1);
return object;
std::unique_ptr <STObject> object (std::make_unique <STObject> (name));
object->set (sit, 1);
return std::move (object);
}
bool STObject::hasMatchingEntry (const SerializedType& t)
@@ -342,14 +332,17 @@ std::string STObject::getFullText () const
}
else ret = "{";
BOOST_FOREACH (const SerializedType & it, mData)
if (it.getSType () != STI_NOTPRESENT)
for (SerializedType const& elem : mData)
{
if (!first) ret += ", ";
else first = false;
if (elem.getSType () != STI_NOTPRESENT)
{
if (!first)
ret += ", ";
else
first = false;
ret += it.getFullText ();
ret += elem.getFullText ();
}
}
ret += "}";
@@ -360,19 +353,21 @@ void STObject::add (Serializer& s, bool withSigningFields) const
{
std::map<int, const SerializedType*> fields;
BOOST_FOREACH (const SerializedType & it, mData)
for (SerializedType const& elem : mData)
{
// pick out the fields and sort them
if ((it.getSType () != STI_NOTPRESENT) && it.getFName ().shouldInclude (withSigningFields))
fields.insert (std::make_pair (it.getFName ().fieldCode, &it));
if ((elem.getSType () != STI_NOTPRESENT) &&
elem.getFName ().shouldInclude (withSigningFields))
{
fields.insert (std::make_pair (elem.getFName ().fieldCode, &elem));
}
}
typedef std::map<int, const SerializedType*>::value_type field_iterator;
BOOST_FOREACH (field_iterator & it, fields)
for (auto const& mapEntry : fields)
{
// insert them in sorted order
const SerializedType* field = it.second;
const SerializedType* field = mapEntry.second;
// When we serialize an object inside another object,
// the type associated by rule with this field name
@@ -394,7 +389,7 @@ std::string STObject::getText () const
{
std::string ret = "{";
bool first = false;
BOOST_FOREACH (const SerializedType & it, mData)
for (SerializedType const& elem : mData)
{
if (!first)
{
@@ -402,7 +397,7 @@ std::string STObject::getText () const
first = false;
}
ret += it.getText ();
ret += elem.getText ();
}
ret += "}";
return ret;
@@ -414,12 +409,14 @@ bool STObject::isEquivalent (const SerializedType& t) const
if (!v)
{
WriteLog (lsDEBUG, STObject) << "notEquiv " << getFullText() << " not object";
WriteLog (lsDEBUG, STObject) <<
"notEquiv " << getFullText() << " not object";
return false;
}
boost::ptr_vector<SerializedType>::const_iterator it1 = mData.begin (), end1 = mData.end ();
boost::ptr_vector<SerializedType>::const_iterator it2 = v->mData.begin (), end2 = v->mData.end ();
typedef boost::ptr_vector<SerializedType>::const_iterator const_iter;
const_iter it1 = mData.begin (), end1 = mData.end ();
const_iter it2 = v->mData.begin (), end2 = v->mData.end ();
while ((it1 != end1) && (it2 != end2))
{
@@ -427,13 +424,13 @@ bool STObject::isEquivalent (const SerializedType& t) const
{
if (it1->getSType () != it2->getSType ())
{
WriteLog (lsDEBUG, STObject) << "notEquiv type " << it1->getFullText() << " != "
<< it2->getFullText();
WriteLog (lsDEBUG, STObject) << "notEquiv type " <<
it1->getFullText() << " != " << it2->getFullText();
}
else
{
WriteLog (lsDEBUG, STObject) << "notEquiv " << it1->getFullText() << " != "
<< it2->getFullText();
WriteLog (lsDEBUG, STObject) << "notEquiv " <<
it1->getFullText() << " != " << it2->getFullText();
}
return false;
}
@@ -467,7 +464,7 @@ int STObject::getFieldIndex (SField::ref field) const
return mType->getIndex (field);
int i = 0;
BOOST_FOREACH (const SerializedType & elem, mData)
for (SerializedType const& elem : mData)
{
if (elem.getFName () == field)
return i;
@@ -655,122 +652,37 @@ std::string STObject::getFieldString (SField::ref field) const
unsigned char STObject::getFieldU8 (SField::ref field) const
{
const SerializedType* rf = peekAtPField (field);
if (!rf) throw std::runtime_error ("Field not found");
SerializedTypeID id = rf->getSType ();
if (id == STI_NOTPRESENT) return 0; // optional field not present
const STUInt8* cf = dynamic_cast<const STUInt8*> (rf);
if (!cf) throw std::runtime_error ("Wrong field type");
return cf->getValue ();
return getFieldByValue <STUInt8> (field);
}
std::uint16_t STObject::getFieldU16 (SField::ref field) const
{
const SerializedType* rf = peekAtPField (field);
if (!rf) throw std::runtime_error ("Field not found");
SerializedTypeID id = rf->getSType ();
if (id == STI_NOTPRESENT) return 0; // optional field not present
const STUInt16* cf = dynamic_cast<const STUInt16*> (rf);
if (!cf) throw std::runtime_error ("Wrong field type");
return cf->getValue ();
return getFieldByValue <STUInt16> (field);
}
std::uint32_t STObject::getFieldU32 (SField::ref field) const
{
const SerializedType* rf = peekAtPField (field);
if (!rf) throw std::runtime_error ("Field not found");
SerializedTypeID id = rf->getSType ();
if (id == STI_NOTPRESENT) return 0; // optional field not present
const STUInt32* cf = dynamic_cast<const STUInt32*> (rf);
if (!cf) throw std::runtime_error ("Wrong field type");
return cf->getValue ();
return getFieldByValue <STUInt32> (field);
}
std::uint64_t STObject::getFieldU64 (SField::ref field) const
{
const SerializedType* rf = peekAtPField (field);
if (!rf) throw std::runtime_error ("Field not found");
SerializedTypeID id = rf->getSType ();
if (id == STI_NOTPRESENT) return 0; // optional field not present
const STUInt64* cf = dynamic_cast<const STUInt64*> (rf);
if (!cf) throw std::runtime_error ("Wrong field type");
return cf->getValue ();
return getFieldByValue <STUInt64> (field);
}
uint128 STObject::getFieldH128 (SField::ref field) const
{
const SerializedType* rf = peekAtPField (field);
if (!rf) throw std::runtime_error ("Field not found");
SerializedTypeID id = rf->getSType ();
if (id == STI_NOTPRESENT) return uint128 (); // optional field not present
const STHash128* cf = dynamic_cast<const STHash128*> (rf);
if (!cf) throw std::runtime_error ("Wrong field type");
return cf->getValue ();
return getFieldByValue <STHash128> (field);
}
uint160 STObject::getFieldH160 (SField::ref field) const
{
const SerializedType* rf = peekAtPField (field);
if (!rf) throw std::runtime_error ("Field not found");
SerializedTypeID id = rf->getSType ();
if (id == STI_NOTPRESENT) return uint160 (); // optional field not present
const STHash160* cf = dynamic_cast<const STHash160*> (rf);
if (!cf) throw std::runtime_error ("Wrong field type");
return cf->getValue ();
return getFieldByValue <STHash160> (field);
}
uint256 STObject::getFieldH256 (SField::ref field) const
{
const SerializedType* rf = peekAtPField (field);
if (!rf)
throw std::runtime_error ("Field not found");
SerializedTypeID id = rf->getSType ();
if (id == STI_NOTPRESENT) return uint256 (); // optional field not present
const STHash256* cf = dynamic_cast<const STHash256*> (rf);
if (!cf) throw std::runtime_error ("Wrong field type");
return cf->getValue ();
return getFieldByValue <STHash256> (field);
}
RippleAddress STObject::getFieldAccount (SField::ref field) const
@@ -782,7 +694,7 @@ RippleAddress STObject::getFieldAccount (SField::ref field) const
SerializedTypeID id = rf->getSType ();
if (id == STI_NOTPRESENT) return RippleAddress (); // optional field not present
if (id == STI_NOTPRESENT) return RippleAddress ();
const STAccount* cf = dynamic_cast<const STAccount*> (rf);
@@ -814,200 +726,66 @@ Account STObject::getFieldAccount160 (SField::ref field) const
Blob STObject::getFieldVL (SField::ref field) const
{
const SerializedType* rf = peekAtPField (field);
if (!rf) throw std::runtime_error ("Field not found");
SerializedTypeID id = rf->getSType ();
if (id == STI_NOTPRESENT) return Blob (); // optional field not present
const STVariableLength* cf = dynamic_cast<const STVariableLength*> (rf);
if (!cf) throw std::runtime_error ("Wrong field type");
return cf->getValue ();
return getFieldByValue <STVariableLength> (field);
}
STAmount const& STObject::getFieldAmount (SField::ref field) const
{
static STAmount empty;
const SerializedType* rf = peekAtPField (field);
if (!rf)
throw std::runtime_error ("Field not found");
SerializedTypeID id = rf->getSType ();
if (id == STI_NOTPRESENT)
return empty; // optional field not present
const STAmount* cf = dynamic_cast<const STAmount*> (rf);
if (!cf)
throw std::runtime_error ("Wrong field type");
return *cf;
static STAmount const empty;
return getFieldByConstRef <STAmount> (field, empty);
}
const STArray& STObject::getFieldArray (SField::ref field) const
{
static STArray empty;
const SerializedType* rf = peekAtPField (field);
if (!rf) throw std::runtime_error ("Field not found");
SerializedTypeID id = rf->getSType ();
if (id == STI_NOTPRESENT) return empty;
const STArray* cf = dynamic_cast<const STArray*> (rf);
if (!cf)
throw std::runtime_error ("Wrong field type");
return *cf;
static STArray const empty;
return getFieldByConstRef <STArray> (field, empty);
}
STPathSet const& STObject::getFieldPathSet (SField::ref field) const
{
static STPathSet empty;
const SerializedType* rf = peekAtPField (field);
if (!rf) throw std::runtime_error ("Field not found");
SerializedTypeID id = rf->getSType ();
if (id == STI_NOTPRESENT) return empty; // optional field not present
const STPathSet* cf = dynamic_cast<const STPathSet*> (rf);
if (!cf) throw std::runtime_error ("Wrong field type");
return *cf;
static STPathSet const empty;
return getFieldByConstRef <STPathSet> (field, empty);
}
const STVector256& STObject::getFieldV256 (SField::ref field) const
{
static STVector256 empty;
const SerializedType* rf = peekAtPField (field);
if (!rf) throw std::runtime_error ("Field not found");
SerializedTypeID id = rf->getSType ();
if (id == STI_NOTPRESENT) return empty; // optional field not present
const STVector256* cf = dynamic_cast<const STVector256*> (rf);
if (!cf) throw std::runtime_error ("Wrong field type");
return *cf;
static STVector256 const empty;
return getFieldByConstRef <STVector256> (field, empty);
}
void STObject::setFieldU8 (SField::ref field, unsigned char v)
{
SerializedType* rf = getPField (field, true);
if (!rf) throw std::runtime_error ("Field not found");
if (rf->getSType () == STI_NOTPRESENT) rf = makeFieldPresent (field);
STUInt8* cf = dynamic_cast<STUInt8*> (rf);
if (!cf) throw std::runtime_error ("Wrong field type");
cf->setValue (v);
setFieldUsingSetValue <STUInt8> (field, v);
}
void STObject::setFieldU16 (SField::ref field, std::uint16_t v)
{
SerializedType* rf = getPField (field, true);
if (!rf) throw std::runtime_error ("Field not found");
if (rf->getSType () == STI_NOTPRESENT) rf = makeFieldPresent (field);
STUInt16* cf = dynamic_cast<STUInt16*> (rf);
if (!cf) throw std::runtime_error ("Wrong field type");
cf->setValue (v);
setFieldUsingSetValue <STUInt16> (field, v);
}
void STObject::setFieldU32 (SField::ref field, std::uint32_t v)
{
SerializedType* rf = getPField (field, true);
if (!rf) throw std::runtime_error ("Field not found");
if (rf->getSType () == STI_NOTPRESENT) rf = makeFieldPresent (field);
STUInt32* cf = dynamic_cast<STUInt32*> (rf);
if (!cf) throw std::runtime_error ("Wrong field type");
cf->setValue (v);
setFieldUsingSetValue <STUInt32> (field, v);
}
void STObject::setFieldU64 (SField::ref field, std::uint64_t v)
{
SerializedType* rf = getPField (field, true);
if (!rf) throw std::runtime_error ("Field not found");
if (rf->getSType () == STI_NOTPRESENT) rf = makeFieldPresent (field);
STUInt64* cf = dynamic_cast<STUInt64*> (rf);
if (!cf) throw std::runtime_error ("Wrong field type");
cf->setValue (v);
setFieldUsingSetValue <STUInt64> (field, v);
}
void STObject::setFieldH128 (SField::ref field, const uint128& v)
void STObject::setFieldH128 (SField::ref field, uint128 const& v)
{
SerializedType* rf = getPField (field, true);
if (!rf) throw std::runtime_error ("Field not found");
if (rf->getSType () == STI_NOTPRESENT) rf = makeFieldPresent (field);
STHash128* cf = dynamic_cast<STHash128*> (rf);
if (!cf) throw std::runtime_error ("Wrong field type");
cf->setValue (v);
setFieldUsingSetValue <STHash128> (field, v);
}
void STObject::setFieldH256 (SField::ref field, uint256 const& v)
{
SerializedType* rf = getPField (field, true);
if (!rf) throw std::runtime_error ("Field not found");
if (rf->getSType () == STI_NOTPRESENT) rf = makeFieldPresent (field);
STHash256* cf = dynamic_cast<STHash256*> (rf);
if (!cf) throw std::runtime_error ("Wrong field type");
cf->setValue (v);
setFieldUsingSetValue <STHash256> (field, v);
}
void STObject::setFieldV256 (SField::ref field, const STVector256& v)
void STObject::setFieldV256 (SField::ref field, STVector256 const& v)
{
SerializedType* rf = getPField (field, true);
if (!rf) throw std::runtime_error ("Field not found");
if (rf->getSType () == STI_NOTPRESENT) rf = makeFieldPresent (field);
STVector256* cf = dynamic_cast<STVector256*> (rf);
if (!cf) throw std::runtime_error ("Wrong field type");
cf->setValue (v);
setFieldUsingSetValue <STVector256> (field, v);
}
void STObject::setFieldAccount (SField::ref field, Account const& v)
@@ -1030,47 +808,22 @@ void STObject::setFieldAccount (SField::ref field, Account const& v)
void STObject::setFieldVL (SField::ref field, Blob const& v)
{
SerializedType* rf = getPField (field, true);
if (!rf) throw std::runtime_error ("Field not found");
if (rf->getSType () == STI_NOTPRESENT) rf = makeFieldPresent (field);
STVariableLength* cf = dynamic_cast<STVariableLength*> (rf);
if (!cf) throw std::runtime_error ("Wrong field type");
cf->setValue (v);
setFieldUsingSetValue <STVariableLength> (field, v);
}
void STObject::setFieldAmount (SField::ref field, STAmount const& v)
{
SerializedType* rf = getPField (field, true);
if (!rf) throw std::runtime_error ("Field not found");
if (rf->getSType () == STI_NOTPRESENT) rf = makeFieldPresent (field);
STAmount* cf = dynamic_cast<STAmount*> (rf);
if (!cf) throw std::runtime_error ("Wrong field type");
(*cf) = v;
setFieldUsingAssignment (field, v);
}
void STObject::setFieldPathSet (SField::ref field, STPathSet const& v)
{
SerializedType* rf = getPField (field, true);
setFieldUsingAssignment (field, v);
}
if (!rf) throw std::runtime_error ("Field not found");
if (rf->getSType () == STI_NOTPRESENT) rf = makeFieldPresent (field);
STPathSet* cf = dynamic_cast<STPathSet*> (rf);
if (!cf) throw std::runtime_error ("Wrong field type");
(*cf) = v;
void STObject::setFieldArray (SField::ref field, STArray const& v)
{
setFieldUsingAssignment (field, v);
}
Json::Value STObject::getJson (int options) const
@@ -1094,42 +847,49 @@ Json::Value STObject::getJson (int options) const
bool STObject::operator== (const STObject& obj) const
{
// This is not particularly efficient, and only compares data elements with binary representations
// This is not particularly efficient, and only compares data elements
// with binary representations
int matches = 0;
BOOST_FOREACH (const SerializedType & t, mData)
if ((t.getSType () != STI_NOTPRESENT) && t.getFName ().isBinary ())
for (SerializedType const& t1 : mData)
{
// each present field must have a matching field
bool match = false;
BOOST_FOREACH (const SerializedType & t2, obj.mData)
if (t.getFName () == t2.getFName ())
if ((t1.getSType () != STI_NOTPRESENT) && t1.getFName ().isBinary ())
{
if (t2 != t)
// each present field must have a matching field
bool match = false;
for (SerializedType const& t2 : obj.mData)
{
if (t1.getFName () == t2.getFName ())
{
if (t2 != t1)
return false;
match = true;
++matches;
break;
}
}
if (!match)
{
WriteLog (lsTRACE, STObject) <<
"STObject::operator==: no match for " <<
t1.getFName ().getName ();
return false;
match = true;
++matches;
break;
}
if (!match)
{
WriteLog (lsTRACE, STObject) << "STObject::operator==: no match for " << t.getFName ().getName ();
return false;
}
}
}
int fields = 0;
BOOST_FOREACH (const SerializedType & t2, obj.mData)
if ((t2.getSType () != STI_NOTPRESENT) && t2.getFName ().isBinary ())
++fields;
for (SerializedType const& t2 : obj.mData)
{
if ((t2.getSType () != STI_NOTPRESENT) && t2.getFName ().isBinary ())
++fields;
}
if (fields != matches)
{
WriteLog (lsTRACE, STObject) << "STObject::operator==: " << fields << " fields, " << matches << " matches";
WriteLog (lsTRACE, STObject) << "STObject::operator==: " <<
fields << " fields, " << matches << " matches";
return false;
}
@@ -1146,128 +906,6 @@ Json::Value STVector256::getJson (int options) const
return ret;
}
std::string STArray::getFullText () const
{
std::string r = "[";
bool first = true;
BOOST_FOREACH (const STObject & o, value)
{
if (!first)
r += ",";
r += o.getFullText ();
first = false;
}
r += "]";
return r;
}
std::string STArray::getText () const
{
std::string r = "[";
bool first = true;
BOOST_FOREACH (const STObject & o, value)
{
if (!first)
r += ",";
r += o.getText ();
first = false;
}
r += "]";
return r;
}
Json::Value STArray::getJson (int p) const
{
Json::Value v = Json::arrayValue;
int index = 1;
for (auto const& object: value)
{
if (object.getSType () != STI_NOTPRESENT)
{
Json::Value inner = Json::objectValue;
auto const& fname = object.getFName ();
auto k = fname.hasName () ? fname.fieldName : std::to_string(index);
inner[k] = object.getJson (p);
v.append (inner);
index++;
}
}
return v;
}
void STArray::add (Serializer& s) const
{
BOOST_FOREACH (const STObject & object, value)
{
object.addFieldID (s);
object.add (s);
s.addFieldID (STI_OBJECT, 1);
}
}
bool STArray::isEquivalent (const SerializedType& t) const
{
const STArray* v = dynamic_cast<const STArray*> (&t);
if (!v)
{
WriteLog (lsDEBUG, STObject) << "notEquiv " << getFullText() << " not array";
return false;
}
return value == v->value;
}
STArray* STArray::construct (SerializerIterator& sit, SField::ref field)
{
vector value;
while (!sit.empty ())
{
int type, field;
sit.getFieldID (type, field);
if ((type == STI_ARRAY) && (field == 1))
break;
if ((type == STI_OBJECT) && (field == 1))
{
WriteLog (lsWARNING, STObject) << "Encountered array with end of object marker";
throw std::runtime_error ("Illegal terminator in array");
}
SField::ref fn = SField::getField (type, field);
if (fn.isInvalid ())
{
WriteLog (lsTRACE, STObject) << "Unknown field: " << type << "/" << field;
throw std::runtime_error ("Unknown field");
}
if (fn.fieldType != STI_OBJECT)
{
WriteLog (lsTRACE, STObject) << "Array contains non-object";
throw std::runtime_error ("Non-object in array");
}
value.push_back (new STObject (fn));
value.rbegin ()->set (sit, 1);
}
return new STArray (field, value);
}
void STArray::sort (bool (*compare) (const STObject&, const STObject&))
{
value.sort (compare);
}
//------------------------------------------------------------------------------
class SerializedObject_test : public beast::unit_test::suite
@@ -1329,7 +967,8 @@ public:
void testParseJSONArray ()
{
testcase ("parse json array");
std::string const json ("{\"Template\":[{\"ModifiedNode\":{\"Sequence\":1}}]}\n");
std::string const json (
"{\"Template\":[{\"ModifiedNode\":{\"Sequence\":1}}]}\n");
Json::Value jsonObject;
bool parsedOK (parseJSONString(json, jsonObject));
@@ -1367,16 +1006,18 @@ public:
STObject object1 (elements, sfTestObject);
STObject object2 (object1);
unexpected (object1.getSerializer () != object2.getSerializer (), "STObject error 1");
unexpected (object1.getSerializer () != object2.getSerializer (),
"STObject error 1");
unexpected (object1.isFieldPresent (sfTestH256) || !object1.isFieldPresent (sfTestVL),
"STObject error");
unexpected (object1.isFieldPresent (sfTestH256) ||
!object1.isFieldPresent (sfTestVL), "STObject error");
object1.makeFieldPresent (sfTestH256);
unexpected (!object1.isFieldPresent (sfTestH256), "STObject Error 2");
unexpected (object1.getFieldH256 (sfTestH256) != uint256 (), "STObject error 3");
unexpected (object1.getFieldH256 (sfTestH256) != uint256 (),
"STObject error 3");
if (object1.getSerializer () == object2.getSerializer ())
{
@@ -1395,7 +1036,8 @@ public:
unexpected (object1.getFlags () != 0, "STObject error 6");
unexpected (object1.getSerializer () != object2.getSerializer (), "STObject error 7");
unexpected (object1.getSerializer () != object2.getSerializer (),
"STObject error 7");
STObject copy (object1);
@@ -1403,11 +1045,13 @@ public:
unexpected (copy.isFieldPresent (sfTestH256), "STObject error 9");
unexpected (object1.getSerializer () != copy.getSerializer (), "STObject error 10");
unexpected (object1.getSerializer () != copy.getSerializer (),
"STObject error 10");
copy.setFieldU32 (sfTestU32, 1);
unexpected (object1.getSerializer () == copy.getSerializer (), "STObject error 11");
unexpected (object1.getSerializer () == copy.getSerializer (),
"STObject error 11");
for (int i = 0; i < 1000; i++)
{

View File

@@ -17,10 +17,10 @@
*/
//==============================================================================
#ifndef RIPPLE_SERIALIZEDOBJECT_H
#define RIPPLE_SERIALIZEDOBJECT_H
#ifndef RIPPLE_STOBJECT_H
#define RIPPLE_STOBJECT_H
#include <boost/ptr_container/ptr_vector.hpp> // VFALCO NOTE this looks like junk
#include <boost/ptr_container/ptr_vector.hpp>
namespace ripple {
@@ -38,35 +38,41 @@ public:
;
}
explicit STObject (SField::ref name) : SerializedType (name), mType (nullptr)
explicit STObject (SField::ref name)
: SerializedType (name), mType (nullptr)
{
;
}
STObject (const SOTemplate & type, SField::ref name) : SerializedType (name)
STObject (const SOTemplate & type, SField::ref name)
: SerializedType (name)
{
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);
}
STObject (SField::ref name, boost::ptr_vector<SerializedType>& data) : SerializedType (name), mType (nullptr)
STObject (SField::ref name, boost::ptr_vector<SerializedType>& data)
: SerializedType (name), mType (nullptr)
{
mData.swap (data);
}
std::unique_ptr <STObject> oClone () const
{
return std::unique_ptr<STObject> (new STObject (*this));
return std::make_unique <STObject> (*this);
}
virtual ~STObject () { }
static std::unique_ptr<SerializedType> deserialize (SerializerIterator & sit, SField::ref name);
static std::unique_ptr<SerializedType>
deserialize (SerializerIterator & sit, SField::ref name);
bool setType (const SOTemplate & type);
bool isValidForType ();
@@ -79,24 +85,25 @@ public:
void set (const SOTemplate&);
bool set (SerializerIterator & u, int depth = 0);
virtual SerializedTypeID getSType () const
virtual SerializedTypeID getSType () const override
{
return STI_OBJECT;
}
virtual bool isEquivalent (const SerializedType & t) const;
virtual bool isDefault () const
virtual bool isEquivalent (const SerializedType & t) const override;
virtual bool isDefault () const override
{
return mData.empty ();
}
virtual void add (Serializer & s) const
virtual void add (Serializer & s) const override
{
add (s, true); // just inner elements
}
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.
Serializer getSerializer () const
{
@@ -105,11 +112,11 @@ public:
return s;
}
std::string getFullText () const;
std::string getText () const;
virtual std::string getFullText () const override;
virtual std::string getText () const override;
// TODO(tom): options should be an enum.
virtual Json::Value getJson (int options) const;
virtual Json::Value getJson (int options) const override;
int addObject (const SerializedType & t)
{
@@ -189,8 +196,8 @@ public:
const SerializedType* peekAtPField (SField::ref field) const;
SerializedType* getPField (SField::ref field, bool createOkay = false);
// these throw if the field type doesn't match, or return default values if the
// field is optional but not present
// these throw if the field type doesn't match, or return default values
// if the field is optional but not present
std::string getFieldString (SField::ref field) const;
unsigned char getFieldU8 (SField::ref field) const;
std::uint16_t getFieldU16 (SField::ref field) const;
@@ -213,17 +220,18 @@ public:
void setFieldU16 (SField::ref field, std::uint16_t);
void setFieldU32 (SField::ref field, std::uint32_t);
void setFieldU64 (SField::ref field, std::uint64_t);
void setFieldH128 (SField::ref field, const uint128&);
void setFieldH128 (SField::ref field, uint128 const&);
void setFieldH256 (SField::ref field, uint256 const& );
void setFieldVL (SField::ref field, Blob const&);
void setFieldAccount (SField::ref field, Account const&);
void setFieldAccount (SField::ref field, const RippleAddress & addr)
void setFieldAccount (SField::ref field, RippleAddress const& addr)
{
setFieldAccount (field, addr.getAccountID ());
}
void setFieldAmount (SField::ref field, STAmount const&);
void setFieldPathSet (SField::ref field, STPathSet const&);
void setFieldV256 (SField::ref field, const STVector256 & v);
void setFieldV256 (SField::ref field, STVector256 const& v);
void setFieldArray (SField::ref field, STArray const& v);
template <class Tag>
void setFieldH160 (SField::ref field, base_uint<160, Tag> const& v)
@@ -251,7 +259,8 @@ public:
bool delField (SField::ref field);
void delField (int index);
static std::unique_ptr <SerializedType> makeDefaultObject (SerializedTypeID id, SField::ref name);
static std::unique_ptr <SerializedType>
makeDefaultObject (SerializedTypeID id, SField::ref name);
// VFALCO TODO remove the 'depth' parameter
static std::unique_ptr<SerializedType> makeDeserializedObject (
@@ -260,7 +269,8 @@ public:
SerializerIterator&,
int depth);
static std::unique_ptr<SerializedType> makeNonPresentObject (SField::ref name)
static std::unique_ptr<SerializedType>
makeNonPresentObject (SField::ref name)
{
return makeDefaultObject (STI_NOTPRESENT, name);
}
@@ -303,229 +313,110 @@ public:
}
private:
/** Returns a value or throws if out of range.
This will throw if the source value cannot be represented
within the destination type.
*/
// VFALCO NOTE This won't work right
/*
template <class T, class U>
static T getWithRangeCheck (U v)
{
if (v < std::numeric_limits <T>::min ()) ||
v > std::numeric_limits <T>::max ())
{
throw std::runtime_error ("Value out of range");
}
return static_cast <T> (v);
}
*/
STObject* duplicate () const
virtual STObject* duplicate () const override
{
return new STObject (*this);
}
// Implementation for getting (most) fields that return by value.
//
// The remove_cv and remove_reference are necessitated by the STBitString
// types. Their getValue returns by const ref. We return those types
// by value.
template <typename T, typename V =
typename std::remove_cv < typename std::remove_reference <
decltype (std::declval <T> ().getValue ())>::type >::type >
V getFieldByValue (SField::ref field) const
{
const SerializedType* rf = peekAtPField (field);
if (!rf)
throw std::runtime_error ("Field not found");
SerializedTypeID id = rf->getSType ();
if (id == STI_NOTPRESENT)
return V (); // optional field not present
const T* cf = dynamic_cast<const T*> (rf);
if (!cf)
throw std::runtime_error ("Wrong field type");
return cf->getValue ();
}
// Implementations for getting (most) fields that return by const reference.
//
// If an absent optional field is deserialized we don't have anything
// obvious to return. So we insist on having the call provide an
// 'empty' value we return in that circumstance.
template <typename T, typename V>
V const& getFieldByConstRef (SField::ref field, V const& empty) const
{
const SerializedType* rf = peekAtPField (field);
if (!rf)
throw std::runtime_error ("Field not found");
SerializedTypeID id = rf->getSType ();
if (id == STI_NOTPRESENT)
return empty; // optional field not present
const T* cf = dynamic_cast<const T*> (rf);
if (!cf)
throw std::runtime_error ("Wrong field type");
return *cf;
}
// Implementation for setting most fields with a setValue() method.
template <typename T, typename V>
void setFieldUsingSetValue (SField::ref field, V value)
{
SerializedType* rf = getPField (field, true);
if (!rf)
throw std::runtime_error ("Field not found");
if (rf->getSType () == STI_NOTPRESENT)
rf = makeFieldPresent (field);
T* cf = dynamic_cast<T*> (rf);
if (!cf)
throw std::runtime_error ("Wrong field type");
cf->setValue (value);
}
// Implementation for setting fields using assignment
template <typename T>
void setFieldUsingAssignment (SField::ref field, T const& value)
{
SerializedType* rf = getPField (field, true);
if (!rf)
throw std::runtime_error ("Field not found");
if (rf->getSType () == STI_NOTPRESENT)
rf = makeFieldPresent (field);
T* cf = dynamic_cast<T*> (rf);
if (!cf)
throw std::runtime_error ("Wrong field type");
(*cf) = value;
}
private:
boost::ptr_vector<SerializedType> mData;
const SOTemplate* mType;
};
//------------------------------------------------------------------------------
// VFALCO TODO these parameters should not be const references.
template <typename T, typename U>
static T range_check_cast (const U& value, const T& minimum, const T& maximum)
{
if ((value < minimum) || (value > maximum))
throw std::runtime_error ("Value out of range");
return static_cast<T> (value);
}
//------------------------------------------------------------------------------
class STArray
: public SerializedType
, public CountedObject <STArray>
{
public:
static char const* getCountedObjectName () { return "STArray"; }
typedef boost::ptr_vector<STObject> vector;
typedef boost::ptr_vector<STObject>::iterator iterator;
typedef boost::ptr_vector<STObject>::const_iterator const_iterator;
typedef boost::ptr_vector<STObject>::reverse_iterator reverse_iterator;
typedef boost::ptr_vector<STObject>::const_reverse_iterator const_reverse_iterator;
typedef boost::ptr_vector<STObject>::size_type size_type;
public:
STArray ()
{
;
}
explicit STArray (int n)
{
value.reserve (n);
}
explicit STArray (SField::ref f) : SerializedType (f)
{
;
}
STArray (SField::ref f, int n) : SerializedType (f)
{
value.reserve (n);
}
STArray (SField::ref f, const vector & v) : SerializedType (f), value (v)
{
;
}
explicit STArray (vector & v) : value (v)
{
;
}
static std::unique_ptr<SerializedType> deserialize (SerializerIterator & sit, SField::ref name)
{
return std::unique_ptr<SerializedType> (construct (sit, name));
}
const vector& getValue () const
{
return value;
}
vector& getValue ()
{
return value;
}
// VFALCO NOTE as long as we're married to boost why not use boost::iterator_facade?
//
// vector-like functions
void push_back (const STObject & object)
{
value.push_back (object.oClone ().release ());
}
STObject& operator[] (int j)
{
return value[j];
}
const STObject& operator[] (int j) const
{
return value[j];
}
iterator begin ()
{
return value.begin ();
}
const_iterator begin () const
{
return value.begin ();
}
iterator end ()
{
return value.end ();
}
const_iterator end () const
{
return value.end ();
}
size_type size () const
{
return value.size ();
}
reverse_iterator rbegin ()
{
return value.rbegin ();
}
const_reverse_iterator rbegin () const
{
return value.rbegin ();
}
reverse_iterator rend ()
{
return value.rend ();
}
const_reverse_iterator rend () const
{
return value.rend ();
}
iterator erase (iterator pos)
{
return value.erase (pos);
}
STObject& front ()
{
return value.front ();
}
const STObject& front () const
{
return value.front ();
}
STObject& back ()
{
return value.back ();
}
const STObject& back () const
{
return value.back ();
}
void pop_back ()
{
value.pop_back ();
}
bool empty () const
{
return value.empty ();
}
void clear ()
{
value.clear ();
}
void swap (STArray & a)
{
value.swap (a.value);
}
virtual std::string getFullText () const;
virtual std::string getText () const;
virtual Json::Value getJson (int index) const;
virtual void add (Serializer & s) const;
void sort (bool (*compare) (const STObject & o1, const STObject & o2));
bool operator== (const STArray & s)
{
return value == s.value;
}
bool operator!= (const STArray & s)
{
return value != s.value;
}
virtual SerializedTypeID getSType () const
{
return STI_ARRAY;
}
virtual bool isEquivalent (const SerializedType & t) const;
virtual bool isDefault () const
{
return value.empty ();
}
private:
vector value;
STArray* duplicate () const
{
return new STArray (*this);
}
static STArray* construct (SerializerIterator&, SField::ref);
};
} // ripple
#endif

View File

@@ -23,6 +23,17 @@
namespace ripple {
template <typename T, typename U>
static T range_check_cast (U value, T minimum, T maximum)
{
if ((value < minimum) || (value > maximum))
throw std::runtime_error ("Value out of range");
return static_cast<T> (value);
}
//------------------------------------------------------------------------------
STParsedJSON::STParsedJSON (std::string const& name, Json::Value const& json)
{
parse (name, json, sfGeneric, 0, object);

View File

@@ -75,7 +75,8 @@
#include <ripple/module/data/protocol/SerializedTypes.cpp>
#include <ripple/module/data/protocol/Serializer.cpp>
#include <ripple/module/data/protocol/SerializedObjectTemplate.cpp>
#include <ripple/module/data/protocol/SerializedObject.cpp>
#include <ripple/module/data/protocol/STObject.cpp>
#include <ripple/module/data/protocol/STArray.cpp>
#include <ripple/module/data/protocol/TER.cpp>
#include <ripple/module/data/protocol/TxFormats.cpp>

View File

@@ -39,10 +39,11 @@ typedef struct bignum_st BIGNUM;
#include <ripple/module/data/protocol/TER.h>
#include <ripple/module/data/protocol/SerializedTypes.h> // needs Serializer, TER
#include <ripple/module/data/protocol/SerializedObjectTemplate.h>
#include <ripple/module/data/protocol/KnownFormats.h>
#include <ripple/module/data/protocol/LedgerFormats.h> // needs SOTemplate from SerializedObjectTemplate
#include <ripple/module/data/protocol/TxFormats.h>
#include <ripple/module/data/protocol/SerializedObject.h>
#include <ripple/module/data/protocol/KnownFormats.h>
#include <ripple/module/data/protocol/LedgerFormats.h> // needs SOTemplate from SerializedObjectTemplate
#include <ripple/module/data/protocol/TxFormats.h>
#include <ripple/module/data/protocol/STObject.h>
#include <ripple/module/data/protocol/STArray.h>
#include <ripple/module/data/protocol/TxFlags.h>
#include <ripple/module/data/utility/UptimeTimerAdapter.h>