aboutsummaryrefslogtreecommitdiff
path: root/core/container
diff options
context:
space:
mode:
authorNicknEma <62065135+NicknEma@users.noreply.github.com>2024-07-12 15:37:34 +0200
committerNicknEma <62065135+NicknEma@users.noreply.github.com>2024-07-12 15:37:34 +0200
commitc75a872909191631f5e5282d37014b51a34a9724 (patch)
tree5df0af9ac1daff48921fa6c97d93d1354909136f /core/container
parenta348a7e84efbf971048359e4bdf17d6006a79b5f (diff)
Write doc comments in intrusive_list.odin
Write description, inputs/returns and some examples for each procedure
Diffstat (limited to 'core/container')
-rw-r--r--core/container/intrusive/list/intrusive_list.odin191
1 files changed, 189 insertions, 2 deletions
diff --git a/core/container/intrusive/list/intrusive_list.odin b/core/container/intrusive/list/intrusive_list.odin
index 1a3175002..6989dfa21 100644
--- a/core/container/intrusive/list/intrusive_list.odin
+++ b/core/container/intrusive/list/intrusive_list.odin
@@ -18,11 +18,18 @@ List :: struct {
tail: ^Node,
}
-
+// The list link you must include in your own structure.
Node :: struct {
prev, next: ^Node,
}
+/*
+Inserts a new element at the front of the list with O(1) time complexity.
+
+**Inputs**
+- list: The container list
+- node: The node member of the user-defined element structure
+*/
push_front :: proc "contextless" (list: ^List, node: ^Node) {
if list.head != nil {
list.head.prev = node
@@ -33,7 +40,13 @@ push_front :: proc "contextless" (list: ^List, node: ^Node) {
node.prev, node.next = nil, nil
}
}
+/*
+Inserts a new element at the back of the list with O(1) time complexity.
+**Inputs**
+- list: The container list
+- node: The node member of the user-defined element structure
+*/
push_back :: proc "contextless" (list: ^List, node: ^Node) {
if list.tail != nil {
list.tail.next = node
@@ -45,6 +58,13 @@ push_back :: proc "contextless" (list: ^List, node: ^Node) {
}
}
+/*
+Removes an element from a list with O(1) time complexity.
+
+**Inputs**
+- list: The container list
+- node: The node member of the user-defined element structure to be removed
+*/
remove :: proc "contextless" (list: ^List, node: ^Node) {
if node != nil {
if node.next != nil {
@@ -61,7 +81,13 @@ remove :: proc "contextless" (list: ^List, node: ^Node) {
}
}
}
+/*
+Removes from the given list all elements that satisfy a condition.
+**Inputs**
+- list: The container list
+- to_erase: The condition procedure. It should return `true` if a node should be removed, `false` otherwise
+*/
remove_by_proc :: proc(list: ^List, to_erase: proc(^Node) -> bool) {
for node := list.head; node != nil; {
next := node.next
@@ -82,7 +108,13 @@ remove_by_proc :: proc(list: ^List, to_erase: proc(^Node) -> bool) {
node = next
}
}
+/*
+Removes from the given list all elements that satisfy a condition.
+**Inputs**
+- list: The container list
+- to_erase: The _contextless_ condition procedure. It should return `true` if a node should be removed, `false` otherwise
+*/
remove_by_proc_contextless :: proc(list: ^List, to_erase: proc "contextless" (^Node) -> bool) {
for node := list.head; node != nil; {
next := node.next
@@ -104,12 +136,26 @@ remove_by_proc_contextless :: proc(list: ^List, to_erase: proc "contextless" (^N
}
}
+/*
+Checks if the given list does not contain any element.
+**Inputs**
+- list: The container list
+**Returns** `true` if `list` is empty, `false` otherwise
+*/
is_empty :: proc "contextless" (list: ^List) -> bool {
return list.head == nil
}
+/*
+Removes and returns the element at the front of the list with O(1) time complexity.
+
+**Inputs**
+- list: The container list
+
+**Returns** The node member of the user-defined element structure, or `nil` if the list is empty
+*/
pop_front :: proc "contextless" (list: ^List) -> ^Node {
link := list.head
if link == nil {
@@ -130,6 +176,14 @@ pop_front :: proc "contextless" (list: ^List) -> ^Node {
return link
}
+/*
+Removes and returns the element at the back of the list with O(1) time complexity.
+
+**Inputs**
+- list: The container list
+
+**Returns** The node member of the user-defined element structure, or `nil` if the list is empty
+*/
pop_back :: proc "contextless" (list: ^List) -> ^Node {
link := list.tail
if link == nil {
@@ -151,29 +205,122 @@ pop_back :: proc "contextless" (list: ^List) -> ^Node {
}
+
Iterator :: struct($T: typeid) {
curr: ^Node,
offset: uintptr,
}
+/*
+Creates an iterator pointing at the head of the given list.
+
+**Inputs**
+- list: The container list
+- T: The type of the list's elements
+- field_name: The name of the node field in the `T` structure
+
+**Returns** An iterator pointing at the head of `list`
+
+Example:
+
+ My_Struct :: struct {
+ node : list.Node,
+ value: int,
+ }
+
+ l: list.List
+ it := list.iterator_head(l, My_Struct, "node")
+
+*/
iterator_head :: proc "contextless" (list: List, $T: typeid, $field_name: string) -> Iterator(T)
where intrinsics.type_has_field(T, field_name),
intrinsics.type_field_type(T, field_name) == Node {
return {list.head, offset_of_by_string(T, field_name)}
}
+/*
+Creates an iterator pointing at the tail of the given list.
+
+**Inputs**
+- list: The container list
+- T: The type of the list's elements
+- field_name: The name of the node field in the `T` structure
+
+**Returns** An iterator pointing at the tail of `list`
+
+Example:
+ My_Struct :: struct {
+ node : list.Node,
+ value: int,
+ }
+
+ l: list.List
+ it := list.iterator_tail(l, My_Struct, "node")
+
+*/
iterator_tail :: proc "contextless" (list: List, $T: typeid, $field_name: string) -> Iterator(T)
where intrinsics.type_has_field(T, field_name),
intrinsics.type_field_type(T, field_name) == Node {
return {list.tail, offset_of_by_string(T, field_name)}
}
+/*
+Creates an iterator pointing at the specified node of a list.
+
+**Inputs**
+- node: a list node
+- T: The type of the list's elements
+- field_name: The name of the node field in the `T` structure
+**Returns** An iterator pointing at `node`
+
+*/
iterator_from_node :: proc "contextless" (node: ^Node, $T: typeid, $field_name: string) -> Iterator(T)
where intrinsics.type_has_field(T, field_name),
intrinsics.type_field_type(T, field_name) == Node {
return {node, offset_of_by_string(T, field_name)}
}
+/*
+Retrieves the next element in a list and advances the iterator.
+
+**Inputs**
+- it: The iterator
+
+**Returns**
+- ptr: The next list element
+- ok: `true` if the element is valid (the iterator could advance), `false` otherwise
+
+Example:
+
+ import "core:fmt"
+ import "core:container/intrusive/list"
+
+ iterate_next_example :: proc() {
+ l: list.List
+
+ one := My_Struct{value=1}
+ two := My_Struct{value=2}
+
+ list.push_back(&l, &one.node)
+ list.push_back(&l, &two.node)
+
+ it := list.iterator_head(&l, My_Struct, "node")
+ for num in list.iterate_next(&it) {
+ fmt.println(num)
+ }
+ }
+
+ My_Struct :: struct {
+ node : list.Node,
+ value: int,
+ }
+
+Output:
+
+ 1
+ 2
+
+*/
iterate_next :: proc "contextless" (it: ^Iterator($T)) -> (ptr: ^T, ok: bool) {
node := it.curr
if node == nil {
@@ -183,7 +330,47 @@ iterate_next :: proc "contextless" (it: ^Iterator($T)) -> (ptr: ^T, ok: bool) {
return (^T)(uintptr(node) - it.offset), true
}
+/*
+Retrieves the previous element in a list and recede the iterator.
+
+**Inputs**
+- it: The iterator
+
+**Returns**
+- ptr: The previous list element
+- ok: `true` if the element is valid (the iterator could recede), `false` otherwise
+
+Example:
+ import "core:fmt"
+ import "core:container/intrusive/list"
+
+ iterate_next_example :: proc() {
+ l: list.List
+
+ one := My_Struct{value=1}
+ two := My_Struct{value=2}
+
+ list.push_back(&l, &one.node)
+ list.push_back(&l, &two.node)
+
+ it := list.iterator_tail(&l, My_Struct, "node")
+ for num in list.iterate_prev(&it) {
+ fmt.println(num)
+ }
+ }
+
+ My_Struct :: struct {
+ node : list.Node,
+ value: int,
+ }
+
+Output:
+
+ 2
+ 1
+
+*/
iterate_prev :: proc "contextless" (it: ^Iterator($T)) -> (ptr: ^T, ok: bool) {
node := it.curr
if node == nil {
@@ -192,4 +379,4 @@ iterate_prev :: proc "contextless" (it: ^Iterator($T)) -> (ptr: ^T, ok: bool) {
it.curr = node.prev
return (^T)(uintptr(node) - it.offset), true
-} \ No newline at end of file
+}