JSBSim Flight Dynamics Model  1.2.0 (05 Nov 2023)
An Open Source Flight Dynamics and Control Software Library in C++
FGPropertyManager.cpp
1 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2 
3  Header: FGPropertyManager.cpp
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 INCLUDES
29 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
30 
31 #include <assert.h>
32 #include "FGPropertyManager.h"
33 
34 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
35 DEFINITIONS
36 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
37 
38 
39 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
40 FORWARD DECLARATIONS
41 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
42 
43 using namespace std;
44 
45 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
46 COMMENTS, REFERENCES, and NOTES [use "class documentation" below for API docs]
47 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
48 */
49 
50 namespace JSBSim {
51 
52 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
53 
54 void FGPropertyManager::Unbind(void)
55 {
56  for(auto& property: tied_properties)
57  property.untie();
58 
59  tied_properties.clear();
60 }
61 
62 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
63 
64 void FGPropertyManager::Unbind(const void* instance)
65 {
66  auto it = tied_properties.begin();
67 
68  while(it != tied_properties.end()) {
69  auto property = it++;
70  if (property->BindingInstance == instance) {
71  property->untie();
72  tied_properties.erase(property);
73  }
74  }
75 }
76 
77 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
78 
79 string FGPropertyManager::mkPropertyName(string name, bool lowercase) {
80 
81  /* do this two pass to avoid problems with characters getting skipped
82  because the index changed */
83  unsigned i;
84  for(i=0;i<name.length();i++) {
85  if( lowercase && isupper(name[i]) )
86  name[i]=tolower(name[i]);
87  else if( isspace(name[i]) )
88  name[i]='-';
89  }
90 
91  return name;
92 }
93 
94 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
95 
97 FGPropertyNode::GetNode (const string &path, bool create)
98 {
99  SGPropertyNode* node = getNode(path.c_str(), create);
100  if (node == 0) {
101  cerr << "FGPropertyManager::GetNode() No node found for " << path << endl;
102  }
103  return (FGPropertyNode*)node;
104 }
105 
106 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
107 
109 FGPropertyNode::GetNode (const string &relpath, int index, bool create)
110 {
111  SGPropertyNode* node = getNode(relpath.c_str(), index, create);
112  if (node == 0) {
113  cerr << "FGPropertyManager::GetNode() No node found for " << relpath
114  << "[" << index << "]" << endl;
115  }
116  return (FGPropertyNode*)node;
117 }
118 
119 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
120 
121 bool FGPropertyNode::HasNode (const string &path)
122 {
123  const SGPropertyNode* node = getNode(path.c_str(), false);
124  return (node != 0);
125 }
126 
127 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
128 
129 string FGPropertyNode::GetPrintableName( void ) const
130 {
131  string temp_string(getNameString());
132  size_t initial_location=0;
133  size_t found_location;
134 
135  found_location = temp_string.rfind("/");
136  if (found_location != string::npos)
137  temp_string = temp_string.substr(found_location);
138 
139  found_location = temp_string.find('_',initial_location);
140  while (found_location != string::npos) {
141  temp_string.replace(found_location,1," ");
142  initial_location = found_location+1;
143  found_location = temp_string.find('_',initial_location);
144  }
145  return temp_string;
146 }
147 
148 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
149 
150 string FGPropertyNode::GetFullyQualifiedName(void) const
151 {
152  string fqname;
153  const SGPropertyNode* node = this;
154  while(node) {
155  fqname = node->getDisplayName(true) + "/" + fqname;
156  node = node->getParent();
157  }
158 
159  // Remove the trailing slash if the node is not the root.
160  size_t len = std::max<size_t>(1, fqname.size()-1);
161  return fqname.substr(0, len);
162 }
163 
164 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
165 
166 string FGPropertyNode::GetRelativeName( const string &path ) const
167 {
168  string temp_string = GetFullyQualifiedName();
169  size_t len = path.length();
170  if ( (len > 0) && (temp_string.substr(0,len) == path) ) {
171  temp_string = temp_string.erase(0,len);
172  }
173  return temp_string;
174 }
175 
176 
177 
178 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
179 
180 bool FGPropertyNode::GetBool (const string &name, bool defaultValue) const
181 {
182  return getBoolValue(name.c_str(), defaultValue);
183 }
184 
185 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
186 
187 int FGPropertyNode::GetInt (const string &name, int defaultValue ) const
188 {
189  return getIntValue(name.c_str(), defaultValue);
190 }
191 
192 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
193 
194 int FGPropertyNode::GetLong (const string &name, long defaultValue ) const
195 {
196  return getLongValue(name.c_str(), defaultValue);
197 }
198 
199 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
200 
201 float FGPropertyNode::GetFloat (const string &name, float defaultValue ) const
202 {
203  return getFloatValue(name.c_str(), defaultValue);
204 }
205 
206 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
207 
208 double FGPropertyNode::GetDouble (const string &name, double defaultValue ) const
209 {
210  return getDoubleValue(name.c_str(), defaultValue);
211 }
212 
213 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
214 
215 string FGPropertyNode::GetString (const string &name, string defaultValue ) const
216 {
217  return string(getStringValue(name.c_str(), defaultValue.c_str()));
218 }
219 
220 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
221 
222 bool FGPropertyNode::SetBool (const string &name, bool val)
223 {
224  return setBoolValue(name.c_str(), val);
225 }
226 
227 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
228 
229 bool FGPropertyNode::SetInt (const string &name, int val)
230 {
231  return setIntValue(name.c_str(), val);
232 }
233 
234 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
235 
236 bool FGPropertyNode::SetLong (const string &name, long val)
237 {
238  return setLongValue(name.c_str(), val);
239 }
240 
241 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
242 
243 bool FGPropertyNode::SetFloat (const string &name, float val)
244 {
245  return setFloatValue(name.c_str(), val);
246 }
247 
248 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
249 
250 bool FGPropertyNode::SetDouble (const string &name, double val)
251 {
252  return setDoubleValue(name.c_str(), val);
253 }
254 
255 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
256 
257 bool FGPropertyNode::SetString (const string &name, const string &val)
258 {
259  return setStringValue(name.c_str(), val.c_str());
260 }
261 
262 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
263 
264 void FGPropertyNode::SetArchivable (const string &name, bool state )
265 {
266  SGPropertyNode * node = getNode(name.c_str());
267  if (node == 0)
268  cerr <<
269  "Attempt to set archive flag for non-existent property "
270  << name << endl;
271  else
272  node->setAttribute(SGPropertyNode::ARCHIVE, state);
273 }
274 
275 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
276 
277 void FGPropertyNode::SetReadable (const string &name, bool state )
278 {
279  SGPropertyNode * node = getNode(name.c_str());
280  if (node == 0)
281  cerr <<
282  "Attempt to set read flag for non-existant property "
283  << name << endl;
284  else
285  node->setAttribute(SGPropertyNode::READ, state);
286 }
287 
288 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
289 
290 void FGPropertyNode::SetWritable (const string &name, bool state )
291 {
292  SGPropertyNode * node = getNode(name.c_str());
293  if (node == 0)
294  cerr <<
295  "Attempt to set write flag for non-existant property "
296  << name << endl;
297  else
298  node->setAttribute(SGPropertyNode::WRITE, state);
299 }
300 
301 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
302 
303 void FGPropertyManager::Untie(const string &name)
304 {
305  SGPropertyNode* property = root->getNode(name.c_str());
306  if (!property) {
307  cerr << "Attempt to untie a non-existant property." << name << endl;
308  return;
309  }
310 
311  Untie(property);
312 }
313 
314 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
315 
316 void FGPropertyManager::Untie(SGPropertyNode *property)
317 {
318  const string& name = property->getNameString();
319 
320  assert(property->isTied());
321 
322  for (auto it = tied_properties.begin(); it != tied_properties.end(); ++it) {
323  if (it->node.ptr() == property) {
324  it->untie();
325  tied_properties.erase(it);
326  if (FGJSBBase::debug_lvl & 0x20) cout << "Untied " << name << endl;
327  return;
328  }
329  }
330 
331  cerr << "Failed to untie property " << name << endl
332  << "JSBSim is not the owner of this property." << endl;
333 }
334 } // namespace JSBSim
Class wrapper for property handling.