|
1 | 1 | using Parsers
|
2 | 2 | using Parsers: AbstractConf, SourceType, XOPTIONS, Result
|
3 | 3 |
|
| 4 | +""" |
| 5 | + RoundThrows |
| 6 | +
|
| 7 | +Raises an `InexactError` if any rounding is necessary. |
| 8 | +""" |
| 9 | +const RoundThrows = RoundingMode{:Throw}() |
| 10 | + |
4 | 11 | struct FixedDecimalConf{T<:Integer} <: AbstractConf{T}
|
5 | 12 | f::Int
|
6 | 13 | end
|
7 | 14 | Parsers.conf(::Type{FixedDecimal{T,f}}, opts::Parsers.Options, kw...) where {T<:Integer,f} = FixedDecimalConf{T}(f)
|
| 15 | +Parsers.returntype(::Type{FixedDecimal{T,f}}) where {T,f} = T |
| 16 | +function Parsers.result(FD::Type{FixedDecimal{T,f}}, res::Parsers.Result{T}) where {T,f} |
| 17 | + return Parsers.invalid(res.code) ? Result{FD}(res.code, res.tlen) : |
| 18 | + Result{FD}(res.code, res.tlen, reinterpret(FD, res.val)) |
| 19 | +end |
8 | 20 |
|
9 | 21 | const OPTIONS_ROUND_NEAREST = Parsers.Options(rounding=RoundNearest)
|
10 | 22 | const OPTIONS_ROUND_TO_ZERO = Parsers.Options(rounding=RoundToZero)
|
11 | 23 | const OPTIONS_ROUND_THROWS = Parsers.Options(rounding=nothing)
|
12 | 24 |
|
13 |
| -# like n * 10^decpos, but faster |
14 |
| -@inline function _shift(n::T, decpos) where {T<:Union{UInt128,Int128}} |
15 |
| - if decpos == 0 && return n |
16 |
| - elseif decpos == 1 && return T(10) * n |
17 |
| - elseif decpos == 2 && return T(100) * n |
18 |
| - elseif decpos == 3 && return T(1000) * n |
19 |
| - elseif decpos == 4 && return T(10000) * n |
20 |
| - elseif decpos == 5 && return T(100000) * n |
21 |
| - elseif decpos == 6 && return T(1000000) * n |
22 |
| - elseif decpos == 7 && return T(10000000) * n |
23 |
| - elseif decpos == 8 && return T(100000000) * n |
24 |
| - elseif decpos == 9 && return T(1000000000) * n |
25 |
| - elseif decpos == 10 && return T(10000000000) * n |
26 |
| - elseif decpos == 11 && return T(100000000000) * n |
27 |
| - elseif decpos == 12 && return T(1000000000000) * n |
28 |
| - elseif decpos == 13 && return T(10000000000000) * n |
29 |
| - elseif decpos == 14 && return T(100000000000000) * n |
30 |
| - elseif decpos == 15 && return T(1000000000000000) * n |
31 |
| - elseif decpos == 16 && return T(10000000000000000) * n |
32 |
| - elseif decpos == 17 && return T(100000000000000000) * n |
33 |
| - elseif decpos == 18 && return T(1000000000000000000) * n |
34 |
| - elseif decpos == 19 && return T(10000000000000000000) * n |
35 |
| - elseif decpos == 20 && return T(100000000000000000000) * n |
36 |
| - elseif decpos == 21 && return T(1000000000000000000000) * n |
37 |
| - elseif decpos == 22 && return T(10000000000000000000000) * n |
38 |
| - elseif decpos == 23 && return T(100000000000000000000000) * n |
39 |
| - elseif decpos == 24 && return T(1000000000000000000000000) * n |
40 |
| - elseif decpos == 25 && return T(10000000000000000000000000) * n |
41 |
| - elseif decpos == 26 && return T(100000000000000000000000000) * n |
42 |
| - elseif decpos == 27 && return T(1000000000000000000000000000) * n |
43 |
| - elseif decpos == 28 && return T(10000000000000000000000000000) * n |
44 |
| - elseif decpos == 29 && return T(100000000000000000000000000000) * n |
45 |
| - elseif decpos == 30 && return T(1000000000000000000000000000000) * n |
46 |
| - elseif decpos == 31 && return T(10000000000000000000000000000000) * n |
47 |
| - elseif decpos == 32 && return T(100000000000000000000000000000000) * n |
48 |
| - elseif decpos == 33 && return T(1000000000000000000000000000000000) * n |
49 |
| - elseif decpos == 34 && return T(10000000000000000000000000000000000) * n |
50 |
| - elseif decpos == 35 && return T(100000000000000000000000000000000000) * n |
51 |
| - elseif decpos == 36 && return T(1000000000000000000000000000000000000) * n |
52 |
| - elseif decpos == 37 && return T(10000000000000000000000000000000000000) * n |
53 |
| - elseif decpos == 38 && return T(100000000000000000000000000000000000000) * n |
54 |
| - elseif decpos == 39 && return T(1000000000000000000000000000000000000000) * n |
55 |
| - else |
56 |
| - @assert false # unreachable |
57 |
| - end |
58 |
| -end |
59 |
| - |
60 |
| -@inline function _shift(n::T, decpos) where {T<:Union{UInt64,Int64}} |
61 |
| - if decpos == 0 && return n |
62 |
| - elseif decpos == 1 && return T(10) * n |
63 |
| - elseif decpos == 2 && return T(100) * n |
64 |
| - elseif decpos == 3 && return T(1000) * n |
65 |
| - elseif decpos == 4 && return T(10000) * n |
66 |
| - elseif decpos == 5 && return T(100000) * n |
67 |
| - elseif decpos == 6 && return T(1000000) * n |
68 |
| - elseif decpos == 7 && return T(10000000) * n |
69 |
| - elseif decpos == 8 && return T(100000000) * n |
70 |
| - elseif decpos == 9 && return T(1000000000) * n |
71 |
| - elseif decpos == 10 && return T(10000000000) * n |
72 |
| - elseif decpos == 11 && return T(100000000000) * n |
73 |
| - elseif decpos == 12 && return T(1000000000000) * n |
74 |
| - elseif decpos == 13 && return T(10000000000000) * n |
75 |
| - elseif decpos == 14 && return T(100000000000000) * n |
76 |
| - elseif decpos == 15 && return T(1000000000000000) * n |
77 |
| - elseif decpos == 16 && return T(10000000000000000) * n |
78 |
| - elseif decpos == 17 && return T(100000000000000000) * n |
79 |
| - elseif decpos == 18 && return T(1000000000000000000) * n |
80 |
| - elseif decpos == 19 && return T(10000000000000000000) * n |
81 |
| - elseif decpos == 20 && return T(100000000000000000000) * n |
82 |
| - else |
83 |
| - @assert false # unreachable |
84 |
| - end |
85 |
| -end |
86 |
| - |
87 |
| -@inline function _shift(n::T, decpos) where {T<:Union{UInt32,Int32}} |
88 |
| - if decpos == 0 && return n |
89 |
| - elseif decpos == 1 && return T(10) * n |
90 |
| - elseif decpos == 2 && return T(100) * n |
91 |
| - elseif decpos == 3 && return T(1000) * n |
92 |
| - elseif decpos == 4 && return T(10000) * n |
93 |
| - elseif decpos == 5 && return T(100000) * n |
94 |
| - elseif decpos == 6 && return T(1000000) * n |
95 |
| - elseif decpos == 7 && return T(10000000) * n |
96 |
| - elseif decpos == 8 && return T(100000000) * n |
97 |
| - elseif decpos == 9 && return T(1000000000) * n |
98 |
| - elseif decpos == 10 && return T(10000000000) * n |
99 |
| - else |
100 |
| - @assert false # unreachable |
101 |
| - end |
102 |
| -end |
103 |
| - |
104 |
| -@inline function _shift(n::T, decpos) where {T<:Union{UInt16,Int16}} |
105 |
| - if decpos == 0 && return n |
106 |
| - elseif decpos == 1 && return T(10) * n |
107 |
| - elseif decpos == 2 && return T(100) * n |
108 |
| - elseif decpos == 3 && return T(1000) * n |
109 |
| - elseif decpos == 4 && return T(10000) * n |
110 |
| - elseif decpos == 5 && return T(100000) * n |
111 |
| - else |
112 |
| - @assert false # unreachable |
113 |
| - end |
114 |
| -end |
115 |
| - |
116 |
| -@inline function _shift(n::T, decpos) where {T<:Union{UInt8,Int8}} |
117 |
| - if decpos == 0 && return n |
118 |
| - elseif decpos == 1 && return T(10) * n |
119 |
| - elseif decpos == 2 && return T(100) * n |
120 |
| - elseif decpos == 3 && return T(1000) * n |
121 |
| - else |
122 |
| - @assert false # unreachable |
123 |
| - end |
124 |
| -end |
| 25 | +@inline _shift(n::T, decpos) where {T} = T(10)^decpos * n |
125 | 26 |
|
126 | 27 | const _BIGINT1 = BigInt(1)
|
127 | 28 | const _BIGINT2 = BigInt(2)
|
|
263 | 164 | end
|
264 | 165 |
|
265 | 166 | startpos = pos
|
266 |
| - code = Parsers.SUCCESS |
267 |
| - |
268 | 167 | # begin parsing
|
269 | 168 | neg = b == UInt8('-')
|
270 | 169 | if neg || b == UInt8('+')
|
|
295 | 194 | return pos, code, Parsers.PosLen(pl.pos, pos - pl.pos), x
|
296 | 195 | end
|
297 | 196 |
|
298 |
| -Parsers.supportedtype(::Type{FixedDecimal{T,f}}) where {T<:Integer,f} = true |
299 |
| - |
300 |
| -function Parsers.xparse(::Type{FixedDecimal{T,f}}, source::SourceType, pos, len, options=XOPTIONS, ::Type{S}=FixedDecimal{T,f}) where {T<:Integer,f,S} |
301 |
| - buf = source isa AbstractString ? codeunits(source) : source |
302 |
| - # TODO: remove @noinline after Parsers is updated |
303 |
| - res = @noinline Parsers._xparse(FixedDecimalConf{T}(f), buf, pos, len, options, T) |
304 |
| - return Result{S}(res.code, res.tlen, reinterpret(S, res.val)) |
305 |
| -end |
306 |
| - |
307 |
| -function Parsers.xparse2(::Type{FixedDecimal{T,f}}, source::SourceType, pos, len, options=XOPTIONS, ::Type{S}=FixedDecimal{T,f}) where {T<:Integer,f,S} |
308 |
| - buf = source isa AbstractString ? codeunits(source) : source |
309 |
| - # TODO: remove @noinline after Parsers is updated |
310 |
| - res = @noinline Parsers._xparse2(FixedDecimalConf{T}(f), buf, pos, len, options, T) |
311 |
| - return Result{S}(res.code, res.tlen, reinterpret(S, res.val)) |
312 |
| -end |
| 197 | +Parsers.supportedtype(::Type{<:FixedDecimal}) = true |
313 | 198 |
|
314 | 199 | function _base_parse(::Type{FD{T, f}}, source::AbstractString, mode::RoundingMode=RoundNearest) where {T, f}
|
315 | 200 | if !(mode in (RoundThrows, RoundNearest, RoundToZero))
|
|
0 commit comments