1 | #Region "Microsoft.VisualBasic::b11d660d704e736afcac6dbdfc461d60, Microsoft.VisualBasic.Core\Extensions\Reflection\Marshal\Pointer(Of T).vb" |
2 | |
3 | ' Author: |
4 | ' |
5 | ' asuka (amethyst.asuka@gcmodeller.org) |
6 | ' xie (genetics@smrucc.org) |
7 | ' xieguigang (xie.guigang@live.com) |
8 | ' |
9 | ' Copyright (c) 2018 GPL3 Licensed |
10 | ' |
11 | ' |
12 | ' GNU GENERAL PUBLIC LICENSE (GPL3) |
13 | ' |
14 | ' |
15 | ' This program is free software: you can redistribute it and/or modify |
16 | ' it under the terms of the GNU General Public License as published by |
17 | ' the Free Software Foundation, either version 3 of the License, or |
18 | ' (at your option) any later version. |
19 | ' |
20 | ' This program is distributed in the hope that it will be useful, |
21 | ' but WITHOUT ANY WARRANTY; without even the implied warranty of |
22 | ' MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
23 | ' GNU General Public License for more details. |
24 | ' |
25 | ' You should have received a copy of the GNU General Public License |
26 | ' along with this program. If not, see <http://www.gnu.org/licenses/>. |
27 | |
28 | |
29 | |
30 | ' /********************************************************************************/ |
31 | |
32 | ' Summaries: |
33 | |
34 | ' Class Pointer |
35 | ' |
36 | ' Properties: Current, EndRead, Length, NullEnd, Position |
37 | ' RawBuffer, UBound |
38 | ' |
39 | ' Constructor: (+4 Overloads) Sub New |
40 | ' Function: MoveNext, PeekNext, stackalloc, ToString |
41 | ' Operators: (+2 Overloads) -, (+2 Overloads) +, <<, (+2 Overloads) <=, <> |
42 | ' =, (+2 Overloads) >=, >> |
43 | ' |
44 | ' Structure SwapHelper |
45 | ' |
46 | ' Sub: Swap |
47 | ' |
48 | ' |
49 | ' /********************************************************************************/ |
50 | |
51 | #End Region |
52 | |
53 | Imports System.Runtime.CompilerServices |
54 | Imports Microsoft.VisualBasic.ComponentModel |
55 | Imports Microsoft.VisualBasic.Linq |
56 | |
57 | Namespace Emit.Marshal |
58 | |
59 | ''' <summary> |
60 | ''' <see cref="Array"/> index helper.(在数组的索引基础上封装了数组本身) |
61 | ''' </summary> |
62 | ''' <typeparam name="T"></typeparam> |
63 | Public Class Pointer(Of T) : Inherits DataStructures.Pointer(Of T) |
64 | |
65 | Protected buffer As T() |
66 | |
67 | ''' <summary> |
68 | ''' <see cref="Position"/> -> its current value |
69 | ''' </summary> |
70 | ''' <returns></returns> |
71 | Public Property Current As T |
72 | <MethodImpl(MethodImplOptions.AggressiveInlining)> |
73 | Get |
74 | Return Value(Scan0) ' 当前的位置是指相对于当前的位置offset为0的位置就是当前的位置 |
75 | End Get |
76 | <MethodImpl(MethodImplOptions.AggressiveInlining)> |
77 | Protected Friend Set(value As T) |
78 | Me.Value(Scan0) = value |
79 | End Set |
80 | End Property |
81 | |
82 | ''' <summary> |
83 | ''' Memory block size |
84 | ''' </summary> |
85 | ''' <returns></returns> |
86 | Public ReadOnly Property Length As Integer |
87 | <MethodImpl(MethodImplOptions.AggressiveInlining)> |
88 | Get |
89 | Return buffer.Length |
90 | End Get |
91 | End Property |
92 | |
93 | ''' <summary> |
94 | ''' 返回指定维度的一个数组,最高可用的下标。 |
95 | ''' </summary> |
96 | ''' <returns> |
97 | ''' <see cref="Integer"/>。 指定维度的下标可以包含的最大值。 如果 Array 只有一个元素, UBound ,则返回 0。 如果 Array 不包含任何元素,例如,如果它是零长度字符串, |
98 | ''' UBound 返回-1。</returns> |
99 | Public ReadOnly Property UBound As Integer |
100 | <MethodImpl(MethodImplOptions.AggressiveInlining)> |
101 | Get |
102 | Return Information.UBound(buffer) |
103 | End Get |
104 | End Property |
105 | |
106 | ''' <summary> |
107 | ''' 相对于当前的指针的位置而言的 |
108 | ''' </summary> |
109 | ''' <param name="p">相对于当前的位置的offset偏移量</param> |
110 | ''' <returns></returns> |
111 | ''' <remarks> |
112 | ''' 这个属性并不会移动当前的指针的位置 |
113 | ''' </remarks> |
114 | Default Public Property Value(p As Integer) As T |
115 | Get |
116 | p += index |
117 | |
118 | If p < 0 OrElse p >= buffer.Length Then |
119 | Return Nothing |
120 | Else |
121 | Return buffer(p) |
122 | End If |
123 | End Get |
124 | Set(value As T) |
125 | p += index |
126 | |
127 | If p < 0 OrElse p >= buffer.Length Then |
128 | Throw New MemberAccessException(p & " reference to invalid memory region!") |
129 | Else |
130 | buffer(p) = value |
131 | End If |
132 | End Set |
133 | End Property |
134 | |
135 | ''' <summary> |
136 | ''' Raw memory of this pointer |
137 | ''' </summary> |
138 | ''' <returns></returns> |
139 | Public ReadOnly Property RawBuffer As T() |
140 | <MethodImpl(MethodImplOptions.AggressiveInlining)> |
141 | Get |
142 | Return buffer |
143 | End Get |
144 | End Property |
145 | |
146 | Public ReadOnly Property NullEnd(Optional offset As Integer = 0) As Boolean |
147 | <MethodImpl(MethodImplOptions.AggressiveInlining)> |
148 | Get |
149 | Return index >= (buffer.Length - 1 - offset) |
150 | End Get |
151 | End Property |
152 | |
153 | ''' <summary> |
154 | ''' Is read to end? |
155 | ''' </summary> |
156 | ''' <returns></returns> |
157 | Public ReadOnly Property EndRead As Boolean |
158 | <MethodImpl(MethodImplOptions.AggressiveInlining)> |
159 | Get |
160 | Return index >= buffer.Length |
161 | End Get |
162 | End Property |
163 | |
164 | ''' <summary> |
165 | ''' Current read position |
166 | ''' </summary> |
167 | ''' <returns></returns> |
168 | Public ReadOnly Property Position As Integer |
169 | <MethodImpl(MethodImplOptions.AggressiveInlining)> |
170 | Get |
171 | Return index |
172 | End Get |
173 | End Property |
174 | |
175 | <MethodImpl(MethodImplOptions.AggressiveInlining)> |
176 | Sub New(ByRef array As T()) |
177 | buffer = array |
178 | End Sub |
179 | |
180 | <MethodImpl(MethodImplOptions.AggressiveInlining)> |
181 | Sub New(array As List(Of T)) |
182 | buffer = array.ToArray |
183 | End Sub |
184 | |
185 | ''' <summary> |
186 | ''' Create a collection wrapper from a <paramref name="source"/> buffer. |
187 | ''' </summary> |
188 | ''' <param name="source">The collection source buffer</param> |
189 | Sub New(source As IEnumerable(Of T)) |
190 | buffer = source.ToArray |
191 | End Sub |
192 | |
193 | Sub New() |
194 | End Sub |
195 | |
196 | ''' <summary> |
197 | ''' Pointer move to next and then returns is <see cref="EndRead"/> |
198 | ''' </summary> |
199 | ''' <returns></returns> |
200 | Public Function MoveNext() As Boolean |
201 | index += 1 |
202 | Return Not EndRead |
203 | End Function |
204 | |
205 | ''' <summary> |
206 | ''' 获取得到下一个对象而不移动当前的内部指针 |
207 | ''' </summary> |
208 | ''' <returns></returns> |
209 | ''' |
210 | <MethodImpl(MethodImplOptions.AggressiveInlining)> |
211 | Public Function PeekNext() As T |
212 | Return Me(index + 1) |
213 | End Function |
214 | |
215 | Public Overrides Function ToString() As String |
216 | Return $"*{GetType(T).Name}: ({index}) {Current}" |
217 | End Function |
218 | |
219 | '''' <summary> |
220 | '''' 前移<paramref name="offset"/>个单位,然后返回值,这个和Peek的作用一样,不会改变指针位置 |
221 | '''' </summary> |
222 | '''' <param name="p"></param> |
223 | '''' <param name="offset"></param> |
224 | '''' <returns></returns> |
225 | 'Public Overloads Shared Operator <=(p As Pointer(Of T), offset As Integer) As T |
226 | ' Return p(-offset) |
227 | 'End Operator |
228 | |
229 | '''' <summary> |
230 | '''' 后移<paramref name="offset"/>个单位,然后返回值,这个和Peek的作用一样,不会改变指针位置 |
231 | '''' </summary> |
232 | '''' <param name="p"></param> |
233 | '''' <param name="offset"></param> |
234 | '''' <returns></returns> |
235 | 'Public Overloads Shared Operator >=(p As Pointer(Of T), offset As Integer) As T |
236 | ' Return p(offset) |
237 | 'End Operator |
238 | |
239 | ''' <summary> |
240 | ''' 获取得到当前的元素 |
241 | ''' </summary> |
242 | ''' <param name="p"></param> |
243 | ''' <returns></returns> |
244 | <MethodImpl(MethodImplOptions.AggressiveInlining)> |
245 | Public Overloads Shared Narrowing Operator CType(p As Pointer(Of T)) As T |
246 | Return p.Current |
247 | End Operator |
248 | |
249 | ''' <summary> |
250 | ''' 前移<paramref name="offset"/>个单位,然后返回值,这个和Peek的作用一样,不会改变指针位置 |
251 | ''' </summary> |
252 | ''' <param name="p"></param> |
253 | ''' <param name="offset"></param> |
254 | ''' <returns></returns> |
255 | <MethodImpl(MethodImplOptions.AggressiveInlining)> |
256 | Public Overloads Shared Operator <<(p As Pointer(Of T), offset As Integer) As T |
257 | Return p(-offset) |
258 | End Operator |
259 | |
260 | ''' <summary> |
261 | ''' 后移<paramref name="offset"/>个单位,然后返回值,这个和Peek的作用一样,不会改变指针位置 |
262 | ''' </summary> |
263 | ''' <param name="p"></param> |
264 | ''' <param name="offset"></param> |
265 | ''' <returns></returns> |
266 | Public Overloads Shared Operator >>(p As Pointer(Of T), offset As Integer) As T |
267 | Return p(offset) |
268 | End Operator |
269 | |
270 | Public Overloads Shared Widening Operator CType(raw As T()) As Pointer(Of T) |
271 | Return New Pointer(Of T)(raw) |
272 | End Operator |
273 | |
274 | ''' <summary> |
275 | ''' Move steps and returns this pointer |
276 | ''' </summary> |
277 | ''' <param name="ptr"></param> |
278 | ''' <param name="d"></param> |
279 | ''' <returns></returns> |
280 | Public Overloads Shared Operator +(ptr As Pointer(Of T), d As Integer) As Pointer(Of T) |
281 | ptr.index += d |
282 | Return ptr |
283 | End Operator |
284 | |
285 | Public Overloads Shared Operator -(ptr As Pointer(Of T), d As Integer) As Pointer(Of T) |
286 | ptr.index -= d |
287 | Return ptr |
288 | End Operator |
289 | |
290 | ''' <summary> |
291 | ''' Pointer move to next and then returns the previous value |
292 | ''' </summary> |
293 | ''' <param name="ptr"></param> |
294 | ''' <returns></returns> |
295 | ''' |
296 | <MethodImpl(MethodImplOptions.AggressiveInlining)> |
297 | Public Overloads Shared Operator +(ptr As Pointer(Of T)) As SeqValue(Of T) |
298 | Dim i% = ptr.index |
299 | ptr.index += 1 |
300 | |
301 | Return New SeqValue(Of T) With { |
302 | .i = i, |
303 | .value = ptr.buffer(i) |
304 | } |
305 | End Operator |
306 | |
307 | ''' <summary> |
308 | ''' The stack trace back operator. |
309 | ''' (指针的位置往回移动一个单位,然后返回原来的位置的元素的值) |
310 | ''' </summary> |
311 | ''' <param name="ptr"></param> |
312 | ''' <returns></returns> |
313 | Public Overloads Shared Operator -(ptr As Pointer(Of T)) As SeqValue(Of T) |
314 | Dim i% = ptr.index |
315 | ptr.index -= 1 |
316 | |
317 | Return New SeqValue(Of T) With { |
318 | .i = i, |
319 | .value = ptr.buffer.ElementAtOrDefault(i, Nothing) |
320 | } |
321 | End Operator |
322 | |
323 | <MethodImpl(MethodImplOptions.AggressiveInlining)> |
324 | Public Overloads Shared Operator <=(a As Pointer(Of T), b As Pointer(Of T)) As SwapHelper(Of T) |
325 | Return New SwapHelper(Of T) With {.a = a, .b = b} |
326 | End Operator |
327 | |
328 | Public Overloads Shared Operator >=(a As Pointer(Of T), b As Pointer(Of T)) As SwapHelper(Of T) |
329 | Throw New NotSupportedException |
330 | End Operator |
331 | |
332 | <MethodImpl(MethodImplOptions.AggressiveInlining)> |
333 | Public Overloads Shared Operator <=(a As Pointer(Of T), b As Integer) As SwapHelper(Of T) |
334 | Return New SwapHelper(Of T) With {.a = a, .i = b} |
335 | End Operator |
336 | |
337 | Public Overloads Shared Operator >=(a As Pointer(Of T), b As Integer) As SwapHelper(Of T) |
338 | Throw New NotSupportedException |
339 | End Operator |
340 | |
341 | <MethodImpl(MethodImplOptions.AggressiveInlining)> |
342 | Public Shared Function stackalloc(len As Integer) As Pointer(Of T) |
343 | Return New Pointer(Of T)(New T(len - 1) {}) |
344 | End Function |
345 | |
346 | <MethodImpl(MethodImplOptions.AggressiveInlining)> |
347 | Public Shared Operator =(p As Pointer(Of T), count%) As Boolean |
348 | Return p.Length = count |
349 | End Operator |
350 | |
351 | <MethodImpl(MethodImplOptions.AggressiveInlining)> |
352 | Public Shared Operator <>(p As Pointer(Of T), count%) As Boolean |
353 | Return Not p = count |
354 | End Operator |
355 | End Class |
356 | |
357 | Public Structure SwapHelper(Of T) |
358 | |
359 | Public a As Pointer(Of T) |
360 | Public b As Pointer(Of T) |
361 | Public i As Integer |
362 | |
363 | Public Sub Swap() |
364 | Dim tmp As T = a.Current |
365 | |
366 | If b Is Nothing Then |
367 | a.Current = a(i) |
368 | a(i) = tmp |
369 | Else |
370 | a.Current = b.Current |
371 | b.Current = tmp |
372 | End If |
373 | End Sub |
374 | End Structure |
375 | End Namespace |