GitHub Actions: Try MSVC builds with /std:c++17 and 20
[ACE_TAO.git] / ACE / ace / Obstack_T.cpp
blob659f643e980421a9f45ae505c5ca3da4554baf71
1 #ifndef ACE_OBSTACK_T_CPP
2 #define ACE_OBSTACK_T_CPP
4 #include "ace/Obstack_T.h"
5 #include "ace/Malloc_Base.h"
6 #include "ace/OS_NS_string.h"
8 #if !defined (ACE_LACKS_PRAGMA_ONCE)
9 # pragma once
10 #endif /* ACE_LACKS_PRAGMA_ONCE */
12 #if !defined (__ACE_INLINE__)
13 #include "ace/Obstack_T.inl"
14 #endif /* __ACE_INLINE__ */
16 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
18 ACE_ALLOC_HOOK_DEFINE_Tc(ACE_Obstack_T)
20 template <class ACE_CHAR_T> void
21 ACE_Obstack_T<ACE_CHAR_T>::dump (void) const
23 #if defined (ACE_HAS_DUMP)
24 ACE_TRACE ("ACE_Obstack_T<ACE_CHAR_T>::dump");
26 ACELIB_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
27 ACELIB_DEBUG ((LM_DEBUG, ACE_TEXT ("size_ = %d\n"), this->size_));
28 ACELIB_DEBUG ((LM_DEBUG, ACE_TEXT ("head_ = %x\n"), this->head_));
29 ACELIB_DEBUG ((LM_DEBUG, ACE_TEXT ("curr_ = %x\n"), this->curr_));
30 ACELIB_DEBUG ((LM_DEBUG, ACE_END_DUMP));
31 #endif /* ACE_HAS_DUMP */
34 template <class ACE_CHAR_T> int
35 ACE_Obstack_T<ACE_CHAR_T>::request (size_t len)
37 ACE_TRACE ("ACE_Obstack_T<ACE_CHAR_T>::request");
39 // normalize the length.
40 len *= sizeof (ACE_CHAR_T);
42 // Check to see if there's room for the requested length, including
43 // any part of an existing string, if any.
44 size_t resulting_len = (this->curr_->cur_ - this->curr_->block_) + len;
46 // Increase the length of the underlying chunks if the request made is
47 // for bigger sized chunks.
48 if (this->size_ < resulting_len)
49 this->size_ = this->size_ << 1;
51 // We now know the request will fit; see if it can fit in the current
52 // chunk or will need a new one.
53 if (this->curr_->cur_ + len >= this->curr_->end_)
55 // Need a new chunk. Save the current one so the current string
56 // can be copied to the new chunk.
57 ACE_Obchunk *temp = this->curr_;
58 if (this->curr_->next_ == 0)
60 // We must allocate new memory.
61 ACE_Obchunk* tmp = this->new_chunk();
62 if (!tmp)
63 return -1;
64 this->curr_->next_ = tmp;
65 this->curr_ = this->curr_->next_;
67 else
69 // We can reuse previously allocated memory.
70 this->curr_ = this->curr_->next_;
71 this->curr_->block_ = this->curr_->cur_ = this->curr_->contents_;
74 // Copy any initial characters to the new chunk.
75 if (temp->cur_ != temp->block_)
77 size_t datasize = temp->cur_ - temp->block_;
78 ACE_OS::memcpy (this->curr_->block_,
79 temp->block_,
80 datasize);
81 this->curr_->cur_ = this->curr_->block_ + datasize;
82 // Reset the old chunk.
83 temp->cur_ = temp->block_;
87 return 0;
90 template <class ACE_CHAR_T> ACE_CHAR_T *
91 ACE_Obstack_T<ACE_CHAR_T>::grow (ACE_CHAR_T c)
93 ACE_TRACE ("ACE_Obstack_T<ACE_CHAR_T>::grow");
95 if (this->request (1) == 0)
97 ACE_CHAR_T *retv = reinterpret_cast<ACE_CHAR_T *> (this->curr_->cur_);
98 this->curr_->cur_ += sizeof (ACE_CHAR_T);
99 *retv = c;
100 return retv;
102 else
103 return 0;
106 template <class ACE_CHAR_T> ACE_Obchunk *
107 ACE_Obstack_T<ACE_CHAR_T>::new_chunk (void)
109 ACE_TRACE ("ACE_Obstack_T<ACE_CHAR_T>::new_chunk");
111 ACE_Obchunk *temp = 0;
113 ACE_NEW_MALLOC_RETURN (temp,
114 static_cast<ACE_Obchunk *> (this->allocator_strategy_->malloc
115 (sizeof (class ACE_Obchunk) + this->size_)),
116 ACE_Obchunk (this->size_),
118 return temp;
121 template <class ACE_CHAR_T>
122 ACE_Obstack_T<ACE_CHAR_T>::ACE_Obstack_T (size_t size,
123 ACE_Allocator *allocator_strategy)
124 : allocator_strategy_ (allocator_strategy),
125 size_ (size),
126 head_ (0),
127 curr_ (0)
129 ACE_TRACE ("ACE_Obstack_T<ACE_CHAR_T>::ACE_Obstack");
131 if (this->allocator_strategy_ == 0)
132 ACE_ALLOCATOR (this->allocator_strategy_,
133 ACE_Allocator::instance ());
135 this->head_ = this->new_chunk ();
136 this->curr_ = this->head_;
139 template <class ACE_CHAR_T>
140 ACE_Obstack_T<ACE_CHAR_T>::~ACE_Obstack_T (void)
142 ACE_TRACE ("ACE_Obstack_T<ACE_CHAR_T>::~ACE_Obstack_T");
144 ACE_Obchunk *temp = this->head_;
146 while (temp != 0)
148 ACE_Obchunk *next = temp->next_;
149 temp->next_ = 0;
150 this->allocator_strategy_->free (temp);
151 temp = next;
155 template <class ACE_CHAR_T> ACE_CHAR_T *
156 ACE_Obstack_T<ACE_CHAR_T>::copy (const ACE_CHAR_T *s,
157 size_t len)
159 ACE_TRACE ("ACE_Obstack_T<ACE_CHAR_T>::copy");
161 if (this->request (len) != 0)
162 return 0;
164 size_t tsize = len * sizeof (ACE_CHAR_T);
165 ACE_OS::memcpy (this->curr_->cur_, s, tsize);
166 this->curr_->cur_ += tsize ;
167 return this->freeze ();
170 template <class ACE_CHAR_T> void
171 ACE_Obstack_T<ACE_CHAR_T>::unwind (void* obj)
173 if (obj >= this->curr_->contents_ && obj < this->curr_->end_)
174 this->curr_->block_ = this->curr_->cur_ = reinterpret_cast<char*> (obj);
175 else
176 this->unwind_i (obj);
179 template <class ACE_CHAR_T> void
180 ACE_Obstack_T<ACE_CHAR_T>::unwind_i (void* obj)
182 ACE_Obchunk* curr = this->head_;
183 while (curr != 0 && (curr->contents_ > obj || curr->end_ < obj))
184 curr = curr->next_;
185 if (curr)
187 this->curr_ = curr;
188 this->curr_->block_ = this->curr_->cur_ = reinterpret_cast<char*> (obj);
190 else if (obj != 0)
191 ACELIB_ERROR ((LM_ERROR,
192 ACE_TEXT ("Deletion of non-existent object.\n%a")));
195 template <class ACE_CHAR_T> void
196 ACE_Obstack_T<ACE_CHAR_T>::release (void)
198 ACE_TRACE ("ACE_Obstack_T<ACE_CHAR_T>::release");
200 this->curr_ = this->head_;
201 this->curr_->block_ = this->curr_->cur_ = this->curr_->contents_;
204 template <class ACE_CHAR_T> void
205 ACE_Obstack_T<ACE_CHAR_T>::grow_fast (ACE_CHAR_T c)
207 * (reinterpret_cast<ACE_CHAR_T *> (this->curr_->cur_)) = c;
208 this->curr_->cur_ += sizeof (ACE_CHAR_T);
211 template <class ACE_CHAR_T> ACE_CHAR_T *
212 ACE_Obstack_T<ACE_CHAR_T>::freeze (void)
214 ACE_CHAR_T *retv = reinterpret_cast<ACE_CHAR_T *> (this->curr_->block_);
215 * (reinterpret_cast<ACE_CHAR_T *> (this->curr_->cur_)) = 0;
217 this->curr_->cur_ += sizeof (ACE_CHAR_T);
218 this->curr_->block_ = this->curr_->cur_;
219 return retv;
222 ACE_END_VERSIONED_NAMESPACE_DECL
224 #endif /* ACE_OBSTACK_T_CPP */