knotkit/lib/vector.h

389 lines
8.3 KiB
C
Raw Normal View History

template<class T>
class vector
{
protected:
class data
{
public:
unsigned refcount;
unsigned n;
unsigned c;
T p[1];
};
data *d;
static data *alloc (unsigned n_, unsigned c_, unsigned initn, T *init);
void unref ();
void ref (data *newd) { assert (d == 0); d = newd; if (d) d->refcount ++; }
T &at (unsigned i) { return operator [] (i); }
const T &at (unsigned i) const { return operator [] (i); }
public:
vector () : d(0) { }
explicit vector (unsigned n_);
vector (const vector &v) : d(0) { ref (v.d); }
vector (const vector &v, const vector &u);
vector (copy, const vector &v);
vector (copy2, const vector &v);
vector (unsigned n_, T *p_);
vector (unsigned n_, const vector &v_);
explicit vector (reader &r);
~vector () { unref (); }
vector &operator = (const vector &v) { unref (); ref (v.d); return *this; }
bool operator == (const vector &v) const;
bool operator != (const vector &v) const { return !operator == (v); }
bool operator < (const vector &v) const;
bool operator % (unsigned i) { return d && i < d->n; }
T &operator [] (unsigned i) { assert (d); assert (i < d->n); return d->p[i]; }
const T &operator [] (unsigned i) const { assert (d); assert (i < d->n); return d->p[i]; }
const T &operator () (unsigned i) const { return operator [] (i); }
/* ??? break resize into grow_capacity/resize, and specialize this
to in-place ctor from v */
void append (const T &v)
{
if (!d)
reserve (4);
else if (d->n == d->c)
reserve (d->c * 2);
assert (d && d->n < d->c);
new (&d->p[d->n ++]) T (v);
}
const T &top () const
{
unsigned n = size ();
assert (n > 0);
return at (n - 1);
}
T pop ();
unsigned capacity () const { return d ? d->c : 0; }
unsigned size () const { return d ? d->n : 0; }
void resize (unsigned new_size);
void reserve (unsigned c);
void sort () { assert (d); sort (0, d->n); }
void sort (unsigned from, unsigned len);
template<typename C> void sort (unsigned from, unsigned len, C comp);
unsigned lower_bound (const T &v) const;
unsigned upper_bound (const T &v) const;
void write_self (writer &w) const;
hash_t hash_self () const;
};
template<class T> typename vector<T>::data *
vector<T>::alloc (unsigned n_, unsigned c_, unsigned initn, T *init)
{
if (c_ > 0)
{
data *d = (data *)new char[sizeof (data) + sizeof (T) * (c_ - 1)];
d->refcount = 1;
d->c = c_;
d->n = n_;
if (initn > n_)
initn = n_;
for (unsigned i = 0; i < initn; i ++)
new (&d->p[i]) T (init[i]);
for (unsigned i = initn; i < n_; i ++)
new (&d->p[i]) T ();
return d;
}
else
return 0;
}
template<class T> void
vector<T>::unref ()
{
if (d && -- d->refcount == 0)
{
for (unsigned i = 0; i < d->n; i ++)
d->p[i].~T ();
delete [] (char *)d;
}
d = 0;
}
template<class T>
vector<T>::vector (const vector &v, const vector &u)
: d(0)
{
if (v.d)
{
unsigned vn = v.d->n,
un = u.size ();
d = alloc (vn, vn + un, v.d->n, v.d->p);
d->n = vn + un;
for (unsigned i = 0; i < un; i ++)
new (&d->p[vn + i]) T (u[i]);
}
else
{
if (u.d)
d = alloc (u.d->n, u.d->n, u.d->n, u.d->p);
}
}
template<class T>
vector<T>::vector (copy, const vector &v)
: d(0)
{
if (v.d)
d = alloc (v.d->n, v.d->n, v.d->n, v.d->p);
}
template<class T>
vector<T>::vector (copy2, const vector &v)
: d(0)
{
if (v.d && v.d->n > 0)
{
unsigned n = v.d->n;
d = (data *)new char[sizeof (data) + sizeof (T) * (n - 1)];
d->refcount = 1;
d->c = n;
d->n = n;
for (unsigned i = 0; i < n; i ++)
new (&d->p[i]) T (COPY1, v.d->p[i]);
}
}
template<class T>
vector<T>::vector (unsigned n_)
: d(0)
{
d = alloc (n_, n_, 0, 0);
}
template<class T>
vector<T>::vector (reader &r)
: d(0)
{
unsigned n_;
read (r, n_);
if (n_ > 0)
{
d = (data *)new char[sizeof (data) + sizeof (T) * (n_ - 1)];
d->refcount = 1;
d->c = n_;
d->n = n_;
for (unsigned i = 0; i < n_; i ++)
ctor_read (r, &d->p[i]);
}
}
template<class T>
vector<T>::vector (unsigned n_, T *p_)
: d(0)
{
d = alloc (n_, n_, n_, p_);
}
template<class T>
vector<T>::vector (unsigned n_, const vector &v)
: d(0)
{
if (v.d)
d = alloc (n_, n_, v.d->n, v.d->p);
else
d = alloc (n_, n_, 0, 0);
}
template<class T> bool
vector<T>::operator < (const vector &v) const
{
unsigned n = size (),
vn = v.size ();
if (n < vn)
return 1;
else if (n > vn)
return 0;
for (unsigned i = 0; i < n; i ++)
{
if (at (i) < v[i])
return 1;
else if (at (i) > v[i])
return 0;
}
return 0;
}
template<class T> bool
vector<T>::operator == (const vector &v) const
{
unsigned n = size ();
if (n != v.size ())
return 0;
for (unsigned i = 0; i < n; i ++)
{
if (at (i) != v[i])
return 0;
}
return 1;
}
template<class T> T
vector<T>::pop ()
{
unsigned n = size ();
assert (n > 0);
T tmp = at (n - 1);
resize (n - 1);
return tmp;
}
template<class T> void
vector<T>::reserve (unsigned newc)
{
if (newc <= capacity ())
return;
data *newd;
if (d)
newd = alloc (d->n, newc, d->n, d->p);
else
newd = alloc (0, newc, 0, 0);
unref ();
d = newd;
}
template<class T> void
vector<T>::resize (unsigned new_size)
{
unsigned n = size ();
if (new_size == n)
return;
reserve (new_size);
assert (d);
assert (new_size <= capacity ());
if (new_size < n)
{
for (unsigned i = new_size; i < n; i ++)
d->p[i].~T ();
}
else
{
for (unsigned i = n; i < new_size; i ++)
new (&d->p[i]) T ();
}
d->n = new_size;
}
template<class T> void
vector<T>::sort (unsigned from, unsigned len)
{
assert (d);
assert (from < d->n);
assert (from + len <= d->n);
std::sort (&d->p[from], &d->p[from + len]);
}
template<class T> template<typename C> void
vector<T>::sort (unsigned from, unsigned len, C comp)
{
assert (d);
assert (from < d->n);
assert (from + len <= d->n);
std::sort (&d->p[from], &d->p[from + len], comp);
}
template<class T> void
vector<T>::write_self (writer &w) const
{
if (d)
{
write (w, d->n);
for (unsigned i = 0; i < d->n; i ++)
write (w, d->p[i]);
}
else
{
unsigned n = 0;
write (w, n);
}
}
template<class T> hash_t
vector<T>::hash_self () const
{
unsigned n = size ();
hash_t h = hash (n);
for (unsigned i = 0; i < n; i ++)
h = hash_combine (h, hash (d->p[i]));
return h;
}
template<class T> unsigned
vector<T>::lower_bound (const T &v) const
{
T *r = std::lower_bound (&d->p[0], &d->p[d->n], v);
return r - &d->p[0];
}
template<class T> unsigned
vector<T>::upper_bound (const T &v) const
{
T *r = std::upper_bound (&d->p[0], &d->p[d->n], v);
return r - &d->p[0];
}
template<class T, unsigned B>
class basedvector : public vector<T>
{
public:
basedvector () { }
explicit basedvector (unsigned n_) : vector<T>(n_) { }
explicit basedvector (vector<T> &v_) : vector<T>(v_) { }
basedvector (unsigned n_, T *p_) : vector<T>(n_, p_) { }
basedvector (unsigned n_, const vector<T> &v_) : vector<T>(n_, v_) { }
basedvector (copy, const vector<T> &v_) : vector<T>(COPY, v_) { }
basedvector (copy2, const vector<T> &v_) : vector<T>(COPY2, v_) { }
basedvector (const vector<T> &v_, const vector<T> &u_) : vector<T>(v_, u_) { }
explicit basedvector (reader &r) : vector<T>(r) { }
~basedvector () { }
vector<T> &operator = (const vector<T> &v) { vector<T>::operator = (v); }
bool operator % (unsigned i) { return vector<T>::operator % (i - B); }
T &operator [] (unsigned i) { return vector<T>::operator [] (i - B); }
const T &operator [] (unsigned i) const { return vector<T>::operator [] (i - B); }
const T &operator () (unsigned i) const { return vector<T>::operator () (i - B); }
void sort () { vector<T>::sort (); }
void sort (unsigned from, unsigned len) { vector<T>::sort (from - B, len); }
template<typename C> void sort (unsigned from, unsigned len, C comp) { vector<T>::sort (from - B, len, comp); }
unsigned lower_bound (const T &v) const { return vector<T>::lower_bound (v) + B; }
unsigned upper_bound (const T &v) const { return vector<T>::upper_bound (v) + B; }
};