00001
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 ~FixedCapacityVector()
00081 {
00082 destroy(begin(),end());
00083 }
00084 FixedCapacityVector(FixedCapacityVector const& rhs){
00085 ptr= &*begin()+rhs.size();
00086 std::uninitialized_copy(rhs.begin(),rhs.end(),begin());
00087 }
00088 FixedCapacityVector& operator=(FixedCapacityVector const& rhs){
00089 if (this == &rhs)
00090 return *this;
00091
00092 if(size()>rhs.size()){
00093 iterator it=std::copy(rhs.begin(),rhs.end(),begin());
00094 destroy(it,end());
00095 }
00096 else{
00097 iterator it=std::copy(&(rhs.elements()[0]),
00098 &(rhs.elements()[0])+size(),begin());
00099 std::uninitialized_copy(&(rhs.elements()[0])+size(),
00100 &(rhs.elements()[0])+rhs.size(),it);
00101 }
00102 ptr= &*begin()+rhs.size();
00103 return *this;
00104 }
00105
00106 T& operator[] (size_t i)
00107 {
00108 assert(i <= size());
00109 return elements()[i];
00110 }
00111
00112 iterator begin() { return &elements()[0]; }
00113 iterator end() { return static_cast<iterator>(ptr); }
00114
00115 T& front() { return *begin(); }
00116 T& back() { return *(end() - 1); }
00117
00118 void push_back(const T& e)
00119 {
00120 assert(size() < Capacity);
00121 construct(ptr,e);
00122 ++ptr;
00123 }
00124 template <class RangeIterator>
00125 void push_back(const RangeIterator& first, const RangeIterator& last);
00126 void pop_back() {
00127 --ptr;
00128 destroy(ptr+1);
00129 }
00130 void clear() {
00131 size_t s=size();
00132 ptr= &(elements()[0]);
00133
00134 destroy(begin(),begin()+(int)s);
00135 }
00136 void resize(size_t new_length)
00137 {
00138 while (size() < new_length)
00139 push_back(T());
00140 if (new_length < size()) {
00141 destroy(begin()+(int)new_length,end());
00142 ptr= &(elements()[new_length]);
00143 }
00144 }
00145
00146 void erase(const T& e)
00147 {
00148 const iterator new_end = std::remove(begin(), end(), e);
00149 ptr= &*new_end;
00150 destroy(new_end,end());
00151 }
00152
00154 void unique()
00155 {
00156 std::sort(begin(),end());
00157 iterator last = std::unique(begin(), end());
00158 ptr = &*last;
00159 destroy(last,end());
00160 }
00161
00162 size_t size() const { return ptr-&*begin(); }
00163 bool empty() const { return ptr==&*begin(); }
00164 size_t capacity() const { return Capacity; }
00165
00166 T const& operator[] (size_t i) const
00167 {
00168 assert(i < size());
00169 return elements()[i];
00170 }
00171 const_iterator begin() const { return &elements()[0]; }
00172 const_iterator end() const { return ptr; }
00173
00174 const T& front() const { return *begin(); }
00175 const T& back() const { return *(end() - 1); }
00176
00177 bool isMember(const T& e, const_iterator first, const_iterator last) const
00178 {
00179 return std::find(first, last, e) != last;
00180 }
00181 bool isMember(const T& e) const
00182 {
00183 return isMember(e, begin(), end());
00184 }
00185 FixedCapacityVectorPushBack<T> pushBackHelper()
00186 {
00187 return FixedCapacityVectorPushBack<T>
00188 (&ptr, &*begin()+Capacity);
00189 }
00190 };
00191 template <typename T, size_t C> inline
00192 bool operator==(const FixedCapacityVector<T,C>& l, const FixedCapacityVector<T,C>& r)
00193 {
00194 return l.size() == r.size() && std::equal(l.begin(), l.end(), r.begin());
00195 }
00196 template <typename T, size_t C> inline
00197 bool operator<(const FixedCapacityVector<T,C>& l, const FixedCapacityVector<T,C>& r)
00198 {
00199 return std::lexicographical_compare(l.begin(), l.end(), r.begin(), r.end());
00200 }
00201 }
00202 using misc::FixedCapacityVector;
00203 using misc::FixedCapacityVectorPushBack;
00204 }
00205
00206 template <typename T, size_t Capacity>
00207 template <class RangeIterator>
00208 void osl::misc::FixedCapacityVector<T,Capacity>::push_back(const RangeIterator& first, const RangeIterator& last)
00209 {
00210 iterator insert_point = end();
00211 std::uninitialized_copy(first, last, insert_point);
00212 ptr += last-first;
00213 assert(size() <= Capacity);
00214 }
00215
00216
00217 #endif
00218
00219
00220
00221