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