This repository has been archived on 2026-01-16. You can view files and clone it, but you cannot make any changes to its state, such as pushing and creating new issues, pull requests or comments.
adobe-source-libraries/tmp/source_release/adobe/vector.hpp
2012-08-03 20:25:01 +02:00

520 lines
17 KiB
C++

/*
Copyright 2005-2007 Adobe Systems Incorporated
Distributed under the MIT License (see accompanying file LICENSE_1_0_0.txt
or a copy at http://stlab.adobe.com/licenses.html)
*/
/*************************************************************************************************/
#ifndef ADOBE_VECTOR_HPP
#define ADOBE_VECTOR_HPP
/*************************************************************************************************/
#include <adobe/config.hpp>
#include <adobe/vector_fwd.hpp>
#include <algorithm>
#include <cassert>
#include <cstddef>
#include <iterator>
#include <memory>
#include <boost/operators.hpp>
#include <boost/static_assert.hpp>
#include <boost/type_traits/has_nothrow_constructor.hpp>
#include <boost/type_traits/is_integral.hpp>
#include <boost/utility/enable_if.hpp>
#include <adobe/empty.hpp>
#include <adobe/typeinfo.hpp>
#include <adobe/memory.hpp>
#include <adobe/algorithm/minmax.hpp>
#include <adobe/move.hpp>
#include <adobe/implementation/swap.hpp>
#ifdef ADOBE_STD_SERIALIZATION
#include <adobe/iomanip.hpp>
#endif
/*************************************************************************************************/
namespace adobe {
namespace version_1 {
/*!
\defgroup container Containers
\ingroup asl_libraries
*/
/*************************************************************************************************/
//!\ingroup abi_container
template <typename T, // T models Regular
typename A> // A models Allocator(T)
class vector : boost::totally_ordered<vector<T, A>, vector<T, A> >
{
public:
typedef T& reference;
typedef const T& const_reference;
typedef T* iterator;
typedef const T* const_iterator;
typedef std::size_t size_type;
typedef std::ptrdiff_t difference_type;
typedef T value_type;
typedef A allocator_type;
typedef T* pointer;
typedef const T* const_pointer;
typedef std::reverse_iterator<T*> reverse_iterator;
typedef std::reverse_iterator<const T*> const_reverse_iterator;
private:
struct header_t
{
struct compact_header_t
{
boost::compressed_pair<A, T*> allocate_finish_m;
T* end_of_storage_m;
};
aligned_storage<compact_header_t> header_m;
T storage_m[1];
allocator_type& allocator() { return header_m.get().allocate_finish_m.first(); }
const allocator_type& allocator() const { return header_m.get().allocate_finish_m.first(); }
pointer& finish() { return header_m.get().allocate_finish_m.second(); }
const pointer& finish() const { return header_m.get().allocate_finish_m.second(); }
pointer& end_of_storage() { return header_m.get().end_of_storage_m; }
const pointer& end_of_storage() const { return header_m.get().end_of_storage_m; }
};
header_t* header_m;
void set_finish(T* x)
{
assert(header_m != 0 || x == 0);
if (header_m) header_m->finish() = x;
}
const T* end_of_storage() const { return header_m ? header_m->end_of_storage() : 0; }
static header_t* allocate(allocator_type, std::size_t);
size_type remaining() const { return end_of_storage() - end(); }
template <typename I> // I models InputIterator
void append(I f, I l) { append(f, l, typename std::iterator_traits<I>::iterator_category()); }
template <typename I> // I models InputIterator
void append(I f, I l, std::input_iterator_tag);
template <typename I> // I models ForwardIterator
void append(I f, I l, std::forward_iterator_tag);
template <typename I> // I models InputIterator
void append_move(I f, I l)
{ append_move(f, l, typename std::iterator_traits<I>::iterator_category()); }
template <typename I> // I models InputIterator
void append_move(I f, I l, std::input_iterator_tag);
template <typename I> // I models ForwardIterator
void append_move(I f, I l, std::forward_iterator_tag);
template <typename I> // I models InputIterator
iterator insert(iterator p, I f, I l, std::input_iterator_tag);
template <typename I> // I models ForwardIterator
iterator insert(iterator p, I f, I l, std::forward_iterator_tag);
public:
// 23.2.4.1 construct/copy/destroy
explicit vector(const allocator_type& a) : header_m(allocate(a, 0)) { }
vector() : header_m(0) { }
explicit vector(size_type n) : header_m(allocate(allocator_type(), n))
{
std::uninitialized_fill_n(end(), n, value_type());
set_finish(end() + n);
}
vector(size_type n, const value_type& x) : header_m(allocate(allocator_type(), n))
{
std::uninitialized_fill_n(end(), n, x);
set_finish(end() + n);
}
vector(size_type n, const value_type& x, const allocator_type& a) : header_m(allocate(a, n))
{
std::uninitialized_fill_n(end(), n, x);
set_finish(end() + n);
}
vector(const vector& x) : header_m(allocate(x.get_allocator(), x.size()))
{
#ifndef NDEBUG
/* REVISIT (sparent) : MS stupid "safety check" doesn't known about empty ranges. */
set_finish(x.begin() == x.end() ? end() : std::uninitialized_copy(x.begin(), x.end(), end()));
#else
set_finish(std::uninitialized_copy(x.begin(), x.end(), end()));
#endif
}
template <typename I> // I models InputIterator
vector(I f, I l, typename boost::disable_if<boost::is_integral<I> >::type* = 0) : header_m(0)
{ append(f, l); }
template <typename I> // I models InputIterator
vector(I f, I l, const allocator_type& a,
typename boost::disable_if<boost::is_integral<I> >::type* = 0) : header_m(allocate(a), 0)
{ append(f, l); }
~vector() {
if (header_m) {
clear();
typename allocator_type::template rebind<char>::other alloc(get_allocator());
alloc.deallocate(reinterpret_cast<char*>(header_m),
(end_of_storage() - begin()) * sizeof(T) + (sizeof(header_t) - sizeof(T)));
}
}
// adobe addition
vector(move_from<vector> x) : header_m(x.source.header_m) { x.source.header_m = 0; }
allocator_type get_allocator() const
{ return header_m ? header_m->allocator() : allocator_type(); }
iterator begin() { return header_m ? &header_m->storage_m[0] : 0; }
iterator end() { return header_m ? header_m->finish() : 0; }
const_iterator begin() const { return header_m ? &header_m->storage_m[0] : 0; }
const_iterator end() const { return header_m ? header_m->finish() : 0; }
reverse_iterator rbegin() { return reverse_iterator(end()); }
reverse_iterator rend() { return reverse_iterator(begin()); }
const_reverse_iterator rbegin() const { return const_reverse_iterator(end()); }
const_reverse_iterator rend() const { return const_reverse_iterator(begin()); }
size_type size() const { return size_type(end() - begin()); }
size_type max_size() const { return size_type(-1) / sizeof(value_type); }
size_type capacity() const { return size_type(end_of_storage() - begin()); }
bool empty() const { return begin() == end(); }
reference operator[](size_type n) { assert(n < size()); return *(begin() + n); }
const_reference operator[](size_type n) const { assert(n < size()); return *(begin() + n); }
/*
REVISIT (sparent@adobe.com): at() explicitly omitted because it pulls in out_of_range
which inherits from logic_error and uses std::string.
*/
vector& operator=(vector x) { swap(x); return *this; }
void reserve(size_type n);
reference front() { assert(!empty()); return *begin(); }
const_reference front() const { assert(!empty()); return *begin(); }
reference back() { assert(!empty()); return *(end() - 1); }
const_reference back() const { assert(!empty()); return *(end() - 1); }
void push_back(value_type x)
{ append_move(&x, &x + 1); }
void pop_back() { assert(!empty()); resize(size() - 1); }
void swap(vector& x) { std::swap(header_m, x.header_m); }
iterator insert(iterator p, value_type x)
{ return insert_move(p, &x, &x + 1); }
template <typename I> // I models InputIterator
iterator insert(iterator p, I f, I l, typename boost::disable_if<boost::is_integral<I> >::type* = 0)
{ return insert(p, f, l, typename std::iterator_traits<I>::iterator_category()); }
template <typename I> // I models ForwardIterator
iterator insert_move(iterator p, I f, I l);
iterator insert(iterator p, size_type n, const T& x);
iterator erase(iterator pos) { assert(pos != end()); return erase(pos, pos + 1); }
iterator erase(iterator f, iterator l);
void clear() { erase(begin(), end()); }
void resize(size_type n);
void resize(size_type n, const value_type& x);
friend inline bool operator==(const vector& x, const vector& y)
{
#if defined(_MSC_VER) && _MSC_VER == 1600 && _ITERATOR_DEBUG_LEVEL != 0
return (x.size() == y.size()) && std::_Equal1(x.begin(), x.end(),
y.begin(), std::tr1::false_type());
#else
return (x.size() == y.size()) && std::equal(x.begin(), x.end(), y.begin());
#endif
}
friend inline bool operator<(const vector& x, const vector& y)
{
return std::lexicographical_compare(x.begin(), x.end(), y.begin(), y.end());
}
friend inline void swap(vector& x, vector& y) { x.swap(y); }
};
template <typename T, typename A>
typename vector<T, A>::header_t* vector<T, A>::allocate(allocator_type a, std::size_t n)
{
if (n == 0) {
if (a == allocator_type()) return 0;
n = 1;
}
typename allocator_type::template rebind<char>::other alloc(a);
header_t* result = reinterpret_cast<header_t*>(alloc.allocate(sizeof(header_t) - sizeof(T)
+ n * sizeof(T)));
construct(&result->allocator(), a);
result->finish() = &result->storage_m[0];
result->end_of_storage() = result->finish() + n;
return result;
}
template <typename T, typename A>
template <typename I> // I models InputIterator
void vector<T, A>::append(I f, I l, std::input_iterator_tag) { while (f != l) { push_back(*f); ++f; } }
template <typename T, typename A>
template <typename I> // I models InputIterator
void vector<T, A>::append_move(I f, I l, std::input_iterator_tag)
{ while (f != l) { push_back(adobe::move(*f)); ++f; } }
template <typename T, typename A>
template <typename I> // I models ForwardIterator
void vector<T, A>::append(I f, I l, std::forward_iterator_tag)
{
size_type n(std::distance(f, l));
if (remaining() < n) reserve((adobe::max)(size() + n, 2 * size()));
set_finish(std::uninitialized_copy(f, l, end()));
}
template <typename T, typename A>
template <typename I> // I models ForwardIterator
void vector<T, A>::append_move(I f, I l, std::forward_iterator_tag)
{
size_type n(std::distance(f, l));
if (remaining() < n) reserve((adobe::max)(size() + n, 2 * size()));
set_finish(adobe::uninitialized_move(f, l, end()));
}
template <typename T, typename A>
template <typename I> // I models InputIterator
typename vector<T, A>::iterator vector<T, A>::insert(iterator p, I f, I l, std::input_iterator_tag)
{
size_type o(p - begin());
size_type s = size();
append(f, l);
// REVISIT (sparent) : This could be a move based rotate
std::rotate(begin() + o, begin() + s, end());
return end() - s + o;
}
template <typename T, typename A>
template <typename I> // I models ForwardIterator
typename vector<T, A>::iterator vector<T, A>::insert(iterator p, I f, I l, std::forward_iterator_tag)
{
size_type n(std::distance(f, l));
iterator last = end();
size_type before = p - begin();
if (remaining() < n) {
vector tmp;
tmp.reserve((adobe::max)(size() + n, 2 * size()));
tmp.append_move(begin(), p);
tmp.append(f, l);
tmp.append_move(p, last);
swap(tmp);
} else {
size_type after(last - p);
if (n < after) {
append_move(last - n, last);
adobe::move_backward(p, last - n, last);
std::copy(f, l, p);
} else {
I m = f;
std::advance(m, after);
append(m, l);
append_move(p, last);
std::copy(f, m, p);
}
}
return begin() + before + n;
}
template <typename T, typename A>
template <typename I> // I models ForwardIterator
typename vector<T, A>::iterator vector<T, A>::insert_move(iterator p, I f, I l)
{
size_type n(std::distance(f, l));
iterator last = end();
size_type before = p - begin();
if (remaining() < n) {
vector tmp;
tmp.reserve((adobe::max)(size() + n, 2 * size()));
tmp.append_move(begin(), p);
tmp.append_move(f, l);
tmp.append_move(p, last);
swap(tmp);
} else {
size_type after(last - p);
if (n < after) {
append_move(last - n, last);
adobe::move_backward(p, last - n, last);
adobe::move(f, l, p);
} else {
I m = f;
std::advance(m, after);
append_move(m, l);
append_move(p, last);
adobe::move(f, m, p);
}
}
return begin() + before + n;
}
template <typename T, typename A>
void vector<T, A>::reserve(size_type n)
{
if (capacity() < n) {
vector tmp;
tmp.header_m = allocate(get_allocator(), n);
tmp.header_m->finish() = adobe::uninitialized_move(begin(), end(), tmp.end());
swap(tmp);
}
}
template <typename T, typename A>
typename vector<T, A>::iterator vector<T, A>::insert(iterator p, size_type n, const T& x)
{
iterator last = end();
size_type before = p - begin();
if (remaining() < n) {
vector tmp;
tmp.reserve((adobe::max)(size() + n, 2 * size()));
tmp.append_move(begin(), p);
std::uninitialized_fill_n(tmp.end(), n, x);
tmp.set_finish(tmp.end() + n);
tmp.append_move(p, last);
swap(tmp);
} else {
size_type after(last - p);
if (n < after) {
append_move(last - n, last);
adobe::move_backward(p, last - n, last);
std::fill_n(p, n, x);
} else {
std::uninitialized_fill_n(last, n - after, x);
set_finish(last + (n - after));
append_move(p, last);
std::fill_n(p, after, x);
}
}
return begin() + before + n;
}
template <typename T, typename A>
typename vector<T, A>::iterator vector<T, A>::erase(iterator f, iterator l)
{
iterator i = adobe::move(l, end(), f);
for (iterator b(i), e(end()); b != e; ++b) {
b->~value_type();
}
set_finish(i);
return f;
}
template <typename T, typename A>
void vector<T, A>::resize(size_type n)
{
if (n < size()) erase(begin() + n, end());
else insert(end(), n - size(), value_type());
}
template <typename T, typename A>
void vector<T, A>::resize(size_type n, const value_type& x)
{
if (n < size()) erase(begin() + n, end());
else insert(end(), n - size(), x);
}
/*************************************************************************************************/
#ifdef ADOBE_STD_SERIALIZATION
template <typename T, typename A>
std::ostream& operator<<(std::ostream& out, const vector<T, A>& x)
{
out << begin_sequence;
for (typename vector<T, A>::const_iterator first(x.begin()), last(x.end()); first != last; ++first)
{
out << format(*first);
}
out << end_sequence;
return out;
}
#endif
/*************************************************************************************************/
BOOST_STATIC_ASSERT(sizeof(vector<int>) == sizeof(void*));
/*************************************************************************************************/
} // namespace version_1
} // namespace adobe
/*************************************************************************************************/
ADOBE_NAME_TYPE_1("vector:version_1:adobe", adobe::version_1::vector<T0,
adobe::capture_allocator<T0> >)
ADOBE_NAME_TYPE_2("vector:version_1:adobe", adobe::version_1::vector<T0, T1>)
/*************************************************************************************************/
namespace boost {
template <typename T, typename A>
struct has_nothrow_constructor<adobe::version_1::vector<T, A> > : boost::mpl::true_ { };
} // namespace boost
/*!
@}
*/
/*************************************************************************************************/
#endif