xrpld
Loading...
Searching...
No Matches
STObject.h
1#pragma once
2
3#include <xrpl/basics/CountedObject.h>
4#include <xrpl/basics/Slice.h>
5#include <xrpl/basics/chrono.h>
6#include <xrpl/basics/contract.h>
7#include <xrpl/beast/utility/instrumentation.h>
8#include <xrpl/protocol/HashPrefix.h>
9#include <xrpl/protocol/SOTemplate.h>
10#include <xrpl/protocol/STAmount.h>
11#include <xrpl/protocol/STBase.h>
12#include <xrpl/protocol/STCurrency.h>
13#include <xrpl/protocol/STIssue.h>
14#include <xrpl/protocol/STPathSet.h>
15#include <xrpl/protocol/STVector256.h>
16#include <xrpl/protocol/Units.h>
17#include <xrpl/protocol/detail/STVar.h>
18
19#include <boost/iterator/transform_iterator.hpp>
20
21#include <optional>
22#include <stdexcept>
23#include <type_traits>
24#include <utility>
25
26namespace xrpl {
27
28class STArray;
29
30inline void
32{
33 Throw<std::runtime_error>("Field not found: " + field.getName());
34}
35
36class STObject : public STBase, public CountedObject<STObject>
37{
38 // Proxy value for a STBase derived class
39 template <class T>
40 class Proxy;
41 template <class T>
42 class ValueProxy;
43 template <class T>
44 class OptionalProxy;
45
46 struct Transform
47 {
48 explicit Transform() = default;
49
52
53 STBase const&
54 operator()(detail::STVar const& e) const;
55 };
56
58
60 SOTemplate const* type_{};
61
62public:
63 using iterator = boost::transform_iterator<Transform, STObject::list_type::const_iterator>;
64
65 ~STObject() override = default;
66 STObject(STObject const&) = default;
67
68 template <typename F>
69 STObject(SOTemplate const& type, SField const& name, F&& f) : STObject(type, name)
70 {
71 f(*this);
72 }
73
75 operator=(STObject const&) = default;
78 operator=(STObject&& other);
79
80 STObject(SOTemplate const& type, SField const& name);
81 STObject(SOTemplate const& type, SerialIter& sit, SField const& name);
82 STObject(SerialIter& sit, SField const& name, int depth = 0);
83 STObject(SerialIter&& sit, SField const& name);
84 explicit STObject(SField const& name);
85
86 static STObject
87 makeInnerObject(SField const& name);
88
89 [[nodiscard]] iterator
90 begin() const;
91
92 [[nodiscard]] iterator
93 end() const;
94
95 [[nodiscard]] bool
96 empty() const;
97
98 void
100
101 void
102 applyTemplate(SOTemplate const& type);
103
104 void
106
107 [[nodiscard]] bool
108 isFree() const;
109
110 void
111 set(SOTemplate const&);
112
113 bool
114 set(SerialIter& u, int depth = 0);
115
116 [[nodiscard]] SerializedTypeID
117 getSType() const override;
118
119 [[nodiscard]] bool
120 isEquivalent(STBase const& t) const override;
121
122 [[nodiscard]] bool
123 isDefault() const override;
124
125 void
126 add(Serializer& s) const override;
127
128 [[nodiscard]] std::string
129 getFullText() const override;
130
131 [[nodiscard]] std::string
132 getText() const override;
133
134 // TODO(tom): options should be an enum.
135 [[nodiscard]] json::Value getJson(JsonOptions = JsonOptions::Values::None) const override;
136
137 void
139
140 [[nodiscard]] Serializer
141 getSerializer() const;
142
143 template <class... Args>
145 emplaceBack(Args&&... args);
146
147 [[nodiscard]] int
148 getCount() const;
149
150 bool
152 bool
154 [[nodiscard]] bool
155 isFlag(std::uint32_t) const;
156
157 [[nodiscard]] std::uint32_t
158 getFlags() const;
159
160 [[nodiscard]] uint256
161 getHash(HashPrefix prefix) const;
162
163 [[nodiscard]] uint256
164 getSigningHash(HashPrefix prefix) const;
165
166 [[nodiscard]] STBase const&
167 peekAtIndex(int offset) const;
168
169 STBase&
170 getIndex(int offset);
171
172 [[nodiscard]] STBase const*
173 peekAtPIndex(int offset) const;
174
175 STBase*
176 getPIndex(int offset);
177
178 [[nodiscard]] int
179 getFieldIndex(SField const& field) const;
180
181 [[nodiscard]] SField const&
182 getFieldSType(int index) const;
183
184 [[nodiscard]] STBase const&
185 peekAtField(SField const& field) const;
186
187 STBase&
188 getField(SField const& field);
189
190 [[nodiscard]] STBase const*
191 peekAtPField(SField const& field) const;
192
193 STBase*
194 getPField(SField const& field, bool createOkay = false);
195
196 // these throw if the field type doesn't match, or return default values
197 // if the field is optional but not present
198 [[nodiscard]] unsigned char
199 getFieldU8(SField const& field) const;
200 [[nodiscard]] std::uint16_t
201 getFieldU16(SField const& field) const;
202 [[nodiscard]] std::uint32_t
203 getFieldU32(SField const& field) const;
204 [[nodiscard]] std::uint64_t
205 getFieldU64(SField const& field) const;
206 [[nodiscard]] uint128
207 getFieldH128(SField const& field) const;
208
209 [[nodiscard]] uint160
210 getFieldH160(SField const& field) const;
211 [[nodiscard]] uint192
212 getFieldH192(SField const& field) const;
213 [[nodiscard]] uint256
214 getFieldH256(SField const& field) const;
215 [[nodiscard]] std::int32_t
216 getFieldI32(SField const& field) const;
217 [[nodiscard]] AccountID
218 getAccountID(SField const& field) const;
219
220 [[nodiscard]] Blob
221 getFieldVL(SField const& field) const;
222 [[nodiscard]] STAmount const&
223 getFieldAmount(SField const& field) const;
224 [[nodiscard]] STPathSet const&
225 getFieldPathSet(SField const& field) const;
226 [[nodiscard]] STVector256 const&
227 getFieldV256(SField const& field) const;
228 // If not found, returns an object constructed with the given field
229 [[nodiscard]] STObject
230 getFieldObject(SField const& field) const;
231 [[nodiscard]] STArray const&
232 getFieldArray(SField const& field) const;
233 [[nodiscard]] STCurrency const&
234 getFieldCurrency(SField const& field) const;
235 [[nodiscard]] STNumber const&
236 getFieldNumber(SField const& field) const;
237
245 template <class T>
246 T::value_type
247 operator[](TypedField<T> const& f) const;
248
257 template <class T>
259 operator[](OptionaledField<T> const& of) const;
260
268 template <class T>
270 operator[](TypedField<T> const& f);
271
281 template <class T>
284
292 template <class T>
293 [[nodiscard]] T::value_type
294 at(TypedField<T> const& f) const;
295
304 template <class T>
306 at(OptionaledField<T> const& of) const;
307
315 template <class T>
317 at(TypedField<T> const& f);
318
328 template <class T>
330 at(OptionaledField<T> const& of);
331
335 void
337
338 void
339 set(STBase&& v);
340
341 void
342 setFieldU8(SField const& field, unsigned char);
343 void
344 setFieldU16(SField const& field, std::uint16_t);
345 void
346 setFieldU32(SField const& field, std::uint32_t);
347 void
348 setFieldU64(SField const& field, std::uint64_t);
349 void
350 setFieldH128(SField const& field, uint128 const&);
351 void
352 setFieldH192(SField const& field, uint192 const&);
353 void
354 setFieldH256(SField const& field, uint256 const&);
355 void
356 setFieldI32(SField const& field, std::int32_t);
357 void
358 setFieldVL(SField const& field, Blob const&);
359 void
360 setFieldVL(SField const& field, Slice const&);
361
362 void
363 setAccountID(SField const& field, AccountID const&);
364
365 void
366 setFieldAmount(SField const& field, STAmount const&);
367 void
368 setFieldIssue(SField const& field, STIssue const&);
369 void
370 setFieldCurrency(SField const& field, STCurrency const&);
371 void
372 setFieldNumber(SField const& field, STNumber const&);
373 void
374 setFieldPathSet(SField const& field, STPathSet const&);
375 void
376 setFieldV256(SField const& field, STVector256 const& v);
377 void
378 setFieldArray(SField const& field, STArray const& v);
379 void
380 setFieldObject(SField const& field, STObject const& v);
381
382 template <class Tag>
383 void
384 setFieldH160(SField const& field, BaseUInt<160, Tag> const& v);
385
386 STObject&
387 peekFieldObject(SField const& field);
388 STArray&
389 peekFieldArray(SField const& field);
390
391 [[nodiscard]] bool
392 isFieldPresent(SField const& field) const;
393 STBase*
394 makeFieldPresent(SField const& field);
395 void
396 makeFieldAbsent(SField const& field);
397 bool
398 delField(SField const& field);
399 void
400 delField(int index);
401
402 [[nodiscard]] SOEStyle
403 getStyle(SField const& field) const;
404
405 [[nodiscard]] bool
406 hasMatchingEntry(STBase const&) const;
407
408 bool
409 operator==(STObject const& o) const;
410 bool
411 operator!=(STObject const& o) const;
412
413 class FieldErr;
414
415private:
416 enum class WhichFields : bool {
417 // These values are carefully chosen to do the right thing if passed
418 // to SField::shouldInclude (bool)
421 };
422
423 void
424 add(Serializer& s, WhichFields whichFields) const;
425
426 // Sort the entries in an STObject into the order that they will be
427 // serialized. Note: they are not sorted into pointer value order, they
428 // are sorted by SField::fieldCode.
430 getSortedFields(STObject const& objToSort, WhichFields whichFields);
431
432 // Implementation for getting (most) fields that return by value.
433 //
434 // The remove_cv and remove_reference are necessitated by the STBitString
435 // types. Their value() returns by const ref. We return those types
436 // by value.
437 template <
438 typename T,
440 V
441 getFieldByValue(SField const& field) const;
442
443 // Implementations for getting (most) fields that return by const reference.
444 //
445 // If an absent optional field is deserialized we don't have anything
446 // obvious to return. So we insist on having the call provide an
447 // 'empty' value we return in that circumstance.
448 template <typename T, typename V>
449 V const&
450 getFieldByConstRef(SField const& field, V const& empty) const;
451
452 // Implementation for setting most fields with a setValue() method.
453 template <typename T, typename V>
454 void
455 setFieldUsingSetValue(SField const& field, V value);
456
457 // Implementation for setting fields using assignment
458 template <typename T>
459 void
460 setFieldUsingAssignment(SField const& field, T const& value);
461
462 // Implementation for peeking STObjects and STArrays
463 template <typename T>
464 T&
465 peekField(SField const& field);
466
467 STBase*
468 copy(std::size_t n, void* buf) const override;
469 STBase*
470 move(std::size_t n, void* buf) override;
471
472 friend class detail::STVar;
473};
474
475//------------------------------------------------------------------------------
476
477template <class T>
479{
480public:
481 using value_type = T::value_type;
482
483 [[nodiscard]] value_type
484 value() const;
485
487 operator*() const;
488
491 T const*
492 operator->() const;
493
494protected:
498
499 Proxy(Proxy const&) = default;
500
501 Proxy(STObject* st, TypedField<T> const* f);
502
503 [[nodiscard]] T const*
504 find() const;
505
506 template <class U>
507 void
508 assign(U&& u);
509};
510
511// Constraint += and -= ValueProxy operators
512// to value types that support arithmetic operations
513template <typename U>
516template <typename U, typename Value = U::value_type, typename Unit = U::unit_type>
519template <typename U, typename Value = U::value_type>
521template <typename U>
523
524template <class T, class U>
525concept Addable = requires(T t, U u) { t = t + u; };
526template <typename T, typename U>
529
530template <class T>
532{
533private:
534 using value_type = T::value_type;
535
536public:
537 ValueProxy(ValueProxy const&) = default;
539 operator=(ValueProxy const&) = delete;
540
541 template <class U>
543 operator=(U&& u);
544
545 // Convenience operators for value types supporting
546 // arithmetic operations
547 template <IsArithmetic U>
550 operator+=(U const& u);
551
552 template <IsArithmetic U>
555 operator-=(U const& u);
556
557 operator value_type() const;
558
559 template <typename U>
560 friend bool
561 operator==(U const& lhs, STObject::ValueProxy<T> const& rhs)
562 {
563 return rhs.value() == lhs;
564 }
565
566private:
567 friend class STObject;
568
569 ValueProxy(STObject* st, TypedField<T> const* f);
570};
571
572template <class T>
574{
575private:
576 using value_type = T::value_type;
577
579
580public:
581 OptionalProxy(OptionalProxy const&) = default;
583 operator=(OptionalProxy const&) = delete;
584
590 explicit
591 operator bool() const noexcept;
592
593 operator optional_type() const;
594
597 operator~() const;
598
599 friend bool
600 operator==(OptionalProxy const& lhs, std::nullopt_t) noexcept
601 {
602 return !lhs.engaged();
603 }
604
605 friend bool
607 {
608 return rhs == std::nullopt;
609 }
610
611 friend bool
612 operator==(OptionalProxy const& lhs, optional_type const& rhs) noexcept
613 {
614 if (!lhs.engaged())
615 return !rhs;
616 if (!rhs)
617 return false;
618 return *lhs == *rhs;
619 }
620
621 friend bool
622 operator==(optional_type const& lhs, OptionalProxy const& rhs) noexcept
623 {
624 return rhs == lhs;
625 }
626
627 friend bool
628 operator==(OptionalProxy const& lhs, OptionalProxy const& rhs) noexcept
629 {
630 if (lhs.engaged() != rhs.engaged())
631 return false;
632 return !lhs.engaged() || *lhs == *rhs;
633 }
634
635 friend bool
637 {
638 return !(lhs == std::nullopt);
639 }
640
641 friend bool
643 {
644 return !(rhs == std::nullopt);
645 }
646
647 friend bool
648 operator!=(OptionalProxy const& lhs, optional_type const& rhs) noexcept
649 {
650 return !(lhs == rhs);
651 }
652
653 friend bool
654 operator!=(optional_type const& lhs, OptionalProxy const& rhs) noexcept
655 {
656 return !(lhs == rhs);
657 }
658
659 friend bool
660 operator!=(OptionalProxy const& lhs, OptionalProxy const& rhs) noexcept
661 {
662 return !(lhs == rhs);
663 }
664
665 // Emulate std::optional::value_or
666 [[nodiscard]] value_type
667 valueOr(value_type val) const;
668
672 operator=(optional_type&& v); // NOLINT(cppcoreguidelines-rvalue-reference-param-not-moved)
674 operator=(optional_type const& v);
675
676 template <class U>
678 operator=(U&& u);
679
680private:
681 friend class STObject;
682
683 OptionalProxy(STObject* st, TypedField<T> const* f);
684
685 [[nodiscard]] bool
686 engaged() const noexcept;
687
688 void
689 disengage();
690
691 [[nodiscard]] optional_type
692 optionalValue() const;
693};
694
699
700template <class T>
702{
703 if (st_->type_ != nullptr)
704 {
705 // STObject has associated template
706 if (!st_->peekAtPField(*f_))
707 Throw<STObject::FieldErr>("Template field error '" + this->f_->getName() + "'");
708 style_ = st_->type_->style(*f_);
709 }
710 else
711 {
712 style_ = SoeInvalid;
713 }
714}
715
716template <class T>
717auto
719{
720 auto const t = find();
721 if (t)
722 return t->value();
723 if (style_ == SoeInvalid)
724 {
725 Throw<STObject::FieldErr>("Value requested from invalid STObject.");
726 }
727 if (style_ != SoeDefault)
728 {
729 Throw<STObject::FieldErr>("Missing field '" + this->f_->getName() + "'");
730 }
731 return value_type{};
732}
733
734template <class T>
735auto
737{
738 return this->value();
739}
740
743template <class T>
744T const*
746{
747 return this->find();
748}
749
750template <class T>
751inline T const*
753{
754 return dynamic_cast<T const*>(st_->peekAtPField(*f_));
755}
756
757template <class T>
758template <class U>
759void
761{
762 if (style_ == SoeDefault && u == value_type{})
763 {
764 st_->makeFieldAbsent(*f_);
765 return;
766 }
767 T* t = nullptr;
768 if (style_ == SoeInvalid)
769 {
770 t = dynamic_cast<T*>(st_->getPField(*f_, true));
771 }
772 else
773 {
774 t = dynamic_cast<T*>(st_->makeFieldPresent(*f_));
775 }
776 XRPL_ASSERT(t, "xrpl::STObject::Proxy::assign : type cast succeeded");
777 *t = std::forward<U>(u);
778}
779
780//------------------------------------------------------------------------------
781
782template <class T>
783template <class U>
786{
787 this->assign(std::forward<U>(u));
788 return *this;
789}
790
791template <typename T>
792template <IsArithmetic U>
796{
797 this->assign(this->value() + u);
798 return *this;
799}
800
801template <class T>
802template <IsArithmetic U>
806{
807 this->assign(this->value() - u);
808 return *this;
809}
810
811template <class T>
813operator value_type() const
814{
815 return this->value();
816}
817
818template <class T>
822
823//------------------------------------------------------------------------------
824
825template <class T>
827operator bool() const noexcept
828{
829 return engaged();
830}
831
832template <class T>
834operator typename STObject::OptionalProxy<T>::optional_type() const
835{
836 return optionalValue();
837}
838
839template <class T>
845
846template <class T>
847auto
853
854template <class T>
855auto
857 optional_type&& v) // NOLINT(cppcoreguidelines-rvalue-reference-param-not-moved)
858 -> OptionalProxy&
859{
860 if (v)
861 {
862 this->assign(std::move(*v));
863 }
864 else
865 {
866 disengage();
867 }
868 return *this;
869}
870
871template <class T>
872auto
874{
875 if (v)
876 {
877 this->assign(*v);
878 }
879 else
880 {
881 disengage();
882 }
883 return *this;
884}
885
886template <class T>
887template <class U>
890{
891 this->assign(std::forward<U>(u));
892 return *this;
893}
894
895template <class T>
899
900template <class T>
901bool
903{
904 return this->style_ == SoeDefault || this->find() != nullptr;
905}
906
907template <class T>
908void
910{
911 if (this->style_ == SoeRequired || this->style_ == SoeDefault)
912 Throw<STObject::FieldErr>("Template field error '" + this->f_->getName() + "'");
913 if (this->style_ == SoeInvalid)
914 {
915 this->st_->delField(*this->f_);
916 }
917 else
918 {
919 this->st_->makeFieldAbsent(*this->f_);
920 }
921}
922
923template <class T>
924auto
926{
927 if (!engaged())
928 return std::nullopt;
929 return this->value();
930}
931
932template <class T>
935{
936 return engaged() ? this->value() : val;
937}
938
939//------------------------------------------------------------------------------
940
941inline STBase const&
943{
944 return e.get();
945}
946
947//------------------------------------------------------------------------------
948
949// NOLINTNEXTLINE(cppcoreguidelines-rvalue-reference-param-not-moved)
950inline STObject::STObject(SerialIter&& sit, SField const& name) : STObject(sit, name)
951{
952}
953
956{
957 return iterator(v_.begin());
958}
959
962{
963 return iterator(v_.end());
964}
965
966inline bool
968{
969 return v_.empty();
970}
971
972inline void
974{
975 v_.reserve(n);
976}
977
978inline bool
980{
981 return type_ == nullptr;
982}
983
984inline void
989
990// VFALCO NOTE does this return an expensive copy of an object with a
991// dynamic buffer?
992// VFALCO TODO Remove this function and fix the few callers.
993inline Serializer
995{
996 Serializer s;
998 return s;
999}
1000
1001template <class... Args>
1002inline std::size_t
1004{
1005 v_.emplace_back(std::forward<Args>(args)...);
1006 return v_.size() - 1;
1007}
1008
1009inline int
1011{
1012 return v_.size();
1013}
1014
1015inline STBase const&
1016STObject::peekAtIndex(int offset) const
1017{
1018 return v_[offset].get();
1019}
1020
1021inline STBase&
1023{
1024 return v_[offset].get();
1025}
1026
1027inline STBase const*
1028STObject::peekAtPIndex(int offset) const
1029{
1030 return &v_[offset].get();
1031}
1032
1033inline STBase*
1035{
1036 return &v_[offset].get();
1037}
1038
1039template <class T>
1040T::value_type
1042{
1043 return at(f);
1044}
1045
1046template <class T>
1049{
1050 return at(of);
1051}
1052
1053template <class T>
1054inline auto
1056{
1057 return at(f);
1058}
1059
1060template <class T>
1061inline auto
1063{
1064 return at(of);
1065}
1066
1067template <class T>
1068[[nodiscard]] T::value_type
1070{
1071 auto const b = peekAtPField(f);
1072 if (!b)
1073 {
1074 // This is a free object (no constraints)
1075 // with no template
1076 Throw<STObject::FieldErr>("Missing field: " + f.getName());
1077 }
1078
1079 if (auto const u = dynamic_cast<T const*>(b))
1080 return u->value();
1081
1082 XRPL_ASSERT(type_, "xrpl::STObject::at(TypedField auto) : field template non-null");
1083 XRPL_ASSERT(
1084 b->getSType() == STI_NOTPRESENT, "xrpl::STObject::at(TypedField auto) : type not present");
1085
1086 if (type_->style(f) == SoeOptional)
1087 Throw<STObject::FieldErr>("Missing optional field: " + f.getName());
1088
1089 XRPL_ASSERT(
1090 type_->style(f) == SoeDefault,
1091 "xrpl::STObject::at(TypedField auto) : template style is default");
1092
1093 // Used to help handle the case where value_type is a const reference,
1094 // otherwise we would return the address of a temporary.
1095 static std::decay_t<typename T::value_type> const kDV{};
1096 return kDV;
1097}
1098
1099template <class T>
1102{
1103 auto const b = peekAtPField(*of.f);
1104 if (!b)
1105 return std::nullopt;
1106 auto const u = dynamic_cast<T const*>(b);
1107 if (!u)
1108 {
1109 XRPL_ASSERT(
1110 type_,
1111 "xrpl::STObject::at(OptionaledField auto) : field template "
1112 "non-null");
1113 XRPL_ASSERT(
1114 b->getSType() == STI_NOTPRESENT,
1115 "xrpl::STObject::at(OptionaledField auto) : type not present");
1116 if (type_->style(*of.f) == SoeOptional)
1117 return std::nullopt;
1118 XRPL_ASSERT(
1119 type_->style(*of.f) == SoeDefault,
1120 "xrpl::STObject::at(OptionaledField auto) : template style is "
1121 "default");
1122 return typename T::value_type{};
1123 }
1124 return u->value();
1125}
1126
1127template <class T>
1128inline auto
1130{
1131 return ValueProxy<T>(this, &f);
1132}
1133
1134template <class T>
1135inline auto
1137{
1138 return OptionalProxy<T>(this, of.f);
1139}
1140
1141template <class Tag>
1142void
1144{
1145 STBase* rf = getPField(field, true);
1146
1147 if (!rf)
1148 throwFieldNotFound(field);
1149
1150 if (rf->getSType() == STI_NOTPRESENT)
1151 rf = makeFieldPresent(field);
1152
1153 using Bits = STBitString<160>;
1154 if (auto cf = dynamic_cast<Bits*>(rf))
1155 {
1156 cf->setValue(v);
1157 }
1158 else
1159 {
1160 Throw<std::runtime_error>("Wrong field type");
1161 }
1162}
1163
1164inline bool
1166{
1167 return !(*this == o);
1168}
1169
1170template <typename T, typename V>
1171V
1173{
1174 STBase const* rf = peekAtPField(field);
1175
1176 if (!rf)
1177 throwFieldNotFound(field);
1178
1179 SerializedTypeID const id = rf->getSType();
1180
1181 if (id == STI_NOTPRESENT)
1182 return V(); // optional field not present
1183
1184 T const* cf = dynamic_cast<T const*>(rf);
1185
1186 if (!cf)
1187 Throw<std::runtime_error>("Wrong field type");
1188
1189 return cf->value();
1190}
1191
1192// Implementations for getting (most) fields that return by const reference.
1193//
1194// If an absent optional field is deserialized we don't have anything
1195// obvious to return. So we insist on having the call provide an
1196// 'empty' value we return in that circumstance.
1197template <typename T, typename V>
1198V const&
1199STObject::getFieldByConstRef(SField const& field, V const& empty) const
1200{
1201 STBase const* rf = peekAtPField(field);
1202
1203 if (!rf)
1204 throwFieldNotFound(field);
1205
1206 SerializedTypeID const id = rf->getSType();
1207
1208 if (id == STI_NOTPRESENT)
1209 {
1210 // NOLINTNEXTLINE(bugprone-return-const-ref-from-parameter)
1211 return empty; // optional field not present
1212 }
1213
1214 T const* cf = dynamic_cast<T const*>(rf);
1215
1216 if (!cf)
1217 Throw<std::runtime_error>("Wrong field type");
1218
1219 return *cf;
1220}
1221
1222// Implementation for setting most fields with a setValue() method.
1223template <typename T, typename V>
1224void
1226{
1227 static_assert(!std::is_lvalue_reference_v<V>, "");
1228
1229 STBase* rf = getPField(field, true);
1230
1231 if (!rf)
1232 throwFieldNotFound(field);
1233
1234 if (rf->getSType() == STI_NOTPRESENT)
1235 rf = makeFieldPresent(field);
1236
1237 T* cf = dynamic_cast<T*>(rf);
1238
1239 if (!cf)
1240 Throw<std::runtime_error>("Wrong field type");
1241
1242 cf->setValue(std::move(value));
1243}
1244
1245// Implementation for setting fields using assignment
1246template <typename T>
1247void
1248STObject::setFieldUsingAssignment(SField const& field, T const& value)
1249{
1250 STBase* rf = getPField(field, true);
1251
1252 if (!rf)
1253 throwFieldNotFound(field);
1254
1255 if (rf->getSType() == STI_NOTPRESENT)
1256 rf = makeFieldPresent(field);
1257
1258 T* cf = dynamic_cast<T*>(rf);
1259
1260 if (!cf)
1261 Throw<std::runtime_error>("Wrong field type");
1262
1263 (*cf) = value;
1264}
1265
1266// Implementation for peeking STObjects and STArrays
1267template <typename T>
1268T&
1270{
1271 STBase* rf = getPField(field, true);
1272
1273 if (!rf)
1274 throwFieldNotFound(field);
1275
1276 if (rf->getSType() == STI_NOTPRESENT)
1277 rf = makeFieldPresent(field);
1278
1279 T* cf = dynamic_cast<T*>(rf);
1280
1281 if (!cf)
1282 Throw<std::runtime_error>("Wrong field type");
1283
1284 return *cf;
1285}
1286
1287} // namespace xrpl
Represents a JSON value.
Definition json_value.h:130
Integers of any length that is a multiple of 32-bits.
Definition base_uint.h:71
Identifies fields.
Definition SField.h:130
std::string const & getName() const
Definition SField.h:196
Defines the fields and their attributes within a STObject.
Definition SOTemplate.h:96
A type which can be exported to a well known binary format.
Definition STBase.h:117
virtual SerializedTypeID getSType() const
Definition STBase.cpp:60
A serializable number.
Definition STNumber.h:35
T runtime_error(T... args)
friend bool operator!=(OptionalProxy const &lhs, optional_type const &rhs) noexcept
Definition STObject.h:648
friend bool operator==(OptionalProxy const &lhs, optional_type const &rhs) noexcept
Definition STObject.h:612
friend bool operator==(optional_type const &lhs, OptionalProxy const &rhs) noexcept
Definition STObject.h:622
friend bool operator==(OptionalProxy const &lhs, OptionalProxy const &rhs) noexcept
Definition STObject.h:628
std::enable_if_t< std::is_assignable_v< T, U >, OptionalProxy & > operator=(U &&u)
OptionalProxy(OptionalProxy const &)=default
value_type valueOr(value_type val) const
Definition STObject.h:934
optional_type operator~() const
Explicit conversion to std::optional.
Definition STObject.h:841
friend bool operator!=(OptionalProxy const &lhs, std::nullopt_t) noexcept
Definition STObject.h:636
std::optional< std::decay_t< value_type > > optional_type
Definition STObject.h:578
friend bool operator!=(std::nullopt_t, OptionalProxy const &rhs) noexcept
Definition STObject.h:642
OptionalProxy & operator=(OptionalProxy const &)=delete
optional_type optionalValue() const
Definition STObject.h:925
bool engaged() const noexcept
Definition STObject.h:902
friend bool operator!=(optional_type const &lhs, OptionalProxy const &rhs) noexcept
Definition STObject.h:654
friend bool operator==(std::nullopt_t, OptionalProxy const &rhs) noexcept
Definition STObject.h:606
friend bool operator!=(OptionalProxy const &lhs, OptionalProxy const &rhs) noexcept
Definition STObject.h:660
void assign(U &&u)
Definition STObject.h:760
Proxy(Proxy const &)=default
T::value_type value_type
Definition STObject.h:481
value_type operator*() const
Definition STObject.h:736
T const * operator->() const
Do not use operator->() unless the field is required, or you've checked that it's set.
Definition STObject.h:745
value_type value() const
Definition STObject.h:718
T const * find() const
Definition STObject.h:752
TypedField< T > const * f_
Definition STObject.h:497
ValueProxy(ValueProxy const &)=default
ValueProxy & operator=(ValueProxy const &)=delete
ValueProxy & operator-=(U const &u)
ValueProxy & operator+=(U const &u)
friend bool operator==(U const &lhs, STObject::ValueProxy< T > const &rhs)
Definition STObject.h:561
T::value_type value_type
Definition STObject.h:534
std::enable_if_t< std::is_assignable_v< T, U >, ValueProxy & > operator=(U &&u)
void setFieldU8(SField const &field, unsigned char)
Definition STObject.cpp:721
SField const & getFieldSType(int index) const
Definition STObject.cpp:421
uint192 getFieldH192(SField const &field) const
Definition STObject.cpp:615
bool isFree() const
Definition STObject.h:979
T::value_type at(TypedField< T > const &f) const
Get the value of a field.
Definition STObject.h:1069
STBase const * peekAtPIndex(int offset) const
Definition STObject.h:1028
void setFieldH192(SField const &field, uint192 const &)
Definition STObject.cpp:751
STCurrency const & getFieldCurrency(SField const &field) const
Definition STObject.cpp:685
Blob getFieldVL(SField const &field) const
Definition STObject.cpp:639
void addWithoutSigningFields(Serializer &s) const
Definition STObject.h:985
void setFieldIssue(SField const &field, STIssue const &)
Definition STObject.cpp:805
uint128 getFieldH128(SField const &field) const
Definition STObject.cpp:603
iterator begin() const
Definition STObject.h:955
bool operator==(STObject const &o) const
Definition STObject.cpp:848
bool isEquivalent(STBase const &t) const override
Definition STObject.cpp:341
bool empty() const
Definition STObject.h:967
void setFieldNumber(SField const &field, STNumber const &)
Definition STObject.cpp:811
void setFieldV256(SField const &field, STVector256 const &v)
Definition STObject.cpp:769
void setFieldU64(SField const &field, std::uint64_t)
Definition STObject.cpp:739
unsigned char getFieldU8(SField const &field) const
Definition STObject.cpp:579
std::uint32_t getFieldU32(SField const &field) const
Definition STObject.cpp:591
STBase const & peekAtIndex(int offset) const
Definition STObject.h:1016
V const & getFieldByConstRef(SField const &field, V const &empty) const
STNumber const & getFieldNumber(SField const &field) const
Definition STObject.cpp:692
void setFieldVL(SField const &field, Blob const &)
Definition STObject.cpp:781
void reserve(std::size_t n)
Definition STObject.h:973
T::value_type operator[](TypedField< T > const &f) const
Get the value of a field.
Definition STObject.h:1041
iterator end() const
Definition STObject.h:961
void applyTemplate(SOTemplate const &type)
Definition STObject.cpp:155
int getFieldIndex(SField const &field) const
Definition STObject.cpp:383
uint256 getHash(HashPrefix prefix) const
Definition STObject.cpp:365
void setFieldI32(SField const &field, std::int32_t)
Definition STObject.cpp:763
std::string getFullText() const override
Definition STObject.cpp:285
void setFieldU32(SField const &field, std::uint32_t)
Definition STObject.cpp:733
list_type v_
Definition STObject.h:59
STArray & peekFieldArray(SField const &field)
Definition STObject.cpp:471
std::string getText() const override
Definition STObject.cpp:322
~STObject() override=default
std::size_t emplaceBack(Args &&... args)
Definition STObject.h:1003
STArray const & getFieldArray(SField const &field) const
Definition STObject.cpp:678
void setFieldArray(SField const &field, STArray const &v)
Definition STObject.cpp:823
V getFieldByValue(SField const &field) const
Definition STObject.h:1172
STObject & peekFieldObject(SField const &field)
Definition STObject.cpp:465
SOEStyle getStyle(SField const &field) const
Definition STObject.cpp:573
STBase & getField(SField const &field)
Definition STObject.cpp:410
std::vector< detail::STVar > list_type
Definition STObject.h:57
void setFieldAmount(SField const &field, STAmount const &)
Definition STObject.cpp:793
json::Value getJson(JsonOptions=JsonOptions::Values::None) const override
Definition STObject.cpp:835
void add(Serializer &s) const override
Definition STObject.cpp:120
Serializer getSerializer() const
Definition STObject.h:994
bool isFlag(std::uint32_t) const
Definition STObject.cpp:501
bool isFieldPresent(SField const &field) const
Definition STObject.cpp:454
STObject & operator=(STObject const &)=default
STObject(STObject const &)=default
int getCount() const
Definition STObject.h:1010
SerializedTypeID getSType() const override
Definition STObject.cpp:108
void setFieldU16(SField const &field, std::uint16_t)
Definition STObject.cpp:727
uint256 getFieldH256(SField const &field) const
Definition STObject.cpp:621
static STObject makeInnerObject(SField const &name)
Definition STObject.cpp:74
SOTemplate const * type_
Definition STObject.h:60
std::int32_t getFieldI32(SField const &field) const
Definition STObject.cpp:627
STBase const & peekAtField(SField const &field) const
Definition STObject.cpp:399
void set(SOTemplate const &)
Definition STObject.cpp:135
STObject(SOTemplate const &type, SField const &name, F &&f)
Definition STObject.h:69
uint256 getSigningHash(HashPrefix prefix) const
Definition STObject.cpp:374
bool clearFlag(std::uint32_t)
Definition STObject.cpp:489
void setFieldCurrency(SField const &field, STCurrency const &)
Definition STObject.cpp:799
std::uint64_t getFieldU64(SField const &field) const
Definition STObject.cpp:597
void setFieldPathSet(SField const &field, STPathSet const &)
Definition STObject.cpp:817
STBase * move(std::size_t n, void *buf) override
Definition STObject.cpp:102
static std::vector< STBase const * > getSortedFields(STObject const &objToSort, WhichFields whichFields)
Definition STObject.cpp:912
STBase * getPField(SField const &field, bool createOkay=false)
Definition STObject.cpp:438
STBase * makeFieldPresent(SField const &field)
Definition STObject.cpp:518
STBase const * peekAtPField(SField const &field) const
Definition STObject.cpp:427
void applyTemplateFromSField(SField const &)
Definition STObject.cpp:204
bool setFlag(std::uint32_t)
Definition STObject.cpp:477
void setFieldObject(SField const &field, STObject const &v)
Definition STObject.cpp:829
bool operator!=(STObject const &o) const
Definition STObject.h:1165
void setFieldH128(SField const &field, uint128 const &)
Definition STObject.cpp:745
STObject getFieldObject(SField const &field) const
Definition STObject.cpp:668
T & peekField(SField const &field)
Definition STObject.h:1269
void setFieldUsingSetValue(SField const &field, V value)
Definition STObject.h:1225
void setAccountID(SField const &field, AccountID const &)
Definition STObject.cpp:775
void setFieldUsingAssignment(SField const &field, T const &value)
Definition STObject.h:1248
bool delField(SField const &field)
Definition STObject.cpp:555
STBase & getIndex(int offset)
Definition STObject.h:1022
uint160 getFieldH160(SField const &field) const
Definition STObject.cpp:609
AccountID getAccountID(SField const &field) const
Definition STObject.cpp:633
STBase * getPIndex(int offset)
Definition STObject.h:1034
STVector256 const & getFieldV256(SField const &field) const
Definition STObject.cpp:661
STPathSet const & getFieldPathSet(SField const &field) const
Definition STObject.cpp:654
bool isDefault() const override
Definition STObject.cpp:114
void setFieldH160(SField const &field, BaseUInt< 160, Tag > const &v)
Definition STObject.h:1143
void makeFieldAbsent(SField const &field)
Definition STObject.cpp:540
bool hasMatchingEntry(STBase const &) const
Definition STObject.cpp:274
void setFieldH256(SField const &field, uint256 const &)
Definition STObject.cpp:757
boost::transform_iterator< Transform, STObject::list_type::const_iterator > iterator
Definition STObject.h:63
std::uint16_t getFieldU16(SField const &field) const
Definition STObject.cpp:585
STAmount const & getFieldAmount(SField const &field) const
Definition STObject.cpp:647
std::uint32_t getFlags() const
Definition STObject.cpp:507
STBase * copy(std::size_t n, void *buf) const override
Definition STObject.cpp:96
An immutable linear range of bytes.
Definition Slice.h:26
STBase & get()
Definition STVar.h:67
T forward(T... args)
T is_arithmetic_v
T is_class_v
T is_lvalue_reference_v
T is_same_v
STL namespace.
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:5
BaseUInt< 192 > uint192
Definition base_uint.h:563
void throwFieldNotFound(SField const &field)
Definition STObject.h:31
SOEStyle
Kind of element in each entry of an SOTemplate.
Definition SOTemplate.h:16
@ SoeDefault
Definition SOTemplate.h:20
@ SoeInvalid
Definition SOTemplate.h:17
@ SoeOptional
Definition SOTemplate.h:19
@ SoeRequired
Definition SOTemplate.h:18
BaseUInt< 128 > uint128
Definition base_uint.h:560
Number operator*(Number const &x, Number const &y)
Definition Number.h:744
BaseUInt< 160 > uint160
Definition base_uint.h:561
SerializedTypeID
Definition SField.h:93
BaseUInt< 160, detail::AccountIDTag > AccountID
A 160-bit unsigned that uniquely identifies an account.
Definition AccountID.h:28
HashPrefix
Prefix for hashing functions.
Definition HashPrefix.h:34
std::vector< unsigned char > Blob
Storage for linear binary data.
Definition Blob.h:10
BaseUInt< 256 > uint256
Definition base_uint.h:562
XRPL_NO_SANITIZE_ADDRESS void Throw(Args &&... args)
Definition contract.h:49
T runtime_error(T... args)
Note, should be treated as flags that can be | and &.
Definition STBase.h:17
Indicate std::optional field semantics.
Definition SField.h:314
TypedField< T > const * f
Definition SField.h:315
STBase const & operator()(detail::STVar const &e) const
Definition STObject.h:942
detail::STVar argument_type
Definition STObject.h:50
A field with a type known at compile time.
Definition SField.h:304