From cf4af691c27084610a2cf50621ce4302ef6edd50 Mon Sep 17 00:00:00 2001 From: syntheticpp Date: Sat, 27 Aug 2005 10:22:04 +0000 Subject: [PATCH] adding yasli git-svn-id: svn://svn.code.sf.net/p/loki-lib/code/trunk@215 7ec92016-0320-0410-acc4-a06ded1c099a --- include/loki/yasli/platform.h | 76 +++ include/loki/yasli/random.h | 52 ++ include/loki/yasli/yasli_fill_iterator.h | 181 +++++++ include/loki/yasli/yasli_memory.h | 447 ++++++++++++++++++ include/loki/yasli/yasli_protocols.h | 113 +++++ include/loki/yasli/yasli_traits.h | 75 +++ include/loki/yasli/yasli_vector.h | 576 +++++++++++++++++++++++ 7 files changed, 1520 insertions(+) create mode 100755 include/loki/yasli/platform.h create mode 100755 include/loki/yasli/random.h create mode 100755 include/loki/yasli/yasli_fill_iterator.h create mode 100755 include/loki/yasli/yasli_memory.h create mode 100755 include/loki/yasli/yasli_protocols.h create mode 100755 include/loki/yasli/yasli_traits.h create mode 100755 include/loki/yasli/yasli_vector.h diff --git a/include/loki/yasli/platform.h b/include/loki/yasli/platform.h new file mode 100755 index 0000000..9d48f0f --- /dev/null +++ b/include/loki/yasli/platform.h @@ -0,0 +1,76 @@ +#ifndef YASLI_PLATFORM_H_ +#define YASLI_PLATFORM_H_ + +// Most conservative + +#define YASLI_HAS_EFFICIENT_MSIZE 0 +#define YASLI_REALLOC_AFTER_NEW 0 +#define YASLI_HAS_EXPAND 0 + +#include + +// Works on MSVC (all versions) +#if defined(_MSC_VER) + + #if defined(NDEBUG)//why only if ndebug? + #undef YASLI_REALLOC_AFTER_NEW//this is not used: what is it's intention? + #define YASLI_REALLOC_AFTER_NEW 1 + + #undef YASLI_HAS_EFFICIENT_MSIZE + #define YASLI_HAS_EFFICIENT_MSIZE 1 + #endif + + // On Wintel platforms, uninit pointers can be copied + #define YASLI_UNDEFINED_POINTERS_COPYABLE 1 + + namespace yasli_platform + { + inline size_t msize(const void *p) + { + return _msize(const_cast(p)); + } + } + + #undef YASLI_HAS_EXPAND + #define YASLI_HAS_EXPAND 1 + namespace yasli_platform + { + inline void* expand(const void *p, size_t s) + { + return _expand (const_cast(p), s); + } + } + +#elif defined(__MINGW32_VERSION) && !defined(RC_INVOKED) +//I havinclude Malloc.h in order to find whether this library is Mingw32 +//i.e. defines __MINGW32_VERSION, +//hmm, I really need to sort this out in earlier versions +//it was _STRICT_ANSI_ not RC_INVOKED but I don't know the details + #undef YASLI_HAS_EFFICIENT_MSIZE + #define YASLI_HAS_EFFICIENT_MSIZE 1 + namespace yasli_platform + { + inline size_t msize(const void *p) + { + return _msize(const_cast(p)); + } + } + + #undef YASLI_HAS_EXPAND + #define YASLI_HAS_EXPAND 1 + namespace yasli_platform + { + inline void* expand(const void *p, size_t s) + { + return _expand (const_cast(p), s); + } + } + + #define YASLI_UNDEFINED_POINTERS_COPYABLE 1 //well it appears to compile ok anyway +#endif + + + + + +#endif // YASLI_PLATFORM_H_ diff --git a/include/loki/yasli/random.h b/include/loki/yasli/random.h new file mode 100755 index 0000000..14c859c --- /dev/null +++ b/include/loki/yasli/random.h @@ -0,0 +1,52 @@ +#ifndef RANDOM_H_ +#define RANDOM_H_ + +#include + +class Random +{ + unsigned int seed_; +public: + Random(unsigned int seed = 0) + : seed_(seed ? seed : static_cast(std::time(0))) + { + } + unsigned short nextShort() + { + /* Use any number from this list for "a" + 18000 18030 18273 18513 18879 19074 19098 19164 19215 19584 + 19599 19950 20088 20508 20544 20664 20814 20970 21153 21243 + 21423 21723 21954 22125 22188 22293 22860 22938 22965 22974 + 23109 23124 23163 23208 23508 23520 23553 23658 23865 24114 + 24219 24660 24699 24864 24948 25023 25308 25443 26004 26088 + 26154 26550 26679 26838 27183 27258 27753 27795 27810 27834 + 27960 28320 28380 28689 28710 28794 28854 28959 28980 29013 + 29379 29889 30135 30345 30459 30714 30903 30963 31059 31083 + */ + static const unsigned int a = 18000; + return static_cast(seed_ = + a * (seed_ & 65535) + + (seed_ >> 16)); + } + + unsigned int nextUint() + { + return (unsigned int)nextShort() << (CHAR_BIT * sizeof(unsigned short)) | + nextShort(); + } + unsigned int nextUint(unsigned int high) + { + assert(high < ULONG_MAX - 1); + ++high; + const unsigned int bucket_size = ULONG_MAX / high; + unsigned int a; + do + { + a = nextUint() / bucket_size; + } + while (a >= high); + return a; + } +}; + +#endif // RANDOM_H_ diff --git a/include/loki/yasli/yasli_fill_iterator.h b/include/loki/yasli/yasli_fill_iterator.h new file mode 100755 index 0000000..37480b6 --- /dev/null +++ b/include/loki/yasli/yasli_fill_iterator.h @@ -0,0 +1,181 @@ +#ifndef YASLI_FILL_ITERATOR_H_ +#define YASLI_FILL_ITERATOR_H_ + +#include +#include + +namespace yasli_nstd +{ + template + class fill_iterator_base + : public std::iterator< + std::random_access_iterator_tag, + T, + ptrdiff_t, + T*, + T&> + { + }; + + template + class fill_iterator_base + : public std::iterator< + std::random_access_iterator_tag, + T, + ptrdiff_t, + T*, + T&> + { + }; + + template + class fill_iterator : public fill_iterator_base + { + T value_; + /*difference_type*/ ptrdiff_t count_;////////////////////////////////// + + public: + typedef std::ptrdiff_t difference_type; + typedef typename fill_iterator_base::pointer pointer; + typedef typename fill_iterator_base::reference reference; + //typedef iterator_type; + + fill_iterator() + { + } + + explicit fill_iterator(reference value, difference_type count = 0) + : value_(value), count_(count) + { + } + + template + fill_iterator(const fill_iterator& rhs) + : value_(rhs.value_), count_(rhs.count_) + { + } + + reference operator*() const + { + return value_; + } + + pointer operator->() const + { + return &**this; + } + + fill_iterator& operator++() + { + ++count_; + return *this; + } + + fill_iterator operator++(int) + { + fill_iterator it(*this); + ++*this; + return it; + } + + fill_iterator& operator--() + { + --count_; + return *this; + } + + fill_iterator operator--(int) + { + fill_iterator it(*this); + --*this; + return it; + } + + fill_iterator& operator+=(difference_type d) + { + count_ += d; + return *this; + } + + fill_iterator operator+(difference_type d) const + { + return fill_iterator(*this) += d; + } + + fill_iterator& operator-=(difference_type d) + { + count_ -= d; + return *this; + } + + fill_iterator operator-(difference_type d) const + { + return fill_iterator(*this) -= d; + } + + difference_type operator-(const fill_iterator& rhs) const + { + return count_ - rhs.count_; + } + + reference operator[](difference_type) const + { + return **this; + } + + template + bool operator==(const fill_iterator& rhs) const + { + return count_ == rhs.count_; + } + + }; + + template + inline fill_iterator operator+(D lhs, const fill_iterator& rhs) + { + return rhs + lhs; + } + + template + inline bool operator!=( + const fill_iterator& lhs, + const fill_iterator& rhs) + { // test for fill_iterator inequality + return !(lhs == rhs); + } + + template + inline bool operator<( + const fill_iterator& lhs, + const fill_iterator& rhs) + { + return lhs.count_ < rhs.count_; + } + + template + inline bool operator>( + const fill_iterator& lhs, + const fill_iterator& rhs) + { + return rhs < lhs; + } + + template + inline bool operator<=( + const fill_iterator& lhs, + const fill_iterator& rhs) + { + return !(rhs < lhs); + } + + template + inline bool operator>=( + const fill_iterator& lhs, + const fill_iterator& rhs) + { + return !(lhs < rhs); + } +} // namespace yasli_nstd + +#endif diff --git a/include/loki/yasli/yasli_memory.h b/include/loki/yasli/yasli_memory.h new file mode 100755 index 0000000..7ab0ea4 --- /dev/null +++ b/include/loki/yasli/yasli_memory.h @@ -0,0 +1,447 @@ +#ifndef YASLI_MEMORY_H_ +#define YASLI_MEMORY_H_ + +#include "yasli_traits.h" +#include "yasli_protocols.h"//! +#include +#include +#include //NOT A SAFE WAY TO INCLUDE IT + +namespace yasli { + + + // 20.4.1, the default allocator: + template class allocator; + template <> class allocator; + + // 20.4.1.2, allocator globals + template + bool operator==(const allocator&, const allocator&) throw() + { return true; } + + template + bool operator!=(const allocator&, const allocator&) throw() + { return false; } + + // 20.4.2, raw storage iterator: + // @@@ not defined, use the std one @@@ + //template class raw_storage_iterator; + + // 20.4.3, temporary buffers: + // @@@ not defined, use the std one @@@ + //template + //pair get_temporary_buffer(ptrdiff_t n); + // @@@ not defined, use the std one @@@ + // template + // void return_temporary_buffer(T* p); + + // 20.4.4, specialized algorithms: + template + ForwardIterator + uninitialized_copy(InputIterator first, InputIterator last, + ForwardIterator result); + + template + void uninitialized_fill_n(ForwardIterator first, Size n, const T& x); + // 20.4.5, pointers: + // @@@ not defined, use the std one @@@ + // template class auto_ptr; +} + +namespace yasli { + template class allocator; + // specialize for void: + template <> class allocator + { + public: + typedef void* pointer; + typedef const void* const_pointer; + // reference-to-void members are impossible. + typedef void value_type; + template struct rebind { typedef allocator other; }; + }; + + template class allocator + { + public: + typedef size_t size_type; + typedef std::ptrdiff_t difference_type; + typedef T* pointer; + typedef const T* const_pointer; + typedef T& reference; + typedef const T& const_reference; + typedef T value_type; + + template struct rebind { typedef allocator other; }; + allocator() throw() {} + allocator(const allocator&) throw() {} + template allocator(const allocator&) throw() {} + ~allocator() throw() {} + pointer address(reference x) const { return &x; } + const_pointer address(const_reference x) { return &x; } + pointer allocate(size_type n, allocator::const_pointer = 0) + { + return static_cast(::operator new(n * sizeof(T))); + } + void deallocate(pointer p, size_type) + { + ::operator delete(p); + } + size_type max_size() const throw() + { + return size_type(-1); + } + void construct(pointer p, const T& val) + { + new((void *) p) T(val); + } + void destroy(pointer p) + { + ((T*) p)->~T(); + } + }; +} // namespace yasli + +namespace yasli_nstd +{ + template class mallocator + { + public: + typedef size_t size_type; + typedef ptrdiff_t difference_type; + typedef T* pointer; + typedef const T* const_pointer; + typedef T& reference; + typedef const T& const_reference; + typedef T value_type; + + template struct rebind { typedef mallocator other; }; + mallocator() throw() {} + mallocator(const mallocator&) throw() {} + template mallocator(const mallocator&) throw() {} + ~mallocator() throw() {} + pointer address(reference x) const { return &x; } + const_pointer address(const_reference x) { return &x; } + pointer allocate(size_type n, yasli::allocator::const_pointer = 0) + { + return static_cast(malloc(n * sizeof(T))); + } + void deallocate(pointer p, size_type) + { + free(p); + } + size_type max_size() const throw() + { + return size_type(-1); + } + void construct(pointer p, const T& val) + { + new((void *) p) T(val); + } + void destroy(pointer p) + { + ((T*) p)->~T(); + } + }; + + //--------------destroy-------- + + namespace _impl + { + struct non_destroyer + { + template + static void destroy(A& a, T* p, typename A::size_type n) {} + + template + static void destroy_range(ForwardIterator b, ForwardIterator e) {} + }; + + struct destroyer + { + template + static void destroy(A& a, T* p, typename A::size_type n) + { + const typename A::pointer p1 = p + n; + for (; p < p1; ++p) a.destroy(p); + } + + template + static void destroy_range(ForwardIterator b, ForwardIterator e) + { + typedef typename std::iterator_traits::value_type + value_type; + for (; b != e; ++b) (*b).~value_type(); + } + }; + } + + template + void destroy(A& a, T* p, typename A::size_type n) + { + yasli_nstd::type_selector::value != 0, + _impl::destroyer, + _impl::non_destroyer + >::result::destroy(a, p, n); + } + + template + void destroy_range(ForwardIterator b, ForwardIterator e) + { + yasli_nstd::type_selector< + yasli_nstd::is_class + ::value_type>::value != 0, + _impl::destroyer, + _impl::non_destroyer + >::result::destroy_range(b, e); + } + + //--------------- + + + template + It2 uninitialized_move(It1 b, It1 e, It2 d) + { + return mojo::uninitialized_move(b, e, d); + } + + template + struct generic_allocator_traits + { + static typename A::pointer + reallocate( + A& a, + typename A::pointer b, + typename A::pointer e, + typename A::size_type newSize) + { + typename A::pointer p1 = a.allocate(newSize, b); + const typename A::size_type oldSize = e - b; + if (oldSize <= newSize) // expand + { + yasli_protocols::move_traits::destructive_move( + b, b + oldSize, p1); + } + else // shrink + { + yasli_protocols::move_traits::destructive_move( + b, b + newSize, p1); + yasli_nstd::destroy(a, b + newSize, oldSize - newSize); + } + a.deallocate(b, oldSize); + return p1; + } + + static bool reallocate_inplace( + A& a, + typename A::pointer b, + typename A::size_type newSize) + { + return false; + } + + private: + generic_allocator_traits(); + }; + + template + struct allocator_traits : public generic_allocator_traits + { + }; + + template + struct allocator_traits< yasli::allocator > + : public generic_allocator_traits< yasli::allocator > + { +#if YASLI_NEW_IS_MALLOC != 0 + + static bool reallocate_inplace( + A& a, + typename A::pointer b, + typename A::size_type newSize) + { + allocator_traits< yasli_nstd::mallocator > + ::reallocate_inplace(a, b, newSize); + } + + static typename yasli::allocator::pointer + reallocate( + yasli::allocator& a, + typename yasli::allocator::pointer b, + typename yasli::allocator::pointer e, + typename yasli::allocator::size_type newSize) + { + allocator_traits< yasli_nstd::mallocator > + ::reallocate(a, b, e, newSize); + } +#endif//yasli_new_is_malloc + }; + + template + struct allocator_traits< yasli_nstd::mallocator > + : public generic_allocator_traits< yasli_nstd::mallocator > + { +#if YASLI_HAS_EXPAND && YASLI_HAS_EFFICIENT_MSIZE + static bool reallocate_inplace( + yasli_nstd::mallocator& a, + typename yasli_nstd::mallocator::pointer b, + typename yasli_nstd::mallocator::size_type newSize) + { + if (b == 0) return malloc(newSize); + if (newSize == 0) {free(b); return false;} + return b == yasli_platform::expand(b, newSize) + && yasli_platform::msize(b) >= newSize; + } +#endif + static typename yasli_nstd::mallocator::pointer + reallocate( + yasli_nstd::mallocator& a, + typename yasli_nstd::mallocator::pointer b, + typename yasli_nstd::mallocator::pointer e, + typename yasli_nstd::mallocator::size_type newSize) + { + if (yasli_nstd::is_memmoveable::value) + { + return static_cast(realloc(b, newSize)); + } + if(reallocate_inplace(a, b, newSize)) return b; + return generic_allocator_traits< yasli_nstd::mallocator >:: + reallocate(a, b, e, newSize); + } + }; +} + +namespace yasli +{ + //Here is where type_selector is really much more ugly than + //enable_if. + + //----------------UNINIT COPY-------- + namespace _impl + { + //safe + template + struct uninitialized_safe_copier + { + static FwdItr execute(InputItr first, InputItr last, FwdItr result) + { + // + struct ScopeGuard + { + FwdItr begin; + FwdItr* current; + ~ScopeGuard() + { + if (!current) return; + FwdItr end = *current; + typedef typename std::iterator_traits::value_type T; + for (; begin != end; ++begin) (&*begin)->~T(); + } + } guard = { result, &result }; + for (; first != last; ++first, ++result) + new(&*result) typename std::iterator_traits::value_type(*first); + // commit + return result; + } + }; + + template + struct uninitialized_memcopier + { + static T* execute(const T* first, const T* last, T* result) + { + yasli_nstd::is_memcopyable::value; + const size_t s = last - first; + memmove(result, first, s * sizeof(T)); + return result + s; + } + }; + + }// _impl + + // @@@ TODO: specialize for yasli_nstd::fill_iterator + + template + FwdItr uninitialized_copy(InputItr first, InputItr last, FwdItr result) + { + std::cout<<"neither\n"; + return _impl::uninitialized_safe_copier::execute(first, last, result); + } + + template + T* uninitialized_copy(const T* first, const T* last, T* result) + { + std::cout<<"const\n"; + return yasli_nstd::type_selector::value != 0, + _impl::uninitialized_memcopier, + _impl::uninitialized_safe_copier + >::result::execute(first, last, result); + } + + template + T* uninitialized_copy(T* first, T* last, T* result) + { + std::cout<<"non-const\n"; + return uninitialized_copy(static_cast(first), + static_cast(last), result); + } + + //-------------------------UNINIT FILL------ + + template + void + uninitialized_fill(ForwardIterator first, ForwardIterator last, + const T& x) + { + struct ScopeGuard + { + ForwardIterator first; + ForwardIterator* pCrt; + ~ScopeGuard() + { + if (pCrt) yasli_nstd::destroy_range(first, *pCrt); + } + } guard = { first, &first }; + for (; first != last; ++first) + new(&*first) T(x); + // Commit + guard.pCrt = 0; + } + + template + void + uninitialized_fill(T* first, T* last, const U& x) + { + struct ScopeGuard + { + T* first; + T** pCrt; + ~ScopeGuard() + { + if (pCrt) yasli_nstd::destroy_range(first, *pCrt); + } + } guard = { first, &first }; + assert(first <= last); + switch ((last - first) & 7u) + { + case 0: + while (first != last) + { + new(first) T(x); ++first; + case 7: new(first) T(x); ++first; + case 6: new(first) T(x); ++first; + case 5: new(first) T(x); ++first; + case 4: new(first) T(x); ++first; + case 3: new(first) T(x); ++first; + case 2: new(first) T(x); ++first; + case 1: new(first) T(x); ++first; + assert(first <= last); + } + } + // Commit + guard.pCrt = 0; + } + +}// yasli + +#endif // YASLI_MEMORY_H_ diff --git a/include/loki/yasli/yasli_protocols.h b/include/loki/yasli/yasli_protocols.h new file mode 100755 index 0000000..191c308 --- /dev/null +++ b/include/loki/yasli/yasli_protocols.h @@ -0,0 +1,113 @@ +#ifndef YASLI_PROTOCOLS_H_ +#define YASLI_PROTOCOLS_H_ + +#include +#include +#include "yasli_memory.h" +#include + +namespace yasli_protocols +{ + + // Most conservative + template + struct safe_move_traits + { + static T* destructive_move( + T* begin, + T* end, + void* dest) + { + T* tdest = static_cast(dest); + typedef std::less ls; + assert(!ls()(tdest, end) || ls()(tdest, begin - (end - begin))); + tdest = /*yasli*/std::uninitialized_copy(begin, end, tdest); + if (yasli_nstd::is_class::value) + { + for (; begin != end; ++begin) + { + begin->~T(); + } + } + return tdest; + } + static T* nondestructive_move( + T* begin, + T* end, + void* dest) + { + T* d = static_cast(dest); + for (; begin != end; ++begin, ++d) + new(d) T(*begin); + return d; + } + static T* nondestructive_assign_move( + T* begin, + T* end, + T* dest) + { + if (begin <= dest && dest < end) + { + dest += end - begin; + T* const result = dest; + while (begin != end) + *--dest = *--end; + return result; + } + for (; begin != end; ++begin, ++dest) + *dest = *begin; + return dest; + } + }; + + + template + struct memmove_traits + { + static T* destructive_move( + T* begin, + T* end, + void* dest) + { + memmove(dest, begin, (end - begin) * sizeof(T)); + return static_cast(dest) + (end - begin); + }; + static T* nondestructive_move( + T* begin, + T* end, + void* dest) + { + memmove(dest, begin, (end - begin) * sizeof(T)); + return static_cast(dest) + (end - begin); + } + static T* nondestructive_assign_move( + T* begin, + T* end, + T* dest) + { + yasli_nstd::destroy_range(begin, end); + memmove(dest, begin, (end - begin) * sizeof(T)); + return static_cast(dest) + (end - begin); + } + }; + + // for nonspecialized classes, use safe_move_traits + template + struct move_traits: public + yasli_nstd::type_selector::value == 0, + memmove_traits, + safe_move_traits + >::result + {}; + + template + struct move_traits >:public + yasli_nstd::type_selector) == 2 * sizeof(T), + memmove_traits< std::complex >, + safe_move_traits< std::complex > + >::result + { + }; +} + +#endif // YASLI_PROTOCOLS_H_ diff --git a/include/loki/yasli/yasli_traits.h b/include/loki/yasli/yasli_traits.h new file mode 100755 index 0000000..9bdd860 --- /dev/null +++ b/include/loki/yasli/yasli_traits.h @@ -0,0 +1,75 @@ +#ifndef YASLI_TRAITS_H_ +#define YASLI_TRAITS_H_ + + +namespace yasli_nstd +{ + /* + template + struct enable_if {}; + + template + struct enable_if { typedef T type; }; + */ + + //!! TYPE SELECTORS + //Used in place of enable_if: + //not so neat or so versitile but they do compile + template + struct type_selector + { + typedef if_true result; + }; + + template + struct type_selector + { + typedef if_false result; + }; + + // Types for differentiating compile-time choices + typedef char (&yes_t)[1]; + typedef char (&no_t)[2]; + + // Credit goes to Boost; + // also found in the C++ Templates book by Vandevoorde and Josuttis + + //!! Wouldn't compile with these inside is_class + template + yes_t class_test(int U::*); + template + no_t class_test(...); + + template struct is_class + { + enum { value = (sizeof(class_test(0)) == sizeof(yes_t)) }; + }; + + template struct is_pointer + { + enum { value = false }; + }; + + template struct is_pointer + { + enum { value = true }; + }; + + template struct is_memcopyable + { + enum { value = int(!is_class::value) }; + }; + + + template struct is_memmoveable + { + enum { value = int(!is_class::value) }; + }; + + + // For moving + enum move_t { move }; + +} // namespace yasli_nstd + +#endif // YASLI_TRAITS_H_ diff --git a/include/loki/yasli/yasli_vector.h b/include/loki/yasli/yasli_vector.h new file mode 100755 index 0000000..2735e97 --- /dev/null +++ b/include/loki/yasli/yasli_vector.h @@ -0,0 +1,576 @@ +#include "platform.h" +#include "yasli_fill_iterator.h" +#include "yasli_memory.h" +#include "yasli_traits.h" +#include "yasli_protocols.h" +#include +#include +#include +#include + +namespace yasli +{ + template > + class vector; +} + +namespace yasli { + + template + class vector + { + struct ebo : public Allocator + { + T *beg_; + ebo() {} + ebo(const Allocator& a) : Allocator(a) {} + } ebo_; + T *end_; + T *eos_; + public: + // types: + typedef vector this_type;//not standard + typedef typename Allocator::reference reference; + typedef typename Allocator::const_reference const_reference; + typedef typename Allocator::pointer iterator; // See 23.1 + typedef typename Allocator::const_pointer const_iterator; // See 23.1 + typedef typename Allocator::size_type size_type; // See 23.1 + typedef typename Allocator::difference_type difference_type;// See 23.1 + typedef T value_type; + typedef Allocator allocator_type; + typedef typename Allocator::pointer pointer; + typedef typename Allocator::const_pointer const_pointer; + typedef std::reverse_iterator reverse_iterator; + typedef std::reverse_iterator const_reverse_iterator; + private: + void init_empty() + { + + #if YASLI_UNDEFINED_POINTERS_COPYABLE == 1 + end_ = ebo_.beg_; + eos_ = ebo_.beg_; + #else + ebo_.beg_ = 0; + end_ = 0; + eos_ = 0; + #endif + assert(empty()); + + } + + void init_move(vector& temp) + { + ebo_ = temp.ebo_; + end_ = temp.end_; + eos_ = temp.eos_; + temp.init_empty(); + } + + void init_fill(size_type n, const T& value, const Allocator& a) + { + // Will avoid catch (...) + vector temp(a); + temp.insert(temp.end(), n, value); + init_move(temp); + assert(size() == n); + } + + // 23.2.4.1 construct/copy/destroy: + template + void init(InputIterator first, InputIterator last, looks_like_itr, const Allocator& a) + { + vector temp(a); + temp.insert(temp.end(), first, last); + init_move(temp); + } + + template + void init(non_iterator n, non_iterator datum, Loki::Int2Type, + const Allocator& a) + { + init_fill((size_type)n, (const T&)datum, a); + } + + public: + vector() + { + init_empty(); + } + + explicit vector(const Allocator& a) + : ebo_(a) + { + init_empty(); + } + + explicit vector(size_type n, const T& value = T(), + const Allocator& a = Allocator()) + { + init_fill(n, value, a); + } + + //!! avoid enable_if + template + vector(InputIterator first, InputIterator last, const Allocator& a = Allocator()) + { + init(first, last, Loki::Int2Type< + yasli_nstd::is_class::value || + yasli_nstd::is_pointer::value >(), a); + } + + public: + vector(const vector& x) + { + vector temp(x.begin(), x.end(), x.ebo_); + init_move(temp); + } + + ~vector() + { + yasli_nstd::destroy(ebo_, ebo_.beg_, size()); + const size_type c = capacity(); + if (c != 0) ebo_.deallocate(ebo_.beg_, c); + } + + // Note pass by value + vector& operator=(vector temp) + { + temp.swap(*this); + return *this; + } + + template + void assign(InputIterator first, InputIterator last) + { + + assign_pre_impl(first, last, Loki::Int2Type::value||yasli_nstd:: + is_pointer::value>()); + } + + private://-------ASSIGN IMPLEMENTATION + template + void assign_pre_impl(InputIterator first, InputIterator last, looks_like_itr) + { + assign_impl(first, last, + std::iterator_traits::iterator_category()); + } + + template + void assign_pre_impl(InputIterator n, InputIterator datum, Loki::Int2Type) + { + assign((size_type) n, (const T&) datum); + } + + template + void assign_impl(InputIterator first, InputIterator last, std::input_iterator_tag) + { + for (iterator i = begin(); i != end(); ++i, ++first) + { + if (first == last) + { + resize(i - begin()); + return; + } + *i = *first; + } + // we filled up the vector, now insert the rest + insert(end(), first, last); + } + + template + void assign_impl(RanIt first, RanIt last, std::random_access_iterator_tag) + { + const typename std::iterator_traits::difference_type d = + last - first; + assert(d >= 0); + size_type newSize = size_type(d); + assert(newSize == d); // no funky iterators + reserve(newSize); + if (newSize >= size()) + { + const size_t delta = newSize - size(); + RanIt i = last - delta; + copy(first, i, ebo_.beg_); + insert(end(), i, last); + } + else + { + copy(first, last, ebo_.beg_); + resize(newSize); + } + assert(size() == newSize); + } + public: + void assign(size_type n, const T& u) + { + const size_type s = size(); + if (n <= s) + { + T* const newEnd = ebo_.beg_ + n; + fill(ebo_.beg_, newEnd, u); + yasli_nstd::destroy(ebo_, newEnd, s - n); + end_ = newEnd; + } + else + { + reserve(n); + T* const newEnd = ebo_.beg_ + n; + fill(ebo_.beg_, end_, u); + uninitialized_fill(end_, newEnd, u); + end_ = newEnd; + } + assert(size() == n); + assert(empty() || front() == back()); + } + + allocator_type get_allocator() const + { + return ebo_; + } + // iterators: + iterator begin() { return ebo_.beg_; } + const_iterator begin() const { return ebo_.beg_; } + iterator end() { return end_; } + const_iterator end() const { return end_; } + reverse_iterator rbegin() { return reverse_iterator(end()); } + const_reverse_iterator rbegin() const { return const_reverse_iterator(end()); } + reverse_iterator rend() { return reverse_iterator(begin()); } + const_reverse_iterator rend() const { return const_reverse_iterator(begin()); } + + // 23.2.4.2 capacity: + + size_type size() const { return end_ - ebo_.beg_; } + size_type max_size() const { return ebo_.max_size(); } + + void resize(size_type sz, T c = T()) + { + const size_type oldSz = size(); + if (oldSz >= sz) + { + erase(ebo_.beg_ + sz, end_); + } + else + { + reserve(sz); + uninitialized_fill(end_, end_ + (sz - oldSz), c); + end_ = ebo_.beg_ + sz; + } + assert(size() == sz); + } + private: + template + void resize_impl(size_type sz, T c) + { + } + public: + size_type capacity() const + { + return eos_ - ebo_.beg_; + } + bool empty() const + { + return ebo_.beg_ == end_; + } + void reserve(size_type n) + { + const size_type + s = size(), + c = capacity(); + if (c >= n) return; + if (capacity() == 0) + { + ebo_.beg_ = ebo_.allocate(n); + } + else + { + ebo_.beg_ = yasli_nstd::allocator_traits::reallocate( + ebo_, ebo_.beg_, end_, n); + } + end_ = ebo_.beg_ + s; + eos_ = ebo_.beg_ + n; + assert(capacity() >= n); + assert(size() == s); + } + bool reserve_inplace_nstd(size_type n) + { + if (capacity() >= n) return true; + if (!yasli_nstd::allocator_traits::reallocate_inplace( + ebo_, ebo_.beg_, n)) + { + return false; + } + eos_ = ebo_.beg_ + n; + return true; + } + // element access: + reference operator[](size_type n) + { + assert(n < size()); + return ebo_.beg_[n]; + } + const_reference operator[](size_type n) const + { + assert(n < size()); + return ebo_.beg_[n]; + } + const_reference at(size_type n) const + { + // Fix by Joseph Canedo + if (n >= size()) throw std::range_error("vector<>::at"); + return ebo_.beg_[n]; + } + reference at(size_type n) + { + // Fix by Joseph Canedo + if (n >= size()) throw std::range_error("vector<>::at"); + return ebo_.beg_[n]; + } + reference front() + { + assert(!empty()); + return *ebo_.beg_; + } + const_reference front() const + { + assert(!empty()); + return *ebo_.beg_; + } + reference back() + { + assert(!empty()); + return end_[-1]; + } + const_reference back() const + { + assert(!empty()); + return end_[-1]; + } + + private: + + void prepare_growth(size_type delta) + { + const size_type s = size(); + // @@@ todo: replace magic constant with something meaningful + const size_type smallThreshold = 8; + if (s < smallThreshold) + { + reserve(std::max(smallThreshold, delta)); + } + else + { + const size_type multiply = 3; + const size_type divide = 2; + const size_type suggestedSize = (s * multiply) / divide; + reserve(std::max(s + delta, suggestedSize)); + } + } + + public: + // 23.2.4.3 modifiers: + void push_back(const T& x) + { + if (size() == capacity()) + { + prepare_growth(1); + } + new(end_) T(x); + ++end_; + } + void pop_back() + { + assert(!empty()); + ebo_.destroy(--end_); + } + void move_back_nstd(T& x) + { + if (size() == capacity()) + { + prepare_growth(1); + } + yasli_protocols::move_traits::nondestructive_move(&x, &x + 1, end_); + } + + // 23.2.4.3 modifiers: + iterator insert(iterator position, const T& x) + { + // @@@ be smarter about this reservation + reserve(size() + 1); + const size_type pos = position - begin(); + insert(position, (size_type)1, x); + return ebo_.beg_ + pos; + } + void insert(iterator position, size_type n, const T& x) + { + insert(position, + yasli_nstd::fill_iterator(x), + yasli_nstd::fill_iterator(x, n) + ); + } + + template + void insert(iterator position, InputIterator first, InputIterator last) + { + insert_pre_impl(position, first, last, + Loki::Int2Type::value|| + yasli_nstd::is_pointer::value>()); + } + private: + template + void + insert_pre_impl(iterator position, InputIterator first, InputIterator last, + looks_like_iterator) + { + insert_impl(position, first, last, + typename std::iterator_traits::iterator_category()); + } + + template + void insert_pre_impl(iterator position, non_iterator n, non_iterator x, + Loki::Int2Type) + { //used if e.g. T is int and insert(itr, 10, 6) is called + insert(position, static_cast(n), + static_cast(x)); + } + + template + void insert_impl(iterator position, + InputIterator first, InputIterator last, std::input_iterator_tag) + { + for (; first != last; ++first) + { + position = insert(position, *first) + 1; + } + } + template + void insert_impl(iterator position, + FwdIterator first, FwdIterator last, std::forward_iterator_tag) + { + typedef yasli_protocols::move_traits mt; + + const typename std::iterator_traits::difference_type + count = std::distance(first, last); + + if (eos_ - end_ > count || reserve_inplace_nstd(size() + count)) // there's enough room + { + if (count > end_ - &*position) + { + // Step 1: fill the hole between end_ and position+count + FwdIterator i1 = first; + std::advance(i1, end_ - &*position); + FwdIterator i2 = i1; + std::advance(i2, &*position + count - end_);//why not i2 = first; advance(i2,count); + T* const oldEnd = end_; + end_ = copy(i1, i2, end_); + assert(end_ == &*position + count); + // Step 2: move existing data to the end + mt::nondestructive_move( + position, + oldEnd, + end_); + end_ = oldEnd + count; + // Step 3: copy in the remaining data + copy(first, i1, position); + } + else // simpler case + { + mt::nondestructive_move( + end_ - count, + end_, + end_); + end_ += count; + mt::nondestructive_assign_move( + position, + end_ - count, + position + count); + copy(first, last, position); + } + } + else + { + vector temp(ebo_); + temp.reserve(size() + count); + // The calls below won't cause infinite recursion + // because they will fall on the other branch + // of the if statement + temp.insert(temp.end(), begin(), position); + temp.insert(temp.end(), first, last); + temp.insert(temp.end(), position, end()); + assert(temp.size() == size() + count); + temp.swap(*this); + } + } + public: + + iterator erase(iterator position) + { + erase(position, position + 1); + return position; + } + iterator erase(iterator first, iterator last) + { + yasli_protocols::move_traits::nondestructive_assign_move( + last, end(), first); + Allocator& a = ebo_; + const size_type destroyed = last - first; + yasli_nstd::destroy(a, end_ - destroyed, destroyed); + end_ -= destroyed; + return first; + } + void swap(vector& rhs)//COULD DO THIS WITH LESS TEMPORARIES + { + std::swap(static_cast(ebo_), static_cast(rhs.ebo_)); + std::swap(ebo_.beg_, rhs.ebo_.beg_); + std::swap(end_, rhs.end_); + std::swap(eos_, rhs.eos_); + } + void clear() + { + Allocator& a = ebo_; + yasli_nstd::destroy(a, ebo_.beg_, size()); + end_ = ebo_.beg_; + } + };//vector + + + + template + bool operator==(const vector& x, + const vector& y); + template + bool operator< (const vector& x, + const vector& y); + template + bool operator!=(const vector& x, + const vector& y); + template + bool operator> (const vector& x, + const vector& y); + template + bool operator>=(const vector& x, + const vector& y); + template + bool operator<=(const vector& x, + const vector& y); + // specialized algorithms: + template + void swap(vector& x, vector& y); + +}//yasli + + + +namespace yasli_protocols +{ + template + struct move_traits< yasli::vector >:public + yasli_nstd::type_selector< + sizeof(yasli::vector) != (3 * sizeof(T*)), + memmove_traits< std::complex >, + safe_move_traits< std::complex > + >::result + { + }; +} +