#ifndef CPP_DATASTRUCTURES_GENARRAY_H
#define CPP_DATASTRUCTURES_GENARRAY_H

// Eine (sehr) generische Array Klasse für dynamische Arrays und
// ein daraus abgeleitetes template array.
//
// In diesem Array dürfen nur Elemente liegen, die mit memcpy()
// kopiert werden können (d.h. keine Objekte mit einem eigenen
// Kopierkonstruktor).
//
// Die Vergrößerungsstrategie ist simpel:
//   Entweder wird die Arraygröße verdoppelt, oder, falls der
//   benötigte Index größer als die alte doppelte Größe ist,
//   das Array gerade so groß gemacht, daß der Index im Array
//   liegt.
//
// Fehlender Speicher wird komplett über Ausnahmen (MemoryX) behandelt.
//
// Autor: Jochen Becher
//
// Historie:
// Version 1.0, am 25. Juni 94
//

#ifndef EXEC_TYPES_H
#include <exec/types.h>
#endif

#ifndef CPP_EXCEPTIONS_EXCEPTIONS_H
#include <classes/exceptions/exceptions.h>
#endif

class gen_array {
public:
	// 'es' bezeichnet die Größe der Einträge (sizeof())
 	// 's' gibt eine Vorgabe für die Größe des Arrays
	gen_array(ULONG es, ULONG s = 16) throw (MemoryX);
	gen_array(const gen_array &) throw (MemoryX);
	gen_array &operator= (const gen_array &) throw (MemoryX);
	~gen_array();
	operator APTR () const { return (APTR) v; };
	ULONG esize() const { return element_size; };
	ULONG count() const { return size; };
	// die Referenz muß auf den passenden Typ gecastet werden
	VOID & operator[] (ULONG i) throw (MemoryX);
	// die Anzahl der Feldelemente, der größte Index auf den ohne
	// Feldvergrößerung zugegriffen werden kann ist somit count-1
private:
	VOID extend(ULONG) throw (MemoryX);
	UBYTE *v;
	ULONG element_size;
	ULONG size;
};

template <class T> class array : private gen_array {
public:
	array(ULONG s = 16) throw (MemoryX);
	ULONG count() const { return gen_array::count(); };
	T &operator[] (ULONG i)  throw (MemoryX);
};

// *************************************************************

template <class T> array<T>::array(ULONG s)
	: gen_array(sizeof(T),s)
{
}

template <class T> T &array<T>::operator[] (ULONG i)
{
	return (T &) gen_array::operator[] (i);
}

#endif
