Created
July 27, 2013 09:37
-
-
Save kikiman/6094395 to your computer and use it in GitHub Desktop.
A three-member vector. Fast, portable & flexible.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <assert.h> | |
#ifndef _MVECTOR | |
#define _MVECTOR | |
#define _V_EMPLACE 0 | |
template <class T> | |
struct mVector | |
{ | |
typedef unsigned int size_type; | |
typedef T* iterator; | |
typedef T def_type; | |
inline mVector() : s(NULL), m(NULL), e(NULL){} | |
inline mVector(size_t sz) : s(NULL), m(NULL){_allocate(sz);} | |
inline ~mVector(){if(s){_destroy(s, m);free(s);}} | |
inline void _construct(T * _s, T* _e) const {while(_s < _e){new (_s) T();++_s;}} | |
inline void _destroy(T * _s, T* _e) const {while(_s < _e){_s->~T();++_s;}} | |
inline void _allocate(size_t sz){if(!sz)return;_destroy(s, m);s = m = (T*)_memalloc(sz);e = &s[sz];assert(s != NULL);} | |
inline void _check(){if(m == e)_double_capacity();} | |
// _assign() functions (Please change if you want it to support operators) | |
inline void _assign(T *_m, const T&t) const | |
{memcpy(_m, &t, sizeof(T)); /*new (_m) T(t);*/ } | |
inline void _copy(T *_m, T *_s, T *_e) const | |
{memcpy(_m, _s, (_e - _s) * sizeof(T)); /*do{new (_m) T(*_s);}while(++_m, (++_s) < _e);*/} | |
inline size_t size() const {return (m - s);} | |
inline size_t capacity() const {return (e - s);} | |
inline void clear(){if(s){_destroy(s, m);m = s;}} | |
inline bool empty() const {return (s == m);} | |
inline void _double_capacity(){_reserve(capacity() * 2);} | |
inline void _double_capacity2(T *& t1){t1=(T*)(t1-s);_double_capacity();t1=s+(size_t)t1;} | |
inline void assign(size_t n, T &val){ | |
if(!n)return;clear(); | |
if(is_full(n))_double_capacity(); | |
do{_assign(m, val);}while(++m, --n); | |
} | |
inline void assign(T *_s, T *_e){if(!_s || !_e)return;clear();copy(_s, (_e - _s));} | |
inline void operator=(const mVector<T>& vec){assign(vec.begin(), vec.end());} | |
inline T*& get_iterator(){return m;} | |
inline void set_size(size_t _size){assert(_size < capacity());m = &s[_size];} // warning : unsafe | |
inline void* _memalloc(size_t n) const {return realloc(s, n * sizeof(T));} | |
inline T& at(size_t i) const {assert(i < size());return s[i];} | |
inline const T &c_back() const {return m[-1];}inline T &back() const {return m[-1];} | |
inline const T &c_front() const {return s[0];}inline T &front() const {return s[0];} | |
inline const T *c_begin() const {return &s[0];}inline T *begin() const {return &s[0];} | |
inline const T *c_end() const {return &m[0];}inline T *end() const {return &m[0];} | |
inline bool enum_object(T *&it) const {if(!it)it = begin() - 1;if((++it) < end())return it;return 0;} | |
inline bool enum_object2(void *&it) const {return enum_object(*((T**)&it));} | |
inline T *data() const {return &s[0];} | |
inline T& operator[](size_t i) const {return s[i];} | |
inline void push_back(const T&t){_check();_assign(m, t);++m;} | |
inline T& push_back2(const T&t){push_back(t);return m[-1];} | |
inline void push_ptr(void* t){_check();_assign(m, ((T*)t)[0]);++m;} | |
inline T* push_ptr2(void* t){push_ptr(t);return &m[-1];} | |
inline void push_construct(){_check();new (&m[0]) T();++m;} | |
inline T* push_construct2(){push_construct();return &m[-1];} | |
#if(_V_EMPLACE == 1) | |
inline void emplace_back(const T&&t){_check();new (&m[0]) T(t);++m;} | |
inline T& emplace_back2(const T&&t){emplace_back(t);return &m[-1];} | |
#endif | |
inline void _pop_back(){--m;m->~T();} | |
inline void pop_back(){if(m != s)_pop_back();} | |
inline bool pop_back_s(){if(m != s){_pop_back();return true;}return false;} | |
inline T* make_space(size_t n){if((m + n) >= e)_adjust_capacity(n + capacity());T * _s = m;m += n;return _s;} | |
inline bool is_full(size_t n = 0) const {return ((m + n) >= e);} | |
inline T* copy(const void *d, size_t n){T *_m = make_space(n);_copy(_m, (T*)d, ((T*)d + n));return _m;} | |
inline void* mcopy(const void *d, size_t sz){assert(!(sz % sizeof(T)));return copy(d, sz / sizeof(T));} | |
inline T* _resize(size_t sz) | |
{ | |
size_t _size = size(); | |
if(!sz || (sz == _size))return 0; | |
if(!s){_allocate(sz);return 0;} | |
if(sz < _size){_destroy(&s[sz], m);m = &s[sz];return 0;} | |
while(sz > capacity())_double_capacity(); | |
m = &s[sz];return &s[_size]; | |
} | |
inline void resize(size_t sz) | |
{ | |
T *_s = _resize(sz); | |
if(_s)_construct(_s, m); | |
} | |
inline void resize(size_t sz, const T&val) | |
{ | |
T *_s = _resize(sz); | |
if(_s)do{_assign(_s, val);}while((++_s) != m); | |
} | |
inline void _adjust_capacity(size_t sz){size_t _c = capacity();if(_c)while(sz > _c)_c *= 2;else _c = sz;if(_c != capacity())reserve(_c);} | |
inline void _reserve(size_t sz) | |
{ | |
if(!sz)sz = 1; | |
T *t = (T*)_memalloc(sz); | |
assert(t != NULL); | |
e = &t[sz]; | |
m = &t[size()]; | |
s = &t[0]; | |
} | |
inline void reserve(size_t sz) | |
{ | |
if(!sz){if(s)return;}else | |
if(sz <= capacity())return; | |
_reserve(sz); | |
} | |
inline void swap(const mVector<T> &vec) | |
{ | |
T* vec_s = (vec.s);vec.s = s;s = vec_s; | |
T* vec_m = (vec.m);vec.m = m;m = vec_m; | |
T* vec_e = (vec.e);vec.e = e;e = vec_e; | |
} | |
inline void erase(T *pos){ | |
if((pos < s) || (pos >= m))return;pos->~T(); | |
memcpy(pos, pos + 1, ((--m) - pos) * sizeof(T)); | |
} | |
inline void erase(T *first, T *last){ | |
if((last >= m) || (size() < (last - first)))return;_destroy(first, last); | |
memcpy(first, last, ((m -= (last - first)) - first) * sizeof(T)); | |
} | |
inline T* insert(T * pos, const T &val){ | |
if(pos > m)return 0; | |
if(m == e)_double_capacity2(pos); | |
memcpy(pos + 1, pos, (m++ - pos) * sizeof(T)); | |
memcpy(pos, &val, sizeof(T));return pos; | |
} | |
inline T* insert(T * pos, size_t n, const T &val){ | |
if(pos > m || !n)return 0; | |
while((m + n) >= e)_double_capacity2(pos); | |
T *_pos = pos; | |
memcpy(pos + n, pos, (m - pos) * sizeof(T));m += n;do{ | |
memcpy(pos, &val, sizeof(T));}while(++pos, --n); | |
return _pos; | |
} | |
inline T* insert(T * pos, T* first, T *last){ | |
if(pos > m || first >= last)return 0; | |
size_t sz = (last - first); | |
while((m + sz) >= e)_double_capacity2(pos); | |
memcpy(pos + sz, pos, (m - pos) * sizeof(T));m += sz; | |
memcpy(pos, first, sz * sizeof(T)); | |
return pos; | |
} | |
inline void shrink_to_fit() | |
{ | |
if(capacity() == size())return; | |
T *t = (T*)_memalloc(size()); | |
assert(t != NULL); | |
m = e = &t[size()]; | |
s = &t[0]; | |
} | |
template<class P> | |
inline void unique(P f) | |
{ | |
T *it1 = begin(), *it2; | |
while(it1 < end()) | |
{ | |
it2 = &it1[1]; | |
while(it2 < end()) | |
{ | |
if(f(*it1, *it2))erase(it2);else ++it2; | |
} | |
++it1; | |
} | |
} | |
static inline bool _equal(T &v1, T &v2) {return (v1 == v2);} | |
inline void unique(){return unique(_equal);} | |
union{ | |
struct{T *s, *m, *e;}; | |
struct{T *_first, *_current, *_last;}; | |
}; | |
}; | |
#endif |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment