2021-11-22 17:32:54 +00:00
/*
* 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/>.
*/
2021-08-29 14:26:31 +00:00
/* 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. */
2022-02-19 17:02:10 +00:00
static inline stack_t * initialize_stack ( ) {
2021-08-29 14:26:31 +00:00
/* Variables. */
stack_t * result ;
/* Attempt to allocate. */
result = ( stack_t * ) malloc ( sizeof ( stack_t ) ) ;
2022-02-19 17:02:10 +00:00
if ( ! result )
2021-08-29 14:26:31 +00:00
return NULL ;
/* Allocation succeeded, initialize and return. */
result - > size = INITIAL_STACK_SIZE ;
result - > head = NULL ;
return result ;
}
2022-02-19 17:02:10 +00:00
/* This function pops the current head node out, if it exists, otherwise will return NULL. */
static inline node_t * pop ( stack_t * stack ) {
2021-08-29 14:26:31 +00:00
/* Sanity check. */
2022-02-19 17:02:10 +00:00
assert ( stack & & ( stack - > head ) ) ;
2021-08-29 14:26:31 +00:00
/* Remove the head. */
node_t * head = stack - > head ;
stack - > head = head - > next ;
2022-02-19 17:02:10 +00:00
( stack - > size ) - = 1L ;
2021-08-29 14:26:31 +00:00
/* Return the head.*/
return head ;
}
2022-02-19 17:02:10 +00:00
/* This function "peeks" at the top of the stack. */
static inline const void * peek ( stack_t * stack ) {
2021-08-29 14:26:31 +00:00
/* Sanity check. */
2022-02-19 17:02:10 +00:00
assert ( stack & & ( stack - > head ) ) ;
2021-09-08 18:55:17 +00:00
/* Return the data in the head. */
return stack - > head - > data ;
2021-08-29 14:26:31 +00:00
}
2022-02-19 17:02:10 +00:00
/* This function pushes a node in. */
2021-08-29 14:26:31 +00:00
/* Will fail for a NULL stack or node! */
2022-02-19 17:02:10 +00:00
static inline void push ( stack_t * stack , node_t * node ) {
2021-08-29 14:26:31 +00:00
/* Sanity check. */
2022-02-19 17:02:10 +00:00
assert ( stack & & node ) ;
2021-08-29 14:26:31 +00:00
/* Try to push. */
/* Increase the count. */
( stack - > size ) + = 1 ;
/* Check if the head is NULL or not. */
2022-02-19 17:02:10 +00:00
if ( ! ( stack - > head ) ) {
2021-08-29 14:26:31 +00:00
stack - > head = node ;
node - > next = NULL ;
2022-02-19 17:02:10 +00:00
return ;
2021-08-29 14:26:31 +00:00
}
/* Relink the head. */
node - > next = stack - > head ;
stack - > head = node ;
}
/* 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. */
2022-02-19 17:02:10 +00:00
static inline int push_data ( stack_t * stack , void * data ) {
2021-08-29 14:26:31 +00:00
/* Sanity check. */
2022-02-19 17:02:10 +00:00
assert ( stack ) ;
2021-08-29 14:26:31 +00:00
/* Try to allocate the new node. */
node_t * node = ( node_t * ) malloc ( sizeof ( node_t ) ) ;
2022-02-19 17:02:10 +00:00
if ( ! node )
2021-08-29 14:26:31 +00:00
return PUSH_FAIL ;
/* Store the data in the node. */
node - > data = data ;
/* Delegate. */
2022-02-19 17:02:10 +00:00
push ( stack , node ) ;
return PUSH_SUCCESS ;
2021-08-29 14:26:31 +00:00
}
/* This function returns the stack's size, will return INVALID_SIZE for a NULL stack. */
2022-02-19 17:02:10 +00:00
static inline const size_t stack_size ( stack_t * stack ) {
2021-08-29 14:26:31 +00:00
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. */
2022-02-19 17:02:10 +00:00
static inline void free_stack ( stack_t * * stack ) {
2021-08-29 14:26:31 +00:00
/* Sanity check. */
2022-02-19 17:02:10 +00:00
assert ( stack & & * stack ) ;
2021-08-29 14:26:31 +00:00
/* Start by freeing node after node. */
node_t * current = ( * stack ) - > head ;
node_t * tmp ;
2022-02-19 17:02:10 +00:00
while ( current ) {
2021-08-29 14:26:31 +00:00
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. */
2022-02-19 17:02:10 +00:00
static inline void free_stack_data ( stack_t * * stack , void ( * free_function ) ( const void * ) ) {
2021-08-29 14:26:31 +00:00
/* Sanity check. */
2022-02-19 17:02:10 +00:00
assert ( stack & & * stack ) ;
2021-08-29 14:26:31 +00:00
/* Start by freeing node after node. */
node_t * current = ( * stack ) - > head ;
node_t * tmp ;
2022-02-19 17:02:10 +00:00
while ( current ) {
2021-08-29 14:26:31 +00:00
tmp = current - > next ;
2022-02-19 17:02:10 +00:00
if ( free_function )
2021-08-29 14:26:31 +00:00
free_function ( current - > data ) ;
else
free ( current - > data ) ;
free ( current ) ;
current = tmp ;
}
/* Free the stack. */
free ( * stack ) ;
* stack = NULL ;
}