github.com/chain5j/chain5j-pkg@v1.0.7/crypto/base/base36/base36.go (about)

     1  // Package base36
     2  //
     3  // @author: xwc1125
     4  package base36
     5  
     6  import (
     7  	"math"
     8  	"math/big"
     9  	"strings"
    10  )
    11  
    12  var (
    13  	base36 = []byte{
    14  		'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
    15  		'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
    16  		'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
    17  		'U', 'V', 'W', 'X', 'Y', 'Z'}
    18  	base36Lower = []byte{
    19  		'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
    20  		'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j',
    21  		'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't',
    22  		'u', 'v', 'w', 'x', 'y', 'z'}
    23  
    24  	index = map[byte]int{
    25  		'0': 0, '1': 1, '2': 2, '3': 3, '4': 4,
    26  		'5': 5, '6': 6, '7': 7, '8': 8, '9': 9,
    27  		'A': 10, 'B': 11, 'C': 12, 'D': 13, 'E': 14,
    28  		'F': 15, 'G': 16, 'H': 17, 'I': 18, 'J': 19,
    29  		'K': 20, 'L': 21, 'M': 22, 'N': 23, 'O': 24,
    30  		'P': 25, 'Q': 26, 'R': 27, 'S': 28, 'T': 29,
    31  		'U': 30, 'V': 31, 'W': 32, 'X': 33, 'Y': 34,
    32  		'Z': 35,
    33  		'a': 10, 'b': 11, 'c': 12, 'd': 13, 'e': 14,
    34  		'f': 15, 'g': 16, 'h': 17, 'i': 18, 'j': 19,
    35  		'k': 20, 'l': 21, 'm': 22, 'n': 23, 'o': 24,
    36  		'p': 25, 'q': 26, 'r': 27, 's': 28, 't': 29,
    37  		'u': 30, 'v': 31, 'w': 32, 'x': 33, 'y': 34,
    38  		'z': 35,
    39  	}
    40  )
    41  
    42  // Encode encodes a number to base36.
    43  func Encode(value uint64) string {
    44  	var res [16]byte
    45  	var i int
    46  	for i = len(res) - 1; ; i-- {
    47  		res[i] = base36[value%36]
    48  		value /= 36
    49  		if value == 0 {
    50  			break
    51  		}
    52  	}
    53  
    54  	return string(res[i:])
    55  }
    56  
    57  // Decode decodes a base36-encoded string.
    58  func Decode(s string) uint64 {
    59  	res := uint64(0)
    60  	l := len(s) - 1
    61  	for idx := range s {
    62  		c := s[l-idx]
    63  		res += uint64(index[c]) * uint64(math.Pow(36, float64(idx)))
    64  	}
    65  	return res
    66  }
    67  
    68  var bigRadix = big.NewInt(36)
    69  var bigZero = big.NewInt(0)
    70  
    71  // EncodeBytesAsBytes encodes a byte slice to base36.
    72  func EncodeBytesAsBytes(b []byte) []byte {
    73  	x := new(big.Int)
    74  	x.SetBytes(b)
    75  
    76  	answer := make([]byte, 0, len(b)*136/100)
    77  	for x.Cmp(bigZero) > 0 {
    78  		mod := new(big.Int)
    79  		x.DivMod(x, bigRadix, mod)
    80  		answer = append(answer, base36[mod.Int64()])
    81  	}
    82  
    83  	// leading zero bytes
    84  	for _, i := range b {
    85  		if i != 0 {
    86  			break
    87  		}
    88  		answer = append(answer, base36[0])
    89  	}
    90  
    91  	// reverse
    92  	alen := len(answer)
    93  	for i := 0; i < alen/2; i++ {
    94  		answer[i], answer[alen-1-i] = answer[alen-1-i], answer[i]
    95  	}
    96  
    97  	return answer
    98  }
    99  
   100  // EncodeBytes encodes a byte slice to base36 string.
   101  func EncodeBytes(b []byte) string {
   102  	return string(EncodeBytesAsBytes(b))
   103  }
   104  
   105  // DecodeToBytes decodes a base36 string to a byte slice, using alphabet.
   106  func DecodeToBytes(isUpper bool, b string) []byte {
   107  	alphabet := string(base36)
   108  	if !isUpper {
   109  		alphabet = string(base36Lower)
   110  	}
   111  	answer := big.NewInt(0)
   112  	j := big.NewInt(1)
   113  
   114  	for i := len(b) - 1; i >= 0; i-- {
   115  		tmp := strings.IndexAny(alphabet, string(b[i]))
   116  		if tmp == -1 {
   117  			return []byte("")
   118  		}
   119  		idx := big.NewInt(int64(tmp))
   120  		tmp1 := big.NewInt(0)
   121  		tmp1.Mul(j, idx)
   122  
   123  		answer.Add(answer, tmp1)
   124  		j.Mul(j, bigRadix)
   125  	}
   126  
   127  	tmpval := answer.Bytes()
   128  
   129  	var numZeros int
   130  	for numZeros = 0; numZeros < len(b); numZeros++ {
   131  		if b[numZeros] != alphabet[0] {
   132  			break
   133  		}
   134  	}
   135  	flen := numZeros + len(tmpval)
   136  	val := make([]byte, flen, flen)
   137  	copy(val[numZeros:], tmpval)
   138  
   139  	return val
   140  }