File:  [parser3project] / parser3 / src / include / pa_array.h
Revision 1.57.2.22: download - view: text, annotated - select for diffs - revision graph
Mon Feb 17 09:56:15 2003 UTC (23 years, 4 months ago) by paf
class fields of simple type not initialized with zeros :(
while class fields of class types initialized with default constructors.
learn C++

/** @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_Y="$Date: 2003/02/17 09:56:15 $";

#include "pa_pool.h"
#include "pa_exception.h"

template<typename T> class Array_iterator;

/**	
	Simple Array.

*/
template<typename T> class Array: public PA_Object {

	friend class Array_iterator<T>;

protected:

	// default expand delta size
	int fdelta;

	/// elements[growing size] here
	T *felements;

	// allocated size
	int fallocated;

	// array size
	int fused;

public:
	typedef T element_type;

	Array(int initial=3, int delta=1):
		fallocated(initial?initial:3),
		fdelta(delta),
		fused(0)
	{
		if(fallocated<=0 || fdelta<1)
			throw Exception(0, 
				Exception::undefined_source,
				"Array::Array(%d, %d) too small", initial, delta);

		felements=static_cast<T*>(calloc(fallocated*sizeof(T)));
	}
	override ~Array() {
		T *last=felements+fused;
		for(T *current=felements; current<last; current++)
			current->~T(); // manually invoking destructors

		free(felements);
	}

	/// how many items are in Array
	int count() const { return fused; }
	/// append to array
	Array& operator += (T src) {
		if(is_full())
			expand(fdelta);

		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 && offset<src.count())) {
			throw Exception(0, 
				Exception::undefined_source,
				"Array::append(offset=%d) out of range [0..%d]", offset, src.count()-1);
			//return 0; // never
		}
		// fix limit
		{
			int m=src.count()-offset;
			if(!m || limit<0)
				return *this;
			if(!limit || limit>m)
				limit=m;
		}

		int needed=limit-(fallocated-fused);
		if(needed>0)
			expand(needed);

		memcpy(&felements[fused+=limit], &src.felements[offset], limit*sizeof(T));
		return *this;
	}

	/// get index-element
	T& get(int index) const {
		if(!(index>=0 && index<count())) {
			throw Exception(0, 
				Exception::undefined_source,
				"Array::get(%d) out of range [0..%d]", index, count()-1);
			return felements[0]; // never
		}

		return felements[index];
	}

	T& operator [](int index) const { return get(index); }

	/// put index-element
	void put(int index, T& element) {
		if(!(index>=0 && index<count())) {
			throw Exception(0, 
				Exception::undefined_source, 
				"Array::put(%d) out of range [0..%d]", index, count()-1);
			return; // never
		}
		felements[index]=element;
	}


	/// 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(int delta) {
		felements = (T *)realloc(felements, (fallocated+delta)*sizeof(T));
		memset(&felements[fallocated], 0, delta*sizeof(T));
		fallocated+=delta;
	}

private: //disabled

	Array& operator = (const Array&) { return *this; }
};

typedef smart_ptr<char> CharPtr;

/** 
	Pool mechanizm allows users not to free up allocated memory,
	leaving that problem to 'pools'.
*/
class Pool: public Array<CharPtr> {
public:
	char *malloc(size_t size) {
		CharPtr result=CharPtr((char *)Array<CharPtr>::malloc(size));
		*this += result;
		return result.get();
	}

	char *copy(const char* buf, size_t size=0) {
		if(!size)
			size=strlen(buf)+1;

		char *result=malloc(size);
		memcpy(result, buf, size);
		return result;
	}
};

inline void *operator new[] (size_t size, Pool& pool) {
	return pool.malloc(size);
}

/// handy array iterator
template<typename T> class Array_iterator {

	Array<T>& farray;
	T *fcurrent;
	T *flast;

public:

	Array_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: