@@ -39,51 +39,71 @@ bool bc_str2num(bc_num *num, char *str, size_t scale)
39
39
{
40
40
size_t digits = 0 ;
41
41
size_t strscale = 0 ;
42
- char * ptr , * nptr ;
43
- size_t trailing_zeros = 0 ;
42
+ char * ptr , * nptr , * integer_ptr , * integer_end , * fractional_ptr = NULL , * fractional_end = NULL , * decimal_point ;
44
43
bool zero_int = false;
44
+ size_t len = strlen (str );
45
+ sign num_sign = PLUS ;
45
46
46
47
/* Prepare num. */
47
48
bc_free_num (num );
48
49
49
50
/* Check for valid number and count digits. */
50
51
ptr = str ;
51
52
52
- if (( * ptr == '+' ) || ( * ptr == '-' ) ) {
53
+ if (* ptr == '+' ) {
53
54
/* Skip Sign */
54
55
ptr ++ ;
56
+ } else if (* ptr == '-' ) {
57
+ /* Skip Sign */
58
+ num_sign = MINUS ;
59
+ ptr ++ ;
55
60
}
61
+
56
62
/* Skip leading zeros. */
57
63
while (* ptr == '0' ) {
58
64
ptr ++ ;
59
65
}
60
- /* digits before the decimal point */
66
+ integer_ptr = ptr ;
67
+
68
+ /* Count digits. */
61
69
while (* ptr >= '0' && * ptr <= '9' ) {
62
70
ptr ++ ;
63
71
digits ++ ;
64
72
}
65
73
/* decimal point */
66
- if (* ptr == '.' ) {
67
- ptr ++ ;
74
+ decimal_point = (* ptr == '.' ) ? ptr : NULL ;
75
+
76
+ /* If a string other than numbers exists */
77
+ if (!decimal_point && * ptr != '\0' ) {
78
+ goto fail ;
68
79
}
69
- /* digits after the decimal point */
70
- while (* ptr >= '0' && * ptr <= '9' ) {
71
- if (* ptr == '0' ) {
72
- trailing_zeros ++ ;
73
- } else {
74
- trailing_zeros = 0 ;
80
+
81
+ /* search and validate fractional end if exists */
82
+ if (decimal_point ) {
83
+ /* search */
84
+ fractional_ptr = decimal_point + 1 ;
85
+ fractional_end = str + len - 1 ;
86
+ bool has_trailing_zero = false;
87
+ while (* fractional_end == '0' && fractional_end >= fractional_ptr ) {
88
+ fractional_end -- ;
89
+ has_trailing_zero = true;
90
+ }
91
+ if (has_trailing_zero ) {
92
+ fractional_end ++ ;
75
93
}
76
- ptr ++ ;
77
- strscale ++ ;
78
- }
79
94
80
- if (trailing_zeros > 0 ) {
81
- /* Trailing zeros should not take part in the computation of the overall scale, as it is pointless. */
82
- strscale = strscale - trailing_zeros ;
95
+ /* validate */
96
+ strscale = fractional_end - fractional_ptr ;
97
+ if (strspn (fractional_ptr , "0123456789" ) < strscale ) {
98
+ /* invalid num */
99
+ * num = bc_copy_num (BCG (_zero_ ));
100
+ return false;
101
+ }
83
102
}
84
- if ((* ptr != '\0' ) || (digits + strscale == 0 )) {
103
+
104
+ if (digits + strscale == 0 ) {
85
105
* num = bc_copy_num (BCG (_zero_ ));
86
- return * ptr == '\0' ;
106
+ return true ;
87
107
}
88
108
89
109
/* Adjust numbers and allocate storage and initialize fields. */
@@ -92,42 +112,39 @@ bool bc_str2num(bc_num *num, char *str, size_t scale)
92
112
zero_int = true;
93
113
digits = 1 ;
94
114
}
95
- * num = bc_new_num (digits , strscale );
96
115
97
- /* Build the whole number. */
98
- ptr = str ;
99
- if (* ptr == '-' ) {
100
- (* num )-> n_sign = MINUS ;
101
- ptr ++ ;
102
- } else {
103
- (* num )-> n_sign = PLUS ;
104
- if (* ptr == '+' ) ptr ++ ;
105
- }
106
- /* Skip leading zeros. */
107
- while (* ptr == '0' ) {
108
- ptr ++ ;
109
- }
116
+ * num = bc_new_num (digits , strscale );
117
+ (* num )-> n_sign = num_sign ;
110
118
nptr = (* num )-> n_value ;
111
- if (zero_int ) {
112
- * nptr ++ = 0 ;
113
- digits = 0 ;
114
- }
115
- for (; digits > 0 ; digits -- ) {
116
- * nptr ++ = CH_VAL (* ptr ++ );
117
- }
118
119
119
- /* Build the fractional part. */
120
- if (strscale > 0 ) {
121
- /* skip the decimal point! */
122
- ptr ++ ;
123
- for (; strscale > 0 ; strscale -- ) {
124
- * nptr ++ = CH_VAL (* ptr ++ );
120
+ if (zero_int ) {
121
+ nptr ++ ;
122
+ if (decimal_point ) {
123
+ while (fractional_ptr <= fractional_end ) {
124
+ * nptr = CH_VAL (* fractional_ptr );
125
+ nptr ++ ;
126
+ fractional_ptr ++ ;
127
+ }
128
+ }
129
+ } else {
130
+ integer_end = integer_ptr + digits - 1 ;
131
+ while (integer_ptr <= integer_end ) {
132
+ * nptr = CH_VAL (* integer_ptr );
133
+ nptr ++ ;
134
+ integer_ptr ++ ;
135
+ }
136
+ if (decimal_point ) {
137
+ while (fractional_ptr <= fractional_end ) {
138
+ * nptr = CH_VAL (* fractional_ptr );
139
+ nptr ++ ;
140
+ fractional_ptr ++ ;
141
+ }
125
142
}
126
- }
127
-
128
- if (bc_is_zero (* num )) {
129
- (* num )-> n_sign = PLUS ;
130
143
}
131
144
132
145
return true;
146
+
147
+ fail :
148
+ * num = bc_copy_num (BCG (_zero_ ));
149
+ return false;
133
150
}
0 commit comments