fixedCapacityVector.h
Go to the documentation of this file.
00001 /* fixedCapacityVector.h
00002  */
00003 #ifndef OSL_FIXED_CAPACITY_VECTOR_H
00004 #define OSL_FIXED_CAPACITY_VECTOR_H
00005 
00006 #include "osl/misc/carray.h"
00007 #include "osl/misc/cstdint.h"
00008 #include "osl/misc/construct.h"
00009 #include <algorithm>
00010 #include <cstddef>
00011 #include <cassert>
00012 
00013 #if (__GNUC__ >= 4 && __GNUC_MINOR__ >=4)
00014 #  pragma GCC diagnostic ignored "-Wstrict-aliasing"
00015 #endif
00016 
00017 namespace osl
00018 {
00019   namespace misc
00020   {
00021   template <typename T>
00022   class FixedCapacityVectorPushBack
00023   {
00024     T *ptr;
00025     T **vPtr;
00026 #if ! (defined NDEBUG && defined MINIMAL)
00027     T *limit;
00028 #endif
00029   public:
00030     FixedCapacityVectorPushBack(T** vPtr_, T* limit_)
00031       : ptr(*vPtr_), vPtr(vPtr_)
00032 #if ! (defined NDEBUG && defined MINIMAL)
00033       ,limit(limit_)
00034 #endif
00035     {
00036     }
00037     ~FixedCapacityVectorPushBack()
00038     {
00039       assert( *vPtr == ptr );
00040       *vPtr = ptr;
00041     }
00042     void push_back(const T& e) 
00043     {
00044       assert(ptr < limit);
00045       assert( *vPtr == ptr );
00046       if(misc::detail::BitCopyTraits<T>::value)
00047         *ptr++ = e;
00048       else
00049         construct(ptr++,e);
00050 #ifndef NDEBUG
00051       (*vPtr)++;
00052 #endif
00053     }
00054   };
00055   template <typename T, size_t Capacity>
00056   class FixedCapacityVector
00057   {
00058   protected:
00059     struct Array : public CArray<T, Capacity> {}
00060 #ifdef __GNUC__
00061     __attribute__((__may_alias__))
00062 #endif
00063       ;
00064     typedef Array array_t;
00065     T* ptr;
00066     CArray<int64_t, (sizeof(T[Capacity])+sizeof(int64_t)-1)/sizeof(int64_t)> relements;
00067   private:
00068     const array_t &elements() const{
00069       return *reinterpret_cast<const array_t*>(&relements);
00070     }
00071     array_t &elements(){
00072       return *reinterpret_cast<array_t*>(&relements);
00073     }
00074   public:
00075     typedef typename array_t::value_type value_type;
00076     typedef typename array_t::iterator iterator;
00077     typedef typename array_t::const_iterator const_iterator;
00078     
00079     FixedCapacityVector() : ptr(&(elements()[0])) {}
00080     explicit FixedCapacityVector(size_t size) : ptr(&(elements()[0])) 
00081     {
00082       resize(size);
00083     }
00084     FixedCapacityVector(FixedCapacityVector const& rhs){
00085       ptr= &*begin()+rhs.size();
00086       std::uninitialized_copy(rhs.begin(),rhs.end(),begin());
00087     }
00088     template <class RangeIterator>
00089     FixedCapacityVector(const RangeIterator& first, const RangeIterator& last)
00090       : ptr(&(elements()[0]))
00091     {
00092       push_back(first, last);
00093     }
00094     ~FixedCapacityVector() 
00095     {
00096       destroy(begin(),end());
00097     }
00098     FixedCapacityVector& operator=(FixedCapacityVector const& rhs){
00099       if (this == &rhs)
00100         return *this;
00101       
00102       if(size()>rhs.size()){
00103         iterator it=std::copy(rhs.begin(),rhs.end(),begin());
00104         destroy(it,end());
00105       }
00106       else{
00107         iterator it=std::copy(&(rhs.elements()[0]),
00108                               &(rhs.elements()[0])+size(),begin());
00109         std::uninitialized_copy(&(rhs.elements()[0])+size(),
00110                                 &(rhs.elements()[0])+rhs.size(),it);
00111       }
00112       ptr= &*begin()+rhs.size();
00113       return *this;
00114     }
00115 
00116     T& operator[] (size_t i)
00117     {
00118       assert(i <= size());
00119       return elements()[i];
00120     }
00121 
00122     iterator begin() {  return &elements()[0]; }
00123     iterator end() { return static_cast<iterator>(ptr); }
00124 
00125     T& front() { return *begin(); }
00126     T& back() { return *(end() - 1); }
00127 
00128     void push_back(const T& e)
00129     {
00130       assert(size() < Capacity);
00131       construct(ptr,e);
00132       ++ptr;
00133     }
00134     template <class RangeIterator>
00135     void push_back(const RangeIterator& first, const RangeIterator& last);
00136     void pop_back() { 
00137       --ptr;
00138       destroy(ptr+1);
00139     }
00140     void clear() { 
00141       size_t s=size();
00142       ptr= &(elements()[0]);
00143       // 該当する部分のdestructorを呼ぶ
00144       destroy(begin(),begin()+(int)s);
00145     }
00146     void resize(size_t new_length)
00147     {
00148       while (size() < new_length)
00149         push_back(T());
00150       if (new_length < size()) {
00151         destroy(begin()+(int)new_length,end());
00152         ptr= &(elements()[new_length]);
00153       }
00154     }
00155 
00156     void erase(const T& e)
00157     {
00158       const iterator new_end = std::remove(begin(), end(), e);
00159       ptr= &*new_end;
00160       destroy(new_end,end());
00161     }
00162 
00164     void unique()
00165     {
00166       std::sort(begin(),end());
00167       iterator last = std::unique(begin(), end());
00168       ptr = &*last;
00169       destroy(last,end());
00170     }
00171 
00172     size_t size() const { return ptr-&*begin(); }
00173     bool empty() const { return ptr==&*begin(); }
00174     size_t capacity() const { return Capacity; }
00175 
00176     T const& operator[] (size_t i) const
00177     {
00178       assert(i < size());
00179       return elements()[i];
00180     }
00181     const_iterator begin() const { return &elements()[0]; }
00182     const_iterator end()   const { return ptr; }
00183 
00184     const T& front() const { return *begin(); }
00185     const T& back() const { return *(end() - 1); }
00186     
00187     bool isMember(const T& e, const_iterator first, const_iterator last) const
00188     {
00189       return std::find(first, last, e) != last;
00190     }
00191     bool isMember(const T& e) const
00192     {
00193       return isMember(e, begin(), end());
00194     }
00195     FixedCapacityVectorPushBack<T> pushBackHelper() 
00196     {
00197       return FixedCapacityVectorPushBack<T>
00198         (&ptr, &*begin()+Capacity);
00199     }
00200   };
00201     template <typename T, size_t C> inline
00202     bool operator==(const FixedCapacityVector<T,C>& l, const FixedCapacityVector<T,C>& r) 
00203     {
00204       return l.size() == r.size() && std::equal(l.begin(), l.end(), r.begin());
00205     }
00206     template <typename T, size_t C> inline
00207     bool operator<(const FixedCapacityVector<T,C>& l, const FixedCapacityVector<T,C>& r) 
00208     {
00209       return std::lexicographical_compare(l.begin(), l.end(), r.begin(), r.end());
00210     }
00211   } // namespace misc
00212   using misc::FixedCapacityVector;
00213   using misc::FixedCapacityVectorPushBack;
00214 } // namespace osl
00215 
00216 template <typename T, size_t Capacity>
00217 template <class RangeIterator>
00218 void osl::misc::FixedCapacityVector<T,Capacity>::push_back(const RangeIterator& first, const RangeIterator& last)
00219 {
00220   iterator insert_point = end();
00221   std::uninitialized_copy(first, last, insert_point);
00222   ptr += last-first;
00223   assert(size() <= Capacity);
00224 }
00225 
00226 
00227 #endif /* OSL_FIXED_CAPACITY_VECTOR_H */
00228 // ;;; Local Variables:
00229 // ;;; mode:c++
00230 // ;;; c-basic-offset:2
00231 // ;;; End:
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines