diff options
author | obscuren <geffobscura@gmail.com> | 2014-11-03 06:33:06 +0800 |
---|---|---|
committer | obscuren <geffobscura@gmail.com> | 2014-11-03 06:33:06 +0800 |
commit | 9f8bcf3abca8c6c32efc384f6c6eda1677b769c5 (patch) | |
tree | 081d285f1ba5a38bf3708c53094f0966e11eee93 /compression/rle/read_write.go | |
parent | 1bb398f4e22feef8f83fedd8a525e4da5b627773 (diff) | |
download | go-tangerine-9f8bcf3abca8c6c32efc384f6c6eda1677b769c5.tar.gz go-tangerine-9f8bcf3abca8c6c32efc384f6c6eda1677b769c5.tar.zst go-tangerine-9f8bcf3abca8c6c32efc384f6c6eda1677b769c5.zip |
Added RLE compression. Closes #171
Diffstat (limited to 'compression/rle/read_write.go')
-rw-r--r-- | compression/rle/read_write.go | 82 |
1 files changed, 82 insertions, 0 deletions
diff --git a/compression/rle/read_write.go b/compression/rle/read_write.go new file mode 100644 index 000000000..e6f78e372 --- /dev/null +++ b/compression/rle/read_write.go @@ -0,0 +1,82 @@ +package rle + +import ( + "bytes" + "errors" + + "github.com/ethereum/go-ethereum/crypto" +) + +const ( + token byte = 0xfe + emptyShaToken = 0xfd + emptyListShaToken = 0xfe + tokenToken = 0xff +) + +var empty = crypto.Sha3([]byte("")) +var emptyList = crypto.Sha3([]byte{0x80}) + +func Decompress(dat []byte) ([]byte, error) { + buf := new(bytes.Buffer) + + for i := 0; i < len(dat); i++ { + if dat[i] == token { + if i+1 < len(dat) { + switch dat[i+1] { + case emptyShaToken: + buf.Write(empty) + case emptyListShaToken: + buf.Write(emptyList) + case tokenToken: + buf.WriteByte(token) + default: + buf.Write(make([]byte, int(dat[i+1]-2))) + } + i++ + } else { + return nil, errors.New("error reading bytes. token encountered without proceeding bytes") + } + } + } + + return buf.Bytes(), nil +} + +func Compress(dat []byte) []byte { + buf := new(bytes.Buffer) + + for i := 0; i < len(dat); i++ { + if dat[i] == token { + buf.Write([]byte{token, tokenToken}) + } else if i+1 < len(dat) { + if dat[i] == 0x0 && dat[i+1] == 0x0 { + j := 0 + for j <= 254 && i+j < len(dat) { + if dat[i+j] != 0 { + break + } + j++ + } + buf.Write([]byte{token, byte(j + 2)}) + i += (j - 1) + } else if len(dat[i:]) >= 32 { + if dat[i] == empty[0] && bytes.Compare(dat[i:i+32], empty) == 0 { + buf.Write([]byte{token, emptyShaToken}) + i += 31 + } else if dat[i] == emptyList[0] && bytes.Compare(dat[i:i+32], emptyList) == 0 { + buf.Write([]byte{token, emptyListShaToken}) + i += 31 + } else { + buf.WriteByte(dat[i]) + } + } else { + buf.WriteByte(dat[i]) + } + } else { + buf.WriteByte(dat[i]) + } + } + + return buf.Bytes() +} |