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>
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
00089
00090
00091
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
00107
00108
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
00124
00125 template <typename CharT>
00126 struct StringEltPolicy {
00127
00128
00129
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
00213
00214
00215
00216
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
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
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;
00251 typedef seq_size_type _size_type;
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;
00272 typedef Element subscript_type;
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
00283 static void freebuf(T* data);
00284
00285
00286
00287
00288
00289
00290
00291
00292
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
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
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
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
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
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
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
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