1 #ifndef guard_unbounded_octet_sequence_hpp
2 #define guard_unbounded_octet_sequence_hpp
6 * @brief Implement octet sequences
8 * @author Johnny Willemsen
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
31 class TAO_Export unbounded_value_sequence
<CORBA::Octet
>
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())
49 , buffer_ (allocation_traits::default_buffer_allocation())
50 , release_ (buffer_
!= 0)
53 inline explicit unbounded_value_sequence(CORBA::ULong maximum
)
56 , buffer_(allocbuf(maximum_
))
60 inline unbounded_value_sequence(
64 CORBA::Boolean release
= false)
71 inline ~unbounded_value_sequence() {
73 ACE_Message_Block::release (mb_
);
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
)
83 , buffer_ (reinterpret_cast <CORBA::Octet
*>(mb
->rd_ptr ()))
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
94 if (ACE_BIT_DISABLED (flg
,
95 ACE_Message_Block::DONT_DELETE
))
97 this->mb_
= ACE_Message_Block::duplicate (mb
);
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 {
122 inline CORBA::Boolean
release() const {
125 inline CORBA::ULong
length() const {
128 inline void length(CORBA::ULong length
) {
129 if (length
<= maximum_
)
137 unbounded_value_sequence
tmp(length
);
138 tmp
.length_
= length
;
139 element_traits::copy_range(
148 unbounded_value_sequence
tmp(length
);
149 tmp
.length_
= length
;
150 element_traits::copy_range(
156 inline value_type
const & operator[](CORBA::ULong i
) const {
157 range::check(i
, length_
, maximum_
, "operator[]() const");
160 inline value_type
& operator[](CORBA::ULong i
) {
161 range::check(i
, length_
, maximum_
, "operator[]() non-const");
165 CORBA::ULong maximum
,
168 CORBA::Boolean release
= false) {
169 unbounded_value_sequence
tmp(maximum
, length
, data
, release
);
172 inline value_type
const * get_buffer() const {
175 buffer_
= allocbuf(maximum_
);
180 inline value_type
* get_buffer(CORBA::Boolean orphan
= false) {
181 if (orphan
&& !release_
)
187 buffer_
= allocbuf(maximum_
);
198 unbounded_value_sequence tmp
;
200 tmp
.release_
= false;
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.
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 {
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
);
252 unbounded_value_sequence (
253 const unbounded_value_sequence
&rhs
)
260 if (rhs
.maximum_
== 0 || rhs
.buffer_
== 0)
262 maximum_
= rhs
.maximum_
;
263 length_
= rhs
.length_
;
266 unbounded_value_sequence
tmp(rhs
.maximum_
);
267 tmp
.length_
= rhs
.length_
;
270 ACE_OS::memcpy (tmp
.buffer_
,
277 for (const ACE_Message_Block
*i
= rhs
.mb_
; i
!= 0; i
= i
->cont ())
279 ACE_OS::memcpy (tmp
.buffer_
+ offset
,
283 offset
+= i
->length ();
289 unbounded_value_sequence
&
290 operator= (const unbounded_value_sequence
& rhs
)
292 unbounded_value_sequence
tmp(rhs
);
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
306 mutable value_type
* buffer_
;
308 /// If true then the sequence should release the buffer when it is
310 mutable CORBA::Boolean release_
;
311 ACE_Message_Block
* mb_
;
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
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 ())
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);
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