From 1c2289dacdc73847222655a4d5b1afd1cedccf21 Mon Sep 17 00:00:00 2001 From: curt Date: Mon, 3 Jul 2000 15:07:33 +0000 Subject: [PATCH] Initial revision. --- simgear/misc/Makefile.am | 2 + simgear/misc/props.cxx | 803 +++++++++++++++++++++++++++++++++++++++ simgear/misc/props.hxx | 295 ++++++++++++++ 3 files changed, 1100 insertions(+) create mode 100644 simgear/misc/props.cxx create mode 100644 simgear/misc/props.hxx diff --git a/simgear/misc/Makefile.am b/simgear/misc/Makefile.am index ee556730..f2166e1f 100644 --- a/simgear/misc/Makefile.am +++ b/simgear/misc/Makefile.am @@ -11,6 +11,7 @@ lib_LIBRARIES = libsgmisc.a include_HEADERS = \ fgpath.hxx \ fgstream.hxx \ + props.hxx \ stopwatch.hxx \ strutils.hxx \ texcoord.hxx \ @@ -19,6 +20,7 @@ include_HEADERS = \ libsgmisc_a_SOURCES = \ fgpath.cxx \ fgstream.cxx \ + props.cxx \ strutils.cxx \ texcoord.cxx \ zfstream.cxx diff --git a/simgear/misc/props.cxx b/simgear/misc/props.cxx new file mode 100644 index 00000000..8248a8ac --- /dev/null +++ b/simgear/misc/props.cxx @@ -0,0 +1,803 @@ +// props.cxx -- implementation of FGFS global properties. +// +// Copyright (C) 2000 David Megginson - david@megginson.com +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 2 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +// +// $Id$ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include + +#include "props.hxx" + +#include + +#include + +using std::string; + +FGPropertyList current_properties; + +static string empty_string; + + + +//////////////////////////////////////////////////////////////////////// +// Implementation of FGValue. +//////////////////////////////////////////////////////////////////////// + + +/** + * Construct a new value. + */ +FGValue::FGValue () + : _type(UNKNOWN), _tied(false) +{ +} + + +/** + * Destroy a value. + */ +FGValue::~FGValue () +{ + if (!_tied && _type == STRING) { + delete _value.string_val; + _value.string_val = 0; + } +} + + +bool +FGValue::getRawBool () const +{ + if (_tied) { + if (_value.bool_func.getter != 0) + return (*(_value.bool_func.getter))(); + else + return false; + } else { + return _value.bool_val; + } +} + + +int +FGValue::getRawInt () const +{ + if (_tied) { + if (_value.int_func.getter != 0) + return (*(_value.int_func.getter))(); + else + return 0; + } else { + return _value.int_val; + } +} + + +float +FGValue::getRawFloat () const +{ + if (_tied) { + if (_value.float_func.getter != 0) + return (*(_value.float_func.getter))(); + else + return 0.0; + } else { + return _value.float_val; + } +} + + +double +FGValue::getRawDouble () const +{ + if (_tied) { + if (_value.double_func.getter != 0) + return (*(_value.double_func.getter))(); + else + return 0.0L; + } else { + return _value.double_val; + } +} + + +const string & +FGValue::getRawString () const +{ + if (_tied) { + if (_value.string_func.getter != 0) + return (*(_value.string_func.getter))(); + else + return empty_string; + } else { + return *_value.string_val; + } +} + + +bool +FGValue::setRawBool (bool value) +{ + if (_tied) { + if (_value.bool_func.setter != 0) { + (*_value.bool_func.setter)(value); + return true; + } else { + return false; + } + } else { + _value.bool_val = value; + return true; + } +} + + +bool +FGValue::setRawInt (int value) +{ + if (_tied) { + if (_value.int_func.setter != 0) { + (*_value.int_func.setter)(value); + return true; + } else { + return false; + } + } else { + _value.int_val = value; + return true; + } +} + + +bool +FGValue::setRawFloat (float value) +{ + if (_tied) { + if (_value.float_func.setter != 0) { + (*_value.float_func.setter)(value); + return true; + } else { + return false; + } + } else { + _value.float_val = value; + return true; + } +} + + +bool +FGValue::setRawDouble (double value) +{ + if (_tied) { + if (_value.double_func.setter != 0) { + (*_value.double_func.setter)(value); + return true; + } else { + return false; + } + } else { + _value.double_val = value; + return true; + } +} + + +bool +FGValue::setRawString (const string &value) +{ + if (_tied) { + if (_value.string_func.setter != 0) { + (*_value.string_func.setter)(value); + return true; + } else { + return false; + } + } else { + if (_value.string_val == 0) + _value.string_val = new string; + *(_value.string_val) = value; + return true; + } +} + + +/** + * Attempt to get the boolean value of a property. + */ +bool +FGValue::getBoolValue () const +{ + switch (_type) { + case UNKNOWN: + return false; + case BOOL: + return getRawBool(); + case INT: + return (getRawInt() == 0 ? false : true); + case FLOAT: + return (getRawFloat() == 0.0 ? false : true); + case DOUBLE: + return (getRawDouble() == 0.0 ? false : true); + case STRING: + return (getRawString() == "false" ? false : true); + default: + return false; + } +} + + +/** + * Attempt to get the integer value of a property. + */ +int +FGValue::getIntValue () const +{ + switch (_type) { + case UNKNOWN: + return 0; + case BOOL: + return getRawBool(); + case INT: + return getRawInt(); + case FLOAT: + return (int)(getRawFloat()); + case DOUBLE: + return (int)(getRawDouble()); + case STRING: + return atoi(getRawString().c_str()); + default: + return 0; + } +} + + +/** + * Attempt to get the float value of a property. + */ +float +FGValue::getFloatValue () const +{ + switch (_type) { + case UNKNOWN: + return 0.0; + case BOOL: + return (float)(getRawBool()); + case INT: + return (float)(getRawInt()); + case FLOAT: + return getRawFloat(); + case DOUBLE: + return (float)(getRawDouble()); + case STRING: + return (float)atof(getRawString().c_str()); + default: + return 0.0; + } +} + + +/** + * Attempt to get the double value of a property. + */ +double +FGValue::getDoubleValue () const +{ + switch (_type) { + case UNKNOWN: + return 0.0; + case BOOL: + return (double)(getRawBool()); + case INT: + return (double)(getRawInt()); + case FLOAT: + return (double)(getRawFloat()); + case DOUBLE: + return getRawDouble(); + case STRING: + return atof(getRawString().c_str()); + default: + return 0.0; + } +} + + +/** + * Attempt to get the string value of a property. + */ +const string & +FGValue::getStringValue () const +{ + switch (_type) { + case UNKNOWN: + case BOOL: + case INT: + case FLOAT: + case DOUBLE: + return empty_string; + case STRING: + return getRawString(); + default: + return empty_string; + } +} + + +bool +FGValue::setBoolValue (bool value) +{ + if (_type == UNKNOWN || _type == BOOL) { + _type = BOOL; + return setRawBool(value); + } else { + return false; + } +} + + +bool +FGValue::setIntValue (int value) +{ + if (_type == UNKNOWN || _type == INT) { + _type = INT; + return setRawInt(value); + } else { + return false; + } +} + + +bool +FGValue::setFloatValue (float value) +{ + if (_type == UNKNOWN || _type == FLOAT) { + _type = FLOAT; + return setRawFloat(value); + } else { + return false; + } +} + + +bool +FGValue::setDoubleValue (double value) +{ + if (_type == UNKNOWN || _type == DOUBLE) { + _type = DOUBLE; + return setRawDouble(value); + } else { + return false; + } +} + + +bool +FGValue::setStringValue (const string &value) +{ + if (_type == UNKNOWN || _type == STRING) { + _type = STRING; + return setRawString(value); + } else { + return false; + } +} + + +bool +FGValue::tieBool (bool_getter getter, bool_setter setter = 0, + bool useDefault = true) +{ + if (_tied) { + return false; + } else { + if (useDefault && setter && _type != UNKNOWN) + (*setter)(getBoolValue()); + _tied = true; + _type = BOOL; + _value.bool_func.getter = getter; + _value.bool_func.setter = setter; + return true; + } +} + + +bool +FGValue::tieInt (int_getter getter, int_setter setter = 0, + bool useDefault = true) +{ + if (_tied) { + return false; + } else { + if (useDefault && setter && _type != UNKNOWN) + (*setter)(getIntValue()); + _tied = true; + _type = INT; + _value.int_func.getter = getter; + _value.int_func.setter = setter; + return true; + } +} + + +bool +FGValue::tieFloat (float_getter getter, float_setter setter = 0, + bool useDefault = true) +{ + if (_tied) { + return false; + } else { + if (useDefault && setter && _type != UNKNOWN) + (*setter)(getFloatValue()); + _tied = true; + _type = FLOAT; + _value.float_func.getter = getter; + _value.float_func.setter = setter; + return true; + } +} + + +bool +FGValue::tieDouble (double_getter getter, double_setter setter = 0, + bool useDefault = true) +{ + if (_tied) { + return false; + } else { + if (useDefault && setter && _type != UNKNOWN) + (*setter)(getDoubleValue()); + _tied = true; + _type = DOUBLE; + _value.double_func.getter = getter; + _value.double_func.setter = setter; + return true; + } +} + + +bool +FGValue::tieString (string_getter getter, string_setter setter = 0, + bool useDefault = true) +{ + if (_tied) { + return false; + } else { + if (useDefault && setter && _type != UNKNOWN) + (*setter)(getStringValue()); + if (_type == STRING) + delete _value.string_val; + _tied = true; + _type = STRING; + _value.string_func.getter = getter; + _value.string_func.setter = setter; + return true; + } +} + + +bool +FGValue::untieBool () +{ + if (_tied && _type == BOOL) { + bool value = getRawBool(); + _value.bool_val = value; + _tied = false; + return true; + } else { + return false; + } +} + + +bool +FGValue::untieInt () +{ + if (_tied && _type == INT) { + int value = getRawInt(); + _value.int_val = value; + _tied = false; + return true; + } else { + return false; + } +} + + +bool +FGValue::untieFloat () +{ + if (_tied && _type == FLOAT) { + float value = getRawFloat(); + _value.float_val = value; + _tied = false; + return true; + } else { + return false; + } +} + + +bool +FGValue::untieDouble () +{ + if (_tied && _type == DOUBLE) { + double value = getRawDouble(); + _value.double_val = value; + _tied = false; + return true; + } else { + return false; + } +} + + +bool +FGValue::untieString () +{ + if (_tied && _type == STRING) { + const string &value = getRawString(); + _value.string_val = new string(value); + _tied = false; + return true; + } else { + return false; + } +} + + + +//////////////////////////////////////////////////////////////////////// +// Implementation of FGPropertyList. +//////////////////////////////////////////////////////////////////////// + +FGPropertyList::FGPropertyList () +{ +} + +FGPropertyList::~FGPropertyList () +{ +} + + +FGValue * +FGPropertyList::getValue (const string &name, bool create = false) +{ + const_iterator el = _props.find(name); + if (el == _props.end()) { + if (!create) + return 0; + else { + FG_LOG(FG_GENERAL, FG_INFO, "Creating new property '" << name << '\''); + } + } + return &(_props[name]); +} + + +const FGValue * +FGPropertyList::getValue (const string &name) const +{ + value_map::const_iterator el = _props.find(name); + return &(el->second); +} + + +bool +FGPropertyList::getBoolValue (const string &name) const +{ + const FGValue * val = getValue(name); + if (val == 0) + return false; + else + return val->getBoolValue(); +} + + +int +FGPropertyList::getIntValue (const string &name) const +{ + const FGValue * val = getValue(name); + if (val == 0) + return 0; + else + return val->getIntValue(); +} + + +float +FGPropertyList::getFloatValue (const string &name) const +{ + const FGValue * val = getValue(name); + if (val == 0) + return 0.0; + else + return val->getFloatValue(); +} + + +double +FGPropertyList::getDoubleValue (const string &name) const +{ + const FGValue * val = getValue(name); + if (val == 0) + return 0.0; + else + return val->getDoubleValue(); +} + + +const string & +FGPropertyList::getStringValue (const string &name) const +{ + const FGValue * val = getValue(name); + if (val == 0) + return empty_string; + else + return val->getStringValue(); +} + + +bool +FGPropertyList::setBoolValue (const string &name, bool value) +{ + return getValue(name, true)->setBoolValue(value); +} + + +bool +FGPropertyList::setIntValue (const string &name, int value) +{ + return getValue(name, true)->setIntValue(value); +} + + +bool +FGPropertyList::setFloatValue (const string &name, float value) +{ + return getValue(name, true)->setFloatValue(value); +} + + +bool +FGPropertyList::setDoubleValue (const string &name, double value) +{ + return getValue(name, true)->setDoubleValue(value); +} + + +bool +FGPropertyList::setStringValue (const string &name, const string &value) +{ + return getValue(name, true)->setStringValue(value); +} + + +bool +FGPropertyList::tieBool (const string &name, + bool_getter getter, + bool_setter setter, + bool useDefault = true) +{ + FG_LOG(FG_GENERAL, FG_INFO, "Tying bool property '" << name << '\''); + return getValue(name, true)->tieBool(getter, setter, useDefault); +} + + +bool +FGPropertyList::tieInt (const string &name, + int_getter getter, + int_setter setter, + bool useDefault = true) +{ + FG_LOG(FG_GENERAL, FG_INFO, "Tying int property '" << name << '\''); + return getValue(name, true)->tieInt(getter, setter, useDefault); +} + + +bool +FGPropertyList::tieFloat (const string &name, + float_getter getter, + float_setter setter, + bool useDefault = true) +{ + FG_LOG(FG_GENERAL, FG_INFO, "Tying float property '" << name << '\''); + return getValue(name, true)->tieFloat(getter, setter, useDefault); +} + + +bool +FGPropertyList::tieDouble (const string &name, + double_getter getter, + double_setter setter, + bool useDefault = true) +{ + FG_LOG(FG_GENERAL, FG_INFO, "Tying double property '" << name << '\''); + return getValue(name, true)->tieDouble(getter, setter, useDefault); +} + + +bool +FGPropertyList::tieString (const string &name, + string_getter getter, + string_setter setter, + bool useDefault = true) +{ + FG_LOG(FG_GENERAL, FG_INFO, "Tying string property '" << name << '\''); + return getValue(name, true)->tieString(getter, setter, useDefault); +} + + +bool +FGPropertyList::untieBool (const string &name) +{ + FG_LOG(FG_GENERAL, FG_INFO, "Untying bool property '" << name << '\''); + return getValue(name, true)->untieBool(); +} + + +bool +FGPropertyList::untieInt (const string &name) +{ + FG_LOG(FG_GENERAL, FG_INFO, "Untying int property '" << name << '\''); + return getValue(name, true)->untieInt(); +} + + +bool +FGPropertyList::untieFloat (const string &name) +{ + FG_LOG(FG_GENERAL, FG_INFO, "Untying float property '" << name << '\''); + return getValue(name, true)->untieFloat(); +} + + +bool +FGPropertyList::untieDouble (const string &name) +{ + FG_LOG(FG_GENERAL, FG_INFO, "Untying double property '" << name << '\''); + return getValue(name, true)->untieDouble(); +} + + +bool +FGPropertyList::untieString (const string &name) +{ + FG_LOG(FG_GENERAL, FG_INFO, "Untying string property '" << name << '\''); + return getValue(name, true)->untieString(); +} + + +void +FGPropertyList::dumpToLog () const +{ + const_iterator it = FGPropertyList::begin(); + FG_LOG(FG_GENERAL, FG_INFO, "Begin property list dump..."); + while (it != end()) { + FG_LOG(FG_GENERAL, FG_INFO, "Property: " << it->first); + it++; + } + FG_LOG(FG_GENERAL, FG_INFO, "...End property list dump"); +} + + + +// end of props.cxx diff --git a/simgear/misc/props.hxx b/simgear/misc/props.hxx new file mode 100644 index 00000000..3980337b --- /dev/null +++ b/simgear/misc/props.hxx @@ -0,0 +1,295 @@ +// props.hxx -- class to manage global FlightGear properties. +// +// Copyright (C) 2000 David Megginson - david@megginson.com +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 2 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +// +// $Id$ + + +#ifndef __PROPS_HXX +#define __PROPS_HXX + +#include +#include + +using std::string; +using std::map; + + + +//////////////////////////////////////////////////////////////////////// +// Values. +//////////////////////////////////////////////////////////////////////// + +/** + * Abstract representation of a FlightGear value. + * + * This value is designed to be fairly robust -- it can exist without + * a specified value, it can be any of several types, and it can + * be tied to an external variable without disrupting any existing + * pointers or references to the value. Some basic type conversions + * are also handled automatically. + * + * Values also have attributes that control whether they can be read + * from, written to, or archived (i.e. saved to disk). + */ +class FGValue +{ +public: + + // External getters + typedef bool (*bool_getter)(); + typedef int (*int_getter)(); + typedef float (*float_getter)(); + typedef double (*double_getter)(); + typedef const string &(*string_getter)(); + + // External setters + typedef void (*bool_setter)(bool); + typedef void (*int_setter)(int); + typedef void (*float_setter)(float); + typedef void (*double_setter)(double); + typedef void (*string_setter)(const string &); + + enum Type { + UNKNOWN, // no value assigned yet + BOOL, // boolean + INT, // integer + FLOAT, // floating point + DOUBLE, // double precision + STRING // text + }; + + FGValue (); + virtual ~FGValue (); + + // Meta information. + virtual Type getType () const { return _type; } + virtual bool isTied () const { return _tied; } + + // Accessors. + virtual bool getBoolValue () const; + virtual int getIntValue () const; + virtual float getFloatValue () const; + virtual double getDoubleValue () const; + virtual const string &getStringValue () const; + + // Setters. + virtual bool setBoolValue (bool value); + virtual bool setIntValue (int value); + virtual bool setFloatValue (float value); + virtual bool setDoubleValue (double value); + virtual bool setStringValue (const string &value); + + // Tie to external variables. + virtual bool tieBool (bool_getter getter, + bool_setter setter = 0, + bool useDefault = true); + virtual bool tieInt (int_getter getter, + int_setter setter = 0, + bool useDefault = true); + virtual bool tieFloat (float_getter getter, + float_setter setter = 0, + bool useDefault = true); + virtual bool tieDouble (double_getter getter, + double_setter setter = 0, + bool useDefault = true); + virtual bool tieString (string_getter getter, + string_setter setter = 0, + bool useDefault = true); + + // Untie from external variables. + virtual bool untieBool (); + virtual bool untieInt (); + virtual bool untieFloat (); + virtual bool untieDouble (); + virtual bool untieString (); + +protected: + + bool getRawBool () const; + int getRawInt () const; + float getRawFloat () const; + double getRawDouble () const; + const string &getRawString () const; + + bool setRawBool (bool value); + bool setRawInt (int value); + bool setRawFloat (float value); + bool setRawDouble (double value); + bool setRawString (const string & value); + +private: + + Type _type; + bool _tied; + + // The value is one of the following... + union { + + bool bool_val; + int int_val; + float float_val; + double double_val; + string * string_val; + + struct { + bool_setter setter; + bool_getter getter; + } bool_func; + + struct { + int_setter setter; + int_getter getter; + } int_func; + + struct { + void * obj; + float_setter setter; + float_getter getter; + } float_func; + + struct { + void * obj; + double_setter setter; + double_getter getter; + } double_func; + + struct { + string_setter setter; + string_getter getter; + } string_func; + + } _value; + +}; + + + +//////////////////////////////////////////////////////////////////////// +// Top-level manager. +//////////////////////////////////////////////////////////////////////// + + +/** + * A list of FlightGear properties. + * + * This list associates names (conventional written as paths, + * i.e. "/foo/bar/hack") with FGValue classes. Once an FGValue + * object is associated with the name, the association is + * permanent -- it is safe to keep a pointer or reference. + * however, that the type of a value may change if it is tied + * to a variable. + * + * When iterating through the list, the value type is + * + * pair + * + * To get the name from a const_iterator, use + * + * it->first + * + * and to get the value from a const_iterator, use + * + * it->second + */ +class FGPropertyList +{ +public: + typedef map value_map; + + typedef FGValue::bool_getter bool_getter; + typedef FGValue::int_getter int_getter; + typedef FGValue::float_getter float_getter; + typedef FGValue::double_getter double_getter; + typedef FGValue::string_getter string_getter; + + typedef FGValue::bool_setter bool_setter; + typedef FGValue::int_setter int_setter; + typedef FGValue::float_setter float_setter; + typedef FGValue::double_setter double_setter; + typedef FGValue::string_setter string_setter; + + typedef value_map::value_type value_type; + typedef value_map::size_type size_type; + typedef value_map::const_iterator const_iterator; + + FGPropertyList (); + virtual ~FGPropertyList (); + + virtual size_type size () const { return _props.size(); } + + virtual const_iterator begin () const { return _props.begin(); } + virtual const_iterator end () const { return _props.end(); } + + virtual FGValue * getValue (const string &name, bool create = false); + virtual const FGValue * getValue (const string &name) const; + + virtual bool getBoolValue (const string &name) const; + virtual int getIntValue (const string &name) const; + virtual float getFloatValue (const string &name) const; + virtual double getDoubleValue (const string &name) const; + virtual const string &getStringValue (const string &name) const; + + virtual bool setBoolValue (const string &name, bool value); + virtual bool setIntValue (const string &name, int value); + virtual bool setFloatValue (const string &name, float value); + virtual bool setDoubleValue (const string &name, double value); + virtual bool setStringValue (const string &name, const string &value); + + virtual bool tieBool (const string &name, + bool_getter getter, + bool_setter setter = 0, + bool useDefault = true); + virtual bool tieInt (const string &name, + int_getter getter, + int_setter setter = 0, + bool useDefault = true); + virtual bool tieFloat (const string &name, + float_getter getter, + float_setter setter = 0, + bool useDefault = true); + virtual bool tieDouble (const string &name, + double_getter getter, + double_setter setter = 0, + bool useDefault = true); + virtual bool tieString (const string &name, + string_getter getter, + string_setter setter = 0, + bool useDefault = true); + + virtual bool untieBool (const string &name); + virtual bool untieInt (const string &name); + virtual bool untieFloat (const string &name); + virtual bool untieDouble (const string &name); + virtual bool untieString (const string &name); + + virtual void dumpToLog () const; + +private: + value_map _props; +}; + + + +//////////////////////////////////////////////////////////////////////// +// Global property manager. +//////////////////////////////////////////////////////////////////////// + +extern FGPropertyList current_properties; + + +#endif __PROPS_HXX -- 2.39.5