14 #if __cplusplus
>=201103L
15 # include <initializer_list> 20 #include "pv/sharedPtr.h" 21 #include "pv/pvIntrospect.h" 22 #include "pv/typeCast.h" 23 #include "pv/templateMeta.h" 25 namespace epics {
namespace pvData {
29 template<
typename TO,
typename FROM>
32 const_shared_vector_cast(shared_vector<FROM>& src);
40 template<
typename T>
struct call_with {
typedef T type; };
41 template<
typename T>
struct call_with<std::tr1::shared_ptr<T> >
42 {
typedef const std::tr1::shared_ptr<T>& type; };
43 template<>
struct call_with<std::string> {
typedef const std::string& type; };
59 std::tr1::shared_ptr<E> m_sdata;
73 #if __cplusplus
>=201103L
75 constexpr shared_vector_base()
noexcept 100 shared_vector_base(A* v, size_t o, size_t c)
101 :m_sdata(v, detail::default_array_deleter<A*>())
105 shared_vector_base(
const std::tr1::shared_ptr<E>& d, size_t o, size_t c)
110 template<
typename A,
typename B>
111 shared_vector_base(A d, B b, size_t o, size_t c)
116 :m_sdata(O.m_sdata),
m_offset(O.m_offset)
120 #if __cplusplus
>= 201103L
122 :m_sdata(std::move(O.m_sdata))
144 throw std::runtime_error(
"Can't freeze non-unique vector");
145 #if __cplusplus
>= 201103L
146 m_sdata = std::move(O.m_sdata);
163 #if __cplusplus
>= 201103L
164 m_sdata = std::move(std::tr1::const_pointer_cast<E>(O.m_sdata));
166 m_sdata = std::tr1::const_pointer_cast<E>(O.m_sdata);
183 #if __cplusplus
>= 201103L
188 m_sdata=std::move(o.m_sdata);
201 m_sdata.swap(o.m_sdata);
202 std::swap(m_count, o.m_count);
203 std::swap(m_offset, o.m_offset);
204 std::swap(m_total, o.m_total);
216 bool unique()
const {
return !m_sdata || m_sdata.use_count()<=1;}
244 void slice(size_t offset, size_t length=(size_t)-1)
249 const size_t max_count =
m_count - offset;
255 if(length > max_count)
261 const std::tr1::shared_ptr<E>& dataPtr()
const {
return m_sdata; }
262 size_t dataOffset()
const {
return m_offset; }
263 size_t dataCount()
const {
return m_count; }
264 size_t dataTotal()
const {
return m_total; }
286 template<
typename E,
class Enable>
290 typedef typename detail::
call_with<E>::type param_type;
293 typedef E value_type;
294 typedef E& reference;
299 typedef std::reverse_iterator<iterator> reverse_iterator;
301 typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
302 typedef ptrdiff_t difference_type;
303 typedef size_t size_type;
305 typedef E element_type;
306 typedef std::tr1::shared_ptr<E> shared_pointer_type;
309 template<
typename E1,
class Enable1>
friend class shared_vector;
312 #if __cplusplus
>=201103L
313 constexpr shared_vector()
noexcept :base_t() {}
318 #if __cplusplus
>=201103L
320 shared_vector(std::initializer_list<A> L)
321 :base_t(
new _E_non_const[L.size()], 0, L.size())
323 _E_non_const *raw =
const_cast<_E_non_const*>(data());
324 std::copy(L.begin(), L.end(), raw);
337 std::fill_n((_E_non_const*)
this->m_sdata.get(),
this->m_count, e);
355 template<
typename E1>
366 template<
typename A,
typename B>
373 #if __cplusplus
>=201103L
380 template<
typename FROM>
381 shared_vector(
const shared_vector<FROM> &src,
383 :base_t(std::tr1::static_pointer_cast<E>(src.dataPtr()),
384 src.dataOffset()/
sizeof(E),
385 src.dataCount()/
sizeof(E))
389 shared_vector(shared_vector<
typename base_t::_E_non_const>& O,
394 shared_vector(shared_vector<
const E>& O,
401 this->base_t::operator=(o);
405 #if __cplusplus
>=201103L
408 this->base_t::operator=(std::move(o));
413 size_t max_size()
const{
return ((size_t)-1)/
sizeof(E);}
415 size_t capacity()
const {
return this->m_total; }
429 if(
this->unique() && i<=
this->m_total)
431 size_t new_count =
this->m_count;
434 _E_non_const* temp=
new _E_non_const[i];
436 std::copy(begin(), begin()+new_count, temp);
437 this->m_sdata.reset(temp, detail::default_array_deleter<E*>());
443 this->m_count = new_count;
458 if(i==
this->m_count) {
462 if(
this->m_sdata &&
this->m_sdata.use_count()==1) {
464 if(i<=
this->m_total) {
471 size_t new_total =
this->m_total;
474 _E_non_const* temp=
new _E_non_const[new_total];
476 size_t n =
this->size();
484 this->m_sdata.reset(temp, detail::default_array_deleter<pointer>());
491 this->m_total = new_total;
499 size_t oldsize=
this->size();
501 if(
this->size()>oldsize) {
502 std::fill(begin()+oldsize, end(), v);
530 _E_non_const *d =
new _E_non_const[
this->m_total];
532 std::copy(
this->m_sdata.get()+
this->m_offset,
533 this->m_sdata.get()+
this->m_offset+
this->m_count,
539 this->m_sdata.reset(d, detail::default_array_deleter<E*>());
550 inline E* base_ptr()
const {
551 #if defined(_MSC_VER) && _MSC_VER<=1800
552 return this->m_count ?
this->m_sdata.get() : (E*)(
this-1);
554 return this->m_sdata.get();
560 iterator begin()
const{
return this->base_ptr()+
this->m_offset;}
561 const_iterator cbegin()
const{
return begin();}
563 iterator end()
const{
return this->base_ptr()+
this->m_offset+
this->m_count;}
564 const_iterator cend()
const{
return end();}
566 reverse_iterator rbegin()
const{
return reverse_iterator(end());}
567 const_reverse_iterator crbegin()
const{
return rbegin();}
569 reverse_iterator rend()
const{
return reverse_iterator(begin());}
570 const_reverse_iterator crend()
const{
return rend();}
572 reference front()
const{
return (*
this)[0];}
573 reference back()
const{
return (*
this)[
this->m_count-1];}
578 void _push_resize() {
579 if(
this->m_count==
this->m_total || !
this->unique()) {
581 if(
this->m_total<1024) {
583 next =
this->m_total;
591 next =
this->m_total+1024;
594 assert(next >
this->m_total);
597 resize(
this->size()+1);
602 void push_back(param_type v)
610 this->slice(0,
this->size()-1);
616 pointer
data()
const{
return this->m_sdata.get()+
this->m_offset;}
620 reference
operator[](size_t i)
const {
return this->m_sdata.get()[
this->m_offset+i];}
624 reference
at(size_t i)
const 627 throw std::out_of_range(
"Index out of bounds");
670 #if __cplusplus
>=201103L
683 template<
typename E1>
690 #if __cplusplus
>=201103L
697 template<
typename FROM>
725 #if __cplusplus
>=201103L
752 template<
typename TO,
typename FROM,
class Enable =
void>
755 template<
typename TO,
typename FROM>
756 struct static_shared_vector_caster<TO, FROM,
757 typename meta::_and<meta::_and<meta::is_not_void<TO>, meta::is_void<FROM> >,
758 meta::same_const<TO,FROM> >::type> {
759 static inline shared_vector<TO> op(
const shared_vector<FROM>& src) {
760 return shared_vector<TO>(src, detail::_shared_vector_cast_tag());
764 template<
typename TO,
typename FROM>
765 struct static_shared_vector_caster<TO, FROM,
766 typename meta::_and<meta::_and<meta::is_void<TO>, meta::is_not_void<FROM> >,
767 meta::same_const<TO,FROM> >::type> {
768 static FORCE_INLINE shared_vector<TO> op(
const shared_vector<FROM>& src) {
769 return shared_vector<TO>(src, detail::_shared_vector_cast_tag());
774 template<
typename TOFRO>
776 static FORCE_INLINE const shared_vector<TOFRO>& op(
const shared_vector<TOFRO>& src) {
789 template<
typename TO,
typename FROM>
792 static_shared_vector_cast(
const shared_vector<FROM>& src)
794 return detail::static_shared_vector_caster<TO,FROM>::op(src);
800 template<
typename TO,
typename FROM,
class Enable =
void>
802 static inline shared_vector<TO> op(
const shared_vector<FROM>& src)
804 shared_vector<TO> ret(src.size());
805 std::transform(src.begin(), src.end(), ret.begin(), castUnsafe<TO,FROM>);
811 template<
typename TO,
typename FROM>
812 struct shared_vector_converter<TO,FROM,
typename meta::same_root<TO,FROM>::type > {
813 static FORCE_INLINE shared_vector<TO> op(
const shared_vector<FROM>& src) {
820 template<
typename TO,
typename FROM>
821 struct shared_vector_converter<TO,FROM,
822 typename meta::_and<meta::is_void<TO>, meta::is_not_void<FROM> >::type
825 static FORCE_INLINE shared_vector<TO> op(
const shared_vector<FROM>& src) {
826 return shared_vector<TO>(src, detail::_shared_vector_cast_tag());
831 template<
typename TO,
typename FROM>
832 struct shared_vector_converter<TO,FROM,
833 typename meta::_and<meta::is_not_void<TO>, meta::is_void<FROM> >::type
836 static shared_vector<TO> op(
const shared_vector<FROM>& src) {
837 typedef typename meta::strip_const<TO>::type to_t;
838 ScalarType stype = src.original_type(),
839 dtype = (ScalarType)ScalarTypeID<TO>::value;
841 return shared_vector<TO>();
843 }
else if(stype==dtype) {
845 return shared_vector<TO>(src, detail::_shared_vector_cast_tag());
849 shared_vector<to_t> ret(src.size()/ScalarTypeFunc::elementSize(stype));
850 castUnsafeV(ret.size(),
852 static_cast<
void*>(ret.data()),
854 static_cast<
const void*>(src.data()));
855 return const_shared_vector_cast<TO>(ret);
872 template<
typename TO,
typename FROM>
875 shared_vector_convert(
const shared_vector<FROM>& src)
877 return detail::shared_vector_converter<TO,FROM>::op(src);
886 template<
typename SRC>
888 shared_vector<
typename meta::decorate_const<
typename SRC::value_type>::type>
891 typedef typename meta::decorate_const<
typename SRC::value_type>::type const_value;
892 return shared_vector<const_value>(src, detail::_shared_vector_freeze_tag());
901 template<
typename SRC>
903 shared_vector<
typename meta::strip_const<
typename SRC::value_type>::type>
906 typedef typename meta::strip_const<
typename SRC::value_type>::type value;
907 return shared_vector<value>(src, detail::_shared_vector_thaw_tag());
911 template<
typename TO,
typename FROM,
class Enable =
void>
914 template<
typename TYPE>
915 struct const_caster<TYPE,
const TYPE> {
916 static FORCE_INLINE shared_vector<TYPE> op(shared_vector<
const TYPE>& src)
922 template<
typename TYPE>
923 struct const_caster<
const TYPE,TYPE> {
924 static FORCE_INLINE shared_vector<
const TYPE> op(shared_vector<TYPE>& src)
930 template<
typename TYPE>
931 struct const_caster<TYPE,TYPE> {
932 static FORCE_INLINE shared_vector<TYPE> op(shared_vector<TYPE>& src)
934 shared_vector<TYPE> ret(src);
942 template<
typename TO,
typename FROM>
945 const_shared_vector_cast(shared_vector<FROM>& src)
947 return detail::const_caster<TO,FROM>::op(src);
961 shared_vector<
void> raw(allocArray(ID, len));
962 return static_shared_vector_cast<
typename ScalarTypeTraits<ID>::type>(raw);
970 template<
typename A,
typename B>
971 bool operator==(
const epics::pvData::shared_vector<A>& a,
972 const epics::pvData::shared_vector<B>& b)
974 if(a.size() != b.size())
976 if(a.dataOffset()==b.dataOffset() && a.dataPtr().get()==b.dataPtr().get())
978 return std::equal(a.begin(), a.end(), b.begin());
981 template<
typename A,
typename B>
982 bool operator!=(
const epics::pvData::shared_vector<A>& a,
983 const epics::pvData::shared_vector<B>& b)
989 std::ostream& operator<<(std::ostream& strm,
const epics::pvData::shared_vector<E>& arr)
991 strm<<
'{'<<arr.size()<<
"}[";
992 for(size_t i=0; i<arr.size(); i++) {
pointer data() const
Return Base pointer.
shared_vector_base & operator=(const shared_vector_base &o)
Copy an existing vector.
shared_vector(size_t c, param_type e)
Allocate (with new[]) a new vector of size c and fill with value e.
shared_vector_base(shared_vector< const E > &O, _shared_vector_thaw_tag)
void swap(shared_vector_base &o)
Swap the contents of this vector with another.
void resize(size_t i)
Grow or shrink array.
shared_vector(A d, B b, size_t o, size_t c)
Build vector from raw pointer and cleanup function.
bool unique() const
Data is not shared?
shared_vector< typename ScalarTypeTraits< ID >::type > allocArray(size_t len)
Allocate an untyped array based on ScalarType.
void slice(size_t offset, size_t length=(size_t) -1)
Reduce the view of this shared_vector.
size_t size() const
Number of elements visible through this vector.
reference at(size_t i) const
Member access.
void reserve(size_t i)
Set array capacity.
shared_vector(const std::tr1::shared_ptr< E1 > &d, size_t o, size_t c)
Build vector from an existing smart pointer.
shared_vector(size_t c)
Allocate (with new[]) a new vector of size c.
epicsShareFunc shared_vector< void > allocArray(ScalarType id, size_t len)
Allocate an untyped array based on ScalarType.
reference operator[](size_t i) const
Member access Undefined if empty()==true.
shared_vector(const shared_vector &o)
Copy an existing vector of same type.
shared_vector()
Empty vector (not very interesting)
epicsShareFunc bool yajl_parse_helper(std::istream &src, yajl_handle handle)
void resize(size_t i, param_type v)
Grow (and fill) or shrink array.
size_t m_offset
Offset in the data array of first visible element.
void make_unique()
Ensure (by copying) that this shared_vector is the sole owner of the data array.
size_t m_total
Total number of elements between m_offset and the end of data.
bool empty() const
shorthand for size()==0
shared_vector_base(shared_vector_base< _E_non_const > &O, _shared_vector_freeze_tag)
size_t m_count
Number of visible elements between m_offset and end of data.
void clear()
Clear contents. size() becomes 0.
shared_vector(A v, size_t o, size_t c)
Build vector from a raw pointer.
shared_vector_base()
Empty vector (not very interesting)