JSBSim Flight Dynamics Model  1.2.0 (05 Nov 2023)
An Open Source Flight Dynamics and Control Software Library in C++
FGPropertyManager.h
1 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2 
3  Header: FGPropertyManager.h
4  Author: Tony Peden
5  Based on work originally by David Megginson
6  Date: 2/2002
7 
8  ------------- Copyright (C) 2002 -------------
9 
10  This program is free software; you can redistribute it and/or modify it under
11  the terms of the GNU Lesser General Public License as published by the Free Software
12  Foundation; either version 2 of the License, or (at your option) any later
13  version.
14 
15  This program is distributed in the hope that it will be useful, but WITHOUT
16  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
17  FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
18  details.
19 
20  You should have received a copy of the GNU Lesser General Public License along with
21  this program; if not, write to the Free Software Foundation, Inc., 59 Temple
22  Place - Suite 330, Boston, MA 02111-1307, USA.
23 
24  Further information about the GNU Lesser General Public License can also be found on
25  the world wide web at http://www.gnu.org.
26 
27 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
28 SENTRY
29 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
30 
31 #ifndef FGPROPERTYMANAGER_H
32 #define FGPROPERTYMANAGER_H
33 
34 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
35 INCLUDES
36 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
37 
38 // This is needed by MSVC9 when included in FlightGear because of
39 // the new Vec4d class in props.hxx
40 #if defined( HAVE_CONFIG_H )
41 # include <config.h>
42 #endif
43 
44 #include <string>
45 #include <list>
46 #include <memory>
47 #include "simgear/props/props.hxx"
48 #if !PROPS_STANDALONE
49 # include "simgear/math/SGMath.hxx"
50 #endif
51 
52 #include "FGJSBBase.h"
53 
54 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
55 FORWARD DECLARATIONS
56 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
57 
58 namespace JSBSim {
59 
60 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
61 CLASS DOCUMENTATION
62 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
63 
68 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
69 CLASS DECLARATION
70 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
71 
72 class JSBSIM_API FGPropertyNode : public SGPropertyNode
73 {
74  public:
76  virtual ~FGPropertyNode(void) {}
77 
86  GetNode (const std::string &path, bool create = false);
87 
89  GetNode (const std::string &relpath, int index, bool create = false);
90 
97  bool HasNode (const std::string &path);
98 
102  const std::string& GetName( void ) const { return getNameString(); }
103 
107  std::string GetPrintableName( void ) const;
108 
113  std::string GetFullyQualifiedName(void) const;
114 
122  std::string GetRelativeName( const std::string &path = "/fdm/jsbsim/" ) const;
123 
138  bool GetBool (const std::string &name, bool defaultValue = false) const;
139 
140 
155  int GetInt (const std::string &name, int defaultValue = 0) const;
156 
157 
172  int GetLong (const std::string &name, long defaultValue = 0L) const;
173 
174 
189  float GetFloat (const std::string &name, float defaultValue = 0.0) const;
190 
191 
206  double GetDouble (const std::string &name, double defaultValue = 0.0) const;
207 
208 
223  std::string GetString (const std::string &name, std::string defaultValue = "") const;
224 
225 
239  bool SetBool (const std::string &name, bool val);
240 
241 
255  bool SetInt (const std::string &name, int val);
256 
257 
271  bool SetLong (const std::string &name, long val);
272 
273 
287  bool SetFloat (const std::string &name, float val);
288 
289 
303  bool SetDouble (const std::string &name, double val);
304 
305 
319  bool SetString (const std::string &name, const std::string &val);
320 
321 
323  // Convenience functions for setting property attributes.
325 
326 
339  void SetArchivable (const std::string &name, bool state = true);
340 
341 
354  void SetReadable (const std::string &name, bool state = true);
355 
356 
369  void SetWritable (const std::string &name, bool state = true);
370 };
371 
372 typedef SGSharedPtr<FGPropertyNode> FGPropertyNode_ptr;
373 typedef SGSharedPtr<const FGPropertyNode> FGConstPropertyNode_ptr;
374 
375 class JSBSIM_API FGPropertyManager
376 {
377  public:
379  FGPropertyManager(void) { root = new FGPropertyNode; }
380 
382  explicit FGPropertyManager(FGPropertyNode* _root) : root(_root) {};
383 
385  virtual ~FGPropertyManager(void) { Unbind(); }
386 
387  FGPropertyNode* GetNode(void) const { return root; }
388  FGPropertyNode* GetNode(const std::string &path, bool create = false)
389  { return root->GetNode(path, create); }
390  FGPropertyNode* GetNode(const std::string &relpath, int index, bool create = false)
391  { return root->GetNode(relpath, index, create); }
392  bool HasNode(const std::string& path) const
393  {
394  std::string newPath = path;
395  if (newPath[0] == '-') newPath.erase(0,1);
396  return root->HasNode(newPath);
397  }
398 
406  std::string mkPropertyName(std::string name, bool lowercase);
407 
409  // Convenience functions for tying properties, with logging.
411 
412 
421  void Untie (const std::string &name);
422 
431  void Untie (SGPropertyNode* property);
432 
434  void Unbind (void);
435 
443  void Unbind(const void* instance);
444 
453  template <typename T> void Unbind(const std::shared_ptr<T>& instance) {
454  Unbind(instance.get());
455  }
456 
466  template <typename T> void
467  Tie (const std::string &name, T *pointer)
468  {
469  SGPropertyNode* property = root->getNode(name.c_str(), true);
470  if (!property) {
471  cerr << "Could not get or create property " << name << endl;
472  return;
473  }
474 
475  if (!property->tie(SGRawValuePointer<T>(pointer), false))
476  cerr << "Failed to tie property " << name << " to a pointer" << endl;
477  else {
478  tied_properties.push_back(PropertyState(property, nullptr));
479  if (FGJSBBase::debug_lvl & 0x20) cout << name << endl;
480  }
481  }
482 
497  template <typename T> void
498  Tie (const std::string &name, T (*getter)(), void (*setter)(T) = nullptr)
499  {
500  SGPropertyNode* property = root->getNode(name.c_str(), true);
501  if (!property) {
502  std::cerr << "Could not get or create property " << name << std::endl;
503  return;
504  }
505 
506  if (!property->tie(SGRawValueFunctions<T>(getter, setter), false))
507  std::cerr << "Failed to tie property " << name << " to functions"
508  << std::endl;
509  else {
510  tied_properties.push_back(PropertyState(property, nullptr));
511  if (!setter) property->setAttribute(SGPropertyNode::WRITE, false);
512  if (!getter) property->setAttribute(SGPropertyNode::READ, false);
513  if (FGJSBBase::debug_lvl & 0x20) std::cout << name << std::endl;
514  }
515  }
516 
532  template <typename T> void
533  Tie (const std::string &name, int index, T (*getter)(int),
534  void (*setter)(int, T) = nullptr)
535  {
536  SGPropertyNode* property = root->getNode(name.c_str(), true);
537  if (!property) {
538  std::cerr << "Could not get or create property " << name << std::endl;
539  return;
540  }
541 
542  if (!property->tie(SGRawValueFunctionsIndexed<T>(index, getter, setter),
543  false))
544  std::cerr << "Failed to tie property " << name << " to indexed functions"
545  << std::endl;
546  else {
547  tied_properties.push_back(PropertyState(property, nullptr));
548  if (!setter) property->setAttribute(SGPropertyNode::WRITE, false);
549  if (!getter) property->setAttribute(SGPropertyNode::READ, false);
550  if (FGJSBBase::debug_lvl & 0x20) std::cout << name << std::endl;
551  }
552  }
553 
570  template <class T, class V> void
571  Tie (const std::string &name, T * obj, V (T::*getter)() const,
572  void (T::*setter)(V) = nullptr)
573  {
574  SGPropertyNode* property = root->getNode(name.c_str(), true);
575  if (!property) {
576  std::cerr << "Could not get or create property " << name << std::endl;
577  return;
578  }
579 
580  if (!property->tie(SGRawValueMethods<T,V>(*obj, getter, setter), false))
581  std::cerr << "Failed to tie property " << name << " to object methods"
582  << std::endl;
583  else {
584  tied_properties.push_back(PropertyState(property, obj));
585  if (!setter) property->setAttribute(SGPropertyNode::WRITE, false);
586  if (!getter) property->setAttribute(SGPropertyNode::READ, false);
587  if (FGJSBBase::debug_lvl & 0x20) std::cout << name << std::endl;
588  }
589  }
590 
607  template <class T, class V> void
608  Tie (const std::string &name, T * obj, int index, V (T::*getter)(int) const,
609  void (T::*setter)(int, V) = nullptr)
610  {
611  SGPropertyNode* property = root->getNode(name.c_str(), true);
612  if (!property) {
613  std::cerr << "Could not get or create property " << name << std::endl;
614  return;
615  }
616 
617  if (!property->tie(SGRawValueMethodsIndexed<T,V>(*obj, index, getter, setter),
618  false))
619  std::cerr << "Failed to tie property " << name
620  << " to indexed object methods" << std::endl;
621  else {
622  tied_properties.push_back(PropertyState(property, obj));
623  if (!setter) property->setAttribute(SGPropertyNode::WRITE, false);
624  if (!getter) property->setAttribute(SGPropertyNode::READ, false);
625  if (FGJSBBase::debug_lvl & 0x20) std::cout << name << std::endl;
626  }
627  }
628 
629  private:
630  struct PropertyState {
631  SGPropertyNode_ptr node;
632  const void* BindingInstance = nullptr;
633  bool WriteAttribute = true;
634  bool ReadAttribute = true;
635  PropertyState(SGPropertyNode* property, const void* instance)
636  : node(property), BindingInstance(instance) {
637  WriteAttribute = node->getAttribute(SGPropertyNode::WRITE);
638  ReadAttribute = node->getAttribute(SGPropertyNode::READ);
639  }
640  void untie(void) {
641  node->setAttribute(SGPropertyNode::WRITE, WriteAttribute);
642  node->setAttribute(SGPropertyNode::READ, ReadAttribute);
643  node->untie();
644  }
645  };
646  std::list<PropertyState> tied_properties;
647  FGPropertyNode_ptr root;
648 };
649 }
650 #endif // FGPROPERTYMANAGER_H
void Tie(const std::string &name, int index, T(*getter)(int), void(*setter)(int, T)=nullptr)
Tie a property to a pair of indexed functions.
virtual ~FGPropertyManager(void)
Destructor.
FGPropertyManager(FGPropertyNode *_root)
Constructor.
void Tie(const std::string &name, T(*getter)(), void(*setter)(T)=nullptr)
Tie a property to a pair of simple functions.
void Tie(const std::string &name, T *obj, V(T::*getter)() const, void(T::*setter)(V)=nullptr)
Tie a property to a pair of object methods.
void Tie(const std::string &name, T *pointer)
Tie a property to an external variable.
void Unbind(const std::shared_ptr< T > &instance)
Unbind all properties bound by this manager to an instance.
void Tie(const std::string &name, T *obj, int index, V(T::*getter)(int) const, void(T::*setter)(int, V)=nullptr)
Tie a property to a pair of indexed object methods.
FGPropertyManager(void)
Default constructor.
Class wrapper for property handling.
FGPropertyNode * GetNode(const std::string &path, bool create=false)
Get a property node.
bool HasNode(const std::string &path)
Test whether a given node exists.
virtual ~FGPropertyNode(void)
Destructor.
const std::string & GetName(void) const
Get the name of a node.