66#ifndef __UNIVALUE_H__
77#define __UNIVALUE_H__
88
9+ // Legacy code that uses UniValue typically makes countless copies of UniValue
10+ // objects. These copies are often unnecessary and costly. To help with
11+ // converting legacy code into more efficient std::move friendly code, enable
12+ // NO_UNIVALUE_COPY_OPERATIONS. This will disable all UniValue methods that
13+ // cause copying of elements, causing compile errors. Each of these compile
14+ // errors can then be fixed with e.g. std::move(), or if a copy is still
15+ // necessary by explicitly calling the .copy() method. Unfortunately it cannot
16+ // detect all cases, as a copy constructor is still necessary for collections.
17+ //
18+ // You can disable copy operations here globally, or in individual files by
19+ // setting it before the first univalue.h include.
20+ //
21+ // #define NO_UNIVALUE_COPY_OPERATIONS
22+
923#include < stdint.h>
1024#include < string.h>
1125
@@ -18,11 +32,32 @@ class UniValue {
1832public:
1933 enum VType { VNULL, VOBJ, VARR, VSTR, VNUM, VBOOL, };
2034
21- UniValue () { typ = VNULL; }
22- UniValue (UniValue::VType initialType, const std::string& initialStr = " " ) {
23- typ = initialType;
24- val = initialStr;
35+ UniValue () = default ;
36+
37+ #if defined(NO_UNIVALUE_COPY_OPERATIONS)
38+ // explicit copy constructor and deleted copy assignment forces the use of .copy() in most cases.
39+ explicit UniValue (const UniValue&) = default;
40+ UniValue& operator =(const UniValue&) = delete ;
41+ #else
42+ UniValue (const UniValue&) = default;
43+ UniValue& operator =(const UniValue&) = default ;
44+ #endif
45+
46+ UniValue (UniValue&&) = default ;
47+ UniValue& operator =(UniValue&&) = default ;
48+ ~UniValue () = default ;
49+
50+ // adds an explicit copy() operation that also works even when NO_UNIVALUE_COPY_OPERATIONS is defined.
51+ UniValue copy () const {
52+ return UniValue{*this };
2553 }
54+
55+ UniValue (UniValue::VType initialType) : typ(initialType) {}
56+ UniValue (UniValue::VType initialType, const std::string& initialStr) : typ(initialType), val(initialStr) {}
57+ UniValue (UniValue::VType initialType, std::string&& initialStr) : typ(initialType), val(std::move(initialStr)) {}
58+ UniValue (const std::string& val_) : typ(VSTR), val(val_) {}
59+ UniValue (std::string&& val_) : typ(VSTR), val(std::move(val_)) {}
60+ UniValue (const char *val_) : typ(VSTR), val(val_) {}
2661 UniValue (uint64_t val_) {
2762 setInt (val_);
2863 }
@@ -38,24 +73,19 @@ class UniValue {
3873 UniValue (double val_) {
3974 setFloat (val_);
4075 }
41- UniValue (const std::string& val_) {
42- setStr (val_);
43- }
44- UniValue (const char *val_) {
45- std::string s (val_);
46- setStr (s);
47- }
4876
4977 void clear ();
5078
5179 bool setNull ();
5280 bool setBool (bool val);
5381 bool setNumStr (const std::string& val);
82+ bool setNumStr (std::string&& val);
5483 bool setInt (uint64_t val);
5584 bool setInt (int64_t val);
5685 bool setInt (int val_) { return setInt ((int64_t )val_); }
5786 bool setFloat (double val);
5887 bool setStr (const std::string& val);
88+ bool setStr (std::string&& val);
5989 bool setArray ();
6090 bool setObject ();
6191
@@ -81,68 +111,56 @@ class UniValue {
81111 bool isArray () const { return (typ == VARR); }
82112 bool isObject () const { return (typ == VOBJ); }
83113
114+ #if !defined(NO_UNIVALUE_COPY_OPERATIONS)
84115 bool push_back (const UniValue& val);
85- bool push_back (const std::string& val_) {
86- UniValue tmpVal (VSTR, val_);
87- return push_back (tmpVal);
88- }
89- bool push_back (const char *val_) {
90- std::string s (val_);
91- return push_back (s);
92- }
93- bool push_back (uint64_t val_) {
94- UniValue tmpVal (val_);
95- return push_back (tmpVal);
96- }
97- bool push_back (int64_t val_) {
98- UniValue tmpVal (val_);
99- return push_back (tmpVal);
100- }
101- bool push_back (bool val_) {
102- UniValue tmpVal (val_);
103- return push_back (tmpVal);
104- }
105- bool push_back (int val_) {
106- UniValue tmpVal (val_);
107- return push_back (tmpVal);
108- }
109- bool push_back (double val_) {
110- UniValue tmpVal (val_);
111- return push_back (tmpVal);
112- }
116+ #endif
117+ bool push_back (UniValue&& val);
118+ bool push_back (const std::string& val_);
119+ bool push_back (std::string&& val_);
120+ bool push_back (const char *val_);
121+ bool push_back (uint64_t val_);
122+ bool push_back (int64_t val_);
123+ bool push_back (bool val_);
124+ bool push_back (int val_);
125+ bool push_back (double val_);
126+ #if !defined(NO_UNIVALUE_COPY_OPERATIONS)
113127 bool push_backV (const std::vector<UniValue>& vec);
128+ #endif
129+ bool push_backV (std::vector<UniValue>&& vec);
114130
131+ #if !defined(NO_UNIVALUE_COPY_OPERATIONS)
115132 void __pushKV (const std::string& key, const UniValue& val);
133+ void __pushKV (std::string&& key, const UniValue& val);
134+ #endif
135+ void __pushKV (const std::string& key, UniValue&& val);
136+ void __pushKV (std::string&& key, UniValue&& val);
137+
138+ #if !defined(NO_UNIVALUE_COPY_OPERATIONS)
116139 bool pushKV (const std::string& key, const UniValue& val);
117- bool pushKV (const std::string& key, const std::string& val_) {
118- UniValue tmpVal (VSTR, val_);
119- return pushKV (key, tmpVal);
120- }
121- bool pushKV (const std::string& key, const char *val_) {
122- std::string _val (val_);
123- return pushKV (key, _val);
124- }
125- bool pushKV (const std::string& key, int64_t val_) {
126- UniValue tmpVal (val_);
127- return pushKV (key, tmpVal);
128- }
129- bool pushKV (const std::string& key, uint64_t val_) {
130- UniValue tmpVal (val_);
131- return pushKV (key, tmpVal);
132- }
133- bool pushKV (const std::string& key, bool val_) {
134- UniValue tmpVal (val_);
135- return pushKV (key, tmpVal);
136- }
137- bool pushKV (const std::string& key, int val_) {
138- UniValue tmpVal ((int64_t )val_);
139- return pushKV (key, tmpVal);
140- }
141- bool pushKV (const std::string& key, double val_) {
142- UniValue tmpVal (val_);
143- return pushKV (key, tmpVal);
144- }
140+ bool pushKV (std::string&& key, const UniValue& val);
141+ #endif
142+ bool pushKV (const std::string& key, UniValue&& val);
143+ bool pushKV (std::string&& key, UniValue&& val);
144+ bool pushKV (const std::string& key, const std::string& val);
145+ bool pushKV (std::string&& key, const std::string& val);
146+ bool pushKV (const std::string& key, std::string&& val);
147+ bool pushKV (std::string&& key, std::string&& val);
148+ bool pushKV (const std::string& key, const char *val);
149+ bool pushKV (std::string&& key, const char *val);
150+ bool pushKV (const std::string& key, int64_t val);
151+ bool pushKV (std::string&& key, int64_t val);
152+ bool pushKV (const std::string& key, uint64_t val);
153+ bool pushKV (std::string&& key, uint64_t val);
154+ bool pushKV (const std::string& key, bool val);
155+ bool pushKV (std::string&& key, bool val);
156+ bool pushKV (const std::string& key, int val);
157+ bool pushKV (std::string&& key, int val);
158+ bool pushKV (const std::string& key, double val);
159+ bool pushKV (std::string&& key, double val);
160+ #if !defined(NO_UNIVALUE_COPY_OPERATIONS)
145161 bool pushKVs (const UniValue& obj);
162+ #endif
163+ bool pushKVs (UniValue&& obj);
146164
147165 std::string write (unsigned int prettyIndent = 0 ,
148166 unsigned int indentLevel = 0 ) const ;
@@ -154,7 +172,13 @@ class UniValue {
154172 }
155173
156174private:
157- UniValue::VType typ;
175+ template <typename V>
176+ bool pushBackGeneric (V&& val_);
177+
178+ template <typename K, typename V>
179+ bool pushKVGeneric (K&& key, V&& val_);
180+
181+ UniValue::VType typ{VNULL};
158182 std::string val; // numbers are stored as C++ strings
159183 std::vector<std::string> keys;
160184 std::vector<UniValue> values;
0 commit comments