mirror of
https://github.com/bkthomps/Containers.git
synced 2025-11-16 12:34:47 +00:00
Add queue
This commit is contained in:
180
src/queue.c
Normal file
180
src/queue.c
Normal file
@@ -0,0 +1,180 @@
|
||||
/*
|
||||
* Copyright (c) 2017 Bailey Thompson
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "deque.h"
|
||||
#include "queue.h"
|
||||
|
||||
const int TRIM_SIZE = 64;
|
||||
|
||||
struct _queue {
|
||||
int trim_count;
|
||||
deque deque_data;
|
||||
};
|
||||
|
||||
/**
|
||||
* Initializes a queue which is first-in first-out.
|
||||
*
|
||||
* @param data_size The size of each element.
|
||||
*
|
||||
* @return The newly-initialized queue, or NULL if out of memory.
|
||||
*/
|
||||
queue queue_init(const size_t data_size) {
|
||||
struct _queue *const init = malloc(sizeof(struct _queue));
|
||||
if (init == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
init->trim_count = 0;
|
||||
init->deque_data = deque_init(data_size);
|
||||
if (init->deque_data == NULL) {
|
||||
free(init);
|
||||
return NULL;
|
||||
}
|
||||
return init;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines the size of the queue.
|
||||
*
|
||||
* @param me The queue to get size of.
|
||||
*
|
||||
* @return The queue size.
|
||||
*/
|
||||
int queue_size(queue me) {
|
||||
return deque_size(me->deque_data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if the queue is empty. The queue is empty if it contains no
|
||||
* elements.
|
||||
*
|
||||
* @param me The queue to check if empty.
|
||||
*
|
||||
* @return If the queue is empty.
|
||||
*/
|
||||
bool queue_is_empty(queue me) {
|
||||
return deque_is_empty(me->deque_data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Frees the unused memory in the queue.
|
||||
*
|
||||
* @param me The queue to trim.
|
||||
*
|
||||
* @return 0 No error.
|
||||
* -ENOMEM Out of memory.
|
||||
*/
|
||||
int queue_trim(queue me) {
|
||||
return deque_trim(me->deque_data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Copies the queue to an array representation.
|
||||
*
|
||||
* @param array The array to have copied from the queue.
|
||||
* @param me The queue to copy to the array.
|
||||
*/
|
||||
void queue_to_array(void *const array, queue me) {
|
||||
deque_to_array(array, me->deque_data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an element to the queue.
|
||||
*
|
||||
* @param me The queue to add an element to.
|
||||
* @param data The data to add to the queue.
|
||||
*
|
||||
* @return 0 No error.
|
||||
* -ENOMEM Out of memory.
|
||||
*/
|
||||
int queue_push(queue me, void *const data) {
|
||||
return deque_push_back(me->deque_data, data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the next element in the queue and copies the data.
|
||||
*
|
||||
* @param data The data to have copied from the queue.
|
||||
* @param me The queue to pop the next element from.
|
||||
*
|
||||
* @return 0 No error.
|
||||
* -EINVAL Invalid argument.
|
||||
*/
|
||||
int queue_pop(void *const data, queue me) {
|
||||
me->trim_count++;
|
||||
if (me->trim_count >= TRIM_SIZE) {
|
||||
deque_trim(me->deque_data);
|
||||
me->trim_count = 0;
|
||||
}
|
||||
return deque_pop_front(data, me->deque_data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the front element of the queue.
|
||||
*
|
||||
* @param data Copies the front element of the queue.
|
||||
* @param me The queue to copy from.
|
||||
*
|
||||
* @return 0 No error.
|
||||
* -EINVAL Invalid argument.
|
||||
*/
|
||||
int queue_front(void *const data, queue me) {
|
||||
return deque_get_first(data, me->deque_data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the back element of the queue.
|
||||
*
|
||||
* @param data Copies the back element of the queue.
|
||||
* @param me The queue to copy from.
|
||||
*
|
||||
* @return 0 No error.
|
||||
* -EINVAL Invalid argument.
|
||||
*/
|
||||
int queue_back(void *const data, queue me) {
|
||||
return deque_get_last(data, me->deque_data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the queue and sets it to the original state from initialization.
|
||||
*
|
||||
* @param me The queue to clear.
|
||||
*
|
||||
* @return 0 No error.
|
||||
* -ENOMEM Out of memory.
|
||||
*/
|
||||
int queue_clear(queue me) {
|
||||
return deque_clear(me->deque_data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroys the queue.
|
||||
*
|
||||
* @param me The queue to destroy.
|
||||
*
|
||||
* @return NULL
|
||||
*/
|
||||
queue queue_destroy(queue me) {
|
||||
deque_destroy(me->deque_data);
|
||||
free(me);
|
||||
return NULL;
|
||||
}
|
||||
48
src/queue.h
Normal file
48
src/queue.h
Normal file
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright (c) 2017 Bailey Thompson
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef CONTAINERS_QUEUE_H
|
||||
#define CONTAINERS_QUEUE_H
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
typedef struct _queue *queue;
|
||||
|
||||
// Starting
|
||||
queue queue_init(size_t data_size);
|
||||
// Utility
|
||||
int queue_size(queue me);
|
||||
bool queue_is_empty(queue me);
|
||||
int queue_trim(queue me);
|
||||
void queue_to_array(void *array, queue me);
|
||||
// Adding
|
||||
int queue_push(queue me, void *data);
|
||||
// Removing
|
||||
int queue_pop(void *data, queue me);
|
||||
// Getting
|
||||
int queue_front(void *data, queue me);
|
||||
int queue_back(void *data, queue me);
|
||||
// Ending
|
||||
int queue_clear(queue me);
|
||||
queue queue_destroy(queue me);
|
||||
|
||||
#endif /* CONTAINERS_QUEUE_H */
|
||||
@@ -21,8 +21,8 @@
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "stack.h"
|
||||
#include "deque.h"
|
||||
#include "stack.h"
|
||||
|
||||
struct _stack {
|
||||
deque deque_data;
|
||||
@@ -36,7 +36,7 @@ struct _stack {
|
||||
* @return The newly-initialized stack, or NULL if could not allocate memory.
|
||||
*/
|
||||
stack stack_init(const size_t data_size) {
|
||||
struct _stack *init = malloc(sizeof(struct _stack));
|
||||
struct _stack *const init = malloc(sizeof(struct _stack));
|
||||
if (init == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
44
tst/test.c
44
tst/test.c
@@ -6,6 +6,7 @@
|
||||
#include "../src/forward_list.h"
|
||||
#include "../src/deque.h"
|
||||
#include "../src/stack.h"
|
||||
#include "../src/queue.h"
|
||||
|
||||
static void test_vector(void) {
|
||||
int val[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
|
||||
@@ -483,15 +484,58 @@ static void test_stack(void) {
|
||||
assert(stack_size(me) == 1);
|
||||
stack_clear(me);
|
||||
assert(stack_size(me) == 0);
|
||||
int get = 0;
|
||||
assert(stack_pop(&get, me) == -EINVAL);
|
||||
assert(stack_top(&get, me) == -EINVAL);
|
||||
me = stack_destroy(me);
|
||||
assert(me == NULL);
|
||||
}
|
||||
|
||||
static void test_queue(void) {
|
||||
int val[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
|
||||
queue me = queue_init(sizeof(int));
|
||||
assert(me != NULL);
|
||||
assert(queue_size(me) == 0);
|
||||
assert(queue_is_empty(me));
|
||||
for (int i = 0; i < 10; i++) {
|
||||
queue_push(me, &val[i]);
|
||||
int get = 0;
|
||||
queue_back(&get, me);
|
||||
assert(get == val[i]);
|
||||
int stuff = 0;
|
||||
queue_front(&stuff, me);
|
||||
assert(stuff == 1);
|
||||
}
|
||||
assert(queue_size(me) == 10);
|
||||
assert(!queue_is_empty(me));
|
||||
int get_arr[10] = {0};
|
||||
queue_to_array(get_arr, me);
|
||||
for (int i = 0; i < 10; i++) {
|
||||
assert(get_arr[i] == i + 1);
|
||||
}
|
||||
for (int i = 0; i < 9; i++) {
|
||||
int get = 0;
|
||||
queue_pop(&get, me);
|
||||
assert(get == i + 1);
|
||||
}
|
||||
queue_trim(me);
|
||||
assert(queue_size(me) == 1);
|
||||
queue_clear(me);
|
||||
assert(queue_size(me) == 0);
|
||||
int get = 0;
|
||||
assert(queue_pop(&get, me) == -EINVAL);
|
||||
assert(queue_front(&get, me) == -EINVAL);
|
||||
assert(queue_back(&get, me) == -EINVAL);
|
||||
me = queue_destroy(me);
|
||||
assert(me == NULL);
|
||||
}
|
||||
|
||||
int main() {
|
||||
test_vector();
|
||||
test_list();
|
||||
test_forward_list();
|
||||
test_deque();
|
||||
test_stack();
|
||||
test_queue();
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user