Serialbox  2.2.0
Data serialization library and tools for C/C++, Python and Fortran
MetainfoValueImpl.cpp
Go to the documentation of this file.
1 //===-- serialbox/core/MetainfoValueImpl.cpp ----------------------------------------*- C++ -*-===//
2 //
3 // S E R I A L B O X
4 //
5 // This file is distributed under terms of BSD license.
6 // See LICENSE.txt for more information
7 //
8 //===------------------------------------------------------------------------------------------===//
9 //
13 //===------------------------------------------------------------------------------------------===//
14 
17 #include <sstream>
18 
19 #include <iostream>
20 
21 namespace serialbox {
22 
23 namespace internal {
24 
26 template <class T>
27 const T& convert(const boost::any& any) noexcept {
28  return *boost::any_cast<T>(&any);
29 }
30 
32 template <class T, class StringType>
33 T fromString(StringType&& valueStr) {
34  std::stringstream ss;
35  ss << valueStr;
36  T value;
37  ss >> value;
38  return value;
39 }
40 
42 template <class T>
43 T makePrimitiveOf(const boost::any& any, TypeID type);
44 
45 template <>
46 bool makePrimitiveOf<bool>(const boost::any& any, TypeID type) {
47  switch(type) {
48  case TypeID::Boolean:
49  return convert<bool>(any);
50  case TypeID::Int32:
51  return (bool)convert<int>(any);
52  case TypeID::Int64:
53  return (bool)convert<std::int64_t>(any);
54  case TypeID::Float32:
55  return (bool)convert<float>(any);
56  case TypeID::Float64:
57  return (bool)convert<double>(any);
58  case TypeID::String:
59  return internal::fromString<bool>(convert<std::string>(any));
60  default:
61  throw Exception("cannot convert [type = %s] to [T = bool]", TypeUtil::toString(type));
62  }
63  serialbox_unreachable("Invalid TypeID");
64 }
65 
66 template <>
67 int makePrimitiveOf<int>(const boost::any& any, TypeID type) {
68  switch(type) {
69  case TypeID::Boolean:
70  return (int)convert<bool>(any);
71  case TypeID::Int32:
72  return convert<int>(any);
73  case TypeID::Int64:
74  return (int)convert<std::int64_t>(any);
75  case TypeID::Float32: {
76  if((float)static_cast<int>(convert<float>(any)) != convert<float>(any))
77  throw Exception("conversion of [type = %s] to [T = %s] results in truncation of the value",
78  TypeUtil::toString(type), TypeUtil::toString(ToTypeID<int>::value));
79  return (int)convert<float>(any);
80  }
81  case TypeID::Float64: {
82  if((double)static_cast<int>(convert<double>(any)) != convert<double>(any))
83  throw Exception("conversion of [type = %s] to [T = %s] results in truncation of the value",
84  TypeUtil::toString(type), TypeUtil::toString(ToTypeID<int>::value));
85  return (int)convert<double>(any);
86  }
87  case TypeID::String:
88  return internal::fromString<int>(convert<std::string>(any));
89  default:
90  throw Exception("cannot convert [type = %s] to [T = int]", TypeUtil::toString(type));
91  }
92  serialbox_unreachable("Invalid TypeID");
93 }
94 
95 template <>
96 std::int64_t makePrimitiveOf<std::int64_t>(const boost::any& any, TypeID type) {
97  switch(type) {
98  case TypeID::Boolean:
99  return (std::int64_t)convert<bool>(any);
100  case TypeID::Int32:
101  return (std::int64_t)convert<int>(any);
102  case TypeID::Int64:
103  return convert<std::int64_t>(any);
104  case TypeID::Float32: {
105  if((float)static_cast<std::int64_t>(convert<float>(any)) != convert<float>(any))
106  throw Exception("conversion of [type = %s] to [T = %s] results in truncation of the value",
107  TypeUtil::toString(type), TypeUtil::toString(ToTypeID<std::int64_t>::value));
108  return (std::int64_t)convert<float>(any);
109  }
110  case TypeID::Float64: {
111  if((double)static_cast<std::int64_t>(convert<double>(any)) != convert<double>(any))
112  throw Exception("conversion of [type = %s] to [T = %s] results in truncation of the value",
113  TypeUtil::toString(type), TypeUtil::toString(ToTypeID<std::int64_t>::value));
114  return (std::int64_t)convert<double>(any);
115  }
116  case TypeID::String:
117  return internal::fromString<std::int64_t>(convert<std::string>(any));
118  default:
119  throw Exception("cannot convert [type = %s] to [T = std::int64_t]", TypeUtil::toString(type));
120  }
121  serialbox_unreachable("Invalid TypeID");
122 }
123 
124 template <>
125 float makePrimitiveOf<float>(const boost::any& any, TypeID type) {
126  switch(type) {
127  case TypeID::Boolean:
128  return (float)convert<bool>(any);
129  case TypeID::Int32:
130  return (float)convert<int>(any);
131  case TypeID::Int64:
132  return (float)convert<std::int64_t>(any);
133  case TypeID::Float32:
134  return convert<float>(any);
135  case TypeID::Float64:
136  return (float)convert<double>(any);
137  case TypeID::String:
138  return internal::fromString<float>(convert<std::string>(any));
139  default:
140  throw Exception("cannot convert [type = %s] to [T = float]", TypeUtil::toString(type));
141  }
142  serialbox_unreachable("Invalid TypeID");
143 }
144 
145 template <>
146 double makePrimitiveOf<double>(const boost::any& any, TypeID type) {
147  switch(type) {
148  case TypeID::Boolean:
149  return (double)convert<bool>(any);
150  case TypeID::Int32:
151  return (double)convert<int>(any);
152  case TypeID::Int64:
153  return (double)convert<std::int64_t>(any);
154  case TypeID::Float32:
155  return (double)convert<float>(any);
156  case TypeID::Float64:
157  return convert<double>(any);
158  case TypeID::String:
159  return internal::fromString<double>(convert<std::string>(any));
160  default:
161  throw Exception("cannot convert [type = %s] to [T = double]", TypeUtil::toString(type));
162  }
163  serialbox_unreachable("Invalid TypeID");
164 }
165 
166 template <>
167 std::string makePrimitiveOf<std::string>(const boost::any& any, TypeID type) {
168  switch(type) {
169  case TypeID::Boolean:
170  return (convert<bool>(any) ? "true" : "false");
171  case TypeID::Int32:
172  return std::to_string(convert<int>(any));
173  case TypeID::Int64:
174  return std::to_string(convert<std::int64_t>(any));
175  case TypeID::Float32:
176  return std::to_string(convert<float>(any));
177  case TypeID::Float64:
178  return std::to_string(convert<double>(any));
179  case TypeID::String:
180  return convert<std::string>(any);
181  default:
182  throw Exception("cannot convert [type = %s] to [T = std::string]", TypeUtil::toString(type));
183  }
184  serialbox_unreachable("Invalid TypeID");
185 }
186 
188 template <class T, class ArrayType = Array<T>>
189 ArrayType makeArrayOf(const boost::any& any, TypeID type) {
190  if(!TypeUtil::isArray(type))
191  throw Exception("cannot convert non-array [type = %s] to array [T = %s]",
192  TypeUtil::toString(type), TypeUtil::toString(ToTypeID<ArrayType>::value));
193 
194  ArrayType arrayT;
195 
196  switch(TypeUtil::getPrimitive(type)) {
197  case TypeID::Boolean: {
198  const auto& array = convert<Array<bool>>(any);
199  for(const auto& a : array)
200  arrayT.push_back(makePrimitiveOf<T>(boost::any(bool(a)), TypeID::Boolean));
201  break;
202  }
203  case TypeID::Int32: {
204  const auto& array = convert<Array<int>>(any);
205  for(const auto& a : array)
206  arrayT.push_back(makePrimitiveOf<T>(boost::any(int(a)), TypeID::Int32));
207  break;
208  }
209  case TypeID::Int64: {
210  const auto& array = convert<Array<std::int64_t>>(any);
211  for(const auto& a : array)
212  arrayT.push_back(makePrimitiveOf<T>(boost::any(std::int64_t(a)), TypeID::Int64));
213  break;
214  }
215  case TypeID::Float32: {
216  const auto& array = convert<Array<float>>(any);
217  for(const auto& a : array)
218  arrayT.push_back(makePrimitiveOf<T>(boost::any(float(a)), TypeID::Float32));
219  break;
220  }
221  case TypeID::Float64: {
222  const auto& array = convert<Array<double>>(any);
223  for(const auto& a : array)
224  arrayT.push_back(makePrimitiveOf<T>(boost::any(double(a)), TypeID::Float64));
225  break;
226  }
227  case TypeID::String: {
228  const auto& array = convert<Array<std::string>>(any);
229  for(const auto& a : array)
230  arrayT.push_back(makePrimitiveOf<T>(boost::any(std::string(a)), TypeID::String));
231  break;
232  }
233  default:
234  serialbox_unreachable("Invalid TypeID");
235  }
236 
237  return arrayT;
238 }
239 
240 } // namespace internal
241 
242 bool MetainfoValueImpl::operator==(const MetainfoValueImpl& right) const noexcept {
243  if(type_ != right.type_)
244  return false;
245 
246  switch(type_) {
247 
248  // Primitive
249  case TypeID::Boolean:
250  return (convert<bool>() == right.convert<bool>());
251  case TypeID::Int32:
252  return (convert<int>() == right.convert<int>());
253  case TypeID::Int64:
254  return (convert<std::int64_t>() == right.convert<std::int64_t>());
255  case TypeID::Float32:
256  return (convert<float>() == right.convert<float>());
257  case TypeID::Float64:
258  return (convert<double>() == right.convert<double>());
259  case TypeID::String:
260  return (convert<std::string>() == right.convert<std::string>());
261 
262  // Array
263  case TypeID::ArrayOfBoolean:
264  return (convert<Array<bool>>() == right.convert<Array<bool>>());
265  case TypeID::ArrayOfInt32:
266  return (convert<Array<int>>() == right.convert<Array<int>>());
267  case TypeID::ArrayOfInt64:
268  return (convert<Array<std::int64_t>>() == right.convert<Array<std::int64_t>>());
269  case TypeID::ArrayOfFloat32:
270  return (convert<Array<float>>() == right.convert<Array<float>>());
271  case TypeID::ArrayOfFloat64:
272  return (convert<Array<double>>() == right.convert<Array<double>>());
273  case TypeID::ArrayOfString:
274  return (convert<Array<std::string>>() == right.convert<Array<std::string>>());
275 
276  default:
277  serialbox_unreachable("Invalid TypeID");
278  }
279 }
280 
281 std::string MetainfoValueImpl::toString() const { return as<std::string>(); }
282 
283 template <>
284 bool MetainfoValueImpl::as() const {
285  return internal::makePrimitiveOf<bool>(any_, type_);
286 }
287 
288 template <>
289 int MetainfoValueImpl::as() const {
290  return internal::makePrimitiveOf<int>(any_, type_);
291 }
292 
293 template <>
294 std::int64_t MetainfoValueImpl::as() const {
295  return internal::makePrimitiveOf<std::int64_t>(any_, type_);
296 }
297 
298 template <>
299 float MetainfoValueImpl::as() const {
300  return internal::makePrimitiveOf<float>(any_, type_);
301 }
302 
303 template <>
304 double MetainfoValueImpl::as() const {
305  return internal::makePrimitiveOf<double>(any_, type_);
306 }
307 
308 template <>
309 std::string MetainfoValueImpl::as() const {
310  return internal::makePrimitiveOf<std::string>(any_, type_);
311 }
312 
313 template <>
315  return internal::makeArrayOf<bool>(any_, type_);
316 }
317 
318 template <>
320  return internal::makeArrayOf<int>(any_, type_);
321 }
322 
323 template <>
325  return internal::makeArrayOf<std::int64_t>(any_, type_);
326 }
327 
328 template <>
330  return internal::makeArrayOf<float>(any_, type_);
331 }
332 
333 template <>
335  return internal::makeArrayOf<double>(any_, type_);
336 }
337 
338 template <>
340  return internal::makeArrayOf<std::string>(any_, type_);
341 }
342 
343 } // namespace serialbox
std::string toString() const
Convert to string.
bool operator==(const MetainfoValueImpl &right) const noexcept
Test for equality.
Represent an immutable meta information value as a type-id and type-erased data.
static bool isArray(TypeID id) noexcept
Check if type is an array of types.
Definition: Type.cpp:91
std::vector< T > Array
Array class used by serialbox to store meta-information.
Definition: Array.h:31
Namespace of the serialbox library.
Definition: Archive.h:25
TypeID
Type-id of types recognized by serialbox.
Definition: Type.h:55
static std::string toString(TypeID id)
Convert to string.
Definition: Type.cpp:35
static TypeID getPrimitive(TypeID id) noexcept
Return the underlying primitve type.
Definition: Type.cpp:93
T as() const
Convert the value to type T
#define serialbox_unreachable(msg)
Marks that the current location is not supposed to be reachable.
Definition: Unreachable.h:41