File: Data\ArrayListBase.cs
Web Access
Project: src\src\runtime\src\native\managed\cdac\Microsoft.Diagnostics.DataContractReader.Contracts\Microsoft.Diagnostics.DataContractReader.Contracts.csproj (Microsoft.Diagnostics.DataContractReader.Contracts)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System;
using System.Collections.Generic;

namespace Microsoft.Diagnostics.DataContractReader.Data;

/// <summary>
/// Encapsulates structure and logic for ArrayListBase implemented in arraylist.h
/// </summary>
internal sealed class ArrayListBase : IData<ArrayListBase>
{
    static ArrayListBase IData<ArrayListBase>.Create(Target target, TargetPointer address) => new ArrayListBase(target, address);
    public ArrayListBase(Target target, TargetPointer address)
    {
        Target.TypeInfo type = target.GetTypeInfo(DataType.ArrayListBase);

        Count = target.ReadField<uint>(address, type, nameof(Count));
        FirstBlock = address + (ulong)type.Fields[nameof(FirstBlock)].Offset;

        TargetPointer next = FirstBlock;
        while (next != TargetPointer.Null)
        {
            ArrayListBlock block = target.ProcessedData.GetOrAdd<ArrayListBlock>(next);
            Blocks.Add(block);
            next = block.Next;
        }

        uint elementsFound = 0;
        foreach (ArrayListBlock block in Blocks)
        {
            foreach (TargetPointer element in block.Elements)
            {
                if (elementsFound >= Count)
                {
                    break;
                }

                Elements.Add(element);
                elementsFound++;
            }
        }
    }

    public uint Count { get; init; }
    public TargetPointer FirstBlock { get; init; }

    public List<ArrayListBlock> Blocks { get; init; } = [];
    public List<TargetPointer> Elements { get; init; } = [];

    internal sealed class ArrayListBlock : IData<ArrayListBlock>
    {
        static ArrayListBlock IData<ArrayListBlock>.Create(Target target, TargetPointer address) => new ArrayListBlock(target, address);
        public ArrayListBlock(Target target, TargetPointer address)
        {
            Target.TypeInfo type = target.GetTypeInfo(DataType.ArrayListBlock);

            Next = target.ReadPointerField(address, type, nameof(Next));
            Size = target.ReadField<uint>(address, type, nameof(Size));
            ArrayStart = address + (ulong)type.Fields[nameof(ArrayStart)].Offset;

            for (ulong i = 0; i < Size; i++)
            {
                Elements.Add(target.ReadPointer(ArrayStart + (i * (ulong)target.PointerSize)));
            }
        }

        public TargetPointer Next { get; init; }
        public uint Size { get; init; }
        public TargetPointer ArrayStart { get; init; }

        public List<TargetPointer> Elements { get; init; } = [];
    }
}