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 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
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 }
00212 using misc::FixedCapacityVector;
00213 using misc::FixedCapacityVectorPushBack;
00214 }
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
00228
00229
00230
00231