Branch data Line data Source code
1 : : /**
2 : : * \file props.hxx
3 : : * Interface definition for a property list.
4 : : * Started Fall 2000 by David Megginson, david@megginson.com
5 : : * This code is released into the Public Domain.
6 : : *
7 : : * See props.html for documentation [replace with URL when available].
8 : : *
9 : : * $Id: props.hxx,v 1.6 2009/10/03 18:23:01 andgi Exp $
10 : : */
11 : :
12 : : #ifndef __PROPS_HXX
13 : : #define __PROPS_HXX
14 : :
15 : : #define PROPS_STANDALONE 1
16 : :
17 : : #ifndef PROPS_STANDALONE
18 : : #define PROPS_STANDALONE 0
19 : : #endif
20 : :
21 : : #include <vector>
22 : :
23 : : #if PROPS_STANDALONE
24 : :
25 : : #include <string>
26 : : #include <iostream>
27 : :
28 : : using std::string;
29 : : using std::vector;
30 : : using std::istream;
31 : : using std::ostream;
32 : :
33 : : #include "SGReferenced.hxx"
34 : : #include "SGSharedPtr.hxx"
35 : :
36 : : #else
37 : :
38 : : #include <simgear/compiler.h>
39 : : #include <simgear/debug/logstream.hxx>
40 : : #include STL_STRING
41 : : #include STL_IOSTREAM
42 : : SG_USING_STD(string);
43 : : SG_USING_STD(vector);
44 : : SG_USING_STD(istream);
45 : : SG_USING_STD(ostream);
46 : : #include <simgear/structure/SGReferenced.hxx>
47 : : #include <simgear/structure/SGSharedPtr.hxx>
48 : : #endif
49 : :
50 : :
51 : : #ifdef NONE
52 : : #pragma warn A sloppy coder has defined NONE as a macro!
53 : : #undef NONE
54 : : #endif
55 : :
56 : : #ifdef ALIAS
57 : : #pragma warn A sloppy coder has defined ALIAS as a macro!
58 : : #undef ALIAS
59 : : #endif
60 : :
61 : : #ifdef UNSPECIFIED
62 : : #pragma warn A sloppy coder has defined UNSPECIFIED as a macro!
63 : : #undef UNSPECIFIED
64 : : #endif
65 : :
66 : : #ifdef BOOL
67 : : #pragma warn A sloppy coder has defined BOOL as a macro!
68 : : #undef BOOL
69 : : #endif
70 : :
71 : : #ifdef INT
72 : : #pragma warn A sloppy coder has defined INT as a macro!
73 : : #undef INT
74 : : #endif
75 : :
76 : : #ifdef LONG
77 : : #pragma warn A sloppy coder has defined LONG as a macro!
78 : : #undef LONG
79 : : #endif
80 : :
81 : : #ifdef FLOAT
82 : : #pragma warn A sloppy coder has defined FLOAT as a macro!
83 : : #undef FLOAT
84 : : #endif
85 : :
86 : : #ifdef DOUBLE
87 : : #pragma warn A sloppy coder has defined DOUBLE as a macro!
88 : : #undef DOUBLE
89 : : #endif
90 : :
91 : : #ifdef STRING
92 : : #pragma warn A sloppy coder has defined STRING as a macro!
93 : : #undef STRING
94 : : #endif
95 : :
96 : :
97 : :
98 : : ////////////////////////////////////////////////////////////////////////
99 : : // A raw value.
100 : : //
101 : : // This is the mechanism that information-providing routines can
102 : : // use to link their own values to the property manager. Any
103 : : // SGValue can be tied to a raw value and then untied again.
104 : : //
105 : : // Note: we are forced to use inlined methods here to ensure
106 : : // that the templates will be instantiated. We're probably taking
107 : : // a small performance hit for that.
108 : : ////////////////////////////////////////////////////////////////////////
109 : :
110 : :
111 : : /**
112 : : * Abstract base class for a raw value.
113 : : *
114 : : * <p>The property manager is implemented in two layers. The {@link
115 : : * SGPropertyNode} is the highest and most abstract layer,
116 : : * representing an LValue/RValue pair: it records the position of the
117 : : * property in the property tree and contains facilities for
118 : : * navigation to other nodes. It is guaranteed to be persistent: the
119 : : * {@link SGPropertyNode} will not change during a session, even if
120 : : * the property is bound and unbound multiple times.</p>
121 : : *
122 : : * <p>When the property value is not managed internally in the
123 : : * SGPropertyNode, the SGPropertyNode will contain a reference to an
124 : : * SGRawValue (this class), which provides an abstract way to get,
125 : : * set, and clone the underlying value. The SGRawValue may change
126 : : * frequently during a session as a value is retyped or bound and
127 : : * unbound to various data source, but the abstract SGPropertyNode
128 : : * layer insulates the application from those changes. The raw value
129 : : * contains no facilities for data binding or for type conversion: it
130 : : * is simply the abstraction of a primitive data type (or a compound
131 : : * data type, in the case of a string).</p>
132 : : *
133 : : * <p>The SGPropertyNode class always keeps a *copy* of a raw value,
134 : : * not the original one passed to it; if you override a derived class
135 : : * but do not replace the {@link #clone} method, strange things will
136 : : * happen.</p>
137 : : *
138 : : * <p>All derived SGRawValue classes must implement {@link #getValue},
139 : : * {@link #setValue}, and {@link #clone} for the appropriate type.</p>
140 : : *
141 : : * @see SGPropertyNode
142 : : * @see SGRawValuePointer
143 : : * @see SGRawValueFunctions
144 : : * @see SGRawValueFunctionsIndexed
145 : : * @see SGRawValueMethods
146 : : * @see SGRawValueMethodsIndexed
147 : : */
148 : : template <class T>
149 : : class SGRawValue
150 : : {
151 : : public:
152 : :
153 : : /**
154 : : * The default underlying value for this type.
155 : : *
156 : : * Every raw value has a default; the default is false for a
157 : : * boolean, 0 for the various numeric values, and "" for a string.
158 : : * If additional types of raw values are added in the future, they
159 : : * may need different kinds of default values (such as epoch for a
160 : : * date type). The default value is used when creating new values.
161 : : */
162 : : static const T DefaultValue; // Default for this kind of raw value.
163 : :
164 : :
165 : : /**
166 : : * Constructor.
167 : : *
168 : : * Use the default value for this type.
169 : : */
170 : 1302 : SGRawValue () {}
171 : :
172 : :
173 : : /**
174 : : * Destructor.
175 : : */
176 [ - + ][ # # ]: 1302 : virtual ~SGRawValue () {}
[ # # ][ - + ]
[ - + ][ - + ]
[ # # ][ - + ]
[ - + ][ - + ]
[ # # ][ - + ]
[ - + ][ - + ]
[ # # ][ - + ]
[ # # ][ # # ]
[ # # ][ # # ]
[ - + ][ - + ]
[ # # ][ # # ]
177 : :
178 : :
179 : : /**
180 : : * Return the underlying value.
181 : : *
182 : : * @return The actual value for the property.
183 : : * @see #setValue
184 : : */
185 : : virtual T getValue () const = 0;
186 : :
187 : :
188 : : /**
189 : : * Assign a new underlying value.
190 : : *
191 : : * If the new value cannot be set (because this is a read-only
192 : : * raw value, or because the new value is not acceptable for
193 : : * some reason) this method returns false and leaves the original
194 : : * value unchanged.
195 : : *
196 : : * @param value The actual value for the property.
197 : : * @return true if the value was set successfully, false otherwise.
198 : : * @see #getValue
199 : : */
200 : : virtual bool setValue (T value) = 0;
201 : :
202 : :
203 : : /**
204 : : * Create a new deep copy of this raw value.
205 : : *
206 : : * The copy will contain its own version of the underlying value
207 : : * as well.
208 : : *
209 : : * @return A deep copy of the current object.
210 : : */
211 : : virtual SGRawValue * clone () const = 0;
212 : : };
213 : :
214 : :
215 : : /**
216 : : * A raw value bound to a pointer.
217 : : *
218 : : * This is the most efficient way to tie an external value, but also
219 : : * the most dangerous, because there is no way for the supplier to
220 : : * perform bounds checking and derived calculations except by polling
221 : : * the variable to see if it has changed. There is no default
222 : : * constructor, because this class would be meaningless without a
223 : : * pointer.
224 : : */
225 : : template <class T>
226 : : class SGRawValuePointer : public SGRawValue<T>
227 : : {
228 : : public:
229 : :
230 : : /**
231 : : * Explicit pointer constructor.
232 : : *
233 : : * Create a new raw value bound to the value of the variable
234 : : * referenced by the pointer.
235 : : *
236 : : * @param ptr The pointer to the variable to which this raw value
237 : : * will be bound.
238 : : */
239 : 56 : SGRawValuePointer (T * ptr) : _ptr(ptr) {}
240 : :
241 : : /**
242 : : * Destructor.
243 : : */
244 [ + - ][ - + ]: 28 : virtual ~SGRawValuePointer () {}
[ # # ][ # # ]
[ # # ][ # # ]
[ + - ][ - + ]
[ # # ][ # # ]
245 : :
246 : : /**
247 : : * Get the underlying value.
248 : : *
249 : : * This method will dereference the pointer and return the
250 : : * variable's value.
251 : : */
252 : 486108 : virtual T getValue () const { return *_ptr; }
253 : :
254 : : /**
255 : : * Set the underlying value.
256 : : *
257 : : * This method will dereference the pointer and change the
258 : : * variable's value.
259 : : */
260 : 54055 : virtual bool setValue (T value) { *_ptr = value; return true; }
261 : :
262 : : /**
263 : : * Create a copy of this raw value.
264 : : *
265 : : * The copy will use the same external pointer as the original.
266 : : */
267 : 14 : virtual SGRawValue<T> * clone () const {
268 : 14 : return new SGRawValuePointer<T>(_ptr);
269 : : }
270 : :
271 : : private:
272 : : T * _ptr;
273 : : };
274 : :
275 : :
276 : : /**
277 : : * A value managed through static functions.
278 : : *
279 : : * A read-only value will not have a setter; a write-only value will
280 : : * not have a getter.
281 : : */
282 : : template <class T>
283 : : class SGRawValueFunctions : public SGRawValue<T>
284 : : {
285 : : public:
286 : :
287 : : /**
288 : : * The template type of a static getter function.
289 : : */
290 : : typedef T (*getter_t)();
291 : :
292 : : /**
293 : : * The template type of a static setter function.
294 : : */
295 : : typedef void (*setter_t)(T);
296 : :
297 : : /**
298 : : * Explicit constructor.
299 : : *
300 : : * Create a new raw value bound to the getter and setter supplied.
301 : : *
302 : : * @param getter A static function for getting a value, or 0
303 : : * to read-disable the value.
304 : : * @param setter A static function for setting a value, or 0
305 : : * to write-disable the value.
306 : : */
307 : : SGRawValueFunctions (getter_t getter = 0, setter_t setter = 0)
308 : : : _getter(getter), _setter(setter) {}
309 : :
310 : : /**
311 : : * Destructor.
312 : : */
313 : : virtual ~SGRawValueFunctions () {}
314 : :
315 : : /**
316 : : * Get the underlying value.
317 : : *
318 : : * This method will invoke the getter function to get a value.
319 : : * If no getter function was supplied, this method will always
320 : : * return the default value for the type.
321 : : */
322 : : virtual T getValue () const {
323 : : if (_getter) return (*_getter)();
324 : : else return SGRawValue<T>::DefaultValue;
325 : : }
326 : :
327 : : /**
328 : : * Set the underlying value.
329 : : *
330 : : * This method will invoke the setter function to change the
331 : : * underlying value. If no setter function was supplied, this
332 : : * method will return false.
333 : : */
334 : : virtual bool setValue (T value) {
335 : : if (_setter) { (*_setter)(value); return true; }
336 : : else return false;
337 : : }
338 : :
339 : : /**
340 : : * Create a copy of this raw value, bound to the same functions.
341 : : */
342 : : virtual SGRawValue<T> * clone () const {
343 : : return new SGRawValueFunctions<T>(_getter,_setter);
344 : : }
345 : :
346 : : private:
347 : : getter_t _getter;
348 : : setter_t _setter;
349 : : };
350 : :
351 : :
352 : : /**
353 : : * An indexed value bound to static functions.
354 : : *
355 : : * A read-only value will not have a setter; a write-only value will
356 : : * not have a getter. An indexed value is useful for binding one
357 : : * of a list of possible values (such as multiple engines for a
358 : : * plane). The index is hard-coded at creation time.
359 : : *
360 : : * @see SGRawValue
361 : : */
362 : : template <class T>
363 : : class SGRawValueFunctionsIndexed : public SGRawValue<T>
364 : : {
365 : : public:
366 : : typedef T (*getter_t)(int);
367 : : typedef void (*setter_t)(int,T);
368 : : SGRawValueFunctionsIndexed (int index, getter_t getter = 0, setter_t setter = 0)
369 : : : _index(index), _getter(getter), _setter(setter) {}
370 : : virtual ~SGRawValueFunctionsIndexed () {}
371 : : virtual T getValue () const {
372 : : if (_getter) return (*_getter)(_index);
373 : : else return SGRawValue<T>::DefaultValue;
374 : : }
375 : : virtual bool setValue (T value) {
376 : : if (_setter) { (*_setter)(_index, value); return true; }
377 : : else return false;
378 : : }
379 : : virtual SGRawValue<T> * clone () const {
380 : : return new SGRawValueFunctionsIndexed<T>(_index, _getter, _setter);
381 : : }
382 : : private:
383 : : int _index;
384 : : getter_t _getter;
385 : : setter_t _setter;
386 : : };
387 : :
388 : :
389 : : /**
390 : : * A value managed through an object and access methods.
391 : : *
392 : : * A read-only value will not have a setter; a write-only value will
393 : : * not have a getter.
394 : : */
395 : : template <class C, class T>
396 : : class SGRawValueMethods : public SGRawValue<T>
397 : : {
398 : : public:
399 : : typedef T (C::*getter_t)() const;
400 : : typedef void (C::*setter_t)(T);
401 : : SGRawValueMethods (C &obj, getter_t getter = 0, setter_t setter = 0)
402 : 1436 : : _obj(obj), _getter(getter), _setter(setter) {}
403 [ + + ][ - + ]: 718 : virtual ~SGRawValueMethods () {}
[ + - ][ - + ]
[ + - ][ - + ]
[ - ][ - + ]
[ + - ][ - + ]
404 : 4958774 : virtual T getValue () const {
405 [ + + ][ + + ]: 4958774 : if (_getter) { return (_obj.*_getter)(); }
[ + - ][ - + ]
[ + + ][ + + ]
406 : 4958774 : else { return SGRawValue<T>::DefaultValue; }
407 : : }
408 : 648065 : virtual bool setValue (T value) {
409 [ + - ][ - + ]: 648065 : if (_setter) { (_obj.*_setter)(value); return true; }
[ # # ][ # # ]
[ # # ][ # # ]
410 : 648065 : else return false;
411 : : }
412 : 359 : virtual SGRawValue<T> * clone () const {
413 : 359 : return new SGRawValueMethods<C,T>(_obj, _getter, _setter);
414 : : }
415 : : private:
416 : : C &_obj;
417 : : getter_t _getter;
418 : : setter_t _setter;
419 : : };
420 : :
421 : :
422 : : /**
423 : : * An indexed value managed through an object and access methods.
424 : : *
425 : : * A read-only value will not have a setter; a write-only value will
426 : : * not have a getter.
427 : : */
428 : : template <class C, class T>
429 : : class SGRawValueMethodsIndexed : public SGRawValue<T>
430 : : {
431 : : public:
432 : : typedef T (C::*getter_t)(int) const;
433 : : typedef void (C::*setter_t)(int, T);
434 : : SGRawValueMethodsIndexed (C &obj, int index,
435 : : getter_t getter = 0, setter_t setter = 0)
436 : 1112 : : _obj(obj), _index(index), _getter(getter), _setter(setter) {}
437 [ + + ][ - + ]: 556 : virtual ~SGRawValueMethodsIndexed () {}
[ + - ][ - + ]
[ - ][ - + ]
[ + - ][ - + ]
438 : 378503 : virtual T getValue () const {
439 [ + - ][ - + ]: 378503 : if (_getter) { return (_obj.*_getter)(_index); }
[ + - ][ - + ]
440 : 378503 : else { return SGRawValue<T>::DefaultValue; }
441 : : }
442 : 213136 : virtual bool setValue (T value) {
443 [ # # ][ # # ]: 213136 : if (_setter) { (_obj.*_setter)(_index, value); return true; }
[ + - ][ - + ]
444 : 213136 : else return false;
445 : : }
446 : 278 : virtual SGRawValue<T> * clone () const {
447 : 278 : return new SGRawValueMethodsIndexed<C,T>(_obj, _index, _getter, _setter);
448 : : }
449 : : private:
450 : : C &_obj;
451 : : int _index;
452 : : getter_t _getter;
453 : : setter_t _setter;
454 : : };
455 : :
456 : :
457 : : /**
458 : : * The smart pointer that manage reference counting
459 : : */
460 : : class SGPropertyNode;
461 : : typedef SGSharedPtr<SGPropertyNode> SGPropertyNode_ptr;
462 : : typedef SGSharedPtr<const SGPropertyNode> SGConstPropertyNode_ptr;
463 : :
464 : :
465 : : /**
466 : : * The property change listener interface.
467 : : *
468 : : * <p>Any class that needs to listen for property changes must implement
469 : : * this interface.</p>
470 : : */
471 : : class SGPropertyChangeListener
472 : : {
473 : : public:
474 : : virtual ~SGPropertyChangeListener ();
475 : : virtual void valueChanged (SGPropertyNode * node);
476 : : virtual void childAdded (SGPropertyNode * parent, SGPropertyNode * child);
477 : : virtual void childRemoved (SGPropertyNode * parent, SGPropertyNode * child);
478 : :
479 : : protected:
480 : : friend class SGPropertyNode;
481 : : virtual void register_property (SGPropertyNode * node);
482 : : virtual void unregister_property (SGPropertyNode * node);
483 : :
484 : : private:
485 : : vector<SGPropertyNode *> _properties;
486 : : };
487 : :
488 : :
489 : :
490 : : /**
491 : : * A node in a property tree.
492 : : */
493 : : class SGPropertyNode : public SGReferenced
494 : : {
495 : : public:
496 : :
497 : : /**
498 : : * Public constants.
499 : : */
500 : : enum {
501 : : MAX_STRING_LEN = 1024
502 : : };
503 : :
504 : : /**
505 : : * Property value types.
506 : : */
507 : : enum Type {
508 : : NONE = 0,
509 : : ALIAS,
510 : : BOOL,
511 : : INT,
512 : : LONG,
513 : : FLOAT,
514 : : DOUBLE,
515 : : STRING,
516 : : UNSPECIFIED
517 : : };
518 : :
519 : :
520 : : /**
521 : : * Access mode attributes.
522 : : *
523 : : * <p>The ARCHIVE attribute is strictly advisory, and controls
524 : : * whether the property should normally be saved and restored.</p>
525 : : */
526 : : enum Attribute {
527 : : READ = 1,
528 : : WRITE = 2,
529 : : ARCHIVE = 4,
530 : : REMOVED = 8,
531 : : TRACE_READ = 16,
532 : : TRACE_WRITE = 32,
533 : : USERARCHIVE = 64
534 : : };
535 : :
536 : :
537 : : /**
538 : : * Last used attribute
539 : : * Update as needed when enum Attribute is changed
540 : : */
541 : : static const int LAST_USED_ATTRIBUTE;
542 : :
543 : :
544 : : /**
545 : : * Default constructor.
546 : : */
547 : : SGPropertyNode ();
548 : :
549 : :
550 : : /**
551 : : * Copy constructor.
552 : : */
553 : : SGPropertyNode (const SGPropertyNode &node);
554 : :
555 : :
556 : : /**
557 : : * Destructor.
558 : : */
559 : : virtual ~SGPropertyNode ();
560 : :
561 : :
562 : :
563 : : //
564 : : // Basic properties.
565 : : //
566 : :
567 : : /**
568 : : * Test whether this node contains a primitive leaf value.
569 : : */
570 : 650 : bool hasValue () const { return (_type != NONE); }
571 : :
572 : :
573 : : /**
574 : : * Get the node's simple (XML) name.
575 : : */
576 : 113046 : const char * getName () const { return _name.c_str(); }
577 : :
578 : :
579 : : /**
580 : : * Get the node's pretty display name, with subscript when needed.
581 : : */
582 : : const char * getDisplayName (bool simplify = false) const;
583 : :
584 : :
585 : : /**
586 : : * Get the node's integer index.
587 : : */
588 : 7789 : int getIndex () const { return _index; }
589 : :
590 : :
591 : : /**
592 : : * Get a non-const pointer to the node's parent.
593 : : */
594 : 14666 : SGPropertyNode * getParent () { return _parent; }
595 : :
596 : :
597 : : /**
598 : : * Get a const pointer to the node's parent.
599 : : */
600 : : const SGPropertyNode * getParent () const { return _parent; }
601 : :
602 : :
603 : : //
604 : : // Children.
605 : : //
606 : :
607 : :
608 : : /**
609 : : * Get the number of child nodes.
610 : : */
611 : 12906 : int nChildren () const { return (int)_children.size(); }
612 : :
613 : :
614 : : /**
615 : : * Get a child node by position (*NOT* index).
616 : : */
617 : : SGPropertyNode * getChild (int position);
618 : :
619 : :
620 : : /**
621 : : * Get a const child node by position (*NOT* index).
622 : : */
623 : : const SGPropertyNode * getChild (int position) const;
624 : :
625 : :
626 : : /**
627 : : * Test whether a named child exists.
628 : : */
629 : : bool hasChild (const char * name, int index = 0) const
630 : : {
631 : : return (getChild(name, index) != 0);
632 : : }
633 : :
634 : :
635 : : /**
636 : : * Get a child node by name and index.
637 : : */
638 : : SGPropertyNode * getChild (const char * name, int index = 0,
639 : : bool create = false);
640 : :
641 : :
642 : : /**
643 : : * Get a const child node by name and index.
644 : : */
645 : : const SGPropertyNode * getChild (const char * name, int index = 0) const;
646 : :
647 : :
648 : : /**
649 : : * Get a vector of all children with the specified name.
650 : : */
651 : : vector<SGPropertyNode_ptr> getChildren (const char * name) const;
652 : :
653 : :
654 : : /**
655 : : * Remove child by position.
656 : : */
657 : : SGPropertyNode_ptr removeChild (int pos, bool keep = true);
658 : :
659 : :
660 : : /**
661 : : * Remove a child node
662 : : */
663 : : SGPropertyNode_ptr removeChild (const char * name, int index = 0,
664 : : bool keep = true);
665 : :
666 : : /**
667 : : * Remove all children with the specified name.
668 : : */
669 : : vector<SGPropertyNode_ptr> removeChildren (const char * name,
670 : : bool keep = true);
671 : :
672 : :
673 : : //
674 : : // Alias support.
675 : : //
676 : :
677 : :
678 : : /**
679 : : * Alias this node's leaf value to another's.
680 : : */
681 : : bool alias (SGPropertyNode * target);
682 : :
683 : :
684 : : /**
685 : : * Alias this node's leaf value to another's by relative path.
686 : : */
687 : : bool alias (const char * path);
688 : :
689 : :
690 : : /**
691 : : * Remove any alias for this node.
692 : : */
693 : : bool unalias ();
694 : :
695 : :
696 : : /**
697 : : * Test whether the node's leaf value is aliased to another's.
698 : : */
699 : : bool isAlias () const { return (_type == ALIAS); }
700 : :
701 : :
702 : : /**
703 : : * Get a non-const pointer to the current alias target, if any.
704 : : */
705 : : SGPropertyNode * getAliasTarget ();
706 : :
707 : :
708 : : /**
709 : : * Get a const pointer to the current alias target, if any.
710 : : */
711 : : const SGPropertyNode * getAliasTarget () const;
712 : :
713 : :
714 : : //
715 : : // Path information.
716 : : //
717 : :
718 : :
719 : : /**
720 : : * Get the path to this node from the root.
721 : : */
722 : : const char * getPath (bool simplify = false) const;
723 : :
724 : :
725 : : /**
726 : : * Get a pointer to the root node.
727 : : */
728 : : SGPropertyNode * getRootNode ();
729 : :
730 : :
731 : : /**
732 : : * Get a const pointer to the root node.
733 : : */
734 : : const SGPropertyNode * getRootNode () const;
735 : :
736 : :
737 : : /**
738 : : * Get a pointer to another node by relative path.
739 : : */
740 : : SGPropertyNode * getNode (const char * relative_path, bool create = false);
741 : :
742 : :
743 : : /**
744 : : * Get a pointer to another node by relative path.
745 : : *
746 : : * This method leaves the index off the last member of the path,
747 : : * so that the user can specify it separately (and save some
748 : : * string building). For example, getNode("/bar[1]/foo", 3) is
749 : : * exactly equivalent to getNode("bar[1]/foo[3]"). The index
750 : : * provided overrides any given in the path itself for the last
751 : : * component.
752 : : */
753 : : SGPropertyNode * getNode (const char * relative_path, int index,
754 : : bool create = false);
755 : :
756 : :
757 : : /**
758 : : * Get a const pointer to another node by relative path.
759 : : */
760 : : const SGPropertyNode * getNode (const char * relative_path) const;
761 : :
762 : :
763 : : /**
764 : : * Get a const pointer to another node by relative path.
765 : : *
766 : : * This method leaves the index off the last member of the path,
767 : : * so that the user can specify it separate.
768 : : */
769 : : const SGPropertyNode * getNode (const char * relative_path,
770 : : int index) const;
771 : :
772 : :
773 : : //
774 : : // Access Mode.
775 : : //
776 : :
777 : : /**
778 : : * Check a single mode attribute for the property node.
779 : : */
780 : 109424 : bool getAttribute (Attribute attr) const { return ((_attr & attr) != 0); }
781 : :
782 : :
783 : : /**
784 : : * Set a single mode attribute for the property node.
785 : : */
786 : : void setAttribute (Attribute attr, bool state) {
787 [ # # ][ # # ]: 0 : (state ? _attr |= attr : _attr &= ~attr);
[ # # ][ # # ]
788 : : }
789 : :
790 : :
791 : : /**
792 : : * Get all of the mode attributes for the property node.
793 : : */
794 : : int getAttributes () const { return _attr; }
795 : :
796 : :
797 : : /**
798 : : * Set all of the mode attributes for the property node.
799 : : */
800 : : void setAttributes (int attr) { _attr = attr; }
801 : :
802 : :
803 : : //
804 : : // Leaf Value (primitive).
805 : : //
806 : :
807 : :
808 : : /**
809 : : * Get the type of leaf value, if any, for this node.
810 : : */
811 : : Type getType () const;
812 : :
813 : :
814 : : /**
815 : : * Get a bool value for this node.
816 : : */
817 : : bool getBoolValue () const;
818 : :
819 : :
820 : : /**
821 : : * Get an int value for this node.
822 : : */
823 : : int getIntValue () const;
824 : :
825 : :
826 : : /**
827 : : * Get a long int value for this node.
828 : : */
829 : : long getLongValue () const;
830 : :
831 : :
832 : : /**
833 : : * Get a float value for this node.
834 : : */
835 : : float getFloatValue () const;
836 : :
837 : :
838 : : /**
839 : : * Get a double value for this node.
840 : : */
841 : : double getDoubleValue () const;
842 : :
843 : :
844 : : /**
845 : : * Get a string value for this node.
846 : : */
847 : : const char * getStringValue () const;
848 : :
849 : :
850 : :
851 : : /**
852 : : * Set a bool value for this node.
853 : : */
854 : : bool setBoolValue (bool value);
855 : :
856 : :
857 : : /**
858 : : * Set an int value for this node.
859 : : */
860 : : bool setIntValue (int value);
861 : :
862 : :
863 : : /**
864 : : * Set a long int value for this node.
865 : : */
866 : : bool setLongValue (long value);
867 : :
868 : :
869 : : /**
870 : : * Set a float value for this node.
871 : : */
872 : : bool setFloatValue (float value);
873 : :
874 : :
875 : : /**
876 : : * Set a double value for this node.
877 : : */
878 : : bool setDoubleValue (double value);
879 : :
880 : :
881 : : /**
882 : : * Set a string value for this node.
883 : : */
884 : : bool setStringValue (const char * value);
885 : :
886 : :
887 : : /**
888 : : * Set a value of unspecified type for this node.
889 : : */
890 : : bool setUnspecifiedValue (const char * value);
891 : :
892 : :
893 : : //
894 : : // Data binding.
895 : : //
896 : :
897 : :
898 : : /**
899 : : * Test whether this node is bound to an external data source.
900 : : */
901 : 699 : bool isTied () const { return _tied; }
902 : :
903 : :
904 : : /**
905 : : * Bind this node to an external bool source.
906 : : */
907 : : bool tie (const SGRawValue<bool> &rawValue, bool useDefault = true);
908 : :
909 : :
910 : : /**
911 : : * Bind this node to an external int source.
912 : : */
913 : : bool tie (const SGRawValue<int> &rawValue, bool useDefault = true);
914 : :
915 : :
916 : : /**
917 : : * Bind this node to an external long int source.
918 : : */
919 : : bool tie (const SGRawValue<long> &rawValue, bool useDefault = true);
920 : :
921 : :
922 : : /**
923 : : * Bind this node to an external float source.
924 : : */
925 : : bool tie (const SGRawValue<float> &rawValue, bool useDefault = true);
926 : :
927 : :
928 : : /**
929 : : * Bind this node to an external double source.
930 : : */
931 : : bool tie (const SGRawValue<double> &rawValue, bool useDefault = true);
932 : :
933 : :
934 : : /**
935 : : * Bind this node to an external string source.
936 : : */
937 : : bool tie (const SGRawValue<const char *> &rawValue, bool useDefault = true);
938 : :
939 : :
940 : : /**
941 : : * Unbind this node from any external data source.
942 : : */
943 : : bool untie ();
944 : :
945 : :
946 : : //
947 : : // Convenience methods using paths.
948 : : // TODO: add attribute methods
949 : : //
950 : :
951 : :
952 : : /**
953 : : * Get another node's type.
954 : : */
955 : : Type getType (const char * relative_path) const;
956 : :
957 : :
958 : : /**
959 : : * Test whether another node has a leaf value.
960 : : */
961 : : bool hasValue (const char * relative_path) const;
962 : :
963 : :
964 : : /**
965 : : * Get another node's value as a bool.
966 : : */
967 : : bool getBoolValue (const char * relative_path,
968 : : bool defaultValue = false) const;
969 : :
970 : :
971 : : /**
972 : : * Get another node's value as an int.
973 : : */
974 : : int getIntValue (const char * relative_path,
975 : : int defaultValue = 0) const;
976 : :
977 : :
978 : : /**
979 : : * Get another node's value as a long int.
980 : : */
981 : : long getLongValue (const char * relative_path,
982 : : long defaultValue = 0L) const;
983 : :
984 : :
985 : : /**
986 : : * Get another node's value as a float.
987 : : */
988 : : float getFloatValue (const char * relative_path,
989 : : float defaultValue = 0.0) const;
990 : :
991 : :
992 : : /**
993 : : * Get another node's value as a double.
994 : : */
995 : : double getDoubleValue (const char * relative_path,
996 : : double defaultValue = 0.0L) const;
997 : :
998 : :
999 : : /**
1000 : : * Get another node's value as a string.
1001 : : */
1002 : : const char * getStringValue (const char * relative_path,
1003 : : const char * defaultValue = "") const;
1004 : :
1005 : :
1006 : : /**
1007 : : * Set another node's value as a bool.
1008 : : */
1009 : : bool setBoolValue (const char * relative_path, bool value);
1010 : :
1011 : :
1012 : : /**
1013 : : * Set another node's value as an int.
1014 : : */
1015 : : bool setIntValue (const char * relative_path, int value);
1016 : :
1017 : :
1018 : : /**
1019 : : * Set another node's value as a long int.
1020 : : */
1021 : : bool setLongValue (const char * relative_path, long value);
1022 : :
1023 : :
1024 : : /**
1025 : : * Set another node's value as a float.
1026 : : */
1027 : : bool setFloatValue (const char * relative_path, float value);
1028 : :
1029 : :
1030 : : /**
1031 : : * Set another node's value as a double.
1032 : : */
1033 : : bool setDoubleValue (const char * relative_path, double value);
1034 : :
1035 : :
1036 : : /**
1037 : : * Set another node's value as a string.
1038 : : */
1039 : : bool setStringValue (const char * relative_path, const char * value);
1040 : :
1041 : :
1042 : : /**
1043 : : * Set another node's value with no specified type.
1044 : : */
1045 : : bool setUnspecifiedValue (const char * relative_path, const char * value);
1046 : :
1047 : :
1048 : : /**
1049 : : * Test whether another node is bound to an external data source.
1050 : : */
1051 : : bool isTied (const char * relative_path) const;
1052 : :
1053 : :
1054 : : /**
1055 : : * Bind another node to an external bool source.
1056 : : */
1057 : : bool tie (const char * relative_path, const SGRawValue<bool> &rawValue,
1058 : : bool useDefault = true);
1059 : :
1060 : :
1061 : : /**
1062 : : * Bind another node to an external int source.
1063 : : */
1064 : : bool tie (const char * relative_path, const SGRawValue<int> &rawValue,
1065 : : bool useDefault = true);
1066 : :
1067 : :
1068 : : /**
1069 : : * Bind another node to an external long int source.
1070 : : */
1071 : : bool tie (const char * relative_path, const SGRawValue<long> &rawValue,
1072 : : bool useDefault = true);
1073 : :
1074 : :
1075 : : /**
1076 : : * Bind another node to an external float source.
1077 : : */
1078 : : bool tie (const char * relative_path, const SGRawValue<float> &rawValue,
1079 : : bool useDefault = true);
1080 : :
1081 : :
1082 : : /**
1083 : : * Bind another node to an external double source.
1084 : : */
1085 : : bool tie (const char * relative_path, const SGRawValue<double> &rawValue,
1086 : : bool useDefault = true);
1087 : :
1088 : :
1089 : : /**
1090 : : * Bind another node to an external string source.
1091 : : */
1092 : : bool tie (const char * relative_path, const SGRawValue<const char *> &rawValue,
1093 : : bool useDefault = true);
1094 : :
1095 : :
1096 : : /**
1097 : : * Unbind another node from any external data source.
1098 : : */
1099 : : bool untie (const char * relative_path);
1100 : :
1101 : :
1102 : : /**
1103 : : * Add a change listener to the property. If "initial" is set call the
1104 : : * listener initially.
1105 : : */
1106 : : void addChangeListener (SGPropertyChangeListener * listener,
1107 : : bool initial = false);
1108 : :
1109 : :
1110 : : /**
1111 : : * Remove a change listener from the property.
1112 : : */
1113 : : void removeChangeListener (SGPropertyChangeListener * listener);
1114 : :
1115 : :
1116 : : /**
1117 : : * Fire a value change event to all listeners.
1118 : : */
1119 : : void fireValueChanged ();
1120 : :
1121 : :
1122 : : /**
1123 : : * Fire a child-added event to all listeners.
1124 : : */
1125 : : void fireChildAdded (SGPropertyNode * child);
1126 : :
1127 : :
1128 : : /**
1129 : : * Fire a child-removed event to all listeners.
1130 : : */
1131 : : void fireChildRemoved (SGPropertyNode * child);
1132 : :
1133 : :
1134 : : /**
1135 : : * Clear any existing value and set the type to NONE.
1136 : : */
1137 : : void clearValue ();
1138 : :
1139 : :
1140 : : protected:
1141 : :
1142 : : void fireValueChanged (SGPropertyNode * node);
1143 : : void fireChildAdded (SGPropertyNode * parent, SGPropertyNode * child);
1144 : : void fireChildRemoved (SGPropertyNode * parent, SGPropertyNode * child);
1145 : :
1146 : : /**
1147 : : * Protected constructor for making new nodes on demand.
1148 : : */
1149 : : SGPropertyNode (const char * name, int index, SGPropertyNode * parent);
1150 : :
1151 : :
1152 : : private:
1153 : :
1154 : : // Get the raw value
1155 : : bool get_bool () const;
1156 : : int get_int () const;
1157 : : long get_long () const;
1158 : : float get_float () const;
1159 : : double get_double () const;
1160 : : const char * get_string () const;
1161 : :
1162 : : // Set the raw value
1163 : : bool set_bool (bool value);
1164 : : bool set_int (int value);
1165 : : bool set_long (long value);
1166 : : bool set_float (float value);
1167 : : bool set_double (double value);
1168 : : bool set_string (const char * value);
1169 : :
1170 : :
1171 : : /**
1172 : : * Get the value as a string.
1173 : : */
1174 : : const char * make_string () const;
1175 : :
1176 : :
1177 : : /**
1178 : : * Trace a read access.
1179 : : */
1180 : : void trace_read () const;
1181 : :
1182 : :
1183 : : /**
1184 : : * Trace a write access.
1185 : : */
1186 : : void trace_write () const;
1187 : :
1188 : :
1189 : : class hash_table;
1190 : :
1191 : : int _index;
1192 : : string _name;
1193 : : mutable string _display_name;
1194 : : /// To avoid cyclic reference counting loops this shall not be a reference
1195 : : /// counted pointer
1196 : : SGPropertyNode * _parent;
1197 : : vector<SGPropertyNode_ptr> _children;
1198 : : vector<SGPropertyNode_ptr> _removedChildren;
1199 : : mutable string _path;
1200 : : mutable string _buffer;
1201 : : hash_table * _path_cache;
1202 : : Type _type;
1203 : : bool _tied;
1204 : : int _attr;
1205 : :
1206 : : // The right kind of pointer...
1207 : : union {
1208 : : SGPropertyNode * alias;
1209 : : SGRawValue<bool> * bool_val;
1210 : : SGRawValue<int> * int_val;
1211 : : SGRawValue<long> * long_val;
1212 : : SGRawValue<float> * float_val;
1213 : : SGRawValue<double> * double_val;
1214 : : SGRawValue<const char *> * string_val;
1215 : : } _value;
1216 : :
1217 : : union {
1218 : : bool bool_val;
1219 : : int int_val;
1220 : : long long_val;
1221 : : float float_val;
1222 : : double double_val;
1223 : : char * string_val;
1224 : : } _local_val;
1225 : :
1226 : : vector <SGPropertyChangeListener *> * _listeners;
1227 : :
1228 : :
1229 : :
1230 : : /**
1231 : : * A very simple hash table with no remove functionality.
1232 : : */
1233 : : class hash_table {
1234 : : public:
1235 : :
1236 : : /**
1237 : : * An entry in a bucket in a hash table.
1238 : : */
1239 : : class entry {
1240 : : public:
1241 : : entry ();
1242 : : ~entry ();
1243 : 5750 : const char * get_key () { return _key.c_str(); }
1244 : : void set_key (const char * key);
1245 : 418 : SGPropertyNode * get_value () { return _value; }
1246 : : void set_value (SGPropertyNode * value);
1247 : : private:
1248 : : string _key;
1249 : : SGSharedPtr<SGPropertyNode> _value;
1250 : : };
1251 : :
1252 : :
1253 : : /**
1254 : : * A bucket in a hash table.
1255 : : */
1256 : : class bucket {
1257 : : public:
1258 : : bucket ();
1259 : : ~bucket ();
1260 : : entry * get_entry (const char * key, bool create = false);
1261 : : void erase(const char * key);
1262 : : private:
1263 : : int _length;
1264 : : entry ** _entries;
1265 : : };
1266 : :
1267 : : friend class bucket;
1268 : :
1269 : : hash_table ();
1270 : : ~hash_table ();
1271 : : SGPropertyNode * get (const char * key);
1272 : : void put (const char * key, SGPropertyNode * value);
1273 : : void erase(const char * key);
1274 : :
1275 : : private:
1276 : : unsigned int hashcode (const char * key);
1277 : : unsigned int _data_length;
1278 : : bucket ** _data;
1279 : : };
1280 : :
1281 : : };
1282 : :
1283 : : #endif // __PROPS_HXX
1284 : :
1285 : : // end of props.hxx
|