Files
2026-08-27 10:56:38 -06:00

277 lines
4.5 KiB
C#

using System;
using System.Collections;
namespace ProtoBuf.Meta;
internal class BasicList : IEnumerable
{
public struct NodeEnumerator : IEnumerator
{
private int position;
private readonly Node node;
public object Current => node[position];
internal NodeEnumerator(Node node)
{
position = -1;
this.node = node;
}
void IEnumerator.Reset()
{
position = -1;
}
public bool MoveNext()
{
int length = node.Length;
if (position <= length)
{
return ++position < length;
}
return false;
}
}
internal sealed class Node
{
private readonly object[] data;
private int length;
public object this[int index]
{
get
{
if (index >= 0 && index < length)
{
return data[index];
}
throw new ArgumentOutOfRangeException("index");
}
set
{
if (index >= 0 && index < length)
{
data[index] = value;
return;
}
throw new ArgumentOutOfRangeException("index");
}
}
public int Length => length;
internal Node(object[] data, int length)
{
this.data = data;
this.length = length;
}
public void RemoveLastWithMutate()
{
if (length == 0)
{
throw new InvalidOperationException();
}
length--;
}
public Node Append(object value)
{
int num = length + 1;
object[] array;
if (data == null)
{
array = new object[10];
}
else if (length == data.Length)
{
array = new object[data.Length * 2];
Array.Copy(data, array, length);
}
else
{
array = data;
}
array[length] = value;
return new Node(array, num);
}
public Node Trim()
{
if (length == 0 || length == data.Length)
{
return this;
}
object[] destinationArray = new object[length];
Array.Copy(data, destinationArray, length);
return new Node(destinationArray, length);
}
internal int IndexOfString(string value)
{
for (int i = 0; i < length; i++)
{
if (value == (string)data[i])
{
return i;
}
}
return -1;
}
internal int IndexOfReference(object instance)
{
for (int i = 0; i < length; i++)
{
if (instance == data[i])
{
return i;
}
}
return -1;
}
internal int IndexOf(MatchPredicate predicate, object ctx)
{
for (int i = 0; i < length; i++)
{
if (predicate(data[i], ctx))
{
return i;
}
}
return -1;
}
internal void CopyTo(Array array, int offset)
{
if (length > 0)
{
Array.Copy(data, 0, array, offset, length);
}
}
internal void Clear()
{
if (data != null)
{
Array.Clear(data, 0, data.Length);
}
length = 0;
}
}
internal delegate bool MatchPredicate(object value, object ctx);
internal sealed class Group
{
public readonly int First;
public readonly BasicList Items;
public Group(int first)
{
First = first;
Items = new BasicList();
}
}
private static readonly Node nil = new Node(null, 0);
protected Node head = nil;
public object this[int index] => head[index];
public int Count => head.Length;
public void CopyTo(Array array, int offset)
{
head.CopyTo(array, offset);
}
public int Add(object value)
{
return (head = head.Append(value)).Length - 1;
}
public void Trim()
{
head = head.Trim();
}
IEnumerator IEnumerable.GetEnumerator()
{
return new NodeEnumerator(head);
}
public NodeEnumerator GetEnumerator()
{
return new NodeEnumerator(head);
}
internal int IndexOf(MatchPredicate predicate, object ctx)
{
return head.IndexOf(predicate, ctx);
}
internal int IndexOfString(string value)
{
return head.IndexOfString(value);
}
internal int IndexOfReference(object instance)
{
return head.IndexOfReference(instance);
}
internal bool Contains(object value)
{
NodeEnumerator enumerator = GetEnumerator();
while (enumerator.MoveNext())
{
object current = enumerator.Current;
if (object.Equals(current, value))
{
return true;
}
}
return false;
}
internal static BasicList GetContiguousGroups(int[] keys, object[] values)
{
if (keys == null)
{
throw new ArgumentNullException("keys");
}
if (values == null)
{
throw new ArgumentNullException("values");
}
if (values.Length < keys.Length)
{
throw new ArgumentException("Not all keys are covered by values", "values");
}
BasicList basicList = new BasicList();
Group obj = null;
for (int i = 0; i < keys.Length; i++)
{
if (i == 0 || keys[i] != keys[i - 1])
{
obj = null;
}
if (obj == null)
{
obj = new Group(keys[i]);
basicList.Add(obj);
}
obj.Items.Add(values[i]);
}
return basicList;
}
}