ledger-core
DynamicValue.hpp
1 /*
2  *
3  * DynamicValue
4  * ledger-core
5  *
6  * Created by Pierre Pollastri on 08/03/2017.
7  *
8  * The MIT License (MIT)
9  *
10  * Copyright (c) 2016 Ledger
11  *
12  * Permission is hereby granted, free of charge, to any person obtaining a copy
13  * of this software and associated documentation files (the "Software"), to deal
14  * in the Software without restriction, including without limitation the rights
15  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
16  * copies of the Software, and to permit persons to whom the Software is
17  * furnished to do so, subject to the following conditions:
18  *
19  * The above copyright notice and this permission notice shall be included in all
20  * copies or substantial portions of the Software.
21  *
22  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
25  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
28  * SOFTWARE.
29  *
30  */
31 
32 #ifndef LEDGER_CORE_DYNAMICVALUE_HPP
33 #define LEDGER_CORE_DYNAMICVALUE_HPP
34 
35 #include "../api/DynamicType.hpp"
36 #include <boost/variant.hpp>
37 #include <cereal/cereal.hpp>
38 #include <cereal/archives/portable_binary.hpp>
39 #include <cereal/archives/binary.hpp>
40 #include <vector>
41 #include <utils/optional.hpp>
42 
43 namespace ledger {
44  namespace core {
45  class DynamicArray;
46  class DynamicObject;
47 
48  struct DynamicValue {
49  // Mandatory default constructor for it to be default-constructible in (e.g.) maps.
50  explicit DynamicValue() = default;
51  explicit DynamicValue(const DynamicValue& rhs);
52  explicit DynamicValue(const char* x);
53  explicit DynamicValue(const std::string& x);
54  explicit DynamicValue(const std::vector<uint8_t>& x);
55  explicit DynamicValue(bool x);
56  explicit DynamicValue(int32_t x);
57  explicit DynamicValue(int64_t x);
58  explicit DynamicValue(double x);
59  explicit DynamicValue(const std::shared_ptr<DynamicArray>& x);
60  explicit DynamicValue(const std::shared_ptr<DynamicObject>& x);
61 
62  template <class Archive>
63  void serialize(Archive& ar) {
64  }
65 
66  std::string dump() const;
67  std::ostream& dump(std::ostream& ss, int depth) const;
68 
70  api::DynamicType getType() const;
71 
73  DynamicValue& operator=(const std::string& rhs);
75  DynamicValue& operator=(std::string&& rhs);
76 
78  DynamicValue& operator=(const std::vector<uint8_t>& rhs);
80  DynamicValue& operator=(std::vector<uint8_t>&& rhs);
81 
83  DynamicValue& operator=(bool rhs);
84 
86  DynamicValue& operator=(int32_t rhs);
87 
89  DynamicValue& operator=(int64_t rhs);
90 
92  DynamicValue& operator=(double rhs);
93 
95  DynamicValue& operator=(const std::shared_ptr<DynamicArray>& rhs);
96 
98  DynamicValue& operator=(const std::shared_ptr<DynamicObject>& rhs);
99 
101  template <typename T>
102  optional<T> get() const {
103  static const OptionalVisitor<T> visitor;
104  return boost::apply_visitor(visitor, data);
105  }
106 
107  private:
108  // Data. We cannot use a union because of C++ restrictions on non-trivial ctors and
109  // dtors. SFOL
110  boost::variant<int32_t, int64_t, bool, double, std::string, std::vector<uint8_t>,
111  std::shared_ptr<DynamicArray>, std::shared_ptr<DynamicObject>> data;
112 
113  // A visitor used to cast from DynamicValue to typed optional values.
114  template <typename T>
115  struct OptionalVisitor: boost::static_visitor<optional<T>> {
116  optional<T> operator()(T x) const {
117  return x;
118  }
119 
120  template <typename Q>
121  optional<T> operator()(const Q&) const {
122  return optional<T>();
123  }
124  };
125 
126  // A helper function to serialize.
127  template <typename Archive>
128  void out_serialize(Archive& ar) {
129  auto type = getType();
130  ar(type);
131 
132  switch (type) {
133  case api::DynamicType::STRING:
134  ar(boost::get<std::string>(data));
135  break;
136 
138  ar(boost::get<std::vector<uint8_t>>(data));
139  break;
140 
142  ar(boost::get<bool>(data));
143  break;
144 
146  ar(boost::get<int32_t>(data));
147  break;
148 
150  ar(boost::get<int64_t>(data));
151  break;
152 
153  case api::DynamicType::DOUBLE:
154  ar(boost::get<double>(data));
155  break;
156 
158  ar(boost::get<std::shared_ptr<DynamicArray>>(data));
159  break;
160 
162  ar(boost::get<std::shared_ptr<DynamicObject>>(data));
163  break;
164 
166  break;
167  }
168  }
169 
170  // A helper function to deserialize.
171  template <typename Archive>
172  void in_serialize(Archive& ar) {
173  auto type = api::DynamicType::UNDEFINED;
174  ar(type);
175 
176  switch (type) {
177  case api::DynamicType::STRING:
178  {
179  std::string x;
180  ar(x);
181  data = x;
182  }
183  break;
184 
186  {
187  std::vector<uint8_t> x;
188  ar(x);
189  data = x;
190  }
191  break;
192 
194  {
195  bool x;
196  ar(x);
197  data = x;
198  }
199  break;
200 
202  {
203  int32_t x;
204  ar(x);
205  data = x;
206  }
207  break;
208 
210  {
211  int64_t x;
212  ar(x);
213  data = x;
214  }
215  break;
216 
217  case api::DynamicType::DOUBLE:
218  {
219  double x;
220  ar(x);
221  data = x;
222  }
223  break;
224 
226  {
227  std::shared_ptr<DynamicArray> x;
228  ar(x);
229  data = x;
230  }
231  break;
232 
234  {
235  std::shared_ptr<DynamicObject> x;
236  ar(x);
237  data = x;
238  }
239  break;
240 
242  break;
243  }
244  }
245  };
246 
247  template<> void DynamicValue::serialize<cereal::PortableBinaryOutputArchive>(cereal::PortableBinaryOutputArchive&);
248  template<> void DynamicValue::serialize<cereal::PortableBinaryInputArchive>(cereal::PortableBinaryInputArchive&);
249  template<> void DynamicValue::serialize<cereal::BinaryOutputArchive>(cereal::BinaryOutputArchive&);
250  template<> void DynamicValue::serialize<cereal::BinaryInputArchive>(cereal::BinaryInputArchive&);
251  }
252 }
253 
254 #endif //LEDGER_CORE_DYNAMICVALUE_HPP
api::DynamicType getType() const
Get the underlying type.
Definition: DynamicValue.cpp:168
Definition: DynamicValue.hpp:48
DynamicType
Definition: DynamicType.hpp:20
Definition: Account.cpp:8
DynamicValue & operator=(const std::string &rhs)
Change the value to a std::string by copying.
Definition: DynamicValue.cpp:207
Definition: optional.hpp:177