X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=simgear%2Fmisc%2Fprops.hxx;h=b9a0157ac4bca01f341913748546a7357ce5c5cd;hb=5bab565cfe4c30d6cf08ecaba50af74d5e4f0c98;hp=d49f181d9d0a9acb5696c4380c9aa7a751baa051;hpb=e07af680183126847f1547a7ad8101e43fbe9023;p=simgear.git diff --git a/simgear/misc/props.hxx b/simgear/misc/props.hxx index d49f181d..b9a0157a 100644 --- a/simgear/misc/props.hxx +++ b/simgear/misc/props.hxx @@ -1,18 +1,17 @@ -// 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$ +/** + * \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 -#ifdef HAVE_CONFIG_H -#include -#endif - #include #include @@ -21,16 +20,26 @@ #include #include STL_IOSTREAM -FG_USING_STD(string); -FG_USING_STD(vector); -#if !defined(FG_HAVE_NATIVE_SGI_COMPILERS) -FG_USING_STD(istream); -FG_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 @@ -43,6 +52,11 @@ FG_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 @@ -72,32 +86,103 @@ FG_USING_STD(ostream); /** * Abstract base class for a raw value. * - * Unlike values, raw values are not persistent -- the raw value can - * change frequently, but the changes are not visible to the application. + * 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). * * 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 clone() method, strange things will happen. + * not replace the {@link #clone} method, strange things will happen. * - * All raw values must implement getValue, setValue, and clone for the - * appropriate type. - */ + * All raw values must implement {@link #getValue}, {@link #setValue}, + * and {@link #clone} for the appropriate type. + * + * @see SGValue + * @see SGPropertyNode */ template class SGRawValue { public: + + /** + * 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; }; /** - * A value managed internally. + * An unbound raw value, stored internally. * * Instances of this class are created automatically, by default, * by the SGValue class; ordinarily the application should not @@ -107,38 +192,106 @@ template class SGRawValueInternal : public SGRawValue { public: + + /** + * 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; }; /** - * A value managed through a direct pointer. + * 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. + * 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: + + /** + * 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; }; @@ -154,22 +307,66 @@ template class SGRawValueFunctions : public SGRawValue { public: + + /** + * 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 DefaultValue; + else return SGRawValue::DefaultValue; } + + /** + * 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; } + + /** + * 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; @@ -177,10 +374,12 @@ private: /** - * An indexed value managed through static functions. + * 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. + * 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 @@ -193,7 +392,7 @@ public: virtual ~SGRawValueFunctionsIndexed () {} virtual T getValue () const { if (_getter) return (*_getter)(_index); - else return DefaultValue; + else return SGRawValue::DefaultValue; } virtual bool setValue (T value) { if (_setter) { (*_setter)(_index, value); return true; } @@ -226,7 +425,7 @@ public: virtual ~SGRawValueMethods () {} virtual T getValue () const { if (_getter) { return (_obj.*_getter)(); } - else { return DefaultValue; } + else { return SGRawValue::DefaultValue; } } virtual bool setValue (T value) { if (_setter) { (_obj.*_setter)(value); return true; } @@ -260,7 +459,7 @@ public: virtual ~SGRawValueMethodsIndexed () {} virtual T getValue () const { if (_getter) { return (_obj.*_getter)(_index); } - else { return DefaultValue; } + else { return SGRawValue::DefaultValue; } } virtual bool setValue (T value) { if (_setter) { (_obj.*_setter)(_index, value); return true; } @@ -278,197 +477,609 @@ private: -//////////////////////////////////////////////////////////////////////// -// A cooked value. -// -// This is the value that property-list clients see. It is a -// persistent layer over the possibly-changing raw value; once a -// client gets an SGValue from the property manager, the pointer -// will be good for the life of the property manager itself, no -// matter how often the pointer is tied or untied. -//////////////////////////////////////////////////////////////////////// - -class SGValue +/** + * A node in a property tree. + */ +class SGPropertyNode { + public: + + + /** + * Property value types. + */ enum Type { + NONE, + ALIAS, BOOL, INT, + LONG, FLOAT, DOUBLE, STRING, - UNKNOWN + UNSPECIFIED }; - SGValue (); - SGValue (const SGValue &value); - ~SGValue (); - - Type getType () const { return _type; } - bool getBoolValue () const; - int getIntValue () const; - float getFloatValue () const; - double getDoubleValue () const; - string getStringValue () const; - bool setBoolValue (bool value); - bool setIntValue (int value); - bool setFloatValue (float value); - bool setDoubleValue (double value); - bool setStringValue (string value); - bool setUnknownValue (string value); + /** + * 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 + }; - bool isTied () const { return _tied; } - bool tie (const SGRawValue &rawValue, bool useDefault = true); - bool tie (const SGRawValue &rawValue, bool useDefault = true); - bool tie (const SGRawValue &rawValue, bool useDefault = true); - bool tie (const SGRawValue &rawValue, bool useDefault = true); - bool tie (const SGRawValue &rawValue, bool useDefault = true); + /** + * Default constructor. + */ + SGPropertyNode (); - bool untie (); -private: + /** + * Copy constructor. + */ + SGPropertyNode (const SGPropertyNode &node); - void clear_value (); - Type _type; - bool _tied; + /** + * Destructor. + */ + virtual ~SGPropertyNode (); - // The right kind of pointer... - union { - SGRawValue * bool_val; - SGRawValue * int_val; - SGRawValue * float_val; - SGRawValue * double_val; - SGRawValue * string_val; - } _value; -}; + // + // Basic properties. + // - -//////////////////////////////////////////////////////////////////////// -// A node in a property tree. -//////////////////////////////////////////////////////////////////////// + /** + * Test whether this node contains a primitive leaf value. + */ + bool hasValue () const { return (_type != NONE); } -class SGPropertyNode -{ -public: + /** + * Get the node's simple (XML) name. + */ + const string &getName () const { return _name; } - SGPropertyNode (); - virtual ~SGPropertyNode (); - // Basic properties. - bool hasValue () const { return (_value != 0); } - SGValue * getValue () { return _value; } - const SGValue * getValue () const { return _value; } - 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. + + // + // 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; - // Path information. + + // + // 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; - // Relative or absolute paths. + + /** + * 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; - // Value-related stuff. - SGValue::Type getType () 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); + } + + + /** + * 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); - bool setUnknownValue (string value); - bool isTied () const; + /** + * 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 (); - // Values from paths. + + // + // 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; - SGValue * getValue (const string &relative_path, bool create = false); - const SGValue * getValue (const string &relative_path) const; - SGValue::Type getType (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); - bool setUnknownValue (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: - SGPropertyNode (const SGPropertyNode &node) {} - SGValue * _value; + /** + * 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; + + }; @@ -477,10 +1088,35 @@ private: // I/O functions. //////////////////////////////////////////////////////////////////////// -bool readProperties (istream &input, SGPropertyNode * start_node); -bool readProperties (const string &file, SGPropertyNode * start_node); -bool writeProperties (ostream &output, const SGPropertyNode * start_node); -bool writeProperties (const string &file, const SGPropertyNode * start_node); + +/** + * Read properties from an XML input stream. + */ +void readProperties (istream &input, SGPropertyNode * start_node, + const string &base = ""); + + +/** + * 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);