]> git.mxchange.org Git - simgear.git/commitdiff
Initial revision.
authorcurt <curt>
Mon, 3 Jul 2000 15:07:33 +0000 (15:07 +0000)
committercurt <curt>
Mon, 3 Jul 2000 15:07:33 +0000 (15:07 +0000)
simgear/misc/Makefile.am
simgear/misc/props.cxx [new file with mode: 0644]
simgear/misc/props.hxx [new file with mode: 0644]

index ee556730db2f4294f09f54aed4a381a15468e990..f2166e1fdea6e0828f6f9ec7f1ca15d1668d80aa 100644 (file)
@@ -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 (file)
index 0000000..8248a8a
--- /dev/null
@@ -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 <config.h>
+#endif
+
+#include <simgear/debug/logstream.hxx>
+
+#include "props.hxx"
+
+#include <stdlib.h>
+
+#include <string>
+
+using std::string;
+
+FGPropertyList current_properties;
+
+static string empty_string;
+
+
+\f
+////////////////////////////////////////////////////////////////////////
+// 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;
+  }
+}
+
+
+\f
+////////////////////////////////////////////////////////////////////////
+// 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 (file)
index 0000000..3980337
--- /dev/null
@@ -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 <string>
+#include <map>
+
+using std::string;
+using std::map;
+
+
+\f
+////////////////////////////////////////////////////////////////////////
+// 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;
+
+};
+
+
+\f
+////////////////////////////////////////////////////////////////////////
+// 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<string,FGValue>
+ *
+ * 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<string, FGValue> 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;
+};
+
+
+\f
+////////////////////////////////////////////////////////////////////////
+// Global property manager.
+////////////////////////////////////////////////////////////////////////
+
+extern FGPropertyList current_properties;
+
+
+#endif __PROPS_HXX