=default for generated implementation copy ctor
[ACE_TAO.git] / TAO / tao / Unbounded_Octet_Sequence_T.h
blob8cfed478e2ccffbd89ce52b1c7c7e80ef251dd9f
1 #ifndef guard_unbounded_octet_sequence_hpp
2 #define guard_unbounded_octet_sequence_hpp
3 /**
4 * @file
6 * @brief Implement octet sequences
8 * @author Johnny Willemsen
9 */
10 #include "tao/orbconf.h"
12 #include "tao/Unbounded_Value_Sequence_T.h"
13 #include "ace/OS_NS_string.h"
15 #if (TAO_NO_COPY_OCTET_SEQUENCES == 1)
17 #include /**/ "tao/TAO_Export.h"
18 #include "tao/Unbounded_Value_Allocation_Traits_T.h"
19 #include "tao/Value_Traits_T.h"
20 #include "tao/Range_Checking_T.h"
22 #include "tao/Basic_Types.h"
23 #include "ace/Message_Block.h"
24 #include "ace/OS_Memory.h"
26 TAO_BEGIN_VERSIONED_NAMESPACE_DECL
28 namespace TAO
30 template<>
31 class TAO_Export unbounded_value_sequence<CORBA::Octet>
33 public:
34 typedef CORBA::Octet value_type;
35 typedef CORBA::Octet element_type;
36 typedef CORBA::Octet const const_value_type;
37 typedef value_type & subscript_type;
38 typedef value_type const & const_subscript_type;
39 typedef ::CORBA::ULong size_type;
41 typedef details::unbounded_value_allocation_traits<value_type,true> allocation_traits;
42 typedef details::value_traits<value_type,true> element_traits;
43 typedef details::generic_sequence<value_type, allocation_traits, element_traits> implementation_type;
44 typedef details::range_checking<value_type,true> range;
46 inline unbounded_value_sequence()
47 : maximum_ (allocation_traits::default_maximum())
48 , length_ (0)
49 , buffer_ (allocation_traits::default_buffer_allocation())
50 , release_ (buffer_ != 0)
51 , mb_ (0)
53 inline explicit unbounded_value_sequence(CORBA::ULong maximum)
54 : maximum_(maximum)
55 , length_(0)
56 , buffer_(allocbuf(maximum_))
57 , release_(true)
58 , mb_ (0)
60 inline unbounded_value_sequence(
61 CORBA::ULong maximum,
62 CORBA::ULong length,
63 value_type * data,
64 CORBA::Boolean release = false)
65 : maximum_ (maximum),
66 length_ (length),
67 buffer_ (data),
68 release_ (release),
69 mb_ (0)
71 inline ~unbounded_value_sequence() {
72 if (mb_)
73 ACE_Message_Block::release (mb_);
74 if (release_)
75 freebuf(buffer_);
77 /// Create a sequence of octets from a single message block (i.e. it
78 /// ignores any chaining in the message block).
79 inline unbounded_value_sequence (CORBA::ULong length,
80 const ACE_Message_Block* mb)
81 : maximum_ (length)
82 , length_ (length)
83 , buffer_ (reinterpret_cast <CORBA::Octet *>(mb->rd_ptr ()))
84 , release_ (false)
85 , mb_(0) {
86 // Get the message block flags.
87 ACE_Message_Block::Message_Flags const flg = mb->self_flags ();
89 // If the DONT_DELETE flag is disabled just a duplicate would
90 // help. If the DONT_DELETE flag is enabled a deep copy is needed as
91 // the contents would be on stack. Just incrementing the ref count
92 // on the stack based data block would only crash the program when
93 // the stack unwinds
94 if (ACE_BIT_DISABLED (flg,
95 ACE_Message_Block::DONT_DELETE))
97 this->mb_ = ACE_Message_Block::duplicate (mb);
99 else
101 // As we are in CORBA mode, all the data blocks would be aligned
102 // on an 8 byte boundary
103 ACE_Message_Block msgb (*mb, ACE_CDR::MAX_ALIGNMENT);
105 // Get the base pointer of the incoming message block
106 char *const start = ACE_ptr_align_binary (mb->base (),
107 ACE_CDR::MAX_ALIGNMENT);
109 // Get the read and write displacements in the incoming stream
110 size_t const rd_pos = mb->rd_ptr () - start;
111 size_t const wr_pos = mb->wr_ptr () - start;
113 this->mb_ = ACE_Message_Block::duplicate (&msgb);
115 this->mb_->rd_ptr (rd_pos);
116 this->mb_->wr_ptr (wr_pos);
119 inline CORBA::ULong maximum() const {
120 return maximum_;
122 inline CORBA::Boolean release() const {
123 return release_;
125 inline CORBA::ULong length() const {
126 return length_;
128 inline void length(CORBA::ULong length) {
129 if (length <= maximum_)
131 if (this->mb_ == 0)
133 length_ = length;
135 else
137 unbounded_value_sequence tmp(length);
138 tmp.length_ = length;
139 element_traits::copy_range(
140 buffer_,
141 buffer_ + length,
142 tmp.buffer_);
143 swap(tmp);
145 return;
148 unbounded_value_sequence tmp(length);
149 tmp.length_ = length;
150 element_traits::copy_range(
151 buffer_,
152 buffer_ + length_,
153 tmp.buffer_);
154 swap(tmp);
156 inline value_type const & operator[](CORBA::ULong i) const {
157 range::check(i, length_, maximum_, "operator[]() const");
158 return buffer_[i];
160 inline value_type & operator[](CORBA::ULong i) {
161 range::check(i, length_, maximum_, "operator[]() non-const");
162 return buffer_[i];
164 inline void replace(
165 CORBA::ULong maximum,
166 CORBA::ULong length,
167 value_type * data,
168 CORBA::Boolean release = false) {
169 unbounded_value_sequence tmp(maximum, length, data, release);
170 swap(tmp);
172 inline value_type const * get_buffer() const {
173 if (buffer_ == 0)
175 buffer_ = allocbuf(maximum_);
176 release_ = true;
178 return buffer_;
180 inline value_type * get_buffer(CORBA::Boolean orphan = false) {
181 if (orphan && !release_)
183 return 0;
185 if (buffer_ == 0)
187 buffer_ = allocbuf(maximum_);
188 if (!orphan)
190 release_ = true;
193 if (!orphan)
195 return buffer_;
198 unbounded_value_sequence tmp;
199 swap(tmp);
200 tmp.release_ = false;
202 return tmp.buffer_;
205 // moved inside the class to resolve namespace lookup issues.
206 // This is a replacement for the commented block below.
207 inline bool operator== (const unbounded_value_sequence & rhs) const {
208 unbounded_value_sequence const & lhs = *this;
209 CORBA::ULong const len = lhs.length();
211 // We use the subscript operator instead of get_buffer() to avoid a
212 // potential buffer allocation.
213 return
214 (len == rhs.length()
215 && (len == 0
216 ? true
217 : ACE_OS::memcmp(&lhs[0], &rhs[0], len) == 0));
220 inline bool operator!= (const unbounded_value_sequence & rhs) const
222 return !this->operator==(rhs);
225 inline void swap(unbounded_value_sequence & rhs) noexcept {
226 std::swap (mb_, rhs.mb_);
227 std::swap (maximum_, rhs.maximum_);
228 std::swap (length_, rhs.length_);
229 std::swap (buffer_, rhs.buffer_);
230 std::swap (release_, rhs.release_);
232 static value_type * allocbuf(CORBA::ULong maximum) {
233 return allocation_traits::allocbuf(maximum);
235 static void freebuf(value_type * buffer) {
236 allocation_traits::freebuf(buffer);
239 /// Returns the underlying message block, the caller must *not*
240 /// release the copy.
241 inline ACE_Message_Block* mb () const {
242 return mb_;
245 /// Replaces the current buffer with @a mb, using only @a length bytes.
246 /// It takes a duplicate of <mb> so the user still owns it.
247 inline void replace (CORBA::ULong length, const ACE_Message_Block* mb) {
248 unbounded_value_sequence s (length, mb);
249 swap (s);
252 unbounded_value_sequence (
253 const unbounded_value_sequence &rhs)
254 : maximum_ (0)
255 , length_ (0)
256 , buffer_(0)
257 , release_(false)
258 , mb_ (0)
260 if (rhs.maximum_ == 0 || rhs.buffer_ == 0)
262 maximum_ = rhs.maximum_;
263 length_ = rhs.length_;
264 return;
266 unbounded_value_sequence tmp(rhs.maximum_);
267 tmp.length_ = rhs.length_;
268 if (rhs.mb_ == 0)
270 ACE_OS::memcpy (tmp.buffer_,
271 rhs.buffer_,
272 rhs.length_);
274 else
276 size_t offset = 0;
277 for (const ACE_Message_Block *i = rhs.mb_; i != 0; i = i->cont ())
279 ACE_OS::memcpy (tmp.buffer_ + offset,
280 i->rd_ptr (),
281 i->length ());
283 offset += i->length ();
286 swap(tmp);
289 unbounded_value_sequence &
290 operator= (const unbounded_value_sequence & rhs)
292 unbounded_value_sequence tmp(rhs);
293 swap(tmp);
294 return * this;
297 private:
298 /// The maximum number of elements the buffer can contain.
299 CORBA::ULong maximum_;
301 /// The current number of elements in the buffer.
302 CORBA::ULong length_;
304 /// The buffer with all the elements, casting must be done in derived
305 /// classes.
306 mutable value_type * buffer_;
308 /// If true then the sequence should release the buffer when it is
309 /// destroyed.
310 mutable CORBA::Boolean release_;
311 ACE_Message_Block* mb_;
313 } // namespace TAO
315 TAO_END_VERSIONED_NAMESPACE_DECL
317 #endif /* TAO_NO_COPY_OCTET_SEQUENCES == 1 */
319 #if (TAO_NO_COPY_OCTET_SEQUENCES == 0)
321 // This doesn't work always for unexplained reason. At least
322 // PortableServer::Active_Object_Map.cpp fails to compile with some compilers.
323 // But I'm keeping this in for the moment so that it may be
324 // resurrected if need be
325 inline
326 bool
327 operator== (const TAO_VERSIONED_NAMESPACE_NAME::TAO::unbounded_value_sequence<CORBA::Octet> & lhs,
328 const TAO_VERSIONED_NAMESPACE_NAME::TAO::unbounded_value_sequence<CORBA::Octet> & rhs)
330 ::CORBA::ULong const rlen = rhs.length ();
332 if (rlen != lhs.length ())
334 return false;
337 const CORBA::Octet * rhs_buff = rhs.get_buffer ();
338 const CORBA::Octet * lhs_buff = lhs.get_buffer ();
339 const bool result = (ACE_OS::memcmp (lhs_buff, rhs_buff, rlen) == 0);
341 return result;
344 inline
345 bool
346 operator!= (const TAO_VERSIONED_NAMESPACE_NAME::TAO::unbounded_value_sequence<CORBA::Octet> & lhs,
347 const TAO_VERSIONED_NAMESPACE_NAME::TAO::unbounded_value_sequence<CORBA::Octet> & rhs)
349 return !(lhs == rhs);
351 #endif /* TAO_NO_COPY_OCTET_SEQUENCES==0 */
353 #endif // guard_unbounded_octet_sequence_hpp