2024-04-22 00:09:51 +08:00

231 lines
5.6 KiB
C

/*********************************************************************************************************
* ------------------------------------------------------------------------------------------------------
* file description
* ------------------------------------------------------------------------------------------------------
* \file deque.c
* \unit deque
* \brief This is a C language deque
* \author Lamdonn
* \version v1.0.0
* \license GPL-2.0
* \copyright Copyright (C) 2023 Lamdonn.
********************************************************************************************************/
#include "deque.h"
#include <string.h>
/* type of deque */
typedef struct DEQUE
{
void* base; /**< base address of data */
int cst; /**< base const */
int dsize; /**< size of deque data */
int capacity; /**< capacity of deque */
int size; /**< size of deque */
int head; /**< index of deque head */
int tail; /**< index of deque tail */
} DEQUE;
/* Address of deque array */
#define at(i) (((unsigned char *)(deque->base))+(i)*(deque->dsize))
deque_t deque_create(int dsize, int capacity, void *base)
{
deque_t deque;
/* Input value validity check */
if (dsize <= 0) return NULL;
if (capacity <= 0) return NULL;
/* Allocate memory for the DEQUE structure */
deque = (deque_t)malloc(sizeof(DEQUE));
if (!deque) return NULL;
/* Initialize structural parameters */
deque->base = base;
deque->cst = 1;
deque->capacity = capacity;
deque->dsize = dsize;
deque->tail = 0;
deque->head = 0;
deque->size = 0;
/* Dynamically allocate an array without passing it in */
if (!deque->base)
{
deque->base = malloc(dsize * capacity);
deque->cst = 0;
}
/* Check if the array space is valid */
if (!deque->base)
{
deque_delete(deque);
return NULL;
}
return deque;
}
void deque_delete(deque_t deque)
{
/* Input value validity check */
if (!deque) return;
/* If it is not a constant array but a dynamic array, release the allocated space */
if (!deque->cst && deque->base) free(deque->base);
/* Free deque structure */
free(deque);
}
int deque_push_front(deque_t deque, void* data)
{
/* Input value validity check */
if (!deque) return 0;
/* Check if the deque is full */
if (deque_full(deque)) return 0;
/* Update deque status */
deque->head = (deque->head + deque->capacity - 1) % deque->capacity;
deque->size++;
/* Assigning data to the deque */
if (data) memcpy(at(deque->head), data, deque->dsize);
return 1;
}
int deque_push_back(deque_t deque, void* data)
{
/* Input value validity check */
if (!deque) return 0;
/* Check if the deque is full */
if (deque_full(deque)) return 0;
/* Assigning data to the deque */
if (data) memcpy(at(deque->tail), data, deque->dsize);
/* Update deque status */
deque->tail = (deque->tail + 1) % deque->capacity;
deque->size++;
return 1;
}
int deque_pop_front(deque_t deque, void* data)
{
/* Input value validity check */
if (!deque) return 0;
/* Check if the deque is full */
if (deque_empty(deque)) return 0;
/* Assigning data from the deque */
if (data) memcpy(data, at(deque->head), deque->dsize);
/* Update deque status */
deque->head = (deque->head + 1) % deque->capacity;
deque->size--;
return 1;
}
int deque_pop_back(deque_t deque, void* data)
{
/* Input value validity check */
if (!deque) return 0;
/* Check if the deque is full */
if (deque_empty(deque)) return 0;
/* Update deque status */
deque->tail = (deque->tail + deque->capacity - 1) % deque->capacity;
deque->size--;
/* Assigning data from the deque */
if (data) memcpy(data, at(deque->tail), deque->dsize);
return 1;
}
void deque_clear(deque_t deque)
{
/* Input value validity check */
if (!deque) return;
/* Reset deque status */
deque->tail = 0;
deque->head = 0;
deque->size = 0;
}
int deque_index(deque_t deque, int index)
{
/* Input value validity check */
if (!deque) return -1;
if (index < 0 || index >= deque->size) return -1;
/* Starting from the head, calculate the data index */
return (deque->head + index) % (deque->capacity);
}
void* deque_data(deque_t deque, int index)
{
/* Input value validity check */
if (!deque) return NULL;
/* Get indexe for accessing data */
index = deque_index(deque, index);
if (index < 0) return NULL;
/* Return array address based on index */
return (void*)at(index);
}
int deque_size(deque_t deque)
{
/* Input value validity check */
if (!deque) return 0;
/* Return deque size */
return deque->size;
}
int deque_capacity(deque_t deque)
{
/* Input value validity check */
if (!deque) return 0;
/* Return deque capacity */
return deque->capacity;
}
int deque_dsize(deque_t deque)
{
/* Input value validity check */
if (!deque) return 0;
/* Return deque data size */
return deque->dsize;
}
int deque_empty(deque_t deque)
{
/* Input value validity check */
if (!deque) return 1;
/* Determine if size is 0 */
return (deque->size == 0) ? 1 : 0;
}
int deque_full(deque_t deque)
{
/* Input value validity check */
if (!deque) return 0;
/* Determine if size is capacity */
return (deque->size == deque->capacity) ? 1 : 0;
}