Exemplo n.º 1
0
// EncodeDecimal encodes a decimal d into a byte slice which can be sorted lexicographically later.
// EncodeDecimal guarantees that the encoded value is in ascending order for comparison.
// Decimal encoding:
// EncodeInt    -> value sign
// EncodeInt    -> exp sign
// EncodeInt    -> exp value
// EncodeBytes  -> abs value bytes
func EncodeDecimal(b []byte, d mysql.Decimal) []byte {
	if d.Equals(mysql.ZeroDecimal) {
		return EncodeInt(b, zeroSign)
	}

	v := d.BigIntValue()
	valSign := codecSign(int64(v.Sign()))

	absVal := new(big.Int)
	absVal.Abs(v)

	value := []byte(absVal.String())

	// Trim right side "0", like "12.34000" -> "12.34" or "0.1234000" -> "0.1234".
	if d.Exponent() != 0 {
		value = bytes.TrimRight(value, "0")
	}

	// Get exp and value, format is "value":"exp".
	// like "12.34" -> "0.1234":"2".
	// like "-0.01234" -> "-0.1234":"-1".
	exp := int64(0)
	div := big.NewInt(10)
	for ; ; exp++ {
		if absVal.Sign() == 0 {
			break
		}
		absVal = absVal.Div(absVal, div)
	}

	expVal := exp + int64(d.Exponent())
	expSign := codecSign(expVal)

	// For negtive exp, do bit reverse for exp.
	// For negtive decimal, do bit reverse for exp and value.
	expVal = encodeExp(expVal, expSign, valSign)
	codecValue(value, valSign)

	r := EncodeInt(b, valSign)
	r = EncodeInt(r, expSign)
	r = EncodeInt(r, expVal)
	r = EncodeBytes(r, value)
	return r
}
Exemplo n.º 2
0
// EncodeDecimal encodes a decimal d into a byte slice which can be sorted lexicographically later.
// EncodeDecimal guarantees that the encoded value is in ascending order for comparison.
// Decimal encoding:
// Byte -> value sign
// EncodeInt -> exp value
// EncodeBytes -> abs value bytes
func EncodeDecimal(b []byte, d mysql.Decimal) []byte {
	if d.Equals(mysql.ZeroDecimal) {
		return append(b, byte(zeroSign))
	}

	v := d.BigIntValue()
	valSign := codecSign(int64(v.Sign()))

	absVal := new(big.Int)
	absVal.Abs(v)

	// Get exp and value, format is "value":"exp".
	// like "12.34" -> "0.1234":"2".
	// like "-0.01234" -> "-0.1234":"-1".
	exp := int64(0)
	div := big.NewInt(10)
	mod := big.NewInt(0)
	value := []byte{}
	for ; ; exp++ {
		if absVal.Sign() == 0 {
			break
		}

		mod.Mod(absVal, div)
		absVal.Div(absVal, div)
		value = append([]byte(strconv.Itoa(int(mod.Int64()))), value...)
	}

	value = bytes.TrimRight(value, "0")

	expVal := exp + int64(d.Exponent())
	if valSign == negativeSign {
		expVal = -expVal
	}

	b = append(b, byte(valSign))
	b = EncodeInt(b, expVal)
	if valSign == negativeSign {
		b = EncodeBytesDesc(b, value)
	} else {
		b = EncodeBytes(b, value)
	}
	return b
}