📄 wy__arrayvalue.h
字号:
/* Copyright is licensed under GNU LGPL. by I.J.Wang 2006 This file is part of wy_array.h*/#include <cstring> // for memcpy,memmove// Element type T is for POD (memcpy and operator= work) such as arithmetic types,// pointer types,.. for those built-in types do not have the move constructor.//template<typename T>class Wy__ArrayValue { typedef T ElemType; typedef size_t SizeType; static const SizeType MaxSizeRawMemory; static const SizeType MinimumCapacity; static const SizeType DefaultSize; ElemType* _b_bgn; // array begin pointer ElemType* _b_end; // end pointer of constructed objects const ElemType* _b_eob; // array end storage ptr // static SizeType _byte_dist(const ElemType* p2, const ElemType* p1) { return static_cast<const char*>(p2)-static_cast<const char*>(p1); }; // [Syn] Allocate n bytes of raw memory block // // [Ret] ElemType pointer to n bytes of raw memory block // NULL= Not enough memory // inline static ElemType* _alloc_raw(size_t n) WY__TSPC() { return reinterpret_cast<ElemType*>(::operator new(n,std::nothrow)); }; // [Syn] Free the memory block allocated by _alloc_raw(size_t) // inline static void _free_raw(ElemType* v) WY__TSPC() { ::operator delete(v); }; // [Syn] Allocate an array of capacity cap, and copy the front // part of the array from [buf, buf+n_elem) // // Note: assert(cap>=n_elem) to call // // [Ret] ElemType pointer to such array // NULL= Not enough memory // // [Depend] T(T), ~T() // static ElemType* _dup_array(const ElemType* buf, SizeType n_elem, SizeType cap) { // allocate another array of cap capacity ElemType *narr=_alloc_raw(cap*sizeof(ElemType)); if(narr==NULL) { return(NULL); } std::memcpy(narr,buf,n_elem*sizeof(ElemType)); return(narr); }; static void _objmove(ElemType* dest, ElemType* src, SizeType n) WY__NOTHROW__ { if(dest<src) { for( ; n; ++src,++dest,--n) { *dest=*src; } } else { if(n==0) { return; } --n; src+=n; dest+=n; for(;;) { *dest=*src; if(n==0) { break; } --src; --dest; --n; }; } }; public: //WY_THROW_REPLY; typedef ElemType value_type; typedef SizeType size_type; static SizeType max_capacity(void) WY__TSPC() { return MaxSizeRawMemory/sizeof(ElemType); }; static SizeType min_capacity(void) WY__TSPC() { return(MinimumCapacity); }; Wy__ArrayValue() : _b_bgn(_alloc_raw(MinimumCapacity*sizeof(ElemType))), _b_end(_b_bgn), _b_eob(_b_bgn+MinimumCapacity) { if(_b_bgn==NULL) { WY_THROW(typename Wy_Array<ElemType>::Reply(Wym_ENOMEM) ); } WY__CHK_VALIDOBJ(*this); }; Wy__ArrayValue(size_t n_elem, const ElemType& elem) : _b_bgn(NULL), _b_end(NULL), _b_eob(NULL) { const SizeType cap( n_elem<MinimumCapacity? MinimumCapacity : n_elem ); if(cap>this->max_capacity()) { WY_THROW( typename Wy_Array<ElemType>::Reply(Wym_EFBIG) ); } _b_end=_b_bgn=_alloc_raw(cap*sizeof(ElemType)); if(_b_bgn==NULL) { WY_THROW( typename Wy_Array<ElemType>::Reply(Wym_ENOMEM) ); } _b_eob=_b_bgn+n_elem; for(; _b_end!=_b_eob; ++_b_end) { *_b_end= elem; } _b_eob=_b_bgn+cap; WY__CHK_VALIDOBJ(*this); }; Wy__ArrayValue(const WySeg<ElemType>& src) : _b_bgn(NULL), _b_end(NULL), _b_eob(NULL) { const SizeType src_size( src.size() ); const SizeType cap( src_size<MinimumCapacity? MinimumCapacity : src_size ); _b_end=_b_bgn=_alloc_raw(cap*sizeof(ElemType)); if(_b_bgn==NULL) { WY_THROW( typename Wy_Array<ElemType>::Reply(Wym_ENOMEM) ); } _b_eob=_b_bgn+src_size; for(ElemType *ep(src.begin()); _b_end!=_b_eob; ++_b_end,++ep) { *_b_end= ElemType(*ep); } _b_eob=_b_bgn+cap; WY__CHK_VALIDOBJ(*this); }; Wy__ArrayValue(const WySeg<const ElemType>& src) : _b_bgn(NULL), _b_end(NULL), _b_eob(NULL) { const SizeType src_size( src.size() ); const SizeType cap( src_size<MinimumCapacity? MinimumCapacity : src_size ); _b_end=_b_bgn=_alloc_raw(cap*sizeof(ElemType)); if(_b_bgn==NULL) { WY_THROW( typename Wy_Array<ElemType>::Reply(Wym_ENOMEM) ); } _b_eob=_b_bgn+src_size; for(const ElemType *ep(src.begin()); _b_end!=_b_eob; ++_b_end,++ep) { *_b_end= ElemType(*ep); } _b_eob=_b_bgn+cap; WY__CHK_VALIDOBJ(*this); }; Wy__ArrayValue(const Wy__ArrayValue& src) : _b_bgn(NULL), _b_end(NULL), _b_eob(NULL) { WY__CHK_VALIDOBJ(src); const SizeType cap( src.size()> Wy_Array<ElemType>::min_capacity()? src.size(): Wy_Array<ElemType>::min_capacity() ); _b_bgn=_dup_array(src._b_bgn,src.size(),cap); if(_b_bgn==NULL) { WY_THROW( typename Wy_Array<ElemType>::Reply(Wym_ENOMEM) ); } _b_eob=_b_bgn+cap; _b_end=_b_bgn+src.size(); WY__CHK_VALIDOBJ(*this); }; Wy__ArrayValue(Wy__ArrayValue& p, Wy::ByMove_t) WY__TSPC() { // move semantics of p to this _b_bgn= p._b_bgn; _b_end= p._b_end; _b_eob= p._b_eob; #ifdef WY_DEBUG // cleanup semantics of p p._b_bgn=p._b_end=NULL; p._b_eob=NULL; #endif }; ~Wy__ArrayValue() { WY__CHK_VALIDOBJ(*this); _free_raw(_b_bgn); _b_bgn=_b_end=NULL; _b_eob=NULL; }; bool is_default(void) const WY__TSPC() { WY__CHK_VALIDOBJ(*this); return _b_end==_b_bgn; }; SizeType size(void) const WY__TSPC() { WY__CHK_VALIDOBJ(*this); return _b_end-_b_bgn; }; // ** Note ** // These members expose the address of the internal dynamic buffer ElemType* begin(void) WY__TSPC() { WY__CHK_VALIDOBJ(*this); return _b_bgn; }; const ElemType* begin(void) const WY__TSPC() { WY__CHK_VALIDOBJ(*this); return _b_bgn; }; const ElemType* end(void) const WY__TSPC() { WY__CHK_VALIDOBJ(*this); return _b_end; }; ElemType* end(void) WY__TSPC() { WY__CHK_VALIDOBJ(*this); return _b_end; }; ElemType& front(void) { WY__CHK_VALIDOBJ(*this); if(_b_end==_b_bgn) { WY_THROW( typename Wy_Array<ElemType>::Reply(Wym_ENOENT) ); } return *_b_bgn; }; const ElemType& front(void) const { WY__CHK_VALIDOBJ(*this); if(_b_end==_b_bgn) { WY_THROW( typename Wy_Array<ElemType>::Reply(Wym_ENOENT) ); } return *_b_bgn; }; ElemType& back(void) { WY__CHK_VALIDOBJ(*this); if(_b_end==_b_bgn) { WY_THROW( typename Wy_Array<ElemType>::Reply(Wym_ENOENT) ); } return *(_b_end-1); }; const ElemType& back(void) const { WY__CHK_VALIDOBJ(*this); if(_b_end==_b_bgn) { WY_THROW( typename Wy_Array<ElemType>::Reply(Wym_ENOENT) ); } return *(_b_end-1); }; WySeg<ElemType> subseg(void) const { WY__CHK_VALIDOBJ(*this); return WySeg<ElemType>(_b_bgn,SizeType(_b_end-_b_bgn)); }; WySeg<ElemType> subseg(SizeType idx) const { WY__CHK_VALIDOBJ(*this); const SizeType csize(_b_end-_b_bgn); if(idx>csize) { WY_THROW( typename Wy_Array<ElemType>::Reply(Wym_EINVAL) ); } return WySeg<ElemType>(_b_bgn+idx,csize-idx); }; WySeg<ElemType> subseg(SizeType idx, SizeType num) const { WY__CHK_VALIDOBJ(*this); SizeType rs(_b_end-_b_bgn); if(idx>rs) { WY_THROW( typename Wy_Array<ElemType>::Reply(Wym_EINVAL) ); } rs-=idx; if(rs>num) { rs=num; } return WySeg<ElemType>(_b_bgn+idx,rs); }; // Note: operator[] checks for valid position n // App. has to make sure n<size(), this could be difficult // with expr like: a[i][j][k] // const ElemType& operator[](SizeType n) const { WY__CHK_VALIDOBJ(*this); if(n>=SizeType(_b_end-_b_bgn)) { WY_THROW( typename Wy_Array<ElemType>::Reply(Wym_EINVAL) ); } return _b_bgn[n]; }; ElemType& operator[](SizeType n) { WY__CHK_VALIDOBJ(*this); if(n>=SizeType(_b_end-_b_bgn)) { WY_THROW( typename Wy_Array<ElemType>::Reply(Wym_EINVAL) ); } return _b_bgn[n]; }; // Note: capacity is intact void reset(void) { WY__CHK_VALIDOBJ(*this); _b_end=_b_bgn; }; void reset(const WySeg<const ElemType>& src) { WY__CHK_VALIDOBJ(*this); const SizeType src_size(src.size()); if(src_size<=this->_capacity()) { if(src.is_overlap( WySeg<const ElemType>(_b_bgn,_b_eob-_b_bgn) )) { WY_THROW( typename Wy_Array<ElemType>::Reply(Wym_ELOOP) ); } ::memcpy(_b_bgn,src.begin(),src_size*sizeof(ElemType)); _b_end=_b_bgn+src_size; } else { // This algorithm duplicate src first // const SizeType cap( src_size>=Wy_Array<ElemType>::min_capacity()? src_size : Wy_Array<ElemType>::min_capacity() ); ElemType *ptmp=_dup_array(src.begin(),src_size,cap); if(ptmp==NULL) { WY_THROW( typename Wy_Array<ElemType>::Reply(Wym_ENOMEM) ); } _free_raw(_b_bgn); _b_bgn=ptmp; _b_end=ptmp+src_size; _b_eob=ptmp+cap; } WY__CHK_VALIDOBJ(*this); }; void reset(const WySeg<ElemType>& src) { WY__CHK_VALIDOBJ(*this); const SizeType src_size(src.size()); if(src_size<=this->_capacity()) { if(src.is_overlap( WySeg<ElemType>(_b_bgn,_b_eob-_b_bgn) )) { WY_THROW( typename Wy_Array<ElemType>::Reply(Wym_ELOOP) ); } ::memcpy(_b_bgn,src.begin(),src_size*sizeof(ElemType)); _b_end=_b_bgn+src_size; } else { // This algorithm duplicate src first // const SizeType cap( src_size>=Wy_Array<ElemType>::min_capacity()? src_size : Wy_Array<ElemType>::min_capacity() ); ElemType *ptmp=_dup_array(src.begin(),src_size,cap); if(ptmp==NULL) { WY_THROW( typename Wy_Array<ElemType>::Reply(Wym_ENOMEM) ); } _free_raw(_b_bgn); _b_bgn=ptmp; _b_end=ptmp+src_size; _b_eob=ptmp+cap; } WY__CHK_VALIDOBJ(*this); }; // Note: capacity is set to needed minimum if reallocation occurred, // otherwise capacity is intact void reset(const Wy__ArrayValue& src) { WY__CHK_VALIDOBJ(*this); const SizeType src_size(src.size()); if(src_size<=this->_capacity()) { if(_b_bgn==src._b_bgn) { return; // v.reset(v) } ::memcpy(_b_bgn,src._b_bgn,src_size*sizeof(ElemType)); _b_end=_b_bgn+src_size; } else { // This algorithm duplicate src first // const SizeType cap( src_size>=Wy_Array<ElemType>::min_capacity()? src_size : Wy_Array<ElemType>::min_capacity() ); ElemType *ptmp=_dup_array(src._b_bgn,src_size,cap); if(ptmp==NULL) { WY_THROW( typename Wy_Array<ElemType>::Reply(Wym_ENOMEM) ); } _free_raw(_b_bgn); _b_bgn=ptmp; _b_end=ptmp+src_size; _b_eob=ptmp+cap; } WY__CHK_VALIDOBJ(*this); }; void reset(size_t n_elem, const ElemType& elem) { WY__CHK_VALIDOBJ(*this); const SizeType cap( n_elem<MinimumCapacity? MinimumCapacity : n_elem ); if(cap>this->max_capacity()) { WY_THROW( typename Wy_Array<ElemType>::Reply(Wym_EFBIG) ); } if(cap<=this->_capacity()) { _b_end=_b_bgn; for(SizeType i=0; i<n_elem; ++i,++_b_end) { *_b_end= elem; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -