Skip to content

Instantly share code, notes, and snippets.

@cwchentw
Last active November 4, 2019 16:01
Show Gist options
  • Save cwchentw/d6e4d921e12ca2a417e30e4aea198a59 to your computer and use it in GitHub Desktop.
Save cwchentw/d6e4d921e12ca2a417e30e4aea198a59 to your computer and use it in GitHub Desktop.
Generic Queue in Void Pointer (Apache 2.0)
#include <stdbool.h>
#include <stdlib.h>
#include "integer.h"
struct int_t {
int data;
};
int_t* int_new(int n)
{
int_t *i = malloc(sizeof(int_t));
if (!i)
return i;
i->data = n;
return i;
}
bool int_copy(void **dest, void *src)
{
*dest = malloc(sizeof(int_t));
if (!dest)
return false;
((int_t *) (*dest))->data = int_value((int_t *) src);
return true;
}
int int_value(int_t *self)
{
return self->data;
}
void int_delete(void *self)
{
if (!self)
return;
free(self);
}
#pragma once
#include <stdbool.h>
typedef struct int_t int_t;
int_t* int_new(int n);
int int_value(int_t *self);
bool int_copy(void **, void *);
void int_delete(void *self);
#include <assert.h>
#include <stdio.h>
#include "integer.h" // Home-made `int`-wrapping box class.
#include "queue.h"
#define ERROR(msg, ...) \
fprintf(stderr, "(%s:%d) " msg "\n", __FILE__, __LINE__, ##__VA_ARGS__);
int main()
{
// queue_t: NULL
queue_t *queue = queue_new(int_copy, int_delete);
if (!queue) {
ERROR("Failed to allocate the queue");
goto ERROR;
}
int_t *temp;
// queue_t: 9 -> NULL
temp = int_new(9);
if (!temp) {
ERROR("Failed to allocate the int object");
goto ERROR;
}
queue_push_front(queue, temp);
temp = (int_t *) queue_peek_front(queue);
if (!(int_value(temp) == 9)) {
ERROR("Wrong value");
goto ERROR;
}
temp = (int_t *) queue_peek_rear(queue);
if (!(int_value(temp) == 9)) {
ERROR("Wrong value");
goto ERROR;
}
// queue_t: 4 -> 9 -> NULL
temp = int_new(4);
if (!temp) {
ERROR("Failed to allocate the int object");
goto ERROR;
}
queue_push_front(queue, temp);
temp = (int_t *) queue_peek_front(queue);
if (!(int_value(temp) == 4)) {
ERROR("Wrong value");
goto ERROR;
}
temp = (int_t *) queue_peek_rear(queue);
if (!(int_value(temp) == 9)) {
ERROR("Wrong value");
goto ERROR;
}
// queue_t: 4 -> 9 -> 5 -> NULL
temp = int_new(5);
if (!temp) {
ERROR("Failed to allocate the int object");
goto ERROR;
}
queue_push_rear(queue, temp);
temp = (int_t *) queue_peek_front(queue);
if (!(int_value(temp) == 4)) {
ERROR("Wrong value");
goto ERROR;
}
temp = (int_t *) queue_peek_rear(queue);
if (!(int_value(temp) == 5)) {
ERROR("Wrong value");
goto ERROR;
}
// queue_t: 9 -> 5 -> NULL
temp = (int_t *) queue_pop_front(queue);
if (!temp) {
ERROR("No valid value");
goto ERROR;
}
if (!(int_value(temp) == 4)) {
ERROR("Wrong value");
goto ERROR;
}
int_delete(temp);
temp = (int_t *) queue_peek_front(queue);
if (!(int_value(temp) == 9)) {
ERROR("Wrong value");
goto ERROR;
}
temp = (int_t *) queue_peek_rear(queue);
if (!(int_value(temp) == 5)) {
ERROR("Wrong value");
goto ERROR;
}
// queue_t: 9 -> NULL
temp = (int_t *) queue_pop_rear(queue);
if (!temp) {
ERROR("No valid value");
goto ERROR;
}
if (!(int_value(temp) == 5)) {
ERROR("Wrong value");
goto ERROR;
}
int_delete(temp);
temp = (int_t *) queue_peek_front(queue);
if (!(int_value(temp) == 9)) {
ERROR("Wrong value");
goto ERROR;
}
temp = (int_t *) queue_peek_rear(queue);
if (!(int_value(temp) == 9)) {
ERROR("Wrong value");
goto ERROR;
}
// queue_t: NULL
temp = (int_t *) queue_pop_rear(queue);
if (!temp) {
ERROR("No valid value");
goto ERROR;
}
if (!(int_value(temp) == 9)) {
ERROR("Wrong value");
goto ERROR;
}
int_delete(temp);
queue_delete(queue);
return 0;
ERROR:
if (queue)
queue_delete(queue);
return 1;
}
#include <stdio.h>
#include <assert.h>
#include <stdbool.h>
#include <stdlib.h>
#include "queue.h"
typedef struct node_t node_t;
struct node_t {
item_t data;
node_t *prev;
node_t *next;
};
static node_t* node_new(item_t data);
struct queue_t {
copy_fn item_copy;
free_fn item_free;
node_t *head;
node_t *tail;
};
static node_t* node_new(item_t data)
{
node_t *node = malloc(sizeof(node_t));
if (!node)
return node;
node->data = data;
node->prev = NULL;
node->next = NULL;
return node;
}
queue_t* queue_new(copy_fn item_copy, free_fn item_free)
{
queue_t *lt = malloc(sizeof(queue_t));
if (!lt)
return lt;
lt->item_copy = item_copy;
lt->item_free = item_free;
lt->head = NULL;
lt->tail = NULL;
return lt;
}
bool queue_is_empty(queue_t *self)
{
return !(self->head);
}
item_t queue_peek_front(queue_t *self)
{
if (!(self->head))
return NULL;
return self->head->data;
}
item_t queue_peek_rear(queue_t *self)
{
if (!(self->head))
return NULL;
return self->tail->data;
}
bool queue_push_front(queue_t *self, item_t data)
{
node_t *node = node_new(data);
if (!node)
return false;
if (!(self->head)) {
self->head = node;
self->tail = node;
return true;
}
node->next = self->head;
self->head->prev = node;
self->head = node;
return true;
}
item_t queue_pop_front(queue_t *self)
{
assert(!queue_is_empty(self));
if (self->head == self->tail) {
item_t popped;
self->item_copy(&popped, self->head->data);
self->item_free(self->head->data);
free(self->head);
self->head = NULL;
self->tail = NULL;
return popped;
}
node_t *curr = self->head;
item_t popped;
self->item_copy(&popped, curr->data);
self->head = self->head->next;
self->item_free(curr->data);
free(curr);
return popped;
}
bool queue_push_rear(queue_t *self, item_t data)
{
node_t *node = node_new(data);
if (!node)
return false;
if (self->tail == NULL) {
self->head = node;
self->tail = node;
return true;
}
self->tail->next = node;
node->prev = self->tail;
self->tail = node;
return true;
}
item_t queue_pop_rear(queue_t *self)
{
assert(!queue_is_empty(self));
if (self->head == self->tail) {
item_t popped;
self->item_copy(&popped, self->tail->data);
self->item_free(self->tail->data);
free(self->tail);
self->head = NULL;
self->tail = NULL;
return popped;
}
node_t *curr = self->tail;
item_t popped;
self->item_copy(&popped, curr->data);
self->tail = self->tail->prev;
self->item_free(curr->data);
free(curr);
return popped;
}
void queue_delete(void *self)
{
if (!self)
return;
free_fn fn = ((queue_t *) self)->item_free;
node_t *curr = ((queue_t *) self)->head;
node_t *temp = NULL;
while (curr) {
temp = curr;
curr = curr->next;
(*fn)(temp->data);
free(temp);
}
free(self);
}
#pragma once
#include <stdbool.h>
typedef void * item_t;
typedef bool (*copy_fn) (void **, void *);
typedef void (*free_fn) (void *);
typedef struct queue_t queue_t;
queue_t* queue_new(copy_fn, free_fn);
bool queue_is_empty(queue_t *self);
item_t queue_peek_front(queue_t *self);
item_t queue_peek_rear(queue_t *self);
bool queue_push_front(queue_t *self, item_t data);
item_t queue_pop_front(queue_t *self);
bool queue_push_rear(queue_t *self, item_t data);
item_t queue_pop_rear(queue_t *self);
void queue_delete(void *self);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment