diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..723ef36 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.idea \ No newline at end of file diff --git a/README.md b/README.md index 7fa76fd..5987836 100644 --- a/README.md +++ b/README.md @@ -1 +1,8 @@ # lz-string-go + +Golang implementation of the [LZ-based compression algorithm](https://www.npmjs.com/package/lz-string). + +## Improvements +- [Performance problems](https://github.com/austinh115/lz-string-go/issues/5) | [PR](https://github.com/austinh115/lz-string-go/pull/6) + - Performance optimizations have been made to this library + - Decompression support for drop characters \ No newline at end of file diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..82320b1 --- /dev/null +++ b/go.mod @@ -0,0 +1,3 @@ +module lz-string-go + +go 1.16 diff --git a/lz-string.go b/lz-string.go index 7efa1c1..a31174f 100644 --- a/lz-string.go +++ b/lz-string.go @@ -3,22 +3,25 @@ package LZString import ( "errors" "math" + "strings" + "sync" "unicode/utf8" ) // Compress +const _defaultKeyStrBase64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=" -var keyStrBase64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=" - -func CompressToBase64(uncompressed string) string { +func Compress(uncompressed string, keyStrBase64 string) string { if len(uncompressed) == 0 { return "" } - - res := Compress(uncompressed, 6, func(character int) string { - return string([]rune(keyStrBase64)[character]) + if keyStrBase64 == "" { + keyStrBase64 = _defaultKeyStrBase64 + } + charArr := []rune(keyStrBase64) + res := _compress(uncompressed, 6, func(character int) string { + return string(charArr[character]) }) - switch len(res) % 4 { default: case 0: @@ -33,7 +36,7 @@ func CompressToBase64(uncompressed string) string { return res } -func Compress(uncompressed string, bitsPerChar int, getCharFromInt func(character int) string) string { +func _compress(uncompressed string, bitsPerChar int, getCharFromInt func(character int) string) string { if len(uncompressed) == 0 { return "" } @@ -46,44 +49,48 @@ func Compress(uncompressed string, bitsPerChar int, getCharFromInt func(characte contextEnlargeIn := float64(2) contextDictSize := int(3) contextNumBits := int(2) - var contextDataString string + //var contextDataString string + var contextDataString = strings.Builder{} + contextDataVal := int(0) contextDataPosition := int(0) - for ii := 0; ii < len([]rune(uncompressed)); ii++ { - contextC = string([]rune(uncompressed)[ii]) + uncompressedRunes := []rune(uncompressed) + for ii := 0; ii < len(uncompressedRunes); ii++ { + contextC = string(uncompressedRunes[ii]) _, in := contextDictionary[contextC] if !in { contextDictionary[contextC] = contextDictSize contextDictSize++ contextDictionaryToCreate[contextC] = true } - contextWc = contextW + contextC - _, in = contextDictionary[contextWc] if in { contextW = contextWc } else { _, in = contextDictionaryToCreate[contextW] if in { - if []rune(contextW)[0] < 256 { + contextWRune := []rune(contextW) + if contextWRune[0] < 256 { for i := 0; i < contextNumBits; i++ { contextDataVal = contextDataVal << 1 if contextDataPosition == bitsPerChar-1 { contextDataPosition = 0 - contextDataString += getCharFromInt(contextDataVal) + //contextDataString += getCharFromInt(contextDataVal) + contextDataString.WriteString(getCharFromInt(contextDataVal)) contextDataVal = 0 } else { contextDataPosition++ } } - value = int([]rune(contextW)[0]) + value = int(contextWRune[0]) for i := 0; i < 8; i++ { contextDataVal = (contextDataVal << 1) | (value & 1) if contextDataPosition == bitsPerChar-1 { contextDataPosition = 0 - contextDataString += getCharFromInt(contextDataVal) + //contextDataString += getCharFromInt(contextDataVal) + contextDataString.WriteString(getCharFromInt(contextDataVal)) contextDataVal = 0 } else { contextDataPosition++ @@ -96,19 +103,21 @@ func Compress(uncompressed string, bitsPerChar int, getCharFromInt func(characte contextDataVal = (contextDataVal << 1) | value if contextDataPosition == bitsPerChar-1 { contextDataPosition = 0 - contextDataString += getCharFromInt(contextDataVal) + //contextDataString += getCharFromInt(contextDataVal) + contextDataString.WriteString(getCharFromInt(contextDataVal)) contextDataVal = 0 } else { contextDataPosition++ } value = 0 } - value = int([]rune(contextW)[0]) + value = int(contextWRune[0]) for i := 0; i < 16; i++ { contextDataVal = (contextDataVal << 1) | (value & 1) if contextDataPosition == bitsPerChar-1 { contextDataPosition = 0 - contextDataString += getCharFromInt(contextDataVal) + //contextDataString += getCharFromInt(contextDataVal) + contextDataString.WriteString(getCharFromInt(contextDataVal)) contextDataVal = 0 } else { contextDataPosition++ @@ -128,7 +137,8 @@ func Compress(uncompressed string, bitsPerChar int, getCharFromInt func(characte contextDataVal = (contextDataVal << 1) | (value & 1) if contextDataPosition == bitsPerChar-1 { contextDataPosition = 0 - contextDataString += getCharFromInt(contextDataVal) + //contextDataString += getCharFromInt(contextDataVal) + contextDataString.WriteString(getCharFromInt(contextDataVal)) contextDataVal = 0 } else { contextDataPosition++ @@ -155,7 +165,8 @@ func Compress(uncompressed string, bitsPerChar int, getCharFromInt func(characte contextDataVal = contextDataVal << 1 if contextDataPosition == bitsPerChar-1 { contextDataPosition = 0 - contextDataString += getCharFromInt(contextDataVal) + //contextDataString += getCharFromInt(contextDataVal) + contextDataString.WriteString(getCharFromInt(contextDataVal)) contextDataVal = 0 } else { contextDataPosition++ @@ -166,7 +177,8 @@ func Compress(uncompressed string, bitsPerChar int, getCharFromInt func(characte contextDataVal = (contextDataVal << 1) | (value & 1) if contextDataPosition == bitsPerChar-1 { contextDataPosition = 0 - contextDataString += getCharFromInt(contextDataVal) + //contextDataString += getCharFromInt(contextDataVal) + contextDataString.WriteString(getCharFromInt(contextDataVal)) contextDataVal = 0 } else { contextDataPosition++ @@ -179,7 +191,8 @@ func Compress(uncompressed string, bitsPerChar int, getCharFromInt func(characte contextDataVal = (contextDataVal << 1) | value if contextDataPosition == bitsPerChar-1 { contextDataPosition = 0 - contextDataString += getCharFromInt(contextDataVal) + //contextDataString += getCharFromInt(contextDataVal) + contextDataString.WriteString(getCharFromInt(contextDataVal)) contextDataVal = 0 } else { contextDataPosition++ @@ -191,7 +204,8 @@ func Compress(uncompressed string, bitsPerChar int, getCharFromInt func(characte contextDataVal = (contextDataVal << 1) | (value & 1) if contextDataPosition == bitsPerChar-1 { contextDataPosition = 0 - contextDataString += getCharFromInt(contextDataVal) + //contextDataString += getCharFromInt(contextDataVal) + contextDataString.WriteString(getCharFromInt(contextDataVal)) contextDataVal = 0 } else { contextDataPosition++ @@ -211,7 +225,8 @@ func Compress(uncompressed string, bitsPerChar int, getCharFromInt func(characte contextDataVal = (contextDataVal << 1) | (value & 1) if contextDataPosition == bitsPerChar-1 { contextDataPosition = 0 - contextDataString += getCharFromInt(contextDataVal) + //contextDataString += getCharFromInt(contextDataVal) + contextDataString.WriteString(getCharFromInt(contextDataVal)) contextDataVal = 0 } else { contextDataPosition++ @@ -231,7 +246,8 @@ func Compress(uncompressed string, bitsPerChar int, getCharFromInt func(characte contextDataVal = (contextDataVal << 1) | (value & 1) if contextDataPosition == bitsPerChar-1 { contextDataPosition = 0 - contextDataString += getCharFromInt(contextDataVal) + //contextDataString += getCharFromInt(contextDataVal) + contextDataString.WriteString(getCharFromInt(contextDataVal)) contextDataVal = 0 } else { contextDataPosition++ @@ -242,21 +258,22 @@ func Compress(uncompressed string, bitsPerChar int, getCharFromInt func(characte for { contextDataVal = contextDataVal << 1 if contextDataPosition == bitsPerChar-1 { - contextDataString += getCharFromInt(contextDataVal) + //contextDataString += getCharFromInt(contextDataVal) + contextDataString.WriteString(getCharFromInt(contextDataVal)) break } else { contextDataPosition++ } } - return contextDataString + return contextDataString.String() } // Decompress - -var keyStrBase64Map map[byte]int = map[byte]int{74: 9, 78: 13, 83: 18, 61: 64, 109: 38, 114: 43, 116: 45, 101: 30, 47: 63, 73: 8, 81: 16, 113: 42, 49: 53, 50: 54, 54: 58, 76: 11, 100: 29, 107: 36, 121: 50, 77: 12, 89: 24, 105: 34, 66: 1, 69: 4, 85: 20, 48: 52, 119: 48, 117: 46, 120: 49, 52: 56, 56: 60, 110: 39, 112: 41, 70: 5, 71: 6, 79: 14, 88: 23, 97: 26, 102: 31, 103: 32, 67: 2, 118: 47, 65: 0, 68: 3, 72: 7, 108: 37, 51: 55, 57: 61, 82: 17, 90: 25, 98: 27, 115: 44, 122: 51, 53: 57, 86: 21, 106: 35, 111: 40, 55: 59, 43: 62, 75: 10, 80: 15, 84: 19, 87: 22, 99: 28, 104: 33} +var baseReverseDic = sync.Map{} type dataStruct struct { input string + alphabet string val int position int index int @@ -265,8 +282,25 @@ type dataStruct struct { numBits int } -func getBaseValue(char byte) int { - return keyStrBase64Map[char] +func covertToBaseReverseDic(alphabet string) map[byte]int { + var val = map[byte]int{} + charArr := []rune(alphabet) + for i := 0; i < len(charArr); i++ { + val[byte(charArr[i])] = i + } + return val +} + +func getBaseValue(alphabet string, char byte) int { + vv, ok := baseReverseDic.Load(alphabet) + var arr map[byte]int + if ok { + arr = vv.(map[byte]int) + } else { + arr = covertToBaseReverseDic(alphabet) + baseReverseDic.Store(alphabet, arr) + } + return arr[char] } // Input is composed of ASCII characters, so accessing it by array has no UTF-8 pb. @@ -278,7 +312,7 @@ func readBits(nb int, data *dataStruct) int { data.position = data.position / 2 if data.position == 0 { data.position = 32 - data.val = getBaseValue(data.input[data.index]) + data.val = getBaseValue(data.alphabet, data.input[data.index]) data.index += 1 } if respB > 0 { @@ -302,11 +336,11 @@ func getString(last string, data *dataStruct) (string, bool, error) { c := readBits(data.numBits, data) switch c { case 0: - str := string(readBits(8, data)) + str := string(rune(readBits(8, data))) appendValue(data, str) return str, false, nil case 1: - str := string(readBits(16, data)) + str := string(rune(readBits(16, data))) appendValue(data, str) return str, false, nil case 2: @@ -327,9 +361,11 @@ func concatWithFirstRune(str string, getFirstRune string) string { return str + string(r) } -func DecompressFromBase64(input string) (string, error) { - data := dataStruct{input, getBaseValue(input[0]), 32, 1, []string{"0", "1", "2"}, 5, 2} - +func Decompress(input string, keyStrBase64 string) (string, error) { + if keyStrBase64 == "" { + keyStrBase64 = _defaultKeyStrBase64 + } + data := dataStruct{input, keyStrBase64, getBaseValue(keyStrBase64, input[0]), 32, 1, []string{"0", "1", "2"}, 5, 2} result, isEnd, err := getString("", &data) if err != nil || isEnd { return result, err @@ -341,9 +377,28 @@ func DecompressFromBase64(input string) (string, error) { if err != nil || isEnd { return result, err } - result = result + str appendValue(&data, concatWithFirstRune(last, str)) last = str } } + +//func DecompressFromBase64New(input string) (string, error) { +// data := dataStruct{input, getBaseValue(input[0]), 32, 1, []string{"0", "1", "2"}, 5, 2} +// result, isEnd, err := getString("", &data) +// if err != nil || isEnd { +// return result, err +// } +// last := result +// data.numBits += 1 +// newResBuf := strings.Builder{} +// for { +// str, isEnd, err := getString(last, &data) +// if err != nil || isEnd { +// return newResBuf.String(), err +// } +// newResBuf.WriteString(str) +// appendValue(&data, concatWithFirstRune(last, str)) +// last = str +// } +//} diff --git a/lz-string_test.go b/lz-string_test.go new file mode 100644 index 0000000..de3c352 --- /dev/null +++ b/lz-string_test.go @@ -0,0 +1,109 @@ +package LZString + +import ( + "fmt" + "sync" + "testing" +) + +func Test_Compress(t *testing.T) { + var dataStr = `{"cNounce":"80309","cRq":{"d":"xeoGCEv+djKzc6ntAdAgZxSfmJcB5E1kLTEFsN1CGukpZkAstuTm8157S94AAYL83gT4cm0q2Hlspb2WKLfanSTXiHu9jWmtI8/NSAUULpdy9R5XxJlz+7mojw42EqGNC+loqPsGHZEbp0+b9lrOGhML8CBcEduUNq2mSTOUjgusEd8ug6+JlwzRC2kABHJDGLFX1LDRaT9WbMEEC/TeQ2bykPoBEYNrG/qxTcYwgshpAwkvHYlCXH0v1NbyBG+DI7E1dYMHQMAPNvxK450Wqh3W9Rq3/iqLrAOTMYXwuXuui82ch47qW5XKTCjLoQ5+TM+gM/EYQ6A+vWw7dkBAAJcekaohmAItymVJ/v234YzavDTna0vRDoeZZyf/v2dLPuz25Rc4ZsUX3M2L9Bne11xI2KWnoCCgsrfwCZ5d6NFRnH1Ld/jO67mVJj1SamexITk9WjwVhSetyjfw3o7Tw4eQ/4WaTe1UcQa2MMZgxO1HZEuNjR3k4MORJATbfwdxsBxhvFn2MXTvDSQMwS6LPKmR3nz3JHhrDgRj2KangIJdKLpFCP+lIK6SPghKJvNM7jXyFLqiucpYMeMqyjyOOn5cy2ANIRiO5HppjaCs36n8xM/qlaSrmbaK7jGMkD1CokK8VHpf4rMkF5VSLhhYHwXZXdSAq2GPzxY+0AOi80Hi3+6HF8e0rQ1nYGOTWrplrzeW/vCRUEiBAq+3SdKeoA==","hh":"tEtDmj9NO12CQujtDAf6znTptSdPuOFPcXitzqFb5a4=","i1":"MmEhOUHiGsRJZjij1zCWjQ==","i2":"ukacN6jPVDqrPE8x7lSyqg==","m":"P76F7Om9PMh31Wrui42tfu7uvpVw9MsguMLcoozrHaY=","ra":"TW96aWxsYS81LjAgKFdpbmRvd3MgTlQgMTAuMDsgV2luNjQ7IHg2NCkgQXBwbGVXZWJLaXQvNTM3LjM2IChLSFRNTCwgbGlrZSBHZWNrbykgQ2hyb21lLzg3LjAuNDI4MC4xNDEgU2FmYXJpLzUzNy4zNg==","rm":"R0VU","ru":"aHR0cHM6Ly93d3cuc25lYWtlcnNuc3R1ZmYuY29tLw==","t":"MTYxODM3NDcyNy4zODkwMDA=","uh":"sfgiHR/bGP0DFXSp4KJXpJnmQXuNHfWxwUhpX9SCMz4="},"chC":0,"chCAS":0,"chLog":{"0":{"start":1618374728142},"c":1},"chReq":"non-interactive","cvId":"2","oV":1}` + var d = `Lz0-6uFWXOjE8lMIok1S49ZH+5TGYfsByPdhQAJK7ebxUpRriqVn2gaCDmcN3tv$w` + fmt.Println(Compress(dataStr, d)) +} + +func Test_DeCompress(t *testing.T) { + var dataStr = `lDXyqyYytyxyfJLedLH0LWLzy8V+OiyL2DL1yXcbyLJbXLW7ALMX-0L7yFD-49L9ylXLr8L-+DLui0091oW8LZKo-jL8i0aLjSLLPLjqULhLFUL8yz4aL8o-M6LVV+ihLzCAWOg3S-lx2zCo-U1KyLEOj1LO7JcldV5duyTePQL6iL6yLagUDLkdQLcriJjy0FY6eJLz7LAJQisEnmTRXLQRyLtzzjQy0bI1GM9L0ss01cAHoTF+OYLZeorL-RX1AU56ioEui54FoL0p58TBOUMYc+H-ADFozMLIO8Lz+LUp6UaJzU9-Lt6jAbuSRI9DUPygdvczyUP6H0Jd26Oz+jHYah1FyLXQiSO5jy+SMd104nWP3hAKJia0qaJ56LzuuXmX5FI5oGkU0XoFm8feQMPJ8LkkTVTVI5V1k5F-Pe0X5ud9lj+-yF008Nk8Eh7A7zoq40EIlj2mc1I+o-P2ByPH1+BOQkN+Bjh8h+fx98yJFc1MmJ5Dk1bEF09FLiTx7uOykDPLOQBEhBPJud36qoZJcEhsxdV5NpfJ2Q11EyYBjELO4XnTYOTkzF6eokmb1opYk-loLlo2NoDjZiXodyPjWWk5hyO49OWk46o3KQoq4W519z8sqyyP1RPX+z03JUI4baFsjk8sF2Y6ozy8fzTjHDvSy4z+EFulq4dq+3A29z666UO-yTSq9WTHyNP6M+agDLiAzjlk6Lr8ihzOO+Z2sOk60GHPKaijLLh85+cHT6O3dO43shLZQ1P15mKKQZoc-RLqhh+FLXuD6PU086OKhR6yl6Q8iYJBjycFUGoc6s-PE-y0hjh8LYA6lk+Az6kfv-49dD66GLl-1kDGKkZo1uDj3VAQu7l07XeK6UuytJauevz6OotAQkmvL2-yXFsLOs6bX5Ez88PbPy8zK-gkzKhXX5s0FMDNhyHoi0FuOOLyu71FbMmf-15qKuD67ZFUGLqWoMyUnX-X1d4FDgzV6ev03ePKd8fuN0yXqvWouUUe46XGQTVqfzGOoS6skDXh1k5jKQ17bFc9XJ-aoocLdEP86t6l8-1TeU0D6o2QUfz66iFmTo8MLXd+Eg3PR5qGQ6kz3yNuy1zclPbKE8yRFiOkn8+1oLuD$bX6Lkp7YoaW6f6guDILX-7AXZueFzsLPVo9z6ooD-85qqFveYNQUI+izbYkz-X1iYA267oQzDPby8ZPKh4lPWdzSTJFUGhmuDTei86uP3ADZQLTzc74A7Oi1Qy6ks-aup2SXFDth++bLyVOoPhXZkPsXlkT-aLXk6ULXNh4ILtJsM2-0RD89K6uo+L0FLMFYupuhi5mxuz9Di0yjzzzRlX1ydFJozR6eT-8z2kzjBXPXdOo$z8HymWD1ibuV91M07IYDyVZA8n81o+FsfuI5GuX8d+iZLPTlO5z1S+huQZAjJ2k+Yd+upOrV-oSzj1eTHYNgU0S$YZP+kDS04G3XWhX4MtRsoAuksk3QmkQJ$ekDPhVLi8P8ok5zWmMJ8g-dZz0MyXWklP5zcuOE-4H2lFYLvsQ60LPP0-vp5-bxTzXOyuUIoy+CzyEo67TkLuy-183O1XqU-5nL6u9YFoXhmW6zQ8LYLXzzZi0oLi3yKDiLd0QILDyS0EFgdLYo-8nLku7Rd5DazxDO4$p$MDcXh0EzErtXF8zWd2FU07Zopo1-pLNKUSLcXYkjFY069VAkKLT-yF7uRS62ybuh7UW77ejPD040i5DyPb+yLLEN6W-0i9LJzEFIz+OXOoldNuOAQOo6LJzCFszj-YZPjL-LdL8-6LXQ+4PvzZz+3LbL-0kI-0okLuL20ChyLLZJbzXkL+Yi-dFbzi5LAdMLpz7Fy8ZqL7LpJdZ+7LL` + var d = `Lz0-6uFWXOjE8lMIok1S49ZH+5TGYfsByPdhQAJK7ebxUpRriqVn2gaCDmcN3tv$w` + fmt.Println(Decompress(dataStr, d)) +} + +func Test_DeCompressToBase641(t *testing.T) { + var dataStr = `lDXyqyYytyxyfJLedLH0LWLzy8V+Oiy0voL=` + str := Compress(dataStr, "") + res, err := Decompress(str, "") + fmt.Println(res == dataStr, err) +} + +func Test_DeCompressToBase642(t *testing.T) { + var dataStr = `lDXyqyYytyxyfJLedLH0LWLzy8V+Oiy0voL=` + var d = `Lz0-6uFWXOjE8lMIok1S49ZH+5TGYfsByPdhQAJK7ebxUpRriqVn2gaCDmcN3tv$w` + str := Compress(dataStr, d) + res, err := Decompress(str, d) + fmt.Println(res == dataStr, res, err) +} +func TestCompressFromString(t *testing.T) { + type args struct { + uncompressed string + chars string + } + tests := []struct { + name string + args args + want string + }{ + // TODO: Add test cases. + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := Compress(tt.args.uncompressed, tt.args.chars); got != tt.want { + t.Errorf("CompressFromString() = %v, want %v", got, tt.want) + } + }) + } +} + +func BenchmarkCompressFromString(b *testing.B) { + for i := 0; i < b.N; i++ { + Compress("1233333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333eeeeeeeeeeeeeeeeee2e23e2qwerqwerqwerqwerqwerqweeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeerqwerqwer1233333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333eeeeeeeeeeeeeeeeee2e23e2qwerqwerqwerqwerqwerqweeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeerqwerqwer1233333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333eeeeeeeeeeeeeeeeee2e23e2qwerqwerqwerqwerqwerqweeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeerqwerqwer1233333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333eeeeeeeeeeeeeeeeee2e23e2qwerqwerqwerqwerqwerqweeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeerqwerqwer1233333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333eeeeeeeeeeeeeeeeee2e23e2qwerqwerqwerqwerqwerqweeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeerqwerqwer1233333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333eeeeeeeeeeeeeeeeee2e23e2qwerqwerqwerqwerqwerqweeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeerqwerqwer1233333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333eeeeeeeeeeeeeeeeee2e23e2qwerqwerqwerqwerqwerqweeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeerqwerqwer1233333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333eeeeeeeeeeeeeeeeee2e23e2qwerqwerqwerqwerqwerqweeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeerqwerqwer1233333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333eeeeeeeeeeeeeeeeee2e23e2qwerqwerqwerqwerqwerqweeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeerqwerqwer1233333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333eeeeeeeeeeeeeeeeee2e23e2qwerqwerqwerqwerqwerqweeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeerqwerqwer", _defaultKeyStrBase64) + } +} + +func BenchmarkCompressFromString2(b *testing.B) { + for i := 0; i < b.N; i++ { + Compress("3123123", _defaultKeyStrBase64) + } +} + +func BenchmarkCompressToBase64(b *testing.B) { + str := `{"cNounce":"36728","cRq":{"d":"oraaF6KB66uNJPX9UPeeiXActri35Lwu5mv+YI1bqHV1rotfmyjcn9iBX5LZto7WyVo6iQlpqpGTRZ3WeOFTCGsJBdry5WLcXcxGqhuJixjpDcv2W9h4geRwf+agasGzInsjMYBCg6GnzYmxxpdVp4U16pzjPJoikxflHq0XG+GkxMnMIAPWgpKeyNAy0Aj7WdTo0pmP3Cn6B4NrNFXhzekJG7IBR8KkfUXlteieFKS3k0WRH09OsmA+GxMz8Pag0KiXN8+tIs19PqDMHNoeJBkLMtmLKTzExtxP2wgaVjWh1UPUim7M7yLGkmdv5bU3Zuz64ASvr8IEWmiZVJYenz9hFA4MhYtNRZVyR1AYx41Fb0hvRcrQG5M5vsZXymJykAYWITIthMw6rxHnTI+Vbx6E46Yu9/QcJ4xT5MWmW8zXRIM+jp5fow4/3335tRsMSdyIL4bE+ulw52cTVXrpNqhqCatH/wHHyUshuhjsFPMMxs6WoRFW4ceOX8vi7R8TtprsOtSmWg1OK7hYrl99ZXfIcbcJwRjRzfdsYrTN5FrpCqdk2DjD5UXG7EDcI+LodnsK4PyDAMzzAFyzubmQFICT8spvRrnUoDqMzCq7ViWt2JpwqDt5gmGMHZJg5VWkGYG1EjwkLr8FZ9gh2ezHeg7e0siiPDf6AbkvU4KCmR1Ht7qgOe0l+LDM1t/m7o1tUwkoY3J1poq0U2juD+Itcg==","hh":"QSlXmfS2NeZCSV7a6l5l5OS3E6mq9iZtckO4Lj4aWug=","i1":"bSoctx5zCBRkkKOF5bXUCQ==","i2":"XPiyF0pHvrNO7OakWEMoOg==","m":"eqV80Sw4dkgMfJScOzRO4cIGos2UPT/g3Fn2WVKKC5Y=","ra":"TW96aWxsYS81LjAgKFdpbmRvd3MgTlQgMTAuMDsgV2luNjQ7IHg2NCkgQXBwbGVXZWJLaXQvNTM3LjM2IChLSFRNTCwgbGlrZSBHZWNrbykgQ2hyb21lLzg3LjAuNDI4MC4xNDEgU2FmYXJpLzUzNy4zNg==","rm":"R0VU","ru":"aHR0cHM6Ly93d3cud29vZHdvb2QuY29tLw==","t":"MTYxODM4NDAzMi4wNzAwMDA=","uh":"sfgiHR/bGP0DFXSp4KJXpJnmQXuNHfWxwUhpX9SCMz4="},"chC":0,"chCAS":0,"chLog":{"0":{"start":1618384032901},"c":1},"chReq":"non-interactive","cvId":"2","oV":1}` + for i := 0; i < b.N; i++ { + Compress(str, `Lz0-6uFWXOjE8lMIok1S49ZH+5TGYfsByPdhQAJK7ebxUpRriqVn2gaCDmcN3tv$w`) + } +} + +func BenchmarkDeCompressToBase64(b *testing.B) { + str := `lDXyqyYytyxyfJLedLH0LWLzy8V+OiyL2DL1yXcbyLJbXLW7ALMX-0L7yFD-49L9ylXLr8L-+DLui0091oW8LZKo-jL8i0aLjSLLPLjqULhLFUL8yz4aL8o-M6LVV+ihLzCAWOg3S-lx2zCo-U1KyLEOj1LO7JcldV5duyTePQL6iL6yLagUDLkdQLcriJjy0FY6eJLz7LAJQisEnmTRXLQRyLtzzjQy0bI1GM9L0ss01cAHoTF+OYLZeorL-RX1AU56ioEui54FoL0p58TBOUMYc+H-ADFozMLIO8Lz+LUp6UaJzU9-Lt6jAbuSRI9DUPygdvczyUP6H0Jd26Oz+jHYah1FyLXQiSO5jy+SMd104nWP3hAKJia0qaJ56LzuuXmX5FI5oGkU0XoFm8feQMPJ8LkkTVTVI5V1k5F-Pe0X5ud9lj+-yF008Nk8Eh7A7zoq40EIlj2mc1I+o-P2ByPH1+BOQkN+Bjh8h+fx98yJFc1MmJ5Dk1bEF09FLiTx7uOykDPLOQBEhBPJud36qoZJcEhsxdV5NpfJ2Q11EyYBjELO4XnTYOTkzF6eokmb1opYk-loLlo2NoDjZiXodyPjWWk5hyO49OWk46o3KQoq4W519z8sqyyP1RPX+z03JUI4baFsjk8sF2Y6ozy8fzTjHDvSy4z+EFulq4dq+3A29z666UO-yTSq9WTHyNP6M+agDLiAzjlk6Lr8ihzOO+Z2sOk60GHPKaijLLh85+cHT6O3dO43shLZQ1P15mKKQZoc-RLqhh+FLXuD6PU086OKhR6yl6Q8iYJBjycFUGoc6s-PE-y0hjh8LYA6lk+Az6kfv-49dD66GLl-1kDGKkZo1uDj3VAQu7l07XeK6UuytJauevz6OotAQkmvL2-yXFsLOs6bX5Ez88PbPy8zK-gkzKhXX5s0FMDNhyHoi0FuOOLyu71FbMmf-15qKuD67ZFUGLqWoMyUnX-X1d4FDgzV6ev03ePKd8fuN0yXqvWouUUe46XGQTVqfzGOoS6skDXh1k5jKQ17bFc9XJ-aoocLdEP86t6l8-1TeU0D6o2QUfz66iFmTo8MLXd+Eg3PR5qGQ6kz3yNuy1zclPbKE8yRFiOkn8+1oLuD$bX6Lkp7YoaW6f6guDILX-7AXZueFzsLPVo9z6ooD-85qqFveYNQUI+izbYkz-X1iYA267oQzDPby8ZPKh4lPWdzSTJFUGhmuDTei86uP3ADZQLTzc74A7Oi1Qy6ks-aup2SXFDth++bLyVOoPhXZkPsXlkT-aLXk6ULXNh4ILtJsM2-0RD89K6uo+L0FLMFYupuhi5mxuz9Di0yjzzzRlX1ydFJozR6eT-8z2kzjBXPXdOo$z8HymWD1ibuV91M07IYDyVZA8n81o+FsfuI5GuX8d+iZLPTlO5z1S+huQZAjJ2k+Yd+upOrV-oSzj1eTHYNgU0S$YZP+kDS04G3XWhX4MtRsoAuksk3QmkQJ$ekDPhVLi8P8ok5zWmMJ8g-dZz0MyXWklP5zcuOE-4H2lFYLvsQ60LPP0-vp5-bxTzXOyuUIoy+CzyEo67TkLuy-183O1XqU-5nL6u9YFoXhmW6zQ8LYLXzzZi0oLi3yKDiLd0QILDyS0EFgdLYo-8nLku7Rd5DazxDO4$p$MDcXh0EzErtXF8zWd2FU07Zopo1-pLNKUSLcXYkjFY069VAkKLT-yF7uRS62ybuh7UW77ejPD040i5DyPb+yLLEN6W-0i9LJzEFIz+OXOoldNuOAQOo6LJzCFszj-YZPjL-LdL8-6LXQ+4PvzZz+3LbL-0kI-0okLuL20ChyLLZJbzXkL+Yi-dFbzi5LAdMLpz7Fy8ZqL7LpJdZ+7LL` + for i := 0; i < b.N; i++ { + Decompress(str, `Lz0-6uFWXOjE8lMIok1S49ZH+5TGYfsByPdhQAJK7ebxUpRriqVn2gaCDmcN3tv$w`) + } +} + +func BenchmarkDeCompressCon(b *testing.B) { + str := `lDXyqyYytyxyfJLedLH0LWLzy8V+OiyL2DL1yXcbyLJbXLW7ALMX-0L7yFD-49L9ylXLr8L-+DLui0091oW8LZKo-jL8i0aLjSLLPLjqULhLFUL8yz4aL8o-M6LVV+ihLzCAWOg3S-lx2zCo-U1KyLEOj1LO7JcldV5duyTePQL6iL6yLagUDLkdQLcriJjy0FY6eJLz7LAJQisEnmTRXLQRyLtzzjQy0bI1GM9L0ss01cAHoTF+OYLZeorL-RX1AU56ioEui54FoL0p58TBOUMYc+H-ADFozMLIO8Lz+LUp6UaJzU9-Lt6jAbuSRI9DUPygdvczyUP6H0Jd26Oz+jHYah1FyLXQiSO5jy+SMd104nWP3hAKJia0qaJ56LzuuXmX5FI5oGkU0XoFm8feQMPJ8LkkTVTVI5V1k5F-Pe0X5ud9lj+-yF008Nk8Eh7A7zoq40EIlj2mc1I+o-P2ByPH1+BOQkN+Bjh8h+fx98yJFc1MmJ5Dk1bEF09FLiTx7uOykDPLOQBEhBPJud36qoZJcEhsxdV5NpfJ2Q11EyYBjELO4XnTYOTkzF6eokmb1opYk-loLlo2NoDjZiXodyPjWWk5hyO49OWk46o3KQoq4W519z8sqyyP1RPX+z03JUI4baFsjk8sF2Y6ozy8fzTjHDvSy4z+EFulq4dq+3A29z666UO-yTSq9WTHyNP6M+agDLiAzjlk6Lr8ihzOO+Z2sOk60GHPKaijLLh85+cHT6O3dO43shLZQ1P15mKKQZoc-RLqhh+FLXuD6PU086OKhR6yl6Q8iYJBjycFUGoc6s-PE-y0hjh8LYA6lk+Az6kfv-49dD66GLl-1kDGKkZo1uDj3VAQu7l07XeK6UuytJauevz6OotAQkmvL2-yXFsLOs6bX5Ez88PbPy8zK-gkzKhXX5s0FMDNhyHoi0FuOOLyu71FbMmf-15qKuD67ZFUGLqWoMyUnX-X1d4FDgzV6ev03ePKd8fuN0yXqvWouUUe46XGQTVqfzGOoS6skDXh1k5jKQ17bFc9XJ-aoocLdEP86t6l8-1TeU0D6o2QUfz66iFmTo8MLXd+Eg3PR5qGQ6kz3yNuy1zclPbKE8yRFiOkn8+1oLuD$bX6Lkp7YoaW6f6guDILX-7AXZueFzsLPVo9z6ooD-85qqFveYNQUI+izbYkz-X1iYA267oQzDPby8ZPKh4lPWdzSTJFUGhmuDTei86uP3ADZQLTzc74A7Oi1Qy6ks-aup2SXFDth++bLyVOoPhXZkPsXlkT-aLXk6ULXNh4ILtJsM2-0RD89K6uo+L0FLMFYupuhi5mxuz9Di0yjzzzRlX1ydFJozR6eT-8z2kzjBXPXdOo$z8HymWD1ibuV91M07IYDyVZA8n81o+FsfuI5GuX8d+iZLPTlO5z1S+huQZAjJ2k+Yd+upOrV-oSzj1eTHYNgU0S$YZP+kDS04G3XWhX4MtRsoAuksk3QmkQJ$ekDPhVLi8P8ok5zWmMJ8g-dZz0MyXWklP5zcuOE-4H2lFYLvsQ60LPP0-vp5-bxTzXOyuUIoy+CzyEo67TkLuy-183O1XqU-5nL6u9YFoXhmW6zQ8LYLXzzZi0oLi3yKDiLd0QILDyS0EFgdLYo-8nLku7Rd5DazxDO4$p$MDcXh0EzErtXF8zWd2FU07Zopo1-pLNKUSLcXYkjFY069VAkKLT-yF7uRS62ybuh7UW77ejPD040i5DyPb+yLLEN6W-0i9LJzEFIz+OXOoldNuOAQOo6LJzCFszj-YZPjL-LdL8-6LXQ+4PvzZz+3LbL-0kI-0okLuL20ChyLLZJbzXkL+Yi-dFbzi5LAdMLpz7Fy8ZqL7LpJdZ+7LL` + mapper := `Lz0-6uFWXOjE8lMIok1S49ZH+5TGYfsByPdhQAJK7ebxUpRriqVn2gaCDmcN3tv$w` + wg := sync.WaitGroup{} + for i := 0; i < b.N; i++ { + wg.Add(1) + go func() { + Decompress(str, mapper) + wg.Done() + }() + } + wg.Wait() +} + +func BenchmarkDecompressFromBase64old(b *testing.B) { + str := `lDXyqyYytyxyfJLedLH0LWLzy8V+OiyL2DL1yXcbyLJbXLW7ALMX-0L7yFD-49L9ylXLr8L-+DLui0091oW8LZKo-jL8i0aLjSLLPLjqULhLFUL8yz4aL8o-M6LVV+ihLzCAWOg3S-lx2zCo-U1KyLEOj1LO7JcldV5duyTePQL6iL6yLagUDLkdQLcriJjy0FY6eJLz7LAJQisEnmTRXLQRyLtzzjQy0bI1GM9L0ss01cAHoTF+OYLZeorL-RX1AU56ioEui54FoL0p58TBOUMYc+H-ADFozMLIO8Lz+LUp6UaJzU9-Lt6jAbuSRI9DUPygdvczyUP6H0Jd26Oz+jHYah1FyLXQiSO5jy+SMd104nWP3hAKJia0qaJ56LzuuXmX5FI5oGkU0XoFm8feQMPJ8LkkTVTVI5V1k5F-Pe0X5ud9lj+-yF008Nk8Eh7A7zoq40EIlj2mc1I+o-P2ByPH1+BOQkN+Bjh8h+fx98yJFc1MmJ5Dk1bEF09FLiTx7uOykDPLOQBEhBPJud36qoZJcEhsxdV5NpfJ2Q11EyYBjELO4XnTYOTkzF6eokmb1opYk-loLlo2NoDjZiXodyPjWWk5hyO49OWk46o3KQoq4W519z8sqyyP1RPX+z03JUI4baFsjk8sF2Y6ozy8fzTjHDvSy4z+EFulq4dq+3A29z666UO-yTSq9WTHyNP6M+agDLiAzjlk6Lr8ihzOO+Z2sOk60GHPKaijLLh85+cHT6O3dO43shLZQ1P15mKKQZoc-RLqhh+FLXuD6PU086OKhR6yl6Q8iYJBjycFUGoc6s-PE-y0hjh8LYA6lk+Az6kfv-49dD66GLl-1kDGKkZo1uDj3VAQu7l07XeK6UuytJauevz6OotAQkmvL2-yXFsLOs6bX5Ez88PbPy8zK-gkzKhXX5s0FMDNhyHoi0FuOOLyu71FbMmf-15qKuD67ZFUGLqWoMyUnX-X1d4FDgzV6ev03ePKd8fuN0yXqvWouUUe46XGQTVqfzGOoS6skDXh1k5jKQ17bFc9XJ-aoocLdEP86t6l8-1TeU0D6o2QUfz66iFmTo8MLXd+Eg3PR5qGQ6kz3yNuy1zclPbKE8yRFiOkn8+1oLuD$bX6Lkp7YoaW6f6guDILX-7AXZueFzsLPVo9z6ooD-85qqFveYNQUI+izbYkz-X1iYA267oQzDPby8ZPKh4lPWdzSTJFUGhmuDTei86uP3ADZQLTzc74A7Oi1Qy6ks-aup2SXFDth++bLyVOoPhXZkPsXlkT-aLXk6ULXNh4ILtJsM2-0RD89K6uo+L0FLMFYupuhi5mxuz9Di0yjzzzRlX1ydFJozR6eT-8z2kzjBXPXdOo$z8HymWD1ibuV91M07IYDyVZA8n81o+FsfuI5GuX8d+iZLPTlO5z1S+huQZAjJ2k+Yd+upOrV-oSzj1eTHYNgU0S$YZP+kDS04G3XWhX4MtRsoAuksk3QmkQJ$ekDPhVLi8P8ok5zWmMJ8g-dZz0MyXWklP5zcuOE-4H2lFYLvsQ60LPP0-vp5-bxTzXOyuUIoy+CzyEo67TkLuy-183O1XqU-5nL6u9YFoXhmW6zQ8LYLXzzZi0oLi3yKDiLd0QILDyS0EFgdLYo-8nLku7Rd5DazxDO4$p$MDcXh0EzErtXF8zWd2FU07Zopo1-pLNKUSLcXYkjFY069VAkKLT-yF7uRS62ybuh7UW77ejPD040i5DyPb+yLLEN6W-0i9LJzEFIz+OXOoldNuOAQOo6LJzCFszj-YZPjL-LdL8-6LXQ+4PvzZz+3LbL-0kI-0okLuL20ChyLLZJbzXkL+Yi-dFbzi5LAdMLpz7Fy8ZqL7LpJdZ+7LL` + mapper := `Lz0-6uFWXOjE8lMIok1S49ZH+5TGYfsByPdhQAJK7ebxUpRriqVn2gaCDmcN3tv$w` + wg := sync.WaitGroup{} + for i := 0; i < b.N; i++ { + wg.Add(1) + go func() { + v, e := Decompress(str, mapper) + fmt.Println(v, e) + wg.Done() + }() + } + wg.Wait() +}