Files
rippled/include/xrpl/protocol/STNumber.h
Ed Hennis 692070dbf1 Add semi-automatic rounding of STNumbers based on Asset types
- Create a new SField metadata enum, sMD_NeedsAsset, which indicates
  the field should be associated with an Asset so it can be rounded.
- Add a new STTakesAsset intermediate class to handle the Asset
  association to a derived ST class. Currently only used in STNumber,
  but could be used by other types in the future.
- Add "associateAsset" which takes an SLE and an Asset, finds the
  sMD_NeedsAsset fields, and associates the Asset to them. In the case
  of STNumber, that both stores the Asset, and rounds the value
  immediately.
- Transactors only need to add a call to associateAsset _after_ all of
  the STNumbers have been set. Unfortunately, the inner workings of
  STObject do not do the association correctly with uninitialized
  fields.
- When serializing an STNumber that has an Asset, round it before
  serializing.
- Add an override of roundToAsset, which rounds a Number value in place
  to an Asset, but without any additional scale.
- Update and fix a bunch of Loan-related tests to accommodate the
  expanded Number class.
- (Not all tests are fixed yet.)
2025-12-08 18:38:30 -05:00

94 lines
2.0 KiB
C++

#ifndef XRPL_PROTOCOL_STNUMBER_H_INCLUDED
#define XRPL_PROTOCOL_STNUMBER_H_INCLUDED
#include <xrpl/basics/CountedObject.h>
#include <xrpl/basics/Number.h>
#include <xrpl/protocol/STBase.h>
#include <xrpl/protocol/STTakesAsset.h>
#include <ostream>
namespace ripple {
/**
* A serializable number.
*
* This type is-a `Number`, and can be used everywhere that is accepted.
* This type simply integrates `Number` with the serialization framework,
* letting it be used for fields in ledger entries and transactions.
* It is effectively an `STAmount` sans `Asset`:
* it can represent a value of any token type (XRP, IOU, or MPT)
* without paying the storage cost of duplicating asset information
* that may be deduced from the context.
*/
class STNumber : public STTakesAsset, public CountedObject<STNumber>
{
private:
Number value_;
public:
using value_type = Number;
STNumber() = default;
explicit STNumber(SField const& field, Number const& value = Number());
STNumber(SerialIter& sit, SField const& field);
SerializedTypeID
getSType() const override;
std::string
getText() const override;
void
add(Serializer& s) const override;
Number const&
value() const;
void
setValue(Number const& v);
STNumber&
operator=(Number const& rhs)
{
setValue(rhs);
return *this;
}
bool
isEquivalent(STBase const& t) const override;
bool
isDefault() const override;
void
associateAsset(Asset const& a) override;
operator Number() const
{
return value_;
}
private:
STBase*
copy(std::size_t n, void* buf) const override;
STBase*
move(std::size_t n, void* buf) override;
};
std::ostream&
operator<<(std::ostream& out, STNumber const& rhs);
struct NumberParts
{
std::uint64_t mantissa = 0;
int exponent = 0;
bool negative = false;
};
NumberParts
partsFromString(std::string const& number);
STNumber
numberFromJson(SField const& field, Json::Value const& value);
} // namespace ripple
#endif