示例#1
0
文件: argo.go 项目: nuin/ampify
func writeBigInt(value *big.Int, buffer *bytes.Buffer, cutoff *big.Int) (positive bool) {
	if value.IsZero() {
		buffer.Write(zeroBase)
		return !value.RawNeg()
	}
	if !value.RawNeg() {
		positive = true
		if value.Cmp(cutoff) == -1 {
			encoding := []byte{'\x80', '\x01', '\x01'}
			mod := big.NewInt(0)
			div, mod := value.DivMod(value, bigint255, mod)
			encoding[2] = byte(mod.Int64()) + 1
			if div.Sign() == 1 {
				div, mod = div.DivMod(div, bigint255, mod)
				encoding[1] = byte(mod.Int64()) + 1
				if div.Sign() == 1 {
					encoding[0] = byte(div.Int64()) + 128
				}
			}
			buffer.Write(encoding)
		} else {
			value = value.Sub(value, cutoff)
			buffer.WriteByte('\xff')
			left := big.NewInt(0)
			lead, left := value.DivMod(value, bigint255, left)
			var n int64 = 1
			exp := big.NewInt(0)
			div := big.NewInt(0)
			for (div.Div(lead, exp.Exp(big.NewInt(253), big.NewInt(n), nil))).Sign() == 1 {
				n += 1
			}
			buffer.WriteByte(byte(n) + 1)
			buffer.WriteByte('\xff')
			leadChars := make([]byte, 0)
			mod := big.NewInt(0)
			for {
				if lead.IsZero() {
					break
				}
				lead, mod = lead.DivMod(lead, bigint253, mod)
				leadChars = append(leadChars, byte(mod.Int64())+2)
			}
			lenLead := len(leadChars)
			if lenLead > 0 {
				for i := lenLead - 1; i >= 0; i-- {
					buffer.WriteByte(leadChars[i])
				}
			}
			if left.Sign() == 1 {
				buffer.WriteByte('\x01')
				buffer.WriteByte(byte(left.Int64()))
			}
		}
	} else {
		value = value.Neg(value)
		if value.Cmp(cutoff) == -1 {
			encoding := []byte{'\x7f', '\xfe', '\xfe'}
			mod := big.NewInt(0)
			div, mod := value.DivMod(value, bigint255, mod)
			encoding[2] = 254 - byte(mod.Int64())
			if div.Sign() == 1 {
				div, mod = div.DivMod(div, bigint255, mod)
				encoding[1] = 254 - byte(mod.Int64())
				if div.Sign() == 1 {
					encoding[0] = 127 - byte(div.Int64())
				}
			}
			buffer.Write(encoding)
		} else {
			value = value.Sub(value, cutoff)
			buffer.WriteByte('\x00')
			left := big.NewInt(0)
			lead, left := value.DivMod(value, bigint254, left)
			var n int64 = 1
			exp := big.NewInt(0)
			div := big.NewInt(0)
			for (div.Div(lead, exp.Exp(big.NewInt(253), big.NewInt(n), nil))).Sign() == 1 {
				n += 1
			}
			buffer.WriteByte(254 - byte(n))
			buffer.WriteByte('\x00')
			leadChars := make([]byte, 0)
			mod := big.NewInt(0)
			for {
				if lead.IsZero() {
					break
				}
				lead, mod = lead.DivMod(lead, bigint253, mod)
				leadChars = append(leadChars, byte(253-mod.Int64()))
			}
			lenLead := len(leadChars)
			if lenLead > 0 {
				for i := lenLead - 1; i >= 0; i-- {
					buffer.WriteByte(leadChars[i])
				}
			}
			if lenLead > 1 {
				buffer.WriteByte('\x00')
			}
			buffer.WriteByte('\xfe')
			if left.Sign() == 1 {
				buffer.WriteByte('\x01')
				buffer.WriteByte(254 - byte(left.Int64()))
			} else {
				buffer.WriteByte('\xfe')
			}
		}
	}
	return
}