/*  
**  vector.h		C++ Runtime
**
**  Copyright (C)	Microway, Inc. 1987 - 1994.
**			P.O. BOX 79
**			Kingston, MA. 02364
**			(508) 746 - 7341 Voice
**			(508) 746 - 4678 FAX
**			e-mail tech@microway.com
**
**  This program is the property of Microway, Inc, its contents are
**  proprietary information and no part of it is to be disclosed to anyone
**  except employees of Microway, Inc., or as agreed in writing by the
**  President of Microway, Inc.
*/

#ifndef __VECTOR_H	/* JY */
#define __VECTOR_H

#include <generic.h>

# define vector(type)	name2(type,vector)
# define vectordeclare(type) \
extern GPT errorhandler(vector,type);					       \
extern GPT set_handler(vector,type,GPT);				       \
class vector(type) {							       \
    int sz;								       \
    type *v;								       \
public: 								       \
    vector(type)(int s) {						       \
	if (s<0) callerror(vector,type,1,"Bad size to constructor");	       \
	else {								       \
	    sz=s;							       \
	    v=new type[s];						       \
	}								       \
    }									       \
    vector(type)(vector(type) &);					       \
    ~vector(type)() { delete [sz]v; }					       \
    vector(type) &operator=(vector(type)&);				       \
    int size() { return sz; }						       \
    void set_size(int); 						       \
    type &elem(int i) { return( v[i]); }				       \
    type &operator[](int i) {						       \
	if ( i<0 || i>=sz ) callerror(vector,type,2,"Bad index");	       \
    return( v[i]);							       \
    }									       \
}

# define vectorimplement(type) \
GPT errorhandler(vector,type)=genericerror;				       \
GPT set_handler(vector,type,GPT handler) {				       \
    GPT old = errorhandler(vector,type);				       \
    errorhandler(vector,type)= handler; 				       \
return( old );								       \
}									       \
									       \
vector(type)::vector(type)(vector(type) &other) {			       \
    int i;								       \
    sz = other.sz;							       \
    v = new type[sz];							       \
    for ( i=0; i<sz; ++i )						       \
	v[i] = other.v[i];						       \
}									       \
									       \
vector(type) &vector(type)::operator=(vector(type)& other) {		       \
    if ( sz != other.sz )						       \
	callerror(vector,type,3,"Vectors have different sizes in assignment"); \
    int i=sz;								       \
    register type *tpt=v;						       \
    register type *opt=other.v; 					       \
    while (--i>=0)							       \
	*(tpt++) = *(opt++);						       \
return(*this);								       \
}									       \
									       \
void vector(type)::set_size(int nsz) {					       \
    type *ov=v; 							       \
    if (nsz<0) callerror(vector,type,1,"Bad size to constructor");		    \
    v = new type[nsz];							       \
    register int i=sz;							       \
    if (nsz<sz) i=nsz;							       \
    register type *opt=ov;						       \
    register type *npt=v;						       \
    while ( --i>=0 )							       \
	*(npt++) = *(opt++);						       \
    delete [sz] ov;							       \
    sz=nsz;								       \
}

# define stack(type)   name2(type,stack)
# define stackdeclare(type) \
extern GPT errorhandler(stack,type);					       \
extern GPT set_handler(stack,type,GPT); 				       \
class stack(type) : vector(type) {					       \
    int t;								       \
public: 								       \
    stack(type)(int s) : (s) { t=0; }					       \
    stack(type)(stack(type) &other) : ((vector(type) &) other) { t = other.t; }\
    stack(type) &push(type it) {					       \
	if ( t==size() ) callerror(stack,type,1,"Stack overflow");	       \
	elem(t++)= it;							       \
    return(*this);							       \
    }									       \
    type pop() {							       \
	if ( t==0 ) callerror(stack,type,2,"Stack underflow");		       \
    return( elem(--t)); 						       \
    }									       \
    type top() {							       \
	if ( t==0 ) callerror(stack,type,3,"Stack empty");		       \
    return( elem(t-1)); 						       \
    }									       \
    stack(type) &drop() {						       \
	if ( t==0 ) callerror(stack,type,2,"Stack underflow");		       \
	--t;								       \
    return( *this );							       \
    }									       \
}

# define stackimplement(type) \
GPT errorhandler(stack,type)=genericerror;				       \
GPT set_handler(stack,type,GPT handler) {				       \
    GPT old = errorhandler(stack,type); 				       \
    errorhandler(stack,type)= handler;					       \
return( old );								       \
}
#endif
