#include "props.hxx"
#include <algorithm>
+#include <sstream>
#include <stdio.h>
#include <string.h>
using std::find;
using std::sort;
using std::vector;
+using std::stringstream;
#else
SG_USING_STD(sort);
SG_USING_STD(find);
SG_USING_STD(vector);
+SG_USING_STD(stringstream);
#if ( _MSC_VER == 1200 )
// MSVC 6 is buggy, and needs something strange here
else
return "false";
case INT:
- sprintf(_buffer, "%d", get_int());
- return _buffer;
+ {
+ stringstream sstr;
+ sstr << get_int();
+ _buffer = sstr.str();
+ return _buffer.c_str();
+ }
case LONG:
- sprintf(_buffer, "%ld", get_long());
- return _buffer;
+ {
+ stringstream sstr;
+ sstr << get_long();
+ _buffer = sstr.str();
+ return _buffer.c_str();
+ }
case FLOAT:
- sprintf(_buffer, "%f", get_float());
- return _buffer;
+ {
+ stringstream sstr;
+ sstr << get_float();
+ _buffer = sstr.str();
+ return _buffer.c_str();
+ }
case DOUBLE:
- sprintf(_buffer, "%f", get_double());
- return _buffer;
+ {
+ stringstream sstr;
+ sstr << get_double();
+ _buffer = sstr.str();
+ return _buffer.c_str();
+ }
case STRING:
case UNSPECIFIED:
return get_string();
#endif
}
-/**
- * Increment reference counter
- */
-void
-SGPropertyNode::incrementRef()
-{
- ++_count;
-}
-
-/**
- * Decrement reference counter
- */
-int
-SGPropertyNode::decrementRef()
-{
- return --_count;
-}
-
-
\f
////////////////////////////////////////////////////////////////////////
// Public methods from SGPropertyNode.
* Default constructor: always creates a root node.
*/
SGPropertyNode::SGPropertyNode ()
- : _name(copy_string("")),
- _display_name(0),
- _index(0),
+ : _index(0),
_parent(0),
- _path(0),
_path_cache(0),
_type(NONE),
_tied(false),
_attr(READ|WRITE),
- _count(0),
_listeners(0)
{
_local_val.string_val = 0;
* Copy constructor.
*/
SGPropertyNode::SGPropertyNode (const SGPropertyNode &node)
- : _display_name(0),
- _index(node._index),
+ : _index(node._index),
+ _name(node._name),
_parent(0), // don't copy the parent
- _path(0),
_path_cache(0),
_type(node._type),
_tied(node._tied),
_attr(node._attr),
- _count(0),
_listeners(0) // CHECK!!
{
- _name = copy_string(node._name);
_local_val.string_val = 0;
switch (_type) {
case NONE:
SGPropertyNode::SGPropertyNode (const char * name,
int index,
SGPropertyNode * parent)
- : _display_name(0),
- _index(index),
+ : _index(index),
_parent(parent),
- _path(0),
_path_cache(0),
_type(NONE),
_tied(false),
_attr(READ|WRITE),
- _count(0),
_listeners(0)
{
- _name = copy_string(name);
+ _name = name;
_local_val.string_val = 0;
}
*/
SGPropertyNode::~SGPropertyNode ()
{
- delete [] _name;
- delete [] _display_name;
- delete [] _path;
delete _path_cache;
clearValue();
delete _listeners;
const char *
SGPropertyNode::getDisplayName (bool simplify) const
{
- string display = _name;
+ _display_name = _name;
if (_index != 0 || !simplify) {
- char buffer[64];
- sprintf(buffer, "[%d]", _index);
- display += buffer;
+ stringstream sstr;
+ sstr << '[' << _index << ']';
+ _display_name += sstr.str();
}
- _display_name = copy_string(display.c_str());
- return _display_name;
+ return _display_name.c_str();
}
const char *
SGPropertyNode::getPath (bool simplify) const
{
- // Calculate the complete path only once.
- if (_path == 0) {
- string path;
- if (_parent == 0) {
- path = "";
- } else {
- path = _parent->getPath(simplify);
- path += '/';
- path += getDisplayName(simplify);
- }
- _path = copy_string(path.c_str());
+ // Calculate the complete path only once.
+ if (_parent != 0 && _path.empty()) {
+ _path = _parent->getPath(simplify);
+ _path += '/';
+ _path += getDisplayName(simplify);
}
- return _path;
+ return _path.c_str();
}
SGPropertyNode::Type
SGPropertyNode::addChangeListener (SGPropertyChangeListener * listener)
{
if (_listeners == 0)
- _listeners = new vector<SGPropertyChangeListener *>;
+ _listeners = new vector<SGPropertyChangeListener*>;
_listeners->push_back(listener);
listener->register_property(this);
}
void
SGPropertyNode::removeChangeListener (SGPropertyChangeListener * listener)
{
- vector<SGPropertyChangeListener *>::iterator it =
+ vector<SGPropertyChangeListener*>::iterator it =
find(_listeners->begin(), _listeners->end(), listener);
if (it != _listeners->end()) {
_listeners->erase(it);
listener->unregister_property(this);
if (_listeners->empty()) {
- vector<SGPropertyChangeListener *> * tmp = _listeners;
+ vector<SGPropertyChangeListener*>* tmp = _listeners;
_listeners = 0;
delete tmp;
}
#define HASH_TABLE_SIZE 199
SGPropertyNode::hash_table::entry::entry ()
- : _key(0),
- _value(0)
+ : _value(0)
{
}
{
// Don't delete the value; we don't own
// the pointer.
- delete [] _key;
}
void
SGPropertyNode::hash_table::entry::set_key (const char * key)
{
- _key = copy_string(key);
+ _key = key;
}
void
}
-
-/**
- * Default constructor
- */
-SGPropertyNode_ptr::SGPropertyNode_ptr()
-{
- _ptr = 0;
-}
-
-/**
- * Copy constructor
- */
-SGPropertyNode_ptr::SGPropertyNode_ptr( const SGPropertyNode_ptr &r )
-{
- _ptr = r._ptr;
- if (_ptr)
- _ptr->incrementRef();
-}
-
-/**
- * Constructor from a pointer to a node
- */
-SGPropertyNode_ptr::SGPropertyNode_ptr( SGPropertyNode *p )
-{
- _ptr = p;
- if (_ptr)
- _ptr->incrementRef();
-}
-
-/**
- * Destructor
- */
-SGPropertyNode_ptr::~SGPropertyNode_ptr()
-{
- if (_ptr && _ptr->decrementRef() == 0)
- delete _ptr;
-}
-
-/**
- * Assignement operator
- */
-SGPropertyNode_ptr &
-SGPropertyNode_ptr::operator=( const SGPropertyNode_ptr &r )
-{
- if (_ptr && _ptr->decrementRef() == 0)
- delete _ptr;
- _ptr = r._ptr;
- if (_ptr)
- _ptr->incrementRef();
-
- return *this;
-}
-
-/**
- * Pointer access operator
- */
-SGPropertyNode *
-SGPropertyNode_ptr::operator->()
-{
- return _ptr;
-}
-
-/**
- * Pointer access operator (const)
- */
-const SGPropertyNode *
-SGPropertyNode_ptr::operator->() const
-{
- return _ptr;
-}
-
-/**
- * Conversion to SGPropertyNode * operator
- */
-SGPropertyNode_ptr::operator SGPropertyNode *()
-{
- return _ptr;
-}
-
-/**
- * Conversion to const SGPropertyNode * operator
- */
-SGPropertyNode_ptr::operator const SGPropertyNode *() const
-{
- return _ptr;
-}
-
-/**
- * Validity test
- */
-bool
-SGPropertyNode_ptr::valid() const
-{
- return _ptr != 0;
-}
-
-
\f
////////////////////////////////////////////////////////////////////////
// Implementation of SGPropertyChangeListener.
#endif
+#include <simgear/structure/SGReferenced.hxx>
+#include <simgear/structure/SGSharedPtr.hxx>
+
#ifdef NONE
#pragma warn A sloppy coder has defined NONE as a macro!
* The smart pointer that manage reference counting
*/
class SGPropertyNode;
-class SGPropertyNode_ptr
-{
-public:
-
- /**
- * Default constructor
- */
- SGPropertyNode_ptr();
-
- /**
- * Copy constructor
- */
- SGPropertyNode_ptr( const SGPropertyNode_ptr &r );
-
- /**
- * Constructor from a pointer to a node
- */
- SGPropertyNode_ptr( SGPropertyNode *p );
-
- /**
- * Destructor
- */
- ~SGPropertyNode_ptr();
-
- /**
- * Assignement operator
- */
- SGPropertyNode_ptr &operator=( const SGPropertyNode_ptr &r );
-
- /**
- * Pointer access operator
- */
- SGPropertyNode *operator->();
-
- /**
- * Pointer access operator (const)
- */
- const SGPropertyNode *operator->() const;
-
- /**
- * Conversion to SGPropertyNode * operator
- */
- operator SGPropertyNode *();
-
- /**
- * Conversion to const SGPropertyNode * operator
- */
- operator const SGPropertyNode *() const;
-
- /**
- * Return the pointer.
- */
- SGPropertyNode * ptr () { return _ptr; }
-
- /**
- * Validity test
- */
- bool valid() const;
-
-private:
-
- SGPropertyNode *_ptr;
-};
-
+typedef SGSharedPtr<SGPropertyNode> SGPropertyNode_ptr;
+typedef SGSharedPtr<const SGPropertyNode> SGConstPropertyNode_ptr;
\f
/**
/**
* A node in a property tree.
*/
-class SGPropertyNode
+class SGPropertyNode : public SGReferenced
{
public:
/**
* Get the node's simple (XML) name.
*/
- const char * getName () const { return _name; }
+ const char * getName () const { return _name.c_str(); }
/**
void trace_write () const;
- /**
- * Increment reference counter
- */
- void incrementRef();
-
- /**
- * Decrement reference counter
- */
- int decrementRef();
-
- friend class SGPropertyNode_ptr;
-
-
- mutable char _buffer[MAX_STRING_LEN+1];
-
class hash_table;
- char * _name;
- mutable char * _display_name;
+ string _name;
+ mutable string _display_name;
int _index;
+ /// To avoid cyclic reference counting loops this shall not be a reference
+ /// counted pointer
SGPropertyNode * _parent;
vector<SGPropertyNode_ptr> _children;
vector<SGPropertyNode_ptr> _removedChildren;
- mutable char * _path;
+ mutable string _path;
+ mutable string _buffer;
hash_table * _path_cache;
Type _type;
bool _tied;
int _attr;
- int _count;
// The right kind of pointer...
union {
public:
entry ();
~entry ();
- const char * get_key () { return _key; }
+ const char * get_key () { return _key.c_str(); }
void set_key (const char * key);
SGPropertyNode * get_value () { return _value; }
void set_value (SGPropertyNode * value);
private:
- char * _key;
- SGPropertyNode * _value;
+ string _key;
+ SGSharedPtr<SGPropertyNode> _value;
};
SGModelLib::~SGModelLib ()
{
- map<string, ssgBase *>::iterator it = _table.begin();
- while (it != _table.end()) {
- ssgDeRefDelete(it->second);
- _table.erase(it);
- }
}
void
return;
- map<string, ssgBase *>::iterator it = _table.begin();
+ map<string, ssgSharedPtr<ssgEntity> >::iterator it = _table.begin();
while (it != _table.end()) {
- ssgBase *item = it->second;
// If there is only one reference, it's
// ours; no one else is using the item.
- if (item->getRef() == 1) {
- ssgDeRefDelete(item);
+ if (!it->second.isShared()) {
+ string key = it->first;
_table.erase(it);
- }
- it++;
+ it = _table.upper_bound(key);
+ } else
+ it++;
}
}
// FIXME: normalize path to
// avoid duplicates.
- map<string, ssgBase *>::iterator it = _table.find(path);
+ map<string, ssgSharedPtr<ssgEntity> >::iterator it = _table.find(path);
if (it == _table.end()) {
- ssgEntity *model = sgLoad3DModel( fg_root, path, prop_root,
- sim_time_sec );
- model->ref();
+ ssgSharedPtr<ssgEntity> model = sgLoad3DModel(fg_root, path, prop_root,
+ sim_time_sec );
_table[path] = model; // add one reference to keep it around
personality_branch->addKid( model );
} else {
- personality_branch->addKid( (ssgEntity *)it->second );
+ personality_branch->addKid( it->second );
}
return personality_branch;
}