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"
25 #include "ace/checked_iterator.h"
27 TAO_BEGIN_VERSIONED_NAMESPACE_DECL
32 class TAO_Export unbounded_value_sequence
<CORBA::Octet
>
35 typedef CORBA::Octet value_type
;
36 typedef CORBA::Octet element_type
;
37 typedef CORBA::Octet
const const_value_type
;
38 typedef value_type
& subscript_type
;
39 typedef value_type
const & const_subscript_type
;
40 typedef ::CORBA::ULong size_type
;
42 typedef details::unbounded_value_allocation_traits
<value_type
,true> allocation_traits
;
43 typedef details::value_traits
<value_type
,true> element_traits
;
44 typedef details::generic_sequence
<value_type
, allocation_traits
, element_traits
> implementation_type
;
45 typedef details::range_checking
<value_type
,true> range
;
47 inline unbounded_value_sequence()
48 : maximum_ (allocation_traits::default_maximum())
50 , buffer_ (allocation_traits::default_buffer_allocation())
51 , release_ (buffer_
!= 0)
54 inline explicit unbounded_value_sequence(CORBA::ULong maximum
)
57 , buffer_(allocbuf(maximum_
))
61 inline unbounded_value_sequence(
65 CORBA::Boolean release
= false)
72 inline ~unbounded_value_sequence() {
74 ACE_Message_Block::release (mb_
);
78 /// Create a sequence of octets from a single message block (i.e. it
79 /// ignores any chaining in the message block).
80 inline unbounded_value_sequence (CORBA::ULong length
,
81 const ACE_Message_Block
* mb
)
84 , buffer_ (reinterpret_cast <CORBA::Octet
*>(mb
->rd_ptr ()))
87 // Get the message block flags.
88 ACE_Message_Block::Message_Flags
const flg
= mb
->self_flags ();
90 // If the DONT_DELETE flag is disabled just a duplicate would
91 // help. If the DONT_DELETE flag is enabled a deep copy is needed as
92 // the contents would be on stack. Just incrementing the ref count
93 // on the stack based data block would only crash the program when
95 if (ACE_BIT_DISABLED (flg
,
96 ACE_Message_Block::DONT_DELETE
))
98 this->mb_
= ACE_Message_Block::duplicate (mb
);
102 // As we are in CORBA mode, all the data blocks would be aligned
103 // on an 8 byte boundary
104 ACE_Message_Block
msgb (*mb
, ACE_CDR::MAX_ALIGNMENT
);
106 // Get the base pointer of the incoming message block
107 char *const start
= ACE_ptr_align_binary (mb
->base (),
108 ACE_CDR::MAX_ALIGNMENT
);
110 // Get the read and write displacements in the incoming stream
111 size_t const rd_pos
= mb
->rd_ptr () - start
;
112 size_t const wr_pos
= mb
->wr_ptr () - start
;
114 this->mb_
= ACE_Message_Block::duplicate (&msgb
);
116 this->mb_
->rd_ptr (rd_pos
);
117 this->mb_
->wr_ptr (wr_pos
);
120 inline CORBA::ULong
maximum() const {
123 inline CORBA::Boolean
release() const {
126 inline CORBA::ULong
length() const {
129 inline void length(CORBA::ULong length
) {
130 if (length
<= maximum_
)
138 unbounded_value_sequence
tmp(length
);
139 tmp
.length_
= length
;
140 element_traits::copy_range(
143 ACE_make_checked_array_iterator (tmp
.buffer_
, tmp
.length_
));
149 unbounded_value_sequence
tmp(length
);
150 tmp
.length_
= length
;
151 element_traits::copy_range(
154 ACE_make_checked_array_iterator (tmp
.buffer_
, tmp
.length_
));
157 inline value_type
const & operator[](CORBA::ULong i
) const {
158 range::check(i
, length_
, maximum_
, "operator[]() const");
161 inline value_type
& operator[](CORBA::ULong i
) {
162 range::check(i
, length_
, maximum_
, "operator[]() non-const");
166 CORBA::ULong maximum
,
169 CORBA::Boolean release
= false) {
170 unbounded_value_sequence
tmp(maximum
, length
, data
, release
);
173 inline value_type
const * get_buffer() const {
176 buffer_
= allocbuf(maximum_
);
181 inline value_type
* get_buffer(CORBA::Boolean orphan
= false) {
182 if (orphan
&& !release_
)
188 buffer_
= allocbuf(maximum_
);
199 unbounded_value_sequence tmp
;
201 tmp
.release_
= false;
206 // moved inside the class to resolve namespace lookup issues.
207 // This is a replacement for the commented block below.
208 inline bool operator== (const unbounded_value_sequence
& rhs
) const {
209 unbounded_value_sequence
const & lhs
= *this;
210 CORBA::ULong
const len
= lhs
.length();
212 // We use the subscript operator instead of get_buffer() to avoid a
213 // potential buffer allocation.
218 : ACE_OS::memcmp(&lhs
[0], &rhs
[0], len
) == 0));
221 inline bool operator!= (const unbounded_value_sequence
& rhs
) const
223 return !this->operator==(rhs
);
226 inline void swap(unbounded_value_sequence
& rhs
) noexcept
{
227 std::swap (mb_
, rhs
.mb_
);
228 std::swap (maximum_
, rhs
.maximum_
);
229 std::swap (length_
, rhs
.length_
);
230 std::swap (buffer_
, rhs
.buffer_
);
231 std::swap (release_
, rhs
.release_
);
233 static value_type
* allocbuf(CORBA::ULong maximum
) {
234 return allocation_traits::allocbuf(maximum
);
236 static void freebuf(value_type
* buffer
) {
237 allocation_traits::freebuf(buffer
);
240 /// Returns the underlying message block, the caller must *not*
241 /// release the copy.
242 inline ACE_Message_Block
* mb () const {
246 /// Replaces the current buffer with @a mb, using only @a length bytes.
247 /// It takes a duplicate of <mb> so the user still owns it.
248 inline void replace (CORBA::ULong length
, const ACE_Message_Block
* mb
) {
249 unbounded_value_sequence
s (length
, mb
);
253 unbounded_value_sequence (
254 const unbounded_value_sequence
&rhs
)
261 if (rhs
.maximum_
== 0 || rhs
.buffer_
== 0)
263 maximum_
= rhs
.maximum_
;
264 length_
= rhs
.length_
;
267 unbounded_value_sequence
tmp(rhs
.maximum_
);
268 tmp
.length_
= rhs
.length_
;
271 ACE_OS::memcpy (tmp
.buffer_
,
278 for (const ACE_Message_Block
*i
= rhs
.mb_
; i
!= 0; i
= i
->cont ())
280 ACE_OS::memcpy (tmp
.buffer_
+ offset
,
284 offset
+= i
->length ();
290 unbounded_value_sequence
&
291 operator= (const unbounded_value_sequence
& rhs
)
293 unbounded_value_sequence
tmp(rhs
);
299 /// The maximum number of elements the buffer can contain.
300 CORBA::ULong maximum_
;
302 /// The current number of elements in the buffer.
303 CORBA::ULong length_
;
305 /// The buffer with all the elements, casting must be done in derived
307 mutable value_type
* buffer_
;
309 /// If true then the sequence should release the buffer when it is
311 mutable CORBA::Boolean release_
;
312 ACE_Message_Block
* mb_
;
316 TAO_END_VERSIONED_NAMESPACE_DECL
318 #endif /* TAO_NO_COPY_OCTET_SEQUENCES == 1 */
320 #if (TAO_NO_COPY_OCTET_SEQUENCES == 0)
322 // This doesn't work always for unexplained reason. At least
323 // PortableServer::Active_Object_Map.cpp fails to compile with some compilers.
324 // But I'm keeping this in for the moment so that it may be
325 // resurrected if need be
328 operator== (const TAO_VERSIONED_NAMESPACE_NAME::TAO::unbounded_value_sequence
<CORBA::Octet
> & lhs
,
329 const TAO_VERSIONED_NAMESPACE_NAME::TAO::unbounded_value_sequence
<CORBA::Octet
> & rhs
)
331 ::CORBA::ULong
const rlen
= rhs
.length ();
333 if (rlen
!= lhs
.length ())
338 const CORBA::Octet
* rhs_buff
= rhs
.get_buffer ();
339 const CORBA::Octet
* lhs_buff
= lhs
.get_buffer ();
340 const bool result
= (ACE_OS::memcmp (lhs_buff
, rhs_buff
, rlen
) == 0);
347 operator!= (const TAO_VERSIONED_NAMESPACE_NAME::TAO::unbounded_value_sequence
<CORBA::Octet
> & lhs
,
348 const TAO_VERSIONED_NAMESPACE_NAME::TAO::unbounded_value_sequence
<CORBA::Octet
> & rhs
)
350 return !(lhs
== rhs
);
352 #endif /* TAO_NO_COPY_OCTET_SEQUENCES==0 */
354 #endif // guard_unbounded_octet_sequence_hpp