@@ -40,30 +40,103 @@ function typeparser(conf::AbstractConf{T}, source, pos, len, b, code, pl, option
4040 return pos, code, pl, T (x)
4141end
4242
43+ function _copy_nulterminated (source:: AbstractVector{UInt8} , pos, len)
44+ vlen = max (0 , len)
45+ buf = Vector {UInt8} (undef, vlen + 1 )
46+ vlen > 0 && copyto! (buf, 1 , source, pos, vlen)
47+ @inbounds buf[vlen + 1 ] = 0x00
48+ return buf
49+ end
50+
51+ @inline _contiguous (source) = false
52+ @inline _contiguous (source:: StridedVector{UInt8} ) = stride (source, 1 ) == 1
53+ @inline _writable_contiguous (source) = false
54+ @inline _writable_contiguous (source:: Vector{UInt8} ) = true
55+ @inline _writable_contiguous (source:: SubArray{UInt8,1} ) =
56+ parent (source) isa Vector{UInt8} && _contiguous (source)
57+
58+ @inline _nulterminated (source, len) = false
59+ @inline _nulterminated (source:: String , len) = len == sizeof (source)
60+ @inline _nulterminated (source:: Base.CodeUnits{UInt8,String} , len) = len == length (source)
61+ @inline function _nulterminated (source:: AbstractVector{UInt8} , len)
62+ return _contiguous (source) && len < length (source) && @inbounds (source[len + 1 ]) == 0x00
63+ end
64+
65+ @inline function _ends_on_delimiter (source:: AbstractVector{UInt8} , len, options)
66+ 0 < len <= length (source) || return false
67+ @inbounds b = source[len]
68+ return b == UInt8 (' \n ' ) || b == UInt8 (' \r ' ) || (options. flags. checkdelim && options. delim == b)
69+ end
70+
71+ function _bigfloat_buffer (source:: AbstractVector{UInt8} , pos, len, b, code, options)
72+ _, _, pl, _ = typeparser (DefaultConf {String} (), source, pos, len, b, code, poslen (pos, 0 ), options)
73+ return _copy_nulterminated (source, pl. pos, pl. len)
74+ end
75+
76+ _bigfloat_buffer (source:: AbstractString , pos, len, b, code, options) =
77+ _bigfloat_buffer (codeunits (source), pos, len, b, code, options)
78+
79+ function _bigfloat_buffer (source:: IO , pos, len, b, code, options)
80+ _, _, pl, _ = typeparser (DefaultConf {String} (), source, pos, len, b, code, poslen (pos, 0 ), options)
81+ vlen = max (0 , pl. len)
82+ buf = Vector {UInt8} (undef, vlen + 1 )
83+ fastseek! (source, pl. pos - 1 )
84+ readbytes! (source, buf, vlen)
85+ @inbounds buf[vlen + 1 ] = 0x00
86+ fastseek! (source, pos - 1 )
87+ return buf
88+ end
89+
90+ @inline function _mpfr_strtofr (z, ptr, endptr, base, rounding)
91+ return ccall ((:mpfr_strtofr , :libmpfr ), Int32, (Ref{BigFloat}, Cstring, Ref{Ptr{UInt8}}, Int32, Base. MPFR. MPFRRoundingMode), z, ptr, endptr, base, rounding)
92+ end
93+
94+ @inline function _finish_bigfloat (source, pos, code, pl, z, ptr, base, rounding)
95+ endptr = Ref {Ptr{UInt8}} ()
96+ err = _mpfr_strtofr (z, ptr, endptr, base, rounding)
97+ code |= endptr[] == ptr ? INVALID : OK
98+ pos += Int (endptr[] - ptr)
99+ source isa IO && fastseek! (source, pos - 1 )
100+ return pos, code, PosLen (pl. pos, max (0 , pos - pl. pos)), z
101+ end
102+
43103function typeparser (:: AbstractConf{BigFloat} , source, pos, len, b, code, pl, options)
44104 base = 0
45105 rounding = Base. MPFR. ROUNDING_MODE[]
46106 z = BigFloat (precision= Base. MPFR. DEFAULT_PRECISION[])
47- if source isa AbstractVector{UInt8} || source isa String
48- str = source
49- strpos = pos
107+ if _nulterminated (source, len)
108+ GC. @preserve source begin
109+ return _finish_bigfloat (source, pos, code, pl, z, pointer (source, pos), base, rounding)
110+ end
111+ elseif _writable_contiguous (source)
112+ nulpos = if _ends_on_delimiter (source, len, options)
113+ len
114+ else
115+ _, _, strpl, _ = typeparser (DefaultConf {String} (), source, pos, len, b, code, poslen (pos, 0 ), options)
116+ strpl. pos + strpl. len
117+ end
118+ if nulpos <= length (source)
119+ @inbounds byte = source[nulpos]
120+ @inbounds source[nulpos] = 0x00
121+ try
122+ GC. @preserve source begin
123+ return _finish_bigfloat (source, pos, code, pl, z, pointer (source, pos), base, rounding)
124+ end
125+ finally
126+ @inbounds source[nulpos] = byte
127+ end
128+ else
129+ _, _, strpl, _ = typeparser (DefaultConf {String} (), source, pos, len, b, code, poslen (pos, 0 ), options)
130+ buf = _copy_nulterminated (source, strpl. pos, strpl. len)
131+ GC. @preserve buf begin
132+ return _finish_bigfloat (source, pos, code, pl, z, pointer (buf), base, rounding)
133+ end
134+ end
50135 else
51- _, _, _pl, _ = typeparser (String, source, pos, len, b, code, pl, options)
52- _pos = position (source)
53- vpos, vlen = _pl. pos, _pl. len
54- fastseek! (source, vpos - 1 )
55- str = Base. StringVector (vlen)
56- strpos = 1
57- readbytes! (source, str, vlen)
58- fastseek! (source, _pos) # reset IO to earlier position
59- end
60- GC. @preserve str begin
61- ptr = pointer (str, strpos)
62- endptr = Ref {Ptr{UInt8}} ()
63- err = ccall ((:mpfr_strtofr , :libmpfr ), Int32, (Ref{BigFloat}, Cstring, Ref{Ptr{UInt8}}, Int32, Base. MPFR. MPFRRoundingMode), z, ptr, endptr, base, rounding)
64- code |= endptr[] == ptr ? INVALID : OK
65- pos += Int (endptr[] - ptr)
66- return pos, code, PosLen (pl. pos, max (0 , pos - pl. pos)), z
136+ buf = _bigfloat_buffer (source, pos, len, b, code, options)
137+ GC. @preserve buf begin
138+ return _finish_bigfloat (source, pos, code, pl, z, pointer (buf), base, rounding)
139+ end
67140 end
68141end
69142
0 commit comments