adding yasli
git-svn-id: svn://svn.code.sf.net/p/loki-lib/code/trunk@215 7ec92016-0320-0410-acc4-a06ded1c099a
This commit is contained in:
parent
f994398a51
commit
cf4af691c2
7 changed files with 1520 additions and 0 deletions
76
include/loki/yasli/platform.h
Executable file
76
include/loki/yasli/platform.h
Executable file
|
@ -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 <malloc.h>
|
||||
|
||||
// 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<void*>(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<void*>(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<void*>(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<void*>(p), s);
|
||||
}
|
||||
}
|
||||
|
||||
#define YASLI_UNDEFINED_POINTERS_COPYABLE 1 //well it appears to compile ok anyway
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#endif // YASLI_PLATFORM_H_
|
52
include/loki/yasli/random.h
Executable file
52
include/loki/yasli/random.h
Executable file
|
@ -0,0 +1,52 @@
|
|||
#ifndef RANDOM_H_
|
||||
#define RANDOM_H_
|
||||
|
||||
#include <ctime>
|
||||
|
||||
class Random
|
||||
{
|
||||
unsigned int seed_;
|
||||
public:
|
||||
Random(unsigned int seed = 0)
|
||||
: seed_(seed ? seed : static_cast<unsigned int>(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<unsigned short>(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_
|
181
include/loki/yasli/yasli_fill_iterator.h
Executable file
181
include/loki/yasli/yasli_fill_iterator.h
Executable file
|
@ -0,0 +1,181 @@
|
|||
#ifndef YASLI_FILL_ITERATOR_H_
|
||||
#define YASLI_FILL_ITERATOR_H_
|
||||
|
||||
#include <iterator>
|
||||
#include <cstddef>
|
||||
|
||||
namespace yasli_nstd
|
||||
{
|
||||
template <class T>
|
||||
class fill_iterator_base
|
||||
: public std::iterator<
|
||||
std::random_access_iterator_tag,
|
||||
T,
|
||||
ptrdiff_t,
|
||||
T*,
|
||||
T&>
|
||||
{
|
||||
};
|
||||
|
||||
template <class T>
|
||||
class fill_iterator_base<T&>
|
||||
: public std::iterator<
|
||||
std::random_access_iterator_tag,
|
||||
T,
|
||||
ptrdiff_t,
|
||||
T*,
|
||||
T&>
|
||||
{
|
||||
};
|
||||
|
||||
template <class T>
|
||||
class fill_iterator : public fill_iterator_base<T>
|
||||
{
|
||||
T value_;
|
||||
/*difference_type*/ ptrdiff_t count_;//////////////////////////////////
|
||||
|
||||
public:
|
||||
typedef std::ptrdiff_t difference_type;
|
||||
typedef typename fill_iterator_base<T>::pointer pointer;
|
||||
typedef typename fill_iterator_base<T>::reference reference;
|
||||
//typedef iterator_type;
|
||||
|
||||
fill_iterator()
|
||||
{
|
||||
}
|
||||
|
||||
explicit fill_iterator(reference value, difference_type count = 0)
|
||||
: value_(value), count_(count)
|
||||
{
|
||||
}
|
||||
|
||||
template<class U>
|
||||
fill_iterator(const fill_iterator<U>& 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<T>& rhs) const
|
||||
{
|
||||
return count_ - rhs.count_;
|
||||
}
|
||||
|
||||
reference operator[](difference_type) const
|
||||
{
|
||||
return **this;
|
||||
}
|
||||
|
||||
template <class T2>
|
||||
bool operator==(const fill_iterator<T2>& rhs) const
|
||||
{
|
||||
return count_ == rhs.count_;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
template <class T, class D>
|
||||
inline fill_iterator<T> operator+(D lhs, const fill_iterator<T>& rhs)
|
||||
{
|
||||
return rhs + lhs;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline bool operator!=(
|
||||
const fill_iterator<T>& lhs,
|
||||
const fill_iterator<T>& rhs)
|
||||
{ // test for fill_iterator inequality
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline bool operator<(
|
||||
const fill_iterator<T>& lhs,
|
||||
const fill_iterator<T>& rhs)
|
||||
{
|
||||
return lhs.count_ < rhs.count_;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline bool operator>(
|
||||
const fill_iterator<T>& lhs,
|
||||
const fill_iterator<T>& rhs)
|
||||
{
|
||||
return rhs < lhs;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline bool operator<=(
|
||||
const fill_iterator<T>& lhs,
|
||||
const fill_iterator<T>& rhs)
|
||||
{
|
||||
return !(rhs < lhs);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline bool operator>=(
|
||||
const fill_iterator<T>& lhs,
|
||||
const fill_iterator<T>& rhs)
|
||||
{
|
||||
return !(lhs < rhs);
|
||||
}
|
||||
} // namespace yasli_nstd
|
||||
|
||||
#endif
|
447
include/loki/yasli/yasli_memory.h
Executable file
447
include/loki/yasli/yasli_memory.h
Executable file
|
@ -0,0 +1,447 @@
|
|||
#ifndef YASLI_MEMORY_H_
|
||||
#define YASLI_MEMORY_H_
|
||||
|
||||
#include "yasli_traits.h"
|
||||
#include "yasli_protocols.h"//!
|
||||
#include <cassert>
|
||||
#include <cstddef>
|
||||
#include <misc/mojo.h>//NOT A SAFE WAY TO INCLUDE IT
|
||||
|
||||
namespace yasli {
|
||||
|
||||
|
||||
// 20.4.1, the default allocator:
|
||||
template <class T> class allocator;
|
||||
template <> class allocator<void>;
|
||||
|
||||
// 20.4.1.2, allocator globals
|
||||
template <class T, class U>
|
||||
bool operator==(const allocator<T>&, const allocator<U>&) throw()
|
||||
{ return true; }
|
||||
|
||||
template <class T, class U>
|
||||
bool operator!=(const allocator<T>&, const allocator<U>&) throw()
|
||||
{ return false; }
|
||||
|
||||
// 20.4.2, raw storage iterator:
|
||||
// @@@ not defined, use the std one @@@
|
||||
//template <class OutputIterator, class T> class raw_storage_iterator;
|
||||
|
||||
// 20.4.3, temporary buffers:
|
||||
// @@@ not defined, use the std one @@@
|
||||
//template <class T>
|
||||
//pair<T*,ptrdiff_t> get_temporary_buffer(ptrdiff_t n);
|
||||
// @@@ not defined, use the std one @@@
|
||||
// template <class T>
|
||||
// void return_temporary_buffer(T* p);
|
||||
|
||||
// 20.4.4, specialized algorithms:
|
||||
template <class InputIterator, class ForwardIterator>
|
||||
ForwardIterator
|
||||
uninitialized_copy(InputIterator first, InputIterator last,
|
||||
ForwardIterator result);
|
||||
|
||||
template <class ForwardIterator, class Size, class T>
|
||||
void uninitialized_fill_n(ForwardIterator first, Size n, const T& x);
|
||||
// 20.4.5, pointers:
|
||||
// @@@ not defined, use the std one @@@
|
||||
// template<class X> class auto_ptr;
|
||||
}
|
||||
|
||||
namespace yasli {
|
||||
template <class T> class allocator;
|
||||
// specialize for void:
|
||||
template <> class allocator<void>
|
||||
{
|
||||
public:
|
||||
typedef void* pointer;
|
||||
typedef const void* const_pointer;
|
||||
// reference-to-void members are impossible.
|
||||
typedef void value_type;
|
||||
template <class U> struct rebind { typedef allocator<U> other; };
|
||||
};
|
||||
|
||||
template <class T> 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 <class U> struct rebind { typedef allocator<U> other; };
|
||||
allocator() throw() {}
|
||||
allocator(const allocator&) throw() {}
|
||||
template <class U> allocator(const allocator<U>&) throw() {}
|
||||
~allocator() throw() {}
|
||||
pointer address(reference x) const { return &x; }
|
||||
const_pointer address(const_reference x) { return &x; }
|
||||
pointer allocate(size_type n, allocator<void>::const_pointer = 0)
|
||||
{
|
||||
return static_cast<pointer>(::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 T> 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 <class U> struct rebind { typedef mallocator<U> other; };
|
||||
mallocator() throw() {}
|
||||
mallocator(const mallocator&) throw() {}
|
||||
template <class U> mallocator(const mallocator<U>&) 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<void>::const_pointer = 0)
|
||||
{
|
||||
return static_cast<pointer>(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 <class A, class T>
|
||||
static void destroy(A& a, T* p, typename A::size_type n) {}
|
||||
|
||||
template <class ForwardIterator>
|
||||
static void destroy_range(ForwardIterator b, ForwardIterator e) {}
|
||||
};
|
||||
|
||||
struct destroyer
|
||||
{
|
||||
template <class A, class T>
|
||||
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 <class ForwardIterator>
|
||||
static void destroy_range(ForwardIterator b, ForwardIterator e)
|
||||
{
|
||||
typedef typename std::iterator_traits<ForwardIterator>::value_type
|
||||
value_type;
|
||||
for (; b != e; ++b) (*b).~value_type();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
template <class A, class T>
|
||||
void destroy(A& a, T* p, typename A::size_type n)
|
||||
{
|
||||
yasli_nstd::type_selector<yasli_nstd::is_class<T>::value != 0,
|
||||
_impl::destroyer,
|
||||
_impl::non_destroyer
|
||||
>::result::destroy(a, p, n);
|
||||
}
|
||||
|
||||
template <class ForwardIterator>
|
||||
void destroy_range(ForwardIterator b, ForwardIterator e)
|
||||
{
|
||||
yasli_nstd::type_selector<
|
||||
yasli_nstd::is_class<typename std::iterator_traits<ForwardIterator>
|
||||
::value_type>::value != 0,
|
||||
_impl::destroyer,
|
||||
_impl::non_destroyer
|
||||
>::result::destroy_range(b, e);
|
||||
}
|
||||
|
||||
//---------------
|
||||
|
||||
|
||||
template <class It1, class It2>
|
||||
It2 uninitialized_move(It1 b, It1 e, It2 d)
|
||||
{
|
||||
return mojo::uninitialized_move(b, e, d);
|
||||
}
|
||||
|
||||
template <class A>
|
||||
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<typename A::value_type>::destructive_move(
|
||||
b, b + oldSize, p1);
|
||||
}
|
||||
else // shrink
|
||||
{
|
||||
yasli_protocols::move_traits<typename A::value_type>::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 <class A>
|
||||
struct allocator_traits : public generic_allocator_traits<A>
|
||||
{
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct allocator_traits< yasli::allocator<T> >
|
||||
: public generic_allocator_traits< yasli::allocator<T> >
|
||||
{
|
||||
#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<T> >
|
||||
::reallocate_inplace(a, b, newSize);
|
||||
}
|
||||
|
||||
static typename yasli::allocator<T>::pointer
|
||||
reallocate(
|
||||
yasli::allocator<T>& a,
|
||||
typename yasli::allocator<T>::pointer b,
|
||||
typename yasli::allocator<T>::pointer e,
|
||||
typename yasli::allocator<T>::size_type newSize)
|
||||
{
|
||||
allocator_traits< yasli_nstd::mallocator<T> >
|
||||
::reallocate(a, b, e, newSize);
|
||||
}
|
||||
#endif//yasli_new_is_malloc
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct allocator_traits< yasli_nstd::mallocator<T> >
|
||||
: public generic_allocator_traits< yasli_nstd::mallocator<T> >
|
||||
{
|
||||
#if YASLI_HAS_EXPAND && YASLI_HAS_EFFICIENT_MSIZE
|
||||
static bool reallocate_inplace(
|
||||
yasli_nstd::mallocator<T>& a,
|
||||
typename yasli_nstd::mallocator<T>::pointer b,
|
||||
typename yasli_nstd::mallocator<T>::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<T>::pointer
|
||||
reallocate(
|
||||
yasli_nstd::mallocator<T>& a,
|
||||
typename yasli_nstd::mallocator<T>::pointer b,
|
||||
typename yasli_nstd::mallocator<T>::pointer e,
|
||||
typename yasli_nstd::mallocator<T>::size_type newSize)
|
||||
{
|
||||
if (yasli_nstd::is_memmoveable<T>::value)
|
||||
{
|
||||
return static_cast<T*>(realloc(b, newSize));
|
||||
}
|
||||
if(reallocate_inplace(a, b, newSize)) return b;
|
||||
return generic_allocator_traits< yasli_nstd::mallocator<T> >::
|
||||
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 <class InputItr, class FwdItr>
|
||||
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<FwdItr>::value_type T;
|
||||
for (; begin != end; ++begin) (&*begin)->~T();
|
||||
}
|
||||
} guard = { result, &result };
|
||||
for (; first != last; ++first, ++result)
|
||||
new(&*result) typename std::iterator_traits<FwdItr>::value_type(*first);
|
||||
// commit
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct uninitialized_memcopier
|
||||
{
|
||||
static T* execute(const T* first, const T* last, T* result)
|
||||
{
|
||||
yasli_nstd::is_memcopyable<T>::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 <class InputItr, class FwdItr>
|
||||
FwdItr uninitialized_copy(InputItr first, InputItr last, FwdItr result)
|
||||
{
|
||||
std::cout<<"neither\n";
|
||||
return _impl::uninitialized_safe_copier<InputItr, FwdItr>::execute(first, last, result);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
T* uninitialized_copy(const T* first, const T* last, T* result)
|
||||
{
|
||||
std::cout<<"const\n";
|
||||
return yasli_nstd::type_selector<yasli_nstd::is_memcopyable<T>::value != 0,
|
||||
_impl::uninitialized_memcopier<T>,
|
||||
_impl::uninitialized_safe_copier<const T*, T*>
|
||||
>::result::execute(first, last, result);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
T* uninitialized_copy(T* first, T* last, T* result)
|
||||
{
|
||||
std::cout<<"non-const\n";
|
||||
return uninitialized_copy(static_cast<const T*>(first),
|
||||
static_cast<const T*>(last), result);
|
||||
}
|
||||
|
||||
//-------------------------UNINIT FILL------
|
||||
|
||||
template <class ForwardIterator, class T>
|
||||
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 <class T, class U>
|
||||
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_
|
113
include/loki/yasli/yasli_protocols.h
Executable file
113
include/loki/yasli/yasli_protocols.h
Executable file
|
@ -0,0 +1,113 @@
|
|||
#ifndef YASLI_PROTOCOLS_H_
|
||||
#define YASLI_PROTOCOLS_H_
|
||||
|
||||
#include <complex>
|
||||
#include <functional>
|
||||
#include "yasli_memory.h"
|
||||
#include <memory.h>
|
||||
|
||||
namespace yasli_protocols
|
||||
{
|
||||
|
||||
// Most conservative
|
||||
template <class T>
|
||||
struct safe_move_traits
|
||||
{
|
||||
static T* destructive_move(
|
||||
T* begin,
|
||||
T* end,
|
||||
void* dest)
|
||||
{
|
||||
T* tdest = static_cast<T*>(dest);
|
||||
typedef std::less<T*> ls;
|
||||
assert(!ls()(tdest, end) || ls()(tdest, begin - (end - begin)));
|
||||
tdest = /*yasli*/std::uninitialized_copy(begin, end, tdest);
|
||||
if (yasli_nstd::is_class<T>::value)
|
||||
{
|
||||
for (; begin != end; ++begin)
|
||||
{
|
||||
begin->~T();
|
||||
}
|
||||
}
|
||||
return tdest;
|
||||
}
|
||||
static T* nondestructive_move(
|
||||
T* begin,
|
||||
T* end,
|
||||
void* dest)
|
||||
{
|
||||
T* d = static_cast<T*>(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 <class T>
|
||||
struct memmove_traits
|
||||
{
|
||||
static T* destructive_move(
|
||||
T* begin,
|
||||
T* end,
|
||||
void* dest)
|
||||
{
|
||||
memmove(dest, begin, (end - begin) * sizeof(T));
|
||||
return static_cast<T*>(dest) + (end - begin);
|
||||
};
|
||||
static T* nondestructive_move(
|
||||
T* begin,
|
||||
T* end,
|
||||
void* dest)
|
||||
{
|
||||
memmove(dest, begin, (end - begin) * sizeof(T));
|
||||
return static_cast<T*>(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<T*>(dest) + (end - begin);
|
||||
}
|
||||
};
|
||||
|
||||
// for nonspecialized classes, use safe_move_traits
|
||||
template <class T>
|
||||
struct move_traits: public
|
||||
yasli_nstd::type_selector<yasli_nstd::is_class<T>::value == 0,
|
||||
memmove_traits<T>,
|
||||
safe_move_traits<T>
|
||||
>::result
|
||||
{};
|
||||
|
||||
template <class T>
|
||||
struct move_traits<std::complex<T> >:public
|
||||
yasli_nstd::type_selector<sizeof(std::complex<T>) == 2 * sizeof(T),
|
||||
memmove_traits< std::complex<T> >,
|
||||
safe_move_traits< std::complex<T> >
|
||||
>::result
|
||||
{
|
||||
};
|
||||
}
|
||||
|
||||
#endif // YASLI_PROTOCOLS_H_
|
75
include/loki/yasli/yasli_traits.h
Executable file
75
include/loki/yasli/yasli_traits.h
Executable file
|
@ -0,0 +1,75 @@
|
|||
#ifndef YASLI_TRAITS_H_
|
||||
#define YASLI_TRAITS_H_
|
||||
|
||||
|
||||
namespace yasli_nstd
|
||||
{
|
||||
/*
|
||||
template <bool b, class T = void>
|
||||
struct enable_if {};
|
||||
|
||||
template <class T>
|
||||
struct enable_if<true, T> { typedef T type; };
|
||||
*/
|
||||
|
||||
//!! TYPE SELECTORS
|
||||
//Used in place of enable_if:
|
||||
//not so neat or so versitile but they do compile
|
||||
template<bool condition, class if_true, class if_false>
|
||||
struct type_selector
|
||||
{
|
||||
typedef if_true result;
|
||||
};
|
||||
|
||||
template<class if_true, class if_false>
|
||||
struct type_selector<false, if_true, if_false>
|
||||
{
|
||||
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 <class U>
|
||||
yes_t class_test(int U::*);
|
||||
template <class U>
|
||||
no_t class_test(...);
|
||||
|
||||
template <class T> struct is_class
|
||||
{
|
||||
enum { value = (sizeof(class_test<T>(0)) == sizeof(yes_t)) };
|
||||
};
|
||||
|
||||
template <typename T> struct is_pointer
|
||||
{
|
||||
enum { value = false };
|
||||
};
|
||||
|
||||
template <typename T> struct is_pointer<T*>
|
||||
{
|
||||
enum { value = true };
|
||||
};
|
||||
|
||||
template <typename T> struct is_memcopyable
|
||||
{
|
||||
enum { value = int(!is_class<T>::value) };
|
||||
};
|
||||
|
||||
|
||||
template <typename T> struct is_memmoveable
|
||||
{
|
||||
enum { value = int(!is_class<T>::value) };
|
||||
};
|
||||
|
||||
|
||||
// For moving
|
||||
enum move_t { move };
|
||||
|
||||
} // namespace yasli_nstd
|
||||
|
||||
#endif // YASLI_TRAITS_H_
|
576
include/loki/yasli/yasli_vector.h
Executable file
576
include/loki/yasli/yasli_vector.h
Executable file
|
@ -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 <iterator>
|
||||
#include <cassert>
|
||||
#include <stdexcept>
|
||||
#include <Loki/TypeManip.h>
|
||||
|
||||
namespace yasli
|
||||
{
|
||||
template <class T, class Allocator = allocator<T> >
|
||||
class vector;
|
||||
}
|
||||
|
||||
namespace yasli {
|
||||
|
||||
template <class T, class Allocator>
|
||||
class vector
|
||||
{
|
||||
struct ebo : public Allocator
|
||||
{
|
||||
T *beg_;
|
||||
ebo() {}
|
||||
ebo(const Allocator& a) : Allocator(a) {}
|
||||
} ebo_;
|
||||
T *end_;
|
||||
T *eos_;
|
||||
public:
|
||||
// types:
|
||||
typedef vector<T, Allocator> 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<iterator> reverse_iterator;
|
||||
typedef std::reverse_iterator<const_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<T, Allocator> temp(a);
|
||||
temp.insert(temp.end(), n, value);
|
||||
init_move(temp);
|
||||
assert(size() == n);
|
||||
}
|
||||
|
||||
// 23.2.4.1 construct/copy/destroy:
|
||||
template <class InputIterator, class looks_like_itr>
|
||||
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 <class non_iterator>
|
||||
void init(non_iterator n, non_iterator datum, Loki::Int2Type<false>,
|
||||
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 <class InputIterator>
|
||||
vector(InputIterator first, InputIterator last, const Allocator& a = Allocator())
|
||||
{
|
||||
init(first, last, Loki::Int2Type<
|
||||
yasli_nstd::is_class<InputIterator>::value ||
|
||||
yasli_nstd::is_pointer<InputIterator>::value >(), a);
|
||||
}
|
||||
|
||||
public:
|
||||
vector(const vector<T,Allocator>& 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<T,Allocator>& operator=(vector<T,Allocator> temp)
|
||||
{
|
||||
temp.swap(*this);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class InputIterator>
|
||||
void assign(InputIterator first, InputIterator last)
|
||||
{
|
||||
|
||||
assign_pre_impl(first, last, Loki::Int2Type<yasli_nstd::
|
||||
is_class<InputIterator>::value||yasli_nstd::
|
||||
is_pointer<InputIterator>::value>());
|
||||
}
|
||||
|
||||
private://-------ASSIGN IMPLEMENTATION
|
||||
template <class InputIterator, class looks_like_itr>
|
||||
void assign_pre_impl(InputIterator first, InputIterator last, looks_like_itr)
|
||||
{
|
||||
assign_impl(first, last,
|
||||
std::iterator_traits<InputIterator>::iterator_category());
|
||||
}
|
||||
|
||||
template <class InputIterator>
|
||||
void assign_pre_impl(InputIterator n, InputIterator datum, Loki::Int2Type<false>)
|
||||
{
|
||||
assign((size_type) n, (const T&) datum);
|
||||
}
|
||||
|
||||
template <class InputIterator>
|
||||
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 <class RanIt>
|
||||
void assign_impl(RanIt first, RanIt last, std::random_access_iterator_tag)
|
||||
{
|
||||
const typename std::iterator_traits<RanIt>::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<class is>
|
||||
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<Allocator>::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<Allocator>::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<T>::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<const T&>(x),
|
||||
yasli_nstd::fill_iterator<const T&>(x, n)
|
||||
);
|
||||
}
|
||||
|
||||
template <class InputIterator>
|
||||
void insert(iterator position, InputIterator first, InputIterator last)
|
||||
{
|
||||
insert_pre_impl(position, first, last,
|
||||
Loki::Int2Type<yasli_nstd::is_class<InputIterator>::value||
|
||||
yasli_nstd::is_pointer<InputIterator>::value>());
|
||||
}
|
||||
private:
|
||||
template<class InputIterator, class looks_like_iterator>
|
||||
void
|
||||
insert_pre_impl(iterator position, InputIterator first, InputIterator last,
|
||||
looks_like_iterator)
|
||||
{
|
||||
insert_impl(position, first, last,
|
||||
typename std::iterator_traits<InputIterator>::iterator_category());
|
||||
}
|
||||
|
||||
template <class non_iterator>
|
||||
void insert_pre_impl(iterator position, non_iterator n, non_iterator x,
|
||||
Loki::Int2Type<false>)
|
||||
{ //used if e.g. T is int and insert(itr, 10, 6) is called
|
||||
insert(position, static_cast<size_type>(n),
|
||||
static_cast<value_type>(x));
|
||||
}
|
||||
|
||||
template <class InputIterator>
|
||||
void insert_impl(iterator position,
|
||||
InputIterator first, InputIterator last, std::input_iterator_tag)
|
||||
{
|
||||
for (; first != last; ++first)
|
||||
{
|
||||
position = insert(position, *first) + 1;
|
||||
}
|
||||
}
|
||||
template <class FwdIterator>
|
||||
void insert_impl(iterator position,
|
||||
FwdIterator first, FwdIterator last, std::forward_iterator_tag)
|
||||
{
|
||||
typedef yasli_protocols::move_traits<T> mt;
|
||||
|
||||
const typename std::iterator_traits<FwdIterator>::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<T, Allocator> 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<T>::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<T,Allocator>& rhs)//COULD DO THIS WITH LESS TEMPORARIES
|
||||
{
|
||||
std::swap(static_cast<Allocator&>(ebo_), static_cast<Allocator&>(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 <class T, class Allocator>
|
||||
bool operator==(const vector<T,Allocator>& x,
|
||||
const vector<T,Allocator>& y);
|
||||
template <class T, class Allocator>
|
||||
bool operator< (const vector<T,Allocator>& x,
|
||||
const vector<T,Allocator>& y);
|
||||
template <class T, class Allocator>
|
||||
bool operator!=(const vector<T,Allocator>& x,
|
||||
const vector<T,Allocator>& y);
|
||||
template <class T, class Allocator>
|
||||
bool operator> (const vector<T,Allocator>& x,
|
||||
const vector<T,Allocator>& y);
|
||||
template <class T, class Allocator>
|
||||
bool operator>=(const vector<T,Allocator>& x,
|
||||
const vector<T,Allocator>& y);
|
||||
template <class T, class Allocator>
|
||||
bool operator<=(const vector<T,Allocator>& x,
|
||||
const vector<T,Allocator>& y);
|
||||
// specialized algorithms:
|
||||
template <class T, class Allocator>
|
||||
void swap(vector<T,Allocator>& x, vector<T,Allocator>& y);
|
||||
|
||||
}//yasli
|
||||
|
||||
|
||||
|
||||
namespace yasli_protocols
|
||||
{
|
||||
template <class T, class A>
|
||||
struct move_traits< yasli::vector<T, A> >:public
|
||||
yasli_nstd::type_selector<
|
||||
sizeof(yasli::vector<T, A>) != (3 * sizeof(T*)),
|
||||
memmove_traits< std::complex<T> >,
|
||||
safe_move_traits< std::complex<T> >
|
||||
>::result
|
||||
{
|
||||
};
|
||||
}
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue