go - Variable length two's complement to int64 -


i'm attempting write go program parse ans.1 ber two's complement integer encoding. however, integer can have either 1, 2, 3 or 4 byte length encoding (depending on size).

according specification (http://www.itu.int/itu-t/studygroups/com17/languages/x.690-0207.pdf) leftmost bit complement.

what's clean way this?

func parseint(b []byte) (int64, error) {     switch len(b) {     case 1:         // works         return int64(b[0]&0x7f) - int64(b[0]&0x80), nil     case 2:         // left byte of b[0] -32768     case 3:         // left byte of b[0] -8388608     case 4:         // left byte of b[0] -2147483648 (and on 5, 6, 7, 8)     case 5:     case 6:     case 7:     case 8:     default:         return 0, errors.new("value not fit in int64")     } }   parseint([]byte{0xfe})       // should return (-2, nil) parseint([]byte{0xfe, 0xff}) // should return (-257, nil) parseint([]byte{0x01, 0x00}) // should return (256, nil) 

easier understand if read bytes end:

  • you don't have shift last byte
  • left-shift last byte 8 (8 bits in byte)
  • left-shift 2nd last byte 16
  • ...
  • and first byte use 7 bits, leftmost bit special.

the leftmost bit of first byte b[0]&080 tells if have add offset result. offset optionally added -1 multiplied number input mean having 1 bit set , others being 0, -1 * (1 << (len(b)*8 - 1)) = 0x80 << (len(b)*8 - 8).

examples. if input is...

  • 1 byte:
    int64(b[0]&0x7f) - int64(b[0]&0x80)
  • 2 bytes:
    int64(b[0]&0x7f)<<8 + int64(b[1]) - int64(b[0]&0x80)<<8
  • 3 bytes:
    int64(b[0]&0x7f)<<16 + int64(b[1])<<8 + int64(b[2]) - int64(b[0]&0x80)<<16

all these cases can covered nice loop.

here's compact implementation (try on go playground):

func parseint(b []byte) (int64, error) {     if len(b) > 8 {         return 0, errors.new("value not fit in int64")     }      var n int64     i, v := range b {         shift := uint((len(b) - - 1) * 8)         if == 0 && v&0x80 != 0 {             n -= 0x80 << shift             v &= 0x7f         }         n += int64(v) << shift     }     return n, nil } 

Comments

Popular posts from this blog

html - Firefox flex bug applied to buttons? -

html - Missing border-right in select on Firefox -

c# - two queries in same method -