]> git.mxchange.org Git - simgear.git/blob - simgear/misc/props.cxx
8248a8acc580671ba9dd1e3a9013a2bf36351ec1
[simgear.git] / simgear / misc / props.cxx
1 // props.cxx -- implementation of FGFS global properties.
2 //
3 // Copyright (C) 2000  David Megginson - david@megginson.com
4 //
5 // This program is free software; you can redistribute it and/or
6 // modify it under the terms of the GNU General Public License as
7 // published by the Free Software Foundation; either version 2 of the
8 // License, or (at your option) any later version.
9 //
10 // This program is distributed in the hope that it will be useful, but
11 // WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13 // General Public License for more details.
14 //
15 // You should have received a copy of the GNU General Public License
16 // along with this program; if not, write to the Free Software
17 // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 //
19 // $Id$
20
21 #ifdef HAVE_CONFIG_H
22 #  include <config.h>
23 #endif
24
25 #include <simgear/debug/logstream.hxx>
26
27 #include "props.hxx"
28
29 #include <stdlib.h>
30
31 #include <string>
32
33 using std::string;
34
35 FGPropertyList current_properties;
36
37 static string empty_string;
38
39
40 \f
41 ////////////////////////////////////////////////////////////////////////
42 // Implementation of FGValue.
43 ////////////////////////////////////////////////////////////////////////
44
45
46 /**
47  * Construct a new value.
48  */
49 FGValue::FGValue ()
50   : _type(UNKNOWN), _tied(false)
51 {
52 }
53
54
55 /**
56  * Destroy a value.
57  */
58 FGValue::~FGValue ()
59 {
60   if (!_tied && _type == STRING) {
61     delete _value.string_val;
62     _value.string_val = 0;
63   }
64 }
65
66
67 bool
68 FGValue::getRawBool () const
69 {
70   if (_tied) {
71     if (_value.bool_func.getter != 0)
72       return (*(_value.bool_func.getter))();
73     else
74       return false;
75   } else {
76     return _value.bool_val;
77   }
78 }
79
80
81 int
82 FGValue::getRawInt () const
83 {
84   if (_tied) {
85     if (_value.int_func.getter != 0)
86       return (*(_value.int_func.getter))();
87     else
88       return 0;
89   } else {
90     return _value.int_val;
91   }
92 }
93
94
95 float
96 FGValue::getRawFloat () const
97 {
98   if (_tied) {
99     if (_value.float_func.getter != 0)
100       return (*(_value.float_func.getter))();
101     else
102       return 0.0;
103   } else {
104     return _value.float_val;
105   }
106 }
107
108
109 double
110 FGValue::getRawDouble () const
111 {
112   if (_tied) {
113     if (_value.double_func.getter != 0)
114       return (*(_value.double_func.getter))();
115     else
116       return 0.0L;
117   } else {
118     return _value.double_val;
119   }
120 }
121
122
123 const string &
124 FGValue::getRawString () const
125 {
126   if (_tied) {
127     if (_value.string_func.getter != 0)
128       return (*(_value.string_func.getter))();
129     else
130       return empty_string;
131   } else {
132     return *_value.string_val;
133   }
134 }
135
136
137 bool
138 FGValue::setRawBool (bool value)
139 {
140   if (_tied) {
141     if (_value.bool_func.setter != 0) {
142       (*_value.bool_func.setter)(value);
143       return true;
144     } else {
145       return false;
146     }
147   } else {
148     _value.bool_val = value;
149     return true;
150   }
151 }
152
153
154 bool
155 FGValue::setRawInt (int value)
156 {
157   if (_tied) {
158     if (_value.int_func.setter != 0) {
159       (*_value.int_func.setter)(value);
160       return true;
161     } else {
162       return false;
163     }
164   } else {
165     _value.int_val = value;
166     return true;
167   }
168 }
169
170
171 bool
172 FGValue::setRawFloat (float value)
173 {
174   if (_tied) {
175     if (_value.float_func.setter != 0) {
176       (*_value.float_func.setter)(value);
177       return true;
178     } else {
179       return false;
180     }
181   } else {
182     _value.float_val = value;
183     return true;
184   }
185 }
186
187
188 bool
189 FGValue::setRawDouble (double value)
190 {
191   if (_tied) {
192     if (_value.double_func.setter != 0) {
193       (*_value.double_func.setter)(value);
194       return true;
195     } else {
196       return false;
197     }
198   } else {
199     _value.double_val = value;
200     return true;
201   }
202 }
203
204
205 bool
206 FGValue::setRawString (const string &value)
207 {
208   if (_tied) {
209     if (_value.string_func.setter != 0) {
210       (*_value.string_func.setter)(value);
211       return true;
212     } else {
213       return false;
214     }
215   } else {
216     if (_value.string_val == 0)
217       _value.string_val = new string;
218     *(_value.string_val) = value;
219     return true;
220   }
221 }
222
223
224 /**
225  * Attempt to get the boolean value of a property.
226  */
227 bool
228 FGValue::getBoolValue () const
229 {
230   switch (_type) {
231   case UNKNOWN:
232     return false;
233   case BOOL:
234     return getRawBool();
235   case INT:
236     return (getRawInt() == 0 ? false : true);
237   case FLOAT:
238     return (getRawFloat() == 0.0 ? false : true);
239   case DOUBLE:
240     return (getRawDouble() == 0.0 ? false : true);
241   case STRING:
242     return (getRawString() == "false" ? false : true);
243   default:
244     return false;
245   }
246 }
247
248
249 /**
250  * Attempt to get the integer value of a property.
251  */
252 int
253 FGValue::getIntValue () const
254 {
255   switch (_type) {
256   case UNKNOWN:
257     return 0;
258   case BOOL:
259     return getRawBool();
260   case INT:
261     return getRawInt();
262   case FLOAT:
263     return (int)(getRawFloat());
264   case DOUBLE:
265     return (int)(getRawDouble());
266   case STRING:
267     return atoi(getRawString().c_str());
268   default:
269     return 0;
270   }
271 }
272
273
274 /**
275  * Attempt to get the float value of a property.
276  */
277 float
278 FGValue::getFloatValue () const
279 {
280   switch (_type) {
281   case UNKNOWN:
282     return 0.0;
283   case BOOL:
284     return (float)(getRawBool());
285   case INT:
286     return (float)(getRawInt());
287   case FLOAT:
288     return getRawFloat();
289   case DOUBLE:
290     return (float)(getRawDouble());
291   case STRING:
292     return (float)atof(getRawString().c_str());
293   default:
294     return 0.0;
295   }
296 }
297
298
299 /**
300  * Attempt to get the double value of a property.
301  */
302 double
303 FGValue::getDoubleValue () const
304 {
305   switch (_type) {
306   case UNKNOWN:
307     return 0.0;
308   case BOOL:
309     return (double)(getRawBool());
310   case INT:
311     return (double)(getRawInt());
312   case FLOAT:
313     return (double)(getRawFloat());
314   case DOUBLE:
315     return getRawDouble();
316   case STRING:
317     return atof(getRawString().c_str());
318   default:
319     return 0.0;
320   }
321 }
322
323
324 /**
325  * Attempt to get the string value of a property.
326  */
327 const string &
328 FGValue::getStringValue () const
329 {
330   switch (_type) {
331   case UNKNOWN:
332   case BOOL:
333   case INT:
334   case FLOAT:
335   case DOUBLE:
336     return empty_string;
337   case STRING:
338     return getRawString();
339   default:
340     return empty_string;
341   }
342 }
343
344
345 bool
346 FGValue::setBoolValue (bool value)
347 {
348   if (_type == UNKNOWN || _type == BOOL) {
349     _type = BOOL;
350     return setRawBool(value);
351   } else {
352     return false;
353   }
354 }
355
356
357 bool
358 FGValue::setIntValue (int value)
359 {
360   if (_type == UNKNOWN || _type == INT) {
361     _type = INT;
362     return setRawInt(value);
363   } else {
364     return false;
365   }
366 }
367
368
369 bool
370 FGValue::setFloatValue (float value)
371 {
372   if (_type == UNKNOWN || _type == FLOAT) {
373     _type = FLOAT;
374     return setRawFloat(value);
375   } else {
376     return false;
377   }
378 }
379
380
381 bool
382 FGValue::setDoubleValue (double value)
383 {
384   if (_type == UNKNOWN || _type == DOUBLE) {
385     _type = DOUBLE;
386     return setRawDouble(value);
387   } else {
388     return false;
389   }
390 }
391
392
393 bool
394 FGValue::setStringValue (const string &value)
395 {
396   if (_type == UNKNOWN || _type == STRING) {
397     _type = STRING;
398     return setRawString(value);
399   } else {
400     return false;
401   }
402 }
403
404
405 bool
406 FGValue::tieBool (bool_getter getter, bool_setter setter = 0,
407                   bool useDefault = true)
408 {
409   if (_tied) {
410     return false;
411   } else {
412     if (useDefault && setter && _type != UNKNOWN)
413       (*setter)(getBoolValue());
414     _tied = true;
415     _type = BOOL;
416     _value.bool_func.getter = getter;
417     _value.bool_func.setter = setter;
418     return true;
419   }
420 }
421
422
423 bool
424 FGValue::tieInt (int_getter getter, int_setter setter = 0,
425                  bool useDefault = true)
426 {
427   if (_tied) {
428     return false;
429   } else {
430     if (useDefault && setter && _type != UNKNOWN)
431       (*setter)(getIntValue());
432     _tied = true;
433     _type = INT;
434     _value.int_func.getter = getter;
435     _value.int_func.setter = setter;
436     return true;
437   }
438 }
439
440
441 bool
442 FGValue::tieFloat (float_getter getter, float_setter setter = 0,
443                    bool useDefault = true)
444 {
445   if (_tied) {
446     return false;
447   } else {
448     if (useDefault && setter && _type != UNKNOWN)
449       (*setter)(getFloatValue());
450     _tied = true;
451     _type = FLOAT;
452     _value.float_func.getter = getter;
453     _value.float_func.setter = setter;
454     return true;
455   }
456 }
457
458
459 bool
460 FGValue::tieDouble (double_getter getter, double_setter setter = 0,
461                     bool useDefault = true)
462 {
463   if (_tied) {
464     return false;
465   } else {
466     if (useDefault && setter && _type != UNKNOWN)
467       (*setter)(getDoubleValue());
468     _tied = true;
469     _type = DOUBLE;
470     _value.double_func.getter = getter;
471     _value.double_func.setter = setter;
472     return true;
473   }
474 }
475
476
477 bool
478 FGValue::tieString (string_getter getter, string_setter setter = 0,
479                     bool useDefault = true)
480 {
481   if (_tied) {
482     return false;
483   } else {
484     if (useDefault && setter && _type != UNKNOWN)
485       (*setter)(getStringValue());
486     if (_type == STRING)
487       delete _value.string_val;
488     _tied = true;
489     _type = STRING;
490     _value.string_func.getter = getter;
491     _value.string_func.setter = setter;
492     return true;
493   }
494 }
495
496
497 bool
498 FGValue::untieBool ()
499 {
500   if (_tied && _type == BOOL) {
501     bool value = getRawBool();
502     _value.bool_val = value;
503     _tied = false;
504     return true;
505   } else {
506     return false;
507   }
508 }
509
510
511 bool
512 FGValue::untieInt ()
513 {
514   if (_tied && _type == INT) {
515     int value = getRawInt();
516     _value.int_val = value;
517     _tied = false;
518     return true;
519   } else {
520     return false;
521   }
522 }
523
524
525 bool
526 FGValue::untieFloat ()
527 {
528   if (_tied && _type == FLOAT) {
529     float value = getRawFloat();
530     _value.float_val = value;
531     _tied = false;
532     return true;
533   } else {
534     return false;
535   }
536 }
537
538
539 bool
540 FGValue::untieDouble ()
541 {
542   if (_tied && _type == DOUBLE) {
543     double value = getRawDouble();
544     _value.double_val = value;
545     _tied = false;
546     return true;
547   } else {
548     return false;
549   }
550 }
551
552
553 bool
554 FGValue::untieString ()
555 {
556   if (_tied && _type == STRING) {
557     const string &value = getRawString();
558     _value.string_val = new string(value);
559     _tied = false;
560     return true;
561   } else {
562     return false;
563   }
564 }
565
566
567 \f
568 ////////////////////////////////////////////////////////////////////////
569 // Implementation of FGPropertyList.
570 ////////////////////////////////////////////////////////////////////////
571
572 FGPropertyList::FGPropertyList ()
573 {
574 }
575
576 FGPropertyList::~FGPropertyList ()
577 {
578 }
579
580
581 FGValue *
582 FGPropertyList::getValue (const string &name, bool create = false)
583 {
584   const_iterator el = _props.find(name);
585   if (el == _props.end()) {
586     if (!create)
587       return 0;
588     else {
589       FG_LOG(FG_GENERAL, FG_INFO, "Creating new property '" << name << '\'');
590     }
591   }
592   return &(_props[name]);
593 }
594
595
596 const FGValue *
597 FGPropertyList::getValue (const string &name) const
598 {
599   value_map::const_iterator el = _props.find(name);
600   return &(el->second);
601 }
602
603
604 bool
605 FGPropertyList::getBoolValue (const string &name) const
606 {
607   const FGValue * val = getValue(name);
608   if (val == 0)
609     return false;
610   else
611     return val->getBoolValue();
612 }
613
614
615 int
616 FGPropertyList::getIntValue (const string &name) const
617 {
618   const FGValue * val = getValue(name);
619   if (val == 0)
620     return 0;
621   else
622     return val->getIntValue();
623 }
624
625
626 float
627 FGPropertyList::getFloatValue (const string &name) const
628 {
629   const FGValue * val = getValue(name);
630   if (val == 0)
631     return 0.0;
632   else
633     return val->getFloatValue();
634 }
635
636
637 double
638 FGPropertyList::getDoubleValue (const string &name) const
639 {
640   const FGValue * val = getValue(name);
641   if (val == 0)
642     return 0.0;
643   else
644     return val->getDoubleValue();
645 }
646
647
648 const string &
649 FGPropertyList::getStringValue (const string &name) const
650 {
651   const FGValue * val = getValue(name);
652   if (val == 0)
653     return empty_string;
654   else
655     return val->getStringValue();
656 }
657
658
659 bool
660 FGPropertyList::setBoolValue (const string &name, bool value)
661 {
662   return getValue(name, true)->setBoolValue(value);
663 }
664
665
666 bool
667 FGPropertyList::setIntValue (const string &name, int value)
668 {
669   return getValue(name, true)->setIntValue(value);
670 }
671
672
673 bool
674 FGPropertyList::setFloatValue (const string &name, float value)
675 {
676   return getValue(name, true)->setFloatValue(value);
677 }
678
679
680 bool
681 FGPropertyList::setDoubleValue (const string &name, double value)
682 {
683   return getValue(name, true)->setDoubleValue(value);
684 }
685
686
687 bool
688 FGPropertyList::setStringValue (const string &name, const string &value)
689 {
690   return getValue(name, true)->setStringValue(value);
691 }
692
693
694 bool
695 FGPropertyList::tieBool (const string &name, 
696                          bool_getter getter,
697                          bool_setter setter,
698                          bool useDefault = true)
699 {
700   FG_LOG(FG_GENERAL, FG_INFO, "Tying bool property '" << name << '\'');
701   return getValue(name, true)->tieBool(getter, setter, useDefault);
702 }
703
704
705 bool
706 FGPropertyList::tieInt (const string &name, 
707                         int_getter getter,
708                         int_setter setter,
709                         bool useDefault = true)
710 {
711   FG_LOG(FG_GENERAL, FG_INFO, "Tying int property '" << name << '\'');
712   return getValue(name, true)->tieInt(getter, setter, useDefault);
713 }
714
715
716 bool
717 FGPropertyList::tieFloat (const string &name, 
718                           float_getter getter,
719                           float_setter setter,
720                           bool useDefault = true)
721 {
722   FG_LOG(FG_GENERAL, FG_INFO, "Tying float property '" << name << '\'');
723   return getValue(name, true)->tieFloat(getter, setter, useDefault);
724 }
725
726
727 bool
728 FGPropertyList::tieDouble (const string &name, 
729                            double_getter getter,
730                            double_setter setter,
731                            bool useDefault = true)
732 {
733   FG_LOG(FG_GENERAL, FG_INFO, "Tying double property '" << name << '\'');
734   return getValue(name, true)->tieDouble(getter, setter, useDefault);
735 }
736
737
738 bool
739 FGPropertyList::tieString (const string &name, 
740                            string_getter getter,
741                            string_setter setter,
742                            bool useDefault = true)
743 {
744   FG_LOG(FG_GENERAL, FG_INFO, "Tying string property '" << name << '\'');
745   return getValue(name, true)->tieString(getter, setter, useDefault);
746 }
747
748
749 bool
750 FGPropertyList::untieBool (const string &name)
751 {
752   FG_LOG(FG_GENERAL, FG_INFO, "Untying bool property '" << name << '\'');
753   return getValue(name, true)->untieBool();
754 }
755
756
757 bool
758 FGPropertyList::untieInt (const string &name)
759 {
760   FG_LOG(FG_GENERAL, FG_INFO, "Untying int property '" << name << '\'');
761   return getValue(name, true)->untieInt();
762 }
763
764
765 bool
766 FGPropertyList::untieFloat (const string &name)
767 {
768   FG_LOG(FG_GENERAL, FG_INFO, "Untying float property '" << name << '\'');
769   return getValue(name, true)->untieFloat();
770 }
771
772
773 bool
774 FGPropertyList::untieDouble (const string &name)
775 {
776   FG_LOG(FG_GENERAL, FG_INFO, "Untying double property '" << name << '\'');
777   return getValue(name, true)->untieDouble();
778 }
779
780
781 bool
782 FGPropertyList::untieString (const string &name)
783 {
784   FG_LOG(FG_GENERAL, FG_INFO, "Untying string property '" << name << '\'');
785   return getValue(name, true)->untieString();
786 }
787
788
789 void
790 FGPropertyList::dumpToLog () const
791 {
792   const_iterator it = FGPropertyList::begin();
793   FG_LOG(FG_GENERAL, FG_INFO, "Begin property list dump...");
794   while (it != end()) {
795     FG_LOG(FG_GENERAL, FG_INFO, "Property: " << it->first);
796     it++;
797   }
798   FG_LOG(FG_GENERAL, FG_INFO, "...End property list dump");
799 }
800
801
802
803 // end of props.cxx