95 lines
3.2 KiB
C++
95 lines
3.2 KiB
C++
|
#ifndef _vec_hpp_INCLUDED
|
||
|
#define _vec_hpp_INCLUDED
|
||
|
|
||
|
#include <cassert>
|
||
|
#include <cstdio>
|
||
|
#include <cstdlib>
|
||
|
#include <cerrno>
|
||
|
#include <cstddef>
|
||
|
#include <cstring>
|
||
|
#include <fstream>
|
||
|
|
||
|
template<class T>
|
||
|
class vec {
|
||
|
static inline int imax (int x, int y) { int mask = (y-x) >> (sizeof(int)*8-1); return (x&mask) + (y&(~mask)); }
|
||
|
static inline void nextCap(int &cap) { cap += ((cap >> 1) + 2) & ~1; }
|
||
|
|
||
|
public:
|
||
|
T* data;
|
||
|
int sz, cap;
|
||
|
vec() : data(NULL), sz(0), cap(0) {}
|
||
|
vec(int size, const T& pad) : data(NULL) , sz(0) , cap(0) { growTo(size, pad); }
|
||
|
explicit vec(int size) : data(NULL), sz(0), cap(0) { growTo(size); }
|
||
|
~vec() { clear(true); }
|
||
|
|
||
|
operator T* (void) { return data; }
|
||
|
|
||
|
int size (void) const { return sz; }
|
||
|
int capacity (void) const { return cap; }
|
||
|
void capacity (int min_cap);
|
||
|
|
||
|
void setsize (int v) { sz = v;}
|
||
|
void push (void) { if (sz == cap) capacity(sz + 1); new (&data[sz]) T(); sz++; }
|
||
|
void push (const T& elem) { if (sz == cap) capInc(sz + 1); data[sz++] = elem; }
|
||
|
void push_ (const T& elem) { assert(sz < cap); data[sz++] = elem; }
|
||
|
void pop (void) { assert(sz > 0), sz--, data[sz].~T(); }
|
||
|
void copyTo (vec<T>& copy) { copy.clear(); copy.growTo(sz); for (int i = 0; i < sz; i++) copy[i] = data[i]; }
|
||
|
|
||
|
void growTo (int size);
|
||
|
void growTo (int size, const T& pad);
|
||
|
void clear (bool dealloc = false);
|
||
|
void capInc (int to_cap);
|
||
|
|
||
|
|
||
|
T& operator [] (int index) { return data[index]; }
|
||
|
const T& operator [] (int index) const { return data[index]; }
|
||
|
|
||
|
T& last (void) { return data[sz - 1]; }
|
||
|
const T& last (void) const { return data[sz - 1]; }
|
||
|
|
||
|
};
|
||
|
|
||
|
|
||
|
class OutOfMemoryException{};
|
||
|
|
||
|
template<class T>
|
||
|
void vec<T>::clear(bool dealloc) {
|
||
|
if (data != NULL) {
|
||
|
sz = 0;
|
||
|
if (dealloc) free(data), data = NULL, cap = 0;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
template<class T>
|
||
|
void vec<T>::capInc(int to_cap) {
|
||
|
if (cap >= to_cap) return;
|
||
|
int add = imax((to_cap - cap + 1) & ~1, ((cap >> 1) + 2) & ~1);
|
||
|
if (add > __INT_MAX__ - cap || ((data = (T*)::realloc(data, (cap += add) * sizeof(T))) == NULL) && errno == ENOMEM)
|
||
|
throw OutOfMemoryException();
|
||
|
}
|
||
|
|
||
|
template<class T>
|
||
|
void vec<T>::capacity(int min_cap) {
|
||
|
if (cap >= min_cap) return;
|
||
|
int add = imax((min_cap - cap + 1) & ~1, ((cap >> 1) + 2) & ~1); // NOTE: grow by approximately 3/2
|
||
|
if (add > __INT_MAX__ - cap || ((data = (T*)::realloc(data, (cap += add) * sizeof(T))) == NULL) && errno == ENOMEM)
|
||
|
throw OutOfMemoryException();
|
||
|
}
|
||
|
|
||
|
template<class T>
|
||
|
void vec<T>::growTo(int size) {
|
||
|
if (sz >= size) return;
|
||
|
capInc(size);
|
||
|
for (int i = 0; i < sz; i++) new (&data[i]) T();
|
||
|
sz = size;
|
||
|
}
|
||
|
|
||
|
template<class T>
|
||
|
void vec<T>::growTo(int size, const T& pad) {
|
||
|
if (sz >= size) return;
|
||
|
capacity(size);
|
||
|
for (int i = sz; i < size; i++) data[i] = pad;
|
||
|
sz = size; }
|
||
|
|
||
|
|
||
|
#endif
|