gitee.com/quant1x/gox@v1.7.6/fastjson/fastfloat.go (about) 1 package fastjson 2 3 import ( 4 "math" 5 "strconv" 6 ) 7 8 // ParseUint64BestEffort parses uint64 number s. 9 // 10 // It is equivalent to strconv.ParseUint(s, 10, 64), but is faster. 11 // 12 // 0 is returned if the number cannot be parsed. 13 func ParseUint64BestEffort(s string) uint64 { 14 if len(s) == 0 { 15 return 0 16 } 17 i := uint(0) 18 d := uint64(0) 19 j := i 20 for i < uint(len(s)) { 21 if s[i] >= '0' && s[i] <= '9' { 22 d = d*10 + uint64(s[i]-'0') 23 i++ 24 if i > 18 { 25 // The integer part may be out of range for uint64. 26 // Fall back to slow parsing. 27 dd, err := strconv.ParseUint(s, 10, 64) 28 if err != nil { 29 return 0 30 } 31 return dd 32 } 33 continue 34 } 35 break 36 } 37 if i <= j { 38 return 0 39 } 40 if i < uint(len(s)) { 41 // Unparsed tail left. 42 return 0 43 } 44 return d 45 } 46 47 // ParseInt64BestEffort parses int64 number s. 48 // 49 // It is equivalent to strconv.ParseInt(s, 10, 64), but is faster. 50 // 51 // 0 is returned if the number cannot be parsed. 52 func ParseInt64BestEffort(s string) int64 { 53 if len(s) == 0 { 54 return 0 55 } 56 i := uint(0) 57 minus := s[0] == '-' 58 if minus { 59 i++ 60 if i >= uint(len(s)) { 61 return 0 62 } 63 } 64 65 d := int64(0) 66 j := i 67 for i < uint(len(s)) { 68 if s[i] >= '0' && s[i] <= '9' { 69 d = d*10 + int64(s[i]-'0') 70 i++ 71 if i > 18 { 72 // The integer part may be out of range for int64. 73 // Fall back to slow parsing. 74 dd, err := strconv.ParseInt(s, 10, 64) 75 if err != nil { 76 return 0 77 } 78 return dd 79 } 80 continue 81 } 82 break 83 } 84 if i <= j { 85 return 0 86 } 87 if i < uint(len(s)) { 88 // Unparsed tail left. 89 return 0 90 } 91 if minus { 92 d = -d 93 } 94 return d 95 } 96 97 // ParseBestEffort parses floating-point number s. 98 // 99 // It is equivalent to strconv.ParseFloat(s, 64), but is faster. 100 // 101 // 0 is returned if the number cannot be parsed. 102 func ParseBestEffort(s string) float64 { 103 if len(s) == 0 { 104 return 0 105 } 106 i := uint(0) 107 minus := s[0] == '-' 108 if minus { 109 i++ 110 if i >= uint(len(s)) { 111 return 0 112 } 113 } 114 115 d := uint64(0) 116 j := i 117 for i < uint(len(s)) { 118 if s[i] >= '0' && s[i] <= '9' { 119 d = d*10 + uint64(s[i]-'0') 120 i++ 121 if i > 18 { 122 // The integer part may be out of range for uint64. 123 // Fall back to slow parsing. 124 f, err := strconv.ParseFloat(s, 64) 125 if err != nil && !math.IsInf(f, 0) { 126 return 0 127 } 128 return f 129 } 130 continue 131 } 132 break 133 } 134 if i <= j { 135 return 0 136 } 137 f := float64(d) 138 if i >= uint(len(s)) { 139 // Fast path - just integer. 140 if minus { 141 f = -f 142 } 143 return f 144 } 145 146 if s[i] == '.' { 147 // Parse fractional part. 148 i++ 149 if i >= uint(len(s)) { 150 return 0 151 } 152 fr := uint64(0) 153 j := i 154 for i < uint(len(s)) { 155 if s[i] >= '0' && s[i] <= '9' { 156 fr = fr*10 + uint64(s[i]-'0') 157 i++ 158 if i-j > 18 { 159 // The fractional part may be out of range for uint64. 160 // Fall back to standard parsing. 161 f, err := strconv.ParseFloat(s, 64) 162 if err != nil && !math.IsInf(f, 0) { 163 return 0 164 } 165 return f 166 } 167 continue 168 } 169 break 170 } 171 if i <= j { 172 return 0 173 } 174 f += float64(fr) / math.Pow10(int(i-j)) 175 if i >= uint(len(s)) { 176 // Fast path - parsed fractional number. 177 if minus { 178 f = -f 179 } 180 return f 181 } 182 } 183 if s[i] == 'e' || s[i] == 'E' { 184 // Parse exponent part. 185 i++ 186 if i >= uint(len(s)) { 187 return 0 188 } 189 expMinus := false 190 if s[i] == '+' || s[i] == '-' { 191 expMinus = s[i] == '-' 192 i++ 193 if i >= uint(len(s)) { 194 return 0 195 } 196 } 197 exp := int16(0) 198 j := i 199 for i < uint(len(s)) { 200 if s[i] >= '0' && s[i] <= '9' { 201 exp = exp*10 + int16(s[i]-'0') 202 i++ 203 if exp > 300 { 204 // The exponent may be too big for float64. 205 // Fall back to standard parsing. 206 f, err := strconv.ParseFloat(s, 64) 207 if err != nil && !math.IsInf(f, 0) { 208 return 0 209 } 210 return f 211 } 212 continue 213 } 214 break 215 } 216 if i <= j { 217 return 0 218 } 219 if expMinus { 220 exp = -exp 221 } 222 f *= math.Pow10(int(exp)) 223 if i >= uint(len(s)) { 224 if minus { 225 f = -f 226 } 227 return f 228 } 229 } 230 return 0 231 }