SafetyProfileSequence.h

Go to the documentation of this file.
00001 #ifndef dds_DCPS_SafetyProfileSequence_h
00002 #define dds_DCPS_SafetyProfileSequence_h
00003 
00004 #include "dds/DCPS/SafetyProfilePool.h"
00005 #include "dds/DCPS/PoolAllocationBase.h"
00006 #include "dds/DCPS/Definitions.h"
00007 #include "dds/DCPS/Serializer.h"
00008 
00009 #include <tao/Array_VarOut_T.h> // Array_Traits
00010 #include <tao/String_Manager_T.h>
00011 
00012 #include <algorithm>
00013 #include <memory>
00014 #include <utility>
00015 #include <cstddef>
00016 #include <cstring>
00017 
00018 namespace OpenDDS {
00019 namespace SafetyProfile {
00020 
00021   template <typename T>
00022   struct StringTraits { };
00023 
00024   template <>
00025   struct StringTraits<CORBA::Char>
00026   {
00027     static CORBA::Char* alloc(CORBA::ULong len) { return CORBA::string_alloc(len); }
00028     static CORBA::Char* empty() { return dup(""); }
00029     static CORBA::Char* dup(const CORBA::Char* s) { return CORBA::string_dup(s); }
00030     static void free(CORBA::Char* s) { if (s) CORBA::string_free(s); }
00031 
00032     static int cmp(const CORBA::Char* lhs, const CORBA::Char* rhs)
00033     {
00034       return std::strcmp(lhs, rhs);
00035     }
00036   };
00037 
00038   typedef CORBA::ULong seq_size_type;
00039   typedef CORBA::Boolean seq_flag_type;
00040 
00041   template <seq_size_type N>
00042   struct Bounded {
00043     static const seq_size_type Bounds = N;
00044   };
00045 
00046   struct Unbounded {
00047     static const seq_size_type Bounds = INT_MAX;
00048   };
00049 
00050   template <typename T, typename Sequence, typename Bounds>
00051   struct AllocPolicy;
00052 
00053   template <typename T, typename Sequence, seq_size_type N>
00054   struct AllocPolicy<T, Sequence, Bounded<N> > {
00055     static T* allocbuf();
00056     seq_size_type maximum() const { return N; }
00057     seq_size_type max_size() const { return N; }
00058     void replace(seq_size_type length, T* data, seq_flag_type release = false)
00059     {
00060       static_cast<Sequence&>(*this).replace_i(N, length, data, release);
00061     }
00062   protected:
00063     explicit AllocPolicy(seq_size_type = N) {}
00064     T* allocate(seq_size_type = N) const { return allocbuf(); }
00065     void swap(AllocPolicy&) throw() {}
00066   };
00067 
00068   template <typename T, typename Sequence>
00069   struct AllocPolicy<T, Sequence, Unbounded> {
00070     static T* allocbuf(seq_size_type n);
00071     seq_size_type maximum() const { return maximum_; }
00072     seq_size_type max_size() const { return Unbounded::Bounds; }
00073     void replace(seq_size_type maximum, seq_size_type length,
00074                  T* data, seq_flag_type release = false)
00075     {
00076       static_cast<Sequence&>(*this).replace_i(maximum, length, data, release);
00077     }
00078   protected:
00079     explicit AllocPolicy(seq_size_type n = 0) : maximum_(n) {}
00080     T* allocate(seq_size_type request = 0) const
00081     {
00082       return allocbuf(request ? request : maximum_);
00083     }
00084     void swap(AllocPolicy& rhs) throw() { std::swap(maximum_, rhs.maximum_); }
00085     seq_size_type maximum_;
00086   };
00087 
00088   /// Element Policy for sequence elements that are IDL "fixed-length" types.
00089   /// These types don't need initialization or destruction of elements in their
00090   /// allocbuf()/freebuf() functions.
00091   /// @tparam T element type of the sequence
00092   template <typename T>
00093   struct DefaultEltPolicy {
00094     typedef T& Element;
00095     typedef const T& ConstElement;
00096     typedef T ConstRawElement;
00097     static const seq_size_type extra = 0;
00098     static T& make_element(T& elt, seq_flag_type) { return elt; }
00099     static void construct(T*, seq_size_type, seq_flag_type) {}
00100     static void copy_n(const T* input, seq_size_type n, T* output);
00101     static void move_n(T* in, seq_size_type n, T* out) { copy_n(in, n, out); }
00102     static void reset_n(T*, seq_size_type) {}
00103     static T* destroy(T* buffer, seq_size_type) { return buffer; }
00104   };
00105 
00106   /// Element Policy for sequence elements that are IDL "variable-length" types
00107   /// except for strings and arrays, which are handled separately.
00108   /// @tparam T element type of the sequence
00109   template <typename T>
00110   struct VariEltPolicy {
00111     typedef T& Element;
00112     typedef const T& ConstElement;
00113     typedef T ConstRawElement;
00114     static const seq_size_type extra = 1;
00115     static T& make_element(T& elt, seq_flag_type) { return elt; }
00116     static void construct(T* buffer, seq_size_type n, seq_flag_type cookie);
00117     static void copy_n(const T* input, seq_size_type n, T* output);
00118     static void move_n(T* in, seq_size_type n, T* out);
00119     static void reset_n(T* buffer, seq_size_type n);
00120     static T* destroy(T* buffer, seq_size_type n);
00121   };
00122 
00123   /// Element Policy for sequences of strings.
00124   /// @tparam CharT FACE::Char or FACE::WChar
00125   template <typename CharT>
00126   struct StringEltPolicy {
00127 
00128     /// Indexing a non-const string sequence yields an object of this class.
00129     /// This allows string memory management duing assignment.
00130     struct Element {
00131       Element(CharT*& element, seq_flag_type release)
00132         : element_(element), release_(release) {}
00133 
00134       Element(const Element& elt)
00135         : element_(elt.element_), release_(elt.release_) {}
00136 
00137       Element& operator=(const CharT* rhs)
00138       {
00139         ::TAO::String_var<CharT> tmp(rhs);
00140         return move_from(tmp);
00141       }
00142 
00143       Element& operator=(CharT* rhs)
00144       {
00145         ::TAO::String_var<CharT> tmp(rhs);
00146         return move_from(tmp);
00147       }
00148 
00149       Element& operator=(const ::TAO::String_var<CharT>& rhs)
00150       {
00151         ::TAO::String_var<CharT> tmp(rhs);
00152         return move_from(tmp);
00153       }
00154 
00155       Element& operator=(const ::TAO::String_Manager_T<CharT>& rhs)
00156       {
00157         ::TAO::String_var<CharT> tmp(rhs);
00158         return move_from(tmp);
00159       }
00160 
00161       operator const CharT*() const { return element_; }
00162       const CharT* in() const { return element_; }
00163       CharT*& inout() { return element_; }
00164 
00165       ::TAO::String_out<CharT> out() const
00166       {
00167         if (release_) StringTraits<CharT>::free(element_);
00168         return element_;
00169       }
00170 
00171       CharT* _retn()
00172       {
00173         CharT* const tmp = element_;
00174         element_ = StringTraits<CharT>::empty();
00175         return tmp;
00176       }
00177 
00178     private:
00179       Element& move_from(::TAO::String_var<CharT>& rhs)
00180       {
00181         if (release_) StringTraits<CharT>::free(element_);
00182         element_ = rhs._retn();
00183         return *this;
00184       }
00185 
00186       CharT*& element_;
00187       seq_flag_type release_;
00188 
00189       inline friend bool operator>>(DCPS::Serializer& ser, Element elt)
00190       {
00191         ser.read_string(elt.out(), StringTraits<CharT>::alloc,
00192           StringTraits<CharT>::free);
00193         return ser.good_bit();
00194       }
00195     };
00196 
00197     static Element make_element(CharT*& elt, seq_flag_type release)
00198     {
00199       return Element(elt, release);
00200     }
00201 
00202     typedef const CharT* ConstElement;
00203     typedef const CharT* ConstRawElement;
00204     static const seq_size_type extra = 1;
00205     static void construct(CharT** buf, seq_size_type n, seq_flag_type cookie);
00206     static void copy_n(const CharT* const* in, seq_size_type n, CharT** out);
00207     static void move_n(CharT** in, seq_size_type n, CharT** out);
00208     static void reset_n(CharT**, seq_size_type);
00209     static CharT** destroy(CharT** buffer, seq_size_type n);
00210   };
00211 
00212   /// Element Policy for sequences of arrays.
00213   /// Currently arrays of fixed-length and variable-length elements are both
00214   /// handled the same way, but optimizing the fixed-length element types could
00215   /// be done here (they don't need construction, destruction, or cookies).
00216   /// @tparam Forany the array's *_forany type generated by the IDL compiler
00217   template <typename Forany, typename T = typename Forany::_array_type>
00218   struct ArrayEltPolicy {
00219     typedef T& Element;
00220     typedef const T& ConstElement;
00221     typedef const T ConstRawElement;
00222     static const seq_size_type extra =
00223       (sizeof(seq_size_type) - 1) / sizeof(T) + 1;
00224     static T& make_element(T& elt, seq_flag_type) { return elt; }
00225     static void construct(T* buffer, seq_size_type n, seq_flag_type use_cookie);
00226     static void copy_n(const T* input, seq_size_type n, T* output);
00227     static void move_n(T* in, seq_size_type n, T* out) { copy_n(in, n, out); }
00228     static void reset_n(T* buffer, seq_size_type n);
00229     static T* destroy(T* buffer, seq_size_type n);
00230   };
00231 
00232   /// Generic base class for all IDL-defined sequences accepted by opendds_idl.
00233   /// Derived classes (generated by opendds_idl) need to provide the following
00234   /// methods to be compliant with the IDL-to-C++ specification:
00235   /// If bounded:
00236   /// - Constructors: default, copy, 3-arg
00237   /// If unbounded:
00238   /// - Constructors: default, copy, 1-arg (maximum), 4-arg
00239   /// Both bounded and unbounded:
00240   /// - Copy assignment
00241   /// - non-member swap(), while not in spec this is useful for copy assignment
00242   /// @tparam T element type of the sequence
00243   /// @tparam Bounds either Bounded<N> or Unbounded
00244   /// @tparam Elts element handling policy
00245   template <typename T, typename Bounds, typename Elts = DefaultEltPolicy<T> >
00246   class Sequence
00247     : public AllocPolicy<T, Sequence<T, Bounds, Elts>, Bounds>
00248     , public ::OpenDDS::DCPS::PoolAllocationBase {
00249   public:
00250     typedef seq_size_type size_type;  // from std C++ Container concept
00251     typedef seq_size_type _size_type; // from IDL-to-C++ specification
00252     typedef Elts ElementPolicy;
00253 
00254   protected:
00255     explicit Sequence(size_type maximum = 0, size_type length = 0,
00256                       T* data = 0, seq_flag_type release = false);
00257     Sequence(const Sequence& seq);
00258     ~Sequence();
00259     Sequence& operator=(const Sequence& seq);
00260 
00261     void swap(Sequence& rhs) throw();
00262   public:
00263     using AllocPolicy<T, Sequence, Bounds>::maximum;
00264     void length(size_type len);
00265     size_type length() const { return length_; }
00266 
00267     typedef typename Elts::Element Element;
00268     typedef typename Elts::ConstElement ConstElement;
00269     typedef typename Elts::ConstRawElement ConstRawElement;
00270 
00271     typedef ConstElement const_subscript_type; // sequence _var compatibility
00272     typedef Element subscript_type; // sequence _var compatibility
00273 
00274     ConstElement operator[](size_type idx) const;
00275     Element operator[](size_type idx);
00276 
00277     seq_flag_type release() const { return release_; }
00278 
00279     T* get_buffer(seq_flag_type orphan = false);
00280     const ConstRawElement* get_buffer() const;
00281 
00282     // allocbuf() inherited from AllocPolicy
00283     static void freebuf(T* data);
00284 
00285 
00286     // The public members below provide C++ standard library container
00287     // compatibility for convenience.
00288     // Iterators are always T* so be careful with string sequences,
00289     // the caller needs to use FACE::string_free() and FACE::string_alloc()
00290     // or FACE::string_dup() to replace a string in the sequence.
00291     // These are the same semantics as get_buffer(bool) in the IDL-to-C++
00292     // mapping.
00293 
00294     typedef T value_type;
00295     typedef T& reference;
00296     typedef const T& const_reference;
00297     typedef T* iterator;
00298     typedef const T* const_iterator;
00299     typedef std::ptrdiff_t difference_type;
00300 
00301     const T* begin() const { return buffer_; }
00302     T* begin() { return buffer_; }
00303 
00304     const T* end() const { return buffer_ + length_; }
00305     T* end() { return buffer_ + length_; }
00306 
00307     bool operator==(const Sequence& rhs) const;
00308     bool operator!=(const Sequence& rhs) const;
00309 
00310     size_type size() const { return length_; }
00311     // max_size() inherited from AllocPolicy
00312     bool empty() const { return !length_; }
00313 
00314 #ifndef __SUNPRO_CC
00315   private:
00316     friend struct AllocPolicy<T, Sequence, Bounds>;
00317 #endif
00318     void replace_i(size_type maximum, size_type length,
00319                    T* data, seq_flag_type release);
00320 
00321   private:
00322     using AllocPolicy<T, Sequence, Bounds>::allocate;
00323     void lazy_alloc() const;
00324 
00325     size_type length_;
00326     mutable seq_flag_type release_;
00327     mutable T* buffer_;
00328   };
00329 
00330 
00331   // Allocation Policies:
00332 
00333   template <typename T, typename Sequence, seq_size_type N>
00334   inline T* AllocPolicy<T, Sequence, Bounded<N> >::allocbuf()
00335   {
00336     void* const raw =
00337       ACE_Allocator::instance()->malloc(N * sizeof(T));
00338     T* const mem = static_cast<T*>(raw);
00339     Sequence::ElementPolicy::construct(mem, N, false);
00340     return mem;
00341   }
00342 
00343   template <typename T, typename Sequence>
00344   inline T* AllocPolicy<T, Sequence, Unbounded>::allocbuf(seq_size_type n)
00345   {
00346     const size_t bytes = (n + Sequence::ElementPolicy::extra) * sizeof(T);
00347     void* const raw = ACE_Allocator::instance()->malloc(bytes);
00348     T* const mem = static_cast<T*>(raw);
00349     Sequence::ElementPolicy::construct(mem, n, true);
00350     return mem + Sequence::ElementPolicy::extra;
00351   }
00352 
00353 
00354   // Default Element Policy:
00355 
00356   template <typename T>
00357   inline void DefaultEltPolicy<T>::copy_n(const T* in, seq_size_type n, T* out)
00358   {
00359     std::memcpy(out, in, n * sizeof(T));
00360   }
00361 
00362 
00363   // String Element Policy:
00364 
00365   template <typename CharT>
00366   inline void StringEltPolicy<CharT>::construct(CharT** buffer, seq_size_type n,
00367                                                 seq_flag_type use_cookie)
00368   {
00369     for (seq_size_type i = use_cookie; i < n + use_cookie; ++i) {
00370       buffer[i] = StringTraits<CharT>::empty();
00371     }
00372     if (use_cookie) {
00373       *reinterpret_cast<seq_size_type*>(buffer) = n;
00374     }
00375   }
00376 
00377   template <typename CharT>
00378   inline void StringEltPolicy<CharT>::copy_n(const CharT* const* in,
00379                                              seq_size_type n, CharT** out)
00380   {
00381     for (seq_size_type i = 0; i < n; ++i) {
00382       StringTraits<CharT>::free(out[i]);
00383       out[i] = StringTraits<CharT>::dup(in[i]);
00384     }
00385   }
00386 
00387   template <typename CharT>
00388   inline void StringEltPolicy<CharT>::move_n(CharT** in, seq_size_type n,
00389                                              CharT** out)
00390   {
00391     for (seq_size_type i = 0; i < n; ++i) {
00392       std::swap(in[i], out[i]);
00393     }
00394   }
00395 
00396   template <typename CharT>
00397   inline void StringEltPolicy<CharT>::reset_n(CharT** buffer, seq_size_type n)
00398   {
00399     for (seq_size_type i = 0; i < n; ++i) {
00400       StringTraits<CharT>::free(buffer[i]);
00401       buffer[i] = StringTraits<CharT>::empty();
00402     }
00403   }
00404 
00405   template <typename CharT>
00406   inline CharT** StringEltPolicy<CharT>::destroy(CharT** buffer,
00407                                                  seq_size_type n_or_int_max)
00408   {
00409     seq_size_type n = n_or_int_max;
00410     CharT** allocated = buffer;
00411 
00412     if (n_or_int_max == INT_MAX) {
00413       allocated = buffer - 1;
00414       n = *reinterpret_cast<seq_size_type*>(allocated);
00415     }
00416 
00417     for (seq_size_type i = 0; i < n; ++i) {
00418       StringTraits<CharT>::free(buffer[i]);
00419     }
00420 
00421     return allocated;
00422   }
00423 
00424 
00425   // Variable-length Element Policy:
00426 
00427   template <typename T>
00428   inline void VariEltPolicy<T>::construct(T* buffer, seq_size_type n,
00429                                           seq_flag_type use_cookie)
00430   {
00431     std::uninitialized_fill_n(buffer + use_cookie, n, T());
00432     if (use_cookie) {
00433       *reinterpret_cast<seq_size_type*>(buffer) = n;
00434     }
00435   }
00436 
00437   template <typename T>
00438   inline void VariEltPolicy<T>::copy_n(const T* in, seq_size_type n, T* out)
00439   {
00440     std::copy(in, in + n, out);
00441   }
00442 
00443   template <typename T>
00444   inline void VariEltPolicy<T>::move_n(T* in, seq_size_type n, T* out)
00445   {
00446     std::swap_ranges(in, in + n, out);
00447   }
00448 
00449   template <typename T>
00450   inline void VariEltPolicy<T>::reset_n(T* buffer, seq_size_type n)
00451   {
00452     std::fill_n(buffer, n, T());
00453   }
00454 
00455   template <typename T>
00456   inline T* VariEltPolicy<T>::destroy(T* buffer, seq_size_type n_or_int_max)
00457   {
00458     seq_size_type n = n_or_int_max;
00459     T* allocated = buffer;
00460 
00461     if (n_or_int_max == INT_MAX) {
00462       allocated = buffer - 1;
00463       n = *reinterpret_cast<seq_size_type*>(allocated);
00464     }
00465 
00466     for (seq_size_type i = 0; i < n; ++i) {
00467       buffer[i].~T();
00468     }
00469 
00470     return allocated;
00471   }
00472 
00473 
00474   // Array Element Policy:
00475 
00476   template <typename Forany, typename T>
00477   inline void ArrayEltPolicy<Forany, T>::construct(T* buffer,
00478                                                    seq_size_type n,
00479                                                    seq_flag_type use_cookie)
00480   {
00481     const seq_size_type start = use_cookie ? extra : 0;
00482     for (seq_size_type i = start; i < n + start; ++i) {
00483       TAO::Array_Traits<Forany>::construct(buffer[i]);
00484     }
00485     if (use_cookie) {
00486       *reinterpret_cast<seq_size_type*>(buffer) = n;
00487     }
00488   }
00489 
00490   template <typename Forany, typename T>
00491   inline void ArrayEltPolicy<Forany, T>::copy_n(const T* in, seq_size_type n,
00492                                                 T* out)
00493   {
00494     for (seq_size_type i = 0; i < n; ++i) {
00495       TAO::Array_Traits<Forany>::copy(out[i], in[i]);
00496     }
00497   }
00498 
00499   template <typename Forany, typename T>
00500   inline void ArrayEltPolicy<Forany, T>::reset_n(T* buffer, seq_size_type n)
00501   {
00502     for (seq_size_type i = 0; i < n; ++i) {
00503       TAO::Array_Traits<Forany>::zero(buffer[i]);
00504     }
00505   }
00506 
00507   template <typename Forany, typename T>
00508   inline T* ArrayEltPolicy<Forany, T>::destroy(T* buffer, seq_size_type n)
00509   {
00510     seq_size_type num = n;
00511     T* alloc = buffer;
00512 
00513     if (n == INT_MAX) {
00514       alloc = buffer - extra;
00515       num = *reinterpret_cast<seq_size_type*>(alloc);
00516     }
00517 
00518     for (seq_size_type i = 0; i < num; ++i) {
00519       TAO::Array_Traits<Forany>::destroy(buffer[i]);
00520     }
00521 
00522     return alloc;
00523   }
00524 
00525 
00526   // Members of the Sequence template itself:
00527 
00528   template <typename T, typename Bounds, typename Elts>
00529   inline Sequence<T, Bounds, Elts>::Sequence(size_type maximum,
00530                                              size_type length,
00531                                              T* data, seq_flag_type release)
00532     : AllocPolicy<T, Sequence, Bounds>(maximum)
00533     , length_(length)
00534     , release_(release)
00535     , buffer_(data)
00536   {
00537   }
00538 
00539   template <typename T, typename Bounds, typename Elts>
00540   inline Sequence<T, Bounds, Elts>::Sequence(const Sequence& seq)
00541     : AllocPolicy<T, Sequence, Bounds>(seq.maximum())
00542     , length_(seq.length_)
00543     , release_(true)
00544     , buffer_((seq.maximum() && seq.buffer_) ? allocate() : 0)
00545   {
00546     if (buffer_) {
00547       Elts::copy_n(seq.buffer_, length_, buffer_);
00548     }
00549   }
00550 
00551   template <typename T, typename Bounds, typename Elts>
00552   inline Sequence<T, Bounds, Elts>::~Sequence()
00553   {
00554     if (release_) {
00555       freebuf(buffer_);
00556     }
00557   }
00558 
00559   template <typename T, typename Bounds, typename Elts>
00560   inline Sequence<T, Bounds, Elts>&
00561   Sequence<T, Bounds, Elts>::operator=(const Sequence& seq)
00562   {
00563     Sequence cpy(seq);
00564     swap(cpy);
00565     return *this;
00566   }
00567 
00568   template <typename T, typename Bounds, typename Elts>
00569   inline void Sequence<T, Bounds, Elts>::swap(Sequence& rhs) throw()
00570   {
00571     AllocPolicy<T, Sequence, Bounds>::swap(rhs);
00572     std::swap(length_, rhs.length_);
00573     std::swap(release_, rhs.release_);
00574     std::swap(buffer_, rhs.buffer_);
00575   }
00576 
00577   template <typename T, typename Bounds, typename Elts>
00578   inline void Sequence<T, Bounds, Elts>::replace_i(size_type maximum,
00579                                                    size_type length, T* data,
00580                                                    seq_flag_type release)
00581   {
00582     Sequence tmp(maximum, length, data, release);
00583     swap(tmp);
00584   }
00585 
00586   template <typename T, typename Bounds, typename Elts>
00587   inline void Sequence<T, Bounds, Elts>::lazy_alloc() const
00588   {
00589     if (!buffer_) {
00590       buffer_ = allocate();
00591       release_ = true;
00592     }
00593   }
00594 
00595   template <typename T, typename Bounds, typename Elts>
00596   inline void Sequence<T, Bounds, Elts>::length(size_type len)
00597   {
00598     if (len <= maximum()) {
00599       if (len && !buffer_) {
00600         lazy_alloc();
00601       }
00602       else if (release_ && len < length_) {
00603         Elts::reset_n(buffer_ + len, length_ - len);
00604       }
00605       length_ = len;
00606       return;
00607     }
00608 
00609     Sequence tmp(len, len, allocate(len), true);
00610     Elts::move_n(buffer_, length_, tmp.buffer_);
00611     swap(tmp);
00612   }
00613 
00614   template <typename T, typename Bounds, typename Elts>
00615   inline typename Sequence<T, Bounds, Elts>::ConstElement
00616   Sequence<T, Bounds, Elts>::operator[](size_type idx) const
00617   {
00618     return buffer_[idx];
00619   }
00620 
00621   template <typename T, typename Bounds, typename Elts>
00622   inline typename Sequence<T, Bounds, Elts>::Element
00623   Sequence<T, Bounds, Elts>::operator[](size_type idx)
00624   {
00625     return Elts::make_element(buffer_[idx], release_);
00626   }
00627 
00628   template <typename T, typename Bounds, typename Elts>
00629   inline T* Sequence<T, Bounds, Elts>::get_buffer(seq_flag_type orphan)
00630   {
00631     if (orphan && !release_) {
00632       return 0;
00633     }
00634 
00635     lazy_alloc();
00636 
00637     if (orphan) {
00638       Sequence tmp;
00639       swap(tmp);
00640       tmp.release_ = false;
00641       return tmp.buffer_;
00642     }
00643 
00644     return buffer_;
00645   }
00646 
00647   template <typename T, typename Bounds, typename Elts>
00648   inline const typename Sequence<T, Bounds, Elts>::ConstRawElement*
00649   Sequence<T, Bounds, Elts>::get_buffer() const
00650   {
00651     lazy_alloc();
00652     return buffer_;
00653   }
00654 
00655   template <typename T, typename Bounds, typename Elts>
00656   inline void Sequence<T, Bounds, Elts>::freebuf(T* data)
00657   {
00658     if (!data) return;
00659     T* const allocated = Elts::destroy(data, Bounds::Bounds);
00660     ACE_Allocator::instance()->free(allocated);
00661   }
00662 
00663   template <typename T, typename Bounds, typename Elts>
00664   inline bool Sequence<T, Bounds, Elts>::operator==(const Sequence& rhs) const
00665   {
00666     const size_type sz = size();
00667     if (sz != rhs.size()) {
00668       return false;
00669     }
00670     for (size_type i = 0; i < sz; ++i) {
00671       if (!((*this)[i] == rhs[i])) {
00672         return false;
00673       }
00674     }
00675     return true;
00676   }
00677 
00678   template <typename T, typename Bounds, typename Elts>
00679   inline bool Sequence<T, Bounds, Elts>::operator!=(const Sequence& rhs) const
00680   {
00681     return !(*this == rhs);
00682   }
00683 }
00684 }
00685 
00686 #endif /* dds_DCPS_SafetyProfileSequence_h */
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines

Generated on 10 Aug 2018 for OpenDDS by  doxygen 1.6.1