JSBSim Flight Dynamics Model 1.3.0 (09 Apr 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#include "input_output/FGLog.h"
55
56/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
57FORWARD DECLARATIONS
58%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
59
60template <class C, class T>
62{
63public:
64 typedef T(C::* getter_t)() const;
65 typedef void (C::* setter_t)(T);
67 getter_t getter = nullptr, setter_t setter = nullptr)
68 : _obj(obj), _getter(getter), _setter(setter) {}
69 int getValue() const override {
70 if (_getter) { return static_cast<int>((_obj.*_getter)()); }
71 else { return SGRawValue<int>::DefaultValue(); }
72 }
73 bool setValue(int value) override {
74 if (_setter) { (_obj.*_setter)(static_cast<T>(value)); return true; }
75 else return false;
76 }
77 SGRaw* clone() const override {
78 return new SGRawValueMethodsEnum(_obj, _getter, _setter);
79 }
80private:
81 C& _obj;
82 getter_t _getter;
83 setter_t _setter;
84};
85
86template <class C, class T, class U>
88{
89public:
90 typedef T(C::* getter_t)(U) const;
91 typedef void (C::* setter_t)(U, T);
92 SGRawValueMethodsIndexedEnum(C& obj, U index,
93 getter_t getter = nullptr, setter_t setter = nullptr)
94 : _obj(obj), _index(index), _getter(getter), _setter(setter) {}
95 T getValue() const override {
96 if (_getter) { return (_obj.*_getter)(_index); }
97 else { return SGRawValue<T>::DefaultValue(); }
98 }
99 bool setValue(T value) override {
100 if (_setter) { (_obj.*_setter)(_index, value); return true; }
101 else return false;
102 }
103 SGRaw* clone() const override {
104 return new SGRawValueMethodsIndexedEnum(_obj, _index, _getter, _setter);
105 }
106private:
107 C& _obj;
108 U _index;
109 getter_t _getter;
110 setter_t _setter;
111};
112
113namespace JSBSim {
114
115JSBSIM_API std::string GetPrintableName(const SGPropertyNode* node);
116JSBSIM_API std::string GetFullyQualifiedName(const SGPropertyNode* node);
117JSBSIM_API std::string GetRelativeName(const SGPropertyNode* node, const std::string &path);
118
119/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
120CLASS DOCUMENTATION
121%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
122
127/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
128CLASS DECLARATION
129%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
130
131class JSBSIM_API FGPropertyManager
132{
133 public:
135 FGPropertyManager(void) { root = new SGPropertyNode; }
136
138 explicit FGPropertyManager(SGPropertyNode* _root) : root(_root) {};
139
141 virtual ~FGPropertyManager(void) { Unbind(); }
142
143 SGPropertyNode* GetNode(void) const { return root; }
144 SGPropertyNode* GetNode(const std::string &path, bool create = false)
145 { return root->getNode(path, create); }
146 SGPropertyNode* GetNode(const std::string &relpath, int index, bool create = false)
147 { return root->getNode(relpath, index, create); }
148 bool HasNode(const std::string& path) const
149 {
150 std::string newPath = path;
151 if (newPath[0] == '-') newPath.erase(0,1);
152 SGPropertyNode* prop = root->getNode(newPath);
153 return prop != nullptr;
154 }
155
163 std::string mkPropertyName(std::string name, bool lowercase);
164
166 // Convenience functions for tying properties, with logging.
168
169
178 void Untie (const std::string &name);
179
188 void Untie (SGPropertyNode* property);
189
191 void Unbind (void);
192
200 void Unbind(const void* instance);
201
210 template <typename T> void Unbind(const std::shared_ptr<T>& instance) {
211 Unbind(instance.get());
212 }
213
223 template <typename T> void
224 Tie (const std::string &name, T *pointer)
225 {
226 SGPropertyNode* property = root->getNode(name.c_str(), true);
227 if (!property) {
228 FGLogging log(LogLevel::ERROR);
229 log << "Could not get or create property " << name << "\n";
230 return;
231 }
232
233 if (!property->tie(SGRawValuePointer<T>(pointer), false)) {
234 FGLogging log(LogLevel::ERROR);
235 log << "Failed to tie property " << name << " to a pointer\n";
236 }
237 else {
238 tied_properties.push_back(PropertyState(property, nullptr));
239 if (FGJSBBase::debug_lvl & 0x20) {
240 FGLogging log(LogLevel::DEBUG);
241 log << name << "\n";
242 }
243 }
244 }
245
262 template <class T, class V>
263 typename std::enable_if_t<std::is_enum_v<V>, void>
264 Tie (const std::string &name, T * obj, V (T::*getter)() const,
265 void (T::*setter)(V) = nullptr)
266 {
267 SGPropertyNode* property = root->getNode(name.c_str(), true);
268 if (!property) {
269 FGLogging log(LogLevel::ERROR);
270 log << "Could not get or create property " << name << "\n";
271 return;
272 }
273
274 if (!property->tie(SGRawValueMethodsEnum<T,V>(*obj, getter, setter), false)) {
275 FGLogging log(LogLevel::ERROR);
276 log << "Failed to tie property " << name << " to object methods\n";
277 }
278 else {
279 tied_properties.push_back(PropertyState(property, obj));
280 if (!setter) property->setAttribute(SGPropertyNode::WRITE, false);
281 if (!getter) property->setAttribute(SGPropertyNode::READ, false);
282 if (FGJSBBase::debug_lvl & 0x20) {
283 FGLogging log(LogLevel::DEBUG);
284 log << name << "\n";
285 }
286 }
287 }
288
289 template <class T, class V>
290 typename std::enable_if_t<!std::is_enum_v<V>, void>
291 Tie (const std::string &name, T * obj, V (T::*getter)() const,
292 void (T::*setter)(V) = nullptr)
293 {
294 SGPropertyNode* property = root->getNode(name.c_str(), true);
295 if (!property) {
296 FGLogging log(LogLevel::ERROR);
297 log << "Could not get or create property " << name << "\n";
298 return;
299 }
300
301 if (!property->tie(SGRawValueMethods<T,V>(*obj, getter, setter), false)) {
302 FGLogging log(LogLevel::ERROR);
303 log << "Failed to tie property " << name << " to object methods\n";
304 }
305 else {
306 tied_properties.push_back(PropertyState(property, obj));
307 if (!setter) property->setAttribute(SGPropertyNode::WRITE, false);
308 if (!getter) property->setAttribute(SGPropertyNode::READ, false);
309 if (FGJSBBase::debug_lvl & 0x20) {
310 FGLogging log(LogLevel::DEBUG);
311 log << name << "\n";
312 }
313 }
314 }
315
332 template <class T, class V> void
333 Tie (const std::string &name, T * obj, int index, V (T::*getter)(int) const,
334 void (T::*setter)(int, V) = nullptr)
335 {
336 SGPropertyNode* property = root->getNode(name.c_str(), true);
337 if (!property) {
338 FGLogging log(LogLevel::ERROR);
339 log << "Could not get or create property " << name << "\n";
340 return;
341 }
342
343 if (!property->tie(SGRawValueMethodsIndexed<T,V>(*obj, index, getter, setter),
344 false)) {
345 FGLogging log(LogLevel::ERROR);
346 log << "Failed to tie property " << name
347 << " to indexed object methods\n";
348 }
349 else {
350 tied_properties.push_back(PropertyState(property, obj));
351 if (!setter) property->setAttribute(SGPropertyNode::WRITE, false);
352 if (!getter) property->setAttribute(SGPropertyNode::READ, false);
353 if (FGJSBBase::debug_lvl & 0x20) {
354 FGLogging log(LogLevel::DEBUG);
355 log << name << "\n";
356 }
357 }
358 }
359
376 template <class T, class V, class U>
377 typename std::enable_if_t<std::is_enum_v<U>, void>
378 Tie(const std::string& name, T* obj, U index, V(T::* getter)(U) const,
379 void (T::* setter)(U, V) = nullptr)
380 {
381 SGPropertyNode* property = root->getNode(name.c_str(), true);
382 if (!property) {
383 FGLogging log(LogLevel::ERROR);
384 log << "Could not get or create property " << name << "\n";
385 return;
386 }
387 if (!property->tie(SGRawValueMethodsIndexedEnum<T, V, U>(*obj, index, getter, setter),
388 false)) {
389 FGLogging log(LogLevel::ERROR);
390 log << "Failed to tie property " << name << " to indexed object methods\n";
391 }
392 else {
393 tied_properties.push_back(PropertyState(property, obj));
394 if (!setter) property->setAttribute(SGPropertyNode::WRITE, false);
395 if (!getter) property->setAttribute(SGPropertyNode::READ, false);
396 if (FGJSBBase::debug_lvl & 0x20) {
397 FGLogging log(LogLevel::DEBUG);
398 log << name << "\n";
399 }
400 }
401 }
402
403 private:
404 struct PropertyState {
405 SGPropertyNode_ptr node;
406 const void* BindingInstance = nullptr;
407 bool WriteAttribute = true;
408 bool ReadAttribute = true;
409 PropertyState(SGPropertyNode* property, const void* instance)
410 : node(property), BindingInstance(instance) {
411 WriteAttribute = node->getAttribute(SGPropertyNode::WRITE);
412 ReadAttribute = node->getAttribute(SGPropertyNode::READ);
413 }
414 void untie(void) {
415 node->setAttribute(SGPropertyNode::WRITE, WriteAttribute);
416 node->setAttribute(SGPropertyNode::READ, ReadAttribute);
417 node->untie();
418 }
419 };
420 std::list<PropertyState> tied_properties;
421 SGPropertyNode_ptr root;
422};
423}
424#endif // FGPROPERTYMANAGER_H
A node in a property tree.
Definition props.hxx:747
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:609
A value managed through an object and access methods.
Definition props.hxx:576
A raw value bound to a pointer.
Definition props.hxx:406
Abstract base class for a raw value.
Definition props.hxx:313
static T DefaultValue()
The default underlying value for this type.
Definition props.hxx:325
Base class for SGRawValue classes that holds no type information.
Definition props.hxx:215
Main namespace for the JSBSim Flight Dynamics Model.
Definition FGFDMExec.cpp:71
Interface definition for a property list.