double.go (96 lines of code) (raw):

/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package hessian import ( "encoding/binary" "math" "strconv" ) import ( perrors "github.com/pkg/errors" ) ///////////////////////////////////////// // Double ///////////////////////////////////////// // # 64-bit IEEE double // ::= 'D' b7 b6 b5 b4 b3 b2 b1 b0 // ::= x5b # 0.0 // ::= x5c # 1.0 // ::= x5d b0 # byte cast to double (-128.0 to 127.0) // ::= x5e b1 b0 # short cast to double // ::= x5f b3 b2 b1 b0 # 32-bit float cast to double func encFloat(b []byte, v float64) []byte { fv := float64(int64(v)) if fv == v { iv := int64(v) switch iv { case 0: return encByte(b, BC_DOUBLE_ZERO) case 1: return encByte(b, BC_DOUBLE_ONE) } if iv >= -0x80 && iv < 0x80 { return encByte(b, BC_DOUBLE_BYTE, byte(iv)) } else if iv >= -0x8000 && iv < 0x8000 { return encByte(b, BC_DOUBLE_SHORT, byte(iv>>8), byte(iv)) } goto END } END: bits := math.Float64bits(v) return encByte(b, BC_DOUBLE, byte(bits>>56), byte(bits>>48), byte(bits>>40), byte(bits>>32), byte(bits>>24), byte(bits>>16), byte(bits>>8), byte(bits)) } func encFloat32(b []byte, v float32) []byte { fv := float32(int32(v)) if fv == v { iv := int32(v) switch iv { case 0: return encByte(b, BC_DOUBLE_ZERO) case 1: return encByte(b, BC_DOUBLE_ONE) } if iv >= -0x80 && iv < 0x80 { return encByte(b, BC_DOUBLE_BYTE, byte(iv)) } else if iv >= -0x8000 && iv < 0x8000 { return encByte(b, BC_DOUBLE_SHORT, byte(iv>>8), byte(iv)) } goto END } END: if float32(int32(v*1000)) == v*1000 { iv := int32(v * 1000) return encByte(b, BC_DOUBLE_MILL, byte(iv>>24), byte(iv>>16), byte(iv>>8), byte(iv)) } else { str := strconv.FormatFloat(float64(v), 'f', -1, 32) d, _ := strconv.ParseFloat(str, 64) bits := math.Float64bits(d) return encByte(b, BC_DOUBLE, byte(bits>>56), byte(bits>>48), byte(bits>>40), byte(bits>>32), byte(bits>>24), byte(bits>>16), byte(bits>>8), byte(bits)) } } ///////////////////////////////////////// // Double ///////////////////////////////////////// // # 64-bit IEEE double // ::= 'D' b7 b6 b5 b4 b3 b2 b1 b0 // ::= x5b # 0.0 // ::= x5c # 1.0 // ::= x5d b0 # byte cast to double (-128.0 to 127.0) // ::= x5e b1 b0 # short cast to double // ::= x5f b3 b2 b1 b0 # 32-bit float cast to double func (d *Decoder) decDouble(flag int32) (interface{}, error) { var ( err error tag byte ) if flag != TAG_READ { tag = byte(flag) } else { tag, _ = d.ReadByte() } switch tag { case BC_LONG_INT: return d.decInt32(TAG_READ) case BC_DOUBLE_ZERO: return float64(0), nil case BC_DOUBLE_ONE: return float64(1), nil case BC_DOUBLE_BYTE: var i8 int8 err = binary.Read(d.reader, binary.BigEndian, &i8) return float64(i8), perrors.WithStack(err) case BC_DOUBLE_SHORT: var i16 int16 err = binary.Read(d.reader, binary.BigEndian, &i16) return float64(i16), perrors.WithStack(err) case BC_DOUBLE_MILL: var i32 int32 err = binary.Read(d.reader, binary.BigEndian, &i32) return float64(i32) / 1000, perrors.WithStack(err) case BC_DOUBLE: var f64 float64 err = binary.Read(d.reader, binary.BigEndian, &f64) return f64, perrors.WithStack(err) } return nil, perrors.Errorf("decDouble parse double wrong tag:%d-%#x", int(tag), tag) }