Unbounded_Octet_Sequence_T.h

Go to the documentation of this file.
00001 #ifndef guard_unbounded_octet_sequence_hpp
00002 #define guard_unbounded_octet_sequence_hpp
00003 /**
00004  * @file
00005  *
00006  * @brief Implement octet sequences
00007  *
00008  * Unbounded_Octet_Sequence_T.h,v 1.9 2006/05/25 03:37:25 mesnier_p Exp
00009  *
00010  * @author Johnny Willemsen
00011  */
00012 #include "tao/orbconf.h"
00013 
00014 #include "tao/Unbounded_Value_Sequence_T.h"
00015 
00016 #if (TAO_NO_COPY_OCTET_SEQUENCES == 1)
00017 
00018 #include "tao/Unbounded_Value_Allocation_Traits_T.h"
00019 #include "tao/Value_Traits_T.h"
00020 #include "tao/Range_Checking_T.h"
00021 
00022 #include "tao/Basic_Types.h"
00023 #include "ace/Message_Block.h"
00024 #include "ace/OS_Memory.h"
00025 #include "ace/OS_NS_string.h"
00026 
00027 TAO_BEGIN_VERSIONED_NAMESPACE_DECL
00028 
00029 namespace TAO
00030 {
00031 template<>
00032 class unbounded_value_sequence<CORBA::Octet>
00033 {
00034 public:
00035   typedef CORBA::Octet value_type;
00036   typedef CORBA::Octet element_type;
00037   typedef CORBA::Octet const const_value_type;
00038   typedef value_type & subscript_type;
00039   typedef value_type const & const_subscript_type;
00040 
00041   typedef details::unbounded_value_allocation_traits<value_type,true> allocation_traits;
00042   typedef details::value_traits<value_type,true> element_traits;
00043   typedef details::generic_sequence<value_type, allocation_traits, element_traits> implementation_type;
00044   typedef details::range_checking<value_type,true> range;
00045 
00046   inline unbounded_value_sequence<CORBA::Octet>()
00047     : maximum_ (allocation_traits::default_maximum())
00048     , length_ (0)
00049     , buffer_ (allocation_traits::default_buffer_allocation())
00050     , release_ (true)
00051     , mb_ (0)
00052   {}
00053   inline explicit unbounded_value_sequence<CORBA::Octet>(CORBA::ULong maximum)
00054     : maximum_(maximum)
00055     , length_(0)
00056     , buffer_(allocbuf(maximum_))
00057     , release_(true)
00058     , mb_ (0)
00059   {}
00060   inline unbounded_value_sequence<CORBA::Octet>(
00061       CORBA::ULong maximum,
00062       CORBA::ULong length,
00063       value_type * data,
00064       CORBA::Boolean release = false)
00065     : maximum_ (maximum),
00066       length_ (length),
00067       buffer_ (data),
00068       release_ (release),
00069       mb_ (0)
00070   {}
00071   inline ~unbounded_value_sequence<CORBA::Octet>() {
00072     if (mb_)
00073       ACE_Message_Block::release (mb_);
00074     if (release_)
00075       freebuf(buffer_);
00076   }
00077   /// Create a sequence of octets from a single message block (i.e. it
00078   /// ignores any chaining in the meesage block).
00079   inline unbounded_value_sequence<CORBA::Octet> (CORBA::ULong length,
00080                                                  const ACE_Message_Block* mb)
00081     : maximum_ (length)
00082     , length_ (length)
00083     , buffer_ (reinterpret_cast <CORBA::Octet *>(mb->rd_ptr ()))
00084     , release_ (false)
00085     , mb_(0) {
00086     // Get the message block flags.
00087     ACE_Message_Block::Message_Flags const flg = mb->self_flags ();
00088 
00089     // If the DONT_DELETE flag is disabled just a duplicate would
00090     // help. If the DONT_DELETE flag is enabled a deep copy is needed as
00091     // the contents would be on stack. Just incrementing the ref count
00092     // on the stack based data block would only crash the program when
00093     // the stack unwinds
00094     if (ACE_BIT_DISABLED (flg,
00095                           ACE_Message_Block::DONT_DELETE))
00096       {
00097         this->mb_ = ACE_Message_Block::duplicate (mb);
00098       }
00099     else
00100       {
00101         // As we are in CORBA mode, all the data blocks would be aligned
00102         // on an 8 byte boundary
00103         ACE_Message_Block msgb (*mb,
00104                                 ACE_CDR::MAX_ALIGNMENT);
00105 
00106         // Get the base pointer of the incoming message block
00107         char *start = ACE_ptr_align_binary (mb->base (),
00108                                             ACE_CDR::MAX_ALIGNMENT);
00109 
00110         // Get the read and write displacements in the incoming stream
00111         size_t const rd_pos = mb->rd_ptr () - start;
00112         size_t const wr_pos = mb->wr_ptr () - start;
00113 
00114         this->mb_ = ACE_Message_Block::duplicate (&msgb);
00115 
00116         this->mb_->rd_ptr (rd_pos);
00117         this->mb_->wr_ptr (wr_pos);
00118       }
00119   }
00120   inline CORBA::ULong maximum() const {
00121     return maximum_;
00122   }
00123   inline CORBA::Boolean release() const {
00124     return release_;
00125   }
00126   inline CORBA::ULong length() const {
00127     return length_;
00128   }
00129   inline void length(CORBA::ULong length) {
00130     if (length <= maximum_ || length <= length_)
00131       {
00132         if (this->mb_ == 0)
00133           {
00134             if (length_ < length)
00135             {
00136               // TODO This code does not provide the strong-exception
00137               //      guarantee, but it does provide the weak-exception
00138               //      guarantee.  The problem would appear when
00139               //      initialize_range() raises an exception after several
00140               //      elements have been modified.  One could argue that
00141               //      this problem is irrelevant, as the elements already
00142               //      modified are unreachable to conforming applications.
00143               element_traits::initialize_range(
00144                   buffer_ + length_, buffer_ + length);
00145             }
00146             length_ = length;
00147           }
00148         else
00149           {
00150             unbounded_value_sequence<CORBA::Octet> tmp(length);
00151             tmp.length_ = length;
00152             element_traits::copy_range(
00153               buffer_, buffer_ + length, tmp.buffer_);
00154             swap(tmp);
00155           }
00156         return;
00157       }
00158 
00159     unbounded_value_sequence<CORBA::Octet> tmp(length);
00160     tmp.length_ = length;
00161     element_traits::copy_range(
00162         buffer_, buffer_ + length_, tmp.buffer_);
00163     element_traits::initialize_range(
00164         tmp.buffer_ + length_, tmp.buffer_ + length);
00165     swap(tmp);
00166   }
00167   inline value_type const & operator[](CORBA::ULong i) const {
00168     range::check(i, length_, maximum_, "operator[]() const");
00169     return buffer_[i];
00170   }
00171   inline value_type & operator[](CORBA::ULong i) {
00172     range::check(i, length_, maximum_, "operator[]() non-const");
00173     return buffer_[i];
00174   }
00175   inline void replace(
00176       CORBA::ULong maximum,
00177       CORBA::ULong length,
00178       value_type * data,
00179       CORBA::Boolean release = false) {
00180     unbounded_value_sequence<CORBA::Octet> tmp(maximum, length, data, release);
00181     swap(tmp);
00182   }
00183   inline value_type const * get_buffer() const {
00184     if (buffer_ == 0)
00185       {
00186         buffer_ = allocbuf(maximum_);
00187       }
00188     return buffer_;
00189   }
00190   inline value_type * get_buffer(CORBA::Boolean orphan = false) {
00191     if (orphan && !release_)
00192     {
00193       return 0;
00194     }
00195     if (buffer_ == 0)
00196     {
00197       buffer_ = allocbuf(maximum_);
00198     }
00199     if (!orphan)
00200     {
00201       return buffer_;
00202     }
00203 
00204     unbounded_value_sequence<CORBA::Octet> tmp;
00205     swap(tmp);
00206     tmp.release_ = false;
00207 
00208     return tmp.buffer_;
00209   }
00210 
00211   // moved inside the class to resolve namespace lookup issues.
00212   // This is a replacement for the commented block below.
00213 
00214   inline bool operator== (const unbounded_value_sequence<CORBA::Octet> & rhs) const
00215 {
00216   ::CORBA::ULong const rlen = rhs.length ();
00217 
00218   if (rlen != this->length ())
00219     {
00220       return false;
00221     }
00222 
00223   for (::CORBA::ULong i = 0; i < rlen; ++i)
00224     {
00225       if (rhs[i] != this->buffer_[i])
00226         {
00227           return false;
00228         }
00229     }
00230 
00231   return true;
00232 }
00233 
00234   inline bool operator!= (const unbounded_value_sequence<CORBA::Octet> & rhs) const
00235 {
00236   return !this->operator==(rhs);
00237 }
00238 
00239   inline void swap(unbounded_value_sequence & rhs) throw() {
00240     std::swap (mb_, rhs.mb_);
00241     std::swap (maximum_, rhs.maximum_);
00242     std::swap (length_, rhs.length_);
00243     std::swap (buffer_, rhs.buffer_);
00244     std::swap (release_, rhs.release_);
00245   }
00246   static value_type * allocbuf(CORBA::ULong maximum) {
00247     return allocation_traits::allocbuf(maximum);
00248   }
00249   static void freebuf(value_type * buffer) {
00250     allocation_traits::freebuf(buffer);
00251   }
00252 
00253   /// Returns the underlying message block, the caller must *not*
00254   /// release the copy.
00255   inline ACE_Message_Block* mb (void) const {
00256     return mb_;
00257   }
00258 
00259   /// Replaces the current buffer with <mb>, using only <length> bytes.
00260   /// It takes a duplicate of <mb> so the user still owns it.
00261   inline void replace (CORBA::ULong length, const ACE_Message_Block* mb) {
00262     unbounded_value_sequence<CORBA::Octet> s (length, mb);
00263     swap (s);
00264   }
00265 
00266   unbounded_value_sequence<CORBA::Octet> (
00267     const unbounded_value_sequence<CORBA::Octet> &rhs)
00268     : maximum_ (0)
00269     , length_ (0)
00270     , buffer_(0)
00271     , release_(false)
00272     , mb_ (0)
00273   {
00274     unbounded_value_sequence<CORBA::Octet> tmp(rhs.maximum_);
00275     tmp.length_ = rhs.length_;
00276     if (rhs.mb_ == 0)
00277       {
00278         ACE_OS::memcpy (tmp.buffer_,
00279                         rhs.buffer_,
00280                         rhs.length_);
00281       }
00282     else
00283       {
00284         size_t offset = 0;
00285         for (const ACE_Message_Block *i = rhs.mb_; i != 0; i = i->cont ())
00286           {
00287             ACE_OS::memcpy (tmp.buffer_ + offset,
00288                             i->rd_ptr (),
00289                             i->length ());
00290 
00291             offset += i->length ();
00292           }
00293       }
00294     swap(tmp);
00295   }
00296 
00297   unbounded_value_sequence<CORBA::Octet> &
00298   operator= (const unbounded_value_sequence<CORBA::Octet> & rhs)
00299   {
00300     unbounded_value_sequence<CORBA::Octet> tmp(rhs);
00301     swap(tmp);
00302     return * this;
00303   }
00304 
00305 private:
00306   /// The maximum number of elements the buffer can contain.
00307   CORBA::ULong maximum_;
00308 
00309   /// The current number of elements in the buffer.
00310   CORBA::ULong length_;
00311 
00312   /// The buffer with all the elements, casting must be done in derived
00313   /// classes.
00314   mutable value_type * buffer_;
00315 
00316   /// If true then the sequence should release the buffer when it is
00317   /// destroyed.
00318   CORBA::Boolean release_;
00319   ACE_Message_Block* mb_;
00320 };
00321 
00322 } // namespace TAO
00323 
00324 TAO_END_VERSIONED_NAMESPACE_DECL
00325 
00326 #endif /* TAO_NO_COPY_OCTET_SEQUENCES == 1 */
00327 
00328 #if 0
00329 // This doesn't work for an unexplained reason. At least
00330 // PortableServer::Active_Object_Map.cpp fails to compile.
00331 // But I'm keeping this in for the moment so that it may be
00332 // resurrected if need be
00333 inline
00334 bool
00335 operator== (const TAO_VERSIONED_NAMESPACE_NAME::TAO::unbounded_value_sequence<CORBA::Octet> & lhs,
00336             const TAO_VERSIONED_NAMESPACE_NAME::TAO::unbounded_value_sequence<CORBA::Octet> & rhs)
00337 {
00338   ::CORBA::ULong const rlen = rhs.length ();
00339 
00340   if (rlen != lhs.length ())
00341     {
00342       return false;
00343     }
00344 
00345   for (::CORBA::ULong i = 0; i < rlen; ++i)
00346     {
00347       if (rhs[i] != lhs[i])
00348         {
00349           return false;
00350         }
00351     }
00352 
00353   return true;
00354 }
00355 
00356 inline
00357 bool
00358 operator!= (const TAO_VERSIONED_NAMESPACE_NAME::TAO::unbounded_value_sequence<CORBA::Octet> & lhs,
00359             const TAO_VERSIONED_NAMESPACE_NAME::TAO::unbounded_value_sequence<CORBA::Octet> & rhs)
00360 {
00361   return !(lhs == rhs);
00362 }
00363 #endif /* 0 */
00364 
00365 #endif // guard_unbounded_octet_sequence_hpp

Generated on Thu Nov 9 11:54:28 2006 for TAO by doxygen 1.3.6