OSSIA
Open Scenario System for Interactive Application
value.hpp
1 #pragma once
2 #include <ossia/detail/concepts.hpp>
4 #include <ossia/detail/string_view.hpp>
5 #include <ossia/network/common/parameter_properties.hpp>
6 #include <ossia/network/exceptions.hpp>
7 #include <ossia/network/value/value_base.hpp>
8 
9 #include <boost/container/flat_map.hpp>
10 
11 #include <limits>
12 #include <string>
13 #include <vector>
14 
15 namespace ossia
16 {
17 namespace detail
18 {
19 template <typename T>
20 struct dummy
21 {
22  using type = T;
23 };
24 }
25 
26 OSSIA_EXPORT std::string to_pretty_string(const ossia::destination_index& index);
27 
28 class value;
29 
41 OSSIA_EXPORT std::string value_to_pretty_string(const ossia::value& val);
42 OSSIA_EXPORT ossia::value parse_pretty_value(std::string_view str);
43 
44 using value_map_element = std::pair<std::string, ossia::value>;
45 struct value_map_type : std::vector<value_map_element>
46 {
47  using vector::vector;
48 
49  OSSIA_EXPORT
50  ossia::value& operator[](std::string_view str) noexcept;
51 };
52 
53 struct value_variant_type
54 {
55 public:
56  struct dummy_t
57  {
58  };
59  union Impl
60  {
61  float m_value0;
62 
63  int32_t m_value1;
64 
65  ossia::vec2f m_value2;
66 
67  ossia::vec3f m_value3;
68 
69  ossia::vec4f m_value4;
70 
71  ossia::impulse m_value5;
72 
73  bool m_value6;
74 
75  std::string m_value7;
76 
77  std::vector<ossia::value> m_value8;
78 
79  value_map_type m_value9;
80 
81  dummy_t m_dummy;
82  Impl()
83  : m_dummy{}
84  {
85  }
86  ~Impl() { }
87  };
88 
89  enum Type : int8_t
90  {
91  Type0,
92  Type1,
93  Type2,
94  Type3,
95  Type4,
96  Type5,
97  Type6,
98  Type7,
99  Type8,
100  Type9,
102  };
103 
104  void destruct_impl();
105  Impl m_impl;
106  Type m_type;
107 
108 public:
109  static const constexpr auto npos = Npos;
110  int which() const;
111 
112  operator bool() const;
113  template <typename T>
114  const T* target() const;
115  template <typename T>
116  T* target();
117  template <typename T>
118  const T& get() const;
119  template <typename T>
120  T& get();
121 
122  template <typename T>
123  static Type matching_type();
124 
125  value_variant_type();
126  ~value_variant_type();
127  value_variant_type(float v);
128  value_variant_type(int32_t v);
129  value_variant_type(ossia::vec2f v);
130  value_variant_type(ossia::vec3f v);
131  value_variant_type(ossia::vec4f v);
132  value_variant_type(ossia::impulse v);
133  value_variant_type(bool v);
134  value_variant_type(const std::string& v);
135  value_variant_type(std::string&& v);
136 
137  value_variant_type(const std::vector<ossia::value>& v);
138  value_variant_type(std::vector<ossia::value>&& v) noexcept;
139  value_variant_type(const value_map_type& v);
140  value_variant_type(value_map_type&& v);
141  value_variant_type(const value_variant_type& other);
142  value_variant_type(value_variant_type&& other) noexcept;
143  value_variant_type& operator=(const value_variant_type& other);
144  value_variant_type& operator=(value_variant_type&& other) noexcept;
145 };
146 using value_variant = value_variant_type;
147 
172 class OSSIA_EXPORT value
173 {
174 public:
175  using value_type = value_variant;
176 
177  value_type v;
178 
179  // Construction
180  template <typename T>
181  value(T*) = delete;
182  value(const char* txt)
183  : v{std::string(txt)}
184  {
185  }
186 
187  OSSIA_INLINE value(impulse val) noexcept
188  : v{val}
189  {
190  }
191 
192  OSSIA_INLINE value(bool val) noexcept
193  : v{val}
194  {
195  }
196  OSSIA_INLINE value(int val) noexcept
197  : v{(int32_t)val}
198  {
199  }
200  OSSIA_INLINE value(long val) noexcept
201  : v{(int32_t)val}
202  {
203  }
204  OSSIA_INLINE value(float val) noexcept
205  : v{val}
206  {
207  }
208  OSSIA_INLINE value(double val) noexcept
209  : v{(float)val}
210  {
211  }
212  OSSIA_INLINE value(const std::string& val) noexcept
213  : v{val}
214  {
215  }
216 
217  OSSIA_INLINE value(const std::vector<ossia::value>& val) noexcept
218  : v(val)
219  {
220  }
221 
222  OSSIA_INLINE value(const value_map_type& val) noexcept
223  : v(val)
224  {
225  }
226  OSSIA_INLINE value(std::array<float, 2> val) noexcept
227  : v(val)
228  {
229  }
230  OSSIA_INLINE value(std::array<float, 3> val) noexcept
231  : v(val)
232  {
233  }
234  OSSIA_INLINE value(std::array<float, 4> val) noexcept
235  : v(val)
236  {
237  }
238 
239  OSSIA_INLINE value(std::string&& val) noexcept
240  : v(std::move(val))
241  {
242  }
243  OSSIA_INLINE value(std::vector<ossia::value>&& val) noexcept
244  : v(std::move(val))
245  {
246  }
247 
248  OSSIA_INLINE value(value_map_type&& val) noexcept
249  : v(std::move(val))
250  {
251  }
252 
253  template <typename T, typename... Args>
254  OSSIA_INLINE value(detail::dummy<T> t, Args&&... args) noexcept
255  : v(T(std::forward<Args>(args)...))
256  {
257  }
258 
259  // To initialize a value directly with correct arguments
260  template <typename T, typename... Args>
261  OSSIA_INLINE static ossia::value make(Args&&... args) noexcept
262  {
263  return ossia::value{detail::dummy<T>{}, std::forward<Args>(args)...};
264  }
265 
266  // Assignment
267  OSSIA_INLINE value& operator=(ossia::impulse val) noexcept
268  {
269  v = val;
270  return *this;
271  }
272  OSSIA_INLINE value& operator=(const char* c) noexcept
273  {
274  v = std::string(c);
275  return *this;
276  }
277  OSSIA_INLINE value& operator=(bool val) noexcept
278  {
279  v = val;
280  return *this;
281  }
282  OSSIA_INLINE value& operator=(int32_t val) noexcept
283  {
284  v = val;
285  return *this;
286  }
287  OSSIA_INLINE value& operator=(float val) noexcept
288  {
289  v = val;
290  return *this;
291  }
292  OSSIA_INLINE value& operator=(const std::string& val) noexcept
293  {
294  v = val;
295  return *this;
296  }
297  OSSIA_INLINE value& operator=(const std::vector<ossia::value>& val) noexcept
298  {
299  v = val;
300  return *this;
301  }
302  OSSIA_INLINE value& operator=(const value_map_type& val) noexcept
303  {
304  v = val;
305  return *this;
306  }
307  OSSIA_INLINE value& operator=(std::array<float, 2> val) noexcept
308  {
309  v = val;
310  return *this;
311  }
312  OSSIA_INLINE value& operator=(std::array<float, 3> val) noexcept
313  {
314  v = val;
315  return *this;
316  }
317  OSSIA_INLINE value& operator=(std::array<float, 4> val) noexcept
318  {
319  v = val;
320  return *this;
321  }
322 
323  OSSIA_INLINE value& operator=(std::string&& val) noexcept
324  {
325  v = std::move(val);
326  return *this;
327  }
328  OSSIA_INLINE value& operator=(std::vector<ossia::value>&& val) noexcept
329  {
330  v = std::move(val);
331  return *this;
332  }
333  OSSIA_INLINE value& operator=(value_map_type&& val) noexcept
334  {
335  v = std::move(val);
336  return *this;
337  }
338 
339  OSSIA_INLINE value() noexcept { }
340  ~value() noexcept;
341  value(const value& other) noexcept
342  : v(other.v)
343  {
344  }
345  value(value&& other) noexcept
346  : v(std::move(other.v))
347  {
348  }
349  value& operator=(const value& other) noexcept
350  {
351  v = other.v;
352  return *this;
353  }
354  value& operator=(value&& other) noexcept
355  {
356  v = std::move(other.v);
357  return *this;
358  }
359 
360  operator value_type&() { return v; }
361  operator const value_type&() const { return v; }
362 
363  // Operations
364  template <typename T>
365  OSSIA_INLINE const T& get() const
366  {
367  return v.get<T>();
368  }
369 
370  template <typename T>
371  OSSIA_INLINE T& get()
372  {
373  return v.get<typename std::remove_const<T>::type>();
374  }
375 
376  template <typename T>
377  OSSIA_INLINE const T* target() const noexcept
378  {
379  using type = typename std::remove_const<T>::type;
380  static_assert(!std::is_same<type, ossia::value>::value, "");
381  return v.target<type>();
382  }
383 
384  template <typename T>
385  OSSIA_INLINE T* target() noexcept
386  {
387  using type = typename std::remove_const<T>::type;
388  static_assert(!std::is_same<type, ossia::value>::value, "");
389  return v.target<type>();
390  }
391 
392  OSSIA_INLINE ossia::val_type get_type() const noexcept
393  {
394  auto t = v.which();
395  if(t == v.npos)
396  {
397  return ossia::val_type::NONE;
398  }
399 
400  return static_cast<ossia::val_type>(t);
401  }
402 
403  bool valid() const noexcept { return bool(v); }
404 
405  void reset() noexcept { v = value_type{}; }
406 
407  template <typename Visitor>
408  auto apply(Visitor&& vis) -> decltype(auto);
409 
410  template <typename Visitor>
411  auto apply(Visitor&& vis) const -> decltype(auto);
412 
413  friend OSSIA_EXPORT bool operator==(const value& lhs, const value& rhs);
414  friend OSSIA_EXPORT bool operator!=(const value& lhs, const value& rhs);
415  friend OSSIA_EXPORT bool operator>(const value& lhs, const value& rhs);
416  friend OSSIA_EXPORT bool operator>=(const value& lhs, const value& rhs);
417  friend OSSIA_EXPORT bool operator<(const value& lhs, const value& rhs);
418  friend OSSIA_EXPORT bool operator<=(const value& lhs, const value& rhs);
419  /*
420  friend std::ostream& operator<<(std::ostream& os, const ossia::value& c)
421  {
422  // TODO OPTIMIZEME
423  return os << value_to_pretty_string(c);
424  }
425 
426  friend std::istream& operator>>(std::istream& is, const ossia::value& c)
427  {
428  // TODO
429  return is;
430  }
431  */
432 };
433 
434 inline ossia::value init_value(ossia::val_type type)
435 {
436  switch(type)
437  {
438  case val_type::IMPULSE:
439  return ossia::impulse{};
440  case val_type::BOOL:
441  return bool{};
442  case val_type::INT:
443  return int32_t{};
444  case val_type::FLOAT:
445  return float{};
446  case val_type::STRING:
447  return value{std::string{}}; // value needed for explicit ctor
448  case val_type::LIST:
449  return value{std::vector<ossia::value>{}};
450  case val_type::MAP:
451  return value{value_map_type{}};
452  case val_type::VEC2F:
453  return vec2f{};
454  case val_type::VEC3F:
455  return vec3f{};
456  case val_type::VEC4F:
457  return vec4f{};
458  case val_type::NONE:
459  default:
460  break;
461  }
462 
463  ossia_do_throw(invalid_value_type_error, "init_value: Invalid type");
464  return {};
465 }
466 
482 OSSIA_EXPORT
485 
486 #include <ossia/network/value/value_variant_impl.hpp>
487 
488 #if defined(OSSIA_HAS_CONCEPTS)
489 template <typename T>
490 concept ossia_visitor = requires(T t) {
491  t();
492  t(std::declval<float&>());
493  t(std::declval<int32_t&>());
494  t(std::declval<ossia::vec2f&>());
495  t(std::declval<ossia::vec3f&>());
496  t(std::declval<ossia::vec4f&>());
497  t(std::declval<ossia::impulse&>());
498  t(std::declval<bool&>());
499  t(std::declval<std::string&>());
500  t(std::declval<std::vector<ossia::value>&>());
501  t(std::declval<value_map_type&>());
502  };
503 #endif
504 
505 template <typename Visitor>
506 inline auto value::apply(Visitor&& vis) -> decltype(auto)
507 {
508 #if defined(OSSIA_HAS_CONCEPTS)
509  static_assert(ossia_visitor<Visitor>, "Not a valid ossia::value visitor");
510 #endif
511  return ossia::apply(std::forward<Visitor>(vis), this->v);
512 }
513 
514 template <typename Visitor>
515 inline auto value::apply(Visitor&& vis) const -> decltype(auto)
516 {
517 #if defined(OSSIA_HAS_CONCEPTS)
518  static_assert(ossia_visitor<Visitor>, "Not a valid ossia::value visitor");
519 #endif
520  return ossia::apply(std::forward<Visitor>(vis), this->v);
521 }
522 }
523 
524 namespace std
525 {
526 OSSIA_EXPORT std::ostream&
527 operator<<(std::ostream&, const std::vector<std::string>& list);
528 OSSIA_EXPORT std::istream& operator>>(std::istream&, std::vector<std::string>& list);
529 }
530 /*
531 extern template class std::vector<ossia::value>;
532 #if defined(OSSIA_USE_BOOST_OPTIONAL)
533 extern template class boost::optional<ossia::value>;
534 #elif defined(OSSIA_USE_STD_OPTIONAL)
535 extern template class std::optional<ossia::value>;
536 #elif defined(OSSIA_USE_STD_EXPERIMENTAL_OPTIONAL)
537 extern template class std::experimental::optional<ossia::value>;
538 #endif
539 */
The value class.
Definition: value.hpp:173
Definition: git_info.h:7
val_type
Enum to represent the types that a value can take.
Definition: parameter_properties.hpp:16
@ IMPULSE
array<float, 4>
@ VEC3F
array<float, 2>
@ LIST
std::string
@ VEC4F
array<float, 3>
@ MAP
std::vector<value>
@ BOOL
ossia::impulse
@ NONE
map<string, value>
OSSIA_EXPORT std::string value_to_pretty_string(const ossia::value &val)
getValueAsString Returns a string corresponding to the value
constexpr OSSIA_INLINE auto max(const T a, const U b) noexcept -> typename std::conditional<(sizeof(T) > sizeof(U)), T, U >::type
max function tailored for values
Definition: math.hpp:96
val_type matching_type(const unit_t &u)
underlying_type Get the implementation type of an unit
Definition: dataspace_visitors.cpp:198
ossia::small_vector< int32_t, 2 > destination_index
Definition: destination_index.hpp:40
std::string to_pretty_string(const value_with_unit &v)
to_pretty_string Pretty string of unit & value
Definition: dataspace_visitors.cpp:242
ossia::value get_value_at_index(const ossia::value &val, const ossia::destination_index &idx)
get_value_at_index
Definition: value.cpp:596