You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
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;
|
|
}
|