github.com/jonasnick/go-ethereum@v0.7.12-0.20150216215225-22176f05d387/ethutil/bytes.go (about)

     1  package ethutil
     2  
     3  import (
     4  	"bytes"
     5  	"encoding/binary"
     6  	"encoding/hex"
     7  	"fmt"
     8  	"math/big"
     9  	"strings"
    10  )
    11  
    12  type Bytes []byte
    13  
    14  func (self Bytes) String() string {
    15  	return string(self)
    16  }
    17  
    18  func DeleteFromByteSlice(s [][]byte, hash []byte) [][]byte {
    19  	for i, h := range s {
    20  		if bytes.Compare(h, hash) == 0 {
    21  			return append(s[:i:i], s[i+1:]...)
    22  		}
    23  	}
    24  
    25  	return s
    26  }
    27  
    28  // Number to bytes
    29  //
    30  // Returns the number in bytes with the specified base
    31  func NumberToBytes(num interface{}, bits int) []byte {
    32  	buf := new(bytes.Buffer)
    33  	err := binary.Write(buf, binary.BigEndian, num)
    34  	if err != nil {
    35  		fmt.Println("NumberToBytes failed:", err)
    36  	}
    37  
    38  	return buf.Bytes()[buf.Len()-(bits/8):]
    39  }
    40  
    41  // Bytes to number
    42  //
    43  // Attempts to cast a byte slice to a unsigned integer
    44  func BytesToNumber(b []byte) uint64 {
    45  	var number uint64
    46  
    47  	// Make sure the buffer is 64bits
    48  	data := make([]byte, 8)
    49  	data = append(data[:len(b)], b...)
    50  
    51  	buf := bytes.NewReader(data)
    52  	err := binary.Read(buf, binary.BigEndian, &number)
    53  	if err != nil {
    54  		fmt.Println("BytesToNumber failed:", err)
    55  	}
    56  
    57  	return number
    58  }
    59  
    60  // Read variable int
    61  //
    62  // Read a variable length number in big endian byte order
    63  func ReadVarInt(buff []byte) (ret uint64) {
    64  	switch l := len(buff); {
    65  	case l > 4:
    66  		d := LeftPadBytes(buff, 8)
    67  		binary.Read(bytes.NewReader(d), binary.BigEndian, &ret)
    68  	case l > 2:
    69  		var num uint32
    70  		d := LeftPadBytes(buff, 4)
    71  		binary.Read(bytes.NewReader(d), binary.BigEndian, &num)
    72  		ret = uint64(num)
    73  	case l > 1:
    74  		var num uint16
    75  		d := LeftPadBytes(buff, 2)
    76  		binary.Read(bytes.NewReader(d), binary.BigEndian, &num)
    77  		ret = uint64(num)
    78  	default:
    79  		var num uint8
    80  		binary.Read(bytes.NewReader(buff), binary.BigEndian, &num)
    81  		ret = uint64(num)
    82  	}
    83  
    84  	return
    85  }
    86  
    87  // Binary length
    88  //
    89  // Returns the true binary length of the given number
    90  func BinaryLength(num int) int {
    91  	if num == 0 {
    92  		return 0
    93  	}
    94  
    95  	return 1 + BinaryLength(num>>8)
    96  }
    97  
    98  // Copy bytes
    99  //
   100  // Returns an exact copy of the provided bytes
   101  func CopyBytes(b []byte) (copiedBytes []byte) {
   102  	copiedBytes = make([]byte, len(b))
   103  	copy(copiedBytes, b)
   104  
   105  	return
   106  }
   107  
   108  func IsHex(str string) bool {
   109  	l := len(str)
   110  	return l >= 4 && l%2 == 0 && str[0:2] == "0x"
   111  }
   112  
   113  func Bytes2Hex(d []byte) string {
   114  	return hex.EncodeToString(d)
   115  }
   116  
   117  func Hex2Bytes(str string) []byte {
   118  	h, _ := hex.DecodeString(str)
   119  
   120  	return h
   121  }
   122  
   123  func StringToByteFunc(str string, cb func(str string) []byte) (ret []byte) {
   124  	if len(str) > 1 && str[0:2] == "0x" && !strings.Contains(str, "\n") {
   125  		ret = Hex2Bytes(str[2:])
   126  	} else {
   127  		ret = cb(str)
   128  	}
   129  
   130  	return
   131  }
   132  
   133  func FormatData(data string) []byte {
   134  	if len(data) == 0 {
   135  		return nil
   136  	}
   137  	// Simple stupid
   138  	d := new(big.Int)
   139  	if data[0:1] == "\"" && data[len(data)-1:] == "\"" {
   140  		return RightPadBytes([]byte(data[1:len(data)-1]), 32)
   141  	} else if len(data) > 1 && data[:2] == "0x" {
   142  		d.SetBytes(Hex2Bytes(data[2:]))
   143  	} else {
   144  		d.SetString(data, 0)
   145  	}
   146  
   147  	return BigToBytes(d, 256)
   148  }
   149  
   150  func ParseData(data ...interface{}) (ret []byte) {
   151  	for _, item := range data {
   152  		switch t := item.(type) {
   153  		case string:
   154  			var str []byte
   155  			if IsHex(t) {
   156  				str = Hex2Bytes(t[2:])
   157  			} else {
   158  				str = []byte(t)
   159  			}
   160  
   161  			ret = append(ret, RightPadBytes(str, 32)...)
   162  		case []byte:
   163  			ret = append(ret, LeftPadBytes(t, 32)...)
   164  		}
   165  	}
   166  
   167  	return
   168  }
   169  
   170  func RightPadBytes(slice []byte, l int) []byte {
   171  	if l < len(slice) {
   172  		return slice
   173  	}
   174  
   175  	padded := make([]byte, l)
   176  	copy(padded[0:len(slice)], slice)
   177  
   178  	return padded
   179  }
   180  
   181  func LeftPadBytes(slice []byte, l int) []byte {
   182  	if l < len(slice) {
   183  		return slice
   184  	}
   185  
   186  	padded := make([]byte, l)
   187  	copy(padded[l-len(slice):], slice)
   188  
   189  	return padded
   190  }
   191  
   192  func LeftPadString(str string, l int) string {
   193  	if l < len(str) {
   194  		return str
   195  	}
   196  
   197  	zeros := Bytes2Hex(make([]byte, (l-len(str))/2))
   198  
   199  	return zeros + str
   200  
   201  }
   202  
   203  func RightPadString(str string, l int) string {
   204  	if l < len(str) {
   205  		return str
   206  	}
   207  
   208  	zeros := Bytes2Hex(make([]byte, (l-len(str))/2))
   209  
   210  	return str + zeros
   211  
   212  }
   213  
   214  func Address(slice []byte) (addr []byte) {
   215  	if len(slice) < 20 {
   216  		addr = LeftPadBytes(slice, 20)
   217  	} else if len(slice) > 20 {
   218  		addr = slice[len(slice)-20:]
   219  	} else {
   220  		addr = slice
   221  	}
   222  
   223  	addr = CopyBytes(addr)
   224  
   225  	return
   226  }
   227  
   228  func ByteSliceToInterface(slice [][]byte) (ret []interface{}) {
   229  	for _, i := range slice {
   230  		ret = append(ret, i)
   231  	}
   232  
   233  	return
   234  }