view oldclasslib/include/stack.h @ 16:f9e4689b837d

Some minor updates for 15 years later.
author David A. Holland
date Tue, 31 May 2022 01:45:26 -0400
parents 13d2b8934445
children
line wrap: on
line source

/*
 * AnaGram, a System for Syntax Directed Programming
 *
 * Stack Class Definition
 *
 * Please note that the entire class is defined in this module. There
 * is no supplementary code module.
 *
 * Copyright 1993 Parsifal Software. All Rights Reserved.
 *
 * This software is provided 'as-is', without any express or implied
 * warranty.  In no event will the authors be held liable for any damages
 * arising from the use of this software.
 *
 * Permission is granted to anyone to use this software for any purpose,
 * including commercial applications, and to alter it and redistribute it
 * freely, subject to the following restrictions:
 *
 * 1. The origin of this software must not be misrepresented; you must not
 *    claim that you wrote the original software. If you use this software
 *    in a product, an acknowledgment in the product documentation would be
 *    appreciated but is not required.
 * 2. Altered source versions must be plainly marked as such, and must not be
 *    misrepresented as being the original software.
 * 3. This notice may not be removed or altered from any source distribution.
 */

#ifndef STACK_H
#define STACK_H

#include <assert.h>

// Some forward decls required in current C++
template <class T> class stack;
template <class T> stack <T> &reset(stack <T> &s);
template <class T> unsigned size(const stack <T> &s);


template <class T>
class stack {
protected:
  T *cs;                               // data storage
  unsigned *ls;                        // index (level) storage
  unsigned sx;                         // stack index
  unsigned lx;                         // level index
  unsigned sxmax;                      // max stack index
  unsigned lxmax;                      // max level index
  int copy_flag;                       // is it live or memorex?
public:


// Constructor

  stack(unsigned n, unsigned m) {      // (storage request, levels)
    cs = new T[n];                     // allocate data storage
    ls = new unsigned[m];              // allocate index storage
    lx = lxmax = m;                    // set up for pre-decrement push
    sx = sxmax = n;                    // post-increment pop
    ls[--lx] = sx;                     // init first level
    copy_flag = 0;                     // live
  }

  stack(unsigned n) {                  // (storage request)
    unsigned m = 1;                    // single level
    cs = new T[n];                     // allocate data storage
    ls = new unsigned[m];              // allocate index storage
    lx = lxmax = m;                    // set up for pre-decrement push
    sx = sxmax = n;                    // post-increment pop
    ls[--lx] = sx;                     // init first level
    copy_flag = 0;                     // live
  }

  stack(stack<T> &s) {
    *this = s;
    copy_flag++;                       // memorex
  }


// Destructor

  ~stack() {
    if (copy_flag) return;
    delete [] cs;
    delete [] ls;
  }


// Reset function
#ifdef __IBMCPP__
  friend stack<T> &reset(stack<T> &s);
#else
  friend stack<T> &reset<>(stack<T> &s);
#endif


// Change levels

  stack<T> &operator ++() {            // next level -- preincrement
    assert(copy_flag == 0);
    assert(lx);                        // not going to overflow
    ls[--lx] = sx;                     // push storage index
    return *this;
  }

  stack<T> operator ++(int);           // next level -- postincrement

  stack<T> &operator --() {            // previous level -- predecrement
    assert(copy_flag == 0);
    sx = ls[lx++];                     // restore storage index
    assert(lx < lxmax);                // no underflow
    return *this;
  }

  stack<T> operator --(int);         // previous level -- postdecrement


// Push data

  stack<T> &operator << (T t) {        // push data
    assert(copy_flag == 0);
    assert(sx && lx < lxmax);          // everything's ok
    cs[--sx] = t;                      // save it
    return *this;
  }


// Pop data

  stack<T> &operator >> (T &t) {       // pop data
    assert(copy_flag == 0);
    assert(lx < lxmax && sx < ls[lx]); // all's well
    t = cs[sx++];                      // get it
    return *this;
  }


// Access stack element

  T &operator[] (unsigned k) {         // access stack element
    assert(lx < lxmax && sx + k < ls[lx]);  // legitimate index
    return cs[sx+k];                   // reference data
  }


// Pointer to top element

// See README.txt
#if 0
  operator T * () {
    return &cs[sx];
  }
#endif
  T *top() {
    return &cs[sx];
  }


// Get size of stack

#ifdef __IBMCPP__
  friend unsigned size(const stack <T> &s);        // size at current level
#else
  friend unsigned size<>(const stack <T> &s);      // size at current level
#endif

};

template <class T>
inline stack <T> &reset(stack <T> &s) {
  assert(s.copy_flag == 0);
  s.lx = s.lxmax;                    // set up for pre-decrement push
  s.sx = s.sxmax;                    // post-increment pop
  s.ls[--s.lx] = s.sx;               // init first level
  return s;
}

template <class T>
inline unsigned size(const stack <T> &s) {     // size at current level
  return s.ls[s.lx] - s.sx;
}


template <class T>
stack<T> stack<T>::operator ++(int) {   // next level -- postintcrement
  stack<T> cpy(*this);                  // make copy for return value
  assert(copy_flag == 0);
  assert(lx);
  ls[--lx] = sx;
  return cpy;
}

template <class T>
stack<T> stack<T>::operator --(int) {    // previous level -- postdecrement
  stack <T> cpy(*this);                  // make copy for return value
  assert(copy_flag == 0);
  sx = ls[lx++];                     // restore storage index
  assert(lx < lxmax);                // no underflow
  return cpy;
}
#endif