X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=simgear%2Fmisc%2Fprops.hxx;h=b9a0157ac4bca01f341913748546a7357ce5c5cd;hb=5bab565cfe4c30d6cf08ecaba50af74d5e4f0c98;hp=ebaaf7f29e40f4b3973e8d24da5ad08a34ae5993;hpb=a1bf8d22297416de9524370f4c0d4f0f0c9e89d4;p=simgear.git diff --git a/simgear/misc/props.hxx b/simgear/misc/props.hxx index ebaaf7f2..b9a0157a 100644 --- a/simgear/misc/props.hxx +++ b/simgear/misc/props.hxx @@ -1,34 +1,45 @@ -// props.hxx -- declaration of SimGear Property Manager. -// -// Written by David Megginson - david@megginson.com -// -// This module is in the PUBLIC DOMAIN. -// -// 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 props.html for documentation [replace with URL when available]. -// -// $Id$ +/** + * \file props.hxx + * Interface definition for a property list. + * Started Fall 2000 by David Megginson, david@megginson.com + * This code is released into the Public Domain. + * + * See props.html for documentation [replace with URL when available]. + * + * $Id$ + */ #ifndef __PROPS_HXX #define __PROPS_HXX +#include + #include -#include -#include -#include +#include STL_STRING +#include +#include STL_IOSTREAM -using std::string; -using std::map; -using std::istream; -using std::ostream; +SG_USING_STD(string); +SG_USING_STD(vector); +#if !defined(SG_HAVE_NATIVE_SGI_COMPILERS) +SG_USING_STD(istream); +SG_USING_STD(ostream); +#endif + +#ifdef NONE +#pragma warn A sloppy coder has defined NONE as a macro! +#undef NONE +#endif + +#ifdef ALIAS +#pragma warn A sloppy coder has defined ALIAS as a macro! +#undef ALIAS +#endif -#ifdef UNKNOWN -#pragma warn A sloppy coder has defined UNKNOWN as a macro! -#undef UNKNOWN +#ifdef UNSPECIFIED +#pragma warn A sloppy coder has defined UNSPECIFIED as a macro! +#undef UNSPECIFIED #endif #ifdef BOOL @@ -41,6 +52,11 @@ using std::ostream; #undef INT #endif +#ifdef LONG +#pragma warn A sloppy coder has defined LONG as a macro! +#undef LONG +#endif + #ifdef FLOAT #pragma warn A sloppy coder has defined FLOAT as a macro! #undef FLOAT @@ -59,364 +75,1051 @@ using std::ostream; //////////////////////////////////////////////////////////////////////// -// Values. +// A raw value. +// +// This is the mechanism that information-providing routines can +// use to link their own values to the property manager. Any +// SGValue can be tied to a raw value and then untied again. //////////////////////////////////////////////////////////////////////// + /** - * Abstract representation of a FlightGear value. + * Abstract base class for a raw 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. + * The property manager is implemented in three layers. The {@link + * SGPropertyNode} is the highest and most abstract layer, + * representing * an LValue/RValue pair: it * records the position + * of the property in the property tree and * contains facilities + * for navigation to other nodes. Each node * may contain an {@link + * SGValue}, which is guaranteed persistent: the * {@link SGValue} + * will not change during a session, even if the * property is bound + * and unbound multiple times. The SGValue is the * abstraction of + * an RValue: it allows for conversion among all of the different + * types, and can be bound to external pointers, functions, methods, + * or other data sources. Every SGValue contains an SGRawValue of + * a specific type. The SGRawValue (this class) may change frequently + * during a session as a value is retyped or bound and unbound to + * various data source, but the abstract SGValue layer insulates + * the application from those changes. The raw value contains no + * facilities for data binding or for type conversion: it is simply + * the abstraction of a primitive data type (or a compound data + * type, in the case of a string). * - * Values also have attributes that control whether they can be read - * from, written to, or archived (i.e. saved to disk). - */ -class SGValue + * The SGValue class always keeps a *copy* of a raw value, not the + * original one passed to it; if you override a derived class but do + * not replace the {@link #clone} method, strange things will happen. + * + * All raw values must implement {@link #getValue}, {@link #setValue}, + * and {@link #clone} for the appropriate type. + * + * @see SGValue + * @see SGPropertyNode */ +template +class SGRawValue { public: - // External getters - typedef bool (*bool_getter)(); - typedef int (*int_getter)(); - typedef float (*float_getter)(); - typedef double (*double_getter)(); - typedef const string &(*string_getter)(); + /** + * The default underlying value for this type. + * + * Every raw value has a default; the default is false for a + * boolean, 0 for the various numeric values, and "" for a string. + * If additional types of raw values are added in the future, they + * may need different kinds of default values (such as epoch for a + * date type). The default value is used when creating new values. + */ + static const T DefaultValue; // Default for this kind of raw value. + + + /** + * Constructor. + * + * Use the default value for this type. + */ + SGRawValue () {} + + + /** + * Destructor. + */ + virtual ~SGRawValue () {} + + + /** + * Return the underlying value. + * + * @return The actual value for the property. + * @see #setValue + */ + virtual T getValue () const = 0; + + + /** + * Assign a new underlying value. + * + * If the new value cannot be set (because this is a read-only + * raw value, or because the new value is not acceptable for + * some reason) this method returns false and leaves the original + * value unchanged. + * + * @param value The actual value for the property. + * @return true if the value was set successfully, false otherwise. + * @see #getValue + */ + virtual bool setValue (T value) = 0; + + + /** + * Create a new deep copy of this raw value. + * + * The copy will contain its own version of the underlying value + * as well. + * + * @return A deep copy of the current object. + */ + virtual SGRawValue * clone () const = 0; +}; - // 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 - }; +/** + * An unbound raw value, stored internally. + * + * Instances of this class are created automatically, by default, + * by the SGValue class; ordinarily the application should not + * need to touch it. + */ +template +class SGRawValueInternal : public SGRawValue +{ +public: - SGValue (); - virtual ~SGValue (); - - // 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); - virtual bool setUnknownValue (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 untie (); + /** + * Default constructor. + * + * Initialize with the default value for this type. + */ + SGRawValueInternal () {} + + /** + * Explicit value constructor. + * + * Initialize with the underlying value provided. + * + * @param value The initial value for this property. + */ + SGRawValueInternal (T value) : _value(value) {} + + /** + * Destructor. + */ + virtual ~SGRawValueInternal () {} + + /** + * Get the underlying value. + */ + virtual T getValue () const { return _value; } + + /** + * Set the underlying value. + */ + virtual bool setValue (T value) { _value = value; return true; } + + /** + * Create a deep copy of this raw value. + */ + virtual SGRawValue * clone () const { + return new SGRawValueInternal(_value); + } + +private: + T _value; +}; -protected: - bool getRawBool () const; - int getRawInt () const; - float getRawFloat () const; - double getRawDouble () const; - const string &getRawString () const; +/** + * A raw value bound to a pointer. + * + * This is the most efficient way to tie an external value, but also + * the most dangerous, because there is no way for the supplier to + * perform bounds checking and derived calculations except by polling + * the variable to see if it has changed. There is no default + * constructor, because this class would be meaningless without a + * pointer. + */ +template +class SGRawValuePointer : public SGRawValue +{ +public: - bool setRawBool (bool value); - bool setRawInt (int value); - bool setRawFloat (float value); - bool setRawDouble (double value); - bool setRawString (const string & value); + /** + * Explicit pointer constructor. + * + * Create a new raw value bound to the value of the variable + * referenced by the pointer. + * + * @param ptr The pointer to the variable to which this raw value + * will be bound. + */ + SGRawValuePointer (T * ptr) : _ptr(ptr) {} + + /** + * Destructor. + */ + virtual ~SGRawValuePointer () {} + + /** + * Get the underlying value. + * + * This method will dereference the pointer and return the + * variable's value. + */ + virtual T getValue () const { return *_ptr; } + + /** + * Set the underlying value. + * + * This method will dereference the pointer and change the + * variable's value. + */ + virtual bool setValue (T value) { *_ptr = value; return true; } + + /** + * Create a copy of this raw value. + * + * The copy will use the same external pointer as the original. + */ + virtual SGRawValue * clone () const { + return new SGRawValuePointer(_ptr); + } private: + T * _ptr; +}; - Type _type; - bool _tied; - mutable string string_val; +/** + * A value managed through static functions. + * + * A read-only value will not have a setter; a write-only value will + * not have a getter. + */ +template +class SGRawValueFunctions : public SGRawValue +{ +public: - // The value is one of the following... - union { + /** + * The template type of a static getter function. + */ + typedef T (*getter_t)(); + + /** + * The template type of a static setter function. + */ + typedef void (*setter_t)(T); + + /** + * Explicit constructor. + * + * Create a new raw value bound to the getter and setter supplied. + * + * @param getter A static function for getting a value, or 0 + * to read-disable the value. + * @param setter A static function for setting a value, or 0 + * to write-disable the value. + */ + SGRawValueFunctions (getter_t getter = 0, setter_t setter = 0) + : _getter(getter), _setter(setter) {} + + /** + * Destructor. + */ + virtual ~SGRawValueFunctions () {} + + /** + * Get the underlying value. + * + * This method will invoke the getter function to get a value. + * If no getter function was supplied, this method will always + * return the default value for the type. + */ + virtual T getValue () const { + if (_getter) return (*_getter)(); + else return SGRawValue::DefaultValue; + } - bool bool_val; - int int_val; - float float_val; - double double_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; + /** + * Set the underlying value. + * + * This method will invoke the setter function to change the + * underlying value. If no setter function was supplied, this + * method will return false. + */ + virtual bool setValue (T value) { + if (_setter) { (*_setter)(value); return true; } + else return false; + } - } _value; + /** + * Create a copy of this raw value, bound to the same functions. + */ + virtual SGRawValue * clone () const { + return new SGRawValueFunctions(_getter,_setter); + } +private: + getter_t _getter; + setter_t _setter; }; - -//////////////////////////////////////////////////////////////////////// -// Top-level manager. -//////////////////////////////////////////////////////////////////////// +/** + * An indexed value bound to static functions. + * + * A read-only value will not have a setter; a write-only value will + * not have a getter. An indexed value is useful for binding one + * of a list of possible values (such as multiple engines for a + * plane). The index is hard-coded at creation time. + */ +template +class SGRawValueFunctionsIndexed : public SGRawValue +{ +public: + typedef T (*getter_t)(int); + typedef void (*setter_t)(int,T); + SGRawValueFunctionsIndexed (int index, getter_t getter = 0, setter_t setter = 0) + : _index(index), _getter(getter), _setter(setter) {} + virtual ~SGRawValueFunctionsIndexed () {} + virtual T getValue () const { + if (_getter) return (*_getter)(_index); + else return SGRawValue::DefaultValue; + } + virtual bool setValue (T value) { + if (_setter) { (*_setter)(_index, value); return true; } + else return false; + } + virtual SGRawValue * clone () const { + return new SGRawValueFunctionsIndexed(_index, _getter, _setter); + } +private: + int _index; + getter_t _getter; + setter_t _setter; +}; /** - * A list of FlightGear properties. - * - * This list associates names (conventional written as paths, - * i.e. "/foo/bar/hack") with SGValue classes. Once an SGValue - * 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. + * A value managed through an object and access methods. * - * 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 + * A read-only value will not have a setter; a write-only value will + * not have a getter. */ -class SGPropertyList +template +class SGRawValueMethods : public SGRawValue { public: - typedef map value_map; - - typedef SGValue::bool_getter bool_getter; - typedef SGValue::int_getter int_getter; - typedef SGValue::float_getter float_getter; - typedef SGValue::double_getter double_getter; - typedef SGValue::string_getter string_getter; - - typedef SGValue::bool_setter bool_setter; - typedef SGValue::int_setter int_setter; - typedef SGValue::float_setter float_setter; - typedef SGValue::double_setter double_setter; - typedef SGValue::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; - - SGPropertyList (); - virtual ~SGPropertyList (); - - 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 SGValue * getValue (const string &name, bool create = false); - virtual const SGValue * getValue (const string &name) const; - - virtual bool getBoolValue (const string &name, - bool defaultValue = false) const; - virtual int getIntValue (const string &name, - int defaultValue = 0) const; - virtual float getFloatValue (const string &name, - float defaultValue = 0.0) const; - virtual double getDoubleValue (const string &name, - double defaultValue = 0.0L) const; - virtual const string & getStringValue (const string &name, - const string &defaultValue = "") - 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 setUnknownValue (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 untie (const string &name); - + typedef T (C::*getter_t)() const; + typedef void (C::*setter_t)(T); + SGRawValueMethods (C &obj, getter_t getter = 0, setter_t setter = 0) + : _obj(obj), _getter(getter), _setter(setter) {} + virtual ~SGRawValueMethods () {} + virtual T getValue () const { + if (_getter) { return (_obj.*_getter)(); } + else { return SGRawValue::DefaultValue; } + } + virtual bool setValue (T value) { + if (_setter) { (_obj.*_setter)(value); return true; } + else return false; + } + virtual SGRawValue * clone () const { + return new SGRawValueMethods(_obj, _getter, _setter); + } private: - value_map _props; + C &_obj; + getter_t _getter; + setter_t _setter; }; - -//////////////////////////////////////////////////////////////////////// -// Tree/node/directory view. -//////////////////////////////////////////////////////////////////////// +/** + * An indexed value managed through an object and access methods. + * + * A read-only value will not have a setter; a write-only value will + * not have a getter. + */ +template +class SGRawValueMethodsIndexed : public SGRawValue +{ +public: + typedef T (C::*getter_t)(int) const; + typedef void (C::*setter_t)(int, T); + SGRawValueMethodsIndexed (C &obj, int index, + getter_t getter = 0, setter_t setter = 0) + : _obj(obj), _index(index), _getter(getter), _setter(setter) {} + virtual ~SGRawValueMethodsIndexed () {} + virtual T getValue () const { + if (_getter) { return (_obj.*_getter)(_index); } + else { return SGRawValue::DefaultValue; } + } + virtual bool setValue (T value) { + if (_setter) { (_obj.*_setter)(_index, value); return true; } + else return false; + } + virtual SGRawValue * clone () const { + return new SGRawValueMethodsIndexed(_obj, _index, _getter, _setter); + } +private: + C &_obj; + int _index; + getter_t _getter; + setter_t _setter; +}; + /** - * Tree view of a property list. - * - * This class provides a virtual tree view of a property list, without - * actually constructing a tree -- the view always stays in sync with - * the property list itself. - * - * This class is designed to be used for setup and configuration; it is - * optimized for ease of use rather than performance, and shouldn't be - * used inside a tight loop. - * - * Every node is actually just a path together with a pointer to - * the real property list and a few convenient operations; to the - * user, however, it looks like a node in a tree or a file system, - * with the regular operations such as getChild and getParent. - * - * Note that a node may be both a branch and a leaf -- that is, it - * may have a value itself and it may have children. Here is a simple - * example that prints the names of all of the different nodes inside - * "/controls": - * - * SGPropertyNode controls("/controls", current_property_list); - * SGPropertyNode child; - * int size = controls.size(); - * for (int i = 0; i < size; i++) { - * if (controls.getChild(child, i)) - * cout << child.getName() << endl; - * else - * cerr << "Failed to read child " << i << endl; - * } + * A node in a property tree. */ class SGPropertyNode { + public: - // Constructor and destructor - SGPropertyNode (const string &path = "", SGPropertyList * props = 0); + + + /** + * Property value types. + */ + enum Type { + NONE, + ALIAS, + BOOL, + INT, + LONG, + FLOAT, + DOUBLE, + STRING, + UNSPECIFIED + }; + + + /** + * Access mode attributes. + * + *

