diff --git a/src/ripple/module/app/book/Amount.h b/src/ripple/module/app/book/Amount.h index 50e82dcbc..acd3747dc 100644 --- a/src/ripple/module/app/book/Amount.h +++ b/src/ripple/module/app/book/Amount.h @@ -20,7 +20,7 @@ #ifndef RIPPLE_CORE_AMOUNT_H_INCLUDED #define RIPPLE_CORE_AMOUNT_H_INCLUDED -#include +#include #include #include // diff --git a/src/ripple/module/data/protocol/STArray.cpp b/src/ripple/module/data/protocol/STArray.cpp new file mode 100644 index 000000000..14b336b28 --- /dev/null +++ b/src/ripple/module/data/protocol/STArray.cpp @@ -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 +STArray::deserialize (SerializerIterator& sit, SField::ref field) +{ + std::unique_ptr ret (std::make_unique (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 (&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 diff --git a/src/ripple/module/data/protocol/STArray.h b/src/ripple/module/data/protocol/STArray.h new file mode 100644 index 000000000..9389743e0 --- /dev/null +++ b/src/ripple/module/data/protocol/STArray.h @@ -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 +#include + +namespace ripple { + +class STArray final + : public SerializedType + , public CountedObject +{ +public: + static char const* getCountedObjectName () { return "STArray"; } + + typedef boost::ptr_vector 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 + 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 diff --git a/src/ripple/module/data/protocol/SerializedObject.cpp b/src/ripple/module/data/protocol/STObject.cpp similarity index 56% rename from src/ripple/module/data/protocol/SerializedObject.cpp rename to src/ripple/module/data/protocol/STObject.cpp index dff2ef9d8..b317af349 100644 --- a/src/ripple/module/data/protocol/SerializedObject.cpp +++ b/src/ripple/module/data/protocol/STObject.cpp @@ -17,68 +17,73 @@ */ //============================================================================== +#include // + namespace ripple { -std::unique_ptr STObject::makeDefaultObject (SerializedTypeID id, SField::ref name) +std::unique_ptr +STObject::makeDefaultObject (SerializedTypeID id, SField::ref name) { assert ((id == STI_NOTPRESENT) || (id == name.fieldType)); switch (id) { case STI_NOTPRESENT: - return std::unique_ptr (new SerializedType (name)); + return std::make_unique (name); case STI_UINT8: - return std::unique_ptr (new STUInt8 (name)); + return std::make_unique (name); case STI_UINT16: - return std::unique_ptr (new STUInt16 (name)); + return std::make_unique (name); case STI_UINT32: - return std::unique_ptr (new STUInt32 (name)); + return std::make_unique (name); case STI_UINT64: - return std::unique_ptr (new STUInt64 (name)); + return std::make_unique (name); case STI_AMOUNT: - return std::unique_ptr (new STAmount (name)); + return std::make_unique (name); case STI_HASH128: - return std::unique_ptr (new STHash128 (name)); + return std::make_unique (name); case STI_HASH160: - return std::unique_ptr (new STHash160 (name)); + return std::make_unique (name); case STI_HASH256: - return std::unique_ptr (new STHash256 (name)); + return std::make_unique (name); case STI_VECTOR256: - return std::unique_ptr (new STVector256 (name)); + return std::make_unique (name); case STI_VL: - return std::unique_ptr (new STVariableLength (name)); + return std::make_unique (name); case STI_ACCOUNT: - return std::unique_ptr (new STAccount (name)); + return std::make_unique (name); case STI_PATHSET: - return std::unique_ptr (new STPathSet (name)); + return std::make_unique (name); case STI_OBJECT: - return std::unique_ptr (new STObject (name)); + return std::make_unique (name); case STI_ARRAY: - return std::unique_ptr (new STArray (name)); + return std::make_unique (name); default: - WriteLog (lsFATAL, STObject) << "Object type: " << beast::lexicalCast (id); + WriteLog (lsFATAL, STObject) << + "Object type: " << beast::lexicalCast (id); assert (false); throw std::runtime_error ("Unknown object type"); } } // VFALCO TODO Remove the 'depth' parameter -std::unique_ptr STObject::makeDeserializedObject (SerializedTypeID id, SField::ref name, +std::unique_ptr +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 STObject::deserialize (SerializerIterator& sit, SField::ref name) +std::unique_ptr +STObject::deserialize (SerializerIterator& sit, SField::ref name) { - STObject* o; - std::unique_ptr object (o = new STObject (name)); - o->set (sit, 1); - return object; + std::unique_ptr object (std::make_unique (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 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::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::const_iterator it1 = mData.begin (), end1 = mData.end (); - boost::ptr_vector::const_iterator it2 = v->mData.begin (), end2 = v->mData.end (); + typedef boost::ptr_vector::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 (rf); - - if (!cf) throw std::runtime_error ("Wrong field type"); - - return cf->getValue (); + return getFieldByValue (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 (rf); - - if (!cf) throw std::runtime_error ("Wrong field type"); - - return cf->getValue (); + return getFieldByValue (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 (rf); - - if (!cf) throw std::runtime_error ("Wrong field type"); - - return cf->getValue (); + return getFieldByValue (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 (rf); - - if (!cf) throw std::runtime_error ("Wrong field type"); - - return cf->getValue (); + return getFieldByValue (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 (rf); - - if (!cf) throw std::runtime_error ("Wrong field type"); - - return cf->getValue (); + return getFieldByValue (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 (rf); - - if (!cf) throw std::runtime_error ("Wrong field type"); - - return cf->getValue (); + return getFieldByValue (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 (rf); - - if (!cf) throw std::runtime_error ("Wrong field type"); - - return cf->getValue (); + return getFieldByValue (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 (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 (rf); - - if (!cf) throw std::runtime_error ("Wrong field type"); - - return cf->getValue (); + return getFieldByValue (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 (rf); - - if (!cf) - throw std::runtime_error ("Wrong field type"); - - return *cf; + static STAmount const empty; + return getFieldByConstRef (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 (rf); - - if (!cf) - throw std::runtime_error ("Wrong field type"); - - return *cf; + static STArray const empty; + return getFieldByConstRef (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 (rf); - - if (!cf) throw std::runtime_error ("Wrong field type"); - - return *cf; + static STPathSet const empty; + return getFieldByConstRef (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 (rf); - - if (!cf) throw std::runtime_error ("Wrong field type"); - - return *cf; + static STVector256 const empty; + return getFieldByConstRef (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 (rf); - - if (!cf) throw std::runtime_error ("Wrong field type"); - - cf->setValue (v); + setFieldUsingSetValue (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 (rf); - - if (!cf) throw std::runtime_error ("Wrong field type"); - - cf->setValue (v); + setFieldUsingSetValue (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 (rf); - - if (!cf) throw std::runtime_error ("Wrong field type"); - - cf->setValue (v); + setFieldUsingSetValue (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 (rf); - - if (!cf) throw std::runtime_error ("Wrong field type"); - - cf->setValue (v); + setFieldUsingSetValue (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 (rf); - - if (!cf) throw std::runtime_error ("Wrong field type"); - - cf->setValue (v); + setFieldUsingSetValue (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 (rf); - - if (!cf) throw std::runtime_error ("Wrong field type"); - - cf->setValue (v); + setFieldUsingSetValue (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 (rf); - - if (!cf) throw std::runtime_error ("Wrong field type"); - - cf->setValue (v); + setFieldUsingSetValue (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 (rf); - - if (!cf) throw std::runtime_error ("Wrong field type"); - - cf->setValue (v); + setFieldUsingSetValue (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 (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 (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 (&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++) { diff --git a/src/ripple/module/data/protocol/SerializedObject.h b/src/ripple/module/data/protocol/STObject.h similarity index 56% rename from src/ripple/module/data/protocol/SerializedObject.h rename to src/ripple/module/data/protocol/STObject.h index 88406e271..01607f4fb 100644 --- a/src/ripple/module/data/protocol/SerializedObject.h +++ b/src/ripple/module/data/protocol/STObject.h @@ -17,10 +17,10 @@ */ //============================================================================== -#ifndef RIPPLE_SERIALIZEDOBJECT_H -#define RIPPLE_SERIALIZEDOBJECT_H +#ifndef RIPPLE_STOBJECT_H +#define RIPPLE_STOBJECT_H -#include // VFALCO NOTE this looks like junk +#include 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& data) : SerializedType (name), mType (nullptr) + STObject (SField::ref name, boost::ptr_vector& data) + : SerializedType (name), mType (nullptr) { mData.swap (data); } std::unique_ptr oClone () const { - return std::unique_ptr (new STObject (*this)); + return std::make_unique (*this); } virtual ~STObject () { } - static std::unique_ptr deserialize (SerializerIterator & sit, SField::ref name); + static std::unique_ptr + 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 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 makeDefaultObject (SerializedTypeID id, SField::ref name); + static std::unique_ptr + makeDefaultObject (SerializedTypeID id, SField::ref name); // VFALCO TODO remove the 'depth' parameter static std::unique_ptr makeDeserializedObject ( @@ -260,7 +269,8 @@ public: SerializerIterator&, int depth); - static std::unique_ptr makeNonPresentObject (SField::ref name) + static std::unique_ptr + 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 - static T getWithRangeCheck (U v) - { - if (v < std::numeric_limits ::min ()) || - v > std::numeric_limits ::max ()) - { - throw std::runtime_error ("Value out of range"); - } - - return static_cast (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 ().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 (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 + 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 (rf); + + if (!cf) + throw std::runtime_error ("Wrong field type"); + + return *cf; + } + + // Implementation for setting most fields with a setValue() method. + template + 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 (rf); + + if (!cf) + throw std::runtime_error ("Wrong field type"); + + cf->setValue (value); + } + + // Implementation for setting fields using assignment + template + 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 (rf); + + if (!cf) + throw std::runtime_error ("Wrong field type"); + + (*cf) = value; + } + private: boost::ptr_vector mData; const SOTemplate* mType; }; -//------------------------------------------------------------------------------ - -// VFALCO TODO these parameters should not be const references. -template -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 (value); -} - -//------------------------------------------------------------------------------ - -class STArray - : public SerializedType - , public CountedObject -{ -public: - static char const* getCountedObjectName () { return "STArray"; } - - typedef boost::ptr_vector vector; - typedef boost::ptr_vector::iterator iterator; - typedef boost::ptr_vector::const_iterator const_iterator; - typedef boost::ptr_vector::reverse_iterator reverse_iterator; - typedef boost::ptr_vector::const_reverse_iterator const_reverse_iterator; - typedef boost::ptr_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) - { - ; - } - - static std::unique_ptr deserialize (SerializerIterator & sit, SField::ref name) - { - return std::unique_ptr (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 diff --git a/src/ripple/module/data/protocol/STParsedJSON.cpp b/src/ripple/module/data/protocol/STParsedJSON.cpp index 2471cb542..8f0e9ed5e 100644 --- a/src/ripple/module/data/protocol/STParsedJSON.cpp +++ b/src/ripple/module/data/protocol/STParsedJSON.cpp @@ -23,6 +23,17 @@ namespace ripple { +template +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 (value); +} + +//------------------------------------------------------------------------------ + STParsedJSON::STParsedJSON (std::string const& name, Json::Value const& json) { parse (name, json, sfGeneric, 0, object); diff --git a/src/ripple/unity/data.cpp b/src/ripple/unity/data.cpp index d3250964d..010e66177 100644 --- a/src/ripple/unity/data.cpp +++ b/src/ripple/unity/data.cpp @@ -75,7 +75,8 @@ #include #include #include -#include +#include +#include #include #include diff --git a/src/ripple/unity/data.h b/src/ripple/unity/data.h index f278f44e6..337464687 100644 --- a/src/ripple/unity/data.h +++ b/src/ripple/unity/data.h @@ -39,10 +39,11 @@ typedef struct bignum_st BIGNUM; #include #include // needs Serializer, TER #include - #include - #include // needs SOTemplate from SerializedObjectTemplate - #include -#include +#include +#include // needs SOTemplate from SerializedObjectTemplate +#include +#include +#include #include #include