/*****************************************************
* Unit:    stacks           release 0.7              *
* Purpose: general manipulation with FIFO structures *
* Licency: GPL or LGPL                               *
******************************************************/
#include <stdlib.h>
#include <limits.h>
#include <string.h>
#include <ctype.h>
#include <stdio.h>
//#ifdef Streams
// #include <iostream.h>
//#endif

#include "typedfs.h"
#include "stacks.h"


/// Constructors Of stack class.
stack::stack(void)
{
 data=NULL;
 Level=Allocated=0;
}


stack &stack::operator=(const stack & s)
{
 erase(*this);
 if(s.Level<=0) return(*this);

 data = (int *)malloc(s.Level*sizeof(int));
 if(data==NULL)
     {
     RaiseError(StackId|No_Memory,this); //Memory Exhausted
     return(*this);
     }
 Allocated = Level = s.Level;
 memcpy(data,s.data,Level*sizeof(int));
 return(*this);
}


int stack::pop(void)
{
 if(Level<=0)
   {
   return(0);
   }
 return(data[--Level]);
}


void stack::push(int value)
{
 if(Allocated<=Level)
   {
   if(data==NULL)
      {
      data = (int *)malloc(16*sizeof(int));
      Allocated = 16;
      }
   else
      {
      Allocated += 16;
      void *cpdata = realloc(data,Allocated*sizeof(int));
      if(cpdata==NULL) free(data);
      data = (int *)cpdata;
      }

   if(data==NULL)
     {
     Allocated=Level=0;
     RaiseError(StackId|No_Memory,this); //Memory Exhausted
     return;		// Prevent accessing data[]
     }
   }
 data[Level++] = value;
}


int stack::operator[](int i) const
{
 if(i>Level) return(0);
 return(data[Level-i]);
}


void erase(stack & s)
{
 if(s.data!=NULL)
   {
   free(s.data);
   s.data=NULL;
   }
 s.Allocated=s.Level=0;
}


/// This procedure verifies integrity of given object ==0 OK  !=0 fail.
int check(stack & s)
{
int ret=0;

if(s.data==NULL)
	{
	if(s.Allocated!=0) ret=StackId | Bad_Allocated;
	if(s.Level!=0) ret=StackId | Bad_Allocated;
	s.Level=s.Allocated=0;
	return(ret);
	}

if(s.Allocated==0) // && data!=NULL
  {
  erase(s);
  return(StackId | Bad_Allocated);
  }

if(s.Level>s.Allocated)
  {
  s.Level=s.Allocated;	// this error could be perhaps fixed
  ret = StackId|Bad_Allocated;
  }

return(ret);
}


#ifdef Streams

#ifndef IOSTREAM_H_ONLY
 using namespace std;
#endif

ostream &operator<<(ostream & xout, const stack & s)
{
int i;
  xout << '{';
  for(i=1; i<=Card(s); i++)
	{
	if(i>1) xout<<',';
	xout << s.data[i];
	}
  xout << '}';
return xout;
}

/*istream &operator>>(istream &, string &)
{
} */
#endif
