@@ -108,6 +108,11 @@ enum ParseState
108108 LeadingWhite ,
109109 Sign ,
110110 Number ,
111+ DecimalPoint ,
112+ FractionNumber ,
113+ Exponent ,
114+ ExponentSign ,
115+ ExponentValue ,
111116 TrailingWhite
112117 }
113118
@@ -125,6 +130,9 @@ enum ParseState
125130
126131 private static ulong ParseUnsignedInteger ( StringSegment value , ulong maxValue )
127132 {
133+ if ( value . Length == 0 )
134+ throw new FormatException ( "Input string was not in a correct format" ) ;
135+
128136 ulong result = 0 ;
129137 int i = 0 ;
130138 var state = ParseState . LeadingWhite ;
@@ -194,9 +202,11 @@ private static ulong ParseUnsignedInteger(StringSegment value, ulong maxValue)
194202 return result ;
195203 }
196204
197-
198205 private static long ParseSignedInteger ( StringSegment value , long maxValue , long minValue )
199206 {
207+ if ( value . Length == 0 )
208+ throw new FormatException ( "Input string was not in a correct format" ) ;
209+
200210 long result = 0 ;
201211 int i = 0 ;
202212 var state = ParseState . LeadingWhite ;
@@ -215,7 +225,7 @@ private static long ParseSignedInteger(StringSegment value, long maxValue, long
215225 } else if ( c == '-' )
216226 {
217227 negative = true ;
218- state = ParseState . Number ;
228+ state = ParseState . Sign ;
219229 i ++ ;
220230 } else if ( c == '0' )
221231 {
@@ -231,6 +241,21 @@ private static long ParseSignedInteger(StringSegment value, long maxValue, long
231241 throw new FormatException ( "Input string was not in a correct format" ) ;
232242 }
233243 break ;
244+ case ParseState . Sign :
245+ if ( c == '0' )
246+ {
247+ state = ParseState . TrailingWhite ;
248+ i ++ ;
249+ } else if ( c > '0' && c <= '9' )
250+ {
251+ result = - ( c - '0' ) ;
252+ state = ParseState . Number ;
253+ i ++ ;
254+ } else
255+ {
256+ throw new FormatException ( "Input string was not in a correct format" ) ;
257+ }
258+ break ;
234259 case ParseState . Number :
235260 if ( c >= '0' && c <= '9' )
236261 {
@@ -278,5 +303,183 @@ private static long ParseSignedInteger(StringSegment value, long maxValue, long
278303 return result ;
279304 }
280305
306+ public static decimal ParseDecimal ( this StringSegment value , bool allowThousands = false )
307+ {
308+ if ( value . Length == 0 )
309+ throw new FormatException ( "Input string was not in a correct format" ) ;
310+
311+ decimal result = 0 ;
312+ int i = 0 ;
313+ var state = ParseState . LeadingWhite ;
314+ bool negative = false ;
315+ bool noIntegerPart = false ;
316+ decimal fraction = 0.1m ;
317+
318+ while ( i < value . Length )
319+ {
320+ var c = value . GetChar ( i ) ;
321+
322+ switch ( state )
323+ {
324+ case ParseState . LeadingWhite :
325+ if ( Char . IsWhiteSpace ( c ) )
326+ {
327+ i ++ ;
328+ }
329+ else if ( c == '-' )
330+ {
331+ negative = true ;
332+ state = ParseState . Sign ;
333+ i ++ ;
334+ } else if ( c == '.' )
335+ {
336+ noIntegerPart = true ;
337+ state = ParseState . FractionNumber ;
338+ i ++ ;
339+
340+ if ( i == value . Length )
341+ {
342+ throw new FormatException ( "Input string was not in a correct format" ) ;
343+ }
344+ }
345+ else if ( c == '0' )
346+ {
347+ state = ParseState . DecimalPoint ;
348+ i ++ ;
349+ }
350+ else if ( c > '0' && c <= '9' )
351+ {
352+ result = ( c - '0' ) ;
353+ state = ParseState . Number ;
354+ i ++ ;
355+ }
356+ else
357+ {
358+ throw new FormatException ( "Input string was not in a correct format" ) ;
359+ }
360+ break ;
361+ case ParseState . Sign :
362+ if ( c == '.' )
363+ {
364+ noIntegerPart = true ;
365+ state = ParseState . FractionNumber ;
366+ i ++ ;
367+
368+ if ( i == value . Length )
369+ {
370+ throw new FormatException ( "Input string was not in a correct format" ) ;
371+ }
372+ } else if ( c == '0' )
373+ {
374+ state = ParseState . DecimalPoint ;
375+ i ++ ;
376+ }
377+ else if ( c > '0' && c <= '9' )
378+ {
379+ result = - ( c - '0' ) ;
380+ state = ParseState . Number ;
381+ i ++ ;
382+ }
383+ else
384+ {
385+ throw new FormatException ( "Input string was not in a correct format" ) ;
386+ }
387+ break ;
388+ case ParseState . Number :
389+ if ( c == '.' )
390+ {
391+ state = ParseState . FractionNumber ;
392+ i ++ ;
393+ } else if ( c >= '0' && c <= '9' )
394+ {
395+ checked
396+ {
397+ result = negative
398+ ? 10 * result - ( c - '0' )
399+ : 10 * result + ( c - '0' ) ;
400+ }
401+ i ++ ;
402+ }
403+ else if ( Char . IsWhiteSpace ( c ) )
404+ {
405+ state = ParseState . TrailingWhite ;
406+ i ++ ;
407+ }
408+ else
409+ {
410+ throw new FormatException ( "Input string was not in a correct format" ) ;
411+ }
412+ break ;
413+ case ParseState . DecimalPoint :
414+ if ( c == '.' )
415+ {
416+ state = ParseState . FractionNumber ;
417+ i ++ ;
418+ } else
419+ {
420+ throw new FormatException ( "Input string was not in a correct format" ) ;
421+ }
422+ break ;
423+ case ParseState . FractionNumber :
424+ if ( Char . IsWhiteSpace ( c ) )
425+ {
426+ if ( noIntegerPart )
427+ throw new FormatException ( "Input string was not in a correct format" ) ;
428+ state = ParseState . TrailingWhite ;
429+ i ++ ;
430+ } else if ( c == 'e' || c == 'E' )
431+ {
432+ if ( noIntegerPart && fraction == 0.1m )
433+ throw new FormatException ( "Input string was not in a correct format" ) ;
434+ state = ParseState . Exponent ;
435+ i ++ ;
436+ } else if ( c >= '0' && c <= '9' )
437+ {
438+ checked
439+ {
440+ result = negative
441+ ? result - fraction * ( c - '0' )
442+ : result + fraction * ( c - '0' ) ;
443+ fraction *= 0.1m ;
444+ }
445+ i ++ ;
446+ } else
447+ {
448+ throw new FormatException ( "Input string was not in a correct format" ) ;
449+ }
450+ break ;
451+ case ParseState . Exponent :
452+ if ( c == '-' || ( c >= '0' && c <= '9' ) )
453+ {
454+ int exp = value . Subsegment ( i , value . Length - i ) . ParseInt16 ( ) ;
455+ checked
456+ {
457+ result *= ( decimal ) Math . Pow ( 10.0 , exp ) ;
458+ }
459+
460+ //set i to end of string, because ParseInt16 eats number and all trailing whites
461+ i = value . Length ;
462+ } else
463+ {
464+ throw new FormatException ( "Input string was not in a correct format" ) ;
465+ }
466+ break ;
467+ case ParseState . TrailingWhite :
468+ if ( Char . IsWhiteSpace ( c ) )
469+ {
470+ state = ParseState . TrailingWhite ;
471+ i ++ ;
472+ }
473+ else
474+ {
475+ throw new FormatException ( "Input string was not in a correct format" ) ;
476+ }
477+ break ;
478+ }
479+ }
480+
481+ return result ;
482+ }
483+
281484 }
282485}
0 commit comments