#ifndef SHARED_LINKED_LIST_H_ #define SHARED_LINKED_LIST_H_ #define linked_list_t(type) linked_list_##type##_t #define linked_list_node_t(type) linked_list_node_##type##_t #define linked_list_push_back(type) linked_list_push_back_##type #define linked_list_push_front(type) linked_list_push_front_##type #define linked_list_pop_front(type) linked_list_pop_front_##type #define linked_list_pop_back(type) linked_list_pop_back_##type #define linked_list_front(type) linked_list_front_##type #define linked_list_back(type) linked_list_back_##type #define linked_list_length(type) linked_list_length_##type #define LINKED_LIST_INIT \ { \ .head = NULL \ } #define linked_list_foreach(ll, val) \ typeof(ll.head) _cur_ = ll.head; \ typeof(_cur_->value) val; \ if (_cur_) val = _cur_->value; \ for (; _cur_ != NULL; _cur_ = _cur_->next, val = _cur_ ? _cur_->value : val) #define NO_ATTRIBUTE #define LINKED_LIST_DECL(type) LINKED_LIST_INTERNAL_DECL(type, NO_ATTRIBUTE) #define LINKED_LIST_STATIC_DECL(type) LINKED_LIST_INTERNAL_DECL(type, static) #define LINKED_LIST_INTERNAL_DECL(type, attr) \ typedef struct LINKED_LIST_NODE_##type { \ type value; \ struct LINKED_LIST_NODE_##type* next; \ } linked_list_node_t(type); \ \ typedef struct { \ linked_list_node_t(type) * head; \ } linked_list_t(type); \ \ attr void linked_list_push_back(type)(linked_list_t(type) * ll, type value); \ attr void linked_list_push_front(type)( \ linked_list_t(type) * ll, type value); \ attr void linked_list_pop_back(type)(linked_list_t(type) * ll); \ attr void linked_list_pop_front(type)(linked_list_t(type) * ll); \ attr type* linked_list_front(type)(linked_list_t(type) * ll); \ attr type* linked_list_back(type)(linked_list_t(type) * ll); #define LINKED_LIST_IMPL(type) LINKED_LIST_INTERNAL_IMPL(type, NO_ATTRIBUTE) #define LINKED_LIST_STATIC_IMPL(type) LINKED_LIST_INTERNAL_IMPL(type, static) #define LINKED_LIST_INTERNAL_IMPL(type, attr) \ attr void linked_list_push_back(type)(linked_list_t(type) * ll, type value) \ { \ if (!ll->head) { \ ll->head = kalloc(sizeof(linked_list_node_t(type))); \ ll->head->value = value; \ ll->head->next = NULL; \ } else { \ linked_list_node_t(type)* c = ll->head; \ while (c->next) c = c->next; \ c->next = kalloc(sizeof(linked_list_node_t(type))); \ c->next->next = NULL; \ c->next->value = value; \ } \ } \ attr void linked_list_push_front(type)(linked_list_t(type) * ll, type value) \ { \ if (!ll->head) { \ ll->head = kalloc(sizeof(linked_list_node_t(type))); \ ll->head->value = value; \ ll->head->next = NULL; \ } else { \ linked_list_node_t(type)* node = \ kalloc(sizeof(linked_list_node_t(type))); \ node->next = ll->head; \ node->value = value; \ ll->head = node; \ } \ } \ attr void linked_list_pop_back(type)(linked_list_t(type) * ll) \ { \ if (!ll->head) { \ return; \ } \ if (!ll->head->next) { \ kfree(ll->head); \ ll->head = NULL; \ return; \ } \ linked_list_node_t(type)* c = ll->head; \ while (c->next->next) c = c->next; \ kfree(c->next); \ c->next = NULL; \ return; \ } \ attr void linked_list_pop_front(type)(linked_list_t(type) * ll) \ { \ if (!ll->head) { \ return; \ } \ linked_list_node_t(type)* node = ll->head; \ ll->head = node->next; \ kfree(node); \ } \ attr type* linked_list_front(type)(linked_list_t(type) * ll) \ { \ if (!ll->head) { \ return NULL; \ } \ return &ll->head->value; \ } \ attr type* linked_list_back(type)(linked_list_t(type) * ll) \ { \ if (!ll->head) { \ return NULL; \ } \ linked_list_node_t(type)* cur = ll->head; \ while (cur->next) cur = cur->next; \ return &cur->value; \ } \ attr size_t linked_list_length(type)(linked_list_t(type) * ll) \ { \ linked_list_node_t(type) * cur; \ size_t ret = 0; \ for (cur = ll->head; cur; cur = cur->next) ++ret; \ return ret; \ } #endif /* SHARED_LINKED_LIST_H_ */