// ============================================================================ // // = LIBRARY // ULib - c++ library // // = FILENAME // tree.h // // = AUTHOR // Stefano Casazza // // ============================================================================ #ifndef ULIB_TREE_H #define ULIB_TREE_H 1 #include template class UTree; template <> class U_EXPORT UTree : public UVector { public: UTree(const void* __elem = U_NULLPTR, const void* __parent = U_NULLPTR, uint32_t n = 1) : UVector(n) { U_TRACE_REGISTER_OBJECT(0, UTree, "%p,%p,%u", __elem, __parent, n) _elem = __elem; _parent = __parent; } ~UTree() { U_TRACE_UNREGISTER_OBJECT(0, UTree) } // ACCESS const void* elem() const { return _elem; } UTree* parent() const { return (UTree*)_parent; } UVector* vector() const { return (UVector*)this; } UTree* childAt(uint32_t pos) const __pure { return (UTree*)vector()->at(pos); } // SERVICES bool null() const { U_TRACE_NO_PARAM(0, "UTree::null()") U_RETURN(_elem == U_NULLPTR); } bool root() const { U_TRACE_NO_PARAM(0, "UTree::root()") U_RETURN(_parent == U_NULLPTR); } bool empty() const { U_TRACE_NO_PARAM(0, "UTree::empty()") U_RETURN(_elem == U_NULLPTR && _length == 0); } uint32_t numChild() const { U_TRACE_NO_PARAM(0, "UTree::numChild()") U_RETURN(_length); } // compute the depth to the root uint32_t depth() const __pure { U_TRACE_NO_PARAM(0, "UTree::depth()") uint32_t result = 0; const UTree* p = this; while (p->parent() != U_NULLPTR) { ++result; p = p->parent(); } U_RETURN(result); } // OPERATIONS void setRoot(const void* __elem) { U_TRACE(0, "UTree::setRoot(%p)", __elem) U_CHECK_MEMORY U_INTERNAL_ASSERT_EQUALS(_parent, U_NULLPTR) _elem = __elem; } void setParent(const void* __parent) { U_TRACE(0, "UTree::setParent(%p)", __parent) U_CHECK_MEMORY _parent = __parent; } // STACK UTree* push(const void* __elem) // add to end { U_TRACE(0, "UTree::push(%p)", __elem) UTree* p; U_NEW(UTree, p, UTree(__elem, this, (size_allocate ? : 64))); UVector::push(p); U_RETURN_POINTER(p,UTree); } UTree* push_back(const void* __elem) { U_TRACE(0, "UTree::push_back(%p)", __elem) if (_parent == U_NULLPTR && _elem == U_NULLPTR) { _elem = __elem; return this; } return push(__elem); } UTree* last() // return last element { U_TRACE_NO_PARAM(0, "UTree::last()") return (UTree*) UVector::last(); } UTree* pop() // remove last element { U_TRACE_NO_PARAM(0, "UTree::pop()") return (UTree*) UVector::pop(); } // LIST UTree* insert(uint32_t pos, const void* __elem) // add elem before pos { U_TRACE(0, "UTree::insert(%u,%p)", pos, __elem) UTree* p; U_NEW(UTree, p, UTree(__elem, this)); UVector::insert(pos, p); U_RETURN_POINTER(p,UTree); } void erase(uint32_t pos) // remove element at pos { U_TRACE(0, "UTree::erase(%u)", pos) delete (UTree*) vec[pos]; UVector::erase(pos); } // Call function for all entry void callForAllEntry(vPFpvpv function); #if defined(U_STDCPP_ENABLE) && defined(DEBUG) const char* dump(bool reset) const; #endif static uint32_t size_allocate; protected: const void* _elem; const void* _parent; private: U_DISALLOW_ASSIGN(UTree) }; template class U_EXPORT UTree : public UTree { public: void clear() // erase all element { U_TRACE_NO_PARAM(0, "UTree::clear()") if (_elem) { u_destroy((const T*)_elem); _elem = U_NULLPTR; } if (UVector::empty() == false) { const void** _end = vec + _length; for (const void** ptr = vec; ptr < _end; ++ptr) delete (UTree*)(*ptr); _length = 0; } } UTree(const T* __elem = U_NULLPTR, const T* __parent = U_NULLPTR, uint32_t n = 1) : UTree(__elem, __parent, n) { U_TRACE_REGISTER_OBJECT(0, UTree, "%p,%p,%u", __elem, __parent, n) } ~UTree() { U_TRACE_UNREGISTER_OBJECT(0, UTree) clear(); } // ACCESS T* elem() const { return (T*) _elem; } UTree* parent() const { return (UTree*)_parent; } UVector* vector() const { return (UVector*)this; } UTree* childAt(uint32_t pos) const __pure { return (UTree*)((UVector*)this)->at(pos); } T* front() { return ((UTree*)UVector::front())->elem(); } T* back() { return ((UTree*)UVector::back())->elem(); } T* at(uint32_t pos) const { return ((UTree*)UVector::at(pos))->elem(); } T* operator[](uint32_t pos) const { return at(pos); } // OPERATIONS void setRoot(const T* __elem) { U_TRACE(0, "UTree::setRoot(%p)", __elem) u_construct(&__elem, false); UTree::setRoot(__elem); } // STACK UTree* push(const T* __elem) // add to end { U_TRACE(0, "UTree::push(%p)", __elem) u_construct(&__elem, false); return (UTree*) UTree::push(__elem); } UTree* push_back(const T* __elem) { U_TRACE(0, "UTree::push_back(%p)", __elem) if (_parent == U_NULLPTR && _elem == U_NULLPTR) { setRoot(__elem); return this; } return push(__elem); } UTree* last() // return last element { U_TRACE_NO_PARAM(0, "UTree::last()") return (UTree*) UVector::last(); } UTree* pop() // remove last element { U_TRACE_NO_PARAM(0, "UTree::pop()") return (UTree*) UVector::pop(); } // LIST UTree* insert(uint32_t pos, const T* __elem) // add elem before pos { U_TRACE(0, "UTree::insert(%u,%p)", pos, __elem) u_construct(&__elem, false); return (UTree*) UTree::insert(pos, __elem); } void erase(uint32_t pos) // remove element at pos { U_TRACE(0, "UTree::erase(%u)", pos) delete (UTree*) vec[pos]; UVector::erase(pos); } // STREAMS #ifdef U_STDCPP_ENABLE friend ostream& operator<<(ostream& os, const UTree& t) { U_TRACE(0+256, "UTree::operator<<(%p,%p)", &os, &t) for (uint32_t i = 0; i < t.depth(); ++i) { os.put('\t'); } os.put('['); if (t.null() == false) { os.put(' '); os << *(t.elem()); } if (t.UVector::empty() == false) { UTree* p; for (const void** ptr = t.vec; ptr < (t.vec + t._length); ++ptr) { p = (UTree*)(*ptr); os.put('\n'); os << *p; } } os.put(' '); os.put(']'); return os; } # ifdef DEBUG const char* dump(bool reset) const { return UTree::dump(reset); } # endif #endif private: U_DISALLOW_ASSIGN(UTree) }; template <> class U_EXPORT UTree : public UTree { public: UTree(uint32_t n = 64) : UTree(U_NULLPTR, U_NULLPTR, n) { U_TRACE_REGISTER_OBJECT(0, UTree, "%u", n) } ~UTree() { U_TRACE_UNREGISTER_OBJECT(0, UTree) } // ACCESS UString elem() const { U_TRACE_NO_PARAM(0, "UTree::elem()") if (_elem) { UString str((UStringRep*)_elem); U_RETURN_STRING(str); } return UString::getStringNull(); } UTree* parent() const { return (UTree*)_parent; } UVector* vector() const { return (UVector*)this; } UTree* childAt(uint32_t pos) const __pure { return (UTree*)((UVector*)this)->at(pos); } UString back(); UString front() { return ((UTree*)UVector::front())->elem(); } UString at(uint32_t pos) const { return ((UTree*)UVector::at(pos))->elem(); } UString operator[](uint32_t pos) const { return at(pos); } // OPERATIONS void setRoot(const UString& str) { U_TRACE(0, "UTree::setRoot(%V)", str.rep) UTree::setRoot(str.rep); } // STACK UTree* push(const UString& str) { U_TRACE(0, "UTree::push(%V)", str.rep) return (UTree*) UTree::push(str.rep); } UTree* push_back(const UString& str) { U_TRACE(0, "UTree::push_back(%V)", str.rep) return (UTree*) UTree::push_back(str.rep); } UTree* last() { U_TRACE_NO_PARAM(0, "UTree::last()") return (UTree*) UTree::last(); } UTree* pop() { U_TRACE_NO_PARAM(0, "UTree::pop()") return (UTree*) UTree::pop(); } // LIST void insert(uint32_t pos, const UString& str); // add elem before pos // EXTENSION uint32_t find(const UString& str) __pure; // STREAMS #ifdef U_STDCPP_ENABLE friend U_EXPORT istream& operator>>(istream& is, UTree& t); friend ostream& operator<<(ostream& os, const UTree& t) { return operator<<(os, (const UTree&)t); } #endif private: U_DISALLOW_ASSIGN(UTree) }; #endif