OSDN Git Service

Merge branch 'dev' into wallet
[bytom/bytom.git] / common / bytes.go
1 // Copyright 2014 The go-ethereum Authors
2 // This file is part of the go-ethereum library.
3 //
4 // The go-ethereum library is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU Lesser General Public License as published by
6 // the Free Software Foundation, either version 3 of the License, or
7 // (at your option) any later version.
8 //
9 // The go-ethereum library is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU Lesser General Public License for more details.
13 //
14 // You should have received a copy of the GNU Lesser General Public License
15 // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
16
17 // Package common contains various helper functions.
18 package common
19
20 import (
21         "bytes"
22         "encoding/binary"
23         "encoding/hex"
24         log "github.com/sirupsen/logrus"
25         "math/big"
26         "strings"
27 )
28
29 func ToHex(b []byte) string {
30         hex := Bytes2Hex(b)
31         // Prefer output of "0x0" instead of "0x"
32         if len(hex) == 0 {
33                 hex = "0"
34         }
35         return "0x" + hex
36 }
37
38 func FromHex(s string) []byte {
39         if len(s) > 1 {
40                 if s[0:2] == "0x" {
41                         s = s[2:]
42                 }
43                 if len(s)%2 == 1 {
44                         s = "0" + s
45                 }
46                 return Hex2Bytes(s)
47         }
48         return nil
49 }
50
51 // Number to bytes
52 //
53 // Returns the number in bytes with the specified base
54 func NumberToBytes(num interface{}, bits int) []byte {
55         buf := new(bytes.Buffer)
56         err := binary.Write(buf, binary.BigEndian, num)
57         if err != nil {
58                 log.WithField("err", err).Error("NumberToBytes failed")
59         }
60
61         return buf.Bytes()[buf.Len()-(bits/8):]
62 }
63
64 // Bytes to number
65 //
66 // Attempts to cast a byte slice to a unsigned integer
67 func BytesToNumber(b []byte) uint64 {
68         var number uint64
69
70         // Make sure the buffer is 64bits
71         data := make([]byte, 8)
72         data = append(data[:len(b)], b...)
73
74         buf := bytes.NewReader(data)
75         err := binary.Read(buf, binary.BigEndian, &number)
76         if err != nil {
77                 log.WithField("err", err).Error("BytesToNumber failed")
78         }
79
80         return number
81 }
82
83 // Read variable int
84 //
85 // Read a variable length number in big endian byte order
86 func ReadVarInt(buff []byte) (ret uint64) {
87         switch l := len(buff); {
88         case l > 4:
89                 d := LeftPadBytes(buff, 8)
90                 binary.Read(bytes.NewReader(d), binary.BigEndian, &ret)
91         case l > 2:
92                 var num uint32
93                 d := LeftPadBytes(buff, 4)
94                 binary.Read(bytes.NewReader(d), binary.BigEndian, &num)
95                 ret = uint64(num)
96         case l > 1:
97                 var num uint16
98                 d := LeftPadBytes(buff, 2)
99                 binary.Read(bytes.NewReader(d), binary.BigEndian, &num)
100                 ret = uint64(num)
101         default:
102                 var num uint8
103                 binary.Read(bytes.NewReader(buff), binary.BigEndian, &num)
104                 ret = uint64(num)
105         }
106
107         return
108 }
109
110 // Copy bytes
111 //
112 // Returns an exact copy of the provided bytes
113 func CopyBytes(b []byte) (copiedBytes []byte) {
114         copiedBytes = make([]byte, len(b))
115         copy(copiedBytes, b)
116
117         return
118 }
119
120 func HasHexPrefix(str string) bool {
121         l := len(str)
122         return l >= 2 && str[0:2] == "0x"
123 }
124
125 func IsHex(str string) bool {
126         l := len(str)
127         return l >= 4 && l%2 == 0 && str[0:2] == "0x"
128 }
129
130 func Bytes2Hex(d []byte) string {
131         return hex.EncodeToString(d)
132 }
133
134 func Hex2Bytes(str string) []byte {
135         h, _ := hex.DecodeString(str)
136
137         return h
138 }
139
140 func Hex2BytesFixed(str string, flen int) []byte {
141         h, _ := hex.DecodeString(str)
142         if len(h) == flen {
143                 return h
144         } else {
145                 if len(h) > flen {
146                         return h[len(h)-flen : len(h)]
147                 } else {
148                         hh := make([]byte, flen)
149                         copy(hh[flen-len(h):flen], h[:])
150                         return hh
151                 }
152         }
153 }
154
155 func StringToByteFunc(str string, cb func(str string) []byte) (ret []byte) {
156         if len(str) > 1 && str[0:2] == "0x" && !strings.Contains(str, "\n") {
157                 ret = Hex2Bytes(str[2:])
158         } else {
159                 ret = cb(str)
160         }
161
162         return
163 }
164
165 func FormatData(data string) []byte {
166         if len(data) == 0 {
167                 return nil
168         }
169         // Simple stupid
170         d := new(big.Int)
171         if data[0:1] == "\"" && data[len(data)-1:] == "\"" {
172                 return RightPadBytes([]byte(data[1:len(data)-1]), 32)
173         } else if len(data) > 1 && data[:2] == "0x" {
174                 d.SetBytes(Hex2Bytes(data[2:]))
175         } else {
176                 d.SetString(data, 0)
177         }
178
179         return BigToBytes(d, 256)
180 }
181
182 func ParseData(data ...interface{}) (ret []byte) {
183         for _, item := range data {
184                 switch t := item.(type) {
185                 case string:
186                         var str []byte
187                         if IsHex(t) {
188                                 str = Hex2Bytes(t[2:])
189                         } else {
190                                 str = []byte(t)
191                         }
192
193                         ret = append(ret, RightPadBytes(str, 32)...)
194                 case []byte:
195                         ret = append(ret, LeftPadBytes(t, 32)...)
196                 }
197         }
198
199         return
200 }
201
202 func RightPadBytes(slice []byte, l int) []byte {
203         if l < len(slice) {
204                 return slice
205         }
206
207         padded := make([]byte, l)
208         copy(padded[0:len(slice)], slice)
209
210         return padded
211 }
212
213 func LeftPadBytes(slice []byte, l int) []byte {
214         if l < len(slice) {
215                 return slice
216         }
217
218         padded := make([]byte, l)
219         copy(padded[l-len(slice):], slice)
220
221         return padded
222 }
223
224 func LeftPadString(str string, l int) string {
225         if l < len(str) {
226                 return str
227         }
228
229         zeros := Bytes2Hex(make([]byte, (l-len(str))/2))
230
231         return zeros + str
232
233 }
234
235 func RightPadString(str string, l int) string {
236         if l < len(str) {
237                 return str
238         }
239
240         zeros := Bytes2Hex(make([]byte, (l-len(str))/2))
241
242         return str + zeros
243
244 }
245
246 func ToAddress(slice []byte) (addr []byte) {
247         if len(slice) < 20 {
248                 addr = LeftPadBytes(slice, 20)
249         } else if len(slice) > 20 {
250                 addr = slice[len(slice)-20:]
251         } else {
252                 addr = slice
253         }
254
255         addr = CopyBytes(addr)
256
257         return
258 }
259
260 func ByteSliceToInterface(slice [][]byte) (ret []interface{}) {
261         for _, i := range slice {
262                 ret = append(ret, i)
263         }
264
265         return
266 }