Initial revision.

This commit is contained in:
curt 2000-07-03 15:07:33 +00:00
parent 044ac5d5d3
commit 1c2289dacd
3 changed files with 1100 additions and 0 deletions

View 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

803
simgear/misc/props.cxx Normal file
View File

@ -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;
////////////////////////////////////////////////////////////////////////
// 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

295
simgear/misc/props.hxx Normal file
View File

@ -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;
////////////////////////////////////////////////////////////////////////
// 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<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;
};
////////////////////////////////////////////////////////////////////////
// Global property manager.
////////////////////////////////////////////////////////////////////////
extern FGPropertyList current_properties;
#endif __PROPS_HXX