github.com/avence12/go-ethereum@v1.5.10-0.20170320123548-1dfd65f6d047/trie/encoding.go (about) 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 trie 18 19 func compactEncode(hexSlice []byte) []byte { 20 terminator := byte(0) 21 if hexSlice[len(hexSlice)-1] == 16 { 22 terminator = 1 23 hexSlice = hexSlice[:len(hexSlice)-1] 24 } 25 var ( 26 odd = byte(len(hexSlice) % 2) 27 buflen = len(hexSlice)/2 + 1 28 bi, hi = 0, 0 // indices 29 hs = byte(0) // shift: flips between 0 and 4 30 ) 31 if odd == 0 { 32 bi = 1 33 hs = 4 34 } 35 buf := make([]byte, buflen) 36 buf[0] = terminator<<5 | byte(odd)<<4 37 for bi < len(buf) && hi < len(hexSlice) { 38 buf[bi] |= hexSlice[hi] << hs 39 if hs == 0 { 40 bi++ 41 } 42 hi, hs = hi+1, hs^(1<<2) 43 } 44 return buf 45 } 46 47 func compactDecode(str []byte) []byte { 48 base := compactHexDecode(str) 49 base = base[:len(base)-1] 50 if base[0] >= 2 { 51 base = append(base, 16) 52 } 53 if base[0]%2 == 1 { 54 base = base[1:] 55 } else { 56 base = base[2:] 57 } 58 return base 59 } 60 61 func compactHexDecode(str []byte) []byte { 62 l := len(str)*2 + 1 63 var nibbles = make([]byte, l) 64 for i, b := range str { 65 nibbles[i*2] = b / 16 66 nibbles[i*2+1] = b % 16 67 } 68 nibbles[l-1] = 16 69 return nibbles 70 } 71 72 // compactHexEncode encodes a series of nibbles into a byte array 73 func compactHexEncode(nibbles []byte) []byte { 74 nl := len(nibbles) 75 if nl == 0 { 76 return nil 77 } 78 if nibbles[nl-1] == 16 { 79 nl-- 80 } 81 l := (nl + 1) / 2 82 var str = make([]byte, l) 83 for i := range str { 84 b := nibbles[i*2] * 16 85 if nl > i*2 { 86 b += nibbles[i*2+1] 87 } 88 str[i] = b 89 } 90 return str 91 } 92 93 func decodeCompact(key []byte) []byte { 94 l := len(key) / 2 95 var res = make([]byte, l) 96 for i := 0; i < l; i++ { 97 v1, v0 := key[2*i], key[2*i+1] 98 res[i] = v1*16 + v0 99 } 100 return res 101 } 102 103 // prefixLen returns the length of the common prefix of a and b. 104 func prefixLen(a, b []byte) int { 105 var i, length = 0, len(a) 106 if len(b) < length { 107 length = len(b) 108 } 109 for ; i < length; i++ { 110 if a[i] != b[i] { 111 break 112 } 113 } 114 return i 115 } 116 117 func hasTerm(s []byte) bool { 118 return s[len(s)-1] == 16 119 } 120 121 func remTerm(s []byte) []byte { 122 if hasTerm(s) { 123 b := make([]byte, len(s)-1) 124 copy(b, s) 125 return b 126 } 127 return s 128 }