1 | #Region "Microsoft.VisualBasic::2e46ec2d70d12084ebd04781a6155f13, Microsoft.VisualBasic.Core\Language\Value\Uid.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 Uid |
35 | ' |
36 | ' Properties: Key |
37 | ' |
38 | ' Constructor: (+4 Overloads) Sub New |
39 | ' |
40 | ' Function: __plus, Plus, ToString |
41 | ' |
42 | ' Sub: __error |
43 | ' |
44 | ' Operators: (+2 Overloads) + |
45 | ' |
46 | ' |
47 | ' /********************************************************************************/ |
48 | |
49 | #End Region |
50 | |
51 | Imports System.Runtime.CompilerServices |
52 | Imports Microsoft.VisualBasic.ComponentModel.Collection.Generic |
53 | Imports Microsoft.VisualBasic.ComponentModel.DataSourceModel.Repository |
54 | Imports Microsoft.VisualBasic.Linq |
55 | Imports Microsoft.VisualBasic.Serialization.JSON |
56 | |
57 | Namespace Language |
58 | |
59 | ''' <summary> |
60 | ''' The unique id generator. |
61 | ''' </summary> |
62 | Public Class Uid : Implements INamedValue |
63 | |
64 | ''' <summary> |
65 | ''' index collection of array <see cref="__chars"/>.(<see cref="__chars"/>数组的下标集合) |
66 | ''' </summary> |
67 | Dim chars As List(Of Integer) |
68 | ''' <summary> |
69 | ''' tick n |
70 | ''' </summary> |
71 | Dim value As Integer = 0 |
72 | |
73 | ReadOnly __chars As Char() = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" |
74 | ReadOnly __upbound As Integer = __chars.Length - 1 |
75 | |
76 | ''' <summary> |
77 | ''' 可以通过这个属性来重设uid的字符串的值 |
78 | ''' </summary> |
79 | ''' <returns></returns> |
80 | Public Property Key As String Implements IKeyedEntity(Of String).Key |
81 | <MethodImpl(MethodImplOptions.AggressiveInlining)> |
82 | Get |
83 | Return ToString() |
84 | End Get |
85 | Set(value As String) |
86 | Call chars.Clear() |
87 | |
88 | For Each c As Char In value |
89 | Dim index% = Array.IndexOf(__chars, c) |
90 | |
91 | If index = -1 Then |
92 | Call __error(c) |
93 | Else |
94 | Call chars.Add(index) |
95 | End If |
96 | Next |
97 | End Set |
98 | End Property |
99 | |
100 | ''' <summary> |
101 | ''' Throw error helper |
102 | ''' </summary> |
103 | ''' <param name="c"></param> |
104 | Private Sub __error(c As Char) |
105 | Dim msg$ = $"Char '{c}' is not a valid ASCII char, valids list: " & __chars.GetJson |
106 | Throw New NotSupportedException(msg) |
107 | End Sub |
108 | |
109 | ''' <summary> |
110 | ''' 使用自定义顺序的字符序列 |
111 | ''' </summary> |
112 | ''' <param name="n"></param> |
113 | ''' <param name="_chars"></param> |
114 | Sub New(n As Integer, _chars As IEnumerable(Of Char)) |
115 | chars += -1 |
116 | __chars = _chars.ToArray |
117 | __upbound = __chars.Length - 1 |
118 | |
119 | For i As Integer = 0 To n - 1 |
120 | Call __plus(chars.Count - 1) |
121 | Next |
122 | End Sub |
123 | |
124 | ''' <summary> |
125 | ''' |
126 | ''' </summary> |
127 | ''' <param name="n"></param> |
128 | ''' <param name="caseSensitive"> |
129 | ''' 假若是使用这个uid对象来生成临时文件名的话,由于Windows的文件系统是不区分大小写的,所以Aa的情况会出现同名的情况, |
130 | ''' 所以在这里就需要设置为False了,大小写重名的情况在Linux或者Mac上面没有影响 |
131 | ''' </param> |
132 | Sub New(n As Integer, Optional caseSensitive As Boolean = True) |
133 | chars += -1 |
134 | |
135 | If Not caseSensitive Then |
136 | __upbound -= 26 ' 则只有小写字母 |
137 | End If |
138 | |
139 | For i As Integer = 0 To n - 1 |
140 | Call __plus(chars.Count - 1) |
141 | Next |
142 | End Sub |
143 | |
144 | Sub New(i As Uid, Optional caseSensitive As Boolean = True) |
145 | chars = New List(Of Integer)(i.chars) |
146 | |
147 | If Not caseSensitive Then |
148 | __upbound -= 26 ' 则只有小写字母 |
149 | End If |
150 | End Sub |
151 | |
152 | ''' <summary> |
153 | ''' ZERO |
154 | ''' </summary> |
155 | ''' <param name="caseSensitive"> |
156 | ''' 大小写敏感?假若是需要应用于文件名称,在Windows操作系统之上建议设置为False不敏感,否则会出现相同字母但是不同大小写的文件会被覆盖的情况出现 |
157 | ''' </param> |
158 | Sub New(Optional caseSensitive As Boolean = True) |
159 | Call Me.New(Scan0, caseSensitive) |
160 | End Sub |
161 | |
162 | Private Function __plus(l As Integer) As Integer |
163 | Dim n As Integer = chars(l) + 1 |
164 | Dim move As Integer = 0 |
165 | |
166 | If n > __upbound Then |
167 | n = 0 |
168 | Dim pl = l - 1 |
169 | |
170 | If pl < 0 Then |
171 | Call chars.Insert(0, 1) |
172 | l += 1 |
173 | move = 1 |
174 | Else |
175 | l += __plus(pl) |
176 | End If |
177 | End If |
178 | |
179 | chars(l) = n |
180 | Me.value += 1 |
181 | |
182 | Return move |
183 | End Function |
184 | |
185 | ''' <summary> |
186 | ''' current id value +1 |
187 | ''' </summary> |
188 | ''' <returns></returns> |
189 | Public Function Plus() As String |
190 | Call __plus(chars.Count - 1) |
191 | Return ToString() |
192 | End Function |
193 | |
194 | ''' <summary> |
195 | ''' Thread unsafe operator for current id value plus <paramref name="n"/>. |
196 | ''' (请注意,这个操作是线程不安全的,所以请确保在执行这个命令之前使用``SyncLock``加锁) |
197 | ''' </summary> |
198 | ''' <param name="i"></param> |
199 | ''' <param name="n"></param> |
200 | ''' <returns></returns> |
201 | Public Shared Operator +(i As Uid, n As Integer) As Uid |
202 | For o As Integer = 0 To n - 1 |
203 | Call i.__plus(i.chars.Count - 1) |
204 | Next |
205 | |
206 | Return i |
207 | End Operator |
208 | |
209 | ''' <summary> |
210 | ''' Thread unsafe operator for current id value +1. |
211 | ''' (请注意,这个操作是线程不安全的,所以请确保在执行这个命令之前使用``SyncLock``加锁) |
212 | ''' </summary> |
213 | ''' <param name="i"></param> |
214 | ''' <returns></returns> |
215 | ''' |
216 | <MethodImpl(MethodImplOptions.AggressiveInlining)> |
217 | Public Shared Operator +(i As Uid) As SeqValue(Of String) |
218 | Call i.__plus(i.chars.Count - 1) |
219 | Return New SeqValue(Of String)(i.value, i.ToString) |
220 | End Operator |
221 | |
222 | ''' <summary> |
223 | ''' Convert the internal id value as the uid string value.(直接字符串序列,不会产生步进前移) |
224 | ''' </summary> |
225 | ''' <returns></returns> |
226 | ''' |
227 | <MethodImpl(MethodImplOptions.AggressiveInlining)> |
228 | Public Overrides Function ToString() As String |
229 | Return chars.Select(Function(x) __chars(x)).CharString |
230 | End Function |
231 | |
232 | ''' <summary> |
233 | ''' String contract of current id value string with a specific <paramref name="s"/> value. |
234 | ''' </summary> |
235 | ''' <param name="i"></param> |
236 | ''' <param name="s$"></param> |
237 | ''' <returns></returns> |
238 | <MethodImpl(MethodImplOptions.AggressiveInlining)> |
239 | Public Shared Operator &(i As Uid, s$) As String |
240 | Return i.ToString & s |
241 | End Operator |
242 | |
243 | ''' <summary> |
244 | ''' Alias for <see cref="ToString()"/> |
245 | ''' </summary> |
246 | ''' <param name="i"></param> |
247 | ''' <returns></returns> |
248 | <MethodImpl(MethodImplOptions.AggressiveInlining)> |
249 | Public Shared Narrowing Operator CType(i As Uid) As String |
250 | Return i.ToString |
251 | End Operator |
252 | End Class |
253 | End Namespace |