/
DoubleType.vb
229 lines (178 loc) · 8.56 KB
/
DoubleType.vb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
' Licensed to the .NET Foundation under one or more agreements.
' The .NET Foundation licenses this file to you under the MIT license.
Imports System
Imports System.Globalization
Imports Microsoft.VisualBasic.CompilerServices.DecimalType
Imports Microsoft.VisualBasic.CompilerServices.Utils
Namespace Microsoft.VisualBasic.CompilerServices
<System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)>
Public NotInheritable Class DoubleType
' Prevent creation.
Private Sub New()
End Sub
Public Shared Function FromString(ByVal Value As String) As Double
Return FromString(Value, Nothing)
End Function
Public Shared Function FromString(ByVal Value As String, ByVal NumberFormat As NumberFormatInfo) As Double
If Value Is Nothing Then
Return 0
End If
Try
Dim i64Value As Int64
If IsHexOrOctValue(Value, i64Value) Then
Return CDbl(i64Value)
End If
Return DoubleType.Parse(Value, NumberFormat)
Catch e As FormatException
Throw New InvalidCastException(SR.Format(SR.InvalidCast_FromStringTo, Left(Value, 32), "Double"), e)
End Try
End Function
Public Shared Function FromObject(ByVal Value As Object) As Double
Return FromObject(Value, Nothing)
End Function
Public Shared Function FromObject(ByVal Value As Object, ByVal NumberFormat As NumberFormatInfo) As Double
If Value Is Nothing Then
Return 0
End If
Dim valueInterface As IConvertible
Dim valueTypeCode As TypeCode
valueInterface = TryCast(Value, IConvertible)
If valueInterface Is Nothing Then
GoTo ThrowInvalidCast
End If
valueTypeCode = valueInterface.GetTypeCode()
Select Case valueTypeCode
Case TypeCode.Boolean
Return CDbl(valueInterface.ToBoolean(Nothing))
Case TypeCode.Byte
If TypeOf Value Is System.Byte Then
Return CDbl(DirectCast(Value, Byte))
Else
Return CDbl(valueInterface.ToByte(Nothing))
End If
Case TypeCode.Int16
If TypeOf Value Is System.Int16 Then
Return CDbl(DirectCast(Value, Int16))
Else
Return CDbl(valueInterface.ToInt16(Nothing))
End If
Case TypeCode.Int32
If TypeOf Value Is System.Int32 Then
Return CDbl(DirectCast(Value, Int32))
Else
Return CDbl(valueInterface.ToInt32(Nothing))
End If
Case TypeCode.Int64
If TypeOf Value Is System.Int64 Then
Return CDbl(DirectCast(Value, Int64))
Else
Return CDbl(valueInterface.ToInt64(Nothing))
End If
Case TypeCode.Single
If TypeOf Value Is System.Single Then
Return DirectCast(Value, Single)
Else
Return CDbl(valueInterface.ToSingle(Nothing))
End If
Case TypeCode.Double
If TypeOf Value Is System.Double Then
Return CDbl(DirectCast(Value, Double))
Else
Return CDbl(valueInterface.ToDouble(Nothing))
End If
Case TypeCode.Decimal
'Do not use .ToDecimal because of jit temp issue effects all perf
Return DecimalToDouble(valueInterface)
Case TypeCode.String
Return DoubleType.FromString(valueInterface.ToString(Nothing), NumberFormat)
Case TypeCode.Char,
TypeCode.DateTime
' Fall through to error
Case Else
' Fall through to error
End Select
ThrowInvalidCast:
Throw New InvalidCastException(SR.Format(SR.InvalidCast_FromTo, VBFriendlyName(Value), "Double"))
End Function
Private Shared Function DecimalToDouble(ByVal ValueInterface As IConvertible) As Double
Return CDbl(ValueInterface.ToDecimal(Nothing))
End Function
Public Shared Function Parse(ByVal Value As String) As Double
Return Parse(Value, Nothing)
End Function
Friend Shared Function TryParse(ByVal Value As String, ByRef Result As Double) As Boolean
Dim numberFormat As NumberFormatInfo
Dim normalizedNumberFormat As NumberFormatInfo
Dim culture As CultureInfo = GetCultureInfo()
numberFormat = culture.NumberFormat
normalizedNumberFormat = GetNormalizedNumberFormat(numberFormat)
Const flags As NumberStyles =
NumberStyles.AllowDecimalPoint Or
NumberStyles.AllowExponent Or
NumberStyles.AllowLeadingSign Or
NumberStyles.AllowLeadingWhite Or
NumberStyles.AllowThousands Or
NumberStyles.AllowTrailingSign Or
NumberStyles.AllowParentheses Or
NumberStyles.AllowTrailingWhite Or
NumberStyles.AllowCurrencySymbol
Value = ToHalfwidthNumbers(Value, culture)
' The below code handles the 80% case efficiently and is inefficient only when the numeric and currency settings
' are different
If numberFormat Is normalizedNumberFormat Then
Return System.Double.TryParse(Value, flags, normalizedNumberFormat, Result)
Else
Try
' Use numeric settings to parse
' Note that we use Parse instead of TryParse in order to distinguish whether the conversion failed
' due to FormatException or other exception like OverFlowException, etc.
Result = System.Double.Parse(Value, flags, normalizedNumberFormat)
Return True
Catch FormatEx As FormatException
' Use currency settings to parse
Try
Return System.Double.TryParse(Value, flags, numberFormat, Result)
Catch ex As ArgumentException
Return False
End Try
Catch ex As StackOverflowException
Throw ex
Catch ex As OutOfMemoryException
Throw ex
Catch Ex As Exception
Return False
End Try
End If
End Function
Public Shared Function Parse(ByVal Value As String, ByVal NumberFormat As NumberFormatInfo) As Double
Dim normalizedNumberFormat As NumberFormatInfo
Dim culture As CultureInfo = GetCultureInfo()
If NumberFormat Is Nothing Then
NumberFormat = culture.NumberFormat
End If
' Normalize number format settings to enable us to first use the numeric settings for both currency and number parsing
' compatible with VB6
normalizedNumberFormat = GetNormalizedNumberFormat(NumberFormat)
Const flags As NumberStyles =
NumberStyles.AllowDecimalPoint Or
NumberStyles.AllowExponent Or
NumberStyles.AllowLeadingSign Or
NumberStyles.AllowLeadingWhite Or
NumberStyles.AllowThousands Or
NumberStyles.AllowTrailingSign Or
NumberStyles.AllowParentheses Or
NumberStyles.AllowTrailingWhite Or
NumberStyles.AllowCurrencySymbol
Value = ToHalfwidthNumbers(Value, culture)
Try
' Use numeric settings to parse
Return System.Double.Parse(Value, flags, normalizedNumberFormat)
Catch FormatEx As FormatException When Not (NumberFormat Is normalizedNumberFormat)
' Use currency settings to parse
Return System.Double.Parse(Value, flags, NumberFormat)
Catch Ex As Exception
Throw Ex
End Try
End Function
End Class
End Namespace