From 13e522ba64e2a0ee0bc417e158c43aa861fe99a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Anta=CC=83o=20Almada?= Date: Sun, 10 Sep 2023 12:39:31 +0100 Subject: [PATCH] Add Where() --- LICENSE | 2 +- ...etFabric.DoublyLinkedList.Benchmark.csproj | 4 +- .../NetFabric.DoublyLinkedList.Tests.csproj | 12 +- .../DoublyLinkedList'1.ForwardEnumeration.cs | 9 +- .../DoublyLinkedList'1.ReverseEnumeration.cs | 7 +- ...blyLinkedList'1.WhereForwardEnumeration.cs | 115 ++++++++++++++++++ ...blyLinkedList'1.WhereReverseEnumeration.cs | 115 ++++++++++++++++++ .../DoublyLinkedList'1.cs | 4 +- .../NetFabric.DoublyLinkedList.csproj | 14 +-- 9 files changed, 259 insertions(+), 23 deletions(-) create mode 100644 NetFabric.DoublyLinkedList/DoublyLinkedList'1.WhereForwardEnumeration.cs create mode 100644 NetFabric.DoublyLinkedList/DoublyLinkedList'1.WhereReverseEnumeration.cs diff --git a/LICENSE b/LICENSE index 2413786..95e4ec9 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2018-2021 Antao Almada +Copyright (c) 2018-2023 Antao Almada Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/NetFabric.DoublyLinkedList.Benchmark/NetFabric.DoublyLinkedList.Benchmark.csproj b/NetFabric.DoublyLinkedList.Benchmark/NetFabric.DoublyLinkedList.Benchmark.csproj index 3b1ecf3..9c3030b 100644 --- a/NetFabric.DoublyLinkedList.Benchmark/NetFabric.DoublyLinkedList.Benchmark.csproj +++ b/NetFabric.DoublyLinkedList.Benchmark/NetFabric.DoublyLinkedList.Benchmark.csproj @@ -1,4 +1,4 @@ - + Exe @@ -7,7 +7,7 @@ - + diff --git a/NetFabric.DoublyLinkedList.Tests/NetFabric.DoublyLinkedList.Tests.csproj b/NetFabric.DoublyLinkedList.Tests/NetFabric.DoublyLinkedList.Tests.csproj index 844a2b8..b6be92d 100644 --- a/NetFabric.DoublyLinkedList.Tests/NetFabric.DoublyLinkedList.Tests.csproj +++ b/NetFabric.DoublyLinkedList.Tests/NetFabric.DoublyLinkedList.Tests.csproj @@ -1,4 +1,4 @@ - + netcoreapp2.1;netcoreapp3.1;net5.0 @@ -6,14 +6,14 @@ - - - - + + + + all runtime; build; native; contentfiles; analyzers - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/NetFabric.DoublyLinkedList/DoublyLinkedList'1.ForwardEnumeration.cs b/NetFabric.DoublyLinkedList/DoublyLinkedList'1.ForwardEnumeration.cs index a793f72..e3b9c45 100644 --- a/NetFabric.DoublyLinkedList/DoublyLinkedList'1.ForwardEnumeration.cs +++ b/NetFabric.DoublyLinkedList/DoublyLinkedList'1.ForwardEnumeration.cs @@ -18,6 +18,9 @@ public readonly struct ForwardEnumeration internal ForwardEnumeration(DoublyLinkedList list) => this.list = list; + public WhereForwardEnumeration Where(Func predicate) + => new(list, predicate); + public int Count => list.count; @@ -102,12 +105,12 @@ public bool MoveNext() return current is not null; } - public readonly void Reset() - => Throw.NotSupportedException(); + public void Reset() + => current = null; public readonly void Dispose() { } - } + } } } } diff --git a/NetFabric.DoublyLinkedList/DoublyLinkedList'1.ReverseEnumeration.cs b/NetFabric.DoublyLinkedList/DoublyLinkedList'1.ReverseEnumeration.cs index 1246e9d..83f177e 100644 --- a/NetFabric.DoublyLinkedList/DoublyLinkedList'1.ReverseEnumeration.cs +++ b/NetFabric.DoublyLinkedList/DoublyLinkedList'1.ReverseEnumeration.cs @@ -17,6 +17,9 @@ public readonly struct ReverseEnumeration internal ReverseEnumeration(DoublyLinkedList list) => this.list = list; + public WhereReverseEnumeration Where(Func predicate) + => new(list, predicate); + public int Count => list.count; @@ -101,8 +104,8 @@ public bool MoveNext() return current is not null; } - public readonly void Reset() - => Throw.NotSupportedException(); + public void Reset() + => current = null; public readonly void Dispose() { } diff --git a/NetFabric.DoublyLinkedList/DoublyLinkedList'1.WhereForwardEnumeration.cs b/NetFabric.DoublyLinkedList/DoublyLinkedList'1.WhereForwardEnumeration.cs new file mode 100644 index 0000000..e365eab --- /dev/null +++ b/NetFabric.DoublyLinkedList/DoublyLinkedList'1.WhereForwardEnumeration.cs @@ -0,0 +1,115 @@ +using NetFabric.Hyperlinq; +using System; +using System.Collections; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Diagnostics.Contracts; +using System.Runtime.CompilerServices; + +namespace NetFabric +{ + public partial class DoublyLinkedList + { + public readonly struct WhereForwardEnumeration + : IValueEnumerable + { + readonly DoublyLinkedList list; + readonly Func predicate; + + internal WhereForwardEnumeration(DoublyLinkedList list, Func predicate) + { + this.list = list; + this.predicate = predicate; + } + + [Pure] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public Enumerator GetEnumerator() => + new(list, predicate); + + DisposableEnumerator IValueEnumerable.GetEnumerator() => + new(list, predicate); + + IEnumerator IEnumerable.GetEnumerator() => + new DisposableEnumerator(list, predicate); + + IEnumerator IEnumerable.GetEnumerator() => + new DisposableEnumerator(list, predicate); + + public struct Enumerator + { + readonly DoublyLinkedList list; + readonly Func predicate; + readonly int version; + Node? current; + + internal Enumerator(DoublyLinkedList list, Func predicate) + { + this.list = list; + this.predicate = predicate; + version = list.version; + current = null; + } + + public readonly T Current + => current!.Value; + + public bool MoveNext() + { + if (version != list.version) + Throw.InvalidOperationException(); + do + { + current = current is null + ? list.First + : current.Next; + } + while (current is not null && !predicate(current.Value)); + return current is not null; + } + } + + public struct DisposableEnumerator + : IEnumerator + { + readonly DoublyLinkedList list; + readonly Func predicate; + readonly int version; + Node? current; + + internal DisposableEnumerator(DoublyLinkedList list, Func predicate) + { + this.list = list; + this.predicate = predicate; + version = list.version; + current = null; + } + + public readonly T Current + => current!.Value; + readonly object? IEnumerator.Current + => current!.Value; + + public bool MoveNext() + { + if (version != list.version) + Throw.InvalidOperationException(); + do + { + current = current is null + ? list.First + : current.Next; + } + while (current is not null && !predicate(current.Value)); + return current is not null; + } + + public void Reset() + => current = null; + + public readonly void Dispose() + { } + } + } + } +} diff --git a/NetFabric.DoublyLinkedList/DoublyLinkedList'1.WhereReverseEnumeration.cs b/NetFabric.DoublyLinkedList/DoublyLinkedList'1.WhereReverseEnumeration.cs new file mode 100644 index 0000000..55aaf15 --- /dev/null +++ b/NetFabric.DoublyLinkedList/DoublyLinkedList'1.WhereReverseEnumeration.cs @@ -0,0 +1,115 @@ +using NetFabric.Hyperlinq; +using System; +using System.Collections; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Diagnostics.Contracts; +using System.Runtime.CompilerServices; + +namespace NetFabric +{ + public partial class DoublyLinkedList + { + public readonly struct WhereReverseEnumeration + : IValueEnumerable + { + readonly DoublyLinkedList list; + readonly Func predicate; + + internal WhereReverseEnumeration(DoublyLinkedList list, Func predicate) + { + this.list = list; + this.predicate = predicate; + } + + [Pure] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public Enumerator GetEnumerator() => + new(list, predicate); + + DisposableEnumerator IValueEnumerable.GetEnumerator() => + new(list, predicate); + + IEnumerator IEnumerable.GetEnumerator() => + new DisposableEnumerator(list, predicate); + + IEnumerator IEnumerable.GetEnumerator() => + new DisposableEnumerator(list, predicate); + + public struct Enumerator + { + readonly DoublyLinkedList list; + readonly Func predicate; + readonly int version; + Node? current; + + internal Enumerator(DoublyLinkedList list, Func predicate) + { + this.list = list; + this.predicate = predicate; + version = list.version; + current = null; + } + + public readonly T Current + => current!.Value; + + public bool MoveNext() + { + if (version != list.version) + Throw.InvalidOperationException(); + do + { + current = current is null + ? list.Last + : current.Previous; + } + while (current is not null && !predicate(current.Value)); + return current is not null; + } + } + + public struct DisposableEnumerator + : IEnumerator + { + readonly DoublyLinkedList list; + readonly Func predicate; + readonly int version; + Node? current; + + internal DisposableEnumerator(DoublyLinkedList list, Func predicate) + { + this.list = list; + this.predicate = predicate; + version = list.version; + current = null; + } + + public readonly T Current + => current!.Value; + readonly object? IEnumerator.Current + => current!.Value; + + public bool MoveNext() + { + if (version != list.version) + Throw.InvalidOperationException(); + do + { + current = current is null + ? list.Last + : current.Previous; + } + while (current is not null && !predicate(current.Value)); + return current is not null; + } + + public void Reset() + => current = null; + + public readonly void Dispose() + { } + } + } + } +} diff --git a/NetFabric.DoublyLinkedList/DoublyLinkedList'1.cs b/NetFabric.DoublyLinkedList/DoublyLinkedList'1.cs index 8c344fe..72bf7ef 100644 --- a/NetFabric.DoublyLinkedList/DoublyLinkedList'1.cs +++ b/NetFabric.DoublyLinkedList/DoublyLinkedList'1.cs @@ -854,7 +854,7 @@ public void RemoveLast() tail = node.Previous; tail.Next = null; } - node.Invalidate(); + node!.Invalidate(); count--; version++; } @@ -944,7 +944,7 @@ public void ReverseInPlace() if (count < 2) return; - Node temp; + Node? temp; var current = head; while (current is not null) { diff --git a/NetFabric.DoublyLinkedList/NetFabric.DoublyLinkedList.csproj b/NetFabric.DoublyLinkedList/NetFabric.DoublyLinkedList.csproj index e07db33..5bc2fe4 100644 --- a/NetFabric.DoublyLinkedList/NetFabric.DoublyLinkedList.csproj +++ b/NetFabric.DoublyLinkedList/NetFabric.DoublyLinkedList.csproj @@ -1,13 +1,13 @@ - + - net461;netstandard2.0 + net461;netstandard2.0; net6.0 NetFabric.DoublyLinkedList NetFabric.DoublyLinkedList An alternative to System.Collection.Generics.LinkedList with reverse operation and enumeration without allocation. - 3.0.0 + 3.1.0 Antao Almada - Copyright 2018-2021 Antao Almada + Copyright 2018-2023 Antao Almada Icon.png LICENSE collections, data structures, algorithms, list @@ -29,16 +29,16 @@ - + all runtime; build; native; contentfiles; analyzers - + all runtime; build; native; contentfiles; analyzers; buildtransitive - + all runtime; build; native; contentfiles; analyzers; buildtransitive