1 #Region "Microsoft.VisualBasic::f663f882ee374e66c69193b6809e73ac, Microsoft.VisualBasic.Core\Text\Splitter.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 Splitter
35     
36     '         Constructor: (+1 OverloadsSub New
37     '         Function: __split, isValidDelimiterBinary, isValidDelimiterText, Split
38     
39     
40     ' /********************************************************************************/
41
42 #End Region
43
44 ' http://www.codeproject.com/Articles/7464/Very-Fast-Splitter-with-support-for-Multi-Characte
45
46 Namespace Text
47
48     ''' <summary>
49     ''' Split strings with support to multi-character, multi-lines Delimiter
50     ''' </summary>
51     Public NotInheritable Class Splitter
52
53         ''' <summary>
54         ''' Holds the string to split
55         ''' </summary>
56         Dim m_Expression As Char()
57         ''' <summary>
58         ''' Delimiter to split the expression with
59         ''' </summary>
60         Dim m_Delimiter As Char()
61
62         ''' <summary>
63         ''' Constrctor for The Splitter
64         ''' </summary>
65         Protected Sub New()
66         End Sub
67
68         Private Function isValidDelimiterBinary(StringIndex As Integer, DelimiterIndex As IntegerAs Boolean
69             If DelimiterIndex = m_Delimiter.Length Then
70                 Return True
71             End If
72             If StringIndex = m_Expression.Length Then
73                 Return False
74             End If
75             'If the current character of the expression matches the current character of the Delimiter , then go to next character
76             If m_Expression(StringIndex) = m_Delimiter(DelimiterIndex) Then
77                 Return isValidDelimiterBinary(StringIndex + 1, DelimiterIndex + 1)
78             Else
79                 Return False
80             End If
81         End Function
82
83         Private Function isValidDelimiterText(StringIndex As Integer, DelimiterIndex As IntegerAs Boolean
84             If DelimiterIndex = m_Delimiter.Length Then
85                 Return True
86             End If
87             If StringIndex = m_Expression.Length Then
88                 Return False
89             End If
90             'If the current character of the expression matches the current character of the Delimiter , then go to next character
91             If [Char].ToLower(m_Expression(StringIndex)) = [Char].ToLower(m_Delimiter(DelimiterIndex)) Then
92                 Return isValidDelimiterText(StringIndex + 1, DelimiterIndex + 1)
93             Else
94                 Return False
95             End If
96         End Function
97
98         Public Shared Function Split(s As String, delimiter As String, isSingle As Boolean,
99                                      Optional count As Integer = Integer.MaxValue,
100                                      Optional compare As CompareMethod = CompareMethod.Binary) As String()
101             Return New Splitter().__split(s, delimiter, isSingle, count, compare)
102         End Function
103
104         Private Function __split(Expression As String, Delimiter As StringSingleSeparator As Boolean, Count As Integer, Compare As CompareMethod) As String()
105             'Update Private Members
106             m_Expression = Expression.ToCharArray
107             m_Delimiter = Delimiter.ToCharArray
108
109             'Array to hold Splitted Tokens
110             Dim Tokens As New List(Of String)
111             'If not using single separator, then use the regular split function
112             If Not SingleSeparator Then
113                 If Count >= 0 Then
114                     Return Expression.Split(Delimiter.ToCharArray(), Count)
115                 Else
116                     Return Expression.Split(Delimiter.ToCharArray())
117                 End If
118             End If
119
120             'Check if count = 0 then return an empty array
121             If Count = 0 Then
122                 Return New String(-1) {}
123                 'Check if Count = 1 then return the whole expression
124             ElseIf Count = 1 Then
125                 Return New String() {Expression}
126             Else
127                 Count -= 1
128             End If
129
130             Dim i As Integer
131             Indexer to loop over the string with
132             Dim iStart As Integer = 0
133             'The Start index of the current token in the expression
134             If Compare = CompareMethod.Binary Then
135
136                 For i = 0 To Expression.Length - 1
137                     If isValidDelimiterBinary(i, 0) Then
138                         'Assign New Token
139                         Tokens.Add(Expression.Substring(iStart, i - iStart))
140                         'Update Index
141                         i += Delimiter.Length - 1
142                         'Update Current Token Start index
143                         iStart = i + 1
144                         'If we reached the tokens limit , then exit For
145                         If Tokens.Count = Count AndAlso Count >= 0 Then
146                             Exit For
147                         End If
148                     End If
149                 Next
150             Else
151                 For i = 0 To Expression.Length - 1
152                     If isValidDelimiterText(i, 0) Then
153                         'Assign New Token
154                         Tokens.Add(Expression.Substring(iStart, i - iStart))
155                         'Update Index
156                         i += Delimiter.Length - 1
157                         'Update Current Token Start index
158                         iStart = i + 1
159                         'If we reached the tokens limit , then exit For
160                         If Tokens.Count = Count AndAlso Count >= 0 Then
161                             Exit For
162                         End If
163                     End If
164                 Next
165             End If
166             Dim LastToken As String = ""
167             'If there is still data & have not been added
168             If iStart < Expression.Length Then
169                 LastToken = Expression.Substring(iStart, Expression.Length - iStart)
170                 If LastToken = Delimiter Then
171                     Tokens.Add(Nothing)
172                 Else
173                     Tokens.Add(LastToken)
174                 End If
175                 'If there is no elements in the tokens array , then pass the whole string as the one element
176             ElseIf Tokens.Count = 0 Then
177                 Tokens.Add(Expression)
178             End If
179
180             'Return Splitted Tokens
181             Return Tokens.ToArray
182         End Function
183     End Class
184 End Namespace