/*
* lftp - file transfer program
*
* Copyright (c) 1996-2017 by Alexander V. Lukyanov (lav@yars.free.net)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
#ifndef XARRAY_H
#define XARRAY_H 1
#include
#include "xmalloc.h"
#include "Ref.h"
class xarray0
{
protected:
void *buf;
int len;
private:
size_t size;
const unsigned short element_size;
const short keep_extra;
void init() { buf=0; size=len=0; }
xarray0& operator=(const xarray0&); // make assignment fail
xarray0(const xarray0&); // disable cloning
protected:
void *get_ptr(int n) const { return static_cast(buf)+n*element_size; }
public:
xarray0(size_t e,int k=0) : element_size(e),keep_extra(k) { init(); }
~xarray0() { xfree(buf); }
// allocates s slots, with preferred granularity g, may shrink
void get_space_do(size_t s,size_t g=32);
void get_space(size_t s,size_t g=32) {
if(size=s+keep_extra)
get_space_do(s,g);
}
// only grows, not shrinks
void grow_space(size_t s,size_t g=32) {
if(size0)
::qsort(buf,len,element_size,cmp);
}
bool _bsearch(const void*,qsort_cmp_t,int *);
void *_insert_ordered(const void*,qsort_cmp_t);
};
template
class xarray : public xarray0
{
xarray& operator=(const xarray&); // make assignment fail
xarray(const xarray&); // disable cloning
public:
xarray() : xarray0(sizeof(T)) {}
T *get_non_const() { return static_cast(buf); }
const T *get() const { return static_cast(buf); }
T& operator[](int i) { return get_non_const()[i]; }
const T& operator[](int i) const { return get()[i]; }
size_t get_element_size() const { return sizeof(T); }
/* operator const T*() const { return get(); }*/
void nset(const T *s,int len) { _nset(s,len); }
void set(const xarray &a) { nset(a.get(),a.count()); }
void set_length(size_t n) { _set_length(n); }
void unset() { _unset(); }
void truncate() { set_length(0); }
void insert(const T& n,int before) { *static_cast(_insert(before))=n; }
void append(const T& n) { *static_cast(_append())=n; }
void remove(int i) { _remove(i); }
void remove(int i,int j) { _remove(i,j); }
void chop() { _chop(); }
T& last() { return (*this)[len-1]; }
T *borrow() { return static_cast(_borrow()); }
typedef int (*cmp_t)(const T*,const T*);
void qsort(cmp_t cmp) {
xarray0::qsort((qsort_cmp_t)cmp);
}
void insert_ordered(const T& n,cmp_t cmp) {
*static_cast(_insert_ordered(&n,(qsort_cmp_t)cmp))=n;
}
int search(const T &x) const {
for(int i=0; i0) {
append(fill);
}
}
};
template
class _RefArray : public xarray0
{
void dispose(int i) { get_non_const()[i].unset(); }
void dispose(int i,int j) { while(i(buf); }
const RefT *get() const { return static_cast(buf); }
RefT& operator[](int i) { return get_non_const()[i]; }
const RefT& operator[](int i) const { return get()[i]; }
size_t get_element_size() const { return sizeof(RefT); }
void set_length(size_t n) { dispose(n,len); _set_length(n); }
void unset() { dispose(0,len); _unset(); }
void truncate() { set_length(0); }
void insert(T *n,int before) { static_cast(_insert(before))->_set(n); }
void append(T *n) { static_cast(_append())->_set(n); }
void remove(int i) { dispose(i); _remove(i); }
void remove(int i,int j) { dispose(i,j); _remove(i,j); }
void chop() { dispose(len-1); _chop(); }
RefT& last() { return (*this)[len-1]; }
RefT *borrow() { return static_cast(_borrow()); }
void allocate(int c) { while(c-->0) append((T*)0); }
typedef int (*cmp_t)(const RefT*,const RefT*);
void qsort(cmp_t cmp) {
xarray0::qsort((qsort_cmp_t)cmp);
}
};
template
class RefArray : public _RefArray< T,Ref > {
RefArray& operator=(const RefArray&); // make assignment fail
RefArray(const RefArray&); // disable cloning
public:
RefArray() : _RefArray< T,Ref >() {}
};
template
class xarray_s : public _RefArray {
xarray_s& operator=(const xarray_s&); // make assignment fail
xarray_s(const xarray_s&); // disable cloning
public:
xarray_s() : _RefArray() {}
};
// array of new'ed pointers
template
class xarray_p : public xarray0
{
xarray_p& operator=(const xarray_p&); // make assignment fail
xarray_p(const xarray_p&); // disable cloning
virtual void dispose(T *p) { delete p; }
void dispose(int i) { dispose(get_non_const()[i]); }
void dispose(int i,int j) { while(i(buf); }
T *const* get() const { return static_cast(buf); }
T *&operator[](int i) { return get_non_const()[i]; }
T *operator[](int i) const { return get()[i]; }
size_t get_element_size() const { return sizeof(T*); }
void nset(T *const*s,int s_len) { dispose(0,len); _nset(s,s_len); if(buf) z(); }
void set(const xarray_p &a) { nset(a.get(),a.count()); }
void set_length(size_t n) { dispose(n,len); _set_length(n); if(buf) z(); }
void unset() { dispose(0,len); _unset(); }
void truncate() { set_length(0); }
void insert(T *n,int before) { *static_cast(_insert(before))=n; z(); }
void append(T *n) { *static_cast(_append())=n; z(); }
void remove(int i) { dispose(i); _remove(i); z(); }
void remove(int i,int j) { dispose(i,j); _remove(i,j); z(); }
void chop() { dispose(len-1); _chop(); }
T *last() { return (*this)[len-1]; }
T **borrow() { return static_cast(_borrow()); }
typedef int (*cmp_t)(const T**,const T**);
void qsort(cmp_t cmp) {
xarray0::qsort((qsort_cmp_t)cmp);
}
};
// array of malloc'ed pointers
template
class xarray_m : public xarray_p
{
void dispose(T *p) { xfree(p); }
public:
~xarray_m() { xarray_p::truncate(); }
};
template class _xqueue
{
protected:
A q;
int ptr;
public:
_xqueue() : ptr(0) {}
int count() const { return q.count()-ptr; }
void empty() { q.truncate(); ptr=0; }
void push(P n) {
if(ptr>count()) {
q.remove(0,ptr);
ptr=0;
}
q.append(n);
}
void remove(int i) {
if(i==0)
ptr++;
else
q.remove(ptr+i);
}
// returned pointer valid till the next push
T& next() { return q[ptr++]; }
T& operator[](int i) { return q[ptr+i]; }
const T& operator[](int i) const { return q[ptr+i]; }
void move_here(_xqueue& o) { q.move_here(o.q); ptr=o.ptr; o.ptr=0; }
};
template class xqueue : public _xqueue {};
template class xqueue_p : public _xqueue,T*> {};
template class xqueue_m : public _xqueue,T*> {};
template class RefQueue : public _xqueue[,RefArray,T*> {};
#endif // XARRAY_H
]