Update stack: better debugging and faster runtime performance.
This commit is contained in:
parent
1957808b0e
commit
d1b2cb96a6
|
@ -24,13 +24,13 @@
|
|||
|
||||
/* This function initializes a new empty stack. */
|
||||
/* Returns a valid pointer on success, and NULL on failure. */
|
||||
stack_t* initialize_stack() {
|
||||
static inline stack_t* initialize_stack() {
|
||||
/* Variables. */
|
||||
stack_t *result;
|
||||
|
||||
/* Attempt to allocate. */
|
||||
result = (stack_t*) malloc(sizeof(stack_t));
|
||||
if (result == NULL)
|
||||
if (!result)
|
||||
return NULL;
|
||||
/* Allocation succeeded, initialize and return. */
|
||||
result->size = INITIAL_STACK_SIZE;
|
||||
|
@ -38,83 +38,81 @@ stack_t* initialize_stack() {
|
|||
return result;
|
||||
}
|
||||
|
||||
/* This function pops the current head node out, if it exists, otherwise will return NULL (also returns NULL on errornous input). */
|
||||
node_t* pop(stack_t *stack) {
|
||||
/* This function pops the current head node out, if it exists, otherwise will return NULL. */
|
||||
static inline node_t* pop(stack_t *stack) {
|
||||
/* Sanity check. */
|
||||
if (stack == NULL || stack->head == NULL)
|
||||
return NULL;
|
||||
assert(stack && (stack->head));
|
||||
|
||||
/* Remove the head. */
|
||||
node_t *head = stack->head;
|
||||
stack->head = head->next;
|
||||
(stack->size) -= 1;
|
||||
(stack->size) -= 1L;
|
||||
|
||||
/* Return the head.*/
|
||||
return head;
|
||||
}
|
||||
|
||||
/* This function "peeks" at the top of the stack, will return NULL on error (in input/internal). */
|
||||
const void* peek(stack_t *stack) {
|
||||
/* This function "peeks" at the top of the stack. */
|
||||
static inline const void* peek(stack_t *stack) {
|
||||
/* Sanity check. */
|
||||
if (stack == NULL || stack->head == NULL)
|
||||
return NULL;
|
||||
assert(stack && (stack->head));
|
||||
|
||||
/* Return the data in the head. */
|
||||
return stack->head->data;
|
||||
}
|
||||
|
||||
/* This function pushes a node in, returns PUSH_SUCCESS on succes and PUSH_FAIL on failure. */
|
||||
/* This function pushes a node in. */
|
||||
/* Will fail for a NULL stack or node! */
|
||||
int push(stack_t *stack, node_t *node) {
|
||||
static inline void push(stack_t *stack, node_t *node) {
|
||||
/* Sanity check. */
|
||||
if (stack == NULL || node == NULL)
|
||||
return PUSH_FAIL;
|
||||
assert(stack && node);
|
||||
|
||||
/* Try to push. */
|
||||
/* Increase the count. */
|
||||
(stack->size) += 1;
|
||||
/* Check if the head is NULL or not. */
|
||||
if (stack->head == NULL) {
|
||||
if (!(stack->head)) {
|
||||
stack->head = node;
|
||||
node->next = NULL;
|
||||
return PUSH_SUCCESS;
|
||||
return;
|
||||
}
|
||||
/* Relink the head. */
|
||||
node->next = stack->head;
|
||||
stack->head = node;
|
||||
return PUSH_SUCCESS;
|
||||
}
|
||||
|
||||
/* This function creates a node, stores the given data and pushes it into the stack, will fail on a NULL stack or allocation errors. */
|
||||
/* Returns PUSH_SUCCESS on success, and PUSH_FAIL on failure. */
|
||||
int push_data(stack_t *stack, void *data) {
|
||||
static inline int push_data(stack_t *stack, void *data) {
|
||||
/* Sanity check. */
|
||||
if (stack == NULL)
|
||||
return PUSH_FAIL;
|
||||
assert(stack);
|
||||
|
||||
/* Try to allocate the new node. */
|
||||
node_t *node = (node_t*) malloc(sizeof(node_t));
|
||||
if (node == NULL)
|
||||
if (!node)
|
||||
return PUSH_FAIL;
|
||||
/* Store the data in the node. */
|
||||
node->data = data;
|
||||
/* Delegate. */
|
||||
return push(stack, node);
|
||||
push(stack, node);
|
||||
return PUSH_SUCCESS;
|
||||
}
|
||||
|
||||
/* This function returns the stack's size, will return INVALID_SIZE for a NULL stack. */
|
||||
int stack_size(stack_t *stack) {
|
||||
static inline const size_t stack_size(stack_t *stack) {
|
||||
return (stack == NULL) ? INVALID_SIZE : stack->size;
|
||||
}
|
||||
|
||||
/* This function frees a stack, doesn't touch the data. */
|
||||
/* Takes a pointer to a pointer so it can set the original pointer to NULL. */
|
||||
void free_stack(stack_t **stack) {
|
||||
static inline void free_stack(stack_t **stack) {
|
||||
/* Sanity check. */
|
||||
if (stack == NULL || *stack == NULL)
|
||||
return;
|
||||
assert(stack && *stack);
|
||||
|
||||
/* Start by freeing node after node. */
|
||||
node_t *current = (*stack)->head;
|
||||
node_t *tmp;
|
||||
while (current != NULL) {
|
||||
while (current) {
|
||||
tmp = current->next;
|
||||
free(current);
|
||||
current = tmp;
|
||||
|
@ -126,16 +124,16 @@ void free_stack(stack_t **stack) {
|
|||
|
||||
/* This function frees a stack and the data stored within the nodes thereof, if free_function is NULL will use STDLIB's free() instead to free the data. */
|
||||
/* Takes a pointer to a pointer so it can set the original pointer to NULL. */
|
||||
void free_stack_data(stack_t **stack, void (*free_function)(const void*)) {
|
||||
static inline void free_stack_data(stack_t **stack, void (*free_function)(const void*)) {
|
||||
/* Sanity check. */
|
||||
if (stack == NULL || *stack == NULL)
|
||||
return;
|
||||
assert(stack && *stack);
|
||||
|
||||
/* Start by freeing node after node. */
|
||||
node_t *current = (*stack)->head;
|
||||
node_t *tmp;
|
||||
while (current != NULL) {
|
||||
while (current) {
|
||||
tmp = current->next;
|
||||
if (free_function != NULL)
|
||||
if (free_function)
|
||||
free_function(current->data);
|
||||
else
|
||||
free(current->data);
|
||||
|
|
|
@ -19,6 +19,13 @@
|
|||
#define STACK_H
|
||||
/* Include stdlib. */
|
||||
#include <stdlib.h>
|
||||
/* Include assert.h to allow code generation, but only run with debug flag. */
|
||||
#ifdef DEBUG
|
||||
#ifndef NDEBUG
|
||||
#define NDEBUG
|
||||
#endif /* NDEBUG. */
|
||||
#endif /* DEBUG. */
|
||||
#include <assert.h>
|
||||
/* Include the single node header. */
|
||||
#include "../nodes/single_node.h"
|
||||
|
||||
|
@ -31,27 +38,27 @@
|
|||
/* The actual stack struct. */
|
||||
typedef struct stack {
|
||||
/* Store the stack's total size. */
|
||||
int size;
|
||||
size_t size;
|
||||
/* Stores the current last node. */
|
||||
node_t *head;
|
||||
} stack_t;
|
||||
|
||||
/* Function declarations. */
|
||||
/* This function initializes a new empty stack. */
|
||||
stack_t* initialize_stack();
|
||||
static inline stack_t* initialize_stack();
|
||||
/* This function pops a node out. */
|
||||
node_t* pop(stack_t *stack);
|
||||
static inline node_t* pop(stack_t *stack);
|
||||
/* This function "peeks" into the top node. */
|
||||
const void* peek(stack_t *stack);
|
||||
static inline const void* peek(stack_t *stack);
|
||||
/* This function pushes a node in. */
|
||||
int push(stack_t *stack, node_t *node);
|
||||
static inline void push(stack_t *stack, node_t *node);
|
||||
/* This function creates a node, stores the data and pushes it in. */
|
||||
int push_data(stack_t *stack, void *data);
|
||||
static inline int push_data(stack_t *stack, void *data);
|
||||
/* This function returns the stack's size. */
|
||||
int stack_size(stack_t *stack);
|
||||
static inline size_t stack_size(stack_t *stack);
|
||||
/* This function frees a stack, doen't touch the data. */
|
||||
void free_stack(stack_t **stack);
|
||||
static inline void free_stack(stack_t **stack);
|
||||
/* This function frees a stack and the data stored within. */
|
||||
void free_stack_data(stack_t **stack, void (*free_function)(const void*));
|
||||
static inline void free_stack_data(stack_t **stack, void (*free_function)(const void*));
|
||||
|
||||
#endif /*STACK_H*/
|
||||
|
|
|
@ -41,7 +41,7 @@ single_linked_list_tests.out: single_linked_list_tests.c
|
|||
gcc -g -D DEBUG -fmem-report -fstack-usage -fsanitize=address -fsanitize=leak -fsanitize=undefined single_linked_list_tests.c -o single_linked_list_tests.out
|
||||
|
||||
stack_tests.out: stack_tests.c
|
||||
gcc -g -fsanitize=address -fsanitize=leak -fsanitize=undefined stack_tests.c -o stack_tests.out
|
||||
gcc -g -D DEBUG -fmem-report -fstack-usage -fsanitize=address -fsanitize=leak -fsanitize=undefined stack_tests.c -o stack_tests.out
|
||||
|
||||
tree_tests.out: tree_tests.c
|
||||
gcc -g -fanalyzer -Wanalyzer-too-complex -fanalyzer-call-summaries -fsanitize=address -fsanitize=leak -fsanitize=undefined tree_tests.c -o tree_tests.out
|
||||
|
|
|
@ -71,10 +71,7 @@ int test_stack() {
|
|||
printf(TEST_CODE_FAILURE);
|
||||
return 1;
|
||||
}
|
||||
if (!push(stack, node)) {
|
||||
printf(SOME_TEST_FAILED);
|
||||
return 1;
|
||||
}
|
||||
push(stack, node);
|
||||
assert(stack->size == STACK_SIZE_ONE);
|
||||
assert(stack->head != NULL);
|
||||
assert(stack->head->next == NULL);
|
||||
|
|
Loading…
Reference in New Issue