File: Data\ArrayListBase.cs
Web Access
Project: 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.Collections.Generic;
using System.Diagnostics.CodeAnalysis;

namespace Microsoft.Diagnostics.DataContractReader.Data;

/// <summary>
/// Encapsulates structure and logic for ArrayListBase implemented in arraylist.h
/// </summary>
[CdacType(nameof(DataType.ArrayListBase))]
internal sealed partial class ArrayListBase : IData<ArrayListBase>
{
    [Field] public uint Count { get; }

    [FieldAddress]
    public TargetPointer FirstBlock { get; }

    public IReadOnlyList<ArrayListBlock> Blocks { get; private set; } = [];
    public IReadOnlyList<TargetPointer> Elements { get; private set; } = [];

    [MemberNotNull(nameof(Blocks), nameof(Elements))]
    partial void OnInit(Target target, TargetPointer address)
    {
        List<ArrayListBlock> blocks = [];
        TargetPointer next = FirstBlock;
        while (next != TargetPointer.Null)
        {
            ArrayListBlock block = target.ProcessedData.GetOrAdd<ArrayListBlock>(next);
            blocks.Add(block);
            next = block.Next;
        }

        List<TargetPointer> elements = [];
        uint elementsFound = 0;
        foreach (ArrayListBlock block in blocks)
        {
            foreach (TargetPointer element in block.Elements)
            {
                if (elementsFound >= Count)
                {
                    break;
                }

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

        Blocks = blocks;
        Elements = elements;
    }
}

[CdacType(nameof(DataType.ArrayListBlock))]
internal sealed partial class ArrayListBlock : IData<ArrayListBlock>
{
    [Field] public TargetPointer Next { get; }
    [Field] public uint Size { get; }

    [FieldAddress]
    public TargetPointer ArrayStart { get; }

    public IReadOnlyList<TargetPointer> Elements { get; private set; } = [];

    [MemberNotNull(nameof(Elements))]
    partial void OnInit(Target target, TargetPointer address)
    {
        List<TargetPointer> elements = new((int)Size);
        for (ulong i = 0; i < Size; i++)
        {
            elements.Add(target.ReadPointer(ArrayStart + (i * (ulong)target.PointerSize)));
        }

        Elements = elements;
    }
}