/** @file
Parser: Array & Array_iterator classes decls.
Copyright (c) 2001-2003 ArtLebedev Group (http://www.artlebedev.com)
Author: Alexandr Petrosian <paf@design.ru> (http://paf.design.ru)
*/
#ifndef PA_ARRAY_H
#define PA_ARRAY_H
static const char* IDENT_ARRAY_H="$Date: 2003/04/02 11:35:20 $";
// includes
#include "pa_memory.h"
#include "pa_exception.h"
// externals
// forwards
template<typename T> class Array_iterator;
/// Simple Array
template<typename T> class Array: public PA_Object {
friend class Array_iterator<T>;
protected:
/// elements[growing size] here
T *felements;
// allocated size
size_t fallocated;
// array size
size_t fused;
public:
typedef T element_type;
Array(int initial=3):
fallocated(initial>3?initial:3),
fused(0)
{
felements=static_cast<T*>(malloc(fallocated*sizeof(T)));
}
/// how many items are in Array
size_t count() const { return fused; }
/// append to array
Array& operator += (T src) {
if(is_full())
expand(2);
felements[fused++]=src;
return *this;
}
/// append other Array portion to this one. starting from offset
Array& append(const Array& src, int offset=0, int limit=0) {
if(offset<0) {
throw Exception(0,
0,
"Array::append(offset=%d) out <0", offset);
//return Nothing; // never
}
// fix limit
{
int m=src.count()-offset;
if(!m || limit<0)
return *this;
if(!limit || limit>m)
limit=m;
}
ssize_t delta=limit-(fallocated-fused);
if(delta>0)
expand(delta);
T* from=&src.felements[offset];
T* to=&felements[fused];
T* from_end=from+limit;
while(from<from_end)
*to++=*from++;
fused+=limit;
return *this;
}
/// get index-element
T get(size_t index) const {
assert(index>=0 && index<count());
return felements[index];
}
/// ref version of get
T& get_ref(size_t index) const {
assert(index>=0 && index<count());
return felements[index];
}
/// put index-element
void put(size_t index, T element) {
assert(index>=0 && index<count());
felements[index]=element;
}
T operator [](size_t index) const { return get(index); }
/// iterate over all elements
template<typename I> void for_each(void (*callback)(T, I), I info) const {
T *last=felements+fused;
for(T *current=felements; current<last; current++)
callback(*current, info);
}
/// iterate over all elements until condition becomes true, return that element
template<typename I> T first_that(bool (*callback)(T, I), I info) const {
T *last=felements+fused;
for(T *current=felements; current<last; current++)
if(callback(*current, info))
return *current;
return T(0);
}
protected:
bool is_full() {
return fused == fallocated;
}
void expand(size_t delta) {
size_t new_allocated=fallocated+delta;
felements = (T *)realloc(felements, new_allocated*sizeof(T));
memset(&felements[fallocated], 0, delta*sizeof(T));
fallocated=new_allocated;
}
private: //disabled
Array(const Array&) {}
Array& operator = (const Array&) { return *this; }
};
/** Array iterator, usage:
@code
// Array<T> a;
for(Array_iterator<T> i(a); i.has_next(); ) {
T& element=i.next();
...
}
@endcode
*/
template<typename T> class Array_iterator {
const Array<T>& farray;
T *fcurrent;
T *flast;
public:
Array_iterator(const Array<T>& aarray): farray(aarray) {
fcurrent=farray.felements;
flast=farray.felements+farray.count();
}
/// there are still elements
bool has_next() {
return fcurrent<flast;
}
/// quickly extracts next Array element
const T next() {
return *(fcurrent++);
}
};
/*
/** Nonconst array iterator, usage:
@code
// Array<T> a;
for(Array_iterator<T> i(a); i.has_next(); ) {
T& element=i.next();
...
}
@endcode
* /
template<typename T> class Array_modifing_iterator {
Array<T>& farray;
T *fcurrent;
T *flast;
public:
Array_modifing_iterator(Array<T>& aarray): farray(aarray) {
fcurrent=farray.felements;
flast=farray.felements+farray.count();
}
/// there are still elements
bool has_next() {
return fcurrent<flast;
}
/// quickly extracts next Array element
T& next() {
return *(fcurrent++);
}
};
*/
#endif
E-mail: