diff options
Diffstat (limited to 'ACE/ace/Obstack_T.cpp')
-rw-r--r-- | ACE/ace/Obstack_T.cpp | 208 |
1 files changed, 208 insertions, 0 deletions
diff --git a/ACE/ace/Obstack_T.cpp b/ACE/ace/Obstack_T.cpp new file mode 100644 index 00000000000..f7b781eee21 --- /dev/null +++ b/ACE/ace/Obstack_T.cpp @@ -0,0 +1,208 @@ +// $Id$ + +#ifndef ACE_OBSTACK_T_CPP +#define ACE_OBSTACK_T_CPP + +#include "ace/Obstack_T.h" +#include "ace/Malloc_Base.h" +#include "ace/OS_NS_string.h" + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +# pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + +#if !defined (__ACE_INLINE__) +#include "ace/Obstack_T.inl" +#endif /* __ACE_INLINE__ */ + +ACE_BEGIN_VERSIONED_NAMESPACE_DECL + +ACE_ALLOC_HOOK_DEFINE(ACE_Obstack_T) + +template <class CHAR> void +ACE_Obstack_T<CHAR>::dump (void) const +{ +#if defined (ACE_HAS_DUMP) + ACE_TRACE ("ACE_Obstack_T<CHAR>::dump"); + + ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this)); + ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("size_ = %d\n"), this->size_)); + ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("head_ = %x\n"), this->head_)); + ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("curr_ = %x\n"), this->curr_)); + ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP)); +#endif /* ACE_HAS_DUMP */ +} + +template <class CHAR> int +ACE_Obstack_T<CHAR>::request (size_t len) +{ + ACE_TRACE ("ACE_Obstack_T<CHAR>::request"); + + // normalize the length. + len *= sizeof (CHAR); + + // Check to see if there's room for the requested length, including + // any part of an existing string, if any. + size_t resulting_len = (this->curr_->cur_ - this->curr_->block_) + len; + + // Increase the length of the underlying chunks if the request made is + // for bigger sized chunks. + if (this->size_ < resulting_len) + this->size_ = this->size_ << 1; + + // We now know the request will fit; see if it can fit in the current + // chunk or will need a new one. + if (this->curr_->cur_ + len >= this->curr_->end_) + { + // Need a new chunk. Save the current one so the current string can be + // copied to the new chunk. + ACE_Obchunk *temp = this->curr_; + if (this->curr_->next_ == 0) + { + // We must allocate new memory. + ACE_Obchunk* tmp = this->new_chunk(); + if (!tmp) + return -1; + this->curr_->next_ = tmp; + this->curr_ = this->curr_->next_; + } + else + { + // We can reuse previously allocated memory. + this->curr_ = this->curr_->next_; + this->curr_->block_ = this->curr_->cur_ = this->curr_->contents_; + } + + // Copy any initial characters to the new chunk. + if (temp->cur_ != temp->block_) + { + size_t datasize = temp->cur_ - temp->block_; + ACE_OS::memcpy (this->curr_->block_, + temp->block_, + datasize); + this->curr_->cur_ = this->curr_->block_ + datasize; + // Reset the old chunk. + temp->cur_ = temp->block_; + } + } + + return 0; +} + +template <class CHAR> CHAR * +ACE_Obstack_T<CHAR>::grow (CHAR c) +{ + ACE_TRACE ("ACE_Obstack_T<CHAR>::grow"); + + if (this->request (1) == 0) + { + CHAR *retv = reinterpret_cast<CHAR *> (this->curr_->cur_); + this->curr_->cur_ += sizeof (CHAR); + *retv = c; + return retv; + } + else + return 0; +} + +template <class CHAR> ACE_Obchunk * +ACE_Obstack_T<CHAR>::new_chunk (void) +{ + ACE_TRACE ("ACE_Obstack_T<CHAR>::new_chunk"); + + ACE_Obchunk *temp; + + ACE_NEW_MALLOC_RETURN (temp, + static_cast<ACE_Obchunk *> (this->allocator_strategy_->malloc + (sizeof (class ACE_Obchunk) + this->size_)), + ACE_Obchunk (this->size_), + 0); + return temp; +} + +template <class CHAR> +ACE_Obstack_T<CHAR>::ACE_Obstack_T (size_t size, + ACE_Allocator *allocator_strategy) + : allocator_strategy_ (allocator_strategy), + size_ (size) +{ + ACE_TRACE ("ACE_Obstack_T<CHAR>::ACE_Obstack"); + + if (this->allocator_strategy_ == 0) + ACE_ALLOCATOR (this->allocator_strategy_, + ACE_Allocator::instance ()); + + this->head_ = this->new_chunk (); + this->curr_ = this->head_; +} + +template <class CHAR> +ACE_Obstack_T<CHAR>::~ACE_Obstack_T (void) +{ + ACE_TRACE ("ACE_Obstack_T<CHAR>::~ACE_Obstack_T"); + + ACE_Obchunk *temp = this->head_; + + while (temp != 0) + { + ACE_Obchunk *next = temp->next_; + temp->next_ = 0; + this->allocator_strategy_->free (temp); + temp = next; + } +} + +template <class CHAR> CHAR * +ACE_Obstack_T<CHAR>::copy (const CHAR *s, + size_t len) +{ + ACE_TRACE ("ACE_Obstack_T<CHAR>::copy"); + + if (this->request (len) != 0) + return 0; + + size_t tsize = len * sizeof (CHAR); + ACE_OS::memcpy (this->curr_->cur_, s, tsize); + this->curr_->cur_ += tsize ; + return this->freeze (); +} + +template <class CHAR> void +ACE_Obstack_T<CHAR>::unwind (void* obj) +{ + if (obj >= this->curr_->contents_ && obj < this->curr_->end_) + this->curr_->block_ = this->curr_->cur_ = reinterpret_cast<char*> (obj); + else + this->unwind_i (obj); +} + +template <class CHAR> void +ACE_Obstack_T<CHAR>::unwind_i (void* obj) +{ + ACE_Obchunk* curr; + + curr = this->head_; + while (curr != 0 && (curr->contents_ > obj || curr->end_ < obj)) + curr = curr->next_; + if (curr) + { + this->curr_ = curr; + this->curr_->block_ = this->curr_->cur_ = reinterpret_cast<char*> (obj); + } + else if (obj != 0) + ACE_ERROR ((LM_ERROR, + ACE_LIB_TEXT ("Deletion of non-existent object.\n%a"))); +} + +template <class CHAR> void +ACE_Obstack_T<CHAR>::release (void) +{ + ACE_TRACE ("ACE_Obstack_T<CHAR>::release"); + + this->curr_ = this->head_; + this->curr_->block_ = this->curr_->cur_ = this->curr_->contents_; +} + +ACE_END_VERSIONED_NAMESPACE_DECL + +#endif /* ACE_OBSTACK_T_CPP */ |