JSBSim Flight Dynamics Model 1.2.4 (07 Feb 2026)
An Open Source Flight Dynamics and Control Software Library in C++
Loading...
Searching...
No Matches
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%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
28SENTRY
29%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
30
31#ifndef FGPROPERTYMANAGER_H
32#define FGPROPERTYMANAGER_H
33
34/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
35INCLUDES
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 <type_traits>
49#if !PROPS_STANDALONE
50# include "simgear/math/SGMath.hxx"
51#endif
52
53#include "FGJSBBase.h"
54
55/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
56FORWARD DECLARATIONS
57%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
58
59template <class C, class T>
61{
62public:
63 typedef T(C::* getter_t)() const;
64 typedef void (C::* setter_t)(T);
66 getter_t getter = nullptr, setter_t setter = nullptr)
67 : _obj(obj), _getter(getter), _setter(setter) {}
68 int getValue() const override {
69 if (_getter) { return static_cast<int>((_obj.*_getter)()); }
70 else { return SGRawValue<int>::DefaultValue(); }
71 }
72 bool setValue(int value) override {
73 if (_setter) { (_obj.*_setter)(static_cast<T>(value)); return true; }
74 else return false;
75 }
76 SGRaw* clone() const override {
77 return new SGRawValueMethodsEnum(_obj, _getter, _setter);
78 }
79private:
80 C& _obj;
81 getter_t _getter;
82 setter_t _setter;
83};
84
85template <class C, class T, class U>
87{
88public:
89 typedef T(C::* getter_t)(U) const;
90 typedef void (C::* setter_t)(U, T);
91 SGRawValueMethodsIndexedEnum(C& obj, U index,
92 getter_t getter = nullptr, setter_t setter = nullptr)
93 : _obj(obj), _index(index), _getter(getter), _setter(setter) {}
94 T getValue() const override {
95 if (_getter) { return (_obj.*_getter)(_index); }
96 else { return SGRawValue<T>::DefaultValue(); }
97 }
98 bool setValue(T value) override {
99 if (_setter) { (_obj.*_setter)(_index, value); return true; }
100 else return false;
101 }
102 SGRaw* clone() const override {
103 return new SGRawValueMethodsIndexedEnum(_obj, _index, _getter, _setter);
104 }
105private:
106 C& _obj;
107 U _index;
108 getter_t _getter;
109 setter_t _setter;
110};
111
112namespace JSBSim {
113
114JSBSIM_API std::string GetPrintableName(const SGPropertyNode* node);
115JSBSIM_API std::string GetFullyQualifiedName(const SGPropertyNode* node);
116JSBSIM_API std::string GetRelativeName(const SGPropertyNode* node, const std::string &path);
117
118/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
119CLASS DOCUMENTATION
120%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
121
126/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
127CLASS DECLARATION
128%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
129
130class JSBSIM_API FGPropertyManager
131{
132 public:
134 FGPropertyManager(void) { root = new SGPropertyNode; }
135
137 explicit FGPropertyManager(SGPropertyNode* _root) : root(_root) {};
138
140 virtual ~FGPropertyManager(void) { Unbind(); }
141
142 SGPropertyNode* GetNode(void) const { return root; }
143 SGPropertyNode* GetNode(const std::string &path, bool create = false)
144 { return root->getNode(path, create); }
145 SGPropertyNode* GetNode(const std::string &relpath, int index, bool create = false)
146 { return root->getNode(relpath, index, create); }
147 bool HasNode(const std::string& path) const
148 {
149 std::string newPath = path;
150 if (newPath[0] == '-') newPath.erase(0,1);
151 SGPropertyNode* prop = root->getNode(newPath);
152 return prop != nullptr;
153 }
154
162 std::string mkPropertyName(std::string name, bool lowercase);
163
165 // Convenience functions for tying properties, with logging.
167
168
177 void Untie (const std::string &name);
178
187 void Untie (SGPropertyNode* property);
188
190 void Unbind (void);
191
199 void Unbind(const void* instance);
200
209 template <typename T> void Unbind(const std::shared_ptr<T>& instance) {
210 Unbind(instance.get());
211 }
212
222 template <typename T> void
223 Tie (const std::string &name, T *pointer)
224 {
225 SGPropertyNode* property = root->getNode(name.c_str(), true);
226 if (!property) {
227 std::cerr << "Could not get or create property " << name << std::endl;
228 return;
229 }
230
231 if (!property->tie(SGRawValuePointer<T>(pointer), false))
232 std::cerr << "Failed to tie property " << name << " to a pointer" << std::endl;
233 else {
234 tied_properties.push_back(PropertyState(property, nullptr));
235 if (FGJSBBase::debug_lvl & 0x20) std::cout << name << std::endl;
236 }
237 }
238
255 template <class T, class V>
256 typename std::enable_if_t<std::is_enum_v<V>, void>
257 Tie (const std::string &name, T * obj, V (T::*getter)() const,
258 void (T::*setter)(V) = nullptr)
259 {
260 SGPropertyNode* property = root->getNode(name.c_str(), true);
261 if (!property) {
262 std::cerr << "Could not get or create property " << name << std::endl;
263 return;
264 }
265
266 if (!property->tie(SGRawValueMethodsEnum<T,V>(*obj, getter, setter), false))
267 std::cerr << "Failed to tie property " << name << " to object methods"
268 << std::endl;
269 else {
270 tied_properties.push_back(PropertyState(property, obj));
271 if (!setter) property->setAttribute(SGPropertyNode::WRITE, false);
272 if (!getter) property->setAttribute(SGPropertyNode::READ, false);
273 if (FGJSBBase::debug_lvl & 0x20) std::cout << name << std::endl;
274 }
275 }
276
277 template <class T, class V>
278 typename std::enable_if_t<!std::is_enum_v<V>, void>
279 Tie (const std::string &name, T * obj, V (T::*getter)() const,
280 void (T::*setter)(V) = nullptr)
281 {
282 SGPropertyNode* property = root->getNode(name.c_str(), true);
283 if (!property) {
284 std::cerr << "Could not get or create property " << name << std::endl;
285 return;
286 }
287
288 if (!property->tie(SGRawValueMethods<T,V>(*obj, getter, setter), false))
289 std::cerr << "Failed to tie property " << name << " to object methods"
290 << std::endl;
291 else {
292 tied_properties.push_back(PropertyState(property, obj));
293 if (!setter) property->setAttribute(SGPropertyNode::WRITE, false);
294 if (!getter) property->setAttribute(SGPropertyNode::READ, false);
295 if (FGJSBBase::debug_lvl & 0x20) std::cout << name << std::endl;
296 }
297 }
298
315 template <class T, class V> void
316 Tie (const std::string &name, T * obj, int index, V (T::*getter)(int) const,
317 void (T::*setter)(int, V) = nullptr)
318 {
319 SGPropertyNode* property = root->getNode(name.c_str(), true);
320 if (!property) {
321 std::cerr << "Could not get or create property " << name << std::endl;
322 return;
323 }
324
325 if (!property->tie(SGRawValueMethodsIndexed<T,V>(*obj, index, getter, setter),
326 false))
327 std::cerr << "Failed to tie property " << name
328 << " to indexed object methods" << std::endl;
329 else {
330 tied_properties.push_back(PropertyState(property, obj));
331 if (!setter) property->setAttribute(SGPropertyNode::WRITE, false);
332 if (!getter) property->setAttribute(SGPropertyNode::READ, false);
333 if (FGJSBBase::debug_lvl & 0x20) std::cout << name << std::endl;
334 }
335 }
336
353 template <class T, class V, class U>
354 typename std::enable_if_t<std::is_enum_v<U>, void>
355 Tie(const std::string& name, T* obj, U index, V(T::* getter)(U) const,
356 void (T::* setter)(U, V) = nullptr)
357 {
358 SGPropertyNode* property = root->getNode(name.c_str(), true);
359 if (!property) {
360 std::cerr << "Could not get or create property " << name << std::endl;
361 return;
362 }
363 if (!property->tie(SGRawValueMethodsIndexedEnum<T, V, U>(*obj, index, getter, setter),
364 false))
365 std::cerr << "Failed to tie property " << name
366 << " to indexed object methods" << std::endl;
367 else {
368 tied_properties.push_back(PropertyState(property, obj));
369 if (!setter) property->setAttribute(SGPropertyNode::WRITE, false);
370 if (!getter) property->setAttribute(SGPropertyNode::READ, false);
371 if (FGJSBBase::debug_lvl & 0x20) std::cout << name << std::endl;
372 }
373 }
374
375 private:
376 struct PropertyState {
377 SGPropertyNode_ptr node;
378 const void* BindingInstance = nullptr;
379 bool WriteAttribute = true;
380 bool ReadAttribute = true;
381 PropertyState(SGPropertyNode* property, const void* instance)
382 : node(property), BindingInstance(instance) {
383 WriteAttribute = node->getAttribute(SGPropertyNode::WRITE);
384 ReadAttribute = node->getAttribute(SGPropertyNode::READ);
385 }
386 void untie(void) {
387 node->setAttribute(SGPropertyNode::WRITE, WriteAttribute);
388 node->setAttribute(SGPropertyNode::READ, ReadAttribute);
389 node->untie();
390 }
391 };
392 std::list<PropertyState> tied_properties;
393 SGPropertyNode_ptr root;
394};
395}
396#endif // FGPROPERTYMANAGER_H
A node in a property tree.
Definition props.hxx:754
void setAttribute(Attribute attr, bool state)
Set a single mode attribute for the property node.
Definition props.hxx:1138
SGPropertyNode * getNode(const char *relative_path, bool create=false)
Get a pointer to another node by relative path.
bool setValue(int value) override
Assign a new underlying value.
int getValue() const override
Return the underlying value.
bool setValue(T value) override
Assign a new underlying value.
T getValue() const override
Return the underlying value.
An indexed value managed through an object and access methods.
Definition props.hxx:616
A value managed through an object and access methods.
Definition props.hxx:583
A raw value bound to a pointer.
Definition props.hxx:413
Abstract base class for a raw value.
Definition props.hxx:320
static T DefaultValue()
The default underlying value for this type.
Definition props.hxx:332
Base class for SGRawValue classes that holds no type information.
Definition props.hxx:222
Interface definition for a property list.