All pastes #439646 Raw Edit

Miscellany

public text v1 · immutable
·published 2007-04-14 12:51 UTC
rendered paste body
#include <stdio.h>
#include <stdlib.h>

#define BUFFER_SIZE 1024

// Represents an area of memory being used to store part of the stack.
struct frame
{
  // Pointer to the previous stack frame.
  struct frame *previous;

  // The buffer for storing data.
  char buffer[BUFFER_SIZE];
};

// Current frame of the stack.
// This will be NULL initially and in future will only be nulled when the last element is pushed off the stack.
struct frame *currentFrame;

// The first free index within the buffer of the current frame.
// The buffer is full when this is equal to BUFFER_SIZE-1.
int bufferIndex = 0;

// Number of frames in the stack. Only used for reporting purposes.
int frameCount = 0;

/** Allocate a new frame on the stack. This is intended to only be called when the
 *  current stack frame is full, and the results are undefined if called otherwise.
 */
int newFrame()
{
  struct frame *oldFrame = currentFrame;
  struct frame *nextFrame;

  nextFrame = malloc(sizeof(struct frame));
  
  if (nextFrame == NULL) return -1; 
  else currentFrame = nextFrame;

  currentFrame->previous = oldFrame;

  bufferIndex = 0;
  frameCount++;

  return 0;
}

/** Free the memory used by the current frame and reset the head of the stack to the 
 *  end of the previous frame.
 */
void clearFrame()
{
  if (currentFrame != NULL)
  {
    struct frame *oldFrame = currentFrame->previous;
    free(currentFrame);
    currentFrame = oldFrame;
    
    bufferIndex = BUFFER_SIZE - 1;
    frameCount--;
  }
}

/**
 * The number of characters currently on the stack.
 */ 
int stackSize()
{
  return (currentFrame == NULL) ? 0 : (frameCount - 1) * BUFFER_SIZE + bufferIndex;
}

/**
 * Push a character onto the stack. This returns -1 if it fails to push, or 0 otherwise.
 */
int push(char i)
{
  int error = 0;
  if ((bufferIndex >= BUFFER_SIZE) || (currentFrame == NULL))
  {
    error = newFrame();   
  }

  if (error == -1) return -1;

  currentFrame->buffer[bufferIndex++] = i;
  
}

/**
 * Pops the character at the head of the stack and returns it, or returns -1 if the stack is
 * empty.
 */
int pop()
{
  // This will reset bufferIndex to BUFFER_SIZE - 1
  if (bufferIndex < 0) clearFrame();

  if (currentFrame == NULL) return -1;

  return currentFrame->buffer[--bufferIndex];
}

/**
 * Returns the current head of the stack without popping it. 
 */ 
int head()
{
  if (currentFrame == NULL) return -1;
  else if ((bufferIndex == 0) && (currentFrame->previous == NULL)) return -1;
  else if (bufferIndex > 0) return currentFrame->buffer[bufferIndex - 1];
  else return currentFrame->previous->buffer[BUFFER_SIZE - 1];
}

/**
 * Duplicates the current head of the stack.
 */
void dup()
{
  push(head());
}

int main()
{
  int val;

  while ( (val = getchar()) != EOF )
  {
    if (push(val) == -1)
    {
      printf("Failed to push ");
      putchar(val);

      printf(". Exiting.");
      return -1;
    }
  }

  printf("Stack size %d \n", stackSize());

  while ( (val = pop()) != -1 ) putchar(val);

  return 0;
}