179 lines
5.6 KiB
C
Executable File
179 lines
5.6 KiB
C
Executable File
/* Type-safe stack data type.
|
||
Copyright (C) 2020-2024 Free Software Foundation, Inc.
|
||
|
||
This program is free software: you can redistribute it and/or modify
|
||
it under the terms of the GNU General Public License as published by
|
||
the Free Software Foundation, either version 3 of the License, or
|
||
(at your option) any later version.
|
||
|
||
This program 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 General Public License for more details.
|
||
|
||
You should have received a copy of the GNU General Public License
|
||
along with this program. If not, see <https://www.gnu.org/licenses/>. */
|
||
|
||
/* Written by Marc Nieper-Wißkirchen <marc@nieper-wisskirchen.de>, 2020. */
|
||
|
||
/* This header file does not have include-guards as it is meant to be
|
||
includable multiple times as long as the necessary defines have
|
||
been set up.
|
||
|
||
A stack is implemented with a homogenous array of elements in
|
||
memory, which will be resized (and moved) as needed. Elements are
|
||
passed by value and it is the responsibility of the user-code to
|
||
free any resources associated with individual elements.
|
||
|
||
The exported names are all prefixed by ‘stack’ (e.g. stack_init),
|
||
but this can be changed by setting an appropriate define.
|
||
Type: stack_type
|
||
Initialization: stack_init (&stack);
|
||
De-initialization: stack_destroy (&stack);
|
||
Predicate: bool res = stack_empty (&stack);
|
||
Introspection: ELEMENT *base = stack_current_base (&stack);
|
||
Pushing: stack_push (&stack, element);
|
||
Popping: ELEMENT element = stack_pop (&stack);
|
||
Discarding: stack_discard (&stack);
|
||
Top-of-stack: ELEMENT element = stack_top (&stack);
|
||
Size: idx_t size = stack_size (&stack);
|
||
|
||
Here, ELEMENT is the type to which GL_STACK_ELEMENT was defined when
|
||
this file was included.
|
||
*/
|
||
|
||
/* Before including this file, you need to define:
|
||
GL_STACK_ELEMENT The type of the elements on the stack.
|
||
GL_STACK_STORAGECLASS (Optional) The storage class specifier (e.g. static)
|
||
to use in the function definitions.
|
||
GL_STACK_NAME (Optional) The prefix to use for the type names
|
||
and functions definitions instead of the default
|
||
‘stack’.
|
||
|
||
After including this file, these names will be undefined.
|
||
|
||
Before including this file, you also need to include:
|
||
#include <stdlib.h>
|
||
#include "assure.h"
|
||
#include "xalloc.h"
|
||
*/
|
||
|
||
/* This file uses _GL_ATTRIBUTE_MAYBE_UNUSED, _GL_ATTRIBUTE_PURE. */
|
||
#if !_GL_CONFIG_H_INCLUDED
|
||
#error "Please include config.h first."
|
||
#endif
|
||
|
||
#ifndef GL_STACK_ELEMENT
|
||
# error "Please define GL_STACK_ELEMENT first."
|
||
#endif
|
||
|
||
#ifndef GL_STACK_STORAGECLASS
|
||
# define GL_STACK_STORAGECLASS
|
||
#endif
|
||
|
||
#ifndef GL_STACK_NAME
|
||
# define GL_STACK_NAME stack
|
||
#endif
|
||
|
||
#define _GL_STACK_PREFIX(name) _GL_CONCAT(GL_STACK_NAME, _GL_CONCAT(_, name))
|
||
#define _GL_STACK_TYPE _GL_STACK_PREFIX(type)
|
||
|
||
typedef struct
|
||
{
|
||
GL_STACK_ELEMENT *base;
|
||
idx_t size;
|
||
idx_t allocated;
|
||
} _GL_STACK_TYPE;
|
||
|
||
/* Initialize a stack. */
|
||
_GL_ATTRIBUTE_MAYBE_UNUSED
|
||
GL_STACK_STORAGECLASS void
|
||
_GL_STACK_PREFIX (init) (_GL_STACK_TYPE *stack)
|
||
{
|
||
stack->base = NULL;
|
||
stack->size = 0;
|
||
stack->allocated = 0;
|
||
}
|
||
|
||
/* Destroy a stack by freeing the allocated space. */
|
||
_GL_ATTRIBUTE_MAYBE_UNUSED
|
||
GL_STACK_STORAGECLASS void
|
||
_GL_STACK_PREFIX (destroy) (_GL_STACK_TYPE *stack)
|
||
{
|
||
free (stack->base);
|
||
}
|
||
|
||
/* Return true if the stack currently holds no element. */
|
||
_GL_ATTRIBUTE_MAYBE_UNUSED _GL_ATTRIBUTE_PURE
|
||
GL_STACK_STORAGECLASS bool
|
||
_GL_STACK_PREFIX (empty) (const _GL_STACK_TYPE *stack)
|
||
{
|
||
return stack->size == 0;
|
||
}
|
||
|
||
/* Return the current address of the array of stack elements.
|
||
|
||
The result is invalidated as soon as an element is added or removed
|
||
from the stack. */
|
||
_GL_ATTRIBUTE_MAYBE_UNUSED _GL_ATTRIBUTE_PURE
|
||
GL_STACK_STORAGECLASS GL_STACK_ELEMENT *
|
||
_GL_STACK_PREFIX (current_base) (const _GL_STACK_TYPE *stack)
|
||
{
|
||
return stack->base;
|
||
}
|
||
|
||
/* Push an element to the top of the stack. */
|
||
_GL_ATTRIBUTE_MAYBE_UNUSED
|
||
GL_STACK_STORAGECLASS void
|
||
_GL_STACK_PREFIX (push) (_GL_STACK_TYPE *stack, GL_STACK_ELEMENT item)
|
||
{
|
||
if (stack->size == stack->allocated)
|
||
stack->base = xpalloc (stack->base, &stack->allocated, 1, -1,
|
||
sizeof *stack->base);
|
||
stack->base [stack->size++] = item;
|
||
}
|
||
|
||
/* Pop the element from the top of the stack, which must be non-empty,
|
||
and return it. */
|
||
_GL_ATTRIBUTE_MAYBE_UNUSED
|
||
GL_STACK_STORAGECLASS GL_STACK_ELEMENT
|
||
_GL_STACK_PREFIX (pop) (_GL_STACK_TYPE *stack)
|
||
{
|
||
affirm (!_GL_STACK_PREFIX (empty) (stack));
|
||
return stack->base [--stack->size];
|
||
}
|
||
|
||
/* Pop the element from the top of the stack, which must be
|
||
non-empty. */
|
||
_GL_ATTRIBUTE_MAYBE_UNUSED
|
||
GL_STACK_STORAGECLASS void
|
||
_GL_STACK_PREFIX (discard) (_GL_STACK_TYPE *stack)
|
||
{
|
||
affirm (!_GL_STACK_PREFIX (empty) (stack));
|
||
--stack->size;
|
||
}
|
||
|
||
/* Return the element from the top of the stack, which must be
|
||
non-empty. */
|
||
_GL_ATTRIBUTE_MAYBE_UNUSED
|
||
GL_STACK_STORAGECLASS GL_STACK_ELEMENT
|
||
_GL_STACK_PREFIX (top) (const _GL_STACK_TYPE *stack)
|
||
{
|
||
affirm (!_GL_STACK_PREFIX (empty) (stack));
|
||
return stack->base [stack->size - 1];
|
||
}
|
||
|
||
/* Return the currently stored number of elements in the stack. */
|
||
_GL_ATTRIBUTE_MAYBE_UNUSED _GL_ATTRIBUTE_PURE
|
||
GL_STACK_STORAGECLASS idx_t
|
||
_GL_STACK_PREFIX (size) (const _GL_STACK_TYPE *stack)
|
||
{
|
||
return stack->size;
|
||
}
|
||
|
||
#undef GL_STACK_ELEMENT
|
||
#undef GL_STACK_STORAGECLASS
|
||
#undef GL_STACK_NAME
|
||
#undef _GL_STACK_PREFIX
|
||
#undef _GL_STACK_TYPE
|