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<class T>
89  std::ostream& operator<<(std::ostream &os, ParamStreamer<T> s)
90  {
91  if (s.precision == std::numeric_limits<int>::max())
92  {
93  if constexpr (std::is_same_v<T, double>
94  || std::is_same_v<T, gz::math::Angle>
95  || std::is_same_v<T, gz::math::Vector2d>
96  || std::is_same_v<T, gz::math::Vector3d>
97  || std::is_same_v<T, gz::math::Quaterniond>
98  || std::is_same_v<T, gz::math::Pose3d>)
99  {
100  os << std::setprecision(std::numeric_limits<double>::max_digits10);
101  }
102  else if constexpr (std::is_same_v<T, float>
103  || std::is_same_v<T, gz::math::Color>)
104  {
105  os << std::setprecision(std::numeric_limits<float>::max_digits10);
106  }
107  }
108  else
109  {
110  os << std::setprecision(s.precision);
111  }
112 
113  os << s.val;
114  return os;
115  }
116 
117  template<class... Ts>
118  std::ostream& operator<<(std::ostream& os,
119  ParamStreamer<std::variant<Ts...>> sv)
120  {
121  std::visit([&os, &sv](auto const &v)
122  {
123  os << ParamStreamer{v, sv.precision};
124  }, sv.val);
125  return os;
126  }
127 
131  {
140  public: Param(const std::string &_key, const std::string &_typeName,
141  const std::string &_default, bool _required,
142  const std::string &_description = "");
143 
152  public: Param(const std::string &_key, const std::string &_typeName,
153  const std::string &_default, bool _required,
154  sdf::Errors &_errors,
155  const std::string &_description = "");
156 
167  public: Param(const std::string &_key, const std::string &_typeName,
168  const std::string &_default, bool _required,
169  const std::string &_minValue, const std::string &_maxValue,
170  const std::string &_description = "");
171 
182  public: Param(const std::string &_key, const std::string &_typeName,
183  const std::string &_default, bool _required,
184  const std::string &_minValue, const std::string &_maxValue,
185  sdf::Errors &_errors,
186  const std::string &_description = "");
187 
191  public: Param(const Param &_param);
192 
195  public: Param(Param &&_param) noexcept = default;
196 
201  public: Param &operator=(const Param &_param);
202 
206  public: Param &operator=(Param &&_param) noexcept = default;
207 
209  public: virtual ~Param();
210 
214  public: std::string GetAsString(
215  const PrintConfig &_config = PrintConfig()) const;
216 
221  public: std::string GetAsString(
222  sdf::Errors &_errors,
223  const PrintConfig &_config = PrintConfig()) const;
224 
228  public: std::string GetDefaultAsString(
229  const PrintConfig &_config = PrintConfig()) const;
230 
235  public: std::string GetDefaultAsString(
236  sdf::Errors &_errors,
237  const PrintConfig &_config = PrintConfig()) const;
238 
244  public: std::optional<std::string> GetMinValueAsString(
245  const PrintConfig &_config = PrintConfig()) const;
246 
253  public: std::optional<std::string> GetMinValueAsString(
254  sdf::Errors &_errors,
255  const PrintConfig &_config = PrintConfig()) const;
256 
262  public: std::optional<std::string> GetMaxValueAsString(
263  const PrintConfig &_config = PrintConfig()) const;
264 
271  public: std::optional<std::string> GetMaxValueAsString(
272  sdf::Errors &_errors,
273  const PrintConfig &_config = PrintConfig()) const;
274 
280  public: bool SetFromString(const std::string &_value,
281  bool _ignoreParentAttributes);
282 
289  public: bool SetFromString(const std::string &_value,
290  bool _ignoreParentAttributes,
291  sdf::Errors &_errors);
292 
295  public: bool SetFromString(const std::string &_value);
296 
300  public: bool SetFromString(const std::string &_value,
301  sdf::Errors &_errors);
302 
306  public: ElementPtr GetParentElement() const;
307 
313  public: bool SetParentElement(ElementPtr _parentElement);
314 
321  public: bool SetParentElement(ElementPtr _parentElement,
322  sdf::Errors &_errors);
323 
325  public: void Reset();
326 
338  public: bool Reparse();
339 
352  public: bool Reparse(sdf::Errors &_errors);
353 
356  public: const std::string &GetKey() const;
357 
361  public: template<typename Type>
362  bool IsType() const;
363 
366  public: const std::string &GetTypeName() const;
367 
370  public: bool GetRequired() const;
371 
374  public: bool GetSet() const;
375 
380  public: bool IgnoresParentElementAttribute() const;
381 
384  public: ParamPtr Clone() const;
385 
389  public: template<typename T>
390  void SetUpdateFunc(T _updateFunc);
391 
394  public: void Update();
395 
399  public: void Update(sdf::Errors &_errors);
400 
406  public: template<typename T>
407  bool Set(const T &_value);
408 
415  public: template<typename T>
416  bool Set(const T &_value,
417  sdf::Errors &_errors);
418 
422  public: bool GetAny(std::any &_anyVal) const;
423 
428  public: bool GetAny(std::any &_anyVal, sdf::Errors &_errors) const;
429 
434  public: template<typename T>
435  bool Get(T &_value) const;
436 
442  public: template<typename T>
443  bool Get(T &_value,
444  sdf::Errors &_errors) const;
445 
450  public: template<typename T>
451  bool GetDefault(T &_value) const;
452 
458  public: template<typename T>
459  bool GetDefault(T &_value,
460  sdf::Errors &_errors) const;
461 
464  public: void SetDescription(const std::string &_desc);
465 
468  public: std::string GetDescription() const;
469 
472  public: bool ValidateValue() const;
473 
477  public: bool ValidateValue(sdf::Errors &_errors) const;
478 
483  public: friend std::ostream &operator<<(std::ostream &_out,
484  const Param &_p)
485  {
486  _out << _p.GetAsString();
487  return _out;
488  }
489 
491  private: std::unique_ptr<ParamPrivate> dataPtr;
492  };
493 
497  {
499  public: std::string key;
500 
502  public: bool required;
503 
505  public: bool set;
506 
508  public: std::string typeName;
509 
511  public: std::string description;
512 
515 
517  public: std::function<std::any ()> updateFunc;
518 
524  public: typedef std::variant<bool, char, std::string, int, std::uint64_t,
525  unsigned int, double, float, sdf::Time,
526  gz::math::Angle,
527  gz::math::Color,
528  gz::math::Vector2i,
529  gz::math::Vector2d,
530  gz::math::Vector3d,
531  gz::math::Quaterniond,
532  gz::math::Pose3d> ParamVariant;
533 
536 
541 
543  public: std::optional<std::string> strValue;
544 
546  public: std::string defaultStrValue;
547 
550 
552  public: std::optional<ParamVariant> minValue;
553 
555  public: std::optional<ParamVariant> maxValue;
556 
565  public: void Init(const std::string &_key, const std::string &_typeName,
566  const std::string &_default, bool _required,
567  sdf::Errors &_errors,
568  const std::string &_description);
569 
580  public: void Init(const std::string &_key, const std::string &_typeName,
581  const std::string &_default, bool _required,
582  const std::string &_minValue, const std::string &_maxValue,
583  sdf::Errors &_errors,
584  const std::string &_description);
585 
593  const std::string &_typeName,
594  const std::string &_valueStr,
595  ParamVariant &_valueToSet,
596  sdf::Errors &_errors) const;
597 
606  public: bool StringFromValueImpl(
607  const PrintConfig &_config,
608  const std::string &_typeName,
609  const ParamVariant &_value,
610  std::string &_valueStr,
611  sdf::Errors &_errors) const;
612 
615  public: template<typename T>
616  std::string TypeToString() const;
617  };
618 
620  template<typename T>
621  std::string ParamPrivate::TypeToString() const
622  {
623  // cppcheck-suppress syntaxError
624  if constexpr (std::is_same_v<T, bool>)
625  return "bool";
626  else if constexpr (std::is_same_v<T, char>)
627  return "char";
628  else if constexpr (std::is_same_v<T, std::string>)
629  return "string";
630  else if constexpr (std::is_same_v<T, int>)
631  return "int";
632  else if constexpr (std::is_same_v<T, std::uint64_t>)
633  return "uint64_t";
634  else if constexpr (std::is_same_v<T, unsigned int>)
635  return "unsigned int";
636  else if constexpr (std::is_same_v<T, double>)
637  return "double";
638  else if constexpr (std::is_same_v<T, float>)
639  return "float";
640  else if constexpr (std::is_same_v<T, sdf::Time>)
641  return "time";
642  else if constexpr (std::is_same_v<T, gz::math::Angle>)
643  return "angle";
644  else if constexpr (std::is_same_v<T, gz::math::Color>)
645  return "color";
646  else if constexpr (std::is_same_v<T, gz::math::Vector2i>)
647  return "vector2i";
648  else if constexpr (std::is_same_v<T, gz::math::Vector2d>)
649  return "vector2d";
650  else if constexpr (std::is_same_v<T, gz::math::Vector3d>)
651  return "vector3";
652  else if constexpr (std::is_same_v<T, gz::math::Quaterniond>)
653  return "quaternion";
654  else if constexpr (std::is_same_v<T, gz::math::Pose3d>)
655  return "pose";
656  else
657  return "";
658  }
659 
661  template<typename T>
662  void Param::SetUpdateFunc(T _updateFunc)
663  {
664  this->dataPtr->updateFunc = _updateFunc;
665  }
666 
668  template<typename T>
669  bool Param::Set(const T &_value)
670  {
671  sdf::Errors errors;
672  bool result = this->Set<T>(_value, errors);
673  if (!errors.empty())
674  sdferr << errors;
675  return result;
676  }
677 
679  template<typename T>
680  bool Param::Set(const T &_value, sdf::Errors &_errors)
681  {
682  try
683  {
684  std::stringstream ss;
685  ss << _value;
686  return this->SetFromString(ss.str(), true, _errors);
687  }
688  catch(...)
689  {
690  _errors.push_back({ErrorCode::PARAMETER_ERROR,
691  "Unable to set parameter["
692  + this->dataPtr->key + "]."
693  + "Type used must have a stream input and output operator,"
694  + "which allows proper functioning of Param."});
695  return false;
696  }
697  }
698 
700  template<typename T>
701  bool Param::Get(T &_value) const
702  {
703  sdf::Errors errors;
704  bool result = this->Get<T>(_value, errors);
705  if (!errors.empty())
706  sdferr << errors;
707  return result;
708  }
709 
711  template<typename T>
712  bool Param::Get(T &_value, sdf::Errors &_errors) const
713  {
714  T *value = std::get_if<T>(&this->dataPtr->value);
715  if (value)
716  {
717  _value = *value;
718  }
719  else
720  {
721  std::string typeStr = this->dataPtr->TypeToString<T>();
722  if (typeStr.empty())
723  {
724  _errors.push_back({ErrorCode::UNKNOWN_PARAMETER_TYPE,
725  "Unknown parameter type[" + std::string(typeid(T).name()) + "]"});
726  return false;
727  }
728 
729  std::string valueStr = this->GetAsString(_errors);
731  bool success = this->dataPtr->ValueFromStringImpl(
732  typeStr, valueStr, pv, _errors);
733 
734  if (success)
735  {
736  _value = std::get<T>(pv);
737  }
738  else if (typeStr == "bool" && this->dataPtr->typeName == "string")
739  {
740  // this section for handling bool types is to keep backward behavior
741  // TODO(anyone) remove for Fortress. For more details:
742  // https://github.com/gazebosim/sdformat/pull/638
743  valueStr = lowercase(valueStr);
744 
745  std::stringstream tmp;
746  if (valueStr == "true" || valueStr == "1")
747  tmp << "1";
748  else
749  tmp << "0";
750 
751  tmp >> _value;
752  return true;
753  }
754 
755  return success;
756  }
757 
758  return true;
759  }
760 
762  template<typename T>
763  bool Param::GetDefault(T &_value) const
764  {
765  sdf::Errors errors;
766  bool result = this>GetDefault<T>(_value, errors);
767  if (!errors.empty())
768  sdferr << errors;
769  return result;
770  }
771 
773  template<typename T>
774  bool Param::GetDefault(T &_value, sdf::Errors &_errors) const
775  {
776  std::stringstream ss;
777 
778  try
779  {
780  ss << ParamStreamer{this->dataPtr->defaultValue};
781  ss >> _value;
782  }
783  catch(...)
784  {
785  _errors.push_back({ErrorCode::PARAMETER_ERROR,
786  "Unable to convert parameter["
787  + this->dataPtr->key + "] "
788  + "whose type is["
789  + this->dataPtr->typeName + "], to "
790  + "type[" + typeid(T).name() + "]"});
791  return false;
792  }
793 
794  return true;
795  }
796 
798  template<typename Type>
799  bool Param::IsType() const
800  {
801  return std::holds_alternative<Type>(this->dataPtr->value);
802  }
803  }
804 }
805 
806 #ifdef _WIN32
807 #pragma warning(pop)
808 #endif
809 
810 #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:511
sdf::SDF_VERSION_NAMESPACE::ParamPrivate::required
bool required
True if the parameter is required.
Definition: Param.hh:502
sdf::SDF_VERSION_NAMESPACE::ParamPrivate
Definition: Param.hh:496
sdf
namespace for Simulation Description Format parser
Definition: Actor.hh:34
sdf::SDF_VERSION_NAMESPACE::ParamPrivate::typeName
std::string typeName
Definition: Param.hh:508
PrintConfig.hh
sdf::SDF_VERSION_NAMESPACE::ParamPrivate::value
ParamVariant value
This parameter's value.
Definition: Param.hh:535
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:543
sdf::SDF_VERSION_NAMESPACE::PrintConfig
This class contains configuration options for printing elements.
Definition: PrintConfig.hh:31
sdf::SDF_VERSION_NAMESPACE::ParamPrivate::updateFunc
std::function< std::any()> updateFunc
Update function pointer.
Definition: Param.hh:517
sdf::SDF_VERSION_NAMESPACE::Param
A parameter class.
Definition: Param.hh:130
sdf::SDF_VERSION_NAMESPACE::Param::GetDefault
bool GetDefault(T &_value) const
Get the default value of the parameter.
Definition: Param.hh:763
Types.hh
sdf::SDF_VERSION_NAMESPACE::ParamPrivate::parentElement
ElementWeakPtr parentElement
Parent element.
Definition: Param.hh:514
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:546
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:621
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:799
sdf::SDF_VERSION_NAMESPACE::ParamPrivate::minValue
std::optional< ParamVariant > minValue
This parameter's minimum allowed value.
Definition: Param.hh:552
sdf::SDF_VERSION_NAMESPACE::Param::SetUpdateFunc
void SetUpdateFunc(T _updateFunc)
Set the update function.
Definition: Param.hh:662
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:540
sdf::SDF_VERSION_NAMESPACE::operator<<
std::ostream & operator<<(std::ostream &os, ParamStreamer< T > s)
Definition: Param.hh:89
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:499
sdf::SDF_VERSION_NAMESPACE::ParamPrivate::defaultValue
ParamVariant defaultValue
This parameter's default value.
Definition: Param.hh:549
sdf::SDF_VERSION_NAMESPACE::Element
class GZ_SDFORMAT_VISIBLE Element
Definition: Element.hh:50
sdf::SDF_VERSION_NAMESPACE::Param::Get
bool Get(T &_value) const
Get the value of the parameter.
Definition: Param.hh:701
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:483
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:62
sdf::SDF_VERSION_NAMESPACE::Param::Set
bool Set(const T &_value)
Set the parameter's value.
Definition: Param.hh:669
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:532
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:505
sdf::SDF_VERSION_NAMESPACE::ElementPtr
std::shared_ptr< Element > ElementPtr
Definition: Element.hh:54
sdf::SDF_VERSION_NAMESPACE::ParamPrivate::maxValue
std::optional< ParamVariant > maxValue
This parameter's maximum allowed value.
Definition: Param.hh:555
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