From 3f663a0e6f266bcb250df03a3e23e4809ca3914b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Sun, 1 Dec 2019 15:50:45 +0100 Subject: [PATCH] tllist: remove git submodule and local copy under subprojects --- .gitmodules | 3 - external/tllist | 1 - subprojects/tllist/LICENSE | 21 --- subprojects/tllist/README.md | 301 --------------------------------- subprojects/tllist/meson.build | 5 - subprojects/tllist/test.c | 96 ----------- subprojects/tllist/tllist.h | 180 -------------------- 7 files changed, 607 deletions(-) delete mode 160000 external/tllist delete mode 100644 subprojects/tllist/LICENSE delete mode 100644 subprojects/tllist/README.md delete mode 100644 subprojects/tllist/meson.build delete mode 100644 subprojects/tllist/test.c delete mode 100644 subprojects/tllist/tllist.h diff --git a/.gitmodules b/.gitmodules index ca00cd8..0235ef9 100644 --- a/.gitmodules +++ b/.gitmodules @@ -2,6 +2,3 @@ path = external/wlr-protocols url = https://github.com/swaywm/wlr-protocols.git branch = master -[submodule "external/tllist"] - path = external/tllist - url = https://codeberg.org/dnkl/tllist.git diff --git a/external/tllist b/external/tllist deleted file mode 160000 index d61be2b..0000000 --- a/external/tllist +++ /dev/null @@ -1 +0,0 @@ -Subproject commit d61be2b6238617d9bfd80aeb1ba0cef13d3a6aba diff --git a/subprojects/tllist/LICENSE b/subprojects/tllist/LICENSE deleted file mode 100644 index 6d93abc..0000000 --- a/subprojects/tllist/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2018 Daniel Eklöf - -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. diff --git a/subprojects/tllist/README.md b/subprojects/tllist/README.md deleted file mode 100644 index 0fc3fa4..0000000 --- a/subprojects/tllist/README.md +++ /dev/null @@ -1,301 +0,0 @@ -# tllist - -**tllist** is a *T*yped *L*inked *L*ist C header file only -library implemented using pre-processor macros. - - -1. [Description](#description) -1. [Usage](#usage) - 1. [Declaring a variable](#declaring-a-variable) - 1. [Adding items - basic](#adding-items-basic) - 1. [List length](#list-length) - 1. [Accessing items](#accessing-items) - 1. [Iterating](#iterating) - 1. [Removing items - basic](#removing-items-basic) - 1. [Adding items - advanced](#adding-items-advanced) - 1. [Removing items - advanced](#removing-items-advanced) - 1. [Freeing](#freeing) -1. [Integrating](#integrating) - 1. [Meson](#meson) -1. [API](#api) - 1. [Cheat sheet](#cheat-sheet) - - -## Description - -Most C implementations of linked list are untyped. That is, their data -carriers are typically `void *`. This is error prone since your -compiler will not be able to help you correct your mistakes (_oh, was -it pointer-to-a-pointer... I though it was just a pointer..._). - -**tllist** addresses this by using pre-processor macros to implement -dynamic types, where the data carrier is typed to whatever you want; -both **primitive** data types are supported as well as aggregated ones -such as **structs**, **enums** and **unions**. - -Being a double-linked list, most operations are constant in time -(including pushing and popping both to/from front and back). - -The memory overhead is fairly small; each item carries, besides its -data, a _prev_ and _next_ pointer (i.e. a constant 16 byte overhead -per item on 64-bit architectures). - -The list itself has two _head_ and _tail_ pointers, plus a _length_ -variable (typically 8 bytes on 64-bit architectures) to make list -length lookup constant in time. - -Thus, assuming 64-bit pointers (and a 64-bit `size_t` type), the total -overhead is `3*8 + n*2*8` bytes. - - -## Usage - -### Declaring a variable - -1. **Declare a variable** - - ```c - /* Declare a variable using an anonymous type */ - tll(int) an_integer_list = tll_init(); - ``` - - -2. **Typedef** - - ```c - /* First typedef the list type */ - typedef tll(int) an_integer_list_t; - - /* Then declare a variable using that typedef */ - an_integer_list_t an_integer_list = tll_init(); - ``` - -3. **Named struct** - - ```c - /* First declare named struct */ - tll(int, an_integer_list); - - /* Then declare a variable using that named struct */ - struct an_integer_list an_integer_list = tll_init(); - ``` - -### Adding items - basic - -Use `tll_push_back()` or `tll_push_front()` to add elements to the -back or front of the list. - -```c -tll_push_back(an_integer_list, 4711); -tll_push_front(an_integer_list, 1234); -``` - - -### List length - -`tll_length()` returns the length (number of items) in a list. - -```c -tll_push_back(an_integer_list, 1234); -tll_push_back(an_integer_list, 5678); -printf("length: %zu\n", tll_length(an_integer_list)); -``` - -Outputs: - - length: 2 - - -### Accessing items - -For the front and back items, you can use `tll_front()` and -`tll_back()` respectively. For any other item in the list, you need to -iterate the list and find the item yourself. - -```c -tll_push_back(an_integer_list, 1234); -tll_push_back(an_integer_list, 5555); -tll_push_back(an_integer_list, 6789); - -printf("front: %d\n", tll_front(an_integer_list)); -printf("back: %d\n", tll_back(an_integer_list)); -``` - -Outputs: - - front: 1234 - back: 6789 - - -### Iterating - -You can iterate the list either forward or backwards, using -`tll_foreach()` and `tll_rforeach()` respectively. - -The `it` variable should be treated as an opaque iterator type, where -`it->item` is the item. - -In reality, it is simply a pointer to the linked list entry, and since -tllist is a header-only implementation, you do have access to e.g. the -next/prev pointers. There should not be any need to access anything -except `item` however. - -Note that `it` can be named anything. - -```c -tll_push_back(an_integer_list, 1); -tll_push_back(an_integer_list, 2); - -tll_foreach(an_integer_list, it) { - printf("forward: %d\n", it->item); -} - -tll_rforeach(an_integer_list, it) { - printf("reverse: %d\n", it->item); -} -``` - -Outputs: - - forward: 1 - forward: 2 - reverse: 2 - reverse: 1 - - -### Removing items - basic - -`tll_pop_front()` and `tll_pop_back()` removes the front/back item and -returns it. - -```c -tll_push_back(an_integer_list, 1234); -tll_push_back(an_integer_list, 5678); - -printf("front: %d\n", tll_pop_front(an_integer_list)); -printf("back: %d\n", tll_pop_back(an_integer_list)); -printf("length: %zu\n", tll_length(an_integer_list)); -``` - -Outputs: - - front: 1234 - back: 5678 - length: 0 - - -### Adding items - advanced - -Given an iterator, you can insert new items before or after that -iterator, using `tll_insert_before()` and `tll_insert_after()`. - -```c -tll_foreach(an_integer_list, it) { - if (it->item == 1234) { - tll_insert_before(an_integer_list, it, 7777); - break; - } -} -``` - -Q: Why do I have to pass **both** the _list_ and the _iterator_ to - `tll_insert_before()`? - -A: If not, **each** element in the list would have to contain a - pointer to the owning list, which would significantly increase the - overhead. - - -### Removing items - advanced - -Similar to how you can add items while iterating a list, you can also -remove them. - -Note that the `*foreach()` functions are **safe** in this regard - it -is perfectly OK to remove the "current" item. - -```c -tll_foreach(an_integer_list, it) { - if (it->item.delete_me) - tll_remove(an_integer_list, it); -} -``` - -To make it slightly easier to handle cases where the item _itself_ -must be free:d as well, there is also `tll_remove_and_free()`. It -works just like `tll_remove()`, but takes an additional argument; a -callback that will be called for each item. - -```c -tll(int *) int_p_list = tll_init(); - -int *a = malloc(sizeof(*a)); -int *b = malloc(sizeof(*b)); - -*a = 1234; -*b = 5678; - -tll_push_back(int_p_list, a); -tll_push_back(int_p_list, b); - -tll_foreach(int_p_list, it) { - tll_remove_and_free(int_p_list, it, free); -} -``` - - -### Freeing - -To remove **all** items, use `tll_free()`, or -`tll_free_and_free()`. These are just convenience functions and -calling these are equivalent to: - -```c -tll_foreach(an_integer_list, it) { - tll_remove(an_integer_list, it); -} -``` - -Note that there is no need to call `tll_free()` on an empty -(`tll_length(list) == 0`) list. - - -## Integrating - -The easiest way may be to simply copy `tllist.h` into your -project. But see sections below for other ways. - - -### Meson - -You can use tllist as a subproject. In your main project's -`meson.build`, to something like: - -```meson -tllist = subproject('tllist').get_variable('tllist') -executable('you-executable', ..., dependencies: [tllist]) -``` - - -## API - -### Cheat sheet - -| Function | Description | Context | Complexity | -|-------------------------------------|-------------------------------------------------------|--------------------|-----------:| -| `list = tll_init()` | initialize a new tllist variable to an empty list | Variable init | O(1) | -| `tll_length(list)` | returns the length (number of items) of a list | | O(1) | -| `tll_push_front(list, item)` | inserts _item_ at the beginning of the list | | O(1) | -| `tll_push_back(list, item)` | inserts _item_ at the end of the list | | O(1) | -| `tll_front(list)` | returns the first item in the list | | O(1) | -| `tll_back(list)` | returns the last item in the list | | O(1) | -| `tll_pop_front(list)` | removes and returns the first item in the list | | O(1) | -| `tll_pop_back(list)` | removes and returns the last item in the list | | O(1) | -| `tll_foreach(list, it)` | iterates the list from the beginning to the end | | O(n) | -| `tll_rforeach(list, it)` | iterates the list from the end to the beginning | | O(n) | -| `tll_insert_before(list, it, item)` | inserts _item_ before _it_. | `tll_(r)foreach()` | O(1) | -| `tll_insert_after(list, it, item)` | inserts _item_ after _it_. | `tll_(r)foreach()` | O(1) | -| `tll_remove(list, it)` | removes _it_ from the list. | `tll_(r)foreach()` | O(1) | -| `tll_remove_and_free(list, it, cb)` | removes _it_ from the list, and calls `cb(it->item)`. | `tll_(r)foreach()` | O(1) | -| `tll_free(list)` | removes **all** items from the list | | O(n) | -| `tll_free_and_free(list, cb)` | removes **all** items from the list, and calls `cb(it->item)` for each item. | | O(n) | diff --git a/subprojects/tllist/meson.build b/subprojects/tllist/meson.build deleted file mode 100644 index 2f6123f..0000000 --- a/subprojects/tllist/meson.build +++ /dev/null @@ -1,5 +0,0 @@ -project('tllist', 'c', version: '1.0.0', license: 'MIT', meson_version: '>=0.50.0') -tllist = declare_dependency(include_directories: '.') - -unittest = executable('unittest', 'test.c', dependencies: [tllist]) -test('unittest', unittest) diff --git a/subprojects/tllist/test.c b/subprojects/tllist/test.c deleted file mode 100644 index 515b5ad..0000000 --- a/subprojects/tllist/test.c +++ /dev/null @@ -1,96 +0,0 @@ -#undef NDEBUG -#include -#include -#include -#include - -#include - -int -main(int argc, const char *const *argv) -{ - tll(int) l = tll_init(); - assert(tll_length(l) == 0); - - /* push back */ - tll_push_back(l, 123); assert(tll_length(l) == 1); - tll_push_back(l, 456); assert(tll_length(l) == 2); - tll_push_back(l, 789); assert(tll_length(l) == 3); - - assert(tll_front(l) == 123); - assert(tll_back(l) == 789); - - /* push front */ - tll_push_front(l, 0xabc); assert(tll_length(l) == 4); - - assert(tll_front(l) == 0xabc); - assert(tll_back(l) == 789); - - /* Pop back */ - assert(tll_pop_back(l) == 789); - assert(tll_back(l) == 456); - - /* Pop front */ - assert(tll_pop_front(l) == 0xabc); - assert(tll_front(l) == 123); - - /* foreach */ - assert(tll_length(l) == 2); - - int seen[tll_length(l)]; - memset(seen, 0, tll_length(l) * sizeof(seen[0])); - - size_t count = 0; - tll_foreach(l, it) - seen[count++] = it->item; - - assert(count == tll_length(l)); - assert(seen[0] == 123); - assert(seen[1] == 456); - - /* rforeach */ - memset(seen, 0, tll_length(l) * sizeof(seen[0])); - count = 0; - tll_rforeach(l, it) - seen[count++] = it->item; - - assert(count == tll_length(l)); - assert(seen[0] == 456); - assert(seen[1] == 123); - - /* remove */ - tll_push_back(l, 789); - tll_foreach(l, it) { - if (it->item > 123 && it->item < 789) - tll_remove(l, it); - } - assert(tll_length(l) == 2); - assert(tll_front(l) == 123); - assert(tll_back(l) == 789); - - /* insert before */ - tll_foreach(l, it) { - if (it->item == 123) - tll_insert_before(l, it, 0xabc); - } - assert(tll_length(l) == 3); - assert(tll_front(l) == 0xabc); - assert(tll_back(l) == 789); - - /* insert after */ - tll_foreach(l, it) { - if (it->item == 789) - tll_insert_after(l, it, 999); - } - assert(tll_length(l) == 4); - assert(tll_front(l) == 0xabc); - assert(tll_back(l) == 999); - - /* free */ - tll_free(l); - assert(tll_length(l) == 0); - assert(l.head == NULL); - assert(l.tail == NULL); - - return EXIT_SUCCESS; -} diff --git a/subprojects/tllist/tllist.h b/subprojects/tllist/tllist.h deleted file mode 100644 index ec2fd41..0000000 --- a/subprojects/tllist/tllist.h +++ /dev/null @@ -1,180 +0,0 @@ -#pragma once - -#include -#include -#include - -#define TLL_PASTE2( a, b) a##b -#define TLL_PASTE( a, b) TLL_PASTE2( a, b) - -/* Utility macro to generate a list element struct with a unique struct tag */ -#define TLL_UNIQUE_INNER_STRUCT(TYPE, ID) \ - struct TLL_PASTE(__tllist_ , ID) { \ - TYPE item; \ - struct TLL_PASTE(__tllist_, ID) *prev; \ - struct TLL_PASTE(__tllist_, ID) *next; \ - } *head, *tail; - -/* - * Defines a new typed-list type, or directly instantiate a typed-list variable - * - * Example a, declare a variable (list of integers): - * tll(int) my_list; - * - * Example b, declare a type, and then use the type: - * tll(int, my_list_type); - * struct my_list_type my_list; - */ -#define tll(TYPE, ...) \ - struct __VA_ARGS__ { \ - TLL_UNIQUE_INNER_STRUCT(TYPE, __COUNTER__) \ - size_t length; \ - } - -/* Initializer: tll(int) my_list = tll_init(); */ -#define tll_init() {.head = NULL, .tail = NULL, .length = 0} - -/* Length/size of list: printf("size: %zu\n", tll_length(my_list)); */ -#define tll_length(list) (list).length - -/* Adds a new item to the back of the list */ -#define tll_push_back(list, new_item) \ - do { \ - tll_insert_after(list, (list).tail, new_item); \ - if ((list).head == NULL) \ - (list).head = (list).tail; \ - } while (0) - -/* Adds a new item to the front of the list */ -#define tll_push_front(list, new_item) \ - do { \ - tll_insert_before(list, (list).head, new_item); \ - if ((list).tail == NULL) \ - (list).tail = (list).head; \ - } while (0) - -/* - * Iterates the list. is an iterator pointer. You can access the - * list item with ->item: - * - * tll(int) my_list = vinit(); - * tll_push_back(my_list, 5); - * - * tll_foreach(my_list i) { - * printf("%d\n", i->item); - * } -*/ -#define tll_foreach(list, it) \ - for (__typeof__(*(list).head) *it = (list).head, \ - *it_next = it != NULL ? it->next : NULL; \ - it != NULL; \ - it = it_next, \ - it_next = it_next != NULL ? it_next->next : NULL) - -/* Same as tll_foreach(), but iterates backwards */ -#define tll_rforeach(list, it) \ - for (__typeof__(*(list).tail) *it = (list).tail, \ - *it_prev = it != NULL ? it->prev : NULL; \ - it != NULL; \ - it = it_prev, \ - it_prev = it_prev != NULL ? it_prev->prev : NULL) - -/* - * Inserts a new item after , which is an iterator. I.e. you can - * only call this from inside a tll_foreach() or tll_rforeach() loop. - */ -#define tll_insert_after(list, it, new_item) \ - do { \ - __typeof__((list).head) __e = malloc(sizeof(*__e)); \ - __e->item = (new_item); \ - __e->prev = (it); \ - __e->next = (it) != NULL ? (it)->next : NULL; \ - if ((it) != NULL) { \ - if ((it)->next != NULL) \ - (it)->next->prev = __e; \ - (it)->next = __e; \ - } \ - if ((it) == (list).tail) \ - (list).tail = __e; \ - (list).length++; \ - } while (0) - -/* - * Inserts a new item before , which is an iterator. I.e. you can - * only call this from inside a tll_foreach() or tll_rforeach() loop. - */ -#define tll_insert_before(list, it, new_item) \ - do { \ - __typeof__((list).head) __e = malloc(sizeof(*__e)); \ - __e->item = (new_item); \ - __e->prev = (it) != NULL ? (it)->prev : NULL; \ - __e->next = (it); \ - if ((it) != NULL) { \ - if ((it)->prev != NULL) \ - (it)->prev->next = __e; \ - (it)->prev = __e; \ - } \ - if ((it) == (list).head) \ - (list).head = __e; \ - (list).length++; \ - } while (0) - -/* - * Removes an entry from the list. is an iterator. I.e. you can - * only call this from inside a tll_foreach() or tll_rforeach() loop. - */ -#define tll_remove(list, it) \ - do { \ - assert((list).length > 0); \ - __typeof__((list).head) __prev = it->prev; \ - __typeof__((list).head) __next = it->next; \ - if (__prev != NULL) \ - __prev->next = __next; \ - else \ - (list).head = __next; \ - if (__next != NULL) \ - __next->prev = __prev; \ - else \ - (list).tail = __prev; \ - free(it); \ - (list).length--; \ - } while (0) - -/* Same as tll_remove(), but calls free_callback(it->item) */ -#define tll_remove_and_free(list, it, free_callback) \ - do { \ - free_callback((it)->item); \ - tll_remove((list), (it)); \ - } while (0) - -#define tll_front(list) (list).head->item -#define tll_back(list) (list).tail->item - -/* - * Removes the first element from the list, and returns it (note: - * returns the *actual* item, not an iterator. - */ -#define tll_pop_front(list) \ - ({__typeof__((list).head) it = (list).head; \ - __typeof__((list).head->item) __ret = it->item; \ - tll_remove((list), it); \ - __ret; \ - }) - -/* Same as tll_pop_front(), but returns/removes the *last* element */ -#define tll_pop_back(list) \ - ({__typeof__((list).tail) it = (list).tail; \ - __typeof__((list).tail->item) __ret = it->item; \ - tll_remove((list), it); \ - __ret; \ - }) - -/* Frees the list. This call is *not* needed if the list is already empty. */ -#define tll_free(list) \ - tll_foreach(list, __it) \ - tll_remove(list, __it) - -/* Same as tll_free(), but also calls free_callback(item) for every item */ -#define tll_free_and_free(list, free_callback) \ - tll_foreach(list, __it) \ - tll_remove_and_free(list, __it, free_callback)