@@ -49,26 +49,34 @@ func NewFromInt(i int64) Decimal {
4949 return Decimal (i ) * scaleFactor
5050}
5151
52+ var errEmpty = errors .New ("empty string" )
53+ var errTooBig = errors .New ("number too big" )
54+ var errInvalid = errors .New ("invalid syntax" )
55+
5256// atoi64 is equivalent to strconv.Atoi
5357func atoi64 (s string ) (bool , int64 , error ) {
5458 sLen := len (s )
55- if sLen < 1 || sLen > 18 {
56- return false , 0 , errors .New ("atoi failed" )
59+ if sLen < 1 {
60+ return false , 0 , errEmpty
61+ }
62+ if sLen > 18 {
63+ return false , 0 , errTooBig
5764 }
65+
5866 neg := false
5967 if s [0 ] == '-' {
6068 neg = true
6169 s = s [1 :]
6270 if len (s ) < 1 {
63- return false , 0 , errors . New ( "atoi failed" )
71+ return neg , 0 , errEmpty
6472 }
6573 }
6674
6775 var n int64
6876 for _ , ch := range []byte (s ) {
6977 ch -= '0'
7078 if ch > 9 {
71- return false , 0 , errors . New ( "atoi failed" )
79+ return neg , 0 , errInvalid
7280 }
7381 n = n * 10 + int64 (ch )
7482 }
@@ -82,21 +90,15 @@ func atoi64(s string) (bool, int64, error) {
8290// error if integer parsing fails.
8391func NewFromString (s string ) (Decimal , error ) {
8492 if whole , frac , split := strings .Cut (s , "." ); split {
85- var neg bool
86- var w int64
87- if whole == "-" {
88- neg = true
89- } else if whole != "" {
90- var err error
91- neg , w , err = atoi64 (whole )
92- if err != nil {
93- return Zero , err
94- }
93+ neg , w , err := atoi64 (whole )
94+ // if fractional portion exists, whole part can be empty
95+ if err != nil && err != errEmpty {
96+ return Zero , err
9597 }
9698
9799 // overflow
98100 if w > parseMax || w < parseMin {
99- return Zero , errors . New ( "number too big" )
101+ return Zero , errTooBig
100102 }
101103 w = w * int64 (scaleFactor )
102104
@@ -106,7 +108,7 @@ func NewFromString(s string) (Decimal, error) {
106108 for _ , b := range frac {
107109 f *= 10
108110 if b < '0' || b > '9' {
109- return Zero , errors . New ( "invalid syntax" )
111+ return Zero , errInvalid
110112 }
111113 f += int64 (b - '0' )
112114 seen ++
@@ -126,7 +128,7 @@ func NewFromString(s string) (Decimal, error) {
126128 } else {
127129 _ , i , err := atoi64 (s )
128130 if i > parseMax || i < parseMin {
129- return Zero , errors . New ( "number too big" )
131+ return Zero , errTooBig
130132 }
131133 i = i * int64 (scaleFactor )
132134 return Decimal (i ), err
0 commit comments