stlab.adobe.com Adobe Systems Incorporated

vector.hpp

Go to the documentation of this file.
00001 /*
00002     Copyright 2005-2007 Adobe Systems Incorporated
00003     Distributed under the MIT License (see accompanying file LICENSE_1_0_0.txt
00004     or a copy at http://stlab.adobe.com/licenses.html)
00005 */
00006 
00007 /*************************************************************************************************/
00008 
00009 #ifndef ADOBE_VECTOR_HPP
00010 #define ADOBE_VECTOR_HPP
00011 
00012 /*************************************************************************************************/
00013 
00014 #include <adobe/config.hpp>
00015 
00016 #include <adobe/vector_fwd.hpp>
00017 
00018 #include <algorithm>
00019 #include <cassert>
00020 #include <cstddef>
00021 #include <iterator>
00022 #include <memory>
00023 
00024 #include <boost/operators.hpp>
00025 #include <boost/static_assert.hpp>
00026 #include <boost/type_traits/has_nothrow_constructor.hpp>
00027 #include <boost/type_traits/is_integral.hpp>
00028 #include <boost/utility/enable_if.hpp>
00029 
00030 #include <adobe/empty.hpp>
00031 #include <adobe/typeinfo.hpp>
00032 #include <adobe/memory.hpp>
00033 #include <adobe/algorithm/minmax.hpp>
00034 
00035 #include <adobe/move.hpp>
00036 #include <adobe/implementation/swap.hpp>
00037 
00038 #ifdef ADOBE_STD_SERIALIZATION
00039 #include <adobe/iomanip.hpp>
00040 #endif
00041 
00042 /*************************************************************************************************/
00043 
00044 namespace adobe {
00045 namespace version_1 {
00046 
00053 /*************************************************************************************************/
00054 
00056 template <typename T,   // T models Regular
00057           typename A>   // A models Allocator(T)
00058 class vector : boost::totally_ordered<vector<T, A>, vector<T, A> >
00059 {
00060  public:
00061     typedef T&                              reference;
00062     typedef const T&                        const_reference;
00063     typedef T*                              iterator;
00064     typedef const T*                        const_iterator;
00065     typedef std::size_t                     size_type;
00066     typedef std::ptrdiff_t                  difference_type;
00067     typedef T                               value_type;
00068     typedef A                               allocator_type;
00069     typedef T*                              pointer;
00070     typedef const T*                        const_pointer;
00071     typedef std::reverse_iterator<T*>       reverse_iterator;
00072     typedef std::reverse_iterator<const T*> const_reverse_iterator;
00073     
00074  private:
00075     struct header_t
00076     {
00077         struct compact_header_t
00078         {
00079             boost::compressed_pair<A, T*> allocate_finish_m;
00080             T* end_of_storage_m;
00081         };
00082         aligned_storage<compact_header_t> header_m;
00083         T  storage_m[1];
00084 
00085         allocator_type& allocator() { return header_m.get().allocate_finish_m.first(); }
00086         const allocator_type& allocator() const { return header_m.get().allocate_finish_m.first(); }
00087 
00088         pointer& finish() { return header_m.get().allocate_finish_m.second(); }
00089         const pointer& finish() const { return header_m.get().allocate_finish_m.second(); }
00090 
00091         pointer& end_of_storage() { return header_m.get().end_of_storage_m; }
00092         const pointer& end_of_storage() const { return header_m.get().end_of_storage_m; }
00093     };
00094 
00095     header_t* header_m;
00096     
00097     void set_finish(T* x)
00098     {
00099         assert(header_m != 0 || x == 0);
00100         if (header_m) header_m->finish() = x;
00101     }
00102     
00103     const T* end_of_storage() const { return header_m ? header_m->end_of_storage() : 0; }
00104     
00105     static header_t* allocate(allocator_type, std::size_t);
00106     
00107     size_type remaining() const { return end_of_storage() - end(); }
00108     
00109     template <typename I> // I models InputIterator
00110     void append(I f, I l) { append(f, l, typename std::iterator_traits<I>::iterator_category()); }
00111     
00112     template <typename I> // I models InputIterator
00113     void append(I f, I l, std::input_iterator_tag);
00114     
00115     template <typename I> // I models ForwardIterator
00116     void append(I f, I l, std::forward_iterator_tag);
00117     
00118     template <typename I> // I models InputIterator
00119     void move_append(I f, I l)
00120     { move_append(f, l, typename std::iterator_traits<I>::iterator_category()); }
00121     
00122     template <typename I> // I models InputIterator
00123     void move_append(I f, I l, std::input_iterator_tag);
00124     
00125     template <typename I> // I models ForwardIterator
00126     void move_append(I f, I l, std::forward_iterator_tag);
00127     
00128     template <typename I> // I models InputIterator
00129     iterator insert(iterator p, I f, I l, std::input_iterator_tag);
00130     
00131     template <typename I> // I models ForwardIterator
00132     iterator insert(iterator p, I f, I l, std::forward_iterator_tag);
00133    
00134  public:
00135     // 23.2.4.1 construct/copy/destroy
00136 
00137     explicit vector(const allocator_type& a) : header_m(allocate(a, 0)) { }
00138     vector() : header_m(0) { }
00139     
00140     explicit vector(size_type n) : header_m(allocate(allocator_type(), n))
00141     {
00142         std::uninitialized_fill_n(end(), n, value_type());
00143         set_finish(end() + n);
00144     }
00145     
00146     vector(size_type n, const value_type& x) : header_m(allocate(allocator_type(), n))
00147     {
00148         std::uninitialized_fill_n(end(), n, x);
00149         set_finish(end() + n);
00150     }
00151 
00152     vector(size_type n, const value_type& x, const allocator_type& a) : header_m(allocate(a, n))
00153     {
00154         std::uninitialized_fill_n(end(), n, x);
00155         set_finish(end() + n);
00156     }
00157 
00158     vector(const vector& x) : header_m(allocate(x.get_allocator(), x.size()))
00159     {
00160 #ifndef NDEBUG
00161     /* REVISIT (sparent) : MS stupid "safety check" doesn't known about empty ranges. */
00162         set_finish(x.begin() == x.end() ? end() : std::uninitialized_copy(x.begin(), x.end(), end()));
00163 #else
00164         set_finish(std::uninitialized_copy(x.begin(), x.end(), end()));
00165 #endif
00166     }
00167 
00168     template <typename I> // I models InputIterator
00169     vector(I f, I l, typename boost::disable_if<boost::is_integral<I> >::type* = 0) : header_m(0)
00170     { append(f, l); }
00171 
00172     template <typename I> // I models InputIterator
00173     vector(I f, I l, const allocator_type& a,
00174         typename boost::disable_if<boost::is_integral<I> >::type* = 0) : header_m(allocate(a), 0)
00175     { append(f, l); }
00176 
00177     ~vector() {
00178         if (header_m) {
00179             clear();
00180 
00181             typename allocator_type::template rebind<char>::other alloc(get_allocator());
00182             alloc.deallocate(reinterpret_cast<char*>(header_m),
00183                 (end_of_storage() - begin()) * sizeof(T) + (sizeof(header_t) - sizeof(T)));
00184         }
00185     }
00186 
00187     // adobe addition
00188     
00189     vector(move_from<vector> x) : header_m(x.source.header_m) { x.source.header_m = 0; }
00190 
00191     allocator_type get_allocator() const
00192     { return header_m ? header_m->allocator() : allocator_type(); }
00193     
00194     iterator begin() { return header_m ? &header_m->storage_m[0] : 0; }
00195     iterator end() { return header_m ? header_m->finish() : 0; }
00196     
00197     const_iterator begin() const { return header_m ? &header_m->storage_m[0] : 0; }
00198     const_iterator end() const { return header_m ? header_m->finish() : 0; }
00199     
00200     reverse_iterator rbegin() { return reverse_iterator(end()); }
00201     reverse_iterator rend() { return reverse_iterator(begin()); }
00202     
00203     const_reverse_iterator rbegin() const { return const_reverse_iterator(end()); }
00204     const_reverse_iterator rend() const { return const_reverse_iterator(begin()); }
00205     
00206     size_type size() const { return size_type(end() - begin()); }
00207     size_type max_size() const { return size_type(-1) / sizeof(value_type); }
00208     
00209     size_type capacity() const { return size_type(end_of_storage() - begin()); }
00210     bool empty() const { return begin() == end(); }
00211     
00212     reference operator[](size_type n) { assert(n < size()); return *(begin() + n); }
00213     const_reference operator[](size_type n) const { assert(n < size()); return *(begin() + n); }
00214     
00215     /*
00216         REVISIT (sparent@adobe.com): at() explicitly omitted because it pulls in out_of_range
00217         which inherits from logic_error and uses std::string.
00218     */
00219     
00220     vector& operator=(vector x) { swap(x); return *this; }
00221     
00222 #if 0
00223     template <typename I> // I models ForwardIterator
00224     vector(I f, I l, move_ctor) : header_m(0)
00225     { move_append(f, l); }
00226 
00227 #endif
00228     
00229     void reserve(size_type n);
00230     
00231     reference front() { assert(!empty()); return *begin(); }
00232     const_reference front() const { assert(!empty()); return *begin(); }
00233     
00234     reference back() { assert(!empty()); return *(end() - 1); }
00235     const_reference back() const { assert(!empty()); return *(end() - 1); }
00236     
00237     template <typename U>
00238     void push_back(const U& x,  typename copy_sink<U, T>::type = 0)
00239     {
00240         if (remaining()) {
00241             construct<value_type>(end(), x);
00242         } else {
00243             value_type tmp(x); // copy in case the reallocation moves the object
00244             reserve(size() ? 2 * size() : 1);
00245             construct(end(), tmp);
00246         }
00247         set_finish(end() + 1);
00248     }
00249     
00250     template <typename U>
00251     void push_back(U x, typename move_sink<U, T>::type = 0)
00252     { move_append(&x, &x + 1); }
00253     
00254     void pop_back() { assert(!empty()); resize(size() - 1); }
00255     
00256     void swap(vector& x) { std::swap(header_m, x.header_m); }
00257     
00258     template <typename U>
00259     iterator insert(iterator p, const U& x, typename copy_sink<U, T>::type = 0)
00260     {
00261         if (remaining()) return insert(p, &x, &x + 1);
00262         else { value_type tmp(x); return insert(p, &tmp, &tmp + 1); }
00263     }
00264     
00265     template <typename U>
00266     iterator insert(iterator p, U x, typename move_sink<U, T>::type = 0)
00267     { return move_insert(p, &x, &x + 1); }
00268     
00269     template <typename I> // I models InputIterator
00270     iterator insert(iterator p, I f, I l, typename boost::disable_if<boost::is_integral<I> >::type* = 0)
00271     { return insert(p, f, l, typename std::iterator_traits<I>::iterator_category()); }
00272     
00273     template <typename I> // I models ForwardIterator
00274     iterator move_insert(iterator p, I f, I l);
00275     
00276     iterator insert(iterator p, size_type n, const T& x);
00277     
00278     iterator erase(iterator pos) { assert(pos != end()); return erase(pos, pos + 1); }
00279     
00280     iterator erase(iterator f, iterator l);
00281     
00282     void clear() { erase(begin(), end()); }
00283     
00284     void resize(size_type n);
00285     
00286     void resize(size_type n, const value_type& x);
00287     
00288     friend inline bool operator==(const vector& x, const vector& y)
00289     {
00290         return (x.size() == y.size()) && std::equal(x.begin(), x.end(), y.begin());
00291     }
00292     
00293     friend inline bool operator<(const vector& x, const vector& y)
00294     {
00295         return std::lexicographical_compare(x.begin(), x.end(), y.begin(), y.end());
00296     }
00297     
00298     friend inline void swap(vector& x, vector& y) { x.swap(y); }
00299 };
00300 
00301 template <typename T, typename A>
00302 typename vector<T, A>::header_t* vector<T, A>::allocate(allocator_type a, std::size_t n)
00303 {
00304     if (n == 0) {
00305         if (a == allocator_type()) return 0;
00306          n = 1;
00307     }
00308 
00309     typename allocator_type::template rebind<char>::other alloc(a);
00310 
00311     header_t* result = reinterpret_cast<header_t*>(alloc.allocate(sizeof(header_t) - sizeof(T)
00312             + n * sizeof(T)));
00313     construct(&result->allocator(), a);
00314     result->finish() = &result->storage_m[0];
00315     result->end_of_storage() = result->finish() + n;
00316     
00317     return result;
00318 }
00319 
00320 template <typename T, typename A>
00321 template <typename I> // I models InputIterator
00322 void vector<T, A>::append(I f, I l, std::input_iterator_tag) { while (f != l) { push_back(*f); ++f; } }
00323 
00324 template <typename T, typename A>
00325 template <typename I> // I models InputIterator
00326 void vector<T, A>::move_append(I f, I l, std::input_iterator_tag)
00327 { while (f != l) { push_back(move(*f)); ++f; } }
00328     
00329 template <typename T, typename A>
00330 template <typename I> // I models ForwardIterator
00331 void vector<T, A>::append(I f, I l, std::forward_iterator_tag)
00332 {
00333     size_type n(std::distance(f, l));
00334     
00335     if (remaining() < n) reserve((adobe::max)(size() + n, 2 * size()));
00336     set_finish(std::uninitialized_copy(f, l, end()));
00337 }
00338     
00339 template <typename T, typename A>
00340 template <typename I> // I models ForwardIterator
00341 void vector<T, A>::move_append(I f, I l, std::forward_iterator_tag)
00342 {
00343     size_type n(std::distance(f, l));
00344     
00345     if (remaining() < n) reserve((adobe::max)(size() + n, 2 * size()));
00346     set_finish(uninitialized_move(f, l, end()));
00347 }
00348     
00349 template <typename T, typename A>
00350 template <typename I> // I models InputIterator
00351 typename vector<T, A>::iterator vector<T, A>::insert(iterator p, I f, I l, std::input_iterator_tag)
00352 {
00353     size_type o(p - begin());
00354     size_type s = size();
00355     append(f, l);
00356     // REVISIT (sparent) : This could be a move based rotate
00357     std::rotate(begin() + o, begin() + s, end());
00358     return end() - s + o;
00359 }
00360     
00361 template <typename T, typename A>
00362 template <typename I> // I models ForwardIterator
00363 typename vector<T, A>::iterator vector<T, A>::insert(iterator p, I f, I l, std::forward_iterator_tag)
00364 {
00365     size_type n(std::distance(f, l));
00366     iterator  last = end();
00367     size_type before = p - begin();
00368 
00369     if (remaining() < n) {
00370         vector tmp;
00371         tmp.reserve((adobe::max)(size() + n, 2 * size()));
00372         tmp.move_append(begin(), p);
00373         tmp.append(f, l);
00374         tmp.move_append(p, last);
00375         swap(tmp);
00376     } else {
00377         size_type after(last - p);
00378         
00379         if (n < after) {
00380             move_append(last - n, last);
00381             move_backward(p, last - n, last);
00382             std::copy(f, l, p);
00383         } else {
00384             I m = f;
00385             std::advance(m, after);
00386             append(m, l);
00387             move_append(p, last);
00388             std::copy(f, m, p);
00389         }
00390     }
00391     return begin() + before + n;
00392 }
00393     
00394 template <typename T, typename A>
00395 template <typename I> // I models ForwardIterator
00396 typename vector<T, A>::iterator vector<T, A>::move_insert(iterator p, I f, I l)
00397 {
00398     size_type n(std::distance(f, l));
00399     iterator  last = end();
00400     size_type before = p - begin();
00401 
00402     if (remaining() < n) {
00403         vector tmp;
00404         tmp.reserve((adobe::max)(size() + n, 2 * size()));
00405         tmp.move_append(begin(), p);
00406         tmp.move_append(f, l);
00407         tmp.move_append(p, last);
00408         swap(tmp);
00409     } else {
00410         size_type after(last - p);
00411         
00412         if (n < after) {
00413             move_append(last - n, last);
00414             move_backward(p, last - n, last);
00415             move(f, l, p);
00416         } else {
00417             I m = f;
00418             std::advance(m, after);
00419             move_append(m, l);
00420             move_append(p, last);
00421             move(f, m, p);
00422         }
00423     }
00424     return begin() + before + n;
00425 }
00426 
00427 template <typename T, typename A>
00428 void vector<T, A>::reserve(size_type n)
00429 {
00430     if (capacity() < n) {
00431         vector tmp;
00432         tmp.header_m = allocate(get_allocator(), n);
00433         tmp.header_m->finish() = uninitialized_move(begin(), end(), tmp.end());
00434         swap(tmp);
00435     }
00436 }
00437 
00438 template <typename T, typename A>
00439 typename vector<T, A>::iterator vector<T, A>::insert(iterator p, size_type n, const T& x)
00440 {
00441     iterator  last = end();
00442     size_type before = p - begin();
00443 
00444     if (remaining() < n) {
00445         vector tmp;
00446         tmp.reserve((adobe::max)(size() + n, 2 * size()));
00447         tmp.move_append(begin(), p);
00448         std::uninitialized_fill_n(tmp.end(), n, x);
00449         tmp.set_finish(tmp.end() + n);
00450         tmp.move_append(p, last);
00451         swap(tmp);
00452     } else {
00453         size_type after(last - p);
00454         
00455         if (n < after) {
00456             move_append(last - n, last);
00457             move_backward(p, last - n, last);
00458             std::fill_n(p, n, x);
00459         } else {
00460             std::uninitialized_fill_n(last, n - after, x);
00461             set_finish(last + (n - after));
00462             move_append(p, last);
00463             std::fill_n(p, after, x);
00464         }
00465     }
00466     return begin() + before + n;
00467 }
00468     
00469 template <typename T, typename A>
00470 typename vector<T, A>::iterator vector<T, A>::erase(iterator f, iterator l)
00471 {
00472     iterator i = move(l, end(), f);
00473     for (iterator b(i), e(end()); b != e; ++b) {
00474         b->~value_type();
00475     }
00476     set_finish(i);
00477     return f;
00478 }
00479     
00480 template <typename T, typename A>
00481 void vector<T, A>::resize(size_type n)
00482 {
00483     if (n < size()) erase(begin() + n, end());
00484     else insert(end(), n - size(), value_type());
00485 }
00486     
00487 template <typename T, typename A>
00488 void vector<T, A>::resize(size_type n, const value_type& x)
00489 {
00490     if (n < size()) erase(begin() + n, end());
00491     else insert(end(), n - size(), x);
00492 }
00493 
00494 /*************************************************************************************************/
00495 
00496 #ifdef ADOBE_STD_SERIALIZATION
00497 
00498 template <typename T, typename A>
00499 std::ostream& operator<<(std::ostream& out, const vector<T, A>& x)
00500 {
00501     out << begin_sequence;
00502     
00503     for (typename vector<T, A>::const_iterator first(x.begin()), last(x.end()); first != last; ++first)
00504     {
00505         out << format(*first);
00506     }
00507     
00508     out << end_sequence;
00509     
00510     return out;
00511 }
00512 
00513 #endif
00514 
00515 /*************************************************************************************************/
00516 
00517 BOOST_STATIC_ASSERT(sizeof(vector<int>) == sizeof(void*));
00518 
00519 /*************************************************************************************************/
00520 
00521 } // namespace version_1
00522 } // namespace adobe
00523 
00524 /*************************************************************************************************/
00525 
00526 ADOBE_NAME_TYPE_1("vector:version_1:adobe", adobe::version_1::vector<T0,
00527         adobe::capture_allocator<T0> >)
00528 ADOBE_NAME_TYPE_2("vector:version_1:adobe", adobe::version_1::vector<T0, T1>)
00529 
00530 /*************************************************************************************************/
00531 
00532 namespace boost {
00533 
00534 template <typename T, typename A>
00535 struct has_nothrow_constructor<adobe::version_1::vector<T, A> > : boost::mpl::true_ { };
00536 
00537 } // namespace boost
00538 
00542 /*************************************************************************************************/
00543 
00544 #endif

Copyright © 2006-2007 Adobe Systems Incorporated.

Use of this website signifies your agreement to the Terms of Use and Online Privacy Policy.

Search powered by Google