Add queue

This commit is contained in:
Bailey Thompson
2017-10-29 21:34:32 -04:00
committed by GitHub
parent 394cd4ac15
commit 6188b5a22a
4 changed files with 274 additions and 2 deletions

180
src/queue.c Normal file
View 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
View 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 */

View File

@@ -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;
}

View File

@@ -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;
}