forked from stride3d/stride
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathUnmanagedArray.cs
134 lines (115 loc) · 3.61 KB
/
UnmanagedArray.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
// Copyright (c) Xenko contributors (https://xenko.com) and Silicon Studio Corp. (https://www.siliconstudio.co.jp)
// Distributed under the MIT license. See the LICENSE.md file in the project root for more information.
using System;
using Xenko.Core.Annotations;
namespace Xenko.Core
{
public class UnmanagedArray<T> : IDisposable where T : struct
{
private readonly int sizeOfT;
private readonly bool isShared;
public UnmanagedArray(int length)
{
Length = length;
sizeOfT = Utilities.SizeOf<T>();
var finalSize = length * sizeOfT;
Pointer = Utilities.AllocateMemory(finalSize);
isShared = false;
}
public UnmanagedArray(int length, IntPtr unmanagedDataPtr)
{
Length = length;
sizeOfT = Utilities.SizeOf<T>();
Pointer = unmanagedDataPtr;
isShared = true;
}
public void Dispose()
{
if (!isShared)
{
Utilities.FreeMemory(Pointer);
}
}
public T this[int index]
{
get
{
if (index >= Length)
{
throw new ArgumentOutOfRangeException();
}
var res = new T();
unsafe
{
var bptr = (byte*)Pointer;
bptr += index * sizeOfT;
Interop.Read<T>(bptr, ref res);
}
return res;
}
set
{
if (index >= Length)
{
throw new ArgumentOutOfRangeException();
}
unsafe
{
var bptr = (byte*)Pointer;
bptr += index * sizeOfT;
Interop.Write<T>(bptr, ref value);
}
}
}
public void Read([NotNull] T[] destination, int offset = 0)
{
if (offset + destination.Length > Length)
{
throw new ArgumentOutOfRangeException();
}
unsafe
{
Interop.Read((void*)Pointer, destination, offset, destination.Length);
}
}
public void Read(T[] destination, int pointerByteOffset, int arrayOffset, int arrayLen)
{
if (arrayOffset + arrayLen > Length)
{
throw new ArgumentOutOfRangeException();
}
unsafe
{
var ptr = (byte*)Pointer;
ptr += pointerByteOffset;
Interop.Read(ptr, destination, arrayOffset, arrayLen);
}
}
public void Write([NotNull] T[] source, int offset = 0)
{
if (offset + source.Length > Length)
{
throw new ArgumentOutOfRangeException();
}
unsafe
{
Interop.Write((void*)Pointer, source, offset, source.Length);
}
}
public void Write(T[] source, int pointerByteOffset, int arrayOffset, int arrayLen)
{
if (arrayOffset + arrayLen > Length)
{
throw new ArgumentOutOfRangeException();
}
unsafe
{
var ptr = (byte*)Pointer;
ptr += pointerByteOffset;
Interop.Write(ptr, source, arrayOffset, arrayLen);
}
}
public IntPtr Pointer { get; }
public int Length { get; }
}
}