/* $Progeny$ */

/**
 * @file stack.c
 * @brief Stack routines for Discover
 *
 * This is a generic stack routine that Discover uses.  The stack is needed
 * because there wasn't a good way to track the traversal depth through the
 * XML data.  These routines brought much sanity to the XML parsing
 * process.  They are generic enough that they can be used for any number
 * of applications.
 */

/*
 * AUTHOR: Josh Bressers <bressers@progeny.com>
 *
 * Copyright 2002 Progeny Linux Systems, Inc.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 * THE COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 */

#include <stdio.h>
#include <assert.h>
#include <stdbool.h>
#include <stdlib.h>

#include <discover/utils.h>
#include <discover/stack.h>


/** Routine responsible for creating the base of the stack */
discover_xml_stack * discover_xml_stack_new()
{
    discover_xml_stack *stack;
    stack = (discover_xml_stack *) _discover_xmalloc(sizeof(discover_xml_stack));
    assert(stack != NULL);

    stack->prev = NULL;
    stack->data = NULL;
    stack->depth = 0;

    return stack;
}

/** Routine responsible for destroying the stack base once we're done */
void discover_xml_stack_destroy(discover_xml_stack *stack)
{
    free(stack);
}

/** Push an item onto the stack. */
void
discover_xml_stack_push(discover_xml_stack **stack, void *data)
{
    discover_xml_stack *new_stack;

    new_stack = discover_xml_stack_new();


    new_stack->prev = *stack;
    new_stack->data = data;
    new_stack->depth = (*stack)->depth + 1;
    *stack = new_stack;
}

/** Pop an item from the stack. */
void * discover_xml_stack_pop(discover_xml_stack **stack)
{
    void *ctx;
    discover_xml_stack *oldstack;

    if((*stack)->prev == 0) {
        return NULL;
    }

    oldstack = *stack;
    ctx = (*stack)->data;

    *stack = (*stack)->prev;
    (*stack)->depth = oldstack->depth - 1;
    discover_xml_stack_destroy(oldstack);

    return ctx;
}

/** Return the top item without popping it. */
void * discover_xml_stack_get(discover_xml_stack *stack)
{
        return stack->data;
}

/** Return the item at depth i on the stack. */
void * discover_xml_stack_getbynum(discover_xml_stack *stack, int i)
{
    discover_xml_stack *S;

    S = stack;
    while(S->depth < i) {
        S = stack->prev;
    }
    return S->data;
}

/*
 * Local variables:
 * c-file-style: "progeny"
 * indent-tabs-mode: nil
 * End:
 */
/* vim: set cin fo=tcroq sw=4 et sts=4 tw=75: */
