Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
airuike committed Apr 11, 2020
0 parents commit c1e19a7
Show file tree
Hide file tree
Showing 8 changed files with 1,171 additions and 0 deletions.
13 changes: 13 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# A LZFSE decompressor written in Go

```
import (
"os"
"gihub.com/aixiansheng/go-pure-lzfse"
)
inf, err := os.Open("some.lzfse")
outf, err := os.Create("some.file")
d := lzfse.NewReader(fh)
io.Copy(outf, inf)
```
29 changes: 29 additions & 0 deletions cachedreader.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package lzfse

import (
"io"
)

type cachedReader struct {
r io.Reader
buf []byte
}

func newCachedReader(r io.Reader) *cachedReader {
return &cachedReader{
r: r,
buf: make([]byte, 0, 1024),
}
}

func (cr *cachedReader) Read(b []byte) (int, error) {
n, err := cr.r.Read(b)
if n > 0 {
cr.buf = append(cr.buf, b[:n]...)
}
return n, err
}

func (cr *cachedReader) Bytes() []byte {
return cr.buf
}
96 changes: 96 additions & 0 deletions decompressor.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
package lzfse

import (
"encoding/binary"
"io"
)

type Magic uint32

const (
LZFSE_NO_BLOCK_MAGIC Magic = 0
LZFSE_ENDOFSTREAM_BLOCK_MAGIC Magic = 0x24787662
LZFSE_UNCOMPRESSED_BLOCK_MAGIC Magic = 0x2d787662
LZFSE_COMPRESSEDV1_BLOCK_MAGIC Magic = 0x31787662
LZFSE_COMPRESSEDV2_BLOCK_MAGIC Magic = 0x32787662
LZFSE_COMPRESSEDLZVN_BLOCK_MAGIC Magic = 0x6e787662
INVALID = 0xdeadbeef
)

type decompressor struct {
r *cachedReader
pipeR *io.PipeReader
pipeW *io.PipeWriter
handlerError error
}

func decodeUncompressedBlock(r *cachedReader, w io.Writer) error {
var n_raw_bytes uint32
if err := binary.Read(r, binary.LittleEndian, &n_raw_bytes); err != nil {
return err
}

if _, err := io.CopyN(w, r, int64(n_raw_bytes)); err != nil {
return err
}

return nil
}

func readBlockMagic(r io.Reader) (magic Magic, err error) {
err = binary.Read(r, binary.LittleEndian, &magic)
return
}

type blockHandler func(*cachedReader, io.Writer) error

func (d *decompressor) handleBlock(handler blockHandler) (Magic, error) {
if err := handler(d.r, d.pipeW); err != nil {
return INVALID, err
}

return readBlockMagic(d.r)
}

func (d *decompressor) Read(b []byte) (int, error) {
return d.pipeR.Read(b)
}

func NewReader(r io.Reader) *decompressor {
pipeR, pipeW := io.Pipe()
d := &decompressor{
r: newCachedReader(r),
pipeR: pipeR,
pipeW: pipeW,
}

go func() {
var err error
magic := LZFSE_NO_BLOCK_MAGIC

for nil == err {
switch magic {
case LZFSE_NO_BLOCK_MAGIC:
magic, err = readBlockMagic(d.r)
case LZFSE_UNCOMPRESSED_BLOCK_MAGIC:
magic, err = d.handleBlock(decodeUncompressedBlock)
case LZFSE_COMPRESSEDV1_BLOCK_MAGIC:
magic, err = d.handleBlock(decodeCompressedV1Block)
case LZFSE_COMPRESSEDV2_BLOCK_MAGIC:
magic, err = d.handleBlock(decodeCompressedV2Block)
case LZFSE_COMPRESSEDLZVN_BLOCK_MAGIC:
magic, err = d.handleBlock(decodeLZVNBlock)
case LZFSE_ENDOFSTREAM_BLOCK_MAGIC:
magic = LZFSE_ENDOFSTREAM_BLOCK_MAGIC
err = io.EOF
default:
panic("Bad magic")
}
}

d.handlerError = err
d.pipeW.Close()
}()

return d
}
Loading

0 comments on commit c1e19a7

Please sign in to comment.