diff options
-rwxr-xr-x | decoder/value_array.h | 163 |
1 files changed, 163 insertions, 0 deletions
diff --git a/decoder/value_array.h b/decoder/value_array.h new file mode 100755 index 00000000..bfdd1155 --- /dev/null +++ b/decoder/value_array.h @@ -0,0 +1,163 @@ +#ifndef VALUE_ARRAY_H +#define VALUE_ARRAY_H + +# include <cstdlib> +# include <algorithm> +# include <new> +# include <boost/range.hpp> +# include <boost/utility/enable_if.hpp> +# include <boost/type_traits.hpp> +#ifdef USE_BOOST_SERIALIZE +# include <boost/serialization/split_member.hpp> +# include <boost/serialization/access.hpp> +#endif + +// valarray like in that size is fixed (so saves space compared to vector), but same interface as vector (less resize/push_back/insert, of course) +template <class T, class A = std::allocator<T> > +class ValueArray : A // private inheritance so stateless allocator adds no size. +{ +public: + typedef T value_type; + typedef T& reference; + typedef T const& const_reference; + typedef T* iterator; + typedef T const* const_iterator; + typedef std::size_t size_type; + typedef std::ptrdiff_t difference_type; + typedef T* pointer; + + size_type size() const { return sz; } + bool empty() const { return size() == 0; } + + iterator begin() { return array; } + iterator end() { return array + size(); } + const_iterator begin() const { return array; } + const_iterator end() const { return array + size(); } + + reference operator[](size_type pos) { return array[pos]; } + const_reference operator[](size_type pos) const { return array[pos]; } + + reference at(size_type pos) { return array[pos]; } + const_reference at(size_type pos) const { return array[pos]; } + + reference front() { return array[0]; } + reference back() { return array[sz-1]; } + + const_reference front() const { return array[0]; } + const_reference back() const { return array[sz-1]; } + + ValueArray() : sz(0), array(NULL) {} + + explicit ValueArray(size_type s, const_reference t = T()) + : sz(s) + , array(A::allocate(s)) + { + for (size_type i = 0; i != sz; ++i) { A::construct(array + i,t); } + } + + template <class I> + ValueArray(I itr, I end) + : sz(std::distance(itr,end)) + , array(A::allocate(sz)) + { + copy_construct(itr,end,array); + } + + ~ValueArray() + { + for (size_type i = sz; i != 0; --i) { + A::destroy(array + (i - 1)); + } + if (array != NULL) A::deallocate(array,sz); + } + + void swap(ValueArray& other) + { + std::swap(sz,other.sz); + std::swap(array,other.array); + } + + ValueArray(ValueArray const& other) + : sz(other.sz) + , array(A::allocate(sz)) + { + copy_construct(other.begin(),other.end(),array); + } + + ValueArray& operator=(ValueArray const& other) + { + ValueArray(other).swap(*this); + return *this; + } + + template <class Range> + ValueArray( Range const& v + , typename boost::disable_if< boost::is_integral<Range> >::type* = 0) + : sz(boost::size(v)) + , array(A::allocate(sz)) + { + copy_construct(boost::begin(v),boost::end(v),array); + } + + template <class Range> typename + boost::disable_if< + boost::is_integral<Range> + , ValueArray>::type& operator=(Range const& other) + { + ValueArray(other).swap(*this); + return *this; + } + +private: +//friend class boost::serialization::access; + +template <class I1, class I2> +void copy_construct(I1 itr, I1 end, I2 into) +{ + for (; itr != end; ++itr, ++into) A::construct(into,*itr); +} + +template <class Archive> +void save(Archive& ar, unsigned int version) const +{ + ar << sz; + for (size_type i = 0; i != sz; ++i) ar << at(i); +} + +template <class Archive> +void load(Archive& ar, unsigned int version) +{ + size_type s; + ar >> s; + ValueArray v(s); + for (size_type i = 0; i != s; ++i) ar >> v[i]; + this->swap(v); +} +#ifdef USE_BOOST_SERIALIZE +BOOST_SERIALIZATION_SPLIT_MEMBER() +#endif +size_type sz; +pointer array; +}; + + +template <class T, class A> +bool operator==(ValueArray<T,A> const& v1, ValueArray<T,A> const& v2) +{ + return (v1.size() == v2.size()) and + std::equal(v1.begin(),v1.end(),v2.begin()); +} + + +template <class T,class A> +bool operator< (ValueArray<T,A> const& v1, ValueArray<T,A> const& v2) +{ + return std::lexicographical_compare( v1.begin() + , v1.end() + , v2.begin() + , v2.end() ); +} + + + +#endif |