222 lines
		
	
	
		
			5.0 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			222 lines
		
	
	
		
			5.0 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/**
 | 
						|
@cond IGNORE
 | 
						|
 | 
						|
======================================================
 | 
						|
 SFSEXP: Small, Fast S-Expression Library version 1.2
 | 
						|
 Written by Matthew Sottile (mjsottile@gmail.com)
 | 
						|
======================================================
 | 
						|
 | 
						|
Copyright (2003-2006). The Regents of the University of California. This
 | 
						|
material was produced under U.S. Government contract W-7405-ENG-36 for Los
 | 
						|
Alamos National Laboratory, which is operated by the University of
 | 
						|
California for the U.S. Department of Energy. The U.S. Government has rights
 | 
						|
to use, reproduce, and distribute this software. NEITHER THE GOVERNMENT NOR
 | 
						|
THE UNIVERSITY MAKES ANY WARRANTY, EXPRESS OR IMPLIED, OR ASSUMES ANY
 | 
						|
LIABILITY FOR THE USE OF THIS SOFTWARE. If software is modified to produce
 | 
						|
derivative works, such modified software should be clearly marked, so as not
 | 
						|
to confuse it with the version available from LANL.
 | 
						|
 | 
						|
Additionally, this library is free software; you can redistribute it and/or
 | 
						|
modify it under the terms of the GNU Lesser General Public License as
 | 
						|
published by the Free Software Foundation; either version 2.1 of the
 | 
						|
License, or (at your option) any later version.
 | 
						|
 | 
						|
This library is distributed in the hope that it will be useful, but WITHOUT
 | 
						|
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 | 
						|
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
 | 
						|
for more details.
 | 
						|
 | 
						|
You should have received a copy of the GNU Lesser General Public License
 | 
						|
along with this library; if not, write to the Free Software Foundation,
 | 
						|
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, U SA
 | 
						|
 | 
						|
LA-CC-04-094
 | 
						|
 | 
						|
@endcond
 | 
						|
**/
 | 
						|
/**
 | 
						|
 * faststack.c : implementation of fast stack.
 | 
						|
 *
 | 
						|
 * matt sottile / matt@lanl.gov
 | 
						|
 */
 | 
						|
#include <stdlib.h>
 | 
						|
#include <stdio.h>
 | 
						|
#include <sexpr/faststack.h>
 | 
						|
#include <sexpr/sexp.h>
 | 
						|
 | 
						|
/**
 | 
						|
 * create an empty stack.
 | 
						|
 */
 | 
						|
faststack_t *
 | 
						|
