bug-gnulib
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH] stack: New module.


From: Marc Nieper-Wißkirchen
Subject: [PATCH] stack: New module.
Date: Sat, 10 Oct 2020 22:55:12 +0200

From: Marc Nieper-Wißkirchen <marc@nieper-wisskirchen.de>

* MODULES.html.sh: Add entry for the stack module.
* modules/stack: New file.
* modules/stack-tests: New file.
* lib/stack.h: New file.
* tests/test-stack.c: New file.
---
 ChangeLog           |   9 +++
 MODULES.html.sh     |   1 +
 lib/stack.h         | 165 ++++++++++++++++++++++++++++++++++++++++++++
 modules/stack       |  25 +++++++
 modules/stack-tests |  13 ++++
 tests/test-stack.c  |  74 ++++++++++++++++++++
 6 files changed, 287 insertions(+)
 create mode 100644 lib/stack.h
 create mode 100644 modules/stack
 create mode 100644 modules/stack-tests
 create mode 100644 tests/test-stack.c

diff --git a/ChangeLog b/ChangeLog
index b479cf0c7..f496c8345 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,12 @@
+2020-10-10  Marc Nieper-Wißkirchen  <marc@nieper-wisskirchen.de>
+
+       stack: New module.
+       * MODULES.html.sh: Add entry for the stack module.
+       * modules/stack: New file.
+       * modules/stack-tests: New file.
+       * lib/stack.h: New file.
+       * tests/test-stack.c: New file.
+
 2020-10-10  Paul Eggert  <eggert@cs.ucla.edu>
 
        attribute: improve const, pure doc
diff --git a/MODULES.html.sh b/MODULES.html.sh
index a8a629e29..7e7cdae3e 100755
--- a/MODULES.html.sh
+++ b/MODULES.html.sh
@@ -2031,6 +2031,7 @@ func_all_modules ()
   func_module readline
   func_module readtokens
   func_module readtokens0
+  func_module stack
   func_module strverscmp
   func_module filevercmp
   func_end_table
diff --git a/lib/stack.h b/lib/stack.h
new file mode 100644
index 000000000..5d803901c
--- /dev/null
+++ b/lib/stack.h
@@ -0,0 +1,165 @@
+/* Type-safe stack data type.
+   Copyright (C) 2020 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
+   includeable 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_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:               size_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 "<stdbool.h>"
+     #include "<stdlib.h>"
+     #include "assure.h"
+     #include "xalloc.h"
+*/
+
+#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;
+  size_t size;
+  size_t allocated;
+} _GL_STACK_TYPE;
+
+/* Initialize a stack.  */
+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_STACK_STORAGECLASS void
+_GL_STACK_PREFIX (destroy) (_GL_STACK_TYPE *stack)
+{
+  free (stack->base);
+}
+
+/* Return true if the stack currently holds no element.  */
+GL_STACK_STORAGECLASS _GL_ATTRIBUTE_PURE 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_STACK_STORAGECLASS _GL_ATTRIBUTE_PURE 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_STACK_STORAGECLASS void
+_GL_STACK_PREFIX (push) (_GL_STACK_TYPE *stack, GL_STACK_ELEMENT item)
+{
+  if (stack->size == stack->allocated)
+    stack->base = x2nrealloc (stack->base, &stack->allocated,
+                              sizeof (GL_STACK_ELEMENT));
+  stack->base [stack->size++] = item;
+}
+
+/* Pop the element from the top of the stack, which must be non-empty,
+   and return it. */
+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_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_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_STACK_STORAGECLASS _GL_ATTRIBUTE_PURE size_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
diff --git a/modules/stack b/modules/stack
new file mode 100644
index 000000000..95f2ce9b9
--- /dev/null
+++ b/modules/stack
@@ -0,0 +1,25 @@
+Description:
+Type-safe stack data type.
+
+Files:
+lib/stack.h
+
+Depends-on:
+assure
+stdbool
+stdlib
+xalloc
+
+configure.ac:
+
+Makefile.am:
+lib_SOURCES += stack.h
+
+Include:
+"stack.h"
+
+License:
+GPL
+
+Maintainer:
+Marc Nieper-Wißkirchen
diff --git a/modules/stack-tests b/modules/stack-tests
new file mode 100644
index 000000000..308d7258e
--- /dev/null
+++ b/modules/stack-tests
@@ -0,0 +1,13 @@
+Files:
+tests/test-stack.c
+tests/macros.h
+
+Depends-on:
+string
+
+configure.ac:
+
+Makefile.am:
+TESTS += test-stack
+check_PROGRAMS += test-stack
+test_stack_SOURCES = test-stack.c
diff --git a/tests/test-stack.c b/tests/test-stack.c
new file mode 100644
index 000000000..dbf4e19a3
--- /dev/null
+++ b/tests/test-stack.c
@@ -0,0 +1,74 @@
+/* Test of the type-safe stack data type.
+   Copyright (C) 2020 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.  */
+
+#include <config.h>
+
+#include <stdbool.h>
+#include <stdlib.h>
+#include <string.h>
+#include "assure.h"
+#include "xalloc.h"
+
+#include "macros.h"
+
+#define GL_STACK_ELEMENT int
+#define GL_STACK_STORAGECLASS static
+#include "stack.h"
+
+#define GL_STACK_ELEMENT const char *
+#define GL_STACK_STORAGECLASS static
+#define GL_STACK_NAME string_stack
+#include "stack.h"
+
+int
+main (void)
+{
+  stack_type int_stack;
+  stack_init (&int_stack);
+  ASSERT (stack_size (&int_stack) == 0);
+  ASSERT (stack_empty (&int_stack));
+  stack_push (&int_stack, 0);
+  stack_push (&int_stack, 1);
+  stack_push (&int_stack, 2);
+  stack_push (&int_stack, 3);
+  stack_push (&int_stack, 4);
+  stack_push (&int_stack, 5);
+  stack_push (&int_stack, 6);
+  stack_push (&int_stack, 7);
+  stack_push (&int_stack, 8);
+  stack_push (&int_stack, 9);
+  ASSERT (stack_size (&int_stack) == 10);
+  ASSERT (!stack_empty (&int_stack));
+  ASSERT (stack_top (&int_stack) == 9);
+  ASSERT (stack_size (&int_stack) == 10);
+  ASSERT (stack_pop (&int_stack) == 9);
+  ASSERT (stack_size (&int_stack) == 9);
+  stack_discard (&int_stack);
+  ASSERT (stack_size (&int_stack) == 8);
+  ASSERT (stack_top (&int_stack) == 7);
+  stack_destroy (&int_stack);
+
+  string_stack_type string_stack [1];
+  string_stack_init (string_stack);
+  string_stack_push (string_stack, "foo");
+  ASSERT (STREQ (string_stack_pop (string_stack), "foo"));
+  ASSERT (string_stack_empty (string_stack));
+  string_stack_destroy (string_stack);
+
+  return EXIT_SUCCESS;
+}
-- 
2.25.1




reply via email to

[Prev in Thread] Current Thread [Next in Thread]