@@ -119,7 +119,7 @@ struct Decimal(size_t maxSize64)
119119 Returns: false in case of overflow or incorrect string. 
120120 Precondition: non-empty coefficients. 
121121 +/  
122-  bool  fromStringImpl (C, bool  allowSpecialValues = true , bool  allowDotOnBounds = true , bool  allowDExponent = true , bool  allowStartingPlus = true , bool  checkEmpty = true )(scope  const (C)[] str, out  DecimalExponentKey key)
122+  bool  fromStringImpl (C, bool  allowSpecialValues = true , bool  allowDotOnBounds = true , bool  allowDExponent = true , bool  allowStartingPlus = true , bool  checkEmpty = true ,  bool  allowUnderscores =  true ,  bool  allowLeadingZeros =  true )(scope  const (C)[] str, out  DecimalExponentKey key)
123123 @safe  pure  @nogc  nothrow 
124124 if  (isSomeChar! C)
125125 {
@@ -163,14 +163,20 @@ struct Decimal(size_t maxSize64)
163163 ulong  v;
164164 uint  afterDot;
165165 bool  dot;
166- 
167-  if  (d ==  0 )
166+  static  if  (allowUnderscores)
168167 {
169-  if  (str.length ==  0 )
170-  goto  R;
171-  if  (str[0 ] >=  ' 0'   &&  str[0 ] <=  ' 9'  )
172-  return  false ;
173-  goto  S;
168+  bool  recentUnderscore;
169+  }
170+  static  if  (! allowLeadingZeros)
171+  {
172+  if  (d ==  0 )
173+  {
174+  if  (str.length ==  0 )
175+  goto  R;
176+  if  (str[0 ] >=  ' 0'   &&  str[0 ] <=  ' 9'  )
177+  return  false ;
178+  goto  S;
179+  }
174180 }
175181
176182 if  (d <  10 )
@@ -206,6 +212,10 @@ struct Decimal(size_t maxSize64)
206212
207213 if  (_expect(d <=  10 , true ))
208214 {
215+  static  if  (allowUnderscores)
216+  {
217+  recentUnderscore = false ;
218+  }
209219 {
210220 import  core.checkedint : addu, mulu;
211221 bool  overflow;
@@ -223,18 +233,35 @@ struct Decimal(size_t maxSize64)
223233 R:
224234 coefficient.data[0 ] = v;
225235 coefficient.length = v !=  0 ;
226-  return  true ;
236+  static  if  (allowUnderscores)
237+  {
238+  return  ! recentUnderscore;
239+  }
240+  else 
241+  {
242+  return  true ;
243+  }
244+  }
245+  key = cast (DecimalExponentKey)d;
246+  static  if  (allowUnderscores)
247+  {
248+  if  (recentUnderscore)
249+  return  false ;
227250 }
228251 switch  (d)
229252 {
230-  D:
231253 case  DecimalExponentKey.dot:
232-  if  (dot)
254+  if  (_expect( dot,  false ) )
233255 break ;
234-  key = cast (DecimalExponentKey)d;
235256 dot = true ;
236257 if  (str.length)
258+  {
259+  static  if  (allowUnderscores)
260+  {
261+  recentUnderscore = true ;
262+  }
237263 continue ;
264+  }
238265 static  if  (allowDotOnBounds)
239266 {
240267 goto  R;
@@ -251,11 +278,18 @@ struct Decimal(size_t maxSize64)
251278 }
252279 case  DecimalExponentKey.e:
253280 case  DecimalExponentKey.E:
254-  key = cast (DecimalExponentKey)d;
255281 import  mir.parse: parse;
256282 if  (parse(str, exponent) &&  str.length ==  0 )
257283 goto  E;
258284 break ;
285+  static  if  (allowUnderscores)
286+  {
287+  case  ' _'   -  ' 0'  :
288+  recentUnderscore = true ;
289+  if  (str.length)
290+  continue ;
291+  break ;
292+  }
259293 default :
260294 }
261295 break ;
@@ -287,7 +321,7 @@ struct Decimal(size_t maxSize64)
287321 {
288322 import  mir.bignum.low_level_view: DecimalView, BigUIntView, MaxWordPow10;
289323 auto  work = DecimalView! size_t (false , 0 , BigUIntView! size_t (coefficient.data));
290-  auto  ret = work.fromStringImpl! (C, allowSpecialValues, allowDExponent, allowStartingPlus)(str, key);
324+  auto  ret = work.fromStringImpl! (C, allowSpecialValues, allowDExponent, allowStartingPlus, checkEmpty, allowUnderscores, allowLeadingZeros )(str, key);
291325 coefficient.length = cast (uint ) work.coefficient.coefficients.length;
292326 coefficient.sign = work.sign;
293327 exponent = work.exponent;
@@ -359,13 +393,13 @@ struct Decimal(size_t maxSize64)
359393 assert (decimal.fromStringImpl(" 4."  , key));
360394 assert (! decimal.fromStringImpl(" ."  , key));
361395 assert (decimal.fromStringImpl(" 0."  , key));
362-  assert (! decimal.fromStringImpl(" 00"  , key));
396+  assert (decimal.fromStringImpl(" 00"  , key));
363397 assert (! decimal.fromStringImpl(" 0d"  , key));
364398 }
365399
366400 static  if  (maxSize64 ==  3 )
367401 version (mir_bignum_test)
368-  //   @safe pure nothrow @nogc
402+  @safe  pure  nothrow  @nogc 
369403 unittest 
370404 {
371405 import  mir.conv: to;
@@ -424,7 +458,7 @@ struct Decimal(size_t maxSize64)
424458 assert (decimal.fromStringImpl(" 4."  , key));
425459 assert (! decimal.fromStringImpl(" ."  , key));
426460 assert (decimal.fromStringImpl(" 0."  , key));
427-  assert (! decimal.fromStringImpl(" 00"  , key));
461+  assert (decimal.fromStringImpl(" 00"  , key));
428462 assert (! decimal.fromStringImpl(" 0d"  , key));
429463 }
430464
0 commit comments