Skip to content

Commit 98f87a5

Browse files
author
Roman Golov
committed
Revert decimal to latest working version.
1 parent 9d88fe4 commit 98f87a5

File tree

4 files changed

+147
-429
lines changed

4 files changed

+147
-429
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
* Fixed incorrect formatting of decimal. Implementation of decimal has been reverted to latest working version
2+
13
## v3.67.1
24
* Fixed race of stop internal processes on close topic writer
35
* Fixed goroutines leak within topic reader on network problems

internal/decimal/decimal.go

Lines changed: 59 additions & 111 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ package decimal
33
import (
44
"math/big"
55
"math/bits"
6+
7+
"github.com/ydb-platform/ydb-go-sdk/v3/internal/xstring"
68
)
79

810
const (
@@ -97,56 +99,27 @@ func Parse(s string, precision, scale uint32) (*big.Int, error) {
9799
return v, nil
98100
}
99101

100-
s, neg, specialValue := setSpecialValue(s, v)
101-
if specialValue != nil {
102-
return specialValue, nil
103-
}
104-
var err error
105-
v, err = parseNumber(s, v, precision, scale, neg)
106-
if err != nil {
107-
return nil, err
108-
}
109-
110-
return v, nil
111-
}
112-
113-
func setSpecialValue(s string, v *big.Int) (string, bool, *big.Int) {
114-
s, neg := parseSign(s)
115-
116-
return parseSpecialValue(s, neg, v)
117-
}
118-
119-
func parseSign(s string) (string, bool) {
120102
neg := s[0] == '-'
121103
if neg || s[0] == '+' {
122104
s = s[1:]
123105
}
124-
125-
return s, neg
126-
}
127-
128-
func parseSpecialValue(s string, neg bool, v *big.Int) (string, bool, *big.Int) {
129106
if isInf(s) {
130107
if neg {
131-
return s, neg, v.Set(neginf)
108+
return v.Set(neginf), nil
132109
}
133110

134-
return s, neg, v.Set(inf)
111+
return v.Set(inf), nil
135112
}
136113
if isNaN(s) {
137114
if neg {
138-
return s, neg, v.Set(negnan)
115+
return v.Set(negnan), nil
139116
}
140117

141-
return s, neg, v.Set(nan)
118+
return v.Set(nan), nil
142119
}
143120

144-
return s, neg, nil
145-
}
146-
147-
func parseNumber(s string, v *big.Int, precision, scale uint32, neg bool) (*big.Int, error) {
148-
var err error
149121
integral := precision - scale
122+
150123
var dot bool
151124
for ; len(s) > 0; s = s[1:] {
152125
c := s[0]
@@ -158,10 +131,12 @@ func parseNumber(s string, v *big.Int, precision, scale uint32, neg bool) (*big.
158131

159132
continue
160133
}
161-
if dot && scale > 0 {
162-
scale--
163-
} else if dot {
164-
break
134+
if dot {
135+
if scale > 0 {
136+
scale--
137+
} else {
138+
break
139+
}
165140
}
166141

167142
if !isDigit(c) {
@@ -180,10 +155,30 @@ func parseNumber(s string, v *big.Int, precision, scale uint32, neg bool) (*big.
180155
}
181156
integral--
182157
}
158+
//nolint:nestif
183159
if len(s) > 0 { // Characters remaining.
184-
v, err = handleRemainingDigits(s, v, precision)
185-
if err != nil {
186-
return nil, err
160+
c := s[0]
161+
if !isDigit(c) {
162+
return nil, syntaxError(s)
163+
}
164+
plus := c > '5'
165+
if !plus && c == '5' {
166+
var x big.Int
167+
plus = x.And(v, one).Cmp(zero) != 0 // Last digit is not a zero.
168+
for !plus && len(s) > 1 {
169+
s = s[1:]
170+
c := s[0]
171+
if !isDigit(c) {
172+
return nil, syntaxError(s)
173+
}
174+
plus = c != '0'
175+
}
176+
}
177+
if plus {
178+
v.Add(v, one)
179+
if v.Cmp(pow(ten, precision)) >= 0 {
180+
v.Set(inf)
181+
}
187182
}
188183
}
189184
v.Mul(v, pow(ten, scale))
@@ -194,56 +189,26 @@ func parseNumber(s string, v *big.Int, precision, scale uint32, neg bool) (*big.
194189
return v, nil
195190
}
196191

197-
func handleRemainingDigits(s string, v *big.Int, precision uint32) (*big.Int, error) {
198-
c := s[0]
199-
if !isDigit(c) {
200-
return nil, syntaxError(s)
201-
}
202-
plus := c > '5'
203-
if !plus && c == '5' {
204-
var x big.Int
205-
plus = x.And(v, one).Cmp(zero) != 0 // Last digit is not a zero.
206-
for !plus && len(s) > 1 {
207-
s = s[1:]
208-
c := s[0]
209-
if !isDigit(c) {
210-
return nil, syntaxError(s)
211-
}
212-
plus = c != '0'
213-
}
214-
}
215-
if plus {
216-
v.Add(v, one)
217-
if v.Cmp(pow(ten, precision)) >= 0 {
218-
v.Set(inf)
219-
}
220-
}
221-
222-
return v, nil
223-
}
224-
225192
// Format returns the string representation of x with the given precision and
226193
// scale.
227-
//
228-
//nolint:funlen
229194
func Format(x *big.Int, precision, scale uint32) string {
230-
// Check for special values and nil pointer upfront.
231-
if x == nil {
232-
return "0"
233-
}
234-
if x.CmpAbs(inf) == 0 {
195+
switch {
196+
case x.CmpAbs(inf) == 0:
235197
if x.Sign() < 0 {
236198
return "-inf"
237199
}
238200

239201
return "inf"
240-
}
241-
if x.CmpAbs(nan) == 0 {
202+
203+
case x.CmpAbs(nan) == 0:
242204
if x.Sign() < 0 {
243205
return "-nan"
244206
}
245207

246208
return "nan"
209+
210+
case x == nil:
211+
return "0"
247212
}
248213

249214
v := big.NewInt(0).Set(x)
@@ -267,59 +232,42 @@ func Format(x *big.Int, precision, scale uint32) string {
267232

268233
digit.Mod(v, ten)
269234
d := int(digit.Int64())
270-
271-
pos--
272-
if d != 0 || scale == 0 || pos >= 0 {
273-
setDigitAtPosition(bts, pos, d)
235+
if d != 0 || scale == 0 || pos > 0 {
236+
const numbers = "0123456789"
237+
pos--
238+
bts[pos] = numbers[d]
274239
}
275-
276240
if scale > 0 {
277241
scale--
278242
if scale == 0 && pos > 0 {
279-
bts[pos-1] = '.'
280243
pos--
244+
bts[pos] = '.'
281245
}
282246
}
283247
}
284-
285-
for ; scale > 0; scale-- {
286-
if precision == 0 {
287-
pos = 0
288-
289-
break
248+
if scale > 0 {
249+
for ; scale > 0; scale-- {
250+
if precision == 0 {
251+
return errorTag
252+
}
253+
precision--
254+
pos--
255+
bts[pos] = '0'
290256
}
291-
precision--
257+
292258
pos--
293-
bts[pos] = '0'
259+
bts[pos] = '.'
294260
}
295-
296261
if bts[pos] == '.' {
297262
pos--
298263
bts[pos] = '0'
299264
}
300-
301265
if neg {
302266
pos--
303267
bts[pos] = '-'
304268
}
305269

306-
return string(bts[pos:])
307-
}
308-
309-
func abs(x *big.Int) (*big.Int, bool) {
310-
v := big.NewInt(0).Set(x)
311-
neg := x.Sign() < 0
312-
if neg {
313-
// Convert negative to positive.
314-
v.Neg(x)
315-
}
316-
317-
return v, neg
318-
}
319-
320-
func setDigitAtPosition(bts []byte, pos, digit int) {
321-
const numbers = "0123456789"
322-
bts[pos] = numbers[digit]
270+
return xstring.FromBytes(bts[pos:])
323271
}
324272

325273
// BigIntToByte returns the 16-byte array representation of x.

0 commit comments

Comments
 (0)