1 #Region "Microsoft.VisualBasic::ec54297c3c4eae55fc3d57041d0e5861, 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 OverloadsSub New
40     '         Function: MoveNext, ToString
41     '         Operators: (+2 Overloads) -, (+2 Overloads) +, <<, (+2 Overloads) <=, (+2 Overloads) >=
42     '                    >>
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         Default Public Property Value(p%) As T
112             Get
113                 p += __index
114
115                 If p < 0 OrElse p >= buffer.Length Then
116                     Return Nothing
117                 Else
118                     Return buffer(p)
119                 End If
120             End Get
121             Set(value As T)
122                 p += __index
123
124                 If p < 0 OrElse p >= buffer.Length Then
125                     Throw New MemberAccessException(p & " reference to invalid memory region!")
126                 Else
127                     buffer(p) = value
128                 End If
129             End Set
130         End Property
131
132         ''' <summary>
133         ''' Raw memory of this pointer
134         ''' </summary>
135         ''' <returns></returns>
136         Public ReadOnly Property RawBuffer As T()
137             <MethodImpl(MethodImplOptions.AggressiveInlining)>
138             Get
139                 Return buffer
140             End Get
141         End Property
142
143         Public ReadOnly Property NullEnd(Optional offset As Integer = 0) As Boolean
144             <MethodImpl(MethodImplOptions.AggressiveInlining)>
145             Get
146                 Return __index >= (buffer.Length - 1 - offset)
147             End Get
148         End Property
149
150         ''' <summary>
151         ''' Is read to end?
152         ''' </summary>
153         ''' <returns></returns>
154         Public ReadOnly Property EndRead As Boolean
155             <MethodImpl(MethodImplOptions.AggressiveInlining)>
156             Get
157                 Return __index >= buffer.Length
158             End Get
159         End Property
160
161         ''' <summary>
162         ''' Current read position
163         ''' </summary>
164         ''' <returns></returns>
165         Public ReadOnly Property Position As Integer
166             <MethodImpl(MethodImplOptions.AggressiveInlining)>
167             Get
168                 Return __index
169             End Get
170         End Property
171
172         <MethodImpl(MethodImplOptions.AggressiveInlining)>
173         Sub New(ByRef array As T())
174             buffer = array
175         End Sub
176
177         <MethodImpl(MethodImplOptions.AggressiveInlining)>
178         Sub New(array As List(Of T))
179             buffer = array.ToArray
180         End Sub
181
182         ''' <summary>
183         ''' Create a collection wrapper from a <paramref name="source"/> buffer.
184         ''' </summary>
185         ''' <param name="source">The collection source buffer</param>
186         Sub New(source As IEnumerable(Of T))
187             buffer = source.ToArray
188         End Sub
189
190         Sub New()
191         End Sub
192
193         Public Overrides Function ToString() As String
194             Return $"* {GetType(T).Name} + {__index} --> {Current}  // {Scan0.ToString}"
195         End Function
196
197         '''' <summary>
198         '''' 前移<paramref name="offset"/>个单位,然后返回值,这个和Peek的作用一样,不会改变指针位置
199         '''' </summary>
200         '''' <param name="p"></param>
201         '''' <param name="offset"></param>
202         '''' <returns></returns>
203         'Public Overloads Shared Operator <=(p As Pointer(Of T), offset As IntegerAs T
204         '    Return p(-offset)
205         'End Operator
206
207         '''' <summary>
208         '''' 后移<paramref name="offset"/>个单位,然后返回值,这个和Peek的作用一样,不会改变指针位置
209         '''' </summary>
210         '''' <param name="p"></param>
211         '''' <param name="offset"></param>
212         '''' <returns></returns>
213         'Public Overloads Shared Operator >=(p As Pointer(Of T), offset As IntegerAs T
214         '    Return p(offset)
215         'End Operator
216
217         <MethodImpl(MethodImplOptions.AggressiveInlining)>
218         Public Overloads Shared Narrowing Operator CType(p As Pointer(Of T)) As T
219             Return p.Current
220         End Operator
221
222         ''' <summary>
223         ''' 前移<paramref name="offset"/>个单位,然后返回值,这个和Peek的作用一样,不会改变指针位置
224         ''' </summary>
225         ''' <param name="p"></param>
226         ''' <param name="offset"></param>
227         ''' <returns></returns>
228         <MethodImpl(MethodImplOptions.AggressiveInlining)>
229         Public Overloads Shared Operator <<(p As Pointer(Of T), offset As IntegerAs T
230             Return p(-offset)
231         End Operator
232
233         ''' <summary>
234         ''' 后移<paramref name="offset"/>个单位,然后返回值,这个和Peek的作用一样,不会改变指针位置
235         ''' </summary>
236         ''' <param name="p"></param>
237         ''' <param name="offset"></param>
238         ''' <returns></returns>
239         Public Overloads Shared Operator >>(p As Pointer(Of T), offset As IntegerAs T
240             Return p(offset)
241         End Operator
242
243         Public Overloads Shared Widening Operator CType(raw As T()) As Pointer(Of T)
244             Return New Pointer(Of T)(raw)
245         End Operator
246
247         ''' <summary>
248         ''' Move steps and returns this pointer
249         ''' </summary>
250         ''' <param name="ptr"></param>
251         ''' <param name="d"></param>
252         ''' <returns></returns>
253         Public Overloads Shared Operator +(ptr As Pointer(Of T), d As IntegerAs Pointer(Of T)
254             ptr.__index += d
255             Return ptr
256         End Operator
257
258         Public Overloads Shared Operator -(ptr As Pointer(Of T), d As IntegerAs Pointer(Of T)
259             ptr.__index -= d
260             Return ptr
261         End Operator
262
263         ''' <summary>
264         ''' Pointer move to next and then returns is <see cref="EndRead"/>
265         ''' </summary>
266         ''' <returns></returns>
267         Public Function MoveNext() As Boolean
268             __index += 1
269             Return Not EndRead
270         End Function
271
272         ''' <summary>
273         ''' Pointer move to next and then returns the previous value
274         ''' </summary>
275         ''' <param name="ptr"></param>
276         ''' <returns></returns>
277         ''' 
278         <MethodImpl(MethodImplOptions.AggressiveInlining)>
279         Public Overloads Shared Operator +(ptr As Pointer(Of T)) As SeqValue(Of T)
280             Dim i% = ptr.__index
281             ptr.__index += 1
282
283             Return New SeqValue(Of T) With {
284                 .i = i,
285                 .value = ptr.buffer(i)
286             }
287         End Operator
288
289         ''' <summary>
290         ''' The stack trace back operator.
291         ''' (指针的位置往回移动一个单位,然后返回原来的位置的元素的值)
292         ''' </summary>
293         ''' <param name="ptr"></param>
294         ''' <returns></returns>
295         Public Overloads Shared Operator -(ptr As Pointer(Of T)) As SeqValue(Of T)
296             Dim i% = ptr.__index
297             ptr.__index -= 1
298
299             Return New SeqValue(Of T) With {
300                 .i = i,
301                 .value = ptr.buffer.ElementAtOrDefault(i, Nothing)
302             }
303         End Operator
304
305         <MethodImpl(MethodImplOptions.AggressiveInlining)>
306         Public Overloads Shared Operator <=(a As Pointer(Of T), b As Pointer(Of T)) As SwapHelper(Of T)
307             Return New SwapHelper(Of T) With {.a = a, .b = b}
308         End Operator
309
310         Public Overloads Shared Operator >=(a As Pointer(Of T), b As Pointer(Of T)) As SwapHelper(Of T)
311             Throw New NotSupportedException
312         End Operator
313
314         <MethodImpl(MethodImplOptions.AggressiveInlining)>
315         Public Overloads Shared Operator <=(a As Pointer(Of T), b As IntegerAs SwapHelper(Of T)
316             Return New SwapHelper(Of T) With {.a = a, .i = b}
317         End Operator
318
319         Public Overloads Shared Operator >=(a As Pointer(Of T), b As IntegerAs SwapHelper(Of T)
320             Throw New NotSupportedException
321         End Operator
322     End Class
323
324     Public Structure SwapHelper(Of T)
325
326         Public a As Pointer(Of T)
327         Public b As Pointer(Of T)
328         Public i As Integer
329
330         Public Sub Swap()
331             Dim tmp As T = a.Current
332
333             If b Is Nothing Then
334                 a.Current = a(i)
335                 a(i) = tmp
336             Else
337                 a.Current = b.Current
338                 b.Current = tmp
339             End If
340         End Sub
341     End Structure
342 End Namespace