@@ -98,11 +98,15 @@ constexpr auto parser(const char* first, const char* last, bool& sign, Unsigned_
9898 sign = false ;
9999 }
100100
101+ constexpr std::size_t significand_buffer_size = std::numeric_limits<Unsigned_Integer>::digits10 ;
102+ char significand_buffer[significand_buffer_size] {};
103+
101104 // Handle non-finite values
102105 // Stl allows for string like "iNf" to return inf
103106 //
104107 // This is nested ifs rather than a big one-liner to ensure that once we hit an invalid character
105108 // or an end of buffer we return the correct value of next
109+ bool signaling {};
106110 if (next != last && (*next == ' i' || *next == ' I' ))
107111 {
108112 ++next;
@@ -112,14 +116,21 @@ constexpr auto parser(const char* first, const char* last, bool& sign, Unsigned_
112116 if (next != last && (*next == ' f' || *next == ' F' ))
113117 {
114118 ++next;
115- significand = 0 ;
119+ exponent = 0 ;
116120 return {next, std::errc::value_too_large};
117121 }
118122 }
119123
120124 return {first, std::errc::invalid_argument};
121125 }
122- else if (next != last && (*next == ' n' || *next == ' N' ))
126+
127+ if (next != last && (*next == ' s' || *next == ' S' ))
128+ {
129+ ++next;
130+ signaling = true ;
131+ }
132+
133+ if (next != last && (*next == ' n' || *next == ' N' ))
123134 {
124135 ++next;
125136 if (next != last && (*next == ' a' || *next == ' A' ))
@@ -128,56 +139,97 @@ constexpr auto parser(const char* first, const char* last, bool& sign, Unsigned_
128139 if (next != last && (*next == ' n' || *next == ' N' ))
129140 {
130141 ++next;
131- if (next != last && (*next == ' ( ' ) )
142+ if (next != last)
132143 {
133144 const auto current_pos {next};
134- ++next;
145+
146+ bool any_valid_char {false };
147+ bool has_opening_brace {false };
148+ if (*next == ' (' )
149+ {
150+ ++next;
151+ has_opening_brace = true ;
152+ }
135153
136154 // Handle nan(SNAN)
137155 if ((last - next) >= 4 && (*next == ' s' || *next == ' S' ) && (*(next + 1 ) == ' n' || *(next + 1 ) == ' N' )
138156 && (*(next + 2 ) == ' a' || *(next + 2 ) == ' A' ) && (*(next + 3 ) == ' n' || *(next + 3 ) == ' N' ))
139157 {
140- next += 3 ;
141- significand = 1 ;
158+ next += 4 ;
159+ signaling = true ;
160+ any_valid_char = true ;
142161 }
143162 // Handle Nan(IND)
144163 else if ((last - next) >= 3 && (*next == ' i' || *next == ' I' ) && (*(next + 1 ) == ' n' || *(next + 1 ) == ' N' )
145164 && (*(next + 2 ) == ' d' || *(next + 2 ) == ' D' ))
146165 {
147- next += 2 ;
148- significand = 0 ;
166+ next += 3 ;
167+ sign = true ;
168+ any_valid_char = true ;
149169 }
150170
151- // Arbitrary payload
152- bool valid_payload {false };
171+ // Arbitrary numerical payload
172+ bool has_numerical_payload {false };
173+ auto significand_buffer_first {significand_buffer};
174+ std::size_t significand_characters {};
153175 while (next != last && (*next != ' )' ))
154176 {
155- if (is_payload_char (*next))
177+ if (significand_characters < significand_buffer_size && is_integer_char (*next))
156178 {
157- ++next;
158- valid_payload = true ;
179+ ++significand_characters;
180+ *significand_buffer_first++ = *next++;
181+ any_valid_char = true ;
182+ has_numerical_payload = true ;
159183 }
160184 else
161185 {
162- valid_payload = false ;
186+ // End of valid payload even if there are more characters
187+ // e.g. SNAN42JUNK stops at J
163188 break ;
164189 }
165190 }
166191
167- if (valid_payload)
192+ // Non-numerical payload still needs to be parsed
193+ // e.g. nan(PAYLOAD)
194+ if (!has_numerical_payload && has_opening_brace)
195+ {
196+ while (next != last && (*next != ' )' ))
197+ {
198+ if (is_payload_char (*next))
199+ {
200+ any_valid_char = true ;
201+ ++next;
202+ }
203+ else
204+ {
205+ break ;
206+ }
207+ }
208+ }
209+
210+ if (next != last && any_valid_char)
168211 {
212+ // One past the end if we need to
169213 ++next;
170214 }
171- else
215+
216+ if (significand_characters != 0 )
217+ {
218+ from_chars_dispatch (significand_buffer, significand_buffer + significand_characters, significand, 10 );
219+ }
220+
221+ if (!any_valid_char)
172222 {
223+ // If we have nan(..BAD..) we should point to (
173224 next = current_pos;
174225 }
175226
227+ exponent = static_cast <Integer>(signaling);
176228 return {next, std::errc::not_supported};
177229 }
178230 else
179231 {
180- significand = 0 ;
232+ exponent = static_cast <Integer>(signaling) ;
181233 return {next, std::errc::not_supported};
182234 }
183235 }
@@ -204,8 +256,6 @@ constexpr auto parser(const char* first, const char* last, bool& sign, Unsigned_
204256 }
205257
206258 // Next we get the significand
207- constexpr std::size_t significand_buffer_size = std::numeric_limits<Unsigned_Integer>::digits10 ;
208- char significand_buffer[significand_buffer_size] {};
209259 std::size_t i = 0 ;
210260 std::size_t dot_position = 0 ;
211261 Integer extra_zeros = 0 ;
0 commit comments