@@ -186,7 +186,7 @@ struct Decimal(uint maxSize64)
186186 static if (optimize || (allowSpecialValues && allowDExponent && allowStartingPlus && checkEmpty) == false )
187187 pragma (inline, true );
188188 }
189- static if (optimize && false )
189+ static if (optimize)
190190 {
191191 import mir.utility: _expect;
192192 static if (checkEmpty)
@@ -218,161 +218,196 @@ struct Decimal(uint maxSize64)
218218 exponent = 0 ;
219219
220220 ulong v;
221- bool dot;
222- static if (allowUnderscores )
221+
222+ if (_expect(d >= 10 , false ) )
223223 {
224- bool recentUnderscore;
224+ static if (allowDotOnBounds)
225+ {
226+ if (d == ' .' - ' 0' )
227+ {
228+ if (str.length == 0 )
229+ return false ;
230+ key = DecimalExponentKey.dot;
231+ d = str[0 ] - ' 0' ;
232+ str = str[1 .. $];
233+ if (_expect(d < 10 , true ))
234+ goto FI ;
235+ return false ;
236+ }
237+ }
238+ static if (allowSpecialValues)
239+ goto NI ;
240+ else
241+ return false ;
225242 }
226- // Was there a recent character within the set: ['.', 'e', 'E', 'd', 'D']?
227- bool recentModifier;
243+
228244 static if (! allowLeadingZeros)
229245 {
230- if (d == 0 )
246+ if (_expect( d == 0 , false ) )
231247 {
232248 if (str.length == 0 )
233249 goto R;
234- if (str[0 ] >= ' 0' && str[0 ] <= ' 9' )
250+ d = str[0 ] - ' 0' ;
251+ str = str[1 .. $];
252+ if (d < 10 )
235253 return false ;
236- goto S ;
254+ goto DOT ;
237255 }
238256 }
239257
258+ v = d;
259+
260+ S:
261+ if (str.length == 0 )
262+ goto R;
263+ d = str[0 ] - ' 0' ;
264+ str = str[1 .. $];
265+
240266 if (d < 10 )
241267 {
268+ F0 :
269+ import mir.checkedint: mulu, addu;
270+ bool overflow;
271+ v = mulu(v, cast (uint )10 , overflow);
272+ if (overflow)
273+ return false ;
274+ v = addu(v, d, overflow);
275+ if (overflow)
276+ return false ;
242277 goto S;
243278 }
244279
245- static if (allowDotOnBounds )
280+ static if (allowUnderscores )
246281 {
247- if (d == ' . ' - ' 0' )
282+ if (d == ' _ ' - ' 0' )
248283 {
249284 if (str.length == 0 )
250285 return false ;
251- key = DecimalExponentKey.dot;
252- dot = true ;
253- recentModifier = true ;
254- goto F;
286+ d = str[0 ] - ' 0' ;
287+ str = str[1 .. $];
288+ if (_expect(d < 10 , true ))
289+ goto F0 ;
290+ return false ;
255291 }
256292 }
257-
258- static if (allowSpecialValues)
259- {
260- goto NI ;
261- }
262- else
293+ DOT :
294+ if (d == DecimalExponentKey.dot)
263295 {
264- return false ;
265- }
296+ // The dot modifier CANNOT be preceded by any modifiers.
297+ if (key != DecimalExponentKey.none)
298+ return false ;
266299
267- F: for (;;)
268- {
269- d = str[0 ] - ' 0' ;
270- str = str[1 .. $];
300+ key = DecimalExponentKey.dot;
271301
272- if (_expect(d <= 10 , true ) )
302+ if (str.length == 0 )
273303 {
274- static if (allowUnderscores)
275- {
276- recentUnderscore = false ;
277- }
278- recentModifier = false ;
279- {
280- import mir.checkedint: mulu;
281- bool overflow;
282- v = mulu(v, cast (uint )10 , overflow);
283- if (overflow)
284- break ;
285- }
286- S:
287- v += d;
288- exponentShift -= dot;
289- if (str.length)
290- continue ;
291- E:
292- exponent += exponentShift;
293- R:
294- coefficient.data[0 ] = v;
295- coefficient.length = v != 0 ;
296- static if (allowUnderscores)
297- {
298- return ! recentUnderscore && ! recentModifier;
299- }
304+ static if (allowDotOnBounds)
305+ goto R;
300306 else
301- {
302- return ! recentModifier;
303- }
307+ return false ;
304308 }
305309
306- switch (d)
307- {
308- case DecimalExponentKey.dot:
309- // The dot modifier CANNOT be preceded by any modifiers.
310- if (recentModifier || key != DecimalExponentKey.none)
311- break ;
310+ IF :
312311
313- static if (allowUnderscores)
314- {
315- // If we allow underscores, the dot also CANNOT be preceded by any underscores.
316- // It must be preceded by a number.
317- if (recentUnderscore)
318- break ;
319- }
320- key = DecimalExponentKey.dot;
321- if (_expect(dot, false ))
322- break ;
323- dot = true ;
324- if (str.length)
325- {
326- recentModifier = true ;
327- continue ;
328- }
329- static if (allowDotOnBounds)
330- {
331- goto R;
332- }
333- else
312+ static if (is (C == char ))
313+ {
314+ import mir.bignum.internal.parse: isMadeOfEightDigits, parseEightDigits;
315+ if (str.length >= 8 && isMadeOfEightDigits(str[0 .. 8 ]))
316+ {
317+ ulong multplier = 100000000 ;
318+ ulong value = parseEightDigits(str[0 .. 8 ]);
319+ str = str[8 .. $];
320+ exponentShift -= 8 ;
321+ if (str.length >= 8 && isMadeOfEightDigits(str[0 .. 8 ]))
334322 {
335- break ;
323+ multplier = 100000000 * 100000000 ;
324+ value *= 100000000 ;
325+ value += parseEightDigits(str[0 .. 8 ]);
326+ str = str[8 .. $];
327+ exponentShift -= 8 ;
336328 }
337- static if (allowExponent)
338- {
339- static if (allowDExponent)
329+
340330 {
341- case DecimalExponentKey.d:
342- case DecimalExponentKey.D:
343- goto case DecimalExponentKey.e;
331+ import mir.checkedint: mulu, addu;
332+ bool overflow;
333+ v = mulu(v, multplier, overflow);
334+ if (overflow)
335+ return false ;
336+ v = addu(v, value, overflow);;
337+ if (overflow)
338+ return false ;
344339 }
345- case DecimalExponentKey.e:
346- case DecimalExponentKey.E:
347- import mir.parse: parse;
348- // We don't really care if the e/E/d/D modifiers are preceded by a modifier,
349- // so as long as they are a dot or a regular number.
350- if (key != DecimalExponentKey.dot && key != DecimalExponentKey.none)
351- break ;
352- key = cast (DecimalExponentKey)d;
353- if (parse(str, exponent) && str.length == 0 ) {
354- recentModifier = false ;
355- goto E;
356- }
357- break ;
358340 }
359- static if (allowUnderscores)
341+ }
342+
343+ d = str[0 ] - ' 0' ;
344+ str = str[1 .. $];
345+ if (_expect(d >= 10 , false ))
346+ goto DOB ;
347+ FI :
348+ {
349+ import mir.checkedint: mulu, addu;
350+ bool overflow;
351+ v = mulu(v, cast (uint )10 , overflow);
352+ if (overflow)
353+ return false ;
354+ v = addu(v, d, overflow);;
355+ if (overflow)
356+ return false ;
357+ }
358+ exponentShift-- ;
359+ if (str.length == 0 )
360+ goto E;
361+ d = str[0 ] - ' 0' ;
362+ str = str[1 .. $];
363+ if (d < 10 )
364+ goto FI ;
365+
366+ static if (allowUnderscores)
367+ {
368+ if (d == ' _' - ' 0' )
360369 {
361- case ' _' - ' 0' :
362- // A underscore cannot be preceded by an underscore or a modifier.
363- if (recentUnderscore || recentModifier)
364- break ;
365-
366- recentUnderscore = true ;
367- if (str.length)
368- continue ;
369- break ;
370+ if (str.length == 0 )
371+ return false ;
372+ d = str[0 ] - ' 0' ;
373+ str = str[1 .. $];
374+ if (_expect(d < 10 , true ))
375+ goto FI ;
376+ return false ;
370377 }
371- default :
372378 }
373- break ;
379+ DOB :
380+ static if (! allowDotOnBounds)
381+ {
382+ if (exponentShift == 0 )
383+ return false ;
384+ }
385+
386+ }
387+
388+ static if (allowExponent)
389+ {
390+ if (d == DecimalExponentKey.e
391+ || d == DecimalExponentKey.E
392+ || d == DecimalExponentKey.d && allowDExponent
393+ || d == DecimalExponentKey.D && allowDExponent
394+ )
395+ {
396+ import mir.parse: parse;
397+ key = cast (DecimalExponentKey)d;
398+ if (parse(str, exponent) && str.length == 0 )
399+ goto E;
400+ }
374401 }
375402 return false ;
403+
404+ E:
405+ exponent += exponentShift;
406+ R:
407+ coefficient.data[0 ] = v;
408+ coefficient.length = v != 0 ;
409+ return true ;
410+
376411 static if (allowSpecialValues)
377412 {
378413 NI :
0 commit comments