00001
00002
00003
00004
00005
00006
00007
00008
00009 #ifdef HAVE_CONFIG_H
00010 # include <simgear_config.h>
00011 #endif
00012
00013 #include "props.hxx"
00014
00015 #include <algorithm>
00016
00017 #include <sstream>
00018 #include <iomanip>
00019 #include <iterator>
00020 #include <stdio.h>
00021 #include <string.h>
00022
00023 #include <boost/algorithm/string/find_iterator.hpp>
00024 #include <boost/algorithm/string/predicate.hpp>
00025 #include <boost/algorithm/string/classification.hpp>
00026 #include <boost/bind.hpp>
00027 #include <boost/functional/hash.hpp>
00028 #include <boost/range.hpp>
00029
00030 #include <simgear/math/SGMath.hxx>
00031
00032 #if PROPS_STANDALONE
00033 #include <iostream>
00034 #else
00035
00036 #include <simgear/compiler.h>
00037 #include <simgear/debug/logstream.hxx>
00038
00039 #if ( _MSC_VER == 1200 )
00040
00041 using std::vector<SGPropertyNode_ptr>;
00042 using std::vector<SGPropertyChangeListener *>;
00043 using std::vector<SGPropertyNode *>;
00044 #endif
00045 #endif
00046
00047 #if PROPS_STANDALONE
00048 using std::cerr;
00049 #endif
00050 using std::endl;
00051 using std::find;
00052 using std::sort;
00053 using std::string;
00054 using std::vector;
00055 using std::stringstream;
00056
00057 using namespace simgear;
00058
00059
00061
00063
00067 class CompareIndices
00068 {
00069 public:
00070 int operator() (const SGPropertyNode_ptr n1, const SGPropertyNode_ptr n2) const {
00071 return (n1->getIndex() < n2->getIndex());
00072 }
00073 };
00074
00075
00076
00078
00080
00081 #define TEST_READ(dflt) if (!getAttribute(READ)) return dflt
00082 #define TEST_WRITE if (!getAttribute(WRITE)) return false
00083
00084
00086
00088
00095 template<typename Range>
00096 inline Range
00097 parse_name (const Range &path)
00098 {
00099 typename Range::iterator i = path.begin();
00100 typename Range::iterator max = path.end();
00101
00102 if (*i == '.') {
00103 i++;
00104 if (i != path.end() && *i == '.') {
00105 i++;
00106 }
00107 if (i != max && *i != '/')
00108 throw string("illegal character after . or ..");
00109 } else if (isalpha(*i) || *i == '_') {
00110 i++;
00111
00112
00113
00114 while (i != max) {
00115 if (isalpha(*i) || isdigit(*i) || *i == '_' ||
00116 *i == '-' || *i == '.') {
00117
00118 } else if (*i == '[' || *i == '/') {
00119 break;
00120 } else {
00121 throw string("name may contain only ._- and alphanumeric characters");
00122 }
00123 i++;
00124 }
00125 }
00126
00127 else {
00128 if (path.begin() == i)
00129 throw string("name must begin with alpha or '_'");
00130 }
00131 return Range(path.begin(), i);
00132 }
00133
00134
00135 inline bool validateName(const string& name)
00136 {
00137 using namespace boost;
00138 if (name.empty())
00139 return false;
00140 if (!isalpha(name[0]) && name[0] != '_')
00141 return false;
00142 return all(make_iterator_range(name.begin(), name.end()),
00143 is_alnum() || is_any_of("_-."));
00144 }
00145
00146
00148
00150
00151
00152 static char *
00153 copy_string (const char * s)
00154 {
00155 unsigned long int slen = strlen(s);
00156 char * copy = new char[slen + 1];
00157
00158
00159
00160 memcpy(copy, s, slen);
00161 *(copy + slen) = '\0';
00162 return copy;
00163 }
00164
00165 static bool
00166 compare_strings (const char * s1, const char * s2)
00167 {
00168 return !strncmp(s1, s2, SGPropertyNode::MAX_STRING_LEN);
00169 }
00170
00174 template<typename Itr>
00175 static int
00176 find_child (Itr begin, Itr end, int index, const PropertyList& nodes)
00177 {
00178 int nNodes = nodes.size();
00179 boost::iterator_range<Itr> name(begin, end);
00180 for (int i = 0; i < nNodes; i++) {
00181 SGPropertyNode * node = nodes[i];
00182
00183
00184
00185 if (node->getIndex() == index && boost::equals(node->getName(), name))
00186 return i;
00187 }
00188 return -1;
00189 }
00190
00194 static int
00195 find_last_child (const char * name, const PropertyList& nodes)
00196 {
00197 int nNodes = nodes.size();
00198 int index = 0;
00199
00200 for (int i = 0; i < nNodes; i++) {
00201 SGPropertyNode * node = nodes[i];
00202 if (compare_strings(node->getName(), name))
00203 {
00204 int idx = node->getIndex();
00205 if (idx > index) index = idx;
00206 }
00207 }
00208 return index;
00209 }
00210
00211 template<typename Itr>
00212 inline SGPropertyNode*
00213 SGPropertyNode::getExistingChild (Itr begin, Itr end, int index, bool create)
00214 {
00215 int pos = find_child(begin, end, index, _children);
00216 if (pos >= 0) {
00217 return _children[pos];
00218 } else if (create) {
00219 SGPropertyNode_ptr node;
00220 pos = find_child(begin, end, index, _removedChildren);
00221 if (pos >= 0) {
00222 PropertyList::iterator it = _removedChildren.begin();
00223 it += pos;
00224 node = _removedChildren[pos];
00225 _removedChildren.erase(it);
00226 node->setAttribute(REMOVED, false);
00227 _children.push_back(node);
00228 fireChildAdded(node);
00229 return node;
00230 }
00231 }
00232 return 0;
00233 }
00234
00235 template<typename Itr>
00236 SGPropertyNode *
00237 SGPropertyNode::getChildImpl (Itr begin, Itr end, int index, bool create)
00238 {
00239 SGPropertyNode* node = getExistingChild(begin, end, index, create);
00240
00241 if (node) {
00242 return node;
00243 } else if (create) {
00244 node = new SGPropertyNode(begin, end, index, this);
00245 _children.push_back(node);
00246 fireChildAdded(node);
00247 return node;
00248 } else {
00249 return 0;
00250 }
00251 }
00252
00253 template<typename SplitItr>
00254 SGPropertyNode*
00255 find_node_aux(SGPropertyNode * current, SplitItr& itr, bool create,
00256 int last_index)
00257 {
00258 typedef typename SplitItr::value_type Range;
00259
00260 if (current == 0) {
00261 return 0;
00262 }
00263
00264
00265 if (itr.eof())
00266 return current;
00267 Range token = *itr;
00268
00269 if (token.empty())
00270 return find_node_aux(current, ++itr, create, last_index);
00271 Range name = parse_name(token);
00272 if (equals(name, "."))
00273 return find_node_aux(current, ++itr, create, last_index);
00274 if (equals(name, "..")) {
00275 SGPropertyNode * parent = current->getParent();
00276 if (parent == 0)
00277 throw string("attempt to move past root with '..'");
00278 return find_node_aux(parent, ++itr, create, last_index);
00279 }
00280 int index = -1;
00281 if (last_index >= 0) {
00282
00283
00284 bool lastTok = true;
00285 while (!(++itr).eof()) {
00286 if (!itr->empty()) {
00287 lastTok = false;
00288 break;
00289 }
00290 }
00291 if (lastTok)
00292 index = last_index;
00293 } else {
00294 ++itr;
00295 }
00296
00297 if (index < 0) {
00298 index = 0;
00299 if (name.end() != token.end()) {
00300 if (*name.end() == '[') {
00301 typename Range::iterator i = name.end() + 1, end = token.end();
00302 for (;i != end; ++i) {
00303 if (isdigit(*i)) {
00304 index = (index * 10) + (*i - '0');
00305 } else {
00306 break;
00307 }
00308 }
00309 if (i == token.end() || *i != ']')
00310 throw string("unterminated index (looking for ']')");
00311 } else {
00312 throw string("illegal characters in token: ")
00313 + string(name.begin(), name.end());
00314 }
00315 }
00316 }
00317 return find_node_aux(current->getChildImpl(name.begin(), name.end(),
00318 index, create), itr, create,
00319 last_index);
00320 }
00321
00322
00323
00324 template<typename Range>
00325 SGPropertyNode*
00326 find_node (SGPropertyNode * current,
00327 const Range& path,
00328 bool create,
00329 int last_index = -1)
00330 {
00331 using namespace boost;
00332 typedef split_iterator<typename range_result_iterator<Range>::type>
00333 PathSplitIterator;
00334
00335 PathSplitIterator itr
00336 = make_split_iterator(path, first_finder("/", is_equal()));
00337 if (*path.begin() == '/')
00338 return find_node_aux(current->getRootNode(), itr, create, last_index);
00339 else
00340 return find_node_aux(current, itr, create, last_index);
00341 }
00342
00343
00345
00347
00348 inline bool
00349 SGPropertyNode::get_bool () const
00350 {
00351 if (_tied)
00352 return static_cast<SGRawValue<bool>*>(_value.val)->getValue();
00353 else
00354 return _local_val.bool_val;
00355 }
00356
00357 inline int
00358 SGPropertyNode::get_int () const
00359 {
00360 if (_tied)
00361 return (static_cast<SGRawValue<int>*>(_value.val))->getValue();
00362 else
00363 return _local_val.int_val;
00364 }
00365
00366 inline long
00367 SGPropertyNode::get_long () const
00368 {
00369 if (_tied)
00370 return static_cast<SGRawValue<long>*>(_value.val)->getValue();
00371 else
00372 return _local_val.long_val;
00373 }
00374
00375 inline float
00376 SGPropertyNode::get_float () const
00377 {
00378 if (_tied)
00379 return static_cast<SGRawValue<float>*>(_value.val)->getValue();
00380 else
00381 return _local_val.float_val;
00382 }
00383
00384 inline double
00385 SGPropertyNode::get_double () const
00386 {
00387 if (_tied)
00388 return static_cast<SGRawValue<double>*>(_value.val)->getValue();
00389 else
00390 return _local_val.double_val;
00391 }
00392
00393 inline const char *
00394 SGPropertyNode::get_string () const
00395 {
00396 if (_tied)
00397 return static_cast<SGRawValue<const char*>*>(_value.val)->getValue();
00398 else
00399 return _local_val.string_val;
00400 }
00401
00402 inline bool
00403 SGPropertyNode::set_bool (bool val)
00404 {
00405 if (_tied) {
00406 if (static_cast<SGRawValue<bool>*>(_value.val)->setValue(val)) {
00407 fireValueChanged();
00408 return true;
00409 } else {
00410 return false;
00411 }
00412 } else {
00413 _local_val.bool_val = val;
00414 fireValueChanged();
00415 return true;
00416 }
00417 }
00418
00419 inline bool
00420 SGPropertyNode::set_int (int val)
00421 {
00422 if (_tied) {
00423 if (static_cast<SGRawValue<int>*>(_value.val)->setValue(val)) {
00424 fireValueChanged();
00425 return true;
00426 } else {
00427 return false;
00428 }
00429 } else {
00430 _local_val.int_val = val;
00431 fireValueChanged();
00432 return true;
00433 }
00434 }
00435
00436 inline bool
00437 SGPropertyNode::set_long (long val)
00438 {
00439 if (_tied) {
00440 if (static_cast<SGRawValue<long>*>(_value.val)->setValue(val)) {
00441 fireValueChanged();
00442 return true;
00443 } else {
00444 return false;
00445 }
00446 } else {
00447 _local_val.long_val = val;
00448 fireValueChanged();
00449 return true;
00450 }
00451 }
00452
00453 inline bool
00454 SGPropertyNode::set_float (float val)
00455 {
00456 if (_tied) {
00457 if (static_cast<SGRawValue<float>*>(_value.val)->setValue(val)) {
00458 fireValueChanged();
00459 return true;
00460 } else {
00461 return false;
00462 }
00463 } else {
00464 _local_val.float_val = val;
00465 fireValueChanged();
00466 return true;
00467 }
00468 }
00469
00470 inline bool
00471 SGPropertyNode::set_double (double val)
00472 {
00473 if (_tied) {
00474 if (static_cast<SGRawValue<double>*>(_value.val)->setValue(val)) {
00475 fireValueChanged();
00476 return true;
00477 } else {
00478 return false;
00479 }
00480 } else {
00481 _local_val.double_val = val;
00482 fireValueChanged();
00483 return true;
00484 }
00485 }
00486
00487 inline bool
00488 SGPropertyNode::set_string (const char * val)
00489 {
00490 if (_tied) {
00491 if (static_cast<SGRawValue<const char*>*>(_value.val)->setValue(val)) {
00492 fireValueChanged();
00493 return true;
00494 } else {
00495 return false;
00496 }
00497 } else {
00498 delete [] _local_val.string_val;
00499 _local_val.string_val = copy_string(val);
00500 fireValueChanged();
00501 return true;
00502 }
00503 }
00504
00505 void
00506 SGPropertyNode::clearValue ()
00507 {
00508 if (_type == props::ALIAS) {
00509 put(_value.alias);
00510 _value.alias = 0;
00511 } else if (_type != props::NONE) {
00512 switch (_type) {
00513 case props::BOOL:
00514 _local_val.bool_val = SGRawValue<bool>::DefaultValue();
00515 break;
00516 case props::INT:
00517 _local_val.int_val = SGRawValue<int>::DefaultValue();
00518 break;
00519 case props::LONG:
00520 _local_val.long_val = SGRawValue<long>::DefaultValue();
00521 break;
00522 case props::FLOAT:
00523 _local_val.float_val = SGRawValue<float>::DefaultValue();
00524 break;
00525 case props::DOUBLE:
00526 _local_val.double_val = SGRawValue<double>::DefaultValue();
00527 break;
00528 case props::STRING:
00529 case props::UNSPECIFIED:
00530 if (!_tied) {
00531 delete [] _local_val.string_val;
00532 }
00533 _local_val.string_val = 0;
00534 break;
00535 default:
00536 break;
00537 }
00538 delete _value.val;
00539 _value.val = 0;
00540 }
00541 _tied = false;
00542 _type = props::NONE;
00543 }
00544
00545
00549 const char *
00550 SGPropertyNode::make_string () const
00551 {
00552 if (!getAttribute(READ))
00553 return "";
00554 switch (_type) {
00555 case props::ALIAS:
00556 return _value.alias->getStringValue();
00557 case props::BOOL:
00558 return get_bool() ? "true" : "false";
00559 case props::STRING:
00560 case props::UNSPECIFIED:
00561 return get_string();
00562 case props::NONE:
00563 return "";
00564 default:
00565 break;
00566 }
00567 stringstream sstr;
00568 switch (_type) {
00569 case props::INT:
00570 sstr << get_int();
00571 break;
00572 case props::LONG:
00573 sstr << get_long();
00574 break;
00575 case props::FLOAT:
00576 sstr << get_float();
00577 break;
00578 case props::DOUBLE:
00579 sstr << std::setprecision(10) << get_double();
00580 break;
00581 case props::EXTENDED:
00582 {
00583 props::Type realType = _value.val->getType();
00584
00585 if (realType == props::VEC3D || realType == props::VEC4D)
00586 sstr.precision(10);
00587 static_cast<SGRawExtended*>(_value.val)->printOn(sstr);
00588 }
00589 break;
00590 default:
00591 return "";
00592 }
00593 _buffer = sstr.str();
00594 return _buffer.c_str();
00595 }
00596
00600 void
00601 SGPropertyNode::trace_write () const
00602 {
00603 #if PROPS_STANDALONE
00604 cerr << "TRACE: Write node " << getPath () << ", value \""
00605 << make_string() << '"' << endl;
00606 #else
00607 SG_LOG(SG_GENERAL, SG_ALERT, "TRACE: Write node " << getPath()
00608 << ", value \"" << make_string() << '"');
00609 #endif
00610 }
00611
00615 void
00616 SGPropertyNode::trace_read () const
00617 {
00618 #if PROPS_STANDALONE
00619 cerr << "TRACE: Write node " << getPath () << ", value \""
00620 << make_string() << '"' << endl;
00621 #else
00622 SG_LOG(SG_GENERAL, SG_ALERT, "TRACE: Read node " << getPath()
00623 << ", value \"" << make_string() << '"');
00624 #endif
00625 }
00626
00627
00629
00631
00636 const int SGPropertyNode::LAST_USED_ATTRIBUTE = USERARCHIVE;
00637
00641 SGPropertyNode::SGPropertyNode ()
00642 : _index(0),
00643 _parent(0),
00644 _path_cache(0),
00645 _type(props::NONE),
00646 _tied(false),
00647 _attr(READ|WRITE),
00648 _listeners(0)
00649 {
00650 _local_val.string_val = 0;
00651 _value.val = 0;
00652 }
00653
00654
00658 SGPropertyNode::SGPropertyNode (const SGPropertyNode &node)
00659 : _index(node._index),
00660 _name(node._name),
00661 _parent(0),
00662 _path_cache(0),
00663 _type(node._type),
00664 _tied(node._tied),
00665 _attr(node._attr),
00666 _listeners(0)
00667 {
00668 _local_val.string_val = 0;
00669 _value.val = 0;
00670 if (_type == props::NONE)
00671 return;
00672 if (_type == props::ALIAS) {
00673 _value.alias = node._value.alias;
00674 get(_value.alias);
00675 _tied = false;
00676 return;
00677 }
00678 if (_tied || _type == props::EXTENDED) {
00679 _value.val = node._value.val->clone();
00680 return;
00681 }
00682 switch (_type) {
00683 case props::BOOL:
00684 set_bool(node.get_bool());
00685 break;
00686 case props::INT:
00687 set_int(node.get_int());
00688 break;
00689 case props::LONG:
00690 set_long(node.get_long());
00691 break;
00692 case props::FLOAT:
00693 set_float(node.get_float());
00694 break;
00695 case props::DOUBLE:
00696 set_double(node.get_double());
00697 break;
00698 case props::STRING:
00699 case props::UNSPECIFIED:
00700 set_string(node.get_string());
00701 break;
00702 default:
00703 break;
00704 }
00705 }
00706
00707
00711 template<typename Itr>
00712 SGPropertyNode::SGPropertyNode (Itr begin, Itr end,
00713 int index,
00714 SGPropertyNode * parent)
00715 : _index(index),
00716 _name(begin, end),
00717 _parent(parent),
00718 _path_cache(0),
00719 _type(props::NONE),
00720 _tied(false),
00721 _attr(READ|WRITE),
00722 _listeners(0)
00723 {
00724 _local_val.string_val = 0;
00725 _value.val = 0;
00726 if (!validateName(_name))
00727 throw string("plain name expected instead of '") + _name + '\'';
00728 }
00729
00730 SGPropertyNode::SGPropertyNode (const string& name,
00731 int index,
00732 SGPropertyNode * parent)
00733 : _index(index),
00734 _name(name),
00735 _parent(parent),
00736 _path_cache(0),
00737 _type(props::NONE),
00738 _tied(false),
00739 _attr(READ|WRITE),
00740 _listeners(0)
00741 {
00742 _local_val.string_val = 0;
00743 _value.val = 0;
00744 if (!validateName(name))
00745 throw string("plain name expected instead of '") + _name + '\'';
00746 }
00747
00751 SGPropertyNode::~SGPropertyNode ()
00752 {
00753
00754 for (unsigned i = 0; i < _children.size(); ++i)
00755 _children[i]->_parent = 0;
00756 for (unsigned i = 0; i < _removedChildren.size(); ++i)
00757 _removedChildren[i]->_parent = 0;
00758 delete _path_cache;
00759 clearValue();
00760
00761 if (_listeners) {
00762 vector<SGPropertyChangeListener*>::iterator it;
00763 for (it = _listeners->begin(); it != _listeners->end(); ++it)
00764 (*it)->unregister_property(this);
00765 delete _listeners;
00766 }
00767 }
00768
00769
00773 bool
00774 SGPropertyNode::alias (SGPropertyNode * target)
00775 {
00776 if (target == 0 || _type == props::ALIAS || _tied)
00777 return false;
00778 clearValue();
00779 get(target);
00780 _value.alias = target;
00781 _type = props::ALIAS;
00782 return true;
00783 }
00784
00785
00789 bool
00790 SGPropertyNode::alias (const char * path)
00791 {
00792 return alias(getNode(path, true));
00793 }
00794
00795
00799 bool
00800 SGPropertyNode::unalias ()
00801 {
00802 if (_type != props::ALIAS)
00803 return false;
00804 clearValue();
00805 return true;
00806 }
00807
00808
00812 SGPropertyNode *
00813 SGPropertyNode::getAliasTarget ()
00814 {
00815 return (_type == props::ALIAS ? _value.alias : 0);
00816 }
00817
00818
00819 const SGPropertyNode *
00820 SGPropertyNode::getAliasTarget () const
00821 {
00822 return (_type == props::ALIAS ? _value.alias : 0);
00823 }
00824
00828 SGPropertyNode *
00829 SGPropertyNode::addChild (const char * name)
00830 {
00831 int pos = find_last_child(name, _children)+1;
00832
00833 SGPropertyNode_ptr node;
00834 node = new SGPropertyNode(name, name + strlen(name), pos, this);
00835 _children.push_back(node);
00836 fireChildAdded(node);
00837 return node;
00838 }
00839
00840
00844 SGPropertyNode *
00845 SGPropertyNode::getChild (int position)
00846 {
00847 if (position >= 0 && position < nChildren())
00848 return _children[position];
00849 else
00850 return 0;
00851 }
00852
00853
00857 const SGPropertyNode *
00858 SGPropertyNode::getChild (int position) const
00859 {
00860 if (position >= 0 && position < nChildren())
00861 return _children[position];
00862 else
00863 return 0;
00864 }
00865
00866
00871 SGPropertyNode *
00872 SGPropertyNode::getChild (const char * name, int index, bool create)
00873 {
00874 return getChildImpl(name, name + strlen(name), index, create);
00875 }
00876
00877 SGPropertyNode *
00878 SGPropertyNode::getChild (const string& name, int index, bool create)
00879 {
00880 SGPropertyNode* node = getExistingChild(name.begin(), name.end(), index,
00881 create);
00882 if (node) {
00883 return node;
00884 } else if (create) {
00885 node = new SGPropertyNode(name, index, this);
00886 _children.push_back(node);
00887 fireChildAdded(node);
00888 return node;
00889 } else {
00890 return 0;
00891 }
00892 }
00893
00897 const SGPropertyNode *
00898 SGPropertyNode::getChild (const char * name, int index) const
00899 {
00900 int pos = find_child(name, name + strlen(name), index, _children);
00901 if (pos >= 0)
00902 return _children[pos];
00903 else
00904 return 0;
00905 }
00906
00907
00911 PropertyList
00912 SGPropertyNode::getChildren (const char * name) const
00913 {
00914 PropertyList children;
00915 int max = _children.size();
00916
00917 for (int i = 0; i < max; i++)
00918 if (compare_strings(_children[i]->getName(), name))
00919 children.push_back(_children[i]);
00920
00921 sort(children.begin(), children.end(), CompareIndices());
00922 return children;
00923 }
00924
00925
00930 void
00931 SGPropertyNode::remove_from_path_caches ()
00932 {
00933 for (unsigned int i = 0; i < _children.size(); ++i)
00934 _children[i]->remove_from_path_caches();
00935
00936 for (unsigned int i = 0; i < _linkedNodes.size(); i++)
00937 _linkedNodes[i]->erase(this);
00938 _linkedNodes.clear();
00939 }
00940
00941
00945 SGPropertyNode_ptr
00946 SGPropertyNode::removeChild (int pos, bool keep)
00947 {
00948 SGPropertyNode_ptr node;
00949 if (pos < 0 || pos >= (int)_children.size())
00950 return node;
00951
00952 PropertyList::iterator it = _children.begin();
00953 it += pos;
00954 node = _children[pos];
00955 _children.erase(it);
00956 if (keep) {
00957 _removedChildren.push_back(node);
00958 }
00959
00960 node->remove_from_path_caches();
00961 node->setAttribute(REMOVED, true);
00962 node->clearValue();
00963 fireChildRemoved(node);
00964 return node;
00965 }
00966
00967
00971 SGPropertyNode_ptr
00972 SGPropertyNode::removeChild (const char * name, int index, bool keep)
00973 {
00974 SGPropertyNode_ptr ret;
00975 int pos = find_child(name, name + strlen(name), index, _children);
00976 if (pos >= 0)
00977 ret = removeChild(pos, keep);
00978 return ret;
00979 }
00980
00981
00985 PropertyList
00986 SGPropertyNode::removeChildren (const char * name, bool keep)
00987 {
00988 PropertyList children;
00989
00990 for (int pos = _children.size() - 1; pos >= 0; pos--)
00991 if (compare_strings(_children[pos]->getName(), name))
00992 children.push_back(removeChild(pos, keep));
00993
00994 sort(children.begin(), children.end(), CompareIndices());
00995 return children;
00996 }
00997
00998
01002 bool
01003 SGPropertyNode::remove_linked_node (hash_table * node)
01004 {
01005 for (unsigned int i = 0; i < _linkedNodes.size(); i++) {
01006 if (_linkedNodes[i] == node) {
01007 vector<hash_table *>::iterator it = _linkedNodes.begin();
01008 it += i;
01009 _linkedNodes.erase(it);
01010 return true;
01011 }
01012 }
01013 return false;
01014 }
01015
01016
01017 string
01018 SGPropertyNode::getDisplayName (bool simplify) const
01019 {
01020 string display_name = _name;
01021 if (_index != 0 || !simplify) {
01022 stringstream sstr;
01023 sstr << '[' << _index << ']';
01024 display_name += sstr.str();
01025 }
01026 return display_name;
01027 }
01028
01029
01030 const char *
01031 SGPropertyNode::getPath (bool simplify) const
01032 {
01033
01034 if (_parent != 0 && _path.empty()) {
01035 _path = _parent->getPath(simplify);
01036 _path += '/';
01037 _path += getDisplayName(simplify);
01038 }
01039
01040 return _path.c_str();
01041 }
01042
01043 props::Type
01044 SGPropertyNode::getType () const
01045 {
01046 if (_type == props::ALIAS)
01047 return _value.alias->getType();
01048 else if (_type == props::EXTENDED)
01049 return _value.val->getType();
01050 else
01051 return _type;
01052 }
01053
01054
01055 bool
01056 SGPropertyNode::getBoolValue () const
01057 {
01058
01059 if (_attr == (READ|WRITE) && _type == props::BOOL)
01060 return get_bool();
01061
01062 if (getAttribute(TRACE_READ))
01063 trace_read();
01064 if (!getAttribute(READ))
01065 return SGRawValue<bool>::DefaultValue();
01066 switch (_type) {
01067 case props::ALIAS:
01068 return _value.alias->getBoolValue();
01069 case props::BOOL:
01070 return get_bool();
01071 case props::INT:
01072 return get_int() == 0 ? false : true;
01073 case props::LONG:
01074 return get_long() == 0L ? false : true;
01075 case props::FLOAT:
01076 return get_float() == 0.0 ? false : true;
01077 case props::DOUBLE:
01078 return get_double() == 0.0L ? false : true;
01079 case props::STRING:
01080 case props::UNSPECIFIED:
01081 return (compare_strings(get_string(), "true") || getDoubleValue() != 0.0L);
01082 case props::NONE:
01083 default:
01084 return SGRawValue<bool>::DefaultValue();
01085 }
01086 }
01087
01088 int
01089 SGPropertyNode::getIntValue () const
01090 {
01091
01092 if (_attr == (READ|WRITE) && _type == props::INT)
01093 return get_int();
01094
01095 if (getAttribute(TRACE_READ))
01096 trace_read();
01097 if (!getAttribute(READ))
01098 return SGRawValue<int>::DefaultValue();
01099 switch (_type) {
01100 case props::ALIAS:
01101 return _value.alias->getIntValue();
01102 case props::BOOL:
01103 return int(get_bool());
01104 case props::INT:
01105 return get_int();
01106 case props::LONG:
01107 return int(get_long());
01108 case props::FLOAT:
01109 return int(get_float());
01110 case props::DOUBLE:
01111 return int(get_double());
01112 case props::STRING:
01113 case props::UNSPECIFIED:
01114 return atoi(get_string());
01115 case props::NONE:
01116 default:
01117 return SGRawValue<int>::DefaultValue();
01118 }
01119 }
01120
01121 long
01122 SGPropertyNode::getLongValue () const
01123 {
01124
01125 if (_attr == (READ|WRITE) && _type == props::LONG)
01126 return get_long();
01127
01128 if (getAttribute(TRACE_READ))
01129 trace_read();
01130 if (!getAttribute(READ))
01131 return SGRawValue<long>::DefaultValue();
01132 switch (_type) {
01133 case props::ALIAS:
01134 return _value.alias->getLongValue();
01135 case props::BOOL:
01136 return long(get_bool());
01137 case props::INT:
01138 return long(get_int());
01139 case props::LONG:
01140 return get_long();
01141 case props::FLOAT:
01142 return long(get_float());
01143 case props::DOUBLE:
01144 return long(get_double());
01145 case props::STRING:
01146 case props::UNSPECIFIED:
01147 return strtol(get_string(), 0, 0);
01148 case props::NONE:
01149 default:
01150 return SGRawValue<long>::DefaultValue();
01151 }
01152 }
01153
01154 float
01155 SGPropertyNode::getFloatValue () const
01156 {
01157
01158 if (_attr == (READ|WRITE) && _type == props::FLOAT)
01159 return get_float();
01160
01161 if (getAttribute(TRACE_READ))
01162 trace_read();
01163 if (!getAttribute(READ))
01164 return SGRawValue<float>::DefaultValue();
01165 switch (_type) {
01166 case props::ALIAS:
01167 return _value.alias->getFloatValue();
01168 case props::BOOL:
01169 return float(get_bool());
01170 case props::INT:
01171 return float(get_int());
01172 case props::LONG:
01173 return float(get_long());
01174 case props::FLOAT:
01175 return get_float();
01176 case props::DOUBLE:
01177 return float(get_double());
01178 case props::STRING:
01179 case props::UNSPECIFIED:
01180 return atof(get_string());
01181 case props::NONE:
01182 default:
01183 return SGRawValue<float>::DefaultValue();
01184 }
01185 }
01186
01187 double
01188 SGPropertyNode::getDoubleValue () const
01189 {
01190
01191 if (_attr == (READ|WRITE) && _type == props::DOUBLE)
01192 return get_double();
01193
01194 if (getAttribute(TRACE_READ))
01195 trace_read();
01196 if (!getAttribute(READ))
01197 return SGRawValue<double>::DefaultValue();
01198
01199 switch (_type) {
01200 case props::ALIAS:
01201 return _value.alias->getDoubleValue();
01202 case props::BOOL:
01203 return double(get_bool());
01204 case props::INT:
01205 return double(get_int());
01206 case props::LONG:
01207 return double(get_long());
01208 case props::FLOAT:
01209 return double(get_float());
01210 case props::DOUBLE:
01211 return get_double();
01212 case props::STRING:
01213 case props::UNSPECIFIED:
01214 return strtod(get_string(), 0);
01215 case props::NONE:
01216 default:
01217 return SGRawValue<double>::DefaultValue();
01218 }
01219 }
01220
01221 const char *
01222 SGPropertyNode::getStringValue () const
01223 {
01224
01225 if (_attr == (READ|WRITE) && _type == props::STRING)
01226 return get_string();
01227
01228 if (getAttribute(TRACE_READ))
01229 trace_read();
01230 if (!getAttribute(READ))
01231 return SGRawValue<const char *>::DefaultValue();
01232 return make_string();
01233 }
01234
01235 bool
01236 SGPropertyNode::setBoolValue (bool value)
01237 {
01238
01239 if (_attr == (READ|WRITE) && _type == props::BOOL)
01240 return set_bool(value);
01241
01242 bool result = false;
01243 TEST_WRITE;
01244 if (_type == props::NONE || _type == props::UNSPECIFIED) {
01245 clearValue();
01246 _tied = false;
01247 _type = props::BOOL;
01248 }
01249
01250 switch (_type) {
01251 case props::ALIAS:
01252 result = _value.alias->setBoolValue(value);
01253 break;
01254 case props::BOOL:
01255 result = set_bool(value);
01256 break;
01257 case props::INT:
01258 result = set_int(int(value));
01259 break;
01260 case props::LONG:
01261 result = set_long(long(value));
01262 break;
01263 case props::FLOAT:
01264 result = set_float(float(value));
01265 break;
01266 case props::DOUBLE:
01267 result = set_double(double(value));
01268 break;
01269 case props::STRING:
01270 case props::UNSPECIFIED:
01271 result = set_string(value ? "true" : "false");
01272 break;
01273 case props::NONE:
01274 default:
01275 break;
01276 }
01277
01278 if (getAttribute(TRACE_WRITE))
01279 trace_write();
01280 return result;
01281 }
01282
01283 bool
01284 SGPropertyNode::setIntValue (int value)
01285 {
01286
01287 if (_attr == (READ|WRITE) && _type == props::INT)
01288 return set_int(value);
01289
01290 bool result = false;
01291 TEST_WRITE;
01292 if (_type == props::NONE || _type == props::UNSPECIFIED) {
01293 clearValue();
01294 _type = props::INT;
01295 _local_val.int_val = 0;
01296 }
01297
01298 switch (_type) {
01299 case props::ALIAS:
01300 result = _value.alias->setIntValue(value);
01301 break;
01302 case props::BOOL:
01303 result = set_bool(value == 0 ? false : true);
01304 break;
01305 case props::INT:
01306 result = set_int(value);
01307 break;
01308 case props::LONG:
01309 result = set_long(long(value));
01310 break;
01311 case props::FLOAT:
01312 result = set_float(float(value));
01313 break;
01314 case props::DOUBLE:
01315 result = set_double(double(value));
01316 break;
01317 case props::STRING:
01318 case props::UNSPECIFIED: {
01319 char buf[128];
01320 sprintf(buf, "%d", value);
01321 result = set_string(buf);
01322 break;
01323 }
01324 case props::NONE:
01325 default:
01326 break;
01327 }
01328
01329 if (getAttribute(TRACE_WRITE))
01330 trace_write();
01331 return result;
01332 }
01333
01334 bool
01335 SGPropertyNode::setLongValue (long value)
01336 {
01337
01338 if (_attr == (READ|WRITE) && _type == props::LONG)
01339 return set_long(value);
01340
01341 bool result = false;
01342 TEST_WRITE;
01343 if (_type == props::NONE || _type == props::UNSPECIFIED) {
01344 clearValue();
01345 _type = props::LONG;
01346 _local_val.long_val = 0L;
01347 }
01348
01349 switch (_type) {
01350 case props::ALIAS:
01351 result = _value.alias->setLongValue(value);
01352 break;
01353 case props::BOOL:
01354 result = set_bool(value == 0L ? false : true);
01355 break;
01356 case props::INT:
01357 result = set_int(int(value));
01358 break;
01359 case props::LONG:
01360 result = set_long(value);
01361 break;
01362 case props::FLOAT:
01363 result = set_float(float(value));
01364 break;
01365 case props::DOUBLE:
01366 result = set_double(double(value));
01367 break;
01368 case props::STRING:
01369 case props::UNSPECIFIED: {
01370 char buf[128];
01371 sprintf(buf, "%ld", value);
01372 result = set_string(buf);
01373 break;
01374 }
01375 case props::NONE:
01376 default:
01377 break;
01378 }
01379
01380 if (getAttribute(TRACE_WRITE))
01381 trace_write();
01382 return result;
01383 }
01384
01385 bool
01386 SGPropertyNode::setFloatValue (float value)
01387 {
01388
01389 if (_attr == (READ|WRITE) && _type == props::FLOAT)
01390 return set_float(value);
01391
01392 bool result = false;
01393 TEST_WRITE;
01394 if (_type == props::NONE || _type == props::UNSPECIFIED) {
01395 clearValue();
01396 _type = props::FLOAT;
01397 _local_val.float_val = 0;
01398 }
01399
01400 switch (_type) {
01401 case props::ALIAS:
01402 result = _value.alias->setFloatValue(value);
01403 break;
01404 case props::BOOL:
01405 result = set_bool(value == 0.0 ? false : true);
01406 break;
01407 case props::INT:
01408 result = set_int(int(value));
01409 break;
01410 case props::LONG:
01411 result = set_long(long(value));
01412 break;
01413 case props::FLOAT:
01414 result = set_float(value);
01415 break;
01416 case props::DOUBLE:
01417 result = set_double(double(value));
01418 break;
01419 case props::STRING:
01420 case props::UNSPECIFIED: {
01421 char buf[128];
01422 sprintf(buf, "%f", value);
01423 result = set_string(buf);
01424 break;
01425 }
01426 case props::NONE:
01427 default:
01428 break;
01429 }
01430
01431 if (getAttribute(TRACE_WRITE))
01432 trace_write();
01433 return result;
01434 }
01435
01436 bool
01437 SGPropertyNode::setDoubleValue (double value)
01438 {
01439
01440 if (_attr == (READ|WRITE) && _type == props::DOUBLE)
01441 return set_double(value);
01442
01443 bool result = false;
01444 TEST_WRITE;
01445 if (_type == props::NONE || _type == props::UNSPECIFIED) {
01446 clearValue();
01447 _local_val.double_val = value;
01448 _type = props::DOUBLE;
01449 }
01450
01451 switch (_type) {
01452 case props::ALIAS:
01453 result = _value.alias->setDoubleValue(value);
01454 break;
01455 case props::BOOL:
01456 result = set_bool(value == 0.0L ? false : true);
01457 break;
01458 case props::INT:
01459 result = set_int(int(value));
01460 break;
01461 case props::LONG:
01462 result = set_long(long(value));
01463 break;
01464 case props::FLOAT:
01465 result = set_float(float(value));
01466 break;
01467 case props::DOUBLE:
01468 result = set_double(value);
01469 break;
01470 case props::STRING:
01471 case props::UNSPECIFIED: {
01472 char buf[128];
01473 sprintf(buf, "%f", value);
01474 result = set_string(buf);
01475 break;
01476 }
01477 case props::NONE:
01478 default:
01479 break;
01480 }
01481
01482 if (getAttribute(TRACE_WRITE))
01483 trace_write();
01484 return result;
01485 }
01486
01487 bool
01488 SGPropertyNode::setStringValue (const char * value)
01489 {
01490
01491 if (_attr == (READ|WRITE) && _type == props::STRING)
01492 return set_string(value);
01493
01494 bool result = false;
01495 TEST_WRITE;
01496 if (_type == props::NONE || _type == props::UNSPECIFIED) {
01497 clearValue();
01498 _type = props::STRING;
01499 }
01500
01501 switch (_type) {
01502 case props::ALIAS:
01503 result = _value.alias->setStringValue(value);
01504 break;
01505 case props::BOOL:
01506 result = set_bool((compare_strings(value, "true")
01507 || atoi(value)) ? true : false);
01508 break;
01509 case props::INT:
01510 result = set_int(atoi(value));
01511 break;
01512 case props::LONG:
01513 result = set_long(strtol(value, 0, 0));
01514 break;
01515 case props::FLOAT:
01516 result = set_float(atof(value));
01517 break;
01518 case props::DOUBLE:
01519 result = set_double(strtod(value, 0));
01520 break;
01521 case props::STRING:
01522 case props::UNSPECIFIED:
01523 result = set_string(value);
01524 break;
01525 case props::EXTENDED:
01526 {
01527 stringstream sstr(value);
01528 static_cast<SGRawExtended*>(_value.val)->readFrom(sstr);
01529 }
01530 break;
01531 case props::NONE:
01532 default:
01533 break;
01534 }
01535
01536 if (getAttribute(TRACE_WRITE))
01537 trace_write();
01538 return result;
01539 }
01540
01541 bool
01542 SGPropertyNode::setUnspecifiedValue (const char * value)
01543 {
01544 bool result = false;
01545 TEST_WRITE;
01546 if (_type == props::NONE) {
01547 clearValue();
01548 _type = props::UNSPECIFIED;
01549 }
01550 props::Type type = _type;
01551 if (type == props::EXTENDED)
01552 type = _value.val->getType();
01553 switch (type) {
01554 case props::ALIAS:
01555 result = _value.alias->setUnspecifiedValue(value);
01556 break;
01557 case props::BOOL:
01558 result = set_bool((compare_strings(value, "true")
01559 || atoi(value)) ? true : false);
01560 break;
01561 case props::INT:
01562 result = set_int(atoi(value));
01563 break;
01564 case props::LONG:
01565 result = set_long(strtol(value, 0, 0));
01566 break;
01567 case props::FLOAT:
01568 result = set_float(atof(value));
01569 break;
01570 case props::DOUBLE:
01571 result = set_double(strtod(value, 0));
01572 break;
01573 case props::STRING:
01574 case props::UNSPECIFIED:
01575 result = set_string(value);
01576 break;
01577 case props::VEC3D:
01578 result = static_cast<SGRawValue<SGVec3d>*>(_value.val)->setValue(parseString<SGVec3d>(value));
01579 break;
01580 case props::VEC4D:
01581 result = static_cast<SGRawValue<SGVec4d>*>(_value.val)->setValue(parseString<SGVec4d>(value));
01582 break;
01583 case props::NONE:
01584 default:
01585 break;
01586 }
01587
01588 if (getAttribute(TRACE_WRITE))
01589 trace_write();
01590 return result;
01591 }
01592
01593 std::ostream& SGPropertyNode::printOn(std::ostream& stream) const
01594 {
01595 if (!getAttribute(READ))
01596 return stream;
01597 switch (_type) {
01598 case props::ALIAS:
01599 return _value.alias->printOn(stream);
01600 case props::BOOL:
01601 stream << (get_bool() ? "true" : "false");
01602 break;
01603 case props::INT:
01604 stream << get_int();
01605 break;
01606 case props::LONG:
01607 stream << get_long();
01608 break;
01609 case props::FLOAT:
01610 stream << get_float();
01611 break;
01612 case props::DOUBLE:
01613 stream << get_double();
01614 break;
01615 case props::STRING:
01616 case props::UNSPECIFIED:
01617 stream << get_string();
01618 break;
01619 case props::EXTENDED:
01620 static_cast<SGRawExtended*>(_value.val)->printOn(stream);
01621 break;
01622 case props::NONE:
01623 break;
01624 default:
01625 break;
01626 }
01627 return stream;
01628 }
01629
01630 template<>
01631 bool SGPropertyNode::tie (const SGRawValue<const char *> &rawValue,
01632 bool useDefault)
01633 {
01634 if (_type == props::ALIAS || _tied)
01635 return false;
01636
01637 useDefault = useDefault && hasValue();
01638 std::string old_val;
01639 if (useDefault)
01640 old_val = getStringValue();
01641 clearValue();
01642 _type = props::STRING;
01643 _tied = true;
01644 _value.val = rawValue.clone();
01645
01646 if (useDefault)
01647 setStringValue(old_val.c_str());
01648
01649 return true;
01650 }
01651 bool
01652 SGPropertyNode::untie ()
01653 {
01654 if (!_tied)
01655 return false;
01656
01657 switch (_type) {
01658 case props::BOOL: {
01659 bool val = getBoolValue();
01660 clearValue();
01661 _type = props::BOOL;
01662 _local_val.bool_val = val;
01663 break;
01664 }
01665 case props::INT: {
01666 int val = getIntValue();
01667 clearValue();
01668 _type = props::INT;
01669 _local_val.int_val = val;
01670 break;
01671 }
01672 case props::LONG: {
01673 long val = getLongValue();
01674 clearValue();
01675 _type = props::LONG;
01676 _local_val.long_val = val;
01677 break;
01678 }
01679 case props::FLOAT: {
01680 float val = getFloatValue();
01681 clearValue();
01682 _type = props::FLOAT;
01683 _local_val.float_val = val;
01684 break;
01685 }
01686 case props::DOUBLE: {
01687 double val = getDoubleValue();
01688 clearValue();
01689 _type = props::DOUBLE;
01690 _local_val.double_val = val;
01691 break;
01692 }
01693 case props::STRING:
01694 case props::UNSPECIFIED: {
01695 string val = getStringValue();
01696 clearValue();
01697 _type = props::STRING;
01698 _local_val.string_val = copy_string(val.c_str());
01699 break;
01700 }
01701 case props::EXTENDED: {
01702 SGRawExtended* val = static_cast<SGRawExtended*>(_value.val);
01703 _value.val = 0;
01704 clearValue();
01705 _type = props::EXTENDED;
01706 _value.val = val->makeContainer();
01707 delete val;
01708 break;
01709 }
01710 case props::NONE:
01711 default:
01712 break;
01713 }
01714
01715 _tied = false;
01716 return true;
01717 }
01718
01719 SGPropertyNode *
01720 SGPropertyNode::getRootNode ()
01721 {
01722 if (_parent == 0)
01723 return this;
01724 else
01725 return _parent->getRootNode();
01726 }
01727
01728 const SGPropertyNode *
01729 SGPropertyNode::getRootNode () const
01730 {
01731 if (_parent == 0)
01732 return this;
01733 else
01734 return _parent->getRootNode();
01735 }
01736
01737 SGPropertyNode *
01738 SGPropertyNode::getNode (const char * relative_path, bool create)
01739 {
01740 using namespace boost;
01741 if (_path_cache == 0)
01742 _path_cache = new hash_table;
01743
01744 SGPropertyNode * result = _path_cache->get(relative_path);
01745 if (result == 0) {
01746 result = find_node(this,
01747 make_iterator_range(relative_path, relative_path
01748 + strlen(relative_path)),
01749 create);
01750 if (result != 0)
01751 _path_cache->put(relative_path, result);
01752 }
01753
01754 return result;
01755 }
01756
01757 SGPropertyNode *
01758 SGPropertyNode::getNode (const char * relative_path, int index, bool create)
01759 {
01760 using namespace boost;
01761 return find_node(this, make_iterator_range(relative_path, relative_path
01762 + strlen(relative_path)),
01763 create, index);
01764 }
01765
01766 const SGPropertyNode *
01767 SGPropertyNode::getNode (const char * relative_path) const
01768 {
01769 return ((SGPropertyNode *)this)->getNode(relative_path, false);
01770 }
01771
01772 const SGPropertyNode *
01773 SGPropertyNode::getNode (const char * relative_path, int index) const
01774 {
01775 return ((SGPropertyNode *)this)->getNode(relative_path, index, false);
01776 }
01777
01778
01780
01782
01783
01787 bool
01788 SGPropertyNode::hasValue (const char * relative_path) const
01789 {
01790 const SGPropertyNode * node = getNode(relative_path);
01791 return (node == 0 ? false : node->hasValue());
01792 }
01793
01794
01798 props::Type
01799 SGPropertyNode::getType (const char * relative_path) const
01800 {
01801 const SGPropertyNode * node = getNode(relative_path);
01802 return (node == 0 ? props::UNSPECIFIED : node->getType());
01803 }
01804
01805
01809 bool
01810 SGPropertyNode::getBoolValue (const char * relative_path,
01811 bool defaultValue) const
01812 {
01813 const SGPropertyNode * node = getNode(relative_path);
01814 return (node == 0 ? defaultValue : node->getBoolValue());
01815 }
01816
01817
01821 int
01822 SGPropertyNode::getIntValue (const char * relative_path,
01823 int defaultValue) const
01824 {
01825 const SGPropertyNode * node = getNode(relative_path);
01826 return (node == 0 ? defaultValue : node->getIntValue());
01827 }
01828
01829
01833 long
01834 SGPropertyNode::getLongValue (const char * relative_path,
01835 long defaultValue) const
01836 {
01837 const SGPropertyNode * node = getNode(relative_path);
01838 return (node == 0 ? defaultValue : node->getLongValue());
01839 }
01840
01841
01845 float
01846 SGPropertyNode::getFloatValue (const char * relative_path,
01847 float defaultValue) const
01848 {
01849 const SGPropertyNode * node = getNode(relative_path);
01850 return (node == 0 ? defaultValue : node->getFloatValue());
01851 }
01852
01853
01857 double
01858 SGPropertyNode::getDoubleValue (const char * relative_path,
01859 double defaultValue) const
01860 {
01861 const SGPropertyNode * node = getNode(relative_path);
01862 return (node == 0 ? defaultValue : node->getDoubleValue());
01863 }
01864
01865
01869 const char *
01870 SGPropertyNode::getStringValue (const char * relative_path,
01871 const char * defaultValue) const
01872 {
01873 const SGPropertyNode * node = getNode(relative_path);
01874 return (node == 0 ? defaultValue : node->getStringValue());
01875 }
01876
01877
01881 bool
01882 SGPropertyNode::setBoolValue (const char * relative_path, bool value)
01883 {
01884 return getNode(relative_path, true)->setBoolValue(value);
01885 }
01886
01887
01891 bool
01892 SGPropertyNode::setIntValue (const char * relative_path, int value)
01893 {
01894 return getNode(relative_path, true)->setIntValue(value);
01895 }
01896
01897
01901 bool
01902 SGPropertyNode::setLongValue (const char * relative_path, long value)
01903 {
01904 return getNode(relative_path, true)->setLongValue(value);
01905 }
01906
01907
01911 bool
01912 SGPropertyNode::setFloatValue (const char * relative_path, float value)
01913 {
01914 return getNode(relative_path, true)->setFloatValue(value);
01915 }
01916
01917
01921 bool
01922 SGPropertyNode::setDoubleValue (const char * relative_path, double value)
01923 {
01924 return getNode(relative_path, true)->setDoubleValue(value);
01925 }
01926
01927
01931 bool
01932 SGPropertyNode::setStringValue (const char * relative_path, const char * value)
01933 {
01934 return getNode(relative_path, true)->setStringValue(value);
01935 }
01936
01937
01941 bool
01942 SGPropertyNode::setUnspecifiedValue (const char * relative_path,
01943 const char * value)
01944 {
01945 return getNode(relative_path, true)->setUnspecifiedValue(value);
01946 }
01947
01948
01952 bool
01953 SGPropertyNode::isTied (const char * relative_path) const
01954 {
01955 const SGPropertyNode * node = getNode(relative_path);
01956 return (node == 0 ? false : node->isTied());
01957 }
01958
01959
01963 bool
01964 SGPropertyNode::tie (const char * relative_path,
01965 const SGRawValue<bool> &rawValue,
01966 bool useDefault)
01967 {
01968 return getNode(relative_path, true)->tie(rawValue, useDefault);
01969 }
01970
01971
01975 bool
01976 SGPropertyNode::tie (const char * relative_path,
01977 const SGRawValue<int> &rawValue,
01978 bool useDefault)
01979 {
01980 return getNode(relative_path, true)->tie(rawValue, useDefault);
01981 }
01982
01983
01987 bool
01988 SGPropertyNode::tie (const char * relative_path,
01989 const SGRawValue<long> &rawValue,
01990 bool useDefault)
01991 {
01992 return getNode(relative_path, true)->tie(rawValue, useDefault);
01993 }
01994
01995
01999 bool
02000 SGPropertyNode::tie (const char * relative_path,
02001 const SGRawValue<float> &rawValue,
02002 bool useDefault)
02003 {
02004 return getNode(relative_path, true)->tie(rawValue, useDefault);
02005 }
02006
02007
02011 bool
02012 SGPropertyNode::tie (const char * relative_path,
02013 const SGRawValue<double> &rawValue,
02014 bool useDefault)
02015 {
02016 return getNode(relative_path, true)->tie(rawValue, useDefault);
02017 }
02018
02019
02023 bool
02024 SGPropertyNode::tie (const char * relative_path,
02025 const SGRawValue<const char *> &rawValue,
02026 bool useDefault)
02027 {
02028 return getNode(relative_path, true)->tie(rawValue, useDefault);
02029 }
02030
02031
02035 bool
02036 SGPropertyNode::untie (const char * relative_path)
02037 {
02038 SGPropertyNode * node = getNode(relative_path);
02039 return (node == 0 ? false : node->untie());
02040 }
02041
02042 void
02043 SGPropertyNode::addChangeListener (SGPropertyChangeListener * listener,
02044 bool initial)
02045 {
02046 if (_listeners == 0)
02047 _listeners = new vector<SGPropertyChangeListener*>;
02048 _listeners->push_back(listener);
02049 listener->register_property(this);
02050 if (initial)
02051 listener->valueChanged(this);
02052 }
02053
02054 void
02055 SGPropertyNode::removeChangeListener (SGPropertyChangeListener * listener)
02056 {
02057 vector<SGPropertyChangeListener*>::iterator it =
02058 find(_listeners->begin(), _listeners->end(), listener);
02059 if (it != _listeners->end()) {
02060 _listeners->erase(it);
02061 listener->unregister_property(this);
02062 if (_listeners->empty()) {
02063 vector<SGPropertyChangeListener*>* tmp = _listeners;
02064 _listeners = 0;
02065 delete tmp;
02066 }
02067 }
02068 }
02069
02070 void
02071 SGPropertyNode::fireValueChanged ()
02072 {
02073 fireValueChanged(this);
02074 }
02075
02076 void
02077 SGPropertyNode::fireChildAdded (SGPropertyNode * child)
02078 {
02079 fireChildAdded(this, child);
02080 }
02081
02082 void
02083 SGPropertyNode::fireChildRemoved (SGPropertyNode * child)
02084 {
02085 fireChildRemoved(this, child);
02086 }
02087
02088 void
02089 SGPropertyNode::fireValueChanged (SGPropertyNode * node)
02090 {
02091 if (_listeners != 0) {
02092 for (unsigned int i = 0; i < _listeners->size(); i++) {
02093 (*_listeners)[i]->valueChanged(node);
02094 }
02095 }
02096 if (_parent != 0)
02097 _parent->fireValueChanged(node);
02098 }
02099
02100 void
02101 SGPropertyNode::fireChildAdded (SGPropertyNode * parent,
02102 SGPropertyNode * child)
02103 {
02104 if (_listeners != 0) {
02105 for (unsigned int i = 0; i < _listeners->size(); i++) {
02106 (*_listeners)[i]->childAdded(parent, child);
02107 }
02108 }
02109 if (_parent != 0)
02110 _parent->fireChildAdded(parent, child);
02111 }
02112
02113 void
02114 SGPropertyNode::fireChildRemoved (SGPropertyNode * parent,
02115 SGPropertyNode * child)
02116 {
02117 if (_listeners != 0) {
02118 for (unsigned int i = 0; i < _listeners->size(); i++) {
02119 (*_listeners)[i]->childRemoved(parent, child);
02120 }
02121 }
02122 if (_parent != 0)
02123 _parent->fireChildRemoved(parent, child);
02124 }
02125
02126
02127
02129
02131
02132 #define HASH_TABLE_SIZE 199
02133
02134 SGPropertyNode::hash_table::entry::entry ()
02135 : _value(0)
02136 {
02137 }
02138
02139 SGPropertyNode::hash_table::entry::~entry ()
02140 {
02141
02142
02143 }
02144
02145 void
02146 SGPropertyNode::hash_table::entry::set_key (const char * key)
02147 {
02148 _key = key;
02149 }
02150
02151 void
02152 SGPropertyNode::hash_table::entry::set_value (SGPropertyNode * value)
02153 {
02154 _value = value;
02155 }
02156
02157 SGPropertyNode::hash_table::bucket::bucket ()
02158 : _length(0),
02159 _entries(0)
02160 {
02161 }
02162
02163 SGPropertyNode::hash_table::bucket::~bucket ()
02164 {
02165 for (int i = 0; i < _length; i++)
02166 delete _entries[i];
02167 delete [] _entries;
02168 }
02169
02170 SGPropertyNode::hash_table::entry *
02171 SGPropertyNode::hash_table::bucket::get_entry (const char * key, bool create)
02172 {
02173 int i;
02174 for (i = 0; i < _length; i++) {
02175 if (!strcmp(_entries[i]->get_key(), key))
02176 return _entries[i];
02177 }
02178 if (create) {
02179 entry ** new_entries = new entry*[_length+1];
02180 for (i = 0; i < _length; i++) {
02181 new_entries[i] = _entries[i];
02182 }
02183 delete [] _entries;
02184 _entries = new_entries;
02185 _entries[_length] = new entry;
02186 _entries[_length]->set_key(key);
02187 _length++;
02188 return _entries[_length - 1];
02189 } else {
02190 return 0;
02191 }
02192 }
02193
02194 bool
02195 SGPropertyNode::hash_table::bucket::erase (SGPropertyNode * node)
02196 {
02197 for (int i = 0; i < _length; i++) {
02198 if (_entries[i]->get_value() == node) {
02199 delete _entries[i];
02200 for (++i; i < _length; i++) {
02201 _entries[i-1] = _entries[i];
02202 }
02203 _length--;
02204 return true;
02205 }
02206 }
02207 return false;
02208 }
02209
02210 void
02211 SGPropertyNode::hash_table::bucket::clear (SGPropertyNode::hash_table * owner)
02212 {
02213 for (int i = 0; i < _length; i++) {
02214 SGPropertyNode * node = _entries[i]->get_value();
02215 if (node)
02216 node->remove_linked_node(owner);
02217 }
02218 }
02219
02220 SGPropertyNode::hash_table::hash_table ()
02221 : _data_length(0),
02222 _data(0)
02223 {
02224 }
02225
02226 SGPropertyNode::hash_table::~hash_table ()
02227 {
02228 for (unsigned int i = 0; i < _data_length; i++) {
02229 if (_data[i]) {
02230 _data[i]->clear(this);
02231 delete _data[i];
02232 }
02233 }
02234 delete [] _data;
02235 }
02236
02237 SGPropertyNode *
02238 SGPropertyNode::hash_table::get (const char * key)
02239 {
02240 if (_data_length == 0)
02241 return 0;
02242 unsigned int index = hashcode(key) % _data_length;
02243 if (_data[index] == 0)
02244 return 0;
02245 entry * e = _data[index]->get_entry(key);
02246 if (e == 0)
02247 return 0;
02248 else
02249 return e->get_value();
02250 }
02251
02252 void
02253 SGPropertyNode::hash_table::put (const char * key, SGPropertyNode * value)
02254 {
02255 if (_data_length == 0) {
02256 _data = new bucket*[HASH_TABLE_SIZE];
02257 _data_length = HASH_TABLE_SIZE;
02258 for (unsigned int i = 0; i < HASH_TABLE_SIZE; i++)
02259 _data[i] = 0;
02260 }
02261 unsigned int index = hashcode(key) % _data_length;
02262 if (_data[index] == 0) {
02263 _data[index] = new bucket;
02264 }
02265 entry * e = _data[index]->get_entry(key, true);
02266 e->set_value(value);
02267 value->add_linked_node(this);
02268 }
02269
02270 bool
02271 SGPropertyNode::hash_table::erase (SGPropertyNode * node)
02272 {
02273 for (unsigned int i = 0; i < _data_length; i++)
02274 if (_data[i] && _data[i]->erase(node))
02275 return true;
02276
02277 return false;
02278 }
02279
02280 unsigned int
02281 SGPropertyNode::hash_table::hashcode (const char * key)
02282 {
02283 unsigned int hash = 0;
02284 while (*key != 0) {
02285 hash = 31 * hash + *key;
02286 key++;
02287 }
02288 return hash;
02289 }
02290
02291
02292
02294
02296
02297 SGPropertyChangeListener::~SGPropertyChangeListener ()
02298 {
02299 for (int i = _properties.size() - 1; i >= 0; i--)
02300 _properties[i]->removeChangeListener(this);
02301 }
02302
02303 void
02304 SGPropertyChangeListener::valueChanged (SGPropertyNode * node)
02305 {
02306
02307 }
02308
02309 void
02310 SGPropertyChangeListener::childAdded (SGPropertyNode * node,
02311 SGPropertyNode * child)
02312 {
02313
02314 }
02315
02316 void
02317 SGPropertyChangeListener::childRemoved (SGPropertyNode * parent,
02318 SGPropertyNode * child)
02319 {
02320
02321 }
02322
02323 void
02324 SGPropertyChangeListener::register_property (SGPropertyNode * node)
02325 {
02326 _properties.push_back(node);
02327 }
02328
02329 void
02330 SGPropertyChangeListener::unregister_property (SGPropertyNode * node)
02331 {
02332 vector<SGPropertyNode *>::iterator it =
02333 find(_properties.begin(), _properties.end(), node);
02334 if (it != _properties.end())
02335 _properties.erase(it);
02336 }
02337
02338 template<>
02339 std::ostream& SGRawBase<SGVec3d>::printOn(std::ostream& stream) const
02340 {
02341 const SGVec3d vec
02342 = static_cast<const SGRawValue<SGVec3d>*>(this)->getValue();
02343 for (int i = 0; i < 3; ++i) {
02344 stream << vec[i];
02345 if (i < 2)
02346 stream << ' ';
02347 }
02348 return stream;
02349 }
02350
02351 namespace simgear
02352 {
02353 template<>
02354 std::istream& readFrom<SGVec3d>(std::istream& stream, SGVec3d& result)
02355 {
02356 for (int i = 0; i < 3; ++i) {
02357 stream >> result[i];
02358 }
02359 return stream;
02360 }
02361 }
02362 template<>
02363 std::ostream& SGRawBase<SGVec4d>::printOn(std::ostream& stream) const
02364 {
02365 const SGVec4d vec
02366 = static_cast<const SGRawValue<SGVec4d>*>(this)->getValue();
02367 for (int i = 0; i < 4; ++i) {
02368 stream << vec[i];
02369 if (i < 3)
02370 stream << ' ';
02371 }
02372 return stream;
02373 }
02374
02375 namespace simgear
02376 {
02377 template<>
02378 std::istream& readFrom<SGVec4d>(std::istream& stream, SGVec4d& result)
02379 {
02380 for (int i = 0; i < 4; ++i) {
02381 stream >> result[i];
02382 }
02383 return stream;
02384 }
02385
02386 namespace
02387 {
02388 bool compareNodeValue(const SGPropertyNode& lhs, const SGPropertyNode& rhs)
02389 {
02390 props::Type ltype = lhs.getType();
02391 props::Type rtype = rhs.getType();
02392 if (ltype != rtype)
02393 return false;
02394 switch (ltype) {
02395 case props::NONE:
02396 return true;
02397 case props::ALIAS:
02398 return false;
02399 case props::BOOL:
02400 return lhs.getValue<bool>() == rhs.getValue<bool>();
02401 case props::INT:
02402 return lhs.getValue<int>() == rhs.getValue<int>();
02403 case props::LONG:
02404 return lhs.getValue<long>() == rhs.getValue<long>();
02405 case props::FLOAT:
02406 return lhs.getValue<float>() == rhs.getValue<float>();
02407 case props::DOUBLE:
02408 return lhs.getValue<double>() == rhs.getValue<double>();
02409 case props::STRING:
02410 case props::UNSPECIFIED:
02411 return !strcmp(lhs.getStringValue(), rhs.getStringValue());
02412 case props::VEC3D:
02413 return lhs.getValue<SGVec3d>() == rhs.getValue<SGVec3d>();
02414 case props::VEC4D:
02415 return lhs.getValue<SGVec4d>() == rhs.getValue<SGVec4d>();
02416 default:
02417 return false;
02418 }
02419 }
02420 }
02421 }
02422
02423 bool SGPropertyNode::compare(const SGPropertyNode& lhs,
02424 const SGPropertyNode& rhs)
02425 {
02426 if (&lhs == &rhs)
02427 return true;
02428 int lhsChildren = lhs.nChildren();
02429 int rhsChildren = rhs.nChildren();
02430 if (lhsChildren != rhsChildren)
02431 return false;
02432 if (lhsChildren == 0)
02433 return compareNodeValue(lhs, rhs);
02434 for (size_t i = 0; i < lhs._children.size(); ++i) {
02435 const SGPropertyNode* lchild = lhs._children[i];
02436 const SGPropertyNode* rchild = rhs._children[i];
02437
02438
02439 if (lchild->getIndex() != rchild->getIndex()
02440 || lchild->getNameString() != rchild->getNameString()) {
02441 rchild = 0;
02442 for (PropertyList::const_iterator itr = rhs._children.begin(),
02443 end = rhs._children.end();
02444 itr != end;
02445 ++itr)
02446 if (lchild->getIndex() == (*itr)->getIndex()
02447 && lchild->getNameString() == (*itr)->getNameString()) {
02448 rchild = *itr;
02449 break;
02450 }
02451 if (!rchild)
02452 return false;
02453 }
02454 if (!compare(*lchild, *rchild))
02455 return false;
02456 }
02457 return true;
02458 }
02459
02460 struct PropertyPlaceLess {
02461 typedef bool result_type;
02462 bool operator()(SGPropertyNode_ptr lhs, SGPropertyNode_ptr rhs) const
02463 {
02464 int comp = lhs->getNameString().compare(rhs->getNameString());
02465 if (comp == 0)
02466 return lhs->getIndex() < rhs->getIndex();
02467 else
02468 return comp < 0;
02469 }
02470 };
02471
02472 size_t hash_value(const SGPropertyNode& node)
02473 {
02474 using namespace boost;
02475
02476 if (node.nChildren() == 0) {
02477 switch (node.getType()) {
02478 case props::NONE:
02479 return 0;
02480
02481 case props::BOOL:
02482 return hash_value(node.getValue<bool>());
02483 case props::INT:
02484 return hash_value(node.getValue<int>());
02485 case props::LONG:
02486 return hash_value(node.getValue<long>());
02487 case props::FLOAT:
02488 return hash_value(node.getValue<float>());
02489 case props::DOUBLE:
02490 return hash_value(node.getValue<double>());
02491 case props::STRING:
02492 case props::UNSPECIFIED:
02493 {
02494 const char *val = node.getStringValue();
02495 return hash_range(val, val + strlen(val));
02496 }
02497 case props::VEC3D:
02498 {
02499 const SGVec3d val = node.getValue<SGVec3d>();
02500 return hash_range(&val[0], &val[3]);
02501 }
02502 case props::VEC4D:
02503 {
02504 const SGVec4d val = node.getValue<SGVec4d>();
02505 return hash_range(&val[0], &val[4]);
02506 }
02507 case props::ALIAS:
02508 default:
02509 return 0;
02510 }
02511 } else {
02512 size_t seed = 0;
02513 PropertyList children(node._children.begin(), node._children.end());
02514 sort(children.begin(), children.end(), PropertyPlaceLess());
02515 for (PropertyList::const_iterator itr = children.begin(),
02516 end = children.end();
02517 itr != end;
02518 ++itr) {
02519 hash_combine(seed, (*itr)->_name);
02520 hash_combine(seed, (*itr)->_index);
02521 hash_combine(seed, hash_value(**itr));
02522 }
02523 return seed;
02524 }
02525 }
02526
02527