peerplays-fc/include/fc/vector.hpp

386 lines
12 KiB
C++
Raw Normal View History

2012-09-08 02:50:37 +00:00
#ifndef _FC_VECTOR_HPP_
#define _FC_VECTOR_HPP_
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <fc/utility.hpp>
#include <fc/log.hpp>
2012-09-10 01:44:57 +00:00
#if 0
#include <vector>
namespace fc {
template<typename T>
using vector = std::vector<T>;
}
#else
2012-09-08 02:50:37 +00:00
namespace fc {
namespace detail {
template<typename T>
struct data {
uint64_t size;
uint64_t capacity;
T first;
static data* allocate( uint64_t cap ) {
data* d = nullptr;
if( cap ){
d = (data*)malloc(sizeof(data) + sizeof(T)*(cap-1));
d->capacity = cap;
} else {
d = (data*)malloc(sizeof(data));
d->capacity = 1;
}
d->size = 0;
return d;
}
static data* reallocate( data* d, uint64_t cap ) {
if( cap ){
d = (data*)realloc(d,sizeof(data) + sizeof(T)*(cap-1));
d->capacity = cap;
} else {
d = (data*)realloc(d,sizeof(data));
d->capacity = 1;
}
if( d->size > d->capacity )
d->size = d->capacity;
return d;
}
private:
data(){};
};
template<typename T, typename IsClass=fc::false_type>
2012-09-08 02:50:37 +00:00
struct vector_impl {
public:
typedef T* iterator;
typedef const T* const_iterator;
2012-09-08 02:50:37 +00:00
vector_impl():_data(nullptr){}
2012-09-30 21:01:54 +00:00
vector_impl( vector_impl&& c):_data(c._data){c._data =nullptr; }
2012-09-08 02:50:37 +00:00
vector_impl( const vector_impl& c):_data(nullptr) {
2012-09-30 21:01:54 +00:00
//slog( "copy: c.size %d", c.size() );
2012-09-08 02:50:37 +00:00
if( c.size() ) {
2012-09-09 03:46:19 +00:00
_data = detail::data<T>::allocate( c.size() );
2012-09-25 21:45:28 +00:00
_data->size = c.size();
2012-09-08 02:50:37 +00:00
memcpy(begin(),c.begin(),c.size() );
}
2012-09-30 21:01:54 +00:00
//slog( "copy: this.size %d", size() );
2012-09-08 02:50:37 +00:00
}
vector_impl(const_iterator b, const_iterator e ):_data(nullptr) {
resize(e-b);
if( size() ) memcpy( data(), b, size() );
}
2012-09-08 02:50:37 +00:00
vector_impl(uint64_t s):_data(nullptr){
resize(s);
}
~vector_impl() {
clear();
}
uint64_t size()const { return _data ? _data->size : 0; }
uint64_t capacity()const { return _data ? _data->capacity : 0; }
T& back() { return (&_data->first)[-1+_data->size]; }
const T& back()const { return (&_data->first)[-1+_data->size]; }
T& front() { return (&_data->first)[0]; }
2012-09-09 03:46:19 +00:00
const T& front()const { return (&_data->first)[0]; }
const T* data()const { return (&_data->first); }
T* data() { return (&_data->first); }
2012-09-08 02:50:37 +00:00
2012-11-24 20:49:26 +00:00
iterator begin() { return _data ? &front() : 0;}
2012-09-08 02:50:37 +00:00
const_iterator begin()const { return _data ? &front() : 0;}
2012-11-24 20:49:26 +00:00
iterator end() { return _data ? (&back())+1: 0;}
2012-09-08 02:50:37 +00:00
const_iterator end()const { return _data ? (&back())+1: 0;}
T& operator[]( uint64_t i ) { return (&_data->first)[i]; }
const T& operator[]( uint64_t i )const { return (&_data->first)[i]; }
T& at( uint64_t i ) { return (&_data->first)[i]; }
const T& at( uint64_t i )const { return (&_data->first)[i]; }
void pop_back() { erase( &back() ); }
void clear() {
2012-09-30 21:01:54 +00:00
if( _data != nullptr ) {
2012-09-08 02:50:37 +00:00
free(_data);
2012-09-30 21:01:54 +00:00
}
2012-09-08 02:50:37 +00:00
_data = nullptr;
}
void reserve( uint64_t i ) {
2012-09-09 03:46:19 +00:00
_data = detail::data<T>::reallocate( _data, i );
2012-09-08 02:50:37 +00:00
}
void resize( uint64_t i ) {
if( capacity() < i ) {
if( _data )
_data = detail::data<T>::reallocate( _data, i );
else
_data = detail::data<T>::allocate( i );
}
if( _data ) _data->size = i;
2012-09-08 02:50:37 +00:00
}
template<typename U>
void push_back( U&& v ) {
resize( size()+1 );
back() = fc::forward<U>(v);
}
template<typename U>
iterator insert( const_iterator loc, U&& t ) {
uint64_t pos = loc - begin();
resize( size()+1 );
char* src = &at(pos);
if( src != &back() )
memmove( src+1, src, (&back() - src) );
&back = fc::forward<U>(t);
return &at(pos);
}
iterator insert( iterator pos, const_iterator first, const_iterator last ) {
if( first >= last ) return pos;
uint64_t loc = pos - begin();
uint64_t right_size = size() - loc;
resize( size() + (last-first) );
char* src = &at(loc);
uint64_t s = last-first;
memmove( src + s, src, right_size );
memcpy( src, first, s );
_data->size += (last-first);
return src;
}
iterator erase( iterator pos ) {
memmove( pos, pos+1, (&back() - pos) );
_data->size--;
return pos;
}
iterator erase( iterator first, iterator last ) {
if( first != last ) {
memmove( first, first + (last-first), (&back() - last) );
_data->size -= last-first;
}
return first;
}
vector_impl& operator=( vector_impl&& v ) {
fc::swap(_data,v._data);
return *this;
}
vector_impl& operator=( const vector_impl& v ) {
vector_impl tmp(v);
fc::swap(tmp._data,_data);
return *this;
}
protected:
2012-09-09 03:46:19 +00:00
detail::data<T>* _data;
2012-09-08 02:50:37 +00:00
};
template<typename T>
struct vector_impl<T,fc::true_type> {
2012-09-08 02:50:37 +00:00
public:
typedef T* iterator;
typedef const T* const_iterator;
2012-09-08 02:50:37 +00:00
vector_impl():_data(nullptr){}
vector_impl( vector_impl&& c):_data(c._data){c._data =nullptr; }
vector_impl( const vector_impl& c):_data(nullptr) {
if( c.size() ) {
2012-09-09 03:46:19 +00:00
_data = detail::data<T>::allocate( c.size() );
2012-09-08 02:50:37 +00:00
auto i = begin();
auto ci = c.begin();
auto ce = c.end();
while( ci != ce ) {
new (i) T(*ci);
++i;
++_data->size;
++ci;
}
}
}
vector_impl(const_iterator b, const_iterator e ):_data(nullptr) {
resize(e-b);
for( auto i = begin(); i != end(); ++i ) {
*i = *b;
++b;
}
}
2012-09-08 02:50:37 +00:00
vector_impl(uint64_t s):_data(nullptr){
resize(s);
}
~vector_impl() {
clear();
}
uint64_t size()const { return _data ? _data->size : 0; }
uint64_t capacity()const { return _data ? _data->capacity : 0; }
T& back() { return (&_data->first)[-1+_data->size]; }
const T& back()const { return (&_data->first)[-1+_data->size]; }
T& front() { return (&_data->first)[0]; }
const T& front()const { return (&_data->first)[0]; }
2012-09-09 03:46:19 +00:00
const T* data()const { return (&_data->first); }
T* data() { return (&_data->first); }
2012-09-08 02:50:37 +00:00
iterator begin() { return _data ? &front() : 0;}
const_iterator begin()const { return _data ? &front() : 0;}
const_iterator end()const { return _data ? (&back())+1: 0;}
T& operator[]( uint64_t i ) { return (&_data->first)[i]; }
const T& operator[]( uint64_t i )const { return (&_data->first)[i]; }
T& at( uint64_t i ) { return (&_data->first)[i]; }
const T& at( uint64_t i )const { return (&_data->first)[i]; }
void pop_back() { erase( &back() ); }
void clear() {
if( this->_data != nullptr ) {
auto c = this->begin();
auto e = this->end();
while( c != e ) {
(*c).~T();
++c;
}
free(this->_data);
}
this->_data = nullptr;
}
void reserve( uint64_t i ) {
if( nullptr != this->_data && i <= this->_data->capacity )
return;
2012-09-09 03:46:19 +00:00
auto _ndata = detail::data<T>::allocate( i );
2012-09-08 02:50:37 +00:00
auto nc = &_ndata->first;
auto c = this->begin();
auto e = this->end();
while( c != e ) {
new (nc) T(fc::move( *c ));
(*c).~T();
++_ndata->size;
++c;
++nc;
}
fc::swap( _ndata, this->_data );
2012-09-30 21:01:54 +00:00
if( _ndata ) free(_ndata);
2012-09-08 02:50:37 +00:00
}
void resize( uint64_t i ) {
this->reserve(i);
while( i < this->_data->size ) {
this->back().~T();
--this->_data->size;
}
while( this->_data->size < i ) {
new (&this->back()+1) T();
++this->_data->size;
}
}
template<typename U>
void push_back( U&& v ) {
this->reserve( this->size()+1 );
new (&back()+1) T(fc::forward<U>(v));
++this->_data->size;
}
template<typename U>
iterator insert( const_iterator loc, U&& t ) {
uint64_t pos = loc - this->begin();
this->reserve( this->size()+1 );
loc = this->begin() + pos;
if( this->size() != 0 ) {
2012-10-26 05:11:35 +00:00
new ((void*)this->end()) T( fc::move(this->back()) );
2012-09-08 02:50:37 +00:00
auto cur = this->back();
++this->_data->size;
while( cur != loc ) {
*cur = fc::move( *(cur-1) );
}
*cur = fc::forward<U>(t);
} else {
new (this->end()) T( fc::forward<U>(t) );
++this->_data->size;
}
return &this->at(pos);
}
iterator insert( iterator pos, const_iterator first, const_iterator last ) {
//static_assert( false, "Not Implemented" );
return 0;
}
iterator erase( iterator pos ) {
if( pos == this->end() ) { return pos; }
auto next = pos + 1;
while( next != this->end() ) {
*pos = fc::move(*next);
++pos; ++next;
}
pos->~T();
this->_data->size--;
return pos;
}
iterator erase( iterator first, iterator last ) {
iterator c = first;
iterator m = last;
iterator e = this->end();
while( c != e ) {
if( m != e ) *c = fc::move( *m );
else c->~T();
++c;
++m;
}
this->_data->size -= last-first;
return last;
}
vector_impl& operator=( vector_impl&& v ) {
fc::swap(_data,v._data);
return *this;
}
vector_impl& operator=( const vector_impl& v ) {
vector_impl tmp(v);
fc::swap(tmp._data,_data);
return *this;
}
private:
2012-09-09 03:46:19 +00:00
detail::data<T>* _data;
2012-09-08 02:50:37 +00:00
};
}
template<typename T>
class vector : public detail::vector_impl<T, typename fc::is_class<T>::type> {
2012-09-08 02:50:37 +00:00
public:
vector(){}
vector( uint64_t s ):detail::vector_impl<T, typename fc::is_class<T>::type>(s){}
vector( const vector& v ):detail::vector_impl<T, typename fc::is_class<T>::type>(v){}
vector( vector&& v ):detail::vector_impl<T, typename fc::is_class<T>::type>(fc::move(v)){}
2012-09-08 02:50:37 +00:00
vector( const T* b, const T* e ):detail::vector_impl<T, typename fc::is_class<T>::type>(b,e){}
2012-09-08 02:50:37 +00:00
vector& operator=( vector&& v ) {
*((base*)this) = fc::move(v);
return *this;
}
vector& operator=( const vector& v ) {
*((base*)this) = v;
return *this;
}
private:
typedef detail::vector_impl<T, typename fc::is_class<T>::type> base;
2012-09-08 02:50:37 +00:00
};
};
2012-09-10 01:44:57 +00:00
#endif
2012-09-08 02:50:37 +00:00
#endif // _FC_VECTOR_HPP_