13 #include <SpaceVecAlg/SpaceVecAlg>
16 #include <spdlog/fmt/fmt.h>
25 #include <string_view>
26 #include <unordered_set>
32 #if defined(__GNUC__) && !defined(__llvm__) && !defined(__INTEL_COMPILER)
33 # if __GNUC__ > 8 || (__GNUC__ == 8 && __GNUC_MINOR__ > 2)
34 # define MC_RTC_USE_VARIANT_WORKAROUND 0
36 # define MC_RTC_USE_VARIANT_WORKAROUND 1
39 # define MC_RTC_USE_VARIANT_WORKAROUND 0
59 static void save(
const T &) {}
78 typename std::enable_if<
81 static std::true_type
test(T * p);
84 static std::false_type
test(...);
89 decltype(_has_configuration_load_object::test<T>(
nullptr))::value;
98 typename = std::enable_if_t<
99 std::is_same_v<decltype(T::fromConfiguration(std::declval<const Configuration &>())), T>>>
100 static std::true_type
test(T * p);
103 static std::false_type
test(...);
117 typename std::enable_if<
121 static std::true_type
test(T * p);
123 template<
typename T,
typename... Args>
124 static std::false_type
test(...);
127 template<
typename T,
typename... Args>
129 decltype(_has_configuration_save_object::test<T, Args...>(
nullptr))::value;
140 typename = std::enable_if_t<
141 std::is_same_v<decltype(std::declval<const T &>().toConfiguration(std::declval<Args>()...)),
Configuration>>>
142 static std::true_type
test(T * p);
144 template<
typename T,
typename... Args>
145 static std::false_type
test(...);
148 template<
typename T,
typename... Args>
150 decltype(_has_toConfiguration_method::test<T, Args...>(
nullptr))::value;
152 #if MC_RTC_USE_VARIANT_WORKAROUND
154 template<
size_t IDX,
typename... Args>
155 std::variant<Args...> to_variant(
const Configuration & c,
size_t idx);
176 bool isArray()
const noexcept;
178 size_t size()
const noexcept;
183 Json operator[](
size_t idx)
const;
185 bool isObject()
const noexcept;
187 std::vector<std::string> keys()
const noexcept;
192 Json operator[](
const std::string & key)
const;
194 std::optional<Json> find(
const std::string & key)
const;
196 bool isString()
const noexcept;
198 bool isNumeric()
const noexcept;
203 double asDouble()
const;
208 void path(std::string & out)
const noexcept;
212 std::shared_ptr<void> doc_;
231 Exception(
const std::string & msg,
const Json & v);
244 virtual const
char * what() const noexcept override;
247 void silence() const noexcept;
250 const
std::
string & msg() const noexcept;
253 mutable
std::
string msg_;
263 MC_RTC_DEPRECATED
bool isMember(const
std::
string & key) const;
271 bool has(const
std::
string & key) const;
277 operator
bool() const;
285 operator int8_t() const;
294 operator uint8_t() const;
302 operator int16_t() const;
311 operator uint16_t() const;
319 operator int32_t() const;
328 operator uint32_t() const;
336 operator int64_t() const;
345 operator uint64_t() const;
353 operator
double() const;
365 operator
std::
string() const;
372 operator Eigen::Vector2d() const;
379 operator Eigen::Vector3d() const;
386 operator Eigen::Vector4d() const;
393 operator Eigen::Vector6d() const;
421 operator Eigen::VectorXd() const;
430 operator Eigen::Quaterniond() const;
437 operator Eigen::Matrix3d() const;
443 operator Eigen::Matrix6d() const;
449 operator Eigen::MatrixXd() const;
455 operator sva::PTransformd() const;
461 operator sva::ForceVecd() const;
467 operator sva::MotionVecd() const;
473 operator sva::ImpedanceVecd() const;
481 template<class T, class A>
482 operator
std::vector<T, A>()
const
486 std::vector<T, A> ret;
487 for(
size_t i = 0; i < v.size(); ++i) { ret.push_back(
Configuration(v[i])); }
499 template<
class T, std::
size_t N>
500 operator std::array<T, N>()
const
502 if(v.isArray() && v.size() == N)
504 std::array<T, N> ret;
505 for(
size_t i = 0; i < N; ++i) { ret[i] =
Configuration(v[i]); }
516 template<
class T1,
class T2>
517 operator std::pair<T1, T2>()
const
528 template<
typename T,
class C,
class A>
529 operator std::map<std::string, T, C, A>()
const
533 std::map<std::string, T, C, A> ret;
534 auto keys = v.keys();
535 assert(std::set<std::string>(keys.begin(), keys.end()).size() == keys.size());
536 for(
const auto & k : keys)
552 template<
typename T,
typename C = std::less<T>,
typename A = std::allocator<T>>
553 operator std::set<T, C, A>()
const
557 std::set<T, C, A> ret;
558 for(
size_t i = 0; i < v.size(); ++i)
574 template<
typename T,
typename H = std::hash<T>,
typename E = std::equal_to<T>,
typename A = std::allocator<T>>
575 operator std::unordered_set<T, H, E, A>()
const
579 std::unordered_set<T, H, E, A> ret;
580 for(
size_t i = 0; i < v.size(); ++i)
599 template<
typename... Args>
600 operator std::variant<Args...>()
const
606 #if MC_RTC_USE_VARIANT_WORKAROUND
607 return internal::to_variant<0, Args...>(v[1], idx);
609 static constexpr
auto table =
610 std::array{+[](
const Configuration & c) {
return std::variant<Args...>{c.operator Args()}; }...};
611 return table[idx](v[1]);
619 template<
typename T,
typename std::enable_if<
internal::is_
integral_v<T>,
int>::type = 0>
622 if constexpr(internal::is_like_int8_t<T>) {
return static_cast<T
>(this->
operator int8_t()); }
623 else if constexpr(internal::is_like_int16_t<T>) {
return static_cast<T
>(this->
operator int16_t()); }
624 else if constexpr(internal::is_like_int32_t<T>) {
return static_cast<T
>(this->
operator int32_t()); }
625 else if constexpr(internal::is_like_int64_t<T>) {
return static_cast<T
>(this->
operator int64_t()); }
626 else if constexpr(internal::is_like_uint8_t<T>) {
return static_cast<T
>(this->
operator uint8_t()); }
627 else if constexpr(internal::is_like_uint16_t<T>) {
return static_cast<T
>(this->
operator uint16_t()); }
628 else if constexpr(internal::is_like_uint32_t<T>) {
return static_cast<T
>(this->
operator uint32_t()); }
629 else if constexpr(internal::is_like_uint64_t<T>) {
return static_cast<T
>(this->
operator uint64_t()); }
630 else { static_assert(!std::is_same_v<T, T>,
"T is integral but has an unsupported size"); }
639 typename std::enable_if<internal::has_configuration_load_object_v<T>
640 || internal::has_static_fromConfiguration_v<T>,
645 else {
return T::fromConfiguration(*
this); }
653 explicit operator std::optional<T>()
const
657 return this->convert<T>();
724 static Configuration fromMessagePack(
const char * data,
size_t size);
735 void load(
const std::string & path);
757 void loadData(
const std::string & data);
766 void loadYAMLData(
const std::string & data);
777 void save(
const std::string & path,
bool pretty =
true)
const;
786 std::string dump(
bool pretty =
false,
bool yaml =
false)
const;
795 size_t toMessagePack(std::vector<char> & data)
const;
824 std::optional<Configuration> find(
const std::string & key)
const;
836 template<
typename... Args>
837 std::optional<Configuration>
find(
const std::string & key, Args &&... others)
const
839 auto out = find(key);
840 return out ? out->find(std::forward<Args>(others)...) : std::nullopt;
853 template<
typename T,
typename... Args>
854 std::optional<T>
find(
const std::string & key, Args &&... others)
const
856 auto maybe_cfg = find(key, std::forward<Args>(others)...);
857 if(maybe_cfg) {
return maybe_cfg->operator T(); }
873 inline bool isArray() const noexcept {
return v.isArray(); }
876 inline bool isObject() const noexcept {
return v.isObject(); }
879 inline bool isString() const noexcept {
return v.isString(); }
882 inline bool isNumeric() const noexcept {
return v.isNumeric(); }
902 T
at(
size_t i,
const T & v)
const
906 return (*
this)[i].convert<T>();
932 v = (*this)(key).convert<T>();
955 return (*
this)(key).convert<T>();
988 void add_null(
const std::string & key);
998 void add(
const std::string & key,
bool value);
1004 void add(
const std::string & key, int8_t value);
1010 void add(
const std::string & key, uint8_t value);
1016 void add(
const std::string & key, int16_t value);
1022 void add(
const std::string & key, uint16_t value);
1028 void add(
const std::string & key, int32_t value);
1034 void add(
const std::string & key, uint32_t value);
1040 void add(
const std::string & key, int64_t value);
1046 void add(
const std::string & key, uint64_t value);
1052 void add(
const std::string & key,
double value);
1058 void add(
const std::string & key,
const std::string & value);
1065 void add(
const std::string & key,
const char * value);
1071 void add(
const std::string & key,
const Eigen::Vector2d & value);
1077 void add(
const std::string & key,
const Eigen::Vector3d & value);
1083 void add(
const std::string & key,
const Eigen::Vector4d & value);
1089 void add(
const std::string & key,
const Eigen::Vector6d & value);
1095 void add(
const std::string & key,
const Eigen::VectorXd & value);
1101 void add(
const std::string & key,
const Eigen::Quaterniond & value);
1107 void add(
const std::string & key,
const Eigen::Matrix3d & value);
1113 void add(
const std::string & key,
const Eigen::Matrix6d & value);
1119 void add(
const std::string & key,
const Eigen::MatrixXd & value);
1125 void add(
const std::string & key,
const sva::PTransformd & value);
1131 void add(
const std::string & key,
const sva::ForceVecd & value);
1137 void add(
const std::string & key,
const sva::MotionVecd & value);
1143 void add(
const std::string & key,
const sva::ImpedanceVecd & value);
1149 void add(
const std::string & key,
const Configuration & value);
1167 Configuration array(
const std::string & key,
size_t size = 0);
1181 void push(
bool value);
1187 void push(int8_t value);
1193 void push(uint8_t value);
1199 void push(int16_t value);
1205 void push(uint16_t value);
1211 void push(int32_t value);
1217 void push(uint32_t value);
1223 void push(int64_t value);
1229 void push(uint64_t value);
1235 void push(
double value);
1241 void push(
const std::string & value);
1247 void push(
const char * value);
1253 void push(
const Eigen::Vector2d & value);
1259 void push(
const Eigen::Vector3d & value);
1265 void push(
const Eigen::Vector4d & value);
1271 void push(
const Eigen::Vector6d & value);
1277 void push(
const Eigen::VectorXd & value);
1283 void push(
const Eigen::Quaterniond & value);
1289 void push(
const Eigen::Matrix3d & value);
1295 void push(
const Eigen::Matrix6d & value);
1301 void push(
const Eigen::MatrixXd & value);
1307 void push(
const sva::PTransformd & value);
1313 void push(
const sva::ForceVecd & value);
1319 void push(
const sva::MotionVecd & value);
1325 void push(
const sva::ImpedanceVecd & value);
1352 template<
typename T,
1357 void push(
const T & value, Args &&... args)
1359 if constexpr(internal::has_configuration_save_object_v<T, Args...>)
1363 else { push(value.toConfiguration(std::forward<Args>(args)...)); }
1370 template<
typename T,
typename std::enable_if<
internal::is_
integral_v<T>,
int>::type = 0>
1373 if constexpr(internal::is_like_int8_t<T>) { push(
static_cast<int8_t
>(value)); }
1374 else if constexpr(internal::is_like_int16_t<T>) { push(
static_cast<int16_t
>(value)); }
1375 else if constexpr(internal::is_like_int32_t<T>) { push(
static_cast<int32_t
>(value)); }
1376 else if constexpr(internal::is_like_int64_t<T>) { push(
static_cast<int64_t
>(value)); }
1377 else if constexpr(internal::is_like_uint8_t<T>) { push(
static_cast<uint8_t
>(value)); }
1378 else if constexpr(internal::is_like_uint16_t<T>) { push(
static_cast<uint16_t
>(value)); }
1379 else if constexpr(internal::is_like_uint32_t<T>) { push(
static_cast<uint32_t
>(value)); }
1380 else if constexpr(internal::is_like_uint64_t<T>) { push(
static_cast<uint64_t
>(value)); }
1381 else { static_assert(!std::is_same_v<T, T>,
"T is integral but has an unsupported size"); }
1392 template<
typename T,
typename A = std::allocator<T>,
typename... Args>
1393 void add(
const std::string & key,
const std::vector<T, A> & value, Args &&... args)
1396 for(
const auto & vi : value) { v.
push(vi, std::forward<Args>(args)...); }
1407 template<
typename T, std::size_t N,
typename... Args>
1408 void add(
const std::string & key,
const std::array<T, N> & value, Args &&... args)
1411 for(
const auto & vi : value) { v.
push(vi, std::forward<Args>(args)...); }
1422 template<
typename T1,
typename T2,
typename... Args>
1423 void add(
const std::string & key,
const std::pair<T1, T2> & value, Args &&... args)
1426 v.
push(value.first, std::forward<Args>(args)...);
1427 v.
push(value.second, std::forward<Args>(args)...);
1438 template<
typename T,
1439 class C = std::less<std::string>,
1440 class A = std::allocator<std::pair<const std::string, T>>,
1442 void add(
const std::string & key,
const std::map<std::string, T, C, A> & value, Args &&... args)
1445 for(
const auto & el : value) { v.
add(el.first, el.second, std::forward<Args>(args)...); }
1456 template<
typename T,
typename C = std::less<T>,
typename A = std::allocator<T>,
typename... Args>
1457 void add(
const std::string & key,
const std::set<T, C, A> & value, Args &&... args)
1460 for(
const auto & v : value) { v.
push(*v, std::forward<Args>(args)...); }
1471 template<
typename T,
1472 typename H = std::hash<T>,
1473 typename E = std::equal_to<T>,
1474 typename A = std::allocator<T>,
1476 void add(
const std::string & key,
const std::unordered_set<T, H, E, A> & value, Args &&... args)
1479 for(
const auto & v : value) { v.
push(*v, std::forward<Args>(args)...); }
1492 template<
typename... Args>
1493 void add(
const std::string & key,
const std::variant<Args...> & value)
1496 v.
push(value.index());
1497 std::visit([&v](
const auto & hold) { v.
push(hold); }, value);
1506 template<
typename T,
typename std::enable_if<
internal::is_
integral_v<T>,
int>::type = 0>
1507 void add(
const std::string & key,
const T & value)
1509 if constexpr(internal::is_like_int8_t<T>) { add(key,
static_cast<int8_t
>(value)); }
1510 else if constexpr(internal::is_like_int16_t<T>) { add(key,
static_cast<int16_t
>(value)); }
1511 else if constexpr(internal::is_like_int32_t<T>) { add(key,
static_cast<int32_t
>(value)); }
1512 else if constexpr(internal::is_like_int64_t<T>) { add(key,
static_cast<int64_t
>(value)); }
1513 else if constexpr(internal::is_like_uint8_t<T>) { add(key,
static_cast<uint8_t
>(value)); }
1514 else if constexpr(internal::is_like_uint16_t<T>) { add(key,
static_cast<uint16_t
>(value)); }
1515 else if constexpr(internal::is_like_uint32_t<T>) { add(key,
static_cast<uint32_t
>(value)); }
1516 else if constexpr(internal::is_like_uint64_t<T>) { add(key,
static_cast<uint64_t
>(value)); }
1517 else { static_assert(!std::is_same_v<T, T>,
"T is integral but has an unsupported size"); }
1529 template<
typename T,
1534 void add(
const std::string & key,
const T & value, Args &&... args)
1536 if constexpr(internal::has_configuration_save_object_v<T, Args...>)
1540 else { add(key, value.toConfiguration(std::forward<Args>(args)...)); }
1547 template<
typename T,
typename A = std::allocator<T>,
typename... Args>
1548 void push(
const std::vector<T, A> & value, Args &&... args)
1551 for(
const auto & vi : value) { v.
push(vi, std::forward<Args>(args)...); }
1558 template<
typename T, std::size_t N,
typename... Args>
1559 void push(
const std::array<T, N> & value, Args &&... args)
1562 for(
const auto & vi : value) { v.
push(vi, std::forward<Args>(args)...); }
1569 template<
typename T1,
typename T2,
typename... Args>
1570 void push(
const std::pair<T1, T2> & value, Args &&... args)
1573 v.
push(value.first, std::forward<Args>(args)...);
1574 v.
push(value.second, std::forward<Args>(args)...);
1581 template<
typename T,
1582 class C = std::less<std::string>,
1583 class A = std::allocator<std::pair<const std::string, T>>,
1585 void push(
const std::map<std::string, T, C, A> & value, Args &&... args)
1588 for(
const auto & el : value) { v.
add(el.first, el.second, std::forward<Args>(args)...); }
1599 template<
typename T,
typename C = std::less<T>,
typename A = std::allocator<T>,
typename... Args>
1600 void push(
const std::set<T, C, A> & value, Args &&... args)
1603 for(
const auto & v : value) { v.
push(*v, std::forward<Args>(args)...); }
1614 template<
typename T,
1615 typename H = std::hash<T>,
1616 typename E = std::equal_to<T>,
1617 typename A = std::allocator<T>,
1619 void push(
const std::unordered_set<T, H, E, A> & value, Args &&... args)
1622 for(
const auto & v : value) { v.
push(*v, std::forward<Args>(args)...); }
1635 template<
typename... Args>
1636 void push(
const std::variant<Args...> & value)
1639 v.
push(value.index());
1640 std::visit([&v](
const auto & hold) { v.
push(hold); }, value);
1652 bool remove(
const std::string & key);
1658 std::vector<std::string> keys()
const;
1668 template<
typename T>
1671 if constexpr(std::is_same_v<T, Configuration>) {
return *
this; }
1672 else {
return this->
operator T(); }
1724 inline const std::string &
path() const noexcept {
return path_; }
1730 #if MC_RTC_USE_VARIANT_WORKAROUND
1734 template<
size_t IDX,
typename... Args>
1735 std::variant<Args...> to_variant(
const Configuration & c,
size_t idx)
1741 if(idx == IDX) {
return c.operator std::variant_alternative_t<IDX, std::variant<Args...>>(); }
1742 else {
return to_variant<IDX + 1, Args...>(c, idx); }
1760 template<
typename FormatContext>
1763 return formatter<string_view>::format(
static_cast<std::string
>(c), ctx);