1 #Region "Microsoft.VisualBasic::dae4b5fab322d08be6da737f009262e8, Microsoft.VisualBasic.Core\Extensions\Collection\Linq\Iterator.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 '     Module IteratorExtensions
35
36 '         Function: [Next], (+2 OverloadsIndices, Ordinals, Previous, (+2 Overloads) SeqIterator
37 '                   (+2 Overloads) SeqTuple, ValueArray
38
39 '     Structure SeqValue
40
41 '         Properties: i, value
42
43 '         Constructor: (+1 OverloadsSub New
44
45 '         Function: (+2 Overloads) CompareTo, ToString
46
47 '         SubAssign
48
49 '         Operators: -, (+2 Overloads) +, <>, =, (+2 OverloadsMod
50
51 '     Interface IIterator
52
53 '         FunctionGetEnumerator, IGetEnumerator
54
55
56 ' /********************************************************************************/
57
58 #End Region
59
60 Imports System.Runtime.CompilerServices
61 Imports Microsoft.VisualBasic.ComponentModel
62 Imports Microsoft.VisualBasic.Emit.Marshal
63 Imports Microsoft.VisualBasic.Language
64 Imports Microsoft.VisualBasic.Language.Default
65 Imports Microsoft.VisualBasic.Serialization.JSON
66
67 Namespace Linq
68
69     Public Module IteratorExtensions
70
71         <Extension>
72         Public Iterator Function SeqIterator(source As IEnumerable, Optional offset% = 0) As IEnumerable(Of SeqValue(Of Object))
73             Dim i As Integer = offset
74
75             For Each o As Object In source
76                 Yield New SeqValue(Of Object)(i, o)
77                 i += 1
78             Next
79         End Function
80
81         ''' <summary>
82         ''' Iterates all of the objects in the source sequence with collection index position.
83         ''' </summary>
84         ''' <typeparam name="T"></typeparam>
85         ''' <param name="source">the source sequence</param>
86         ''' <param name="offset"></param>
87         ''' <returns></returns>
88         <Extension>
89         Public Iterator Function SeqIterator(Of T)(source As IEnumerable(Of T), Optional offset% = 0) As IEnumerable(Of SeqValue(Of T))
90             If Not source Is Nothing Then
91                 Dim idx% = offset
92
93                 For Each x As T In source
94                     Yield New SeqValue(Of T)(idx, x)
95                     idx += 1
96                 Next
97             End If
98         End Function
99
100         <MethodImpl(MethodImplOptions.AggressiveInlining)>
101         <Extension>
102         Public Function SeqTuple(Of T1, T2)(tuple As (a As IEnumerable(Of T1), b As IEnumerable(Of T2)), Optional offset% = 0) As IEnumerable(Of SeqValue(Of (a As T1, b As T2)))
103             Return (tuple.a.ToArray, tuple.b.ToArray).SeqTuple(offset)
104         End Function
105
106         <Extension>
107         Public Iterator Function SeqTuple(Of T1, T2)(tuple As (x As T1(), y As T2()), Optional offset% = 0) As IEnumerable(Of SeqValue(Of (a As T1, b As T2)))
108             Dim value As (T1, T2)
109             Dim length% = Math.Max(tuple.x.Length, tuple.y.Length)
110
111             For i As Integer = 0 To length - 1
112                 value = (
113                     tuple.x.ElementAtOrDefault(i),
114                     tuple.y.ElementAtOrDefault(i)
115                 )
116                 Yield New SeqValue(Of (T1, T2))(i + offset, value)
117             Next
118         End Function
119
120         ''' <summary>
121         ''' Move the enumerator pointer to next and get next value, if the pointer is reach the end, then will returns nothing
122         ''' </summary>
123         ''' <typeparam name="T"></typeparam>
124         ''' <param name="source"></param>
125         ''' <returns></returns>
126         <Extension>
127         Public Function [Next](Of T)(source As IEnumerator(Of T)) As T
128             If source.MoveNext() Then
129                 Return source.Current
130             Else
131                 Return Nothing
132             End If
133         End Function
134
135         <Extension>
136         Public Function Previous(Of T)(source As IEnumerator(Of T)) As T
137             Throw New NotImplementedException
138         End Function
139
140         ''' <summary>
141         ''' Creates an array from property <see cref="Value(Of T).IValueOf.value"/>
142         ''' </summary>
143         ''' <typeparam name="T"></typeparam>
144         ''' <param name="source"></param>
145         ''' <returns></returns>
146         ''' 
147         <MethodImpl(MethodImplOptions.AggressiveInlining)>
148         <Extension>
149         Public Function ValueArray(Of T)(source As IEnumerable(Of Value(Of T).IValueOf)) As T()
150             Return source.Select(Function(o) o.Value).ToArray
151         End Function
152
153         <MethodImpl(MethodImplOptions.AggressiveInlining)>
154         <Extension>
155         Public Function Indices(Of T)(source As IEnumerable(Of SeqValue(Of T))) As Integer()
156             Return source.Ordinals.ToArray
157         End Function
158
159         <MethodImpl(MethodImplOptions.AggressiveInlining)>
160         <Extension>
161         Public Function Ordinals(Of T)(source As IEnumerable(Of SeqValue(Of T))) As IEnumerable(Of Integer)
162             Return source.Select(Function(o) o.i)
163         End Function
164
165         <MethodImpl(MethodImplOptions.AggressiveInlining)>
166         <Extension>
167         Public Function Indices(Of T)(source As IEnumerable(Of T), assert As Func(Of T, Boolean)) As Integer()
168             Return source _
169                 .SeqIterator _
170                 .Where(Function(x) True = assert(x.value)) _
171                 .Indices
172         End Function
173     End Module
174
175     ''' <summary>
176     ''' Value <typeparamref name="T"/> with sequence index <see cref="i"/>.
177     ''' </summary>
178     ''' <typeparam name="T"></typeparam>
179     Public Structure SeqValue(Of T) : Implements IAddressOf
180         Implements IComparable(Of Integer)
181         Implements IComparable
182         Implements Value(Of T).IValueOf
183         Implements IsEmpty
184
185         ''' <summary>
186         ''' The position of this object value in the original sequence.
187         ''' </summary>
188         ''' <returns></returns>
189         Public Property i As Integer Implements IAddressOf.Address
190         ''' <summary>
191         ''' The Object data
192         ''' </summary>
193         ''' <returns></returns>
194         Public Property value As T Implements Value(Of T).IValueOf.Value
195
196         Public ReadOnly Property IsEmpty As Boolean Implements IsEmpty.IsEmpty
197             Get
198                 Return i = 0 AndAlso value Is Nothing
199             End Get
200         End Property
201
202         Sub New(i%, x As T)
203             Me.i = i
204             value = x
205         End Sub
206
207         <MethodImpl(MethodImplOptions.AggressiveInlining)>
208         Public Overrides Function ToString() As String
209             Return Me.value.GetJson(False)
210         End Function
211
212         <MethodImpl(MethodImplOptions.AggressiveInlining)>
213         Public Shared Narrowing Operator CType(x As SeqValue(Of T)) As T
214             Return x.value
215         End Operator
216
217         <MethodImpl(MethodImplOptions.AggressiveInlining)>
218         Public Shared Narrowing Operator CType(x As SeqValue(Of T)) As Integer
219             Return x.i
220         End Operator
221
222         Public Shared Operator +(list As System.Collections.Generic.List(Of T), x As SeqValue(Of T)) As System.Collections.Generic.List(Of T)
223             Call list.Add(x.value)
224             Return list
225         End Operator
226
227         <MethodImpl(MethodImplOptions.AggressiveInlining)>
228         Public Shared Operator Mod(i As SeqValue(Of T), n%) As Integer
229             Return i.i Mod n
230         End Operator
231
232         Public Shared Operator <>(v As SeqValue(Of T), i%) As Boolean
233             Return v.i <> i
234         End Operator
235
236         Public Shared Operator =(v As SeqValue(Of T), i%) As Boolean
237             Return v.i = i
238         End Operator
239
240         ''' <summary>
241         ''' Get value from <see cref="value"/> property.
242         ''' </summary>
243         ''' <param name="x"></param>
244         ''' <returns></returns>
245         ''' <remarks>
246         ''' Syntax helper for the <see cref="Pointer(Of T)"/>:
247         ''' 
248         ''' ```vbnet
249         ''' Dim p As Pointer(Of T) = T()
250         ''' Dim x As T = ++p
251         ''' ```
252         ''' </remarks>
253         ''' 
254         <MethodImpl(MethodImplOptions.AggressiveInlining)>
255         Public Shared Operator +(x As SeqValue(Of T)) As T
256             Return x.value
257         End Operator
258
259         ''' <summary>
260         ''' Get value from <see cref="value"/> property.
261         ''' </summary>
262         ''' <param name="x"></param>
263         ''' <returns></returns>
264         ''' <remarks>
265         ''' Syntax helper for the <see cref="Pointer(Of T)"/>:
266         ''' 
267         ''' ```vbnet
268         ''' Dim p As Pointer(Of T) = T()
269         ''' Dim x As T = --p
270         ''' ```
271         ''' </remarks>
272         <MethodImpl(MethodImplOptions.AggressiveInlining)>
273         Public Shared Operator -(x As SeqValue(Of T)) As T
274             Return x.value
275         End Operator
276
277         ''' <summary>
278         ''' Compares the index value <see cref="i"/>.
279         ''' </summary>
280         ''' <param name="other"></param>
281         ''' <returns></returns>
282         ''' 
283         <MethodImpl(MethodImplOptions.AggressiveInlining)>
284         Public Function CompareTo(other As IntegerAs Integer Implements IComparable(Of Integer).CompareTo
285             Return i.CompareTo(other)
286         End Function
287
288         Public Function CompareTo(obj As ObjectAs Integer Implements IComparable.CompareTo
289             If obj Is Nothing Then
290                 Return 1
291             End If
292
293             If Not obj.GetType Is Me.GetType Then
294                 Return 10
295             End If
296
297             Return i.CompareTo(DirectCast(obj, SeqValue(Of T)).i)
298         End Function
299
300         Private Sub Assign(address As IntegerImplements IAddress(Of Integer).Assign
301             i = address
302         End Sub
303     End Structure
304
305     ''' <summary>
306     ''' Exposes the enumerator, which supports a simple iteration over a collection of
307     ''' a specified type.To browse the .NET Framework source code for this type, see
308     ''' the Reference Source.
309     ''' (使用这个的原因是系统自带的<see cref="IEnumerable(Of T)"/>在Xml序列化之中的支持不太好)
310     ''' </summary>
311     ''' <typeparam name="T">The type of objects to enumerate.This type parameter is covariant. That is, you
312     ''' can use either the type you specified or any type that is more derived. For more
313     ''' information about covariance and contravariance, see Covariance and Contravariance
314     ''' in Generics.</typeparam>
315     Public Interface IIterator(Of T)
316
317         ''' <summary>
318         ''' Returns an enumerator that iterates through the collection.
319         ''' </summary>
320         ''' <returns>An enumerator that can be used to iterate through the collection.</returns>
321         Function GetEnumerator() As IEnumerator(Of T)
322
323         ''' <summary>
324         ''' Returns an enumerator that iterates through a collection.
325         ''' </summary>
326         ''' <returns>An System.Collections.IEnumerator object that can be used to iterate through
327         ''' the collection.</returns>
328         Function IGetEnumerator() As IEnumerator
329     End Interface
330 End Namespace