make_stack ()
 | 
						|
{
 | 
						|
  faststack_t *s;
 | 
						|
 | 
						|
#ifdef __cplusplus
 | 
						|
  s = (faststack_t *)sexp_malloc (sizeof (faststack_t));
 | 
						|
#else
 | 
						|
  s = sexp_malloc (sizeof (faststack_t));
 | 
						|
#endif
 | 
						|
 | 
						|
  if (s == NULL) {
 | 
						|
    sexp_errno = SEXP_ERR_MEMORY;
 | 
						|
    return NULL;
 | 
						|
  }
 | 
						|
 | 
						|
  s->top = s->bottom = NULL;
 | 
						|
  s->height = 0;
 | 
						|
 | 
						|
  return s;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * free all levels of a stack
 | 
						|
 */
 | 
						|
void
 | 
						|
destroy_stack (faststack_t * s)
 | 
						|
{
 | 
						|
  stack_lvl_t *sl;
 | 
						|
 | 
						|
  /* return if stack is null.  no error condition - just return. */
 | 
						|
  if (s == NULL)
 | 
						|
    return;
 | 
						|
 | 
						|
  /* start at the bottom */
 | 
						|
  sl = s->bottom;
 | 
						|
 | 
						|
  /* if bottom is null, no levels to free. just free stack itself then. */
 | 
						|
  if (sl == NULL) {
 | 
						|
    sexp_free(s, sizeof(faststack_t));
 | 
						|
    return;
 | 
						|
  }
 | 
						|
 | 
						|
  /* go up to the top of the allocated stack */
 | 
						|
  while (sl->above != NULL)
 | 
						|
    sl = sl->above;
 | 
						|
 | 
						|
  /* until we get to the bottom (where below is null), free the data
 | 
						|
     at each level and the level itself. */
 | 
						|
  while (sl->below != NULL)
 | 
						|
    {
 | 
						|
      sl = sl->below;
 | 
						|
      sexp_free (sl->above, sizeof(stack_lvl_t));
 | 
						|
    }
 | 
						|
 | 
						|
  /* free the bottom level */
 | 
						|
  sexp_free (sl, sizeof(stack_lvl_t));
 | 
						|
 | 
						|
  /* free the stack wrapper itself. */
 | 
						|
  sexp_free (s, sizeof(faststack_t));
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * push a level onto the cur_stack.  reuse levels that have
 | 
						|
 * been previously allocated, allocate a new one if none
 | 
						|
 * are available.
 | 
						|
 */
 | 
						|
faststack_t *
 | 
						|
push (faststack_t * cur_stack, void *data)
 | 
						|
{
 | 
						|
  stack_lvl_t *top, *tmp;
 | 
						|
 | 
						|
  if (cur_stack == NULL) {
 | 
						|
    sexp_errno = SEXP_ERR_BAD_STACK;
 | 
						|
    return NULL;
 | 
						|
  }
 | 
						|
 | 
						|
  top = cur_stack->top;
 | 
						|
 | 
						|
  /* if top isn't null, try to push above it. */
 | 
						|
  if (top != NULL)
 | 
						|
    {
 | 
						|
      /* if above isn't null, set the stack top to it and set the
 | 
						|
         data */
 | 
						|
      if (top->above != NULL)
 | 
						|
	{
 | 
						|
	  top = cur_stack->top = cur_stack->top->above;
 | 
						|
	  top->data = data;
 | 
						|
	}
 | 
						|
      else
 | 
						|
	{
 | 
						|
	  /* otherwise, allocate a new level. */
 | 
						|
 | 
						|
#ifdef __cplusplus
 | 
						|
	  tmp = top->above = (stack_level *)sexp_malloc (sizeof (stack_lvl_t));
 | 
						|
#else
 | 
						|
	  tmp = top->above = sexp_malloc (sizeof (stack_lvl_t));
 | 
						|
#endif
 | 
						|
 | 
						|
          if (tmp == NULL) {
 | 
						|
	    sexp_errno = SEXP_ERR_MEMORY;
 | 
						|
	    return NULL;
 | 
						|
	  }
 | 
						|
 | 
						|
	  tmp->below = cur_stack->top;
 | 
						|
	  tmp->above = NULL;
 | 
						|
	  cur_stack->top = tmp;
 | 
						|
	  tmp->data = data;
 | 
						|
	}
 | 
						|
    }
 | 
						|
  else
 | 
						|
    {
 | 
						|
      if (cur_stack->bottom != NULL)
 | 
						|
	{
 | 
						|
	  cur_stack->top = cur_stack->bottom;
 | 
						|
	  cur_stack->top->data = data;
 | 
						|
	}
 | 
						|
      else
 | 
						|
	{
 | 
						|
#ifdef __cplusplus
 | 
						|
	  tmp = cur_stack->top =
 | 
						|
            (stack_lvl_t *)sexp_malloc (sizeof (stack_lvl_t));
 | 
						|
#else
 | 
						|
	  tmp = cur_stack->top = sexp_malloc (sizeof (stack_lvl_t));
 | 
						|
#endif
 | 
						|
	  if (tmp == NULL) {
 | 
						|
	    sexp_errno = SEXP_ERR_MEMORY;
 | 
						|
	    return NULL;
 | 
						|
	  }
 | 
						|
 | 
						|
	  cur_stack->bottom = tmp;
 | 
						|
	  tmp->above = NULL;
 | 
						|
	  tmp->below = NULL;
 | 
						|
	  tmp->data = data;
 | 
						|
	}
 | 
						|
    }
 | 
						|
 | 
						|
  cur_stack->height++;
 | 
						|
 | 
						|
  return cur_stack;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * pop the top of the stack, return the stack level that was
 | 
						|
 * popped of.
 | 
						|
 */
 | 
						|
stack_lvl_t *
 | 
						|
pop (faststack_t * s)
 | 
						|
{
 | 
						|
  stack_lvl_t *top;
 | 
						|
 | 
						|
  if (s == NULL) {
 | 
						|
    sexp_errno = SEXP_ERR_BAD_STACK;
 | 
						|
    return NULL;
 | 
						|
  }
 | 
						|
 | 
						|
  top = s->top;
 | 
						|
 | 
						|
  /* if stack top isn't null, set the top pointer to the next
 | 
						|
     level down and return the old top. */
 | 
						|
  if (top != NULL && s->height > 0)
 | 
						|
    {
 | 
						|
      s->top = s->top->below;
 | 
						|
      s->height--;
 | 
						|
    }
 | 
						|
  else
 | 
						|
    {
 | 
						|
      if (s->height < 1) return NULL;
 | 
						|
    }
 | 
						|
 | 
						|
  return top;
 | 
						|
}
 |