1 #Region "Microsoft.VisualBasic::a85c68ec7dde72b8386e325bb6946b13, Microsoft.VisualBasic.Core\ComponentModel\DataStructures\HashDictionary.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 HashDictionary
35     
36     '         Properties: __keys, __values, (+2 Overloads) Count, IsReadOnly, Keys
37     '                     Values
38     
39     '         Constructor: (+2 OverloadsSub New
40     
41     '         Function: Contains, (+2 Overloads) ContainsKey, GetEnumerator, GetEnumerator1, (+2 Overloads) Remove
42     '                   (+2 OverloadsTryGetValue
43     
44     '         Sub: (+2 Overloads) Add, Clear, CopyTo, (+2 Overloads) Dispose
45     
46     
47     ' /********************************************************************************/
48
49 #End Region
50
51 Imports System.Collections.ObjectModel
52 Imports Microsoft.VisualBasic.Language
53
54 Namespace ComponentModel.Collection.Generic
55
56     ''' <summary>
57     ''' The key of the dictionary is string value and the keys is not sensitive to the character case.
58     ''' (字典的键名为字符串,大小写不敏感,行为和哈希表类型)
59     ''' </summary>
60     ''' <typeparam name="T"></typeparam>
61     ''' <remarks></remarks>
62     Public Class HashDictionary(Of T) : Implements IDisposable
63         Implements IDictionary(Of String, T)
64         Implements IReadOnlyDictionary(Of String, T)
65
66         Protected ReadOnly _hashBuffer As Dictionary(Of String, T)
67         Protected ReadOnly _keysHash As Dictionary(Of StringString)
68
69         Sub New(data As IDictionary(Of String, T))
70             Call Me.New
71
72             If Not data Is Nothing Then
73                 For Each ItemObject In data
74                     Call Add(ItemObject)
75                 Next
76             End If
77         End Sub
78
79         ''' <summary>
80         ''' Initializes a new instance of the System.Collections.Generic.Dictionary`2 class
81         ''' that is empty, has the default initial capacity, and uses the default equality
82         ''' comparer for the key type.
83         ''' </summary>
84         Sub New()
85             _hashBuffer = New Dictionary(Of String, T)
86             _keysHash = New Dictionary(Of StringString)
87         End Sub
88
89 #Region "Implements System.IDisposable, Generic.IDictionary(Of String, T)"
90
91         Public Sub Add(item As KeyValuePair(Of String, T)) Implements ICollection(Of KeyValuePair(Of String, T)).Add
92             Dim Key As String = item.Key
93             Me(Key) = item.Value
94         End Sub
95
96         Public Sub Clear() Implements ICollection(Of KeyValuePair(Of String, T)).Clear
97             Call _keysHash.Clear()
98             Call _hashBuffer.Clear()
99         End Sub
100
101         Public Function Contains(item As KeyValuePair(Of String, T)) As Boolean Implements ICollection(Of KeyValuePair(Of String, T)).Contains
102             Dim value = Me(item.Key)
103             If item.Value Is Nothing AndAlso value Is Nothing Then
104                 Return True
105             ElseIf value Is Nothing Then
106                 Return False
107             ElseIf Object.Equals(item.Value, value) Then
108                 Return True
109             End If
110
111             Return False
112         End Function
113
114 #If NET_40 = 1 Then
115         Public ReadOnly Property Count As Integer Implements ICollection(Of KeyValuePair(Of String, T)).Count
116 #Else
117            Public ReadOnly Property Count As Integer Implements ICollection(Of KeyValuePair(Of String, T)).Count, IReadOnlyCollection(Of KeyValuePair(Of String, T)).Count
118 #End If
119             Get
120                 Return _keysHash.Count
121             End Get
122         End Property
123
124         Public ReadOnly Property IsReadOnly As Boolean Implements ICollection(Of KeyValuePair(Of String, T)).IsReadOnly
125             Get
126                 Return False
127             End Get
128         End Property
129
130         Public Function Remove(item As KeyValuePair(Of String, T)) As Boolean Implements ICollection(Of KeyValuePair(Of String, T)).Remove
131             Dim Key As String = item.Key.ToLower
132             Call _hashBuffer.Remove(Key)
133             Return _keysHash.Remove(Key)
134         End Function
135
136         Public Sub Add(key As String, value As T) Implements IDictionary(Of String, T).Add
137             Call Add(New KeyValuePair(Of String, T)(key, value))
138         End Sub
139
140         ''' <summary>
141         ''' 
142         ''' </summary>
143         ''' <param name="key">大小写不敏感</param>
144         ''' <returns></returns>
145         ''' <remarks></remarks>
146         ''' 
147 #If NET_40 = 1 Then
148         Public Function ContainsKey(key As StringAs Boolean Implements IDictionary(Of String, T).ContainsKey
149 #Else
150         Public Function ContainsKey(key As StringAs Boolean Implements IDictionary(Of String, T).ContainsKey, IReadOnlyDictionary(Of String, T).ContainsKey
151 #End If
152             Return _keysHash.ContainsKey(key.ToLower)
153         End Function
154
155         ''' <summary>
156         ''' 添加<see cref="Add"></see>和替换操作主要在这里进行
157         ''' </summary>
158         ''' <param name="key">大小写不敏感</param>
159         ''' <value></value>
160         ''' <returns></returns>
161         ''' <remarks></remarks>
162         ''' 
163 #If NET_40 = 1 Then
164         Default Public Property Item(key As StringAs T Implements IDictionary(Of String, T).Item
165 #Else
166            Default Public Property Item(key As StringAs T Implements IDictionary(Of String, T).Item, IReadOnlyDictionary(Of String, T).Item
167 #End If
168
169             Get
170                 key = key.ToLower
171                 If _keysHash.ContainsKey(key) Then
172                     Return _hashBuffer(key)
173                 Else
174                     Return Nothing
175                 End If
176             End Get
177             Set(value As T)
178                 Dim query As String = key.ToLower
179
180                 If _keysHash.ContainsKey(query) Then
181                     _hashBuffer(query) = value
182                 Else
183                     Call _hashBuffer.Add(query, value)
184                     Call _keysHash.Add(query, key)
185                 End If
186             End Set
187         End Property
188
189         Public Sub CopyTo(array() As KeyValuePair(Of String, T), arrayIndex As IntegerImplements ICollection(Of KeyValuePair(Of String, T)).CopyTo
190             Dim LQuery = (From item In _keysHash Select New KeyValuePair(Of String, T)(item.Value, _hashBuffer(item.Key))).ToArray
191             Call System.Array.ConstrainedCopy(LQuery, 0, array, arrayIndex, array.Length - arrayIndex)
192         End Sub
193
194         Public ReadOnly Property Keys As ICollection(Of StringImplements IDictionary(Of String, T).Keys
195             Get
196                 Return _keysHash.Values
197             End Get
198         End Property
199
200 #If NET_40 = 0 Then
201         Private ReadOnly Property __keys As IEnumerable(Of StringImplements IReadOnlyDictionary(Of String, T).Keys
202             Get
203                 Return Keys
204             End Get
205         End Property
206 #End If
207
208         Public Function Remove(key As StringAs Boolean Implements IDictionary(Of String, T).Remove
209             key = key.ToLower
210             If Me._keysHash.ContainsKey(key) Then
211                 Call _keysHash.Remove(key)
212                 Call _hashBuffer.Remove(key)
213
214                 Return True
215             Else
216                 Return False
217             End If
218         End Function
219
220 #If NET_40 = 1 Then
221         Public Function TryGetValue(key As StringByRef value As T) As Boolean Implements IDictionary(Of String, T).TryGetValue
222 #Else
223         Public Function TryGetValue(key As StringByRef value As T) As Boolean Implements IDictionary(Of String, T).TryGetValue, IReadOnlyDictionary(Of String, T).TryGetValue
224 #End If
225
226             value = Me(key)
227             Return _keysHash.ContainsKey(key.ToLower)
228         End Function
229
230         Public ReadOnly Property Values As ICollection(Of T) Implements IDictionary(Of String, T).Values
231             Get
232                 Return _hashBuffer.Values
233             End Get
234         End Property
235
236 #If NET_40 = 0 Then
237         Private ReadOnly Property __values As IEnumerable(Of T) Implements IReadOnlyDictionary(Of String, T).Values
238             Get
239                 Return Values
240             End Get
241         End Property
242 #End If
243         Public Iterator Function GetEnumerator1() As IEnumerator(Of KeyValuePair(Of String, T)) Implements IEnumerable(Of KeyValuePair(Of String, T)).GetEnumerator
244             For Each ItemObject In Me._hashBuffer
245                 Yield New KeyValuePair(Of String, T)(Me._keysHash(ItemObject.Key), ItemObject.Value)
246             Next
247         End Function
248
249         Public Iterator Function GetEnumerator() As IEnumerator Implements IEnumerable.GetEnumerator
250             Yield GetEnumerator1()
251         End Function
252
253 #Region "IDisposable Support"
254         Private disposedValue As Boolean To detect redundant calls
255
256         ' IDisposable
257         Protected Overridable Sub Dispose(disposing As Boolean)
258             If Not Me.disposedValue Then
259                 If disposing Then
260                     ' TODO: dispose managed state (managed objects).
261                     Call Me.Clear()
262                 End If
263
264                 ' TODO: free unmanaged resources (unmanaged objects) and override Finalize() below.
265                 ' TODO: set large fields to null.
266             End If
267             Me.disposedValue = True
268         End Sub
269
270         ' TODO: override Finalize() only if Dispose(      disposing As Boolean) above has code to free unmanaged resources.
271         'Protected Overrides Sub Finalize()
272         '    ' Do not change this code.  Put cleanup code in Dispose(      disposing As Boolean) above.
273         '    Dispose(False)
274         '    MyBase.Finalize()
275         'End Sub
276
277         ' This code added by Visual Basic to correctly implement the disposable pattern.
278         Public Sub Dispose() Implements IDisposable.Dispose
279             Do not change this code.  Put cleanup code in Dispose(disposing As Boolean) above.
280             Dispose(True)
281             GC.SuppressFinalize(Me)
282         End Sub
283 #End Region
284 #End Region
285     End Class
286 End Namespace