added linked lists in lib/data-types
parent
d4b9d88464
commit
ea56a08981
|
@ -12,6 +12,7 @@
|
||||||
|
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include "data-types/linked-list.h"
|
||||||
|
|
||||||
#define bool _Bool
|
#define bool _Bool
|
||||||
#define true ((bool)1)
|
#define true ((bool)1)
|
||||||
|
|
|
@ -0,0 +1,156 @@
|
||||||
|
/* ----------------------------------------------------------------------------
|
||||||
|
* linked list
|
||||||
|
* ----------------------------------------------------------------------------
|
||||||
|
* Copyright (c) 2012 Ben Blazak <benblazak.dev@gmail.com>
|
||||||
|
* Released under The MIT License (MIT) (see "license.md")
|
||||||
|
* Project located at <https://github.com/benblazak/ergodox-firmware>
|
||||||
|
* ------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include "lib/data-types.h"
|
||||||
|
|
||||||
|
#include "linked-list.h"
|
||||||
|
|
||||||
|
|
||||||
|
// convenience macros (undefined later)
|
||||||
|
#define _NEW_STRUCT_POINTER(type, name) \
|
||||||
|
struct type * name = (struct type *) malloc(sizeof(struct type))
|
||||||
|
|
||||||
|
|
||||||
|
struct linked_list * linked_list_new(void) {
|
||||||
|
_NEW_STRUCT_POINTER(linked_list, list);
|
||||||
|
if (!list) return NULL;
|
||||||
|
|
||||||
|
list->head = NULL;
|
||||||
|
list->tail = NULL;
|
||||||
|
|
||||||
|
list->number_of_elements = 0;
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct linked_list * linked_list_add_head(
|
||||||
|
struct linked_list * list,
|
||||||
|
LINKED_LIST_DATA_TYPE data ) {
|
||||||
|
|
||||||
|
_NEW_STRUCT_POINTER(linked_list_node, node);
|
||||||
|
if (!node) return NULL;
|
||||||
|
|
||||||
|
node->data = data;
|
||||||
|
node->next = list->head;
|
||||||
|
list->head = node;
|
||||||
|
if (list->number_of_elements == 0)
|
||||||
|
list->tail = node;
|
||||||
|
|
||||||
|
list->number_of_elements++;
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct linked_list * linked_list_add_tail(
|
||||||
|
struct linked_list * list,
|
||||||
|
LINKED_LIST_DATA_TYPE data ) {
|
||||||
|
|
||||||
|
_NEW_STRUCT_POINTER(linked_list_node, node);
|
||||||
|
if (!node) return NULL;
|
||||||
|
|
||||||
|
node->data = data;
|
||||||
|
node->next = NULL;
|
||||||
|
if (list->number_of_elements == 0)
|
||||||
|
list->head = node;
|
||||||
|
else
|
||||||
|
list->tail->next = node;
|
||||||
|
list->tail = node;
|
||||||
|
|
||||||
|
list->number_of_elements++;
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
LINKED_LIST_DATA_TYPE linked_list_pop_head(struct linked_list * list) {
|
||||||
|
if (list->number_of_elements == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
struct linked_list_node node = {
|
||||||
|
.data = list->head->data,
|
||||||
|
.next = list->head->next
|
||||||
|
};
|
||||||
|
|
||||||
|
free(list->head);
|
||||||
|
|
||||||
|
if (list->number_of_elements == 1) {
|
||||||
|
list->head = NULL;
|
||||||
|
list->tail = NULL;
|
||||||
|
} else {
|
||||||
|
list->head = node.next;
|
||||||
|
}
|
||||||
|
|
||||||
|
list->number_of_elements--;
|
||||||
|
return node.data;
|
||||||
|
}
|
||||||
|
|
||||||
|
// note: this function is inefficient for singly linked lists: it has O(n) time
|
||||||
|
// instead of O(1) time like most of the other functions. but it's not needed
|
||||||
|
// for implementing stacks or queues, so i don't anticipate it being used all
|
||||||
|
// that much. it's here for completeness.
|
||||||
|
LINKED_LIST_DATA_TYPE linked_list_pop_tail(struct linked_list * list) {
|
||||||
|
if (list->number_of_elements == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
struct linked_list_node node = {
|
||||||
|
.data = list->tail->data,
|
||||||
|
.next = list->tail->next
|
||||||
|
};
|
||||||
|
|
||||||
|
free(list->tail);
|
||||||
|
|
||||||
|
if (list->number_of_elements == 1) {
|
||||||
|
list->head = NULL;
|
||||||
|
list->tail = NULL;
|
||||||
|
} else {
|
||||||
|
list->tail = list->head;
|
||||||
|
for (uint8_t i=2; i<(list->number_of_elements); i++)
|
||||||
|
list->tail = list->tail->next;
|
||||||
|
list->tail->next = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
list->number_of_elements--;
|
||||||
|
return node.data;
|
||||||
|
}
|
||||||
|
|
||||||
|
LINKED_LIST_DATA_TYPE linked_list_read(
|
||||||
|
struct linked_list * list,
|
||||||
|
uint8_t position ) {
|
||||||
|
|
||||||
|
if (position < 1 || position > (list->number_of_elements))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
struct linked_list_node * node = list->head;
|
||||||
|
for (uint8_t i=1; i<position; i++)
|
||||||
|
node = node->next;
|
||||||
|
|
||||||
|
return node->data;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct linked_list * linked_list_copy(struct linked_list * list) {
|
||||||
|
_NEW_STRUCT_POINTER(linked_list, copy);
|
||||||
|
|
||||||
|
for (uint8_t i=1; i<=(list->number_of_elements); i++)
|
||||||
|
linked_list_add_tail(copy, linked_list_read(list, i));
|
||||||
|
|
||||||
|
return copy;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// note: this is implemented inefficiently (using ...pop_head(), which does
|
||||||
|
// extra work). but that makes things simpler, and i don't anticipate using it
|
||||||
|
// all that often.
|
||||||
|
void linked_list_free(struct linked_list * list) {
|
||||||
|
while ((list->number_of_elements) > 0)
|
||||||
|
linked_list_pop_head(list);
|
||||||
|
|
||||||
|
free(list);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// convenience macros (undefined here)
|
||||||
|
#undef _NEW_STRUCT_POINTER
|
||||||
|
|
|
@ -0,0 +1,86 @@
|
||||||
|
/* ----------------------------------------------------------------------------
|
||||||
|
* linked list : exports
|
||||||
|
*
|
||||||
|
* Includes aliases to treat the list as a queue or stack.
|
||||||
|
* ----------------------------------------------------------------------------
|
||||||
|
* Copyright (c) 2012 Ben Blazak <benblazak.dev@gmail.com>
|
||||||
|
* Released under The MIT License (MIT) (see "license.md")
|
||||||
|
* Project located at <https://github.com/benblazak/ergodox-firmware>
|
||||||
|
* ------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef LINKED_LIST_h
|
||||||
|
#define LINKED_LIST_h
|
||||||
|
|
||||||
|
#include "lib/data-types.h"
|
||||||
|
|
||||||
|
|
||||||
|
// default list data type
|
||||||
|
#ifndef LINKED_LIST_DATA_TYPE
|
||||||
|
#define LINKED_LIST_DATA_TYPE uint8_t
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
// structs
|
||||||
|
struct linked_list_node {
|
||||||
|
LINKED_LIST_DATA_TYPE data;
|
||||||
|
struct linked_list_node * next;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct linked_list{
|
||||||
|
uint8_t number_of_elements;
|
||||||
|
struct linked_list_node * head;
|
||||||
|
struct linked_list_node * tail;
|
||||||
|
};
|
||||||
|
|
||||||
|
// functions
|
||||||
|
struct linked_list * linked_list_new(void);
|
||||||
|
struct linked_list * linked_list_add_head(
|
||||||
|
struct linked_list * list,
|
||||||
|
LINKED_LIST_DATA_TYPE data );
|
||||||
|
struct linked_list * linked_list_add_tail(
|
||||||
|
struct linked_list * list,
|
||||||
|
LINKED_LIST_DATA_TYPE data );
|
||||||
|
LINKED_LIST_DATA_TYPE linked_list_pop_head(struct linked_list * list);
|
||||||
|
LINKED_LIST_DATA_TYPE linked_list_pop_tail(struct linked_list * list);
|
||||||
|
LINKED_LIST_DATA_TYPE linked_list_read(
|
||||||
|
struct linked_list * list,
|
||||||
|
uint8_t position );
|
||||||
|
struct linked_list * linked_list_copy(struct linked_list * list);
|
||||||
|
void linked_list_free(struct linked_list * list);
|
||||||
|
|
||||||
|
|
||||||
|
// typedefs, for user code
|
||||||
|
typedef struct linked_list * linked_list_t;
|
||||||
|
typedef struct linked_list_node * linked_list_node_t;
|
||||||
|
|
||||||
|
// aliases, for user code
|
||||||
|
#define list_t linked_list_t
|
||||||
|
#define list_new linked_list_new
|
||||||
|
#define list_push linked_list_add_head
|
||||||
|
#define list_append linked_list_add_tail
|
||||||
|
#define list_pop linked_list_pop_head
|
||||||
|
#define list_pop_tail linked_list_pop_tail
|
||||||
|
#define list_read linked_list_read
|
||||||
|
#define list_copy linked_list_copy
|
||||||
|
#define list_free linked_list_free
|
||||||
|
|
||||||
|
#define queue_t list_t
|
||||||
|
#define queue_new list_new
|
||||||
|
#define queue_append list_append
|
||||||
|
#define queue_pop list_pop
|
||||||
|
#define queue_read list_read
|
||||||
|
#define queue_copy list_copy
|
||||||
|
#define queue_free list_free
|
||||||
|
|
||||||
|
#define stack_t list_t
|
||||||
|
#define stack_new list_new
|
||||||
|
#define stack_push list_push
|
||||||
|
#define stack_pop list_pop
|
||||||
|
#define stack_read list_read
|
||||||
|
#define stack_copy list_copy
|
||||||
|
#define stack_free list_free
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue