github.com/cnboonhan/delve@v0.0.0-20230908061759-363f2388c2fb/pkg/dwarf/leb128/decode.go (about)

     1  package leb128
     2  
     3  import (
     4  	"io"
     5  )
     6  
     7  // Reader is a io.ByteReader with a Len method. This interface is
     8  // satisfied by both bytes.Buffer and bytes.Reader.
     9  type Reader interface {
    10  	io.ByteReader
    11  	io.Reader
    12  	Len() int
    13  }
    14  
    15  // DecodeUnsigned decodes an unsigned Little Endian Base 128
    16  // represented number.
    17  func DecodeUnsigned(buf Reader) (uint64, uint32) {
    18  	var (
    19  		result uint64
    20  		shift  uint64
    21  		length uint32
    22  	)
    23  
    24  	if buf.Len() == 0 {
    25  		return 0, 0
    26  	}
    27  
    28  	for {
    29  		b, err := buf.ReadByte()
    30  		if err != nil {
    31  			panic("Could not parse ULEB128 value")
    32  		}
    33  		length++
    34  
    35  		result |= uint64((uint(b) & 0x7f) << shift)
    36  
    37  		// If high order bit is 1.
    38  		if b&0x80 == 0 {
    39  			break
    40  		}
    41  
    42  		shift += 7
    43  	}
    44  
    45  	return result, length
    46  }
    47  
    48  // DecodeSigned decodes a signed Little Endian Base 128
    49  // represented number.
    50  func DecodeSigned(buf Reader) (int64, uint32) {
    51  	var (
    52  		b      byte
    53  		err    error
    54  		result int64
    55  		shift  uint64
    56  		length uint32
    57  	)
    58  
    59  	if buf.Len() == 0 {
    60  		return 0, 0
    61  	}
    62  
    63  	for {
    64  		b, err = buf.ReadByte()
    65  		if err != nil {
    66  			panic("Could not parse SLEB128 value")
    67  		}
    68  		length++
    69  
    70  		result |= int64((int64(b) & 0x7f) << shift)
    71  		shift += 7
    72  		if b&0x80 == 0 {
    73  			break
    74  		}
    75  	}
    76  
    77  	if (shift < 8*uint64(length)) && (b&0x40 > 0) {
    78  		result |= -(1 << shift)
    79  	}
    80  
    81  	return result, length
    82  }