Skip to content

Instantly share code, notes, and snippets.

@kikiman
Created July 27, 2013 09:37
Show Gist options
  • Save kikiman/6094395 to your computer and use it in GitHub Desktop.
Save kikiman/6094395 to your computer and use it in GitHub Desktop.
A three-member vector. Fast, portable & flexible.
#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