peerplays-fc/include/fc/vector.hpp
Daniel Larimer 3d56a96d4e major updates to stream,reflect,value,and json
- removed polymorphic reflection, made static_reflect default because
  there are cases such as deserializing an array that you need more
  information than the runtime reflection can provide such as the
  ability to resize arrays and know the array content type.

- refactored iostream, sstream, fstream to be much simpler, fewer
  indirections, and fixed getline.

- json parsing works using code from mace.
- value is reimplemented based upon mace::rpc::value and no longer uses
  the runtime reflection that was removed.

- moved the typename utility to its own header
2012-10-21 02:28:59 -04:00

384 lines
12 KiB
C++

#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>
#if 0
#include <vector>
namespace fc {
template<typename T>
using vector = std::vector<T>;
}
#else
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>
struct vector_impl {
public:
typedef T* iterator;
typedef const T* const_iterator;
vector_impl():_data(nullptr){}
vector_impl( vector_impl&& c):_data(c._data){c._data =nullptr; }
vector_impl( const vector_impl& c):_data(nullptr) {
//slog( "copy: c.size %d", c.size() );
if( c.size() ) {
_data = detail::data<T>::allocate( c.size() );
_data->size = c.size();
memcpy(begin(),c.begin(),c.size() );
}
//slog( "copy: this.size %d", size() );
}
vector_impl(const_iterator b, const_iterator e ):_data(nullptr) {
resize(e-b);
if( size() ) memcpy( data(), b, size() );
}
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]; }
const T* data()const { return (&_data->first); }
T* data() { return (&_data->first); }
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( _data != nullptr ) {
free(_data);
}
_data = nullptr;
}
void reserve( uint64_t i ) {
_data = detail::data<T>::reallocate( _data, i );
}
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;
}
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:
detail::data<T>* _data;
};
template<typename T>
class vector_impl<T,fc::true_type> {
public:
typedef T* iterator;
typedef const T* const_iterator;
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() ) {
_data = detail::data<T>::allocate( c.size() );
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;
}
}
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]; }
const T* data()const { return (&_data->first); }
T* data() { return (&_data->first); }
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;
auto _ndata = detail::data<T>::allocate( i );
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 );
if( _ndata ) free(_ndata);
}
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 ) {
new (this->end()) T( fc::move(this->back()) );
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:
detail::data<T>* _data;
};
}
template<typename T>
class vector : public detail::vector_impl<T, typename fc::is_class<T>::type> {
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)){}
vector( const T* b, const T* e ):detail::vector_impl<T, typename fc::is_class<T>::type>(b,e){}
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;
};
};
#endif
#endif // _FC_VECTOR_HPP_