Param.hh
Go to the documentation of this file.
1 /*
2  * Copyright 2012 Open Source Robotics Foundation
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16 */
17 
18 #ifndef SDFORMAT_PARAM_HH_
19 #define SDFORMAT_PARAM_HH_
20 
21 #include <any>
22 #include <algorithm>
23 #include <cctype>
24 #include <cstdint>
25 #include <functional>
26 #include <iomanip>
27 #include <limits>
28 #include <memory>
29 #include <optional>
30 #include <sstream>
31 #include <string>
32 #include <typeinfo>
33 #include <variant>
34 #include <vector>
35 
36 #include <gz/math/Angle.hh>
37 #include <gz/math/Color.hh>
38 #include <gz/math/Pose3.hh>
39 #include <gz/math/Quaternion.hh>
40 #include <gz/math/Vector2.hh>
41 #include <gz/math/Vector3.hh>
42 
43 #include "sdf/Console.hh"
44 #include "sdf/PrintConfig.hh"
45 #include "sdf/sdf_config.h"
46 #include "sdf/system_util.hh"
47 #include "sdf/Types.hh"
48 
49 #ifdef _WIN32
50 // Disable warning C4251 which is triggered by
51 // std::unique_ptr
52 #pragma warning(push)
53 #pragma warning(disable: 4251)
54 #endif
55 
56 namespace sdf
57 {
58  // Inline bracket to help doxygen filtering.
59  inline namespace SDF_VERSION_NAMESPACE {
60  //
61 
63  using ElementPtr = std::shared_ptr<Element>;
64  using ElementWeakPtr = std::weak_ptr<Element>;
65 
67 
70  typedef std::shared_ptr<Param> ParamPtr;
71 
74  typedef std::vector<ParamPtr> Param_V;
75 
77  class ParamPrivate;
78 
79  template<class T>
81  {
82  const T &val;
83  const int precision; // Used to set std::ostream's std::setprecision
84  explicit ParamStreamer(const T &_val, int _precision = 0)
85  : val(_val), precision(_precision) {}
86  };
87 
88  // Template deduction guide for ParamVariant
89  template<typename ParamVariant>
90  ParamStreamer(const ParamVariant &_val, int _precision)
92 
93  template<class T>
94  std::ostream& operator<<(std::ostream &os, ParamStreamer<T> s)
95  {
96  if (s.precision == std::numeric_limits<int>::max())
97  {
98  if constexpr (std::is_same_v<T, double>
99  || std::is_same_v<T, gz::math::Angle>
100  || std::is_same_v<T, gz::math::Vector2d>
101  || std::is_same_v<T, gz::math::Vector3d>
102  || std::is_same_v<T, gz::math::Quaterniond>
103  || std::is_same_v<T, gz::math::Pose3d>)
104  {
105  os << std::setprecision(std::numeric_limits<double>::max_digits10);
106  }
107  else if constexpr (std::is_same_v<T, float>
108  || std::is_same_v<T, gz::math::Color>)
109  {
110  os << std::setprecision(std::numeric_limits<float>::max_digits10);
111  }
112  }
113  else
114  {
115  os << std::setprecision(s.precision);
116  }
117 
118  os << s.val;
119  return os;
120  }
121 
122  template<class... Ts>
123  std::ostream& operator<<(std::ostream& os,
124  ParamStreamer<std::variant<Ts...>> sv)
125  {
126  std::visit([&os, &sv](auto const &v)
127  {
128  os << ParamStreamer{v, sv.precision};
129  }, sv.val);
130  return os;
131  }
132 
136  {
145  public: Param(const std::string &_key, const std::string &_typeName,
146  const std::string &_default, bool _required,
147  const std::string &_description = "");
148 
157  public: Param(const std::string &_key, const std::string &_typeName,
158  const std::string &_default, bool _required,
159  sdf::Errors &_errors,
160  const std::string &_description = "");
161 
172  public: Param(const std::string &_key, const std::string &_typeName,
173  const std::string &_default, bool _required,
174  const std::string &_minValue, const std::string &_maxValue,
175  const std::string &_description = "");
176 
187  public: Param(const std::string &_key, const std::string &_typeName,
188  const std::string &_default, bool _required,
189  const std::string &_minValue, const std::string &_maxValue,
190  sdf::Errors &_errors,
191  const std::string &_description = "");
192 
196  public: Param(const Param &_param);
197 
200  public: Param(Param &&_param) noexcept = default;
201 
206  public: Param &operator=(const Param &_param);
207 
211  public: Param &operator=(Param &&_param) noexcept = default;
212 
214  public: virtual ~Param();
215 
219  public: std::string GetAsString(
220  const PrintConfig &_config = PrintConfig()) const;
221 
226  public: std::string GetAsString(
227  sdf::Errors &_errors,
228  const PrintConfig &_config = PrintConfig()) const;
229 
233  public: std::string GetDefaultAsString(
234  const PrintConfig &_config = PrintConfig()) const;
235 
240  public: std::string GetDefaultAsString(
241  sdf::Errors &_errors,
242  const PrintConfig &_config = PrintConfig()) const;
243 
249  public: std::optional<std::string> GetMinValueAsString(
250  const PrintConfig &_config = PrintConfig()) const;
251 
258  public: std::optional<std::string> GetMinValueAsString(
259  sdf::Errors &_errors,
260  const PrintConfig &_config = PrintConfig()) const;
261 
267  public: std::optional<std::string> GetMaxValueAsString(
268  const PrintConfig &_config = PrintConfig()) const;
269 
276  public: std::optional<std::string> GetMaxValueAsString(
277  sdf::Errors &_errors,
278  const PrintConfig &_config = PrintConfig()) const;
279 
285  public: bool SetFromString(const std::string &_value,
286  bool _ignoreParentAttributes);
287 
294  public: bool SetFromString(const std::string &_value,
295  bool _ignoreParentAttributes,
296  sdf::Errors &_errors);
297 
300  public: bool SetFromString(const std::string &_value);
301 
305  public: bool SetFromString(const std::string &_value,
306  sdf::Errors &_errors);
307 
311  public: ElementPtr GetParentElement() const;
312 
318  public: bool SetParentElement(ElementPtr _parentElement);
319 
326  public: bool SetParentElement(ElementPtr _parentElement,
327  sdf::Errors &_errors);
328 
330  public: void Reset();
331 
343  public: bool Reparse();
344 
357  public: bool Reparse(sdf::Errors &_errors);
358 
361  public: const std::string &GetKey() const;
362 
366  public: template<typename Type>
367  bool IsType() const;
368 
371  public: const std::string &GetTypeName() const;
372 
375  public: bool GetRequired() const;
376 
379  public: bool GetSet() const;
380 
385  public: bool IgnoresParentElementAttribute() const;
386 
389  public: ParamPtr Clone() const;
390 
394  public: template<typename T>
395  void SetUpdateFunc(T _updateFunc);
396 
399  public: void Update();
400 
404  public: void Update(sdf::Errors &_errors);
405 
411  public: template<typename T>
412  bool Set(const T &_value);
413 
420  public: template<typename T>
421  bool Set(const T &_value,
422  sdf::Errors &_errors);
423 
427  public: bool GetAny(std::any &_anyVal) const;
428 
433  public: bool GetAny(std::any &_anyVal, sdf::Errors &_errors) const;
434 
439  public: template<typename T>
440  bool Get(T &_value) const;
441 
447  public: template<typename T>
448  bool Get(T &_value,
449  sdf::Errors &_errors) const;
450 
455  public: template<typename T>
456  bool GetDefault(T &_value) const;
457 
463  public: template<typename T>
464  bool GetDefault(T &_value,
465  sdf::Errors &_errors) const;
466 
469  public: void SetDescription(const std::string &_desc);
470 
473  public: std::string GetDescription() const;
474 
477  public: bool ValidateValue() const;
478 
482  public: bool ValidateValue(sdf::Errors &_errors) const;
483 
488  public: friend std::ostream &operator<<(std::ostream &_out,
489  const Param &_p)
490  {
491  _out << _p.GetAsString();
492  return _out;
493  }
494 
496  private: std::unique_ptr<ParamPrivate> dataPtr;
497  };
498 
502  {
504  public: std::string key;
505 
507  public: bool required;
508 
510  public: bool set;
511 
513  public: std::string typeName;
514 
516  public: std::string description;
517 
520 
522  public: std::function<std::any ()> updateFunc;
523 
529  public: typedef std::variant<bool, char, std::string, int, std::uint64_t,
530  unsigned int, double, float, sdf::Time,
531  gz::math::Angle,
532  gz::math::Color,
533  gz::math::Vector2i,
534  gz::math::Vector2d,
535  gz::math::Vector3d,
536  gz::math::Quaterniond,
537  gz::math::Pose3d> ParamVariant;
538 
541 
546 
548  public: std::optional<std::string> strValue;
549 
551  public: std::string defaultStrValue;
552 
555 
557  public: std::optional<ParamVariant> minValue;
558 
560  public: std::optional<ParamVariant> maxValue;
561 
570  public: void Init(const std::string &_key, const std::string &_typeName,
571  const std::string &_default, bool _required,
572  sdf::Errors &_errors,
573  const std::string &_description);
574 
585  public: void Init(const std::string &_key, const std::string &_typeName,
586  const std::string &_default, bool _required,
587  const std::string &_minValue, const std::string &_maxValue,
588  sdf::Errors &_errors,
589  const std::string &_description);
590 
598  const std::string &_typeName,
599  const std::string &_valueStr,
600  ParamVariant &_valueToSet,
601  sdf::Errors &_errors) const;
602 
611  public: bool StringFromValueImpl(
612  const PrintConfig &_config,
613  const std::string &_typeName,
614  const ParamVariant &_value,
615  std::string &_valueStr,
616  sdf::Errors &_errors) const;
617 
620  public: template<typename T>
621  std::string TypeToString() const;
622  };
623 
625  template<typename T>
626  std::string ParamPrivate::TypeToString() const
627  {
628  // cppcheck-suppress syntaxError
629  if constexpr (std::is_same_v<T, bool>)
630  return "bool";
631  else if constexpr (std::is_same_v<T, char>)
632  return "char";
633  else if constexpr (std::is_same_v<T, std::string>)
634  return "string";
635  else if constexpr (std::is_same_v<T, int>)
636  return "int";
637  else if constexpr (std::is_same_v<T, std::uint64_t>)
638  return "uint64_t";
639  else if constexpr (std::is_same_v<T, unsigned int>)
640  return "unsigned int";
641  else if constexpr (std::is_same_v<T, double>)
642  return "double";
643  else if constexpr (std::is_same_v<T, float>)
644  return "float";
645  else if constexpr (std::is_same_v<T, sdf::Time>)
646  return "time";
647  else if constexpr (std::is_same_v<T, gz::math::Angle>)
648  return "angle";
649  else if constexpr (std::is_same_v<T, gz::math::Color>)
650  return "color";
651  else if constexpr (std::is_same_v<T, gz::math::Vector2i>)
652  return "vector2i";
653  else if constexpr (std::is_same_v<T, gz::math::Vector2d>)
654  return "vector2d";
655  else if constexpr (std::is_same_v<T, gz::math::Vector3d>)
656  return "vector3";
657  else if constexpr (std::is_same_v<T, gz::math::Quaterniond>)
658  return "quaternion";
659  else if constexpr (std::is_same_v<T, gz::math::Pose3d>)
660  return "pose";
661  else
662  return "";
663  }
664 
666  template<typename T>
667  void Param::SetUpdateFunc(T _updateFunc)
668  {
669  this->dataPtr->updateFunc = _updateFunc;
670  }
671 
673  template<typename T>
674  bool Param::Set(const T &_value)
675  {
676  sdf::Errors errors;
677  bool result = this->Set<T>(_value, errors);
678  if (!errors.empty())
679  sdferr << errors;
680  return result;
681  }
682 
684  template<typename T>
685  bool Param::Set(const T &_value, sdf::Errors &_errors)
686  {
687  try
688  {
689  std::stringstream ss;
690  ss << ParamStreamer<T>{_value, std::numeric_limits<int>::max()};
691  return this->SetFromString(ss.str(), true, _errors);
692  }
693  catch(...)
694  {
695  _errors.push_back({ErrorCode::PARAMETER_ERROR,
696  "Unable to set parameter["
697  + this->dataPtr->key + "]."
698  + "Type used must have a stream input and output operator,"
699  + "which allows proper functioning of Param."});
700  return false;
701  }
702  }
703 
705  template<typename T>
706  bool Param::Get(T &_value) const
707  {
708  sdf::Errors errors;
709  bool result = this->Get<T>(_value, errors);
710  if (!errors.empty())
711  sdferr << errors;
712  return result;
713  }
714 
716  template<typename T>
717  bool Param::Get(T &_value, sdf::Errors &_errors) const
718  {
719  T *value = std::get_if<T>(&this->dataPtr->value);
720  if (value)
721  {
722  _value = *value;
723  }
724  else
725  {
726  std::string typeStr = this->dataPtr->TypeToString<T>();
727  if (typeStr.empty())
728  {
729  _errors.push_back({ErrorCode::UNKNOWN_PARAMETER_TYPE,
730  "Unknown parameter type[" + std::string(typeid(T).name()) + "]"});
731  return false;
732  }
733 
734  std::string valueStr = this->GetAsString(_errors);
736  bool success = this->dataPtr->ValueFromStringImpl(
737  typeStr, valueStr, pv, _errors);
738 
739  if (success)
740  {
741  _value = std::get<T>(pv);
742  }
743  else if (typeStr == "bool" && this->dataPtr->typeName == "string")
744  {
745  // this section for handling bool types is to keep backward behavior
746  // TODO(anyone) remove for Fortress. For more details:
747  // https://github.com/gazebosim/sdformat/pull/638
748  valueStr = lowercase(valueStr);
749 
750  std::stringstream tmp;
751  if (valueStr == "true" || valueStr == "1")
752  tmp << "1";
753  else
754  tmp << "0";
755 
756  tmp >> _value;
757  return true;
758  }
759 
760  return success;
761  }
762 
763  return true;
764  }
765 
767  template<typename T>
768  bool Param::GetDefault(T &_value) const
769  {
770  sdf::Errors errors;
771  bool result = this>GetDefault<T>(_value, errors);
772  if (!errors.empty())
773  sdferr << errors;
774  return result;
775  }
776 
778  template<typename T>
779  bool Param::GetDefault(T &_value, sdf::Errors &_errors) const
780  {
781  std::stringstream ss;
782 
783  try
784  {
785  ss << ParamStreamer{this->dataPtr->defaultValue,
786  std::numeric_limits<int>::max()};
787  ss >> _value;
788  }
789  catch(...)
790  {
791  _errors.push_back({ErrorCode::PARAMETER_ERROR,
792  "Unable to convert parameter["
793  + this->dataPtr->key + "] "
794  + "whose type is["
795  + this->dataPtr->typeName + "], to "
796  + "type[" + typeid(T).name() + "]"});
797  return false;
798  }
799 
800  return true;
801  }
802 
804  template<typename Type>
805  bool Param::IsType() const
806  {
807  return std::holds_alternative<Type>(this->dataPtr->value);
808  }
809  }
810 }
811 
812 #ifdef _WIN32
813 #pragma warning(pop)
814 #endif
815 
816 #endif
sdf::SDF_VERSION_NAMESPACE::lowercase
std::string GZ_SDFORMAT_VISIBLE lowercase(const std::string &_in)
Transforms a string to its lowercase equivalent.
sdf::SDF_VERSION_NAMESPACE::ParamPrivate::ValueFromStringImpl
bool GZ_SDFORMAT_VISIBLE ValueFromStringImpl(const std::string &_typeName, const std::string &_valueStr, ParamVariant &_valueToSet, sdf::Errors &_errors) const
Method used to set the Param from a passed-in string.
sdf::SDF_VERSION_NAMESPACE::ParamPrivate::Init
void Init(const std::string &_key, const std::string &_typeName, const std::string &_default, bool _required, sdf::Errors &_errors, const std::string &_description)
Initializer function to help Param constructors.
sdf::SDF_VERSION_NAMESPACE::ParamPrivate::description
std::string description
Description of the parameter.
Definition: Param.hh:516
sdf::SDF_VERSION_NAMESPACE::ParamPrivate::required
bool required
True if the parameter is required.
Definition: Param.hh:507
sdf::SDF_VERSION_NAMESPACE::ParamPrivate
Definition: Param.hh:501
sdf
namespace for Simulation Description Format parser
Definition: Actor.hh:34
sdf::SDF_VERSION_NAMESPACE::ParamPrivate::typeName
std::string typeName
Definition: Param.hh:513
PrintConfig.hh
sdf::SDF_VERSION_NAMESPACE::ParamPrivate::value
ParamVariant value
This parameter's value.
Definition: Param.hh:540
sdf::SDF_VERSION_NAMESPACE::ParamStreamer
Definition: Param.hh:80
Console.hh
sdf::SDF_VERSION_NAMESPACE::Param
class GZ_SDFORMAT_VISIBLE Param
Definition: Param.hh:66
sdf::SDF_VERSION_NAMESPACE::ParamPrivate::strValue
std::optional< std::string > strValue
This parameter's value that was provided as a string.
Definition: Param.hh:548
sdf::SDF_VERSION_NAMESPACE::PrintConfig
This class contains configuration options for printing elements.
Definition: PrintConfig.hh:32
sdf::SDF_VERSION_NAMESPACE::ParamPrivate::updateFunc
std::function< std::any()> updateFunc
Update function pointer.
Definition: Param.hh:522
sdf::SDF_VERSION_NAMESPACE::Param
A parameter class.
Definition: Param.hh:135
sdf::SDF_VERSION_NAMESPACE::Param::GetDefault
bool GetDefault(T &_value) const
Get the default value of the parameter.
Definition: Param.hh:768
Types.hh
sdf::SDF_VERSION_NAMESPACE::ParamPrivate::parentElement
ElementWeakPtr parentElement
Parent element.
Definition: Param.hh:519
sdf::SDF_VERSION_NAMESPACE::ParamStreamer::precision
const int precision
Definition: Param.hh:83
sdf_config.h
sdf::SDF_VERSION_NAMESPACE::Time
A Time class, can be used to hold wall- or sim-time.
Definition: Types.hh:91
sdf::SDF_VERSION_NAMESPACE::ParamPrivate::defaultStrValue
std::string defaultStrValue
This parameter's default value that was provided as a string.
Definition: Param.hh:551
sdf::SDF_VERSION_NAMESPACE::ParamPtr
std::shared_ptr< Param > ParamPtr
Definition: Param.hh:70
sdf::SDF_VERSION_NAMESPACE::ParamPrivate::TypeToString
std::string TypeToString() const
Data type to string mapping.
Definition: Param.hh:626
SDFORMAT_VISIBLE
#define SDFORMAT_VISIBLE
Definition: system_util.hh:25
sdf::SDF_VERSION_NAMESPACE::ParamStreamer::ParamStreamer
ParamStreamer(const T &_val, int _precision=0)
Definition: Param.hh:84
sdf::SDF_VERSION_NAMESPACE::ParamStreamer::val
const T & val
Definition: Param.hh:82
sdf::SDF_VERSION_NAMESPACE::Param::IsType
bool IsType() const
Return true if the param is a particular type.
Definition: Param.hh:805
sdf::SDF_VERSION_NAMESPACE::ParamPrivate::minValue
std::optional< ParamVariant > minValue
This parameter's minimum allowed value.
Definition: Param.hh:557
sdf::SDF_VERSION_NAMESPACE::Param::SetUpdateFunc
void SetUpdateFunc(T _updateFunc)
Set the update function.
Definition: Param.hh:667
sdf::SDF_VERSION_NAMESPACE::ParamPrivate::ignoreParentAttributes
bool ignoreParentAttributes
True if the value has been parsed while ignoring its parent element's attributes, and will continue t...
Definition: Param.hh:545
sdf::SDF_VERSION_NAMESPACE::operator<<
std::ostream & operator<<(std::ostream &os, ParamStreamer< T > s)
Definition: Param.hh:94
sdf::SDF_VERSION_NAMESPACE::ErrorCode::PARAMETER_ERROR
@ PARAMETER_ERROR
Generic error type for parameters (values of SDFormat elements or attributes).
sdf::SDF_VERSION_NAMESPACE::ParamPrivate::StringFromValueImpl
bool StringFromValueImpl(const PrintConfig &_config, const std::string &_typeName, const ParamVariant &_value, std::string &_valueStr, sdf::Errors &_errors) const
Method used to get the string representation from a ParamVariant, or the string that was used to set ...
sdf::SDF_VERSION_NAMESPACE::ParamPrivate::key
std::string key
Key value.
Definition: Param.hh:504
sdf::SDF_VERSION_NAMESPACE::ParamStreamer
ParamStreamer(const ParamVariant &_val, int _precision) -> ParamStreamer< ParamVariant >
sdf::SDF_VERSION_NAMESPACE::ParamPrivate::defaultValue
ParamVariant defaultValue
This parameter's default value.
Definition: Param.hh:554
sdf::SDF_VERSION_NAMESPACE::Element
class GZ_SDFORMAT_VISIBLE Element
Definition: Element.hh:51
sdf::SDF_VERSION_NAMESPACE::Param::Get
bool Get(T &_value) const
Get the value of the parameter.
Definition: Param.hh:706
sdf::SDF_VERSION_NAMESPACE::Errors
std::vector< Error > Errors
A vector of Error.
Definition: Types.hh:80
sdf::SDF_VERSION_NAMESPACE::Param::operator<<
friend std::ostream & operator<<(std::ostream &_out, const Param &_p)
Ostream operator.
Definition: Param.hh:488
sdf::SDF_VERSION_NAMESPACE::Param::GetAsString
std::string GetAsString(const PrintConfig &_config=PrintConfig()) const
Get the value as a string.
sdf::SDF_VERSION_NAMESPACE::ElementWeakPtr
std::weak_ptr< Element > ElementWeakPtr
Definition: Element.hh:63
sdf::SDF_VERSION_NAMESPACE::Param::Set
bool Set(const T &_value)
Set the parameter's value.
Definition: Param.hh:674
system_util.hh
sdf::SDF_VERSION_NAMESPACE::ParamPrivate::ParamVariant
std::variant< bool, char, std::string, int, std::uint64_t, unsigned int, double, float, sdf::Time, gz::math::Angle, gz::math::Color, gz::math::Vector2i, gz::math::Vector2d, gz::math::Vector3d, gz::math::Quaterniond, gz::math::Pose3d > ParamVariant
Definition: Param.hh:537
sdferr
#define sdferr
Output an error message.
Definition: Console.hh:57
sdf::SDF_VERSION_NAMESPACE::ParamPrivate::set
bool set
True if the parameter is set.
Definition: Param.hh:510
sdf::SDF_VERSION_NAMESPACE::ElementPtr
std::shared_ptr< Element > ElementPtr
Definition: Element.hh:55
sdf::SDF_VERSION_NAMESPACE::ParamPrivate::maxValue
std::optional< ParamVariant > maxValue
This parameter's maximum allowed value.
Definition: Param.hh:560
sdf::SDF_VERSION_NAMESPACE::ErrorCode::UNKNOWN_PARAMETER_TYPE
@ UNKNOWN_PARAMETER_TYPE
The specified parameter (values of SDFormat elements or attributes) type is unknown.
sdf::SDF_VERSION_NAMESPACE::Param::SetFromString
bool SetFromString(const std::string &_value, bool _ignoreParentAttributes)
Set the parameter value from a string.
sdf::SDF_VERSION_NAMESPACE::Param_V
std::vector< ParamPtr > Param_V
Definition: Param.hh:74