//
// Copyright (C) 1991 Texas Instruments Incorporated.
//
// Permission is granted to any individual or institution to use, copy, modify,
// and distribute this software, provided that this complete copyright and
// permission notice is maintained, intact, in all copies and supporting
// documentation.
//
// Texas Instruments Incorporated provides this software "as is" without
// express or implied warranty.
//
// Created: MBN 08/29/89 -- Initial design and implementation
// Updated: MJF 03/12/90 -- Added group names to RAISE
//
// The Stack class is  publicly  derived from the  Generic class and is used to
// implement non-type specific functionality for the parameterized Stack class.
// In  this manner, code common  to  all instances  of the  Stack  class can be
// shared to reduce code replication.  The  Stack class  implements a one
// dimensional vector of a user-specified type.  This  is accomplished by using
// the parameterized type  capability of C++.  The  stack will grow dynamically
// as necessary  with   the amount  of  growth determined  by  the value  of an
// allocation size slot.  Fixed length stacks are also supported by setting the
// value of the allocation size slot to zero.
//

#ifndef BASE_STACKH				// If no definition for Stack
#include <cool/Base_Stack.h>				// Include definition file
#endif

// long set_length(long, char*) -- Change number of elements in this stack
// Input:                          Integer number of elements and
//                                 character string of type
// Output:                         Number of elements

long Stack::set_length (long n, const char* Type) {
#if ERROR_CHECKING
  if (n < 0)					// If index out of range
    RAISE (Error, SYM(Stack), SYM(Negative_Length),
	   "Stack<%s>::set_length(): Negative length %d",
	   Type, n);
#endif
  if (n <= size)				// If not greater than size
    this->number_elements = n;			// Set new length
  else
    this->number_elements = size;		// Else set to maximum possible
  return this->number_elements;			// Return value
}


// void set_growth_ratio(float, char*) -- Set growth percentage of this stack
// Input:                                 Float ratio and character string type
// Output:                                None

void Stack::set_growth_ratio (float ratio, const char* Type) {
#if ERROR_CHECKING
  if (ratio <= 0.0)				// If non-positive growth
    RAISE (Error, SYM(Stack), SYM(Negative_Ratio),
	   "Stack<%s>::set_growth_ratio(): Negative growth ratio %f",
	   Type, ratio);
#endif
  this->growth_ratio = ratio;			// Adjust instance ration
} 


// void set_alloc_size(int, char*) -- Set the default allocation size 
// Input:                             Integer size and character string type
// Output:                            None

void Stack::set_alloc_size (int size, const char* Type) {
#if ERROR_CHECKING
  if (size < 0)					// If index out of range
    RAISE (Error, SYM(Stack), SYM(Negative_Size),
	   "Stack<%s>::set_alloc_size(): Negative growth size %d",
	   Type, size);
#endif
  this->alloc_size_s = size;			// Set growth size
}


// Stack () -- Empty constructor for the Stack class
// Input:            None
// Output:           None

Stack::Stack () {
  this->size = 0;				// Initialize size
  this->number_elements = 0;			// Initialize element count
  if (alloc_size_s == 0)			// If no size specified
    alloc_size_s = STACK_MEM_BLK_SZ;		// Set the default size 
  this->growth_ratio = 0.0;			// Intialize growth ratio
}


// Stack (long) -- Constructor that specifies number of elements
// Input:          Integer number of elements
// Output:         None

Stack::Stack (long n) {
  this->size = n;				// Element capacity
  this->number_elements = 0;			// No elements
  if (alloc_size_s == 0)			// If no allocation size
    alloc_size_s = STACK_MEM_BLK_SZ;		// Set default size
  this->growth_ratio = 0.0;			// Initialize growth ratio 
}


// Stack (Stack&) -- Constructor for reference to another stack
// Input:                        Stack reference
// Output:                       None

Stack::Stack (const Stack& s) {
  if (alloc_size_s == 0)			// If no allocation size
    alloc_size_s = STACK_MEM_BLK_SZ;			// Default
  this->growth_ratio = s.growth_ratio;		// New growth ratio
  this->size = s.size;				// New size
  this->number_elements = s.number_elements;	// New number of elements
}


// ~Stack -- Destructor for Stack class that frees up storage
// Input:          None
// Output:         None

Stack::~Stack () {
}


// Stack& operator= (Stack&) -- Assigns this stack to another stack
// Input:                       Reference to a stack
// Output:                      Reference to modified this

Stack& Stack::operator= (const Stack& s) {
  this->number_elements = s.number_elements;    // New number of elements
  this->growth_ratio = s.growth_ratio;          // New growth ratio
  return *this;					// Return reference
}


// assign_error -- Error message for parameterized Stack<Type>::operator=()
// Input:          Character string of type
// Output:         None

void Stack::assign_error (const char* Type) {
  RAISE (Error, SYM(Stack), SYM(Static_Size),
	 "Stack<%s>::operator=(): Static-size stack", Type);
}


// top_error -- Error message for parameterized Stack<Type>::top()
// Input:       Character string of type
// Output:      None

void Stack::top_error (const char* Type) {
  RAISE (Error, SYM(Stack), SYM(No_Elements),
	 "Stack<%s>::top(): No elements in stack", Type);
}


// pop_error -- Error message for parameterized Stack<Type>::pop()
// Input:       Character string of type
// Output:      None

void Stack::pop_error (const char* Type) {
  RAISE (Error, SYM(Stack), SYM(No_Elements),
	 "Stack<%s>::pop(): No elements in stack", Type);
}


// bracket_error -- Error message for parameterized Stack<Type>::operator[]()
// Input:           Character string of type and index
// Output:          None

void Stack::bracket_error (const char* Type, long n) {
  RAISE (Error, SYM(Stack), SYM(Out_Of_Range),
	 "Stack<%s>::operator[](): Index %d out of range", Type, n);
}


// push_error -- Error message for parameterized Stack<Type>::push()
// Input:        Character string of type
// Output:       None

void Stack::push_error (const char* Type) {
  RAISE (Error, SYM(Stack), SYM(Static_Size),
	 "Stack<%s>::push(): Static-size stack", Type);
}


// popn_error -- Error message for parameterized Stack<Type>::popn()
// Input:        Character string of type and index
// Output:       None

void Stack::popn_error (const char* Type, long n) {
  RAISE (Error, SYM(Stack), SYM(Negative_Index),
	 "Stack<%s>::popn(): Negative stack index %d", Type, n);
}


// resize_error -- Error message for parameterized Stack<Type>::resize()
// Input:          Character string of type and size
// Output:         None

void Stack::resize_error (const char* Type, long new_size) {
  RAISE (Error, SYM(Stack), SYM(Negative_Size),
	 "Stack<%s>::resize(): Negative resize %d", Type, new_size);
}
