Skip to content

Commit

Permalink
Merge pull request #1171 Enable funlen linter (part 2) from brojeg/ma…
Browse files Browse the repository at this point in the history
…ster
  • Loading branch information
rekby authored Apr 24, 2024
2 parents 506a662 + 013a60c commit d063e33
Show file tree
Hide file tree
Showing 8 changed files with 605 additions and 111 deletions.
1 change: 1 addition & 0 deletions internal/allocator/allocator.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ func New() (v *Allocator) {
return allocatorPool.Get()
}

//nolint:funlen
func (a *Allocator) Free() {
a.valueAllocator.free()
a.typeAllocator.free()
Expand Down
168 changes: 109 additions & 59 deletions internal/decimal/decimal.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@ package decimal
import (
"math/big"
"math/bits"

"github.com/ydb-platform/ydb-go-sdk/v3/internal/xstring"
)

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

s, neg, specialValue := setSpecialValue(s, v)
if specialValue != nil {
return specialValue, nil
}
var err error
v, err = parseNumber(s, v, precision, scale, neg)
if err != nil {
return nil, err
}

return v, nil
}

func setSpecialValue(s string, v *big.Int) (string, bool, *big.Int) {
s, neg := parseSign(s)

return parseSpecialValue(s, neg, v)
}

func parseSign(s string) (string, bool) {
neg := s[0] == '-'
if neg || s[0] == '+' {
s = s[1:]
}

return s, neg
}

func parseSpecialValue(s string, neg bool, v *big.Int) (string, bool, *big.Int) {
if isInf(s) {
if neg {
return v.Set(neginf), nil
return s, neg, v.Set(neginf)
}

return v.Set(inf), nil
return s, neg, v.Set(inf)
}
if isNaN(s) {
if neg {
return v.Set(negnan), nil
return s, neg, v.Set(negnan)
}

return v.Set(nan), nil
return s, neg, v.Set(nan)
}

integral := precision - scale
return s, neg, nil
}

func parseNumber(s string, v *big.Int, precision, scale uint32, neg bool) (*big.Int, error) {
var err error
integral := precision - scale
var dot bool
for ; len(s) > 0; s = s[1:] {
c := s[0]
Expand All @@ -131,12 +158,10 @@ func Parse(s string, precision, scale uint32) (*big.Int, error) {

continue
}
if dot {
if scale > 0 {
scale--
} else {
break
}
if dot && scale > 0 {
scale--
} else if dot {
break
}

if !isDigit(c) {
Expand All @@ -155,30 +180,10 @@ func Parse(s string, precision, scale uint32) (*big.Int, error) {
}
integral--
}
//nolint:nestif
if len(s) > 0 { // Characters remaining.
c := s[0]
if !isDigit(c) {
return nil, syntaxError(s)
}
plus := c > '5'
if !plus && c == '5' {
var x big.Int
plus = x.And(v, one).Cmp(zero) != 0 // Last digit is not a zero.
for !plus && len(s) > 1 {
s = s[1:]
c := s[0]
if !isDigit(c) {
return nil, syntaxError(s)
}
plus = c != '0'
}
}
if plus {
v.Add(v, one)
if v.Cmp(pow(ten, precision)) >= 0 {
v.Set(inf)
}
v, err = handleRemainingDigits(s, v, precision)
if err != nil {
return nil, err
}
}
v.Mul(v, pow(ten, scale))
Expand All @@ -189,26 +194,54 @@ func Parse(s string, precision, scale uint32) (*big.Int, error) {
return v, nil
}

func handleRemainingDigits(s string, v *big.Int, precision uint32) (*big.Int, error) {
c := s[0]
if !isDigit(c) {
return nil, syntaxError(s)
}
plus := c > '5'
if !plus && c == '5' {
var x big.Int
plus = x.And(v, one).Cmp(zero) != 0 // Last digit is not a zero.
for !plus && len(s) > 1 {
s = s[1:]
c := s[0]
if !isDigit(c) {
return nil, syntaxError(s)
}
plus = c != '0'
}
}
if plus {
v.Add(v, one)
if v.Cmp(pow(ten, precision)) >= 0 {
v.Set(inf)
}
}

return v, nil
}

// Format returns the string representation of x with the given precision and
// scale.
func Format(x *big.Int, precision, scale uint32) string {
switch {
case x.CmpAbs(inf) == 0:
// Check for special values and nil pointer upfront.
if x == nil {
return "0"
}
if x.CmpAbs(inf) == 0 {
if x.Sign() < 0 {
return "-inf"
}

return "inf"

case x.CmpAbs(nan) == 0:
}
if x.CmpAbs(nan) == 0 {
if x.Sign() < 0 {
return "-nan"
}

return "nan"

case x == nil:
return "0"
}

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

digit.Mod(v, ten)
d := int(digit.Int64())
if d != 0 || scale == 0 || pos > 0 {
const numbers = "0123456789"
pos--
bts[pos] = numbers[d]

pos--
if d != 0 || scale == 0 || pos >= 0 {
setDigitAtPosition(bts, pos, d)
}

if scale > 0 {
scale--
if scale == 0 && pos > 0 {
bts[pos-1] = '.'
pos--
bts[pos] = '.'
}
}
}
if scale > 0 {
for ; scale > 0; scale-- {
if precision == 0 {
return errorTag
}
precision--
pos--
bts[pos] = '0'
}

for ; scale > 0; scale-- {
if precision == 0 {
pos = 0

break
}
precision--
pos--
bts[pos] = '.'
bts[pos] = '0'
}

if bts[pos] == '.' {
pos--
bts[pos] = '0'
}

if neg {
pos--
bts[pos] = '-'
}

return xstring.FromBytes(bts[pos:])
return string(bts[pos:])
}

func abs(x *big.Int) (*big.Int, bool) {
v := big.NewInt(0).Set(x)
neg := x.Sign() < 0
if neg {
// Convert negative to positive.
v.Neg(x)
}

return v, neg
}

func setDigitAtPosition(bts []byte, pos, digit int) {
const numbers = "0123456789"
bts[pos] = numbers[digit]
}

// BigIntToByte returns the 16-byte array representation of x.
Expand Down
Loading

0 comments on commit d063e33

Please sign in to comment.