MulAvailable

This commit is contained in:
Nitload
2025-12-16 23:13:17 +08:00
parent 28ea5d1d1e
commit 3486375470
2637 changed files with 23787 additions and 838773 deletions
@@ -1,206 +0,0 @@
//-----------------------------------------------------------------------
//-----------------------------------------------------------------------
// file="BidirectionalDictionary.cs"
// Project: StgSharp
// AuthorGroup: Nitload Space
// Copyright (c) Nitload Space. All rights reserved.
//
// 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.
//
//-----------------------------------------------------------------------
//-----------------------------------------------------------------------
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
namespace StgSharp.Commom.Collections
{
public sealed class BidirectionalDictionary<TFirst, TSecond> : IBidirectionalDictionary<TFirst, TSecond>
{
private readonly Dictionary<TFirst, TSecond> _forward;
private readonly Dictionary<TSecond, TFirst> _reverse;
public BidirectionalDictionary()
{
_forward = new Dictionary<TFirst, TSecond>();
_reverse = new Dictionary<TSecond, TFirst>();
}
public TFirst this[ TSecond key ]
{
get
{
if( _reverse.TryGetValue( key, out TFirst value ) ) {
return value;
}
throw new ArgumentException( $"Cannot find key {key!.ToString()} in dictionary." );
}
set
{
if( _reverse.TryGetValue( key, out TFirst origin ) )
{
_reverse[ key ] = value;
_forward.Remove( origin );
} else
{
_reverse.Add( key, value );
}
_forward.Add( value, key );
}
}
public TSecond this[ TFirst key ]
{
get
{
if( _forward.TryGetValue( key, out TSecond value ) ) {
return value;
}
throw new ArgumentException( $"Cannot find key {key!.ToString()} in dictionary." );
}
set
{
if( _forward.TryGetValue( key, out TSecond origin ) )
{
_forward[ key ] = value;
_reverse.Remove( origin );
} else
{
_forward.Add( key, value );
}
_reverse.Add( value, key );
}
}
public bool IsReadOnly => false;
public ICollection<TFirst> FirstIndex => _forward.Keys;
public ICollection<TSecond> SecondIndex => _reverse.Keys;
public int Count => _forward.Count;
public IReadOnlyDictionary<TFirst, TSecond> Forward => new ReadOnlyDictionary<TFirst, TSecond>(
_forward );
public IReadOnlyDictionary<TSecond, TFirst> Reverse => new ReadOnlyDictionary<TSecond, TFirst>(
_reverse );
public void Add( KeyValuePair<TFirst, TSecond> item )
{
if( _forward.ContainsKey( item.Key ) || _reverse.ContainsKey( item.Value ) ) {
throw new ArgumentException( "Duplicate key or value." );
}
_forward.Add( item.Key, item.Value );
_reverse.Add( item.Value, item.Key );
}
public void Add( TFirst key, TSecond value )
{
if( _forward.ContainsKey( key ) || _reverse.ContainsKey( value ) ) {
throw new ArgumentException( "Duplicate key or value." );
}
_forward.Add( key, value );
_reverse.Add( value, key );
}
public void Clear()
{
_forward.Clear();
_reverse.Clear();
}
public bool Contains( KeyValuePair<TFirst, TSecond> item )
{
return _forward.Contains( item ) &&
_reverse.TryGetValue( item.Value, out TFirst var ) &&
var!.Equals( item.Key );
}
public bool Contains( TSecond key )
{
return _reverse.ContainsKey( key );
}
public bool Contains( TFirst key )
{
return _forward.ContainsKey( key );
}
public void CopyTo( KeyValuePair<TFirst, TSecond>[] array, int arrayIndex )
{
if( array == null ) {
throw new ArgumentNullException( nameof( array ) );
}
if( arrayIndex < 0 || arrayIndex > array.Length ) {
throw new ArgumentOutOfRangeException( nameof( arrayIndex ) );
}
if( array.Length - arrayIndex < _forward.Count ) {
throw new ArgumentException( "The array is too small to copy the elements." );
}
foreach( KeyValuePair<TFirst, TSecond> pair in _forward ) {
array[ arrayIndex++ ] = pair;
}
}
public IEnumerator<KeyValuePair<TFirst, TSecond>> GetEnumerator()
{
foreach( KeyValuePair<TFirst, TSecond> pair in _forward ) {
yield return pair;
}
}
public bool Remove( TFirst key )
{
throw new NotImplementedException();
}
public bool Remove( KeyValuePair<TFirst, TSecond> item )
{
if( _forward.Remove( item.Key ) ) {
return _reverse.Remove( item.Value );
}
return false;
}
public bool TryGetValue( TFirst key, out TSecond value )
{
return _forward.TryGetValue( key, out value );
}
public bool TryGetValue( TSecond key, out TFirst value )
{
return _reverse.TryGetValue( key, out value );
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
}
-63
View File
@@ -1,63 +0,0 @@
//-----------------------------------------------------------------------
//-----------------------------------------------------------------------
// file="CachePool.cs"
// Project: StgSharp
// AuthorGroup: Nitload Space
// Copyright (c) Nitload Space. All rights reserved.
//
// 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.
//
//-----------------------------------------------------------------------
//-----------------------------------------------------------------------
using StgSharp.Graphics.OpenGL;
using System;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Text;
namespace StgSharp.Commom.Collections
{
/*
public interface IPoolItem<TSignature>
{
public int ID
{
get;
init;
}
}
public class CacheIndexPool<TSignature, TItem> : IEnumerable<TItem>
where TItem: IPoolItem<TSignature>
{
public CacheIndexPool(
Func<TSignature>
) { }
}
/**/
}
@@ -0,0 +1,92 @@
//-----------------------------------------------------------------------
// -----------------------------------------------------------------------
// file="CapacityFixedBag"
// Project: StgSharp
// AuthorGroup: Nitload
// Copyright (c) Nitload. All rights reserved.
//
// 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.
//
// -----------------------------------------------------------------------
// -----------------------------------------------------------------------
using System;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
namespace StgSharp.Collections
{
public sealed class CapacityFixedBag<T> : IEnumerable<T>
{
private readonly T[] _buffer;
public CapacityFixedBag(int capacity)
{
_buffer = new T[capacity];
}
public int Count { get; set; }
public int Capacity => _buffer.Length;
public void Add(T item)
{
if (Count >= _buffer.Length) {
throw new InvalidOperationException("Bag capacity exceeded.");
}
_buffer[Count] = item;
Count++;
}
public IEnumerator<T> GetEnumerator()
{
for (int i = 0; i < Count; i++) {
yield return _buffer[i];
}
}
public void Remove(T item)
{
int index = Array.IndexOf(_buffer, item, 0, Count);
if (index >= 0)
{
_buffer[index] = _buffer[Count - 1];
_buffer[Count - 1] = default!;
Count--;
}
}
public void RemoveAt(int index)
{
if (index >= 0)
{
_buffer[index] = _buffer[Count - 1];
_buffer[Count - 1] = default!;
Count--;
}
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
}
@@ -1,191 +0,0 @@
//-----------------------------------------------------------------------
//-----------------------------------------------------------------------
// file="CapacityFixedList.cs"
// Project: StgSharp
// AuthorGroup: Nitload Space
// Copyright (c) Nitload Space. All rights reserved.
//
// 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.
//
//-----------------------------------------------------------------------
//-----------------------------------------------------------------------
using System;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Text;
namespace StgSharp.Commom.Collections
{
public static class CapacityFixedListBuilder
{
internal static CapacityFixedList<T> Create<T>( ReadOnlySpan<T> values )
{
return new CapacityFixedList<T>( values );
}
}
[CollectionBuilder(
typeof( CapacityFixedListBuilder ),
nameof( CapacityFixedListBuilder.Create ) )]
public class CapacityFixedList<T> : IList<T>
{
private T[] _values;
private int capacity, _index;
public CapacityFixedList( int size )
{
_values = new T[size];
}
public CapacityFixedList( ReadOnlySpan<T> values )
{
_values = values.ToArray();
}
public T this[ int index ]
{
get => index < _index ?
_values[ index ] : throw new ArgumentOutOfRangeException( nameof( index ) );
set
{
if( index < _index )
{
_values[ index ] = value;
} else
{
throw new ArgumentOutOfRangeException( nameof( index ) );
}
}
}
public bool IsReadOnly => false;
public int Count => _index + 1;
public void Add( T item )
{
if( _index < capacity - 1 )
{
_index++;
this[ _index ] = item;
}
}
public void Clear()
{
_values = new T[capacity];
_index = 0;
}
public bool Contains( T item )
{
for( int i = 0; i <= _index; i++ )
{
if( item.Equals( _values[ i ] ) ) {
return true;
}
}
return false;
}
public void CopyTo( T[] array, int arrayIndex )
{
_values.CopyTo( array, arrayIndex );
}
public IEnumerator<T> GetEnumerator()
{
for( int i = 0; i <= _index; i++ ) {
yield return _values[ i ];
}
}
public int IndexOf( T item )
{
T v;
for( int i = 0; i <= _index; i++ )
{
if( ( v = _values[ i ] ) != null && v.Equals( item ) ) {
return i;
}
}
return -1;
}
public bool Remove( T item )
{
T v;
for( int i = 0; i <= _index; i++ )
{
if( ( v = _values[ i ] ) != null && v.Equals( item ) )
{
_values[ i ] = _values[ _index ];
_index--;
return true;
}
}
return false;
}
public void RemoveAll( Predicate<T> predicate )
{
for( int i = _index; i > 0; i-- )
{
if( predicate( _values[ i ] ) )
{
_values[ i ] = _values[ _index ];
_index--;
}
}
}
public void RemoveAt( int index )
{
if( index <= _index )
{
_values[ index ] = _values[ _index ];
_index--;
}
}
public void Resize( int newSize )
{
Array.Resize( ref _values, newSize );
}
IEnumerator IEnumerable.GetEnumerator()
{
yield return GetEnumerator();
}
void IList<T>.Insert( int index, T item )
{
throw new NotSupportedException();
}
}//------------------------------------- End of Class ------------------------------------------
}
@@ -0,0 +1,170 @@
//-----------------------------------------------------------------------
// -----------------------------------------------------------------------
// file="CapacityFixedStack"
// Project: StgSharp
// AuthorGroup: Nitload
// Copyright (c) Nitload. All rights reserved.
//
// 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.
//
// -----------------------------------------------------------------------
// -----------------------------------------------------------------------
using System;
using System.Collections;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using System.Threading;
namespace StgSharp.Collections
{
[CollectionBuilder(typeof(CapacityFixedStackBuilder), nameof(CapacityFixedStackBuilder.Create))]
public class CapacityFixedStack<T> : IEnumerable<T>
{
private readonly T[] _values;
// _index points to the next free slot (top empty position). Therefore Count == _index.
private int _index;
public CapacityFixedStack(int size)
{
ArgumentOutOfRangeException.ThrowIfNegative(size);
_values = new T[size];
_index = 0; // empty stack
}
public T? First => Volatile.Read(ref _index) > 0 ? _values[0] : default;
public bool IsEmpty => Volatile.Read(ref _index) == 0;
public int Count => Volatile.Read(ref _index);
public int Capacity => _values.Length;
public ReadOnlySpan<T> AsSpan() => _values.AsSpan(0, _index);
public void Clear()
{
if (_index > 0)
{
Array.Clear(_values, 0, _index);
_index = 0;
}
}
public IEnumerator<T> GetEnumerator()
{
for (int i = _index - 1; i >= 0; i--) {
yield return _values[i];
}
}
public T Peek()
{
if (_index == 0) {
throw new InvalidOperationException("Stack is empty.");
}
return _values[_index - 1];
}
public T Pop()
{
if (_index == 0) {
throw new InvalidOperationException("Stack is empty.");
}
_index--;
T item = _values[_index];
_values[_index] = default!; // Clear reference for GC
return item;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public T[] PopRange(int count)
{
if (count <= 0 || _index == 0) {
return Array.Empty<T>();
}
int n = Math.Min(count, _index);
int start = _index - n;
T[] ret = new T[n];
Array.Copy(_values, start, ret, 0, n);
Array.Clear(_values, start, n);
_index -= n;
return ret;
}
public void Push(T item)
{
if (_index >= _values.Length) {
throw new InvalidOperationException("Stack is full.");
}
_values[_index] = item;
_index++;
}
public void PushRange(ReadOnlySpan<T> span)
{
if (span.Length == 0) {
return;
}
if (_index + span.Length > _values.Length) {
throw new InvalidOperationException("Not enough space in the stack to push the entire span.");
}
span.CopyTo(_values.AsSpan(_index, span.Length));
_index += span.Length;
}
public bool TryPop(out T value)
{
if (_index == 0)
{
value = default!;
return false;
}
_index--;
value = _values[_index];
_values[_index] = default!;
return true;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal Span<T> GetValueLayout()
{
return _values.AsSpan();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
public static class CapacityFixedStackBuilder
{
public static CapacityFixedStack<T> Create<T>(ReadOnlySpan<T> values)
{
CapacityFixedStack<T> stack = new(values.Length);
stack.PushRange(values); // Push in order
return stack;
}
}
}
@@ -0,0 +1,287 @@
//-----------------------------------------------------------------------
// -----------------------------------------------------------------------
// file="ConcurrentCapacityFixedStack"
// Project: StgSharp
// AuthorGroup: Nitload Space
// Copyright (c) Nitload Space. All rights reserved.
//
// 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.
//
// -----------------------------------------------------------------------
// -----------------------------------------------------------------------
using System;
using System.Collections;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using System.Threading;
namespace StgSharp.Collections
{
/// <summary>
/// Lock-free, fixed-capacity stack implemented on top of an array using atomic index
/// operations. - No linked list; only array slots - Uses CAS on a shared top index to
/// reserve/release slots - Per-slot state flag to safely publish/consume values under races
/// </summary>
public class ConcurrentCapacityFixedStack<T> : IEnumerable<T>
{
private readonly int[] _states; // 0 = empty, 1 = full
private readonly T[] _values;
private readonly int _capacity;
// Number of full slots (observable count)
private int _count;
// Next push position (0.._capacity). Only modified via CAS.
private int _top;
public ConcurrentCapacityFixedStack(int capacity)
{
if (capacity <= 0) {
throw new ArgumentOutOfRangeException(nameof(capacity));
}
_capacity = capacity;
_values = new T[capacity];
_states = new int[capacity];
_top = 0;
_count = 0;
}
public bool IsEmpty => Count == 0;
public int Capacity => _capacity;
public int Count => Volatile.Read(ref _count);
public void Clear()
{
// Pop all elements to return slots to empty state
while (TryPop(out _)) { }
}
public IEnumerator<T> GetEnumerator()
{
T[] snap = ToArraySnapshot();
for (int i = 0; i < snap.Length; i++) {
yield return snap[i];
}
}
public T Peek()
{
if (TryPeek(out T? v)) {
return v;
}
throw new InvalidOperationException("Stack is empty.");
}
public T Pop()
{
if (TryPop(out T value)) {
return value;
}
throw new InvalidOperationException("Stack is empty.");
}
public T[] PopRange(int count)
{
if (count <= 0) {
return [];
}
T[] result = new T[count];
int i = 0;
for (; i < count; i++)
{
if (!TryPop(out result[i]))
{
break;
}
}
if (i == count) {
return result;
}
if (i == 0) {
return [];
}
T[] trimmed = new T[i];
Array.Copy(result, trimmed, i);
return trimmed;
}
public void Push(T item)
{
SpinWait sw = default;
while (true)
{
int oldTop = Volatile.Read(ref _top);
if (oldTop >= _capacity) {
throw new InvalidOperationException("Stack is full.");
}
if (Interlocked.CompareExchange(ref _top, oldTop + 1, oldTop) != oldTop)
{
sw.SpinOnce();
continue; // failed to reserve slot
}
// We exclusively own slot oldTop. Publish value then state.
_values[oldTop] = item;
Volatile.Write(ref _states[oldTop], 1); // publish
_ = Interlocked.Increment(ref _count);
return;
}
}
public void PushRange(ReadOnlySpan<T> span)
{
for (int i = 0; i < span.Length; i++) {
Push(span[i]);
}
}
/// <summary>
/// Best-effort snapshot for enumeration; not strongly consistent under concurrent
/// mutations.
/// </summary>
public T[] ToArraySnapshot()
{
int expected = Math.Min(Volatile.Read(ref _count), _capacity);
if (expected == 0) {
return Array.Empty<T>();
}
T[] snap = new T[expected];
int copied = 0;
int idx = Volatile.Read(ref _top) - 1;
while (idx >= 0 && copied < expected)
{
if (Volatile.Read(ref _states[idx]) == 1) {
snap[copied++] = _values[idx];
}
idx--;
}
if (copied == snap.Length) {
return snap;
}
T[] trimmed = new T[copied];
Array.Copy(snap, trimmed, copied);
return trimmed;
}
public bool TryPeek(out T value)
{
value = default!;
SpinWait sw = default;
while (true)
{
int top = Volatile.Read(ref _top);
if (top <= 0) {
return false;
}
int idx = top - 1;
// If not yet published or racing, retry/spin
if (Volatile.Read(ref _states[idx]) == 0)
{
if (Volatile.Read(ref _top) != top)
{
continue; // head moved, retry
}
sw.SpinOnce();
continue;
}
T v = _values[idx];
// Validate consistency
if (Volatile.Read(ref _top) == top && Volatile.Read(ref _states[idx]) == 1)
{
value = v;
return true;
}
}
}
public bool TryPop(out T value)
{
value = default!;
SpinWait sw = default;
while (true)
{
int oldTop = Volatile.Read(ref _top);
if (oldTop <= 0)
{
return false; // empty
}
int newTop = oldTop - 1; // index to consume
if (Interlocked.CompareExchange(ref _top, newTop, oldTop) != oldTop)
{
sw.SpinOnce();
continue; // failed to reserve element
}
// If producer hasn't published yet, roll back our reservation and retry.
if (Volatile.Read(ref _states[newTop]) == 0)
{
// attempt to restore top; ok if it fails due to concurrent operations
_ = Interlocked.CompareExchange(ref _top, newTop + 1, newTop);
sw.SpinOnce();
continue;
}
value = _values[newTop];
_values[newTop] = default!; // avoid ref retention
Volatile.Write(ref _states[newTop], 0); // mark empty
_ = Interlocked.Decrement(ref _count);
return true;
}
}
public int TryPopRange(Span<T> destination)
{
if (destination.IsEmpty) {
return 0;
}
int i = 0;
for (; i < destination.Length; i++)
{
if (!TryPop(out destination[i]))
{
break;
}
}
return i;
}
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
}
}
@@ -1,87 +0,0 @@
//-----------------------------------------------------------------------
//-----------------------------------------------------------------------
// file="IBidrirectionalDictionary.cs"
// Project: StgSharp
// AuthorGroup: Nitload Space
// Copyright (c) Nitload Space. All rights reserved.
//
// 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.
//
//-----------------------------------------------------------------------
//-----------------------------------------------------------------------
using System;
using System.Collections;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace StgSharp.Commom.Collections
{
public interface IBidirectionalDictionary<TFirst, TSecond> : IDictionary<TFirst, TSecond>
{
public TFirst this[ TSecond key ] { get; set; }
public ICollection<TFirst> FirstIndex { get; }
public ICollection<TSecond> SecondIndex { get; }
public IReadOnlyDictionary<TFirst, TSecond> Forward { get; }
public IReadOnlyDictionary<TSecond, TFirst> Reverse { get; }
/// <summary>
/// Determines whether the <see cref="IBidirectionalDictionary{TFirst, TSecond}" />
/// contains the specified key.
/// </summary>
/// <param _label="key">
/// The value to locate in the <see cref="IBidirectionalDictionary{TFirst, TSecond}" />.
/// </param>
/// <returns>
/// true if the <see cref="IBidirectionalDictionary{TFirst, TSecond}" /> contains an
/// element with the specified key; otherwise, false.
/// </returns>
public bool Contains( TSecond key );
/// <summary>
/// Determines whether the <see cref="IBidirectionalDictionary{TFirst, TSecond}" />
/// contains the specified key.
/// </summary>
/// <param _label="key">
/// The value to locate in the <see cref="IBidirectionalDictionary{TFirst, TSecond}" />.
/// </param>
/// <returns>
/// true if the <see cref="IBidirectionalDictionary{TFirst, TSecond}" /> contains an
/// element with the specified key; otherwise, false.
/// </returns>
public bool Contains( TFirst key );
public bool TryGetValue( TSecond key, out TFirst value );
#pragma warning disable CA1033
ICollection<TFirst> IDictionary<TFirst, TSecond>.Keys => FirstIndex;
ICollection<TSecond> IDictionary<TFirst, TSecond>.Values => SecondIndex;
bool IDictionary<TFirst, TSecond>.ContainsKey( TFirst key ) => Contains( key );
#pragma warning restore CA1033
}
}
@@ -1,48 +0,0 @@
//-----------------------------------------------------------------------
//-----------------------------------------------------------------------
// file="IHashMultiplexer.cs"
// Project: StgSharp
// AuthorGroup: Nitload Space
// Copyright (c) Nitload Space. All rights reserved.
//
// 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.
//
//-----------------------------------------------------------------------
//-----------------------------------------------------------------------
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
namespace StgSharp.Collections
{
public interface IHashMultiplexer<T> : IEqualityComparer<T>
{
int RemainedMultiplexCount { get; set; }
void CacheHash( T obj, int count );
void ExtendCache( int count );
int ForceComputeHash( T count );
}
}
-134
View File
@@ -1,134 +0,0 @@
//-----------------------------------------------------------------------
//-----------------------------------------------------------------------
// file="ListSegment.cs"
// Project: StgSharp
// AuthorGroup: Nitload Space
// Copyright (c) Nitload Space. All rights reserved.
//
// 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.
//
//-----------------------------------------------------------------------
//-----------------------------------------------------------------------
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Serialization;
namespace StgSharp.Collections
{
/// <summary>
/// Part of a collection. This contains a direct reference to _origin collection, so all
/// change to _origin collection will be reflected in this object.
/// </summary>
/// <typeparam name="T">
///
/// </typeparam>
public struct ListSegment<T> : ICollection<T>
{
private int _begin;
private int _length;
private List<T> _collection;
public ListSegment( List<T> collection, int begin, int length )
{
ArgumentNullException.ThrowIfNull( collection );
ArgumentOutOfRangeException.ThrowIfLessThan( begin, 0 );
ArgumentOutOfRangeException.ThrowIfLessThan( length, 0 );
ArgumentOutOfRangeException.ThrowIfLessThan( begin + length, collection.Count );
_collection = collection;
_begin = begin;
_length = length;
}
public T this[ int indexValue ]
{
get
{
ArgumentOutOfRangeException.ThrowIfLessThan( indexValue, 0 );
ArgumentOutOfRangeException.ThrowIfGreaterThanOrEqual( indexValue, _length );
return _collection[ indexValue + _begin ];
}
}
public T this[ Index i ]
{
get
{
int offset = i.IsFromEnd ? _length - i.Value : i.Value;
ArgumentOutOfRangeException.ThrowIfLessThan( offset, 0 );
ArgumentOutOfRangeException.ThrowIfGreaterThanOrEqual( offset, _length );
return _collection[ offset + _begin ];
}
}
public bool IsReadOnly => true;
public int Count => _length;
public bool Contains( T item )
{
int index = _collection.IndexOf( item );
return index >= _begin && index < _length + index;
}
public void CopyTo( T[] array, int arrayIndex )
{
ArgumentNullException.ThrowIfNull( array );
Span<T> span = CollectionsMarshal.AsSpan<T>( _collection ).Slice( _begin, _length );
Span<T> target = new Span<T>( array, arrayIndex, _length );
span.CopyTo( target );
}
public IEnumerator<T> GetEnumerator()
{
for( int i = _begin; i < _length; i++ ) {
yield return this[ i ];
}
}
void ICollection<T>.Add( T item )
{
throw new NotSupportedException();
}
void ICollection<T>.Clear()
{
throw new NotSupportedException();
}
bool ICollection<T>.Remove( T item )
{
throw new NotSupportedException();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
}
@@ -0,0 +1,191 @@
//-----------------------------------------------------------------------
// -----------------------------------------------------------------------
// file="NotEnumerableList"
// Project: StgSharp
// AuthorGroup: Nitload
// Copyright (c) Nitload. All rights reserved.
//
// 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.
//
// -----------------------------------------------------------------------
// -----------------------------------------------------------------------
using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
namespace StgSharp.Collections
{
public static class LinearBagBuilder
{
/// <summary>
/// Build a <see cref="LinearBag{T}" /> from a read-only span. Capacity will exactly fit
/// the input.
/// </summary>
public static LinearBag<T> FromSpan<T>(ReadOnlySpan<T> values)
{
if (values.IsEmpty) {
return new LinearBag<T>(4);
}
LinearBag<T> bag = new(values.Length);
for (int i = 0; i < values.Length; i++) {
bag.Add(values[i]);
}
return bag;
}
}
/// <summary>
/// A very lightweight contiguous storage structure: unordered, not enumerable by design.
/// Provides O(1) Add and O(1) RemoveAt (by swapping with the tail). Intended for high-
/// performance scenarios where element ordering does not matter. NOT thread-safe.
/// </summary>
/// <typeparam name="T">
/// Element type.
/// </typeparam>
[CollectionBuilder(typeof(LinearBagBuilder), nameof(LinearBagBuilder.FromSpan))]
public class LinearBag<T>(int capacity = 4)
{
// Invariant: valid elements occupy indexes [0, Count-1]. Count is the number of live elements.
private T[] _items = new T[Math.Max(0, capacity)];
/// <summary>
/// Access element by index (0..Count-1). Throws if out of range.
/// </summary>
public T this[int index]
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get => (uint)index >= (uint)Count ? throw new ArgumentOutOfRangeException(nameof(index)) : _items[index];
[MethodImpl(MethodImplOptions.AggressiveInlining)]
set
{
if ((uint)index >= (uint)Count) {
throw new ArgumentOutOfRangeException(nameof(index));
}
_items[index] = value;
}
}
/// <summary>
/// Total allocated slots.
/// </summary>
public int Capacity => _items.Length;
/// <summary>
/// Number of currently stored elements (valid index range 0..Count-1).
/// </summary>
public int Count { get; private set; }
/// <summary>
/// Adds an item (unordered). Expands internal array if needed.
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Add(T item)
{
if (Count == _items.Length) {
EnsureCapacity(Count + 1);
}
_items[Count] = item;
Count++;
}
/// <summary>
/// Returns a span over the live portion of the bag (0..Count-1).
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public Span<T> AsSpan() => new Span<T>(_items, 0, Count);
/// <summary>
/// Clears all elements and zeroes out references to avoid retention. Count becomes 0.
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Clear()
{
Array.Clear(_items, 0, Count);
Count = 0;
}
/// <summary>
/// Fast clear: only resets Count (leaves underlying array unchanged). References are NOT
/// released. Use only when you are certain old references can remain.
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void FastClear() => Count = 0;
/// <summary>
/// Removes the first occurrence of value (unordered). Does nothing if not found.
/// </summary>
public void Remove(T value)
{
EqualityComparer<T> comparer = EqualityComparer<T>.Default;
for (int i = 0; i < Count; i++)
{
if (comparer.Equals(_items[i], value))
{
RemoveAt(i);
return;
}
}
}
/// <summary>
/// Removes element at index by swapping the last element into its slot (unless already
/// last). Preserves O(1) removal at cost of ordering.
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void RemoveAt(int index)
{
if ((uint)index >= (uint)Count) {
throw new ArgumentOutOfRangeException(nameof(index));
}
int last = Count - 1;
if (index != last) {
_items[index] = _items[last];
}
_items[last] = default!; // release reference / reset value
Count = last;
}
/// <summary>
/// Ensures capacity is at least <paramref name="min" />. Doubles size when growing.
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private void EnsureCapacity(int min)
{
if (_items.Length >= min) {
return;
}
int newCapacity = _items.Length == 0 ? 4 : _items.Length * 2;
if (newCapacity < min) {
newCapacity = min;
}
Array.Resize(ref _items, newCapacity);
}
}
}
@@ -1,180 +0,0 @@
//-----------------------------------------------------------------------
//-----------------------------------------------------------------------
// file="PartialDictionary.cs"
// Project: StgSharp
// AuthorGroup: Nitload Space
// Copyright (c) Nitload Space. All rights reserved.
//
// 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.
//
//-----------------------------------------------------------------------
//-----------------------------------------------------------------------
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Net.Http.Headers;
using System.Text;
namespace StgSharp.Collections
{
public partial class PartialDictionary<TKey, TValue> : IDictionary<TKey, TValue>
{
private readonly Dictionary<TKey, TValue> _source;
private readonly HashSet<TKey> _keys;
private readonly PartialDictionaryValues _values;
public PartialDictionary( Dictionary<TKey, TValue> source, TKey[] index )
{
_source = source;
_keys = new HashSet<TKey>( index );
foreach( TKey item in _keys )
{
if( !_source.ContainsKey( item ) ) {
_source.Add( item, default! );
}
}
_values = new PartialDictionaryValues( this );
}
public PartialDictionary( Dictionary<TKey, TValue> source, HashSet<TKey> keys )
{
_source = source;
_keys = keys;
foreach( TKey item in _keys )
{
if( !_source.ContainsKey( item ) ) {
_source.Add( item, default! );
}
}
_values = new PartialDictionaryValues( this );
}
public PartialDictionary(
Dictionary<TKey, TValue> source,
TKey[] index,
IHashMultiplexer<TKey> multiplexer )
{
_source = source;
_keys = new HashSet<TKey>( index );
foreach( TKey item in _keys )
{
if( !_source.ContainsKey( item ) ) {
_source.Add( item, default! );
}
}
_values = new PartialDictionaryValues( this );
}
public TValue this[ TKey key ]
{
get
{
if( _keys.Contains( key ) ) {
return _source[ key ];
}
throw new KeyNotFoundException();
}
set
{
if( _keys.Contains( key ) ) {
_source[ key ] = value;
}
throw new KeyNotFoundException();
}
}
public ICollection<TKey> Keys => _keys;
public ICollection<TValue> Values => _values;
public int Count => _keys.Count;
public bool Contains( KeyValuePair<TKey, TValue> item )
{
return _keys.Contains( item.Key ) && _source.Contains( item );
}
public bool ContainsKey( TKey key )
{
return _keys.Contains( key );
}
public void CopyTo( KeyValuePair<TKey, TValue>[] array, int arrayIndex )
{
throw new NotImplementedException();
}
public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
{
foreach( TKey item in _keys ) {
yield return new KeyValuePair<TKey, TValue>( item, _source[ item ] );
}
}
public bool TryGetValue( TKey key, out TValue value )
{
if( _keys.Contains( key ) )
{
value = _source[ key ];
return true;
}
value = default!;
return false;
}
void ICollection<KeyValuePair<TKey, TValue>>.Add( KeyValuePair<TKey, TValue> item )
{
return;
}
void ICollection<KeyValuePair<TKey, TValue>>.Clear()
{
throw new NotSupportedException();
}
bool ICollection<KeyValuePair<TKey, TValue>>.Remove( KeyValuePair<TKey, TValue> item )
{
throw new NotSupportedException();
}
bool ICollection<KeyValuePair<TKey, TValue>>.IsReadOnly => true;
void IDictionary<TKey, TValue>.Add( TKey key, TValue value )
{
return;
}
bool IDictionary<TKey, TValue>.Remove( TKey key )
{
throw new NotSupportedException();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
}
@@ -1,105 +0,0 @@
//-----------------------------------------------------------------------
//-----------------------------------------------------------------------
// file="PartialDictionaryValues.cs"
// Project: StgSharp
// AuthorGroup: Nitload Space
// Copyright (c) Nitload Space. All rights reserved.
//
// 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.
//
//-----------------------------------------------------------------------
//-----------------------------------------------------------------------
using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
namespace StgSharp.Collections
{
public partial class PartialDictionary<TKey, TValue>
{
internal sealed class PartialDictionaryValues : ICollection<TValue>
{
private readonly PartialDictionary<TKey, TValue> _values;
public PartialDictionaryValues( PartialDictionary<TKey, TValue> value )
{
_values = value;
}
public bool IsReadOnly => true;
public int Count => _values.Count;
public bool Contains( TValue item )
{
foreach( KeyValuePair<TKey, TValue> kvp in _values )
{
if( kvp.Value != null && kvp.Value.Equals( item ) ) {
return true;
}
}
return false;
}
public void CopyTo( TValue[] array, int arrayIndex )
{
foreach( KeyValuePair<TKey, TValue> kvp in _values )
{
array[ arrayIndex ] = kvp.Value;
arrayIndex++;
}
}
public IEnumerator<TValue> GetEnumerator()
{
foreach( TKey key in _values._keys ) {
yield return _values._source[ key ];
}
}
void ICollection<TValue>.Add( TValue item )
{
return;
}
void ICollection<TValue>.Clear()
{
return;
}
bool ICollection<TValue>.Remove( TValue item )
{
throw new NotSupportedException();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
}
}
@@ -1,185 +0,0 @@
//-----------------------------------------------------------------------
//-----------------------------------------------------------------------
// file="RandomAccessibleStack.cs"
// Project: StgSharp
// AuthorGroup: Nitload Space
// Copyright (c) Nitload Space. All rights reserved.
//
// 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.
//
//-----------------------------------------------------------------------
//-----------------------------------------------------------------------
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
namespace StgSharp.Collections
{
public class RandomAccessibleStack<T> : IEnumerable<T>
{
private const int DefaultCapacity = 4;
private T[] _array;
private int _size;
private int _version;
/// <summary>
/// Initializes a new instance of the RandomAccessStack class that is empty and has the
/// default initial capacity.
/// </summary>
public RandomAccessibleStack()
{
_array = new T[DefaultCapacity];
}
/// <summary>
/// Initializes a new instance of the RandomAccessStack class that is empty and has the
/// specified initial capacity.
/// </summary>
public RandomAccessibleStack( int capacity )
{
if( capacity < 0 ) {
throw new ArgumentOutOfRangeException(
nameof( capacity ), "Capacity must be non-negative." );
}
_array = new T[capacity];
}
/// <summary>
/// Gets or sets the element at the specified index in the stack (0 = bottom, Count-1 =
/// top).
/// </summary>
public T this[ int index ]
{
get
{
if( index < 0 || index >= _size ) {
throw new ArgumentOutOfRangeException( nameof( index ) );
}
return _array[ index ];
}
/*
set
{
if( index < 0 || index >= _size ) {
throw new ArgumentOutOfRangeException( nameof( index ) );
}
_array[ index ] = value;
_version++;
}
/**/
}
/// <summary>
/// Gets the number of elements contained in the stack.
/// </summary>
public int Count => _size;
/// <summary>
/// Removes all objects from the stack.
/// </summary>
public void Clear()
{
Array.Clear( _array, 0, _size );
_size = 0;
_version++;
}
/// <summary>
/// Returns an enumerator that iterates through the stack from top to bottom. Throws if
/// the stack is modified during iteration.
/// </summary>
public IEnumerator<T> GetEnumerator()
{
int expectedVersion = _version;
for( int i = _size - 1; i >= 0; i-- )
{
if( expectedVersion != _version ) {
throw new InvalidOperationException(
"Collection was modified during enumeration." );
}
yield return _array[ i ];
}
}
/// <summary>
/// Returns the object at the top of the stack without removing it.
/// </summary>
public T Peek()
{
if( _size == 0 ) {
throw new InvalidOperationException( "Stack is empty." );
}
return _array[ _size - 1 ];
}
/// <summary>
/// Removes and returns the object at the top of the stack.
/// </summary>
public T Pop()
{
if( _size == 0 ) {
throw new InvalidOperationException( "Stack is empty." );
}
T item = _array[ --_size ];
_array[ _size ] = default!;
_version++;
return item;
}
/// <summary>
/// Adds an item to the top of the stack.
/// </summary>
public void Push( T item )
{
if( _size == _array.Length ) {
EnsureCapacity( _size + 1 );
}
_array[ _size++ ] = item;
_version++;
}
private void EnsureCapacity( int min )
{
int newCapacity = _array.Length == 0 ? DefaultCapacity : _array.Length * 2;
if( newCapacity < min ) {
newCapacity = min;
}
Array.Resize( ref _array, newCapacity );
}
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
}
}
@@ -1,165 +0,0 @@
//-----------------------------------------------------------------------
//-----------------------------------------------------------------------
// file="StringHashMultiplexer.cs"
// Project: StgSharp
// AuthorGroup: Nitload Space
// Copyright (c) Nitload Space. All rights reserved.
//
// 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.
//
//-----------------------------------------------------------------------
//-----------------------------------------------------------------------
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading;
namespace StgSharp.Collections
{
public sealed class StringHashMultiplexer : IHashMultiplexer<string>
{
private int _initCount, _remainedCount, _hashCache, _hashLast;
private string _source, _sourceLast;
public int RemainedMultiplexCount
{
get => _remainedCount;
set => _initCount = value;
}
public void CacheHash( string obj, int count )
{
_hashCache = ForceComputeHash( obj );
_initCount = count;
_remainedCount = _initCount;
_source = obj;
}
public bool Equals( string x, string y )
{
return x == y;
}
public void ExtendCache( int count )
{
_initCount += count;
_remainedCount += count;
}
[MethodImpl( MethodImplOptions.AggressiveInlining )]
public unsafe int ForceComputeHash( [NotNull] string obj )
{
int hash;
fixed( char* cPtr = obj.AsSpan() ) {
hash = InternalIO.Intrinsic.city_hash_simplify( cPtr, obj.Length );
}
return hash;
}
public int GetHashCode( string obj )
{
if( _remainedCount > 0 && ReferenceEquals( _source, obj ) )
{
_remainedCount--;
return _hashCache;
}
if( ReferenceEquals( _sourceLast, obj ) ) {
return _hashLast;
}
_sourceLast = obj;
_hashLast = ForceComputeHash( obj );
return _hashLast;
}
}
public sealed class ConcurrentStringHashMultiplexer : IHashMultiplexer<string>, IDisposable
{
private bool disposedValue;
private readonly ThreadLocal<StringHashMultiplexer> _multiplexers =
new( () => new StringHashMultiplexer() );
public int RemainedMultiplexCount
{
get => _multiplexers.Value.RemainedMultiplexCount;
set => _multiplexers.Value.RemainedMultiplexCount = value;
}
public void CacheHash( string obj, int count )
{
throw new NotImplementedException();
}
// ~ConcurrentStringHashMultiplexer()
// {
// Dispose(disposing: false);
// }
public void Dispose()
{
Dispose( disposing: true );
GC.SuppressFinalize( this );
}
public bool Equals( string x, string y )
{
return x == y;
}
public void ExtendCache( int count )
{
_multiplexers.Value.ExtendCache( count );
}
public unsafe int ForceComputeHash( [NotNull] string obj )
{
int hash;
fixed( char* cPtr = obj.AsSpan() ) {
hash = InternalIO.Intrinsic.city_hash_simplify( cPtr, obj.Length );
}
return hash;
}
public int GetHashCode( string obj )
{
return _multiplexers.Value.GetHashCode( obj );
}
private void Dispose( bool disposing )
{
if( !disposedValue )
{
if( disposing ) {
_multiplexers.Dispose();
}
disposedValue = true;
}
}
}
}