Add operator[] field accessors to STObject:

New array index operators allow for concise reading and
writing of fields in the STObject, with associated unit test.
This commit is contained in:
Vinnie Falco
2015-07-24 21:06:16 -07:00
committed by Edward Hennis
parent 3e342e4b71
commit 2ec40cb6f1
14 changed files with 1230 additions and 249 deletions

View File

@@ -20,6 +20,7 @@
#ifndef RIPPLE_BASICS_BUFFER_H_INCLUDED
#define RIPPLE_BASICS_BUFFER_H_INCLUDED
#include <ripple/basics/Slice.h>
#include <beast/utility/noexcept.h>
#include <cstdint>
#include <cstring>
@@ -80,6 +81,13 @@ public:
std::memcpy(p_.get(), data, size);
}
/** Create a buffer from a copy of existing memory. */
explicit
Buffer (Slice const& slice)
: Buffer(slice.data(), slice.size())
{
}
/** Returns the number of bytes in the buffer. */
std::size_t
size() const noexcept
@@ -93,6 +101,13 @@ public:
return 0 == size_;
}
operator Slice() const noexcept
{
if (! size_)
return Slice{};
return Slice{ p_.get(), size_ };
}
/** Return a pointer to beginning of the storage.
@note The return type is guaranteed to be a pointer
to a single byte, to facilitate pointer arithmetic.

View File

@@ -58,8 +58,6 @@ public:
std::uint8_t const*>(data))
, size_ (size)
{
assert(data_ != nullptr);
assert(size_ > 0);
}
/** Return `true` if the byte range is empty. */

View File

@@ -97,6 +97,11 @@ public:
return { buf_, size_ };
}
operator Slice() const noexcept
{
return slice();
}
bool
verify (Slice const& message, Slice const& sig,
bool mustBeFullyCanonical) const;

View File

