Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035 #ifndef STRINGTREE_H
00036 #define STRINGTREE_H
00037
00038 #include <vector>
00039 #include <deque>
00040 #include <iostream>
00041 #include <boost/container/stable_vector.hpp>
00042 #include <boost/noncopyable.hpp>
00043 #include "ros_type_introspection/string.hpp"
00044
00045 namespace RosIntrospection {
00046
00047 namespace details{
00048
00049
00050
00051
00052 #define STATIC_TREE true
00053
00057 template <typename T> class TreeElement
00058 {
00059
00060 public:
00061 #if !STATIC_TREE
00062 typedef boost::container::stable_vector<TreeElement> ChildrenVector;
00063 #else
00064 typedef std::vector<TreeElement> ChildrenVector;
00065 #endif
00066
00067 TreeElement(const TreeElement* parent, const T& value );
00068
00069 const TreeElement* parent() const { return _parent; }
00070
00071 const T& value() const { return _value; }
00072 T& value() { return _value; }
00073
00074 const ChildrenVector& children()const { return _children; }
00075 ChildrenVector& children() { return _children; }
00076
00077 void addChild(const T& child );
00078
00079 bool isLeaf() const { return _children.empty(); }
00080
00081 private:
00082 const TreeElement* _parent;
00083 T _value;
00084 ChildrenVector _children;
00085 };
00086
00087
00088 template <typename T> class Tree : boost::noncopyable
00089 {
00090 public:
00091 Tree(): _root(nullptr,"root") {}
00092
00093 #if !STATIC_TREE // this operation is illegal in a static tree
00094
00099 template<typename Vect> void insert(const Vect& concatenated_values);
00100 #endif
00101
00107 template<typename Vect> const TreeElement<T>* find( const Vect& concatenated_values, bool partial_allowed = false);
00108
00110 const TreeElement<T>* croot() const { return &_root; }
00111
00113 TreeElement<T>* root() { return &_root; }
00114
00115
00116 friend std::ostream& operator<<(std::ostream& os, const Tree& _this){
00117 _this.print_impl(os, (_this._root.children()), 0);
00118 return os;
00119 }
00120
00121 private:
00122
00123 void print_impl(std::ostream& os, const typename TreeElement<T>::ChildrenVector& children, int indent ) const;
00124
00125 TreeElement<T> _root;
00126 };
00127
00128
00129
00130
00131 template <typename T> inline
00132 std::ostream& operator<<(std::ostream &os, const std::pair<const TreeElement<T>*, const TreeElement<T>* >& tail_head )
00133 {
00134 const TreeElement<T>* tail = tail_head.first;
00135 const TreeElement<T>* head = tail_head.second;
00136
00137 if( !head ) return os;
00138
00139 const TreeElement<T>* array[64];
00140 int index = 0;
00141 array[index++] = head;
00142
00143 while( !head || head != tail)
00144 {
00145 head = head->parent();
00146 array[index++] = head;
00147 };
00148 array[index] = nullptr;
00149 index--;
00150
00151 while ( index >=0)
00152 {
00153 if( array[index] ){
00154 os << array[index]->value();
00155 }
00156 if( index >0 ) os << ".";
00157 index--;
00158 }
00159 return os;
00160 }
00161
00162 template <typename T> inline
00163 void Tree<T>::print_impl(std::ostream &os, const typename TreeElement<T>::ChildrenVector& children, int indent) const
00164 {
00165 for (const auto& child: children)
00166 {
00167 for (int i=0; i<indent; i++) os << " ";
00168 os << child.value();
00169 if( child.parent())
00170 std::cout << "("<< child.parent()->value() << ")" << std::endl;
00171 else
00172 std::cout << "(null)" << std::endl;
00173 print_impl(os, child.children(), indent+3);
00174 }
00175 }
00176
00177 template <typename T> inline
00178 TreeElement<T>::TreeElement(const TreeElement *parent, const T& value):
00179 _parent(parent), _value(value)
00180 {
00181
00182 }
00183
00184 template <typename T> inline
00185 void TreeElement<T>::addChild(const T& value)
00186 {
00187
00188 for (int i=0; i< _children.size(); i++){
00189 if( value == _children[i].value() ){
00190 return;
00191 }
00192 }
00193 #if STATIC_TREE
00194 assert(_children.capacity() > _children.size() );
00195 #endif
00196 _children.push_back( TreeElement<T>(this, value));
00197 }
00198
00199 #if !STATIC_TREE
00200 template <typename T> template<typename Vect> inline
00201 void Tree<T>::insert(const Vect &concatenated_values)
00202 {
00203 TreeElement<T>* node = &_root;
00204
00205 for (const auto& value: concatenated_values)
00206 {
00207 bool found = false;
00208 for (auto& child: (node->children() ) )
00209 {
00210 if( child.value() == value)
00211 {
00212 node = &(child);
00213 found = true;
00214 break;
00215 }
00216 }
00217 if(!found){
00218 node->addChild( value );
00219 node = &(node->children().back());
00220 }
00221 }
00222 }
00223 #endif
00224
00225 template <typename T> template<typename Vect> inline
00226 const TreeElement<T> *Tree<T>::find(const Vect& concatenated_values, bool partial_allowed )
00227 {
00228 TreeElement<T>* node = &_root;
00229
00230 for (const auto& value: concatenated_values)
00231 {
00232 bool found = false;
00233 for (auto& child: (node->children() ) )
00234 {
00235 if( child.value() == value)
00236 {
00237 node = &(child);
00238 found = true;
00239 break;
00240 }
00241 }
00242 if( !found ) return nullptr;
00243 }
00244
00245 if( partial_allowed || node->children().empty() )
00246 {
00247 return node;
00248 }
00249 return nullptr;
00250 }
00251
00252 }
00253
00254 }
00255
00256
00257
00258 #endif // STRINGTREE_H