//	Programmer:		Ralph Looney
//  PH        :   (619) 744 - 4000 x498 or x497
//  FAX       :   (619) 471 - 6255
//
// This program is based on the example in
// Stanley B. Lippman C++ Primer 2nd edition book
// Page 50 - 55
// Page 146 - 148
// Page 380 - 386
//
// As it is now, the program compiles/run BUT does not use the
// overloaded cout << operator ???



#include <iostream.h>
#include <assert.h>
#include <string.h>
#include <conio.h>

const int ArraySize = 12;                        // default size

/*******************TEMPLATE*********************/
/* IntArray Class Definition                    */
/* Tag Name = IntArray                          */
/* Member Function/Interface                    */
/* 		- getsize																	*/
/*		- grow																		*/
/*		- operator[]	(overloading [] )					  */
/*		- print				(overloading << )						*/
/* Member Variable                              */
/*		- size											              */
/*		- pointer ia															*/
/************************************************/
template <class MyType>
class IntArray
{
public:
	IntArray( int sz = ArraySize);								 // constructors
 ~IntArray() {delete[] ia;}                      // destructor
	MyType getsize() { return size; }
	MyType& operator[] (int);
	void grow();

	void print(ostream& = cout);                   // overloading <<

protected:                                       // accessible from
	int size;                                      // inside class
	MyType *ia;                                    // only
};


/*****************CONSTRUCTOR********************/
template<class MyType> IntArray<MyType>::IntArray( int sz)
{
	size = sz;
	ia = new MyType[size];                         // allocating memory
	assert( ia != 0);
	for (int ix=0; ix < sz; ++ix)
			 ia[ix] = 0;
}

/*********************GROW***********************/
template<class MyType> void IntArray<MyType>::grow()
{
	int oldsize = size;
	MyType *oldia = ia;

	size += size/2 + 1;                            // increase by 1/2 + 1
	ia = new MyType[size];                         // allocating memory

	int ix = 0;
	for ( ; ix < oldsize; ++ix)                    // copying old array
			ia[ix] =  oldia[ix];                       // into new array

	for ( ; ix < size; ++ix) ia[ix] = 0;           // initializing new part
	delete oldia;                                  // deallocate memory
}
/******************OPERATOR[]********************/
template<class MyType> inline MyType&
IntArray<MyType>::operator[] (int index)
{
	 assert(index >=0 && index < size);            // checks bounds
	 return ia[ index ];
}

// --------------------------------------------------------
// --------------------------------------------------------
template <class MyType> ostream&
operator<<( ostream_withassign& os, IntArray<MyType>& ar)
{
	ar.print(os);
	return os;
}
// =====
template <class MyType> void IntArray<MyType>::print(ostream& os)
{
	const lineLength = 12;

  cout << "got here" << endl;
	os << "( " << size << " )< ";

	for (int ix = 0; ix < size; ++ix)
	{
		if (ix % lineLength == 0 && ix) os << "\n\t";
		os << ia[ ix ];

		if (ix % lineLength != lineLength-1 &&
						 ix != size-1) os << ", ";
	}
	os << " >\n";
}
/************************************************/
/*                  M A I N                     */
/************************************************/
int main()
{
	clrscr();
	int ix = 0;
	char Response;

	IntArray <int> ia;                             // Integer    instantiation
	IntArray <double> da(10);                      // Double     instantiation
	IntArray <char> sa(3);                         // Character  instantiation

	cout << "DISPLAY SIZE:" << endl;
//         -------------
	cout << "size: " << ia.getsize() << endl;
	cout << "size: " << da.getsize() << endl;
	cout << "size: " << sa.getsize() << endl;

	for (ix=0; ix < ia.getsize(); ++ix )
			ia[ix] = ix * 2;                           // initialize 0,2,4, ..
	for (ix=0; ix < da.getsize(); ++ix )
			da[ix] = ix * 3;                           // initialize 0,3,6, ..
	for (ix=0; ix < sa.getsize(); ++ix )
			sa[ix] = ix + 65;                          // initialize A,B,C, ..

	cout << endl;
	cout << ia << endl;
/*
	cout << "DISPLAY ARRAY:" << endl;
//         --------------
	for ( ix=0; ix < ia.getsize(); ++ix )
			cout << ia[ix] << " ";
			cout << endl;
	for ( ix=0; ix < da.getsize(); ++ix )
			cout << da[ix] << " ";
			cout << endl;
	for ( ix=0; ix < sa.getsize(); ++ix )
			cout << sa[ix] << " ";
			cout << endl;

	cout << endl;
	cout << "GROWING ARRAY'S:" << endl;
//         ----------------
	ia.grow();
	da.grow();
	sa.grow();

	cout << endl;
	cout << "DISPLAY GROWN ARRAY:" << endl;
//         --------------------
	for ( ix=0; ix < ia.getsize(); ++ix )
			cout << ia[ix] << " ";
			cout << endl;
	for ( ix=0; ix < da.getsize(); ++ix )
			cout << da[ix] << " ";
			cout << endl;
	for ( ix=0; ix < sa.getsize(); ++ix )
			cout << sa[ix] << " ";
			cout << endl;

	cout << endl;
	cout << "TEST BOUNDS CHECKING:" << endl;
//         ---------------------
	for ( ix=0; ix < ia.getsize() + 2; ++ix )      // size PLUS 2
			cout << ia[ix] << " ";                     // out of bound
			cout << endl;
*/
	return 0;
}
