ACEC/vec.hpp

95 lines
3.2 KiB
C++
Raw Normal View History

2022-10-14 14:04:57 +08:00
#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