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-10-17 11:55:37 +00:00
/* This file contains the function implementations for queues. */
/* Include guards + includes. */
# ifndef QUEUE_C
# define QUEUE_C
# include "queue.h"
# endif /* QUEUE_C */
/* Function implementations. */
/* This function initializes a new empty queue. */
/* Will return a pointer to the queue on success, otherwise will return NULL. */
2021-10-25 12:19:28 +00:00
queue_t * initialize_queue ( ) {
2021-10-17 11:55:37 +00:00
/* Variables. */
queue_t * result ;
/* Attempt to allocate. */
result = ( queue_t * ) malloc ( sizeof ( queue_t ) ) ;
/* Check if the allocation failed. */
if ( result = = NULL )
return NULL ;
/* Allocate the internal list struct. */
result - > list = ( list_t * ) malloc ( sizeof ( list_t ) ) ;
/* Check if the allocation failed. */
if ( result - > list = = NULL ) {
free ( result ) ;
return NULL ;
}
/* Initialize the internal fields. */
result - > tail = NULL ;
result - > list - > head = NULL ;
result - > list - > length = 0 ;
/* Return the result. */
return result ;
}
/* This function enqueues a node. */
/* This function attempts to enqueue a given node into the given queue, on success will return SUCCESS_CODE_QUEUE_C, otherwise will return FAILURE_CODE_QUEUE_C. */
/* Note that if either the queue or node pointer are NULL, the function will automatically fail. */
int enqueue ( queue_t * queue , node_t * node ) {
/* Input sanity check. */
if ( queue = = NULL | | queue - > list = = NULL | | node = = NULL | | ( ( queue - > list - > head = = NULL & & queue - > tail ! = NULL ) | | ( queue - > list - > head ! = NULL & & queue - > tail = = NULL ) ) )
return FAILURE_CODE_QUEUE_C ;
/* Attempt to enqueue the node. */
/* Check if the queue is empty. */
if ( queue - > list - > head = = NULL ) {
node - > next = NULL ;
queue - > tail = node ;
} else
node - > next = queue - > list - > head ;
/* Relink the head. */
queue - > list - > head = node ;
/* Increase the length. */
( queue - > list - > length ) + + ;
/* Success. */
return SUCCESS_CODE_QUEUE_C ;
}
2021-10-17 12:15:21 +00:00
2021-10-20 07:45:42 +00:00
/* This function allocates and enqueues a node. */
/* This function attempts to create a node then enqueue it into the given queue, on success will return SUCCESS_CODE_QUEUE_C, otherwise will return FAILURE_CODE_QUEUE_C. */
/* Note that if either the queue pointer is NULL or node allocation fails, the function will automatically fail. */
int enqueue_data ( queue_t * queue , void * data ) {
/* Variables. */
node_t * node ;
/* Input sanity check. */
if ( queue = = NULL | | queue - > list = = NULL | | ( ( queue - > list - > head = = NULL & & queue - > tail ! = NULL ) | | ( queue - > list - > head ! = NULL & & queue - > tail = = NULL ) ) )
return FAILURE_CODE_QUEUE_C ;
/* Attempt to allocate the node. */
node = ( node_t ) malloc ( sizeof ( node ) ) ;
if ( node = = NULL )
return FAILURE_CODE_QUEUE_C ;
/* Attempt to enqueue the node. */
/* Check if the queue is empty. */
if ( queue - > list - > head = = NULL ) {
node - > next = NULL ;
queue - > tail = node ;
} else
node - > next = queue - > list - > head ;
/* Relink the head. */
queue - > list - > head = node ;
/* Increase the length. */
( queue - > list - > length ) + + ;
/* Success. */
return SUCCESS_CODE_QUEUE_C ;
}
2021-10-17 12:15:21 +00:00
/* This function dequeues a node. */
/* This function attempts to dequeues a node from the given queue, on success will return a pointer to the dequeued node - otherwise returns NULL. */
/* Note that if either the queue or node pointer are NULL, the function will automatically fail. */
2021-10-25 12:19:28 +00:00
node_t * dequeue ( queue_t * queue ) {
2021-10-17 12:15:21 +00:00
/* Variables. */
2021-10-25 12:19:28 +00:00
node_t * result , * replacement , * tmp ;
2021-10-17 12:15:21 +00:00
int i ;
/* Input sanity check. */
if ( queue = = NULL | | queue - > list = = NULL | | ( ( queue - > list - > head = = NULL & & queue - > tail ! = NULL ) | | ( queue - > list - > head ! = NULL & & queue - > tail = = NULL ) ) )
return NULL ;
/* Attempt to dequeue the node. */
/* Check if the queue is empty. */
if ( queue - > list - > head = = NULL )
2021-10-25 13:51:53 +00:00
return NULL ;
2021-10-17 12:15:21 +00:00
else if ( queue - > list - > length = = 1 ) {
2021-10-25 13:51:53 +00:00
/* A queue that is of length 1. */
2021-10-17 12:15:21 +00:00
result = queue - > list - > head ;
queue - > list - > head = NULL ;
queue - > tail = NULL ;
} else {
2021-10-25 13:51:53 +00:00
/* This is the general case, move the tail and unlink. */
2021-10-25 12:19:28 +00:00
/* Set the result to be the tail. */
result = queue - > tail ;
/* Attempt to find the new tail. */
tmp = queue - > list - > head ;
while ( tmp - > next ! = result )
tmp = tmp - > next ;
/* Unlink and set the new tail. */
tmp - > next = NULL ;
queue - > tail = tmp ;
2021-10-17 12:15:21 +00:00
}
2021-10-25 12:19:28 +00:00
/* Decrease the length. */
( queue - > list - > length ) - - ;
2021-10-17 12:15:21 +00:00
/* Success. */
return SUCCESS_CODE_QUEUE_C ;
}
2021-10-20 07:45:42 +00:00
2021-10-25 12:19:28 +00:00
/* This function frees all the nodes of the given queue and the queue itself (setting it to NULL). */
/* Note that it doesn't touch the data stored within the queue's nodes, returns 1 on success and 0 on failure - in the latter case might exhibit undefined behavior. */
int clear_queue ( queue_t * * queue ) {
/* Sanity check. */
if ( queue = = NULL | | * queue = = NULL )
return FAILURE_CODE_QUEUE_C ;
/* Delegate to implementation (linked list). */
if ( ! clear_single_linked_list ( & ( ( * queue ) - > list ) ) )
return FAILURE_CODE_QUEUE_C ;
/* Successfully cleared the internal structure, just free the queue struct and set the pointer to NULL. */
free ( * queue ) ;
* queue = NULL ;
return SUCCESS_CODE_QUEUE_C ;
}
/* This function frees all the nodes of the given queue and the queue itself (setting it to NULL).*/
/* Note that it does free the stored data, returns 1 on success and 0 on failure - in the latter case might exhibit undefined behavior. */
/* If free_function is NULL, then it the standard library's free() call is used. */
int clear_queue ( queue_t * * queue , void ( * free_func ) ( ) ) {
/* Sanity check. */
if ( queue = = NULL | | * queue = = NULL )
return FAILURE_CODE_QUEUE_C ;
/* Delegate to implementation (linked list). */
if ( ! clear_single_linked_list ( & ( ( * queue ) - > list ) , free_function ) )
return FAILURE_CODE_QUEUE_C ;
/* Successfully cleared the internal structure, just free the queue struct and set the pointer to NULL. */
free ( * queue ) ;
* queue = NULL ;
return SUCCESS_CODE_QUEUE_C ;
}
2021-10-20 07:45:42 +00:00
/* This function serializes the queue. */
/* Note that it'll return NULL on allocation failure or invalid input - in the former case it'll set the correct length in the specified pointer, in the second it will set -1. */
void * * serialize_queue ( queue_t * queue , int * length ) {
/* Sanity check. */
if ( queue = = NULL ) {
* length = - 1 ;
return NULL ;
}
/* Delegate. */
return serialize_list ( queue - > list , length ) ;
}