| File: DataFrameBuffer.cs | Web Access |
| Project: src\src\Microsoft.Data.Analysis\Microsoft.Data.Analysis.csproj (Microsoft.Data.Analysis) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. using System; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; namespace Microsoft.Data.Analysis { /// <summary> /// A basic mutable store to hold values in a DataFrame column. Supports wrapping with an ArrowBuffer /// </summary> /// <typeparam name="T"></typeparam> internal class DataFrameBuffer<T> : ReadOnlyDataFrameBuffer<T> where T : unmanaged { private const int MinCapacity = 8; private Memory<byte> _memory; public override ReadOnlyMemory<byte> ReadOnlyBuffer => _memory; public Memory<byte> Buffer { get => _memory; } public Span<T> Span { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => (MemoryMarshal.Cast<byte, T>(Buffer.Span)).Slice(0, Length); } public Span<T> RawSpan { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => MemoryMarshal.Cast<byte, T>(Buffer.Span); } public DataFrameBuffer(int capacity = 0) { if ((long)capacity > MaxCapacity) { throw new ArgumentException($"{capacity} exceeds buffer capacity", nameof(capacity)); } _memory = new byte[Math.Max(capacity, MinCapacity) * Size]; } internal DataFrameBuffer(ReadOnlyMemory<byte> buffer, int length) { _memory = new byte[buffer.Length]; buffer.CopyTo(_memory); Length = length; } public void Append(T value) { EnsureCapacity(1); RawSpan[Length] = value; Length++; } public void IncreaseSize(int numberOfValues) { EnsureCapacity(numberOfValues); Length += numberOfValues; } public void EnsureCapacity(int numberOfValues) { long newLength = Length + (long)numberOfValues; if (newLength > MaxCapacity) { throw new ArgumentException("Current buffer is full", nameof(numberOfValues)); } if (newLength > Capacity) { //Double buffer size, but not higher than MaxByteCapacity var doubledSize = (int)Math.Min((long)ReadOnlyBuffer.Length * 2, ArrayUtility.ArrayMaxSize); var newCapacity = Math.Max(newLength * Size, doubledSize); var memory = new Memory<byte>(new byte[newCapacity]); _memory.CopyTo(memory); _memory = memory; } } internal override T this[int index] { set { if (index >= Length) throw new ArgumentOutOfRangeException(nameof(index)); RawSpan[index] = value; } } internal static DataFrameBuffer<T> GetMutableBuffer(ReadOnlyDataFrameBuffer<T> buffer) { DataFrameBuffer<T> mutableBuffer = buffer as DataFrameBuffer<T>; if (mutableBuffer == null) { mutableBuffer = new DataFrameBuffer<T>(buffer.ReadOnlyBuffer, buffer.Length); } return mutableBuffer; } } }