Major property-manager rewrite, using const char * throughout

interface instead of string.  This will result in a lot more
efficiency later, once I add in a simple hash table for caching
lookups, since it will avoid creating a lot of temporary string
objects.  The major considerations for users will be that they cannot
use

  node->getName() == "foo";

any more, and will have to use c_str() when setting a string value
from a C++ string.
This commit is contained in:
david
2002-03-19 16:07:47 +00:00
parent f9824aa7de
commit 4d0bc0ae39
4 changed files with 246 additions and 171 deletions
+154 -109
View File
@@ -6,17 +6,25 @@
// //
// $Id$ // $Id$
#include <simgear/compiler.h>
#include <simgear/debug/logstream.hxx>
#include <stdio.h>
#include <stdlib.h>
#include STL_IOSTREAM
#include <algorithm>
#include "props.hxx" #include "props.hxx"
#if PROPS_STANDALONE
#include <iostream>
using std::cerr;
using std::endl;
using std::sort;
#else
#include <simgear/compiler.h>
#include <simgear/debug/logstream.hxx>
SG_USING_STD(sort); SG_USING_STD(sort);
#endif
#include <string.h>
//////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////
@@ -54,7 +62,7 @@ const int SGRawValue<int>::DefaultValue = 0;
const long SGRawValue<long>::DefaultValue = 0L; const long SGRawValue<long>::DefaultValue = 0L;
const float SGRawValue<float>::DefaultValue = 0.0; const float SGRawValue<float>::DefaultValue = 0.0;
const double SGRawValue<double>::DefaultValue = 0.0L; const double SGRawValue<double>::DefaultValue = 0.0L;
const string SGRawValue<string>::DefaultValue = ""; const char * const SGRawValue<const char *>::DefaultValue = "";
@@ -76,7 +84,7 @@ struct PathComponent
* *
* Name: [_a-zA-Z][-._a-zA-Z0-9]* * Name: [_a-zA-Z][-._a-zA-Z0-9]*
*/ */
static inline string static inline const string
parse_name (const string &path, int &i) parse_name (const string &path, int &i)
{ {
string name = ""; string name = "";
@@ -204,16 +212,35 @@ parse_path (const string &path, vector<PathComponent> &components)
//////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////
static const char *
copy_string (const char * s)
{
// FIXME: potential buffer overflow.
// For some reason, strnlen and
// strncpy cause all kinds of crashes.
string str = s;
size_t len = strlen(s);
char * copy = new char[str.size() + 1];
strcpy(copy, str.c_str());
return copy;
}
static bool
compare_strings (const char * s1, const char * s2)
{
return !strncmp(s1, s2, SGPropertyNode::MAX_STRING_LEN);
}
/** /**
* Locate a child node by name and index. * Locate a child node by name and index.
*/ */
static int static int
find_child (const string &name, int index, vector<SGPropertyNode *> nodes) find_child (const char * name, int index, vector<SGPropertyNode *> nodes)
{ {
int nNodes = nodes.size(); int nNodes = nodes.size();
for (int i = 0; i < nNodes; i++) { for (int i = 0; i < nNodes; i++) {
SGPropertyNode * node = nodes[i]; SGPropertyNode * node = nodes[i];
if (node->getName() == name && node->getIndex() == index) if (compare_strings(node->getName(), name) && node->getIndex() == index)
return i; return i;
} }
return -1; return -1;
@@ -261,7 +288,7 @@ find_node (SGPropertyNode * current,
// Otherwise, a child name // Otherwise, a child name
else { else {
SGPropertyNode * child = SGPropertyNode * child =
current->getChild(components[position].name, current->getChild(components[position].name.c_str(),
components[position].index, components[position].index,
create); create);
return find_node(child, components, position + 1, create); return find_node(child, components, position + 1, create);
@@ -319,13 +346,13 @@ SGPropertyNode::get_double () const
return _local_val.double_val; return _local_val.double_val;
} }
inline const string inline const char *
SGPropertyNode::get_string () const SGPropertyNode::get_string () const
{ {
if (_tied) if (_tied)
return _value.string_val->getValue(); return _value.string_val->getValue();
else else
return *(_local_val.string_val); return _local_val.string_val;
} }
inline bool inline bool
@@ -384,12 +411,13 @@ SGPropertyNode::set_double (double val)
} }
inline bool inline bool
SGPropertyNode::set_string (const string &val) SGPropertyNode::set_string (const char * val)
{ {
if (_tied) { if (_tied) {
return _value.string_val->setValue(val); return _value.string_val->setValue(val);
} else { } else {
(*_local_val.string_val) = val; delete _local_val.string_val;
_local_val.string_val = copy_string(val);
return true; return true;
} }
} }
@@ -443,12 +471,11 @@ SGPropertyNode::clear_value ()
/** /**
* Get the value as a string. * Get the value as a string.
*/ */
string const char *
SGPropertyNode::make_string () const SGPropertyNode::make_string () const
{ {
if (!getAttribute(READ)) if (!getAttribute(READ))
return ""; return "";
char buf[128];
switch (_type) { switch (_type) {
case ALIAS: case ALIAS:
@@ -459,17 +486,17 @@ SGPropertyNode::make_string () const
else else
return "false"; return "false";
case INT: case INT:
sprintf(buf, "%d", get_int()); sprintf(_buffer, "%d", get_int());
return buf; return _buffer;
case LONG: case LONG:
sprintf(buf, "%ld", get_long()); sprintf(_buffer, "%ld", get_long());
return buf; return _buffer;
case FLOAT: case FLOAT:
sprintf(buf, "%f", get_float()); sprintf(_buffer, "%f", get_float());
return buf; return _buffer;
case DOUBLE: case DOUBLE:
sprintf(buf, "%f", get_double()); sprintf(_buffer, "%f", get_double());
return buf; return _buffer;
case STRING: case STRING:
case UNSPECIFIED: case UNSPECIFIED:
return get_string(); return get_string();
@@ -485,8 +512,13 @@ SGPropertyNode::make_string () const
void void
SGPropertyNode::trace_write () const SGPropertyNode::trace_write () const
{ {
#if PROPS_STANDALONE
cerr << "TRACE: Write node " << getPath () << ", value\""
<< make_string() << '"' << endl;
#else
SG_LOG(SG_GENERAL, SG_INFO, "TRACE: Write node " << getPath() SG_LOG(SG_GENERAL, SG_INFO, "TRACE: Write node " << getPath()
<< ", value\"" << make_string() << '"'); << ", value\"" << make_string() << '"');
#endif
} }
/** /**
@@ -495,8 +527,13 @@ SGPropertyNode::trace_write () const
void void
SGPropertyNode::trace_read () const SGPropertyNode::trace_read () const
{ {
#if PROPS_STANDALONE
cerr << "TRACE: Write node " << getPath () << ", value \""
<< make_string() << '"' << endl;
#else
SG_LOG(SG_GENERAL, SG_INFO, "TRACE: Read node " << getPath() SG_LOG(SG_GENERAL, SG_INFO, "TRACE: Read node " << getPath()
<< ", value \"" << make_string() << '"'); << ", value \"" << make_string() << '"');
#endif
} }
@@ -509,7 +546,7 @@ SGPropertyNode::trace_read () const
* Default constructor: always creates a root node. * Default constructor: always creates a root node.
*/ */
SGPropertyNode::SGPropertyNode () SGPropertyNode::SGPropertyNode ()
: _name(""), : _name(copy_string("")),
_index(0), _index(0),
_parent(0), _parent(0),
_path_cache(0), _path_cache(0),
@@ -517,6 +554,7 @@ SGPropertyNode::SGPropertyNode ()
_tied(false), _tied(false),
_attr(READ|WRITE) _attr(READ|WRITE)
{ {
_local_val.string_val = 0;
} }
@@ -524,14 +562,15 @@ SGPropertyNode::SGPropertyNode ()
* Copy constructor. * Copy constructor.
*/ */
SGPropertyNode::SGPropertyNode (const SGPropertyNode &node) SGPropertyNode::SGPropertyNode (const SGPropertyNode &node)
: _name(node._name), : _index(node._index),
_index(node._index),
_parent(0), // don't copy the parent _parent(0), // don't copy the parent
_path_cache(0), _path_cache(0),
_type(node._type), _type(node._type),
_tied(node._tied), _tied(node._tied),
_attr(node._attr) _attr(node._attr)
{ {
_name = copy_string(node._name);
_local_val.string_val = 0;
switch (_type) { switch (_type) {
case NONE: case NONE:
break; break;
@@ -591,7 +630,6 @@ SGPropertyNode::SGPropertyNode (const SGPropertyNode &node)
_value.string_val = node._value.string_val->clone(); _value.string_val = node._value.string_val->clone();
} else { } else {
_tied = false; _tied = false;
_local_val.string_val = new string;
set_string(node.get_string()); set_string(node.get_string());
} }
break; break;
@@ -602,16 +640,18 @@ SGPropertyNode::SGPropertyNode (const SGPropertyNode &node)
/** /**
* Convenience constructor. * Convenience constructor.
*/ */
SGPropertyNode::SGPropertyNode (const string &name, SGPropertyNode::SGPropertyNode (const char * name,
int index, SGPropertyNode * parent) int index,
: _name(name), SGPropertyNode * parent)
_index(index), : _index(index),
_parent(parent), _parent(parent),
_path_cache(0), _path_cache(0),
_type(NONE), _type(NONE),
_tied(false), _tied(false),
_attr(READ|WRITE) _attr(READ|WRITE)
{ {
_name = copy_string(name);
_local_val.string_val = 0;
} }
@@ -620,10 +660,11 @@ SGPropertyNode::SGPropertyNode (const string &name,
*/ */
SGPropertyNode::~SGPropertyNode () SGPropertyNode::~SGPropertyNode ()
{ {
delete _name;
for (int i = 0; i < (int)_children.size(); i++) { for (int i = 0; i < (int)_children.size(); i++) {
delete _children[i]; delete _children[i];
} }
delete _path_cache; // delete _path_cache;
clear_value(); clear_value();
} }
@@ -647,7 +688,7 @@ SGPropertyNode::alias (SGPropertyNode * target)
* Alias to another node by path. * Alias to another node by path.
*/ */
bool bool
SGPropertyNode::alias (const string &path) SGPropertyNode::alias (const char * path)
{ {
return alias(getNode(path, true)); return alias(getNode(path, true));
} }
@@ -714,7 +755,7 @@ SGPropertyNode::getChild (int position) const
* Get a non-const child by name and index, creating if necessary. * Get a non-const child by name and index, creating if necessary.
*/ */
SGPropertyNode * SGPropertyNode *
SGPropertyNode::getChild (const string &name, int index, bool create) SGPropertyNode::getChild (const char * name, int index, bool create)
{ {
int pos = find_child(name, index, _children); int pos = find_child(name, index, _children);
if (pos >= 0) { if (pos >= 0) {
@@ -732,7 +773,7 @@ SGPropertyNode::getChild (const string &name, int index, bool create)
* Get a const child by name and index. * Get a const child by name and index.
*/ */
const SGPropertyNode * const SGPropertyNode *
SGPropertyNode::getChild (const string &name, int index) const SGPropertyNode::getChild (const char * name, int index) const
{ {
int pos = find_child(name, index, _children); int pos = find_child(name, index, _children);
if (pos >= 0) if (pos >= 0)
@@ -746,13 +787,13 @@ SGPropertyNode::getChild (const string &name, int index) const
* Get all children with the same name (but different indices). * Get all children with the same name (but different indices).
*/ */
vector<SGPropertyNode *> vector<SGPropertyNode *>
SGPropertyNode::getChildren (const string &name) SGPropertyNode::getChildren (const char * name)
{ {
vector<SGPropertyNode *> children; vector<SGPropertyNode *> children;
int max = _children.size(); int max = _children.size();
for (int i = 0; i < max; i++) for (int i = 0; i < max; i++)
if (_children[i]->getName() == name) if (compare_strings(_children[i]->getName(), name))
children.push_back(_children[i]); children.push_back(_children[i]);
sort(children.begin(), children.end(), CompareIndices()); sort(children.begin(), children.end(), CompareIndices());
@@ -764,13 +805,13 @@ SGPropertyNode::getChildren (const string &name)
* Get all children const with the same name (but different indices). * Get all children const with the same name (but different indices).
*/ */
vector<const SGPropertyNode *> vector<const SGPropertyNode *>
SGPropertyNode::getChildren (const string &name) const SGPropertyNode::getChildren (const char * name) const
{ {
vector<const SGPropertyNode *> children; vector<const SGPropertyNode *> children;
int max = _children.size(); int max = _children.size();
for (int i = 0; i < max; i++) for (int i = 0; i < max; i++)
if (_children[i]->getName() == name) if (compare_strings(_children[i]->getName(), name))
children.push_back(_children[i]); children.push_back(_children[i]);
sort(children.begin(), children.end(), CompareIndices()); sort(children.begin(), children.end(), CompareIndices());
@@ -778,7 +819,7 @@ SGPropertyNode::getChildren (const string &name) const
} }
string const char *
SGPropertyNode::getPath (bool simplify) const SGPropertyNode::getPath (bool simplify) const
{ {
if (_parent == 0) if (_parent == 0)
@@ -792,7 +833,7 @@ SGPropertyNode::getPath (bool simplify) const
sprintf(buffer, "[%d]", _index); sprintf(buffer, "[%d]", _index);
path += buffer; path += buffer;
} }
return path; return path.c_str();
} }
SGPropertyNode::Type SGPropertyNode::Type
@@ -831,7 +872,7 @@ SGPropertyNode::getBoolValue () const
return get_double() == 0.0L ? false : true; return get_double() == 0.0L ? false : true;
case STRING: case STRING:
case UNSPECIFIED: case UNSPECIFIED:
return (get_string() == "true" || getDoubleValue() != 0.0L); return (compare_strings(get_string(), "true") || getDoubleValue() != 0.0L);
case NONE: case NONE:
default: default:
return SGRawValue<bool>::DefaultValue; return SGRawValue<bool>::DefaultValue;
@@ -864,7 +905,7 @@ SGPropertyNode::getIntValue () const
return int(get_double()); return int(get_double());
case STRING: case STRING:
case UNSPECIFIED: case UNSPECIFIED:
return atoi(get_string().c_str()); return atoi(get_string());
case NONE: case NONE:
default: default:
return SGRawValue<int>::DefaultValue; return SGRawValue<int>::DefaultValue;
@@ -897,7 +938,7 @@ SGPropertyNode::getLongValue () const
return long(get_double()); return long(get_double());
case STRING: case STRING:
case UNSPECIFIED: case UNSPECIFIED:
return strtol(get_string().c_str(), 0, 0); return strtol(get_string(), 0, 0);
case NONE: case NONE:
default: default:
return SGRawValue<long>::DefaultValue; return SGRawValue<long>::DefaultValue;
@@ -930,7 +971,7 @@ SGPropertyNode::getFloatValue () const
return float(get_double()); return float(get_double());
case STRING: case STRING:
case UNSPECIFIED: case UNSPECIFIED:
return atof(get_string().c_str()); return atof(get_string());
case NONE: case NONE:
default: default:
return SGRawValue<float>::DefaultValue; return SGRawValue<float>::DefaultValue;
@@ -964,14 +1005,14 @@ SGPropertyNode::getDoubleValue () const
return get_double(); return get_double();
case STRING: case STRING:
case UNSPECIFIED: case UNSPECIFIED:
return strtod(get_string().c_str(), 0); return strtod(get_string(), 0);
case NONE: case NONE:
default: default:
return SGRawValue<double>::DefaultValue; return SGRawValue<double>::DefaultValue;
} }
} }
string const char *
SGPropertyNode::getStringValue () const SGPropertyNode::getStringValue () const
{ {
// Shortcut for common case // Shortcut for common case
@@ -981,7 +1022,7 @@ SGPropertyNode::getStringValue () const
if (getAttribute(TRACE_READ)) if (getAttribute(TRACE_READ))
trace_read(); trace_read();
if (!getAttribute(READ)) if (!getAttribute(READ))
return SGRawValue<string>::DefaultValue; return SGRawValue<const char *>::DefaultValue;
return make_string(); return make_string();
} }
@@ -1238,7 +1279,7 @@ SGPropertyNode::setDoubleValue (double value)
} }
bool bool
SGPropertyNode::setStringValue (string value) SGPropertyNode::setStringValue (const char * value)
{ {
// Shortcut for common case // Shortcut for common case
if (_attr == (READ|WRITE) && _type == STRING) if (_attr == (READ|WRITE) && _type == STRING)
@@ -1248,7 +1289,6 @@ SGPropertyNode::setStringValue (string value)
TEST_WRITE; TEST_WRITE;
if (_type == NONE || _type == UNSPECIFIED) { if (_type == NONE || _type == UNSPECIFIED) {
clear_value(); clear_value();
_local_val.string_val = new string;
_type = STRING; _type = STRING;
} }
@@ -1257,19 +1297,20 @@ SGPropertyNode::setStringValue (string value)
result = _value.alias->setStringValue(value); result = _value.alias->setStringValue(value);
break; break;
case BOOL: case BOOL:
result = set_bool((value == "true" || atoi(value.c_str())) ? true : false); result = set_bool((compare_strings(value, "true")
|| atoi(value)) ? true : false);
break; break;
case INT: case INT:
result = set_int(atoi(value.c_str())); result = set_int(atoi(value));
break; break;
case LONG: case LONG:
result = set_long(strtol(value.c_str(), 0, 0)); result = set_long(strtol(value, 0, 0));
break; break;
case FLOAT: case FLOAT:
result = set_float(atof(value.c_str())); result = set_float(atof(value));
break; break;
case DOUBLE: case DOUBLE:
result = set_double(strtod(value.c_str(), 0)); result = set_double(strtod(value, 0));
break; break;
case STRING: case STRING:
case UNSPECIFIED: case UNSPECIFIED:
@@ -1286,13 +1327,12 @@ SGPropertyNode::setStringValue (string value)
} }
bool bool
SGPropertyNode::setUnspecifiedValue (string value) SGPropertyNode::setUnspecifiedValue (const char * value)
{ {
bool result = false; bool result = false;
TEST_WRITE; TEST_WRITE;
if (_type == NONE) { if (_type == NONE) {
clear_value(); clear_value();
_local_val.string_val = new string;
_type = UNSPECIFIED; _type = UNSPECIFIED;
} }
@@ -1301,19 +1341,20 @@ SGPropertyNode::setUnspecifiedValue (string value)
result = _value.alias->setUnspecifiedValue(value); result = _value.alias->setUnspecifiedValue(value);
break; break;
case BOOL: case BOOL:
result = set_bool((value == "true" || atoi(value.c_str())) ? true : false); result = set_bool((compare_strings(value, "true")
|| atoi(value)) ? true : false);
break; break;
case INT: case INT:
result = set_int(atoi(value.c_str())); result = set_int(atoi(value));
break; break;
case LONG: case LONG:
result = set_long(strtol(value.c_str(), 0, 0)); result = set_long(strtol(value, 0, 0));
break; break;
case FLOAT: case FLOAT:
result = set_float(atof(value.c_str())); result = set_float(atof(value));
break; break;
case DOUBLE: case DOUBLE:
result = set_double(strtod(value.c_str(), 0)); result = set_double(strtod(value, 0));
break; break;
case STRING: case STRING:
case UNSPECIFIED: case UNSPECIFIED:
@@ -1441,7 +1482,7 @@ SGPropertyNode::tie (const SGRawValue<double> &rawValue, bool useDefault)
} }
bool bool
SGPropertyNode::tie (const SGRawValue<string> &rawValue, bool useDefault) SGPropertyNode::tie (const SGRawValue<const char *> &rawValue, bool useDefault)
{ {
if (_type == ALIAS || _tied) if (_type == ALIAS || _tied)
return false; return false;
@@ -1457,7 +1498,7 @@ SGPropertyNode::tie (const SGRawValue<string> &rawValue, bool useDefault)
_value.string_val = rawValue.clone(); _value.string_val = rawValue.clone();
if (useDefault) if (useDefault)
setStringValue(old_val); setStringValue(old_val.c_str());
return true; return true;
} }
@@ -1509,7 +1550,7 @@ SGPropertyNode::untie ()
string val = getStringValue(); string val = getStringValue();
clear_value(); clear_value();
_type = STRING; _type = STRING;
_local_val.string_val = new string(val); _local_val.string_val = copy_string(val.c_str());
break; break;
} }
case NONE: case NONE:
@@ -1540,25 +1581,28 @@ SGPropertyNode::getRootNode () const
} }
SGPropertyNode * SGPropertyNode *
SGPropertyNode::getNode (const string &relative_path, bool create) SGPropertyNode::getNode (const char * relative_path, bool create)
{ {
if (_path_cache == 0) // if (_path_cache == 0)
_path_cache = new cache_map; // _path_cache = new cache_map;
SGPropertyNode * result = (*_path_cache)[relative_path]; // SGPropertyNode * result = (*_path_cache)[relative_path];
if (result == 0) { // if (result == 0) {
vector<PathComponent> components; // vector<PathComponent> components;
parse_path(relative_path, components); // parse_path(relative_path, components);
result = find_node(this, components, 0, create); // result = find_node(this, components, 0, create);
if (result != 0) // if (result != 0)
(*_path_cache)[relative_path] = result; // (*_path_cache)[relative_path] = result;
} // }
return result; // return result;
vector<PathComponent> components;
parse_path(relative_path, components);
return find_node(this, components, 0, create);
} }
SGPropertyNode * SGPropertyNode *
SGPropertyNode::getNode (const string &relative_path, int index, bool create) SGPropertyNode::getNode (const char * relative_path, int index, bool create)
{ {
vector<PathComponent> components; vector<PathComponent> components;
parse_path(relative_path, components); parse_path(relative_path, components);
@@ -1568,13 +1612,13 @@ SGPropertyNode::getNode (const string &relative_path, int index, bool create)
} }
const SGPropertyNode * const SGPropertyNode *
SGPropertyNode::getNode (const string &relative_path) const SGPropertyNode::getNode (const char * relative_path) const
{ {
return ((SGPropertyNode *)this)->getNode(relative_path, false); return ((SGPropertyNode *)this)->getNode(relative_path, false);
} }
const SGPropertyNode * const SGPropertyNode *
SGPropertyNode::getNode (const string &relative_path, int index) const SGPropertyNode::getNode (const char * relative_path, int index) const
{ {
return ((SGPropertyNode *)this)->getNode(relative_path, index, false); return ((SGPropertyNode *)this)->getNode(relative_path, index, false);
} }
@@ -1589,7 +1633,7 @@ SGPropertyNode::getNode (const string &relative_path, int index) const
* Test whether another node has a value attached. * Test whether another node has a value attached.
*/ */
bool bool
SGPropertyNode::hasValue (const string &relative_path) const SGPropertyNode::hasValue (const char * relative_path) const
{ {
const SGPropertyNode * node = getNode(relative_path); const SGPropertyNode * node = getNode(relative_path);
return (node == 0 ? false : node->hasValue()); return (node == 0 ? false : node->hasValue());
@@ -1600,7 +1644,7 @@ SGPropertyNode::hasValue (const string &relative_path) const
* Get the value type for another node. * Get the value type for another node.
*/ */
SGPropertyNode::Type SGPropertyNode::Type
SGPropertyNode::getType (const string &relative_path) const SGPropertyNode::getType (const char * relative_path) const
{ {
const SGPropertyNode * node = getNode(relative_path); const SGPropertyNode * node = getNode(relative_path);
return (node == 0 ? UNSPECIFIED : (Type)(node->getType())); return (node == 0 ? UNSPECIFIED : (Type)(node->getType()));
@@ -1611,7 +1655,7 @@ SGPropertyNode::getType (const string &relative_path) const
* Get a bool value for another node. * Get a bool value for another node.
*/ */
bool bool
SGPropertyNode::getBoolValue (const string &relative_path, SGPropertyNode::getBoolValue (const char * relative_path,
bool defaultValue) const bool defaultValue) const
{ {
const SGPropertyNode * node = getNode(relative_path); const SGPropertyNode * node = getNode(relative_path);
@@ -1623,7 +1667,7 @@ SGPropertyNode::getBoolValue (const string &relative_path,
* Get an int value for another node. * Get an int value for another node.
*/ */
int int
SGPropertyNode::getIntValue (const string &relative_path, SGPropertyNode::getIntValue (const char * relative_path,
int defaultValue) const int defaultValue) const
{ {
const SGPropertyNode * node = getNode(relative_path); const SGPropertyNode * node = getNode(relative_path);
@@ -1635,7 +1679,7 @@ SGPropertyNode::getIntValue (const string &relative_path,
* Get a long value for another node. * Get a long value for another node.
*/ */
long long
SGPropertyNode::getLongValue (const string &relative_path, SGPropertyNode::getLongValue (const char * relative_path,
long defaultValue) const long defaultValue) const
{ {
const SGPropertyNode * node = getNode(relative_path); const SGPropertyNode * node = getNode(relative_path);
@@ -1647,7 +1691,7 @@ SGPropertyNode::getLongValue (const string &relative_path,
* Get a float value for another node. * Get a float value for another node.
*/ */
float float
SGPropertyNode::getFloatValue (const string &relative_path, SGPropertyNode::getFloatValue (const char * relative_path,
float defaultValue) const float defaultValue) const
{ {
const SGPropertyNode * node = getNode(relative_path); const SGPropertyNode * node = getNode(relative_path);
@@ -1659,7 +1703,7 @@ SGPropertyNode::getFloatValue (const string &relative_path,
* Get a double value for another node. * Get a double value for another node.
*/ */
double double
SGPropertyNode::getDoubleValue (const string &relative_path, SGPropertyNode::getDoubleValue (const char * relative_path,
double defaultValue) const double defaultValue) const
{ {
const SGPropertyNode * node = getNode(relative_path); const SGPropertyNode * node = getNode(relative_path);
@@ -1670,9 +1714,9 @@ SGPropertyNode::getDoubleValue (const string &relative_path,
/** /**
* Get a string value for another node. * Get a string value for another node.
*/ */
string const char *
SGPropertyNode::getStringValue (const string &relative_path, SGPropertyNode::getStringValue (const char * relative_path,
string defaultValue) const const char * defaultValue) const
{ {
const SGPropertyNode * node = getNode(relative_path); const SGPropertyNode * node = getNode(relative_path);
return (node == 0 ? defaultValue : node->getStringValue()); return (node == 0 ? defaultValue : node->getStringValue());
@@ -1683,7 +1727,7 @@ SGPropertyNode::getStringValue (const string &relative_path,
* Set a bool value for another node. * Set a bool value for another node.
*/ */
bool bool
SGPropertyNode::setBoolValue (const string &relative_path, bool value) SGPropertyNode::setBoolValue (const char * relative_path, bool value)
{ {
return getNode(relative_path, true)->setBoolValue(value); return getNode(relative_path, true)->setBoolValue(value);
} }
@@ -1693,7 +1737,7 @@ SGPropertyNode::setBoolValue (const string &relative_path, bool value)
* Set an int value for another node. * Set an int value for another node.
*/ */
bool bool
SGPropertyNode::setIntValue (const string &relative_path, int value) SGPropertyNode::setIntValue (const char * relative_path, int value)
{ {
return getNode(relative_path, true)->setIntValue(value); return getNode(relative_path, true)->setIntValue(value);
} }
@@ -1703,7 +1747,7 @@ SGPropertyNode::setIntValue (const string &relative_path, int value)
* Set a long value for another node. * Set a long value for another node.
*/ */
bool bool
SGPropertyNode::setLongValue (const string &relative_path, long value) SGPropertyNode::setLongValue (const char * relative_path, long value)
{ {
return getNode(relative_path, true)->setLongValue(value); return getNode(relative_path, true)->setLongValue(value);
} }
@@ -1713,7 +1757,7 @@ SGPropertyNode::setLongValue (const string &relative_path, long value)
* Set a float value for another node. * Set a float value for another node.
*/ */
bool bool
SGPropertyNode::setFloatValue (const string &relative_path, float value) SGPropertyNode::setFloatValue (const char * relative_path, float value)
{ {
return getNode(relative_path, true)->setFloatValue(value); return getNode(relative_path, true)->setFloatValue(value);
} }
@@ -1723,7 +1767,7 @@ SGPropertyNode::setFloatValue (const string &relative_path, float value)
* Set a double value for another node. * Set a double value for another node.
*/ */
bool bool
SGPropertyNode::setDoubleValue (const string &relative_path, double value) SGPropertyNode::setDoubleValue (const char * relative_path, double value)
{ {
return getNode(relative_path, true)->setDoubleValue(value); return getNode(relative_path, true)->setDoubleValue(value);
} }
@@ -1733,7 +1777,7 @@ SGPropertyNode::setDoubleValue (const string &relative_path, double value)
* Set a string value for another node. * Set a string value for another node.
*/ */
bool bool
SGPropertyNode::setStringValue (const string &relative_path, string value) SGPropertyNode::setStringValue (const char * relative_path, const char * value)
{ {
return getNode(relative_path, true)->setStringValue(value); return getNode(relative_path, true)->setStringValue(value);
} }
@@ -1743,7 +1787,8 @@ SGPropertyNode::setStringValue (const string &relative_path, string value)
* Set an unknown value for another node. * Set an unknown value for another node.
*/ */
bool bool
SGPropertyNode::setUnspecifiedValue (const string &relative_path, string value) SGPropertyNode::setUnspecifiedValue (const char * relative_path,
const char * value)
{ {
return getNode(relative_path, true)->setUnspecifiedValue(value); return getNode(relative_path, true)->setUnspecifiedValue(value);
} }
@@ -1753,7 +1798,7 @@ SGPropertyNode::setUnspecifiedValue (const string &relative_path, string value)
* Test whether another node is tied. * Test whether another node is tied.
*/ */
bool bool
SGPropertyNode::isTied (const string &relative_path) const SGPropertyNode::isTied (const char * relative_path) const
{ {
const SGPropertyNode * node = getNode(relative_path); const SGPropertyNode * node = getNode(relative_path);
return (node == 0 ? false : node->isTied()); return (node == 0 ? false : node->isTied());
@@ -1764,7 +1809,7 @@ SGPropertyNode::isTied (const string &relative_path) const
* Tie a node reached by a relative path, creating it if necessary. * Tie a node reached by a relative path, creating it if necessary.
*/ */
bool bool
SGPropertyNode::tie (const string &relative_path, SGPropertyNode::tie (const char * relative_path,
const SGRawValue<bool> &rawValue, const SGRawValue<bool> &rawValue,
bool useDefault) bool useDefault)
{ {
@@ -1776,7 +1821,7 @@ SGPropertyNode::tie (const string &relative_path,
* Tie a node reached by a relative path, creating it if necessary. * Tie a node reached by a relative path, creating it if necessary.
*/ */
bool bool
SGPropertyNode::tie (const string &relative_path, SGPropertyNode::tie (const char * relative_path,
const SGRawValue<int> &rawValue, const SGRawValue<int> &rawValue,
bool useDefault) bool useDefault)
{ {
@@ -1788,7 +1833,7 @@ SGPropertyNode::tie (const string &relative_path,
* Tie a node reached by a relative path, creating it if necessary. * Tie a node reached by a relative path, creating it if necessary.
*/ */
bool bool
SGPropertyNode::tie (const string &relative_path, SGPropertyNode::tie (const char * relative_path,
const SGRawValue<long> &rawValue, const SGRawValue<long> &rawValue,
bool useDefault) bool useDefault)
{ {
@@ -1800,7 +1845,7 @@ SGPropertyNode::tie (const string &relative_path,
* Tie a node reached by a relative path, creating it if necessary. * Tie a node reached by a relative path, creating it if necessary.
*/ */
bool bool
SGPropertyNode::tie (const string &relative_path, SGPropertyNode::tie (const char * relative_path,
const SGRawValue<float> &rawValue, const SGRawValue<float> &rawValue,
bool useDefault) bool useDefault)
{ {
@@ -1812,7 +1857,7 @@ SGPropertyNode::tie (const string &relative_path,
* Tie a node reached by a relative path, creating it if necessary. * Tie a node reached by a relative path, creating it if necessary.
*/ */
bool bool
SGPropertyNode::tie (const string &relative_path, SGPropertyNode::tie (const char * relative_path,
const SGRawValue<double> &rawValue, const SGRawValue<double> &rawValue,
bool useDefault) bool useDefault)
{ {
@@ -1824,8 +1869,8 @@ SGPropertyNode::tie (const string &relative_path,
* Tie a node reached by a relative path, creating it if necessary. * Tie a node reached by a relative path, creating it if necessary.
*/ */
bool bool
SGPropertyNode::tie (const string &relative_path, SGPropertyNode::tie (const char * relative_path,
const SGRawValue<string> &rawValue, const SGRawValue<const char *> &rawValue,
bool useDefault) bool useDefault)
{ {
return getNode(relative_path, true)->tie(rawValue, useDefault); return getNode(relative_path, true)->tie(rawValue, useDefault);
@@ -1836,7 +1881,7 @@ SGPropertyNode::tie (const string &relative_path,
* Attempt to untie another node reached by a relative path. * Attempt to untie another node reached by a relative path.
*/ */
bool bool
SGPropertyNode::untie (const string &relative_path) SGPropertyNode::untie (const char * relative_path)
{ {
SGPropertyNode * node = getNode(relative_path); SGPropertyNode * node = getNode(relative_path);
return (node == 0 ? false : node->untie()); return (node == 0 ? false : node->untie());
+78 -52
View File
@@ -12,16 +12,30 @@
#ifndef __PROPS_HXX #ifndef __PROPS_HXX
#define __PROPS_HXX #define __PROPS_HXX
#include <simgear/compiler.h> #ifndef PROPS_STANDALONE
#include <simgear/debug/logstream.hxx> #define PROPS_STANDALONE 0
#endif
#include <stdio.h>
#include STL_STRING
#include <vector> #include <vector>
#include <map> #include <map>
#include STL_IOSTREAM
#if PROPS_STANDALONE
#include <string>
#include <iostream>
using std::string;
using std::vector;
using std::map;
using std::istream;
using std::ostream;
#else
#include <simgear/compiler.h>
#include <simgear/debug/logstream.hxx>
#include STL_STRING
#include STL_IOSTREAM
SG_USING_STD(string); SG_USING_STD(string);
SG_USING_STD(vector); SG_USING_STD(vector);
SG_USING_STD(map); SG_USING_STD(map);
@@ -30,6 +44,9 @@ SG_USING_STD(istream);
SG_USING_STD(ostream); SG_USING_STD(ostream);
#endif #endif
#endif
#ifdef NONE #ifdef NONE
#pragma warn A sloppy coder has defined NONE as a macro! #pragma warn A sloppy coder has defined NONE as a macro!
#undef NONE #undef NONE
@@ -444,6 +461,13 @@ class SGPropertyNode
{ {
public: public:
/**
* Public constants.
*/
enum {
MAX_STRING_LEN = 1024
};
/** /**
* Property value types. * Property value types.
*/ */
@@ -507,7 +531,7 @@ public:
/** /**
* Get the node's simple (XML) name. * Get the node's simple (XML) name.
*/ */
const string &getName () const { return _name; } const char * getName () const { return _name; }
/** /**
@@ -554,26 +578,26 @@ public:
/** /**
* Get a child node by name and index. * Get a child node by name and index.
*/ */
SGPropertyNode * getChild (const string &name, int index = 0, SGPropertyNode * getChild (const char * name, int index = 0,
bool create = false); bool create = false);
/** /**
* Get a const child node by name and index. * Get a const child node by name and index.
*/ */
const SGPropertyNode * getChild (const string &name, int index = 0) const; const SGPropertyNode * getChild (const char * name, int index = 0) const;
/** /**
* Get a vector of all children with the specified name. * Get a vector of all children with the specified name.
*/ */
vector<SGPropertyNode *> getChildren (const string &name); vector<SGPropertyNode *> getChildren (const char * name);
/** /**
* Get a vector all all children (const) with the specified name. * Get a vector all all children (const) with the specified name.
*/ */
vector<const SGPropertyNode *> getChildren (const string &name) const; vector<const SGPropertyNode *> getChildren (const char * name) const;
// //
@@ -590,7 +614,7 @@ public:
/** /**
* Alias this node's leaf value to another's by relative path. * Alias this node's leaf value to another's by relative path.
*/ */
bool alias (const string &path); bool alias (const char * path);
/** /**
@@ -625,7 +649,7 @@ public:
/** /**
* Get the path to this node from the root. * Get the path to this node from the root.
*/ */
string getPath (bool simplify = false) const; const char * getPath (bool simplify = false) const;
/** /**
@@ -643,7 +667,7 @@ public:
/** /**
* Get a pointer to another node by relative path. * Get a pointer to another node by relative path.
*/ */
SGPropertyNode * getNode (const string &relative_path, bool create = false); SGPropertyNode * getNode (const char * relative_path, bool create = false);
/** /**
@@ -656,14 +680,14 @@ public:
* provided overrides any given in the path itself for the last * provided overrides any given in the path itself for the last
* component. * component.
*/ */
SGPropertyNode * getNode (const string &relative_path, int index, SGPropertyNode * getNode (const char * relative_path, int index,
bool create = false); bool create = false);
/** /**
* Get a const pointer to another node by relative path. * Get a const pointer to another node by relative path.
*/ */
const SGPropertyNode * getNode (const string &relative_path) const; const SGPropertyNode * getNode (const char * relative_path) const;
/** /**
@@ -672,7 +696,7 @@ public:
* This method leaves the index off the last member of the path, * This method leaves the index off the last member of the path,
* so that the user can specify it separate. * so that the user can specify it separate.
*/ */
const SGPropertyNode * getNode (const string &relative_path, const SGPropertyNode * getNode (const char * relative_path,
int index) const; int index) const;
@@ -750,7 +774,7 @@ public:
/** /**
* Get a string value for this node. * Get a string value for this node.
*/ */
string getStringValue () const; const char * getStringValue () const;
@@ -787,13 +811,13 @@ public:
/** /**
* Set a string value for this node. * Set a string value for this node.
*/ */
bool setStringValue (string value); bool setStringValue (const char * value);
/** /**
* Set a value of unspecified type for this node. * Set a value of unspecified type for this node.
*/ */
bool setUnspecifiedValue (string value); bool setUnspecifiedValue (const char * value);
// //
@@ -840,7 +864,7 @@ public:
/** /**
* Bind this node to an external string source. * Bind this node to an external string source.
*/ */
bool tie (const SGRawValue<string> &rawValue, bool useDefault = true); bool tie (const SGRawValue<const char *> &rawValue, bool useDefault = true);
/** /**
@@ -858,151 +882,151 @@ public:
/** /**
* Get another node's type. * Get another node's type.
*/ */
Type getType (const string &relative_path) const; Type getType (const char * relative_path) const;
/** /**
* Test whether another node has a leaf value. * Test whether another node has a leaf value.
*/ */
bool hasValue (const string &relative_path) const; bool hasValue (const char * relative_path) const;
/** /**
* Get another node's value as a bool. * Get another node's value as a bool.
*/ */
bool getBoolValue (const string &relative_path, bool getBoolValue (const char * relative_path,
bool defaultValue = false) const; bool defaultValue = false) const;
/** /**
* Get another node's value as an int. * Get another node's value as an int.
*/ */
int getIntValue (const string &relative_path, int getIntValue (const char * relative_path,
int defaultValue = 0) const; int defaultValue = 0) const;
/** /**
* Get another node's value as a long int. * Get another node's value as a long int.
*/ */
long getLongValue (const string &relative_path, long getLongValue (const char * relative_path,
long defaultValue = 0L) const; long defaultValue = 0L) const;
/** /**
* Get another node's value as a float. * Get another node's value as a float.
*/ */
float getFloatValue (const string &relative_path, float getFloatValue (const char * relative_path,
float defaultValue = 0.0) const; float defaultValue = 0.0) const;
/** /**
* Get another node's value as a double. * Get another node's value as a double.
*/ */
double getDoubleValue (const string &relative_path, double getDoubleValue (const char * relative_path,
double defaultValue = 0.0L) const; double defaultValue = 0.0L) const;
/** /**
* Get another node's value as a string. * Get another node's value as a string.
*/ */
string getStringValue (const string &relative_path, const char * getStringValue (const char * relative_path,
string defaultValue = "") const; const char * defaultValue = "") const;
/** /**
* Set another node's value as a bool. * Set another node's value as a bool.
*/ */
bool setBoolValue (const string &relative_path, bool value); bool setBoolValue (const char * relative_path, bool value);
/** /**
* Set another node's value as an int. * Set another node's value as an int.
*/ */
bool setIntValue (const string &relative_path, int value); bool setIntValue (const char * relative_path, int value);
/** /**
* Set another node's value as a long int. * Set another node's value as a long int.
*/ */
bool setLongValue (const string &relative_path, long value); bool setLongValue (const char * relative_path, long value);
/** /**
* Set another node's value as a float. * Set another node's value as a float.
*/ */
bool setFloatValue (const string &relative_path, float value); bool setFloatValue (const char * relative_path, float value);
/** /**
* Set another node's value as a double. * Set another node's value as a double.
*/ */
bool setDoubleValue (const string &relative_path, double value); bool setDoubleValue (const char * relative_path, double value);
/** /**
* Set another node's value as a string. * Set another node's value as a string.
*/ */
bool setStringValue (const string &relative_path, string value); bool setStringValue (const char * relative_path, const char * value);
/** /**
* Set another node's value with no specified type. * Set another node's value with no specified type.
*/ */
bool setUnspecifiedValue (const string &relative_path, string value); bool setUnspecifiedValue (const char * relative_path, const char * value);
/** /**
* Test whether another node is bound to an external data source. * Test whether another node is bound to an external data source.
*/ */
bool isTied (const string &relative_path) const; bool isTied (const char * relative_path) const;
/** /**
* Bind another node to an external bool source. * Bind another node to an external bool source.
*/ */
bool tie (const string &relative_path, const SGRawValue<bool> &rawValue, bool tie (const char * relative_path, const SGRawValue<bool> &rawValue,
bool useDefault = true); bool useDefault = true);
/** /**
* Bind another node to an external int source. * Bind another node to an external int source.
*/ */
bool tie (const string &relative_path, const SGRawValue<int> &rawValue, bool tie (const char * relative_path, const SGRawValue<int> &rawValue,
bool useDefault = true); bool useDefault = true);
/** /**
* Bind another node to an external long int source. * Bind another node to an external long int source.
*/ */
bool tie (const string &relative_path, const SGRawValue<long> &rawValue, bool tie (const char * relative_path, const SGRawValue<long> &rawValue,
bool useDefault = true); bool useDefault = true);
/** /**
* Bind another node to an external float source. * Bind another node to an external float source.
*/ */
bool tie (const string &relative_path, const SGRawValue<float> &rawValue, bool tie (const char * relative_path, const SGRawValue<float> &rawValue,
bool useDefault = true); bool useDefault = true);
/** /**
* Bind another node to an external double source. * Bind another node to an external double source.
*/ */
bool tie (const string &relative_path, const SGRawValue<double> &rawValue, bool tie (const char * relative_path, const SGRawValue<double> &rawValue,
bool useDefault = true); bool useDefault = true);
/** /**
* Bind another node to an external string source. * Bind another node to an external string source.
*/ */
bool tie (const string &relative_path, const SGRawValue<string> &rawValue, bool tie (const char * relative_path, const SGRawValue<const char *> &rawValue,
bool useDefault = true); bool useDefault = true);
/** /**
* Unbind another node from any external data source. * Unbind another node from any external data source.
*/ */
bool untie (const string &relative_path); bool untie (const char * relative_path);
protected: protected:
@@ -1011,7 +1035,7 @@ protected:
/** /**
* Protected constructor for making new nodes on demand. * Protected constructor for making new nodes on demand.
*/ */
SGPropertyNode (const string &name, int index, SGPropertyNode * parent); SGPropertyNode (const char * name, int index, SGPropertyNode * parent);
private: private:
@@ -1022,7 +1046,7 @@ private:
long get_long () const; long get_long () const;
float get_float () const; float get_float () const;
double get_double () const; double get_double () const;
const string get_string () const; const char * get_string () const;
// Set the raw value // Set the raw value
bool set_bool (bool value); bool set_bool (bool value);
@@ -1030,7 +1054,7 @@ private:
bool set_long (long value); bool set_long (long value);
bool set_float (float value); bool set_float (float value);
bool set_double (double value); bool set_double (double value);
bool set_string (const string &value); bool set_string (const char * value);
/** /**
@@ -1042,7 +1066,7 @@ private:
/** /**
* Get the value as a string. * Get the value as a string.
*/ */
string make_string () const; const char * make_string () const;
/** /**
@@ -1056,7 +1080,9 @@ private:
*/ */
void trace_write () const; void trace_write () const;
string _name; mutable char _buffer[MAX_STRING_LEN+1];
const char * _name;
int _index; int _index;
SGPropertyNode * _parent; SGPropertyNode * _parent;
vector<SGPropertyNode *> _children; vector<SGPropertyNode *> _children;
@@ -1074,7 +1100,7 @@ private:
SGRawValue<long> * long_val; SGRawValue<long> * long_val;
SGRawValue<float> * float_val; SGRawValue<float> * float_val;
SGRawValue<double> * double_val; SGRawValue<double> * double_val;
SGRawValue<string> * string_val; SGRawValue<const char *> * string_val;
} _value; } _value;
union { union {
@@ -1083,7 +1109,7 @@ private:
long long_val; long long_val;
float float_val; float float_val;
double double_val; double double_val;
string * string_val; const char * string_val;
} _local_val; } _local_val;
+3 -3
View File
@@ -235,9 +235,9 @@ PropsVisitor::endElement (const char * name)
} else if (st.type == "double") { } else if (st.type == "double") {
ret = st.node->setDoubleValue(strtod(_data.c_str(), 0)); ret = st.node->setDoubleValue(strtod(_data.c_str(), 0));
} else if (st.type == "string") { } else if (st.type == "string") {
ret = st.node->setStringValue(_data); ret = st.node->setStringValue(_data.c_str());
} else if (st.type == "unspecified") { } else if (st.type == "unspecified") {
ret = st.node->setUnspecifiedValue(_data); ret = st.node->setUnspecifiedValue(_data.c_str());
} else { } else {
string message = "Unrecognized data type '"; string message = "Unrecognized data type '";
message += st.type; message += st.type;
@@ -438,7 +438,7 @@ writeNode (ostream &output, const SGPropertyNode * node,
if (!write_all && !isArchivable(node)) if (!write_all && !isArchivable(node))
return true; // Everything's OK, but we won't write. return true; // Everything's OK, but we won't write.
const string &name = node->getName(); const string name = node->getName();
int nChildren = node->nChildren(); int nChildren = node->nChildren();
// If there is a literal value, // If there is a literal value,
+11 -7
View File
@@ -53,7 +53,7 @@ static double getNum (int index) { return 1.0 / index; }
static void static void
show_values (const SGPropertyNode * node) show_values (const SGPropertyNode * node)
{ {
cout << "Bool: " << node->getBoolValue() << endl; cout << "Bool: " << (node->getBoolValue() ? "true" : "false") << endl;
cout << "Int: " << node->getIntValue() << endl; cout << "Int: " << node->getIntValue() << endl;
cout << "Float: " << node->getFloatValue() << endl; cout << "Float: " << node->getFloatValue() << endl;
cout << "Double: " << node->getDoubleValue() << endl; cout << "Double: " << node->getDoubleValue() << endl;
@@ -275,7 +275,7 @@ test_value ()
static void static void
dump_node (const SGPropertyNode * node) dump_node (const SGPropertyNode * node)
{ {
writeProperties(cout, node); writeProperties(cout, node, true);
} }
static void static void
@@ -333,11 +333,15 @@ int main (int ac, char ** av)
test_property_nodes(); test_property_nodes();
for (int i = 1; i < ac; i++) { for (int i = 1; i < ac; i++) {
cout << "Reading " << av[i] << endl; try {
SGPropertyNode root; cout << "Reading " << av[i] << endl;
readProperties(av[i], &root); SGPropertyNode root;
writeProperties(cout, &root); readProperties(av[i], &root);
cout << endl; writeProperties(cout, &root, true);
cout << endl;
} catch (string &message) {
cout << "Aborted with " << message << endl;
}
} }
return 0; return 0;