The ARCHIVE attribute is strictly advisory, and controls + * whether the property should normally be saved and restored.

+ */ + enum Attribute { + READ = 1, + WRITE = 2, + ARCHIVE = 4, + TRACE_READ = 8, + TRACE_WRITE = 16 + }; + + + /** + * Default constructor. + */ + SGPropertyNode (); + + + /** + * Copy constructor. + */ + SGPropertyNode (const SGPropertyNode &node); + + + /** + * Destructor. + */ virtual ~SGPropertyNode (); - // Accessor and setter for the internal - // path. - virtual const string &getPath () const { return _path; } - virtual void setPath (const string &path); - // Accessor and setter for the real - // property list. - virtual SGPropertyList * getPropertyList () { return _props; } - virtual void setPropertyList (SGPropertyList * props) { - _props = props; + + // + // Basic properties. + // + + /** + * Test whether this node contains a primitive leaf value. + */ + bool hasValue () const { return (_type != NONE); } + + + /** + * Get the node's simple (XML) name. + */ + const string &getName () const { return _name; } + + + /** + * Get the node's integer index. + */ + const int getIndex () const { return _index; } + + + /** + * Get a non-const pointer to the node's parent. + */ + SGPropertyNode * getParent () { return _parent; } + + + /** + * Get a const pointer to the node's parent. + */ + const SGPropertyNode * getParent () const { return _parent; } + + + // + // Children. + // + + + /** + * Get the number of child nodes. + */ + const int nChildren () const { return _children.size(); } + + + /** + * Get a child node by position (*NOT* index). + */ + SGPropertyNode * getChild (int position); + + + /** + * Get a const child node by position (*NOT* index). + */ + const SGPropertyNode * getChild (int position) const; + + + /** + * Get a child node by name and index. + */ + SGPropertyNode * getChild (const string &name, int index = 0, + bool create = false); + + + /** + * Get a const child node by name and index. + */ + const SGPropertyNode * getChild (const string &name, int index = 0) const; + + + /** + * Get a vector of all children with the specified name. + */ + vector getChildren (const string &name); + + + /** + * Get a vector all all children (const) with the specified name. + */ + vector getChildren (const string &name) const; + + + // + // Alias support. + // + + + /** + * Alias this node's leaf value to another's. + */ + bool alias (SGPropertyNode * target); + + + /** + * Alias this node's leaf value to another's by relative path. + */ + bool alias (const string &path); + + + /** + * Remove any alias for this node. + */ + bool unalias (); + + + /** + * Test whether the node's leaf value is aliased to another's. + */ + bool isAlias () const { return (_type == ALIAS); } + + + /** + * Get a non-const pointer to the current alias target, if any. + */ + SGPropertyNode * getAliasTarget (); + + + /** + * Get a const pointer to the current alias target, if any. + */ + const SGPropertyNode * getAliasTarget () const; + + + // + // Path information. + // + + + /** + * Get the path to this node from the root. + */ + string getPath (bool simplify = false) const; + + + /** + * Get a pointer to the root node. + */ + SGPropertyNode * getRootNode (); + + + /** + * Get a const pointer to the root node. + */ + const SGPropertyNode * getRootNode () const; + + + /** + * Get a pointer to another node by relative path. + */ + SGPropertyNode * getNode (const string &relative_path, bool create = false); + + + /** + * Get a const pointer to another node by relative path. + */ + const SGPropertyNode * getNode (const string &relative_path) const; + + + // + // Access Mode. + // + + /** + * Check a single mode attribute for the property node. + */ + bool getAttribute (Attribute attr) const { return ((_attr & attr) != 0); } + + + /** + * Set a single mode attribute for the property node. + */ + void setAttribute (Attribute attr, bool state) { + (state ? _attr |= attr : _attr &= ~attr); } - // Accessors for derived information. - virtual int size () const; - virtual const string &getName () const; - virtual SGPropertyNode &getParent () const; - virtual SGPropertyNode &getChild (int n) const; - virtual SGPropertyNode &getSubNode (const string &subpath) const; - - // Get values directly. - virtual SGValue * getValue (const string &subpath = ""); - virtual bool getBoolValue (const string &subpath = "", - bool defaultValue = false) const; - virtual int getIntValue (const string &subpath = "", - int defaultValue = 0) const; - virtual float getFloatValue (const string &subpath = "", - float defaultValue = 0.0) const; - virtual double getDoubleValue (const string &subpath = "", - double defaultValue = 0.0L) const; - virtual const string & - getStringValue (const string &subpath = "", - const string &defaultValue = "") const; + + /** + * Get all of the mode attributes for the property node. + */ + int getAttributes () const { return _attr; } + + + /** + * Set all of the mode attributes for the property node. + */ + void setAttributes (int attr) { _attr = attr; } + + + // + // Leaf Value (primitive). + // + + + /** + * Get the type of leaf value, if any, for this node. + */ + Type getType () const; + + + /** + * Get a bool value for this node. + */ + bool getBoolValue () const; + + + /** + * Get an int value for this node. + */ + int getIntValue () const; + + + /** + * Get a long int value for this node. + */ + long getLongValue () const; + + + /** + * Get a float value for this node. + */ + float getFloatValue () const; + + + /** + * Get a double value for this node. + */ + double getDoubleValue () const; + + + /** + * Get a string value for this node. + */ + string getStringValue () const; + + + + /** + * Set a bool value for this node. + */ + bool setBoolValue (bool value); + + + /** + * Set an int value for this node. + */ + bool setIntValue (int value); + + + /** + * Set a long int value for this node. + */ + bool setLongValue (long value); + + + /** + * Set a float value for this node. + */ + bool setFloatValue (float value); + + + /** + * Set a double value for this node. + */ + bool setDoubleValue (double value); + + + /** + * Set a string value for this node. + */ + bool setStringValue (string value); + + + /** + * Set a value of unspecified type for this node. + */ + bool setUnspecifiedValue (string value); + + + // + // Data binding. + // + + + /** + * Test whether this node is bound to an external data source. + */ + bool isTied () const { return _tied; } + + + /** + * Bind this node to an external bool source. + */ + bool tie (const SGRawValue &rawValue, bool useDefault = true); + + + /** + * Bind this node to an external int source. + */ + bool tie (const SGRawValue &rawValue, bool useDefault = true); + + + /** + * Bind this node to an external long int source. + */ + bool tie (const SGRawValue &rawValue, bool useDefault = true); + + + /** + * Bind this node to an external float source. + */ + bool tie (const SGRawValue &rawValue, bool useDefault = true); + + + /** + * Bind this node to an external double source. + */ + bool tie (const SGRawValue &rawValue, bool useDefault = true); + + + /** + * Bind this node to an external string source. + */ + bool tie (const SGRawValue &rawValue, bool useDefault = true); + + + /** + * Unbind this node from any external data source. + */ + bool untie (); + + + // + // Convenience methods using paths. + // TODO: add attribute methods + // + + + /** + * Get another node's type. + */ + Type getType (const string &relative_path) const; + + + /** + * Test whether another node has a leaf value. + */ + bool hasValue (const string &relative_path) const; + + + /** + * Get another node's value as a bool. + */ + bool getBoolValue (const string &relative_path, + bool defaultValue = false) const; + + + /** + * Get another node's value as an int. + */ + int getIntValue (const string &relative_path, + int defaultValue = 0) const; + + + /** + * Get another node's value as a long int. + */ + long getLongValue (const string &relative_path, + long defaultValue = 0L) const; + + + /** + * Get another node's value as a float. + */ + float getFloatValue (const string &relative_path, + float defaultValue = 0.0) const; + + + /** + * Get another node's value as a double. + */ + double getDoubleValue (const string &relative_path, + double defaultValue = 0.0L) const; + + + /** + * Get another node's value as a string. + */ + string getStringValue (const string &relative_path, + string defaultValue = "") const; + + + /** + * Set another node's value as a bool. + */ + bool setBoolValue (const string &relative_path, bool value); + + + /** + * Set another node's value as an int. + */ + bool setIntValue (const string &relative_path, int value); + + + /** + * Set another node's value as a long int. + */ + bool setLongValue (const string &relative_path, long value); + + + /** + * Set another node's value as a float. + */ + bool setFloatValue (const string &relative_path, float value); + + + /** + * Set another node's value as a double. + */ + bool setDoubleValue (const string &relative_path, double value); + + + /** + * Set another node's value as a string. + */ + bool setStringValue (const string &relative_path, string value); + + + /** + * Set another node's value with no specified type. + */ + bool setUnspecifiedValue (const string &relative_path, string value); + + + /** + * Test whether another node is bound to an external data source. + */ + bool isTied (const string &relative_path) const; + + + /** + * Bind another node to an external bool source. + */ + bool tie (const string &relative_path, const SGRawValue &rawValue, + bool useDefault = true); + + + /** + * Bind another node to an external int source. + */ + bool tie (const string &relative_path, const SGRawValue &rawValue, + bool useDefault = true); + + + /** + * Bind another node to an external long int source. + */ + bool tie (const string &relative_path, const SGRawValue &rawValue, + bool useDefault = true); + + + /** + * Bind another node to an external float source. + */ + bool tie (const string &relative_path, const SGRawValue &rawValue, + bool useDefault = true); + + + /** + * Bind another node to an external double source. + */ + bool tie (const string &relative_path, const SGRawValue &rawValue, + bool useDefault = true); + + + /** + * Bind another node to an external string source. + */ + bool tie (const string &relative_path, const SGRawValue &rawValue, + bool useDefault = true); + + + /** + * Unbind another node from any external data source. + */ + bool untie (const string &relative_path); + + +protected: + + + /** + * Protected constructor for making new nodes on demand. + */ + SGPropertyNode (const string &name, int index, SGPropertyNode * parent); + private: - string _path; - SGPropertyList * _props; - // for pointer persistence... - // NOT THREAD SAFE!!! - // (each thread must have its own node - // object) - mutable string _name; - mutable SGPropertyNode * _node; + + + /** + * Clear any existing value and set the type to NONE. + */ + void clear_value (); + + + /** + * Get the value as a string. + */ + string get_string () const; + + + /** + * Trace a read access. + */ + void trace_read (Type accessType) const; + + + /** + * Trace a write access. + */ + void trace_write (Type accessType) const; + + string _name; + int _index; + SGPropertyNode * _parent; + vector _children; + + + Type _type; + bool _tied; + int _attr; + + // The right kind of pointer... + union { + SGPropertyNode * alias; + SGRawValue * bool_val; + SGRawValue * int_val; + SGRawValue * long_val; + SGRawValue * float_val; + SGRawValue * double_val; + SGRawValue * string_val; + } _value; + + }; //////////////////////////////////////////////////////////////////////// -// Input and output. +// I/O functions. //////////////////////////////////////////////////////////////////////// -extern bool readPropertyList (istream &input, SGPropertyList * props); -extern bool writePropertyList (ostream &output, const SGPropertyList * props); +/** + * Read properties from an XML input stream. + */ +void readProperties (istream &input, SGPropertyNode * start_node, + const string &base = ""); - -//////////////////////////////////////////////////////////////////////// -// Global property manager. -//////////////////////////////////////////////////////////////////////// -extern SGPropertyList current_properties; +/** + * Read properties from an XML file. + */ +void readProperties (const string &file, SGPropertyNode * start_node); + + +/** + * Write properties to an XML output stream. + */ +void writeProperties (ostream &output, const SGPropertyNode * start_node); + + +/** + * Write properties to an XML file. + */ +void writeProperties (const string &file, const SGPropertyNode * start_node); + + +/** + * Copy properties from one node to another. + */ +bool copyProperties (const SGPropertyNode *in, SGPropertyNode *out); -#endif __PROPS_HXX +#endif // __PROPS_HXX // end of props.hxx