@@ -27,10 +27,26 @@
namespace ripple {
/*
Some fields have a different meaning for their
default value versus not present.
Example:
QualityIn on a TrustLine
*/
//------------------------------------------------------------------------------
// Forwards
class STAccount;
class STAmount;
class STBlob;
template <std::size_t>
class STBitString;
template <class>
class STInteger;
class STVector256;
enum SerializedTypeID
{
@@ -280,6 +296,45 @@ struct TypedField : SField
}
};
/** Indicate boost::optional field semantics. */
template <class T>
struct OptionaledField
{
TypedField<T> const* f;
explicit
OptionaledField (TypedField<T> const& f_)
: f (&f_)
{
}
};
template <class T>
inline
OptionaledField<T>
operator~(TypedField<T> const& f)
{
return OptionaledField<T>(f);
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
using SF_U8 = TypedField<STInteger<std::uint8_t>>;
using SF_U16 = TypedField<STInteger<std::uint16_t>>;
using SF_U32 = TypedField<STInteger<std::uint32_t>>;
using SF_U64 = TypedField<STInteger<std::uint64_t>>;
using SF_U128 = TypedField<STBitString<128>>;
using SF_U160 = TypedField<STBitString<160>>;
using SF_U256 = TypedField<STBitString<256>>;
using SF_Account = TypedField<STAccount>;
using SF_Amount = TypedField<STAmount>;
using SF_Blob = TypedField<STBlob>;
using SF_Vec256 = TypedField<STVector256>;
//------------------------------------------------------------------------------
extern SField const sfInvalid;
extern SField const sfGeneric;
extern SField const sfLedgerEntry;
@@ -288,139 +343,141 @@ extern SField const sfValidation;
extern SField const sfMetadata;
// 8-bit integers
extern SField const sfCloseResolution;
extern SField const sfTemplateEntryType;
extern SField const sfTransactionResult;
extern SF_U8 const sfCloseResolution;
extern SF_U8 const sfTemplateEntryType;
extern SF_U8 const sfTransactionResult;
// 16-bit integers
extern SField const sfLedgerEntryType;
extern SField const sfTransactionType;
extern SField const sfSignerWeight;
extern SF_U16 const sfLedgerEntryType;
extern SF_U16 const sfTransactionType;
extern SF_U16 const sfSignerWeight;
// 32-bit integers (common)
extern SField const sfFlags;
extern SField const sfSourceTag;
extern TypedField<STInteger<std::uint32_t>> const sfSequence;
extern SField const sfPreviousTxnLgrSeq;
extern SField const sfLedgerSequence;
extern SField const sfCloseTime;
extern SField const sfParentCloseTime;
extern SField const sfSigningTime;
extern SField const sfExpiration;
extern SField const sfTransferRate;
extern SField const sfWalletSize;
extern SField const sfOwnerCount;
extern SField const sfDestinationTag;
extern SF_U32 const sfFlags;
extern SF_U32 const sfSourceTag;
extern SF_U32 const sfSequence;
extern SF_U32 const sfPreviousTxnLgrSeq;
extern SF_U32 const sfLedgerSequence;
extern SF_U32 const sfCloseTime;
extern SF_U32 const sfParentCloseTime;
extern SF_U32 const sfSigningTime;
extern SF_U32 const sfExpiration;
extern SF_U32 const sfTransferRate;
extern SF_U32 const sfWalletSize;
extern SF_U32 const sfOwnerCount;
extern SF_U32 const sfDestinationTag;
// 32-bit integers (uncommon)
extern SField const sfHighQualityIn;
extern SField const sfHighQualityOut;
extern SField const sfLowQualityIn;
extern SField const sfLowQualityOut;
extern SField const sfQualityIn;
extern SField const sfQualityOut;
extern SField const sfStampEscrow;
extern SField const sfBondAmount;
extern SField const sfLoadFee;
extern SField const sfOfferSequence;
extern SField const sfFirstLedgerSequence; // Deprecated: do not use
extern SField const sfLastLedgerSequence;
extern SField const sfTransactionIndex;
extern SField const sfOperationLimit;
extern SField const sfReferenceFeeUnits;
extern SField const sfReserveBase;
extern SField const sfReserveIncrement;
extern SField const sfSetFlag;
extern SField const sfClearFlag;
extern SField const sfSignerQuorum;
extern SF_U32 const sfHighQualityIn;
extern SF_U32 const sfHighQualityOut;
extern SF_U32 const sfLowQualityIn;
extern SF_U32 const sfLowQualityOut;
extern SF_U32 const sfQualityIn;
extern SF_U32 const sfQualityOut;
extern SF_U32 const sfStampEscrow;
extern SF_U32 const sfBondAmount;
extern SF_U32 const sfLoadFee;
extern SF_U32 const sfOfferSequence;
extern SF_U32 const sfFirstLedgerSequence; // Deprecated: do not use
extern SF_U32 const sfLastLedgerSequence;
extern SF_U32 const sfTransactionIndex;
extern SF_U32 const sfOperationLimit;
extern SF_U32 const sfReferenceFeeUnits;
extern SF_U32 const sfReserveBase;
extern SF_U32 const sfReserveIncrement;
extern SF_U32 const sfSetFlag;
extern SF_U32 const sfClearFlag;
extern SF_U32 const sfSignerQuorum;
// 64-bit integers
extern SField const sfIndexNext;
extern SField const sfIndexPrevious;
extern SField const sfBookNode;
extern SField const sfOwnerNode;
extern SField const sfBaseFee;
extern SField const sfExchangeRate;
extern SField const sfLowNode;
extern SField const sfHighNode;
extern SF_U64 const sfIndexNext;
extern SF_U64 const sfIndexPrevious;
extern SF_U64 const sfBookNode;
extern SF_U64 const sfOwnerNode;
extern SF_U64 const sfBaseFee;
extern SF_U64 const sfExchangeRate;
extern SF_U64 const sfLowNode;
extern SF_U64 const sfHighNode;
// 128-bit
extern SField const sfEmailHash;
// 256-bit (common)
extern SField const sfLedgerHash;
extern SField const sfParentHash;
extern SField const sfTransactionHash;
extern SField const sfAccountHash;
extern SField const sfPreviousTxnID;
extern SField const sfLedgerIndex;
extern SField const sfWalletLocator;
extern SField const sfRootIndex;
extern SField const sfAccountTxnID;
// 256-bit (uncommon)
extern SField const sfBookDirectory;
extern SField const sfInvoiceID;
extern SField const sfNickname;
extern SField const sfAmendment;
extern SField const sfTicketID;
extern SF_U128 const sfEmailHash;
// 160-bit (common)
extern SField const sfTakerPaysCurrency;
extern SField const sfTakerPaysIssuer;
extern SField const sfTakerGetsCurrency;
extern SField const sfTakerGetsIssuer;
extern SF_U160 const sfTakerPaysCurrency;
extern SF_U160 const sfTakerPaysIssuer;
extern SF_U160 const sfTakerGetsCurrency;
extern SF_U160 const sfTakerGetsIssuer;
// 256-bit (common)
extern SF_U256 const sfLedgerHash;
extern SF_U256 const sfParentHash;
extern SF_U256 const sfTransactionHash;
extern SF_U256 const sfAccountHash;
extern SF_U256 const sfPreviousTxnID;
extern SF_U256 const sfLedgerIndex;
extern SF_U256 const sfWalletLocator;
extern SF_U256 const sfRootIndex;
extern SF_U256 const sfAccountTxnID;
// 256-bit (uncommon)
extern SF_U256 const sfBookDirectory;
extern SF_U256 const sfInvoiceID;
extern SF_U256 const sfNickname;
extern SF_U256 const sfAmendment;
extern SF_U256 const sfTicketID;
extern SF_U256 const sfDigest;
// currency amount (common)
extern SField const sfAmount;
extern SField const sfBalance;
extern SField const sfLimitAmount;
extern SField const sfTakerPays;
extern SField const sfTakerGets;
extern SField const sfLowLimit;
extern SField const sfHighLimit;
extern SField const sfFee;
extern SField const sfSendMax;
extern SField const sfDeliverMin;
extern SF_Amount const sfAmount;
extern SF_Amount const sfBalance;
extern SF_Amount const sfLimitAmount;
extern SF_Amount const sfTakerPays;
extern SF_Amount const sfTakerGets;
extern SF_Amount const sfLowLimit;
extern SF_Amount const sfHighLimit;
extern SF_Amount const sfFee;
extern SF_Amount const sfSendMax;
extern SF_Amount const sfDeliverMin;
// currency amount (uncommon)
extern SField const sfMinimumOffer;
extern SField const sfRippleEscrow;
extern SField const sfDeliveredAmount;
extern SF_Amount const sfMinimumOffer;
extern SF_Amount const sfRippleEscrow;
extern SF_Amount const sfDeliveredAmount;
// variable length (common)
extern TypedField<STBlob> const sfPublicKey;
extern SField const sfMessageKey;
extern TypedField<STBlob> const sfSigningPubKey;
extern SField const sfTxnSignature;
extern TypedField<STBlob> const sfSignature;
extern SField const sfDomain;
extern SField const sfFundCode;
extern SField const sfRemoveCode;
extern SField const sfExpireCode;
extern SField const sfCreateCode;
extern SField const sfMemoType;
extern SField const sfMemoData;
extern SField const sfMemoFormat;
extern SF_Blob const sfPublicKey;
extern SF_Blob const sfMessageKey;
extern SF_Blob const sfSigningPubKey;
extern SF_Blob const sfTxnSignature;
extern SF_Blob const sfSignature;
extern SF_Blob const sfDomain;
extern SF_Blob const sfFundCode;
extern SF_Blob const sfRemoveCode;
extern SF_Blob const sfExpireCode;
extern SF_Blob const sfCreateCode;
extern SF_Blob const sfMemoType;
extern SF_Blob const sfMemoData;
extern SF_Blob const sfMemoFormat;
// variable length (uncommon)
extern SField const sfMultiSignature;
extern SF_Blob const sfMultiSignature;
extern SF_Blob const sfInnerSig;
// account
extern SField const sfAccount;
extern SField const sfOwner;
extern SField const sfDestination;
extern SField const sfIssuer;
extern SField const sfTarget;
extern SField const sfRegularKey;
extern SF_Account const sfAccount;
extern SF_Account const sfOwner;
extern SF_Account const sfDestination;
extern SF_Account const sfIssuer;
extern SF_Account const sfTarget;
extern SF_Account const sfRegularKey;
// path set
extern SField const sfPaths;
// vector of 256-bit
extern SField const sfIndexes;
extern SField const sfHashes;
extern SField const sfAmendments;
extern SF_Vec256 const sfIndexes;
extern SF_Vec256 const sfHashes;
extern SF_Vec256 const sfAmendments;
// inner object
// OBJECT/1 is reserved for end of object

View File

@@ -71,6 +71,12 @@ public:
*/
SOTemplate () = default;
SOTemplate(SOTemplate&& other)
: mTypes(std::move(other.mTypes))
, mIndex(std::move(other.mIndex))
{
}
/* Provide for the enumeration of fields */
iterator_range all () const
{
@@ -89,6 +95,12 @@ public:
/** Retrieve the position of a named field. */
int getIndex (SField const&) const;
SOE_Flags
style(SField const& sf) const
{
return mTypes[mIndex[sf.getNum()]]->flags;
}
private:
list_type mTypes;

View File

@@ -20,6 +20,7 @@
#ifndef RIPPLE_PROTOCOL_STACCOUNT_H_INCLUDED
#define RIPPLE_PROTOCOL_STACCOUNT_H_INCLUDED
#include <ripple/protocol/AccountID.h>
#include <ripple/protocol/RippleAddress.h>
#include <ripple/protocol/STBlob.h>
#include <string>
@@ -30,6 +31,8 @@ class STAccount final
: public STBlob
{
public:
using value_type = AccountID;
STAccount (SField const& n, Buffer&& v)
: STBlob (n, std::move(v))
{
@@ -63,8 +66,24 @@ public:
{
return STI_ACCOUNT;
}
std::string getText () const override;
STAccount&
operator= (value_type const& value)
{
setValueH160(value);
return *this;
}
value_type
value() const noexcept
{
AccountID result;
getValueH160(result);
return result;
}
template <typename Tag>
void setValueH160 (base_uint<160, Tag> const& v)
{

View File

@@ -54,6 +54,8 @@ private:
bool mIsNegative;
public:
using value_type = STAmount;
static const int cMinOffset = -96;
static const int cMaxOffset = 80;
@@ -166,6 +168,12 @@ public:
void
setJson (Json::Value&) const;
STAmount const&
value() const noexcept
{
return *this;
}
//--------------------------------------------------------------------------
//
// Operators

View File

@@ -29,7 +29,7 @@ class STBitString final
: public STBase
{
public:
using BitString = base_uint<Bits>;
using value_type = base_uint<Bits>;
STBitString () = default;
@@ -37,24 +37,24 @@ public:
: STBase (n)
{ }
STBitString (const BitString& v)
: bitString_ (v)
STBitString (const value_type& v)
: value_ (v)
{ }
STBitString (SField const& n, const BitString& v)
: STBase (n), bitString_ (v)
STBitString (SField const& n, const value_type& v)
: STBase (n), value_ (v)
{ }
STBitString (SField const& n, const char* v)
: STBase (n)
{
bitString_.SetHex (v);
value_.SetHex (v);
}
STBitString (SField const& n, std::string const& v)
: STBase (n)
{
bitString_.SetHex (v);
value_.SetHex (v);
}
STBitString (SerialIter& sit, SField const& name)
@@ -80,14 +80,14 @@ public:
std::string
getText () const override
{
return to_string (bitString_);
return to_string (value_);
}
bool
isEquivalent (const STBase& t) const override
{
const STBitString* v = dynamic_cast<const STBitString*> (&t);
return v && (bitString_ == v->bitString_);
return v && (value_ == v->value_);
}
void
@@ -95,34 +95,40 @@ public:
{
assert (fName->isBinary ());
assert (fName->fieldType == getSType());
s.addBitString<Bits> (bitString_);
s.addBitString<Bits> (value_);
}
const BitString&
const value_type&
getValue () const
{
return bitString_;
return value_;
}
template <typename Tag>
void setValue (base_uint<Bits, Tag> const& v)
{
bitString_.copyFrom(v);
value_.copyFrom(v);
}
operator BitString () const
value_type const&
value() const
{
return bitString_;
return value_;
}
operator value_type () const
{
return value_;
}
bool
isDefault () const override
{
return bitString_ == zero;
return value_ == zero;
}
private:
BitString bitString_;
value_type value_;
};
using STHash128 = STBitString<128>;

View File

@@ -121,6 +121,26 @@ public:
return value_;
}
STBlob&
operator= (Slice const& slice)
{
value_ = Buffer(slice.data(), slice.size());
return *this;
}
value_type
value() const noexcept
{
return value_;
}
STBlob&
operator= (Buffer&& buffer)
{
value_ = std::move(buffer);
return *this;
}
Buffer&
peekValue ()
{

View File

@@ -77,6 +77,17 @@ public:
return value_;
}
STInteger& operator= (value_type const& v)
{
value_ = v;
return *this;
}
value_type value() const noexcept
{
return value_;
}
void
setValue (Integer v)
{

View File

@@ -20,6 +20,7 @@
#ifndef RIPPLE_PROTOCOL_STOBJECT_H_INCLUDED
#define RIPPLE_PROTOCOL_STOBJECT_H_INCLUDED
#include <ripple/basics/contract.h>
#include <ripple/basics/CountedObject.h>
#include <ripple/protocol/STAmount.h>
#include <ripple/protocol/STPathSet.h>
@@ -27,6 +28,10 @@
#include <ripple/protocol/SOTemplate.h>
#include <ripple/protocol/impl/STVar.h>
#include <boost/iterator/transform_iterator.hpp>
#include <boost/optional.hpp>
#include <cassert>
#include <stdexcept>
#include <beast/cxx14/type_traits.h> // <type_traits>
#include <utility>
#include <beast/streams/debug_ostream.h>
@@ -38,11 +43,213 @@ namespace ripple {
class STArray;
/** Thrown on illegal access to non-present SField. */
struct missing_field_error : std::logic_error
{
explicit
missing_field_error (SField const& f)
: logic_error(
"missing field '" + f.getName() + "'")
{
}
};
/** Thrown on a field template violation. */
struct template_field_error : std::logic_error
{
explicit
template_field_error (SField const& f)
: logic_error(
"template field error '" + f.getName() + "'")
{
}
};
//------------------------------------------------------------------------------
class STObject
: public STBase
, public CountedObject <STObject>
{
private:
// Proxy value for a STBase derived class
template <class T>
class Proxy
{
protected:
using value_type =
typename T::value_type;
STObject* st_;
SOE_Flags style_;
TypedField<T> const* f_;
Proxy (Proxy const&) = default;
Proxy (STObject* st, TypedField<T> const* f);
value_type value() const;
T const* find() const;
template <class U>
void assign (U&& u);
};
template <class T>
class ValueProxy : private Proxy<T>
{
private:
using value_type =
typename T::value_type;
public:
ValueProxy& operator= (ValueProxy const&) = delete;
template <class U>
std::enable_if_t<
std::is_assignable<T, U>::value,
ValueProxy&>
operator= (U&& u);
operator value_type() const;
private:
friend class STObject;
ValueProxy (STObject* st, TypedField<T> const* f);
};
template <class T>
class OptionalProxy : private Proxy<T>
{
private:
using value_type =
typename T::value_type;
using optional_type = boost::optional<
typename std::decay<value_type>::type>;
public:
OptionalProxy& operator= (OptionalProxy const&) = delete;
/** Returns `true` if the field is set.
Fields with SOE_DEFAULT and set to the
default value will return `true`
*/
explicit operator bool() const noexcept;
/** Return the contained value
Throws:
missing_field_error if !engaged()
*/
value_type operator*() const;
operator optional_type() const;
/** Explicit conversion to boost::optional */
optional_type
operator~() const;
friend bool operator==(
OptionalProxy const& lhs,
boost::none_t) noexcept
{
return ! lhs.engaged();
}
friend bool operator==(
boost::none_t,
OptionalProxy const& rhs) noexcept
{
return rhs == boost::none;
}
friend bool operator==(
OptionalProxy const& lhs,
optional_type const& rhs) noexcept
{
if (! lhs.engaged())
return ! rhs;
if (! rhs)
return false;
return *lhs == *rhs;
}
friend bool operator==(
optional_type const& lhs,
OptionalProxy const& rhs) noexcept
{
return rhs == lhs;
}
friend bool operator==(
OptionalProxy const& lhs,
OptionalProxy const& rhs) noexcept
{
if (lhs.engaged() != lhs.engaged())
return false;
return ! lhs.engaged() || *lhs == *rhs;
}
friend bool operator!=(
OptionalProxy const& lhs,
boost::none_t) noexcept
{
return ! (lhs == boost::none);
}
friend bool operator!=(boost::none_t,
OptionalProxy const& rhs) noexcept
{
return ! (rhs == boost::none);
}
friend bool operator!=(
OptionalProxy const& lhs,
optional_type const& rhs) noexcept
{
return ! (lhs == rhs);
}
friend bool operator!=(
optional_type const& lhs,
OptionalProxy const& rhs) noexcept
{
return ! (lhs == rhs);
}
friend bool operator!=(
OptionalProxy const& lhs,
OptionalProxy const& rhs) noexcept
{
return ! (lhs == rhs);
}
OptionalProxy& operator= (boost::none_t const&);
OptionalProxy& operator= (optional_type&& v);
OptionalProxy& operator= (optional_type const& v);
template <class U>
std::enable_if_t<
std::is_assignable<T, U>::value,
OptionalProxy&>
operator= (U&& u);
private:
friend class STObject;
OptionalProxy (STObject* st,
TypedField<T> const* f);
bool engaged() const noexcept;
void disengage();
optional_type
optional_value() const;
};
struct Transform
{
using argument_type = detail::STVar;
@@ -275,6 +482,45 @@ public:
const STArray& getFieldArray (SField const& field) const;
const STObject& getFieldObject (SField const& field) const;
/** Return the value of a field.
Throws:
missing_field_error if the field is
not present.
*/
template<class T>
typename T::value_type
operator[](TypedField<T> const& f) const;
/** Return the value of a field as boost::optional
@return boost::none if the field is not present.
*/
template<class T>
boost::optional<std::decay_t<typename T::value_type>>
operator[](OptionaledField<T> const& of) const;
/** Return a modifiable field value.
Throws:
missing_field_error if the field is
not present.
*/
template<class T>
ValueProxy<T>
operator[](TypedField<T> const& f);
/** Return a modifiable field value as boost::optional
The return value equals boost::none if the
field is not present.
*/
template<class T>
OptionalProxy<T>
operator[](OptionaledField<T> const& of);
/** Set a field.
if the field already exists, it is replaced.
*/
@@ -468,6 +714,277 @@ private:
}
};
//------------------------------------------------------------------------------
template <class T>
STObject::Proxy<T>::Proxy (STObject* st, TypedField<T> const* f)
: st_ (st)
, f_ (f)
{
if (st_->mType)
{
// STObject has associated template
if (! st_->peekAtPField(*f_))
THROW(template_field_error, *f);
style_ = st_->mType->style(*f_);
}
else
{
style_ = SOE_INVALID;
}
}
template <class T>
auto
STObject::Proxy<T>::value() const ->
value_type
{
auto const t = find();
if (t)
return t->value();
if (style_ != SOE_DEFAULT)
THROW(missing_field_error, *f_);
return value_type{};
}
template <class T>
inline
T const*
STObject::Proxy<T>::find() const
{
return dynamic_cast<T const*>(
st_->peekAtPField(*f_));
}
template <class T>
template <class U>
void
STObject::Proxy<T>::assign(U&& u)
{
if (style_ == SOE_DEFAULT &&
u == value_type{})
{
st_->makeFieldAbsent(*f_);
return;
}
T* t;
if (style_ == SOE_INVALID)
t = dynamic_cast<T*>(
st_->getPField(*f_, true));
else
t = dynamic_cast<T*>(
st_->makeFieldPresent(*f_));
assert(t);
*t = std::forward<U>(u);
}
//------------------------------------------------------------------------------
template <class T>
template <class U>
std::enable_if_t<
std::is_assignable<T, U>::value,
STObject::ValueProxy<T>&>
STObject::ValueProxy<T>::operator= (U&& u)
{
this->assign(std::forward<U>(u));
return *this;
}
template <class T>
STObject::ValueProxy<T>::operator value_type() const
{
return this->value();
}
template <class T>
STObject::ValueProxy<T>::ValueProxy(
STObject* st, TypedField<T> const* f)
: Proxy<T>(st, f)
{
}
//------------------------------------------------------------------------------
template <class T>
STObject::OptionalProxy<T>::operator bool() const noexcept
{
return engaged();
}
template <class T>
auto
STObject::OptionalProxy<T>::operator*() const ->
value_type
{
return this->value();
}
template <class T>
STObject::OptionalProxy<T>::operator
typename STObject::OptionalProxy<T>::optional_type() const
{
return optional_value();
}
template <class T>
typename STObject::OptionalProxy<T>::optional_type
STObject::OptionalProxy<T>::operator~() const
{
return optional_value();
}
template <class T>
auto
STObject::OptionalProxy<T>::operator=(boost::none_t const&) ->
OptionalProxy&
{
disengage();
return *this;
}
template <class T>
auto
STObject::OptionalProxy<T>::operator=(optional_type&& v) ->
OptionalProxy&
{
if (v)
this->assign(std::move(*v));
else
disengage();
return *this;
}
template <class T>
auto
STObject::OptionalProxy<T>::operator=(optional_type const& v) ->
OptionalProxy&
{
if (v)
this->assign(*v);
else
disengage();
return *this;
}
template <class T>
template <class U>
std::enable_if_t<
std::is_assignable<T, U>::value,
STObject::OptionalProxy<T>&>
STObject::OptionalProxy<T>::operator=(U&& u)
{
this->assign(std::forward<U>(u));
return *this;
}
template <class T>
STObject::OptionalProxy<T>::OptionalProxy(
STObject* st, TypedField<T> const* f)
: Proxy<T>(st, f)
{
}
template <class T>
bool
STObject::OptionalProxy<T>::engaged() const noexcept
{
return this->style_ == SOE_DEFAULT
|| this->find() != nullptr;
}
template <class T>
void
STObject::OptionalProxy<T>::disengage()
{
if (this->style_ == SOE_REQUIRED ||
this->style_ == SOE_DEFAULT)
THROW(template_field_error, *this->f_);
if (this->style_ == SOE_INVALID)
this->st_->delField(*this->f_);
else
this->st_->makeFieldAbsent(*this->f_);
}
template <class T>
auto
STObject::OptionalProxy<T>::optional_value() const ->
optional_type
{
if (! engaged())
return boost::none;
return this->value();
}
//------------------------------------------------------------------------------
template<class T>
typename T::value_type
STObject::operator[](TypedField<T> const& f) const
{
auto const b = peekAtPField(f);
if (! b)
// This is a free object (no constraints)
// with no template
THROW(missing_field_error, f);
auto const u =
dynamic_cast<T const*>(b);
if (! u)
{
assert(mType);
assert(b->getSType() == STI_NOTPRESENT);
if(mType->style(f) == SOE_OPTIONAL)
THROW(missing_field_error, f);
assert(mType->style(f) == SOE_DEFAULT);
// Handle the case where value_type is a
// const reference, otherwise we return
// the address of a temporary.
static std::decay_t<
typename T::value_type> const dv{};
return dv;
}
return u->value();
}
template<class T>
boost::optional<std::decay_t<typename T::value_type>>
STObject::operator[](OptionaledField<T> const& of) const
{
auto const b = peekAtPField(*of.f);
if (! b)
return boost::none;
auto const u =
dynamic_cast<T const*>(b);
if (! u)
{
assert(mType);
assert(b->getSType() == STI_NOTPRESENT);
if(mType->style(*of.f) == SOE_OPTIONAL)
return boost::none;
assert(mType->style(*of.f) == SOE_DEFAULT);
return typename T::value_type{};
}
return u->value();
}
template<class T>
inline
auto
STObject::operator[](TypedField<T> const& f) ->
ValueProxy<T>
{
return ValueProxy<T>(this, &f);
}
template<class T>
inline
auto
STObject::operator[](OptionaledField<T> const& of) ->
OptionalProxy<T>
{
return OptionalProxy<T>(this, of.f);
}
} // ripple
#endif

View File

@@ -31,6 +31,8 @@ class STVector256
: public STBase
{
public:
using value_type = std::vector<uint256> const&;
STVector256 () = default;
explicit STVector256 (SField const& n)
@@ -80,6 +82,20 @@ public:
return mValue.empty ();
}
STVector256&
operator= (std::vector<uint256> const& v)
{
mValue = v;
return *this;
}
STVector256&
operator= (std::vector<uint256>&& v)
{
mValue = std::move(v);
return *this;
}
void
setValue (const STVector256& v)
{
@@ -93,15 +109,14 @@ public:
return mValue;
}
// std::vector<uint256> interface:
std::vector<uint256>::size_type
std::size_t
size () const
{
return mValue.size ();
}
void
resize (std::vector<uint256>::size_type n)
resize (std::size_t n)
{
return mValue.resize (n);
}
@@ -124,6 +139,12 @@ public:
return mValue[n];
}
std::vector<uint256> const&
value() const
{
return mValue;
}
void
push_back (uint256 const& v)
{

View File

@@ -76,139 +76,141 @@ SField const sfHash = make::one(&sfHash, STI_HASH256, 257, "ha
SField const sfIndex = make::one(&sfIndex, STI_HASH256, 258, "index");
// 8-bit integers
SField const sfCloseResolution = make::one(&sfCloseResolution, STI_UINT8, 1, "CloseResolution");
SField const sfTemplateEntryType = make::one(&sfTemplateEntryType, STI_UINT8, 2, "TemplateEntryType");
SField const sfTransactionResult = make::one(&sfTransactionResult, STI_UINT8, 3, "TransactionResult");
SF_U8 const sfCloseResolution = make::one<SF_U8::type>(&sfCloseResolution, STI_UINT8, 1, "CloseResolution");
SF_U8 const sfTemplateEntryType = make::one<SF_U8::type>(&sfTemplateEntryType, STI_UINT8, 2, "TemplateEntryType");
SF_U8 const sfTransactionResult = make::one<SF_U8::type>(&sfTransactionResult, STI_UINT8, 3, "TransactionResult");
// 16-bit integers
SField const sfLedgerEntryType = make::one(&sfLedgerEntryType, STI_UINT16, 1, "LedgerEntryType", SField::sMD_Never);
SField const sfTransactionType = make::one(&sfTransactionType, STI_UINT16, 2, "TransactionType");
SField const sfSignerWeight = make::one(&sfSignerWeight, STI_UINT16, 3, "SignerWeight");
SF_U16 const sfLedgerEntryType = make::one<SF_U16::type>(&sfLedgerEntryType, STI_UINT16, 1, "LedgerEntryType", SField::sMD_Never);
SF_U16 const sfTransactionType = make::one<SF_U16::type>(&sfTransactionType, STI_UINT16, 2, "TransactionType");
SF_U16 const sfSignerWeight = make::one<SF_U16::type>(&sfSignerWeight, STI_UINT16, 3, "SignerWeight");
// 32-bit integers (common)
SField const sfFlags = make::one(&sfFlags, STI_UINT32, 2, "Flags");
SField const sfSourceTag = make::one(&sfSourceTag, STI_UINT32, 3, "SourceTag");
TypedField<STInteger<std::uint32_t>> const sfSequence = make::one<STInteger<std::uint32_t>>(&sfSequence, STI_UINT32, 4, "Sequence");
SField const sfPreviousTxnLgrSeq = make::one(&sfPreviousTxnLgrSeq, STI_UINT32, 5, "PreviousTxnLgrSeq", SField::sMD_DeleteFinal);
SField const sfLedgerSequence = make::one(&sfLedgerSequence, STI_UINT32, 6, "LedgerSequence");
SField const sfCloseTime = make::one(&sfCloseTime, STI_UINT32, 7, "CloseTime");
SField const sfParentCloseTime = make::one(&sfParentCloseTime, STI_UINT32, 8, "ParentCloseTime");
SField const sfSigningTime = make::one(&sfSigningTime, STI_UINT32, 9, "SigningTime");
SField const sfExpiration = make::one(&sfExpiration, STI_UINT32, 10, "Expiration");
SField const sfTransferRate = make::one(&sfTransferRate, STI_UINT32, 11, "TransferRate");
SField const sfWalletSize = make::one(&sfWalletSize, STI_UINT32, 12, "WalletSize");
SField const sfOwnerCount = make::one(&sfOwnerCount, STI_UINT32, 13, "OwnerCount");
SField const sfDestinationTag = make::one(&sfDestinationTag, STI_UINT32, 14, "DestinationTag");
SF_U32 const sfFlags = make::one<SF_U32::type>(&sfFlags, STI_UINT32, 2, "Flags");
SF_U32 const sfSourceTag = make::one<SF_U32::type>(&sfSourceTag, STI_UINT32, 3, "SourceTag");
SF_U32 const sfSequence = make::one<SF_U32::type>(&sfSequence, STI_UINT32, 4, "Sequence");
SF_U32 const sfPreviousTxnLgrSeq = make::one<SF_U32::type>(&sfPreviousTxnLgrSeq, STI_UINT32, 5, "PreviousTxnLgrSeq", SField::sMD_DeleteFinal);
SF_U32 const sfLedgerSequence = make::one<SF_U32::type>(&sfLedgerSequence, STI_UINT32, 6, "LedgerSequence");
SF_U32 const sfCloseTime = make::one<SF_U32::type>(&sfCloseTime, STI_UINT32, 7, "CloseTime");
SF_U32 const sfParentCloseTime = make::one<SF_U32::type>(&sfParentCloseTime, STI_UINT32, 8, "ParentCloseTime");
SF_U32 const sfSigningTime = make::one<SF_U32::type>(&sfSigningTime, STI_UINT32, 9, "SigningTime");
SF_U32 const sfExpiration = make::one<SF_U32::type>(&sfExpiration, STI_UINT32, 10, "Expiration");
SF_U32 const sfTransferRate = make::one<SF_U32::type>(&sfTransferRate, STI_UINT32, 11, "TransferRate");
SF_U32 const sfWalletSize = make::one<SF_U32::type>(&sfWalletSize, STI_UINT32, 12, "WalletSize");
SF_U32 const sfOwnerCount = make::one<SF_U32::type>(&sfOwnerCount, STI_UINT32, 13, "OwnerCount");
SF_U32 const sfDestinationTag = make::one<SF_U32::type>(&sfDestinationTag, STI_UINT32, 14, "DestinationTag");
// 32-bit integers (uncommon)
SField const sfHighQualityIn = make::one(&sfHighQualityIn, STI_UINT32, 16, "HighQualityIn");
SField const sfHighQualityOut = make::one(&sfHighQualityOut, STI_UINT32, 17, "HighQualityOut");
SField const sfLowQualityIn = make::one(&sfLowQualityIn, STI_UINT32, 18, "LowQualityIn");
SField const sfLowQualityOut = make::one(&sfLowQualityOut, STI_UINT32, 19, "LowQualityOut");
SField const sfQualityIn = make::one(&sfQualityIn, STI_UINT32, 20, "QualityIn");
SField const sfQualityOut = make::one(&sfQualityOut, STI_UINT32, 21, "QualityOut");
SField const sfStampEscrow = make::one(&sfStampEscrow, STI_UINT32, 22, "StampEscrow");
SField const sfBondAmount = make::one(&sfBondAmount, STI_UINT32, 23, "BondAmount");
SField const sfLoadFee = make::one(&sfLoadFee, STI_UINT32, 24, "LoadFee");
SField const sfOfferSequence = make::one(&sfOfferSequence, STI_UINT32, 25, "OfferSequence");
SField const sfFirstLedgerSequence = make::one(&sfFirstLedgerSequence, STI_UINT32, 26, "FirstLedgerSequence"); // Deprecated: do not use
SField const sfLastLedgerSequence = make::one(&sfLastLedgerSequence, STI_UINT32, 27, "LastLedgerSequence");
SField const sfTransactionIndex = make::one(&sfTransactionIndex, STI_UINT32, 28, "TransactionIndex");
SField const sfOperationLimit = make::one(&sfOperationLimit, STI_UINT32, 29, "OperationLimit");
SField const sfReferenceFeeUnits = make::one(&sfReferenceFeeUnits, STI_UINT32, 30, "ReferenceFeeUnits");
SField const sfReserveBase = make::one(&sfReserveBase, STI_UINT32, 31, "ReserveBase");
SField const sfReserveIncrement = make::one(&sfReserveIncrement, STI_UINT32, 32, "ReserveIncrement");
SField const sfSetFlag = make::one(&sfSetFlag, STI_UINT32, 33, "SetFlag");
SField const sfClearFlag = make::one(&sfClearFlag, STI_UINT32, 34, "ClearFlag");
SField const sfSignerQuorum = make::one(&sfSignerQuorum, STI_UINT32, 35, "SignerQuorum");
SF_U32 const sfHighQualityIn = make::one<SF_U32::type>(&sfHighQualityIn, STI_UINT32, 16, "HighQualityIn");
SF_U32 const sfHighQualityOut = make::one<SF_U32::type>(&sfHighQualityOut, STI_UINT32, 17, "HighQualityOut");
SF_U32 const sfLowQualityIn = make::one<SF_U32::type>(&sfLowQualityIn, STI_UINT32, 18, "LowQualityIn");
SF_U32 const sfLowQualityOut = make::one<SF_U32::type>(&sfLowQualityOut, STI_UINT32, 19, "LowQualityOut");
SF_U32 const sfQualityIn = make::one<SF_U32::type>(&sfQualityIn, STI_UINT32, 20, "QualityIn");
SF_U32 const sfQualityOut = make::one<SF_U32::type>(&sfQualityOut, STI_UINT32, 21, "QualityOut");
SF_U32 const sfStampEscrow = make::one<SF_U32::type>(&sfStampEscrow, STI_UINT32, 22, "StampEscrow");
SF_U32 const sfBondAmount = make::one<SF_U32::type>(&sfBondAmount, STI_UINT32, 23, "BondAmount");
SF_U32 const sfLoadFee = make::one<SF_U32::type>(&sfLoadFee, STI_UINT32, 24, "LoadFee");
SF_U32 const sfOfferSequence = make::one<SF_U32::type>(&sfOfferSequence, STI_UINT32, 25, "OfferSequence");
SF_U32 const sfFirstLedgerSequence = make::one<SF_U32::type>(&sfFirstLedgerSequence, STI_UINT32, 26, "FirstLedgerSequence"); // Deprecated: do not use
SF_U32 const sfLastLedgerSequence = make::one<SF_U32::type>(&sfLastLedgerSequence, STI_UINT32, 27, "LastLedgerSequence");
SF_U32 const sfTransactionIndex = make::one<SF_U32::type>(&sfTransactionIndex, STI_UINT32, 28, "TransactionIndex");
SF_U32 const sfOperationLimit = make::one<SF_U32::type>(&sfOperationLimit, STI_UINT32, 29, "OperationLimit");
SF_U32 const sfReferenceFeeUnits = make::one<SF_U32::type>(&sfReferenceFeeUnits, STI_UINT32, 30, "ReferenceFeeUnits");
SF_U32 const sfReserveBase = make::one<SF_U32::type>(&sfReserveBase, STI_UINT32, 31, "ReserveBase");
SF_U32 const sfReserveIncrement = make::one<SF_U32::type>(&sfReserveIncrement, STI_UINT32, 32, "ReserveIncrement");
SF_U32 const sfSetFlag = make::one<SF_U32::type>(&sfSetFlag, STI_UINT32, 33, "SetFlag");
SF_U32 const sfClearFlag = make::one<SF_U32::type>(&sfClearFlag, STI_UINT32, 34, "ClearFlag");
SF_U32 const sfSignerQuorum = make::one<SF_U32::type>(&sfSignerQuorum, STI_UINT32, 35, "SignerQuorum");
// 64-bit integers
SField const sfIndexNext = make::one(&sfIndexNext, STI_UINT64, 1, "IndexNext");
SField const sfIndexPrevious = make::one(&sfIndexPrevious, STI_UINT64, 2, "IndexPrevious");
SField const sfBookNode = make::one(&sfBookNode, STI_UINT64, 3, "BookNode");
SField const sfOwnerNode = make::one(&sfOwnerNode, STI_UINT64, 4, "OwnerNode");
SField const sfBaseFee = make::one(&sfBaseFee, STI_UINT64, 5, "BaseFee");
SField const sfExchangeRate = make::one(&sfExchangeRate, STI_UINT64, 6, "ExchangeRate");
SField const sfLowNode = make::one(&sfLowNode, STI_UINT64, 7, "LowNode");
SField const sfHighNode = make::one(&sfHighNode, STI_UINT64, 8, "HighNode");
SF_U64 const sfIndexNext = make::one<SF_U64::type>(&sfIndexNext, STI_UINT64, 1, "IndexNext");
SF_U64 const sfIndexPrevious = make::one<SF_U64::type>(&sfIndexPrevious, STI_UINT64, 2, "IndexPrevious");
SF_U64 const sfBookNode = make::one<SF_U64::type>(&sfBookNode, STI_UINT64, 3, "BookNode");
SF_U64 const sfOwnerNode = make::one<SF_U64::type>(&sfOwnerNode, STI_UINT64, 4, "OwnerNode");
SF_U64 const sfBaseFee = make::one<SF_U64::type>(&sfBaseFee, STI_UINT64, 5, "BaseFee");
SF_U64 const sfExchangeRate = make::one<SF_U64::type>(&sfExchangeRate, STI_UINT64, 6, "ExchangeRate");
SF_U64 const sfLowNode = make::one<SF_U64::type>(&sfLowNode, STI_UINT64, 7, "LowNode");
SF_U64 const sfHighNode = make::one<SF_U64::type>(&sfHighNode, STI_UINT64, 8, "HighNode");
// 128-bit
SField const sfEmailHash = make::one(&sfEmailHash, STI_HASH128, 1, "EmailHash");
// 256-bit (common)
SField const sfLedgerHash = make::one(&sfLedgerHash, STI_HASH256, 1, "LedgerHash");
SField const sfParentHash = make::one(&sfParentHash, STI_HASH256, 2, "ParentHash");
SField const sfTransactionHash = make::one(&sfTransactionHash, STI_HASH256, 3, "TransactionHash");
SField const sfAccountHash = make::one(&sfAccountHash, STI_HASH256, 4, "AccountHash");
SField const sfPreviousTxnID = make::one(&sfPreviousTxnID, STI_HASH256, 5, "PreviousTxnID", SField::sMD_DeleteFinal);
SField const sfLedgerIndex = make::one(&sfLedgerIndex, STI_HASH256, 6, "LedgerIndex");
SField const sfWalletLocator = make::one(&sfWalletLocator, STI_HASH256, 7, "WalletLocator");
SField const sfRootIndex = make::one(&sfRootIndex, STI_HASH256, 8, "RootIndex", SField::sMD_Always);
SField const sfAccountTxnID = make::one(&sfAccountTxnID, STI_HASH256, 9, "AccountTxnID");
// 256-bit (uncommon)
SField const sfBookDirectory = make::one(&sfBookDirectory, STI_HASH256, 16, "BookDirectory");
SField const sfInvoiceID = make::one(&sfInvoiceID, STI_HASH256, 17, "InvoiceID");
SField const sfNickname = make::one(&sfNickname, STI_HASH256, 18, "Nickname");
SField const sfAmendment = make::one(&sfAmendment, STI_HASH256, 19, "Amendment");
SField const sfTicketID = make::one(&sfTicketID, STI_HASH256, 20, "TicketID");
SF_U128 const sfEmailHash = make::one<SF_U128::type>(&sfEmailHash, STI_HASH128, 1, "EmailHash");
// 160-bit (common)
SField const sfTakerPaysCurrency = make::one(&sfTakerPaysCurrency, STI_HASH160, 1, "TakerPaysCurrency");
SField const sfTakerPaysIssuer = make::one(&sfTakerPaysIssuer, STI_HASH160, 2, "TakerPaysIssuer");
SField const sfTakerGetsCurrency = make::one(&sfTakerGetsCurrency, STI_HASH160, 3, "TakerGetsCurrency");
SField const sfTakerGetsIssuer = make::one(&sfTakerGetsIssuer, STI_HASH160, 4, "TakerGetsIssuer");
SF_U160 const sfTakerPaysCurrency = make::one<SF_U160::type>(&sfTakerPaysCurrency, STI_HASH160, 1, "TakerPaysCurrency");
SF_U160 const sfTakerPaysIssuer = make::one<SF_U160::type>(&sfTakerPaysIssuer, STI_HASH160, 2, "TakerPaysIssuer");
SF_U160 const sfTakerGetsCurrency = make::one<SF_U160::type>(&sfTakerGetsCurrency, STI_HASH160, 3, "TakerGetsCurrency");
SF_U160 const sfTakerGetsIssuer = make::one<SF_U160::type>(&sfTakerGetsIssuer, STI_HASH160, 4, "TakerGetsIssuer");
// 256-bit (common)
SF_U256 const sfLedgerHash = make::one<SF_U256::type>(&sfLedgerHash, STI_HASH256, 1, "LedgerHash");
SF_U256 const sfParentHash = make::one<SF_U256::type>(&sfParentHash, STI_HASH256, 2, "ParentHash");
SF_U256 const sfTransactionHash = make::one<SF_U256::type>(&sfTransactionHash, STI_HASH256, 3, "TransactionHash");
SF_U256 const sfAccountHash = make::one<SF_U256::type>(&sfAccountHash, STI_HASH256, 4, "AccountHash");
SF_U256 const sfPreviousTxnID = make::one<SF_U256::type>(&sfPreviousTxnID, STI_HASH256, 5, "PreviousTxnID", SField::sMD_DeleteFinal);
SF_U256 const sfLedgerIndex = make::one<SF_U256::type>(&sfLedgerIndex, STI_HASH256, 6, "LedgerIndex");
SF_U256 const sfWalletLocator = make::one<SF_U256::type>(&sfWalletLocator, STI_HASH256, 7, "WalletLocator");
SF_U256 const sfRootIndex = make::one<SF_U256::type>(&sfRootIndex, STI_HASH256, 8, "RootIndex", SField::sMD_Always);
SF_U256 const sfAccountTxnID = make::one<SF_U256::type>(&sfAccountTxnID, STI_HASH256, 9, "AccountTxnID");
// 256-bit (uncommon)
SF_U256 const sfBookDirectory = make::one<SF_U256::type>(&sfBookDirectory, STI_HASH256, 16, "BookDirectory");
SF_U256 const sfInvoiceID = make::one<SF_U256::type>(&sfInvoiceID, STI_HASH256, 17, "InvoiceID");
SF_U256 const sfNickname = make::one<SF_U256::type>(&sfNickname, STI_HASH256, 18, "Nickname");
SF_U256 const sfAmendment = make::one<SF_U256::type>(&sfAmendment, STI_HASH256, 19, "Amendment");
SF_U256 const sfTicketID = make::one<SF_U256::type>(&sfTicketID, STI_HASH256, 20, "TicketID");
SF_U256 const sfDigest = make::one<SF_U256::type>(&sfDigest, STI_HASH256, 21, "Digest");
// currency amount (common)
SField const sfAmount = make::one(&sfAmount, STI_AMOUNT, 1, "Amount");
SField const sfBalance = make::one(&sfBalance, STI_AMOUNT, 2, "Balance");
SField const sfLimitAmount = make::one(&sfLimitAmount, STI_AMOUNT, 3, "LimitAmount");
SField const sfTakerPays = make::one(&sfTakerPays, STI_AMOUNT, 4, "TakerPays");
SField const sfTakerGets = make::one(&sfTakerGets, STI_AMOUNT, 5, "TakerGets");
SField const sfLowLimit = make::one(&sfLowLimit, STI_AMOUNT, 6, "LowLimit");
SField const sfHighLimit = make::one(&sfHighLimit, STI_AMOUNT, 7, "HighLimit");
SField const sfFee = make::one(&sfFee, STI_AMOUNT, 8, "Fee");
SField const sfSendMax = make::one(&sfSendMax, STI_AMOUNT, 9, "SendMax");
SField const sfDeliverMin = make::one(&sfDeliverMin, STI_AMOUNT, 10, "DeliverMin");
SF_Amount const sfAmount = make::one<SF_Amount::type>(&sfAmount, STI_AMOUNT, 1, "Amount");
SF_Amount const sfBalance = make::one<SF_Amount::type>(&sfBalance, STI_AMOUNT, 2, "Balance");
SF_Amount const sfLimitAmount = make::one<SF_Amount::type>(&sfLimitAmount, STI_AMOUNT, 3, "LimitAmount");
SF_Amount const sfTakerPays = make::one<SF_Amount::type>(&sfTakerPays, STI_AMOUNT, 4, "TakerPays");
SF_Amount const sfTakerGets = make::one<SF_Amount::type>(&sfTakerGets, STI_AMOUNT, 5, "TakerGets");
SF_Amount const sfLowLimit = make::one<SF_Amount::type>(&sfLowLimit, STI_AMOUNT, 6, "LowLimit");
SF_Amount const sfHighLimit = make::one<SF_Amount::type>(&sfHighLimit, STI_AMOUNT, 7, "HighLimit");
SF_Amount const sfFee = make::one<SF_Amount::type>(&sfFee, STI_AMOUNT, 8, "Fee");
SF_Amount const sfSendMax = make::one<SF_Amount::type>(&sfSendMax, STI_AMOUNT, 9, "SendMax");
SF_Amount const sfDeliverMin = make::one<SF_Amount::type>(&sfDeliverMin, STI_AMOUNT, 10, "DeliverMin");
// currency amount (uncommon)
SField const sfMinimumOffer = make::one(&sfMinimumOffer, STI_AMOUNT, 16, "MinimumOffer");
SField const sfRippleEscrow = make::one(&sfRippleEscrow, STI_AMOUNT, 17, "RippleEscrow");
SField const sfDeliveredAmount = make::one(&sfDeliveredAmount, STI_AMOUNT, 18, "DeliveredAmount");
SF_Amount const sfMinimumOffer = make::one<SF_Amount::type>(&sfMinimumOffer, STI_AMOUNT, 16, "MinimumOffer");
SF_Amount const sfRippleEscrow = make::one<SF_Amount::type>(&sfRippleEscrow, STI_AMOUNT, 17, "RippleEscrow");
SF_Amount const sfDeliveredAmount = make::one<SF_Amount::type>(&sfDeliveredAmount, STI_AMOUNT, 18, "DeliveredAmount");
// variable length (common)
TypedField<STBlob> const sfPublicKey = make::one<STBlob>(&sfPublicKey, STI_VL, 1, "PublicKey");
TypedField<STBlob> const sfSigningPubKey = make::one<STBlob>(&sfSigningPubKey, STI_VL, 3, "SigningPubKey");
TypedField<STBlob> const sfSignature = make::one<STBlob>(&sfSignature, STI_VL, 6, "Signature", SField::sMD_Default, SField::notSigning);
SField const sfMessageKey = make::one(&sfMessageKey, STI_VL, 2, "MessageKey");
SField const sfTxnSignature = make::one(&sfTxnSignature, STI_VL, 4, "TxnSignature", SField::sMD_Default, SField::notSigning);
SField const sfDomain = make::one(&sfDomain, STI_VL, 7, "Domain");
SField const sfFundCode = make::one(&sfFundCode, STI_VL, 8, "FundCode");
SField const sfRemoveCode = make::one(&sfRemoveCode, STI_VL, 9, "RemoveCode");
SField const sfExpireCode = make::one(&sfExpireCode, STI_VL, 10, "ExpireCode");
SField const sfCreateCode = make::one(&sfCreateCode, STI_VL, 11, "CreateCode");
SField const sfMemoType = make::one(&sfMemoType, STI_VL, 12, "MemoType");
SField const sfMemoData = make::one(&sfMemoData, STI_VL, 13, "MemoData");
SField const sfMemoFormat = make::one(&sfMemoFormat, STI_VL, 14, "MemoFormat");
SF_Blob const sfPublicKey = make::one<SF_Blob::type>(&sfPublicKey, STI_VL, 1, "PublicKey");
SF_Blob const sfSigningPubKey = make::one<SF_Blob::type>(&sfSigningPubKey, STI_VL, 3, "SigningPubKey");
SF_Blob const sfSignature = make::one<SF_Blob::type>(&sfSignature, STI_VL, 6, "Signature", SField::sMD_Default, SField::notSigning);
SF_Blob const sfMessageKey = make::one<SF_Blob::type>(&sfMessageKey, STI_VL, 2, "MessageKey");
SF_Blob const sfTxnSignature = make::one<SF_Blob::type>(&sfTxnSignature, STI_VL, 4, "TxnSignature", SField::sMD_Default, SField::notSigning);
SF_Blob const sfDomain = make::one<SF_Blob::type>(&sfDomain, STI_VL, 7, "Domain");
SF_Blob const sfFundCode = make::one<SF_Blob::type>(&sfFundCode, STI_VL, 8, "FundCode");
SF_Blob const sfRemoveCode = make::one<SF_Blob::type>(&sfRemoveCode, STI_VL, 9, "RemoveCode");
SF_Blob const sfExpireCode = make::one<SF_Blob::type>(&sfExpireCode, STI_VL, 10, "ExpireCode");
SF_Blob const sfCreateCode = make::one<SF_Blob::type>(&sfCreateCode, STI_VL, 11, "CreateCode");
SF_Blob const sfMemoType = make::one<SF_Blob::type>(&sfMemoType, STI_VL, 12, "MemoType");
SF_Blob const sfMemoData = make::one<SF_Blob::type>(&sfMemoData, STI_VL, 13, "MemoData");
SF_Blob const sfMemoFormat = make::one<SF_Blob::type>(&sfMemoFormat, STI_VL, 14, "MemoFormat");
// variable length (uncommon)
SField const sfMultiSignature = make::one(&sfMultiSignature, STI_VL, 16, "MultiSignature");
SF_Blob const sfMultiSignature = make::one<SF_Blob::type>(&sfMultiSignature, STI_VL, 16, "MultiSignature");
SF_Blob const sfInnerSig = make::one<SF_Blob::type>(&sfInnerSig, STI_VL, 17, "InnerSig");
// account
SField const sfAccount = make::one(&sfAccount, STI_ACCOUNT, 1, "Account");
SField const sfOwner = make::one(&sfOwner, STI_ACCOUNT, 2, "Owner");
SField const sfDestination = make::one(&sfDestination, STI_ACCOUNT, 3, "Destination");
SField const sfIssuer = make::one(&sfIssuer, STI_ACCOUNT, 4, "Issuer");
SField const sfTarget = make::one(&sfTarget, STI_ACCOUNT, 7, "Target");
SField const sfRegularKey = make::one(&sfRegularKey, STI_ACCOUNT, 8, "RegularKey");
SF_Account const sfAccount = make::one<SF_Account::type>(&sfAccount, STI_ACCOUNT, 1, "Account");
SF_Account const sfOwner = make::one<SF_Account::type>(&sfOwner, STI_ACCOUNT, 2, "Owner");
SF_Account const sfDestination = make::one<SF_Account::type>(&sfDestination, STI_ACCOUNT, 3, "Destination");
SF_Account const sfIssuer = make::one<SF_Account::type>(&sfIssuer, STI_ACCOUNT, 4, "Issuer");
SF_Account const sfTarget = make::one<SF_Account::type>(&sfTarget, STI_ACCOUNT, 7, "Target");
SF_Account const sfRegularKey = make::one<SF_Account::type>(&sfRegularKey, STI_ACCOUNT, 8, "RegularKey");
// path set
SField const sfPaths = make::one(&sfPaths, STI_PATHSET, 1, "Paths");
// vector of 256-bit
SField const sfIndexes = make::one(&sfIndexes, STI_VECTOR256, 1, "Indexes", SField::sMD_Never);
SField const sfHashes = make::one(&sfHashes, STI_VECTOR256, 2, "Hashes");
SField const sfAmendments = make::one(&sfAmendments, STI_VECTOR256, 3, "Amendments");
SF_Vec256 const sfIndexes = make::one<SF_Vec256::type>(&sfIndexes, STI_VECTOR256, 1, "Indexes", SField::sMD_Never);
SF_Vec256 const sfHashes = make::one<SF_Vec256::type>(&sfHashes, STI_VECTOR256, 2, "Hashes");
SF_Vec256 const sfAmendments = make::one<SF_Vec256::type>(&sfAmendments, STI_VECTOR256, 3, "Amendments");
// inner object
// OBJECT/1 is reserved for end of object

View File

@@ -19,28 +19,19 @@
#include <BeastConfig.h>
#include <ripple/basics/Log.h>
#include <ripple/protocol/STBase.h>
#include <ripple/protocol/STAccount.h>
#include <ripple/protocol/STArray.h>
#include <ripple/protocol/STObject.h>
#include <ripple/protocol/STParsedJSON.h>
#include <ripple/protocol/SecretKey.h>
#include <ripple/protocol/st.h>
#include <ripple/json/json_reader.h>
#include <ripple/json/to_string.h>
#include <beast/unit_test/suite.h>
#include <beast/cxx14/memory.h> // <memory>
#include <memory>
#include <type_traits>
namespace ripple {
class SerializedObject_test : public beast::unit_test::suite
class STObject_test : public beast::unit_test::suite
{
public:
void run()
{
testSerialization();
testParseJSONArray();
testParseJSONArrayWithInvalidChildrenObjects();
}
bool parseJSONString (std::string const& json, Json::Value& to)
{
Json::Reader reader;
@@ -192,8 +183,307 @@ public:
unexpected (object3.getFieldVL (sfTestVL) != j, "STObject error");
}
}
// Exercise field accessors
void
testFields()
{
testcase ("fields");
auto const& sf1 = sfSequence;
auto const& sf2 = sfExpiration;
auto const& sf3 = sfQualityIn;
auto const& sf4 = sfSignature;
auto const& sf5 = sfPublicKey;
// read free object
{
auto const st = [&]()
{
STObject st(sfGeneric);
st.setFieldU32(sf1, 1);
st.setFieldU32(sf2, 2);
return st;
}();
expect(st[sf1] == 1);
expect(st[sf2] == 2);
except<missing_field_error>([&]()
{ st[sf3]; });
expect(*st[~sf1] == 1);
expect(*st[~sf2] == 2);
expect(st[~sf3] == boost::none);
expect(!! st[~sf1]);
expect(!! st[~sf2]);
expect(! st[~sf3]);
expect(st[sf1] != st[sf2]);
expect(st[~sf1] != st[~sf2]);
}
// read templated object
auto const sot = [&]()
{
SOTemplate sot;
sot.push_back(SOElement(sf1, SOE_REQUIRED));
sot.push_back(SOElement(sf2, SOE_OPTIONAL));
sot.push_back(SOElement(sf3, SOE_DEFAULT));
sot.push_back(SOElement(sf4, SOE_OPTIONAL));
sot.push_back(SOElement(sf5, SOE_DEFAULT));
return sot;
}();
{
auto const st = [&]()
{
STObject st(sot, sfGeneric);
st.setFieldU32(sf1, 1);
st.setFieldU32(sf2, 2);
return st;
}();
expect(st[sf1] == 1);
expect(st[sf2] == 2);
expect(st[sf3] == 0);
expect(*st[~sf1] == 1);
expect(*st[~sf2] == 2);
expect(*st[~sf3] == 0);
expect(!! st[~sf1]);
expect(!! st[~sf2]);
expect(!! st[~sf3]);
}
// write free object
{
STObject st(sfGeneric);
unexcept([&]() { st[sf1]; });
except([&](){ return st[sf1] == 0; });
expect(st[~sf1] == boost::none);
expect(st[~sf1] == boost::optional<std::uint32_t>{});
expect(st[~sf1] != boost::optional<std::uint32_t>(1));
expect(! st[~sf1]);
st[sf1] = 2;
expect(st[sf1] == 2);
expect(st[~sf1] != boost::none);
expect(st[~sf1] == boost::optional<std::uint32_t>(2));
expect(!! st[~sf1]);
st[sf1] = 1;
expect(st[sf1] == 1);
expect(!! st[sf1]);
expect(!! st[~sf1]);
st[sf1] = 0;
expect(! st[sf1]);
expect(!! st[~sf1]);
st[~sf1] = boost::none;
expect(! st[~sf1]);
expect(st[~sf1] == boost::none);
expect(st[~sf1] == boost::optional<std::uint32_t>{});
st[~sf1] = boost::none;
expect(! st[~sf1]);
except([&]() { return st[sf1] == 0; });
except([&]() { return *st[~sf1]; });
st[sf1] = 1;
expect(st[sf1] == 1);
expect(!! st[sf1]);
expect(!! st[~sf1]);
st[sf1] = 3;
st[sf2] = st[sf1];
expect(st[sf1] == 3);
expect(st[sf2] == 3);
expect(st[sf2] == st[sf1]);
st[sf1] = 4;
st[sf2] = st[sf1];
expect(st[sf1] == 4);
expect(st[sf2] == 4);
expect(st[sf2] == st[sf1]);
}
// Write templated object
{
STObject st(sot, sfGeneric);
expect(!! st[~sf1]);
expect(st[~sf1] != boost::none);
expect(st[sf1] == 0);
expect(*st[~sf1] == 0);
expect(! st[~sf2]);
expect(st[~sf2] == boost::none);
except([&]() { return st[sf2] == 0; });
expect(!! st[~sf3]);
expect(st[~sf3] != boost::none);
expect(st[sf3] == 0);
except([&]() { st[~sf1] = boost::none; });
st[sf1] = 1;
expect(st[sf1] == 1);
expect(*st[~sf1] == 1);
expect(!! st[~sf1]);
st[sf1] = 0;
expect(st[sf1] == 0);
expect(*st[~sf1] == 0);
expect(!! st[~sf1]);
st[sf2] = 2;
expect(st[sf2] == 2);
expect(*st[~sf2] == 2);
expect(!! st[~sf2]);
st[~sf2] = boost::none;
except([&]() { return *st[~sf2]; });
expect(! st[~sf2]);
st[sf3] = 3;
expect(st[sf3] == 3);
expect(*st[~sf3] == 3);
expect(!! st[~sf3]);
st[sf3] = 2;
expect(st[sf3] == 2);
expect(*st[~sf3] == 2);
expect(!! st[~sf3]);
st[sf3] = 0;
expect(st[sf3] == 0);
expect(*st[~sf3] == 0);
expect(!! st[~sf3]);
except([&]() { st[~sf3] = boost::none; });
expect(st[sf3] == 0);
expect(*st[~sf3] == 0);
expect(!! st[~sf3]);
}
// coercion operator to boost::optional
{
STObject st(sfGeneric);
auto const v = ~st[~sf1];
static_assert(std::is_same<
std::decay_t<decltype(v)>,
boost::optional<std::uint32_t>>::value, "");
}
// UDT scalar fields
{
STObject st(sfGeneric);
st[sfAmount] = STAmount{};
st[sfAccount] = AccountID{};
st[sfDigest] = uint256{};
[&](STAmount){}(st[sfAmount]);
[&](AccountID){}(st[sfAccount]);
[&](uint256){}(st[sfDigest]);
}
// STBlob and slice
{
{
STObject st(sfGeneric);
Buffer b(1);
expect(! b.empty());
st[sf4] = std::move(b);
expect(b.empty());
expect(Slice(st[sf4]).size() == 1);
st[~sf4] = boost::none;
expect(! ~st[~sf4]);
b = Buffer{2};
st[sf4] = Slice(b);
expect(b.size() == 2);
expect(Slice(st[sf4]).size() == 2);
st[sf5] = st[sf4];
expect(Slice(st[sf4]).size() == 2);
expect(Slice(st[sf5]).size() == 2);
}
{
STObject st(sot, sfGeneric);
expect(st[sf5] == Slice{});
expect(!! st[~sf5]);
expect(!! ~st[~sf5]);
Buffer b(1);
st[sf5] = std::move(b);
expect(b.empty());
expect(Slice(st[sf5]).size() == 1);
st[~sf4] = boost::none;
expect(! ~st[~sf4]);
}
}
// UDT blobs
{
STObject st(sfGeneric);
expect(! st[~sf5]);
auto const kp = generateKeyPair(
KeyType::secp256k1,
generateSeed("masterpassphrase"));
st[sf5] = kp.first;
expect(st[sf5] != PublicKey{});
st[~sf5] = boost::none;
#if 0
pk = st[sf5];
expect(pk.size() == 0);
#endif
}
// By reference fields
{
auto const& sf = sfIndexes;
STObject st(sfGeneric);
std::vector<uint256> v;
v.emplace_back(1);
st[sf] = v;
st[sf] = std::move(v);
auto const& cst = st;
expect(cst[sf].size() == 1);
expect(cst[~sf]->size() == 1);
static_assert(std::is_same<decltype(cst[sfIndexes]),
std::vector<uint256> const&>::value, "");
}
// Default by reference field
{
auto const& sf1 = sfIndexes;
auto const& sf2 = sfHashes;
auto const& sf3 = sfAmendments;
auto const sot = [&]()
{
SOTemplate sot;
sot.push_back(SOElement(sf1, SOE_REQUIRED));
sot.push_back(SOElement(sf2, SOE_OPTIONAL));
sot.push_back(SOElement(sf3, SOE_DEFAULT));
return sot;
}();
STObject st(sot, sfGeneric);
auto const& cst(st);
expect(cst[sf1].size() == 0);
expect(! cst[~sf2]);
expect(cst[sf3].size() == 0);
std::vector<uint256> v;
v.emplace_back(1);
st[sf1] = v;
expect(cst[sf1].size() == 1);
expect(cst[sf1][0] == uint256{1});
st[sf2] = v;
expect(cst[sf2].size() == 1);
expect(cst[sf2][0] == uint256{1});
st[~sf2] = boost::none;
expect(! st[~sf2]);
st[sf3] = v;
expect(cst[sf3].size() == 1);
expect(cst[sf3][0] == uint256{1});
st[sf3] = std::vector<uint256>{};
expect(cst[sf3].size() == 0);
}
}
void
run()
{
testFields();
testSerialization();
testParseJSONArray();
testParseJSONArrayWithInvalidChildrenObjects();
}
};
BEAST_DEFINE_TESTSUITE(SerializedObject,ripple_data,ripple);
BEAST_DEFINE_TESTSUITE(STObject,protocol,ripple);
} // ripple