149 lines
4.3 KiB
C
149 lines
4.3 KiB
C
/*
|
|
* C_lib Copyright (C) 2021 Wael Karram.
|
|
*
|
|
* 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, version 3 of the License.
|
|
*
|
|
* 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/>.
|
|
*/
|
|
|
|
/* This file contains the function implementations for a stack. */
|
|
/* Include guards + includes. */
|
|
#ifndef STACK_C
|
|
#define STACK_C
|
|
/* Include statements. */
|
|
#include "stack.h"
|
|
#endif /* STACK_C */
|
|
|
|
/* This function initializes a new empty stack. */
|
|
/* Returns a valid pointer on success, and NULL on failure. */
|
|
stack_t* initialize_stack() {
|
|
/* Variables. */
|
|
stack_t *result;
|
|
|
|
/* Attempt to allocate. */
|
|
result = (stack_t*) malloc(sizeof(stack_t));
|
|
if (result == NULL)
|
|
return NULL;
|
|
/* Allocation succeeded, initialize and return. */
|
|
result->size = INITIAL_STACK_SIZE;
|
|
result->head = NULL;
|
|
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) {
|
|
/* Sanity check. */
|
|
if (stack == NULL || stack->head == NULL)
|
|
return NULL;
|
|
|
|
/* Remove the head. */
|
|
node_t *head = stack->head;
|
|
stack->head = head->next;
|
|
(stack->size) -= 1;
|
|
|
|
/* 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) {
|
|
/* Sanity check. */
|
|
if (stack == NULL || stack->head == NULL)
|
|
return NULL;
|
|
|
|
/* 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. */
|
|
/* Will fail for a NULL stack or node! */
|
|
int push(stack_t *stack, node_t *node) {
|
|
/* Sanity check. */
|
|
if (stack == NULL || node == NULL)
|
|
return PUSH_FAIL;
|
|
/* Try to push. */
|
|
/* Increase the count. */
|
|
(stack->size) += 1;
|
|
/* Check if the head is NULL or not. */
|
|
if (stack->head == NULL) {
|
|
stack->head = node;
|
|
node->next = NULL;
|
|
return PUSH_SUCCESS;
|
|
}
|
|
/* 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) {
|
|
/* Sanity check. */
|
|
if (stack == NULL)
|
|
return PUSH_FAIL;
|
|
/* Try to allocate the new node. */
|
|
node_t *node = (node_t*) malloc(sizeof(node_t));
|
|
if (node == NULL)
|
|
return PUSH_FAIL;
|
|
/* Store the data in the node. */
|
|
node->data = data;
|
|
/* Delegate. */
|
|
return push(stack, node);
|
|
}
|
|
|
|
/* This function returns the stack's size, will return INVALID_SIZE for a NULL stack. */
|
|
int 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) {
|
|
/* Sanity check. */
|
|
if (stack == NULL || *stack == NULL)
|
|
return;
|
|
/* Start by freeing node after node. */
|
|
node_t *current = (*stack)->head;
|
|
node_t *tmp;
|
|
while (current != NULL) {
|
|
tmp = current->next;
|
|
free(current);
|
|
current = tmp;
|
|
}
|
|
/* Free the stack. */
|
|
free(*stack);
|
|
*stack = NULL;
|
|
}
|
|
|
|
/* 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*)) {
|
|
/* Sanity check. */
|
|
if (stack == NULL || *stack == NULL)
|
|
return;
|
|
/* Start by freeing node after node. */
|
|
node_t *current = (*stack)->head;
|
|
node_t *tmp;
|
|
while (current != NULL) {
|
|
tmp = current->next;
|
|
if (free_function != NULL)
|
|
free_function(current->data);
|
|
else
|
|
free(current->data);
|
|
free(current);
|
|
current = tmp;
|
|
}
|
|
/* Free the stack. */
|
|
free(*stack);
|
|
*stack = NULL;
|
|
}
|