diff options
Diffstat (limited to 'vendor/github.com/glycerine/go-unsnap-stream/snap.go')
-rw-r--r-- | vendor/github.com/glycerine/go-unsnap-stream/snap.go | 100 |
1 files changed, 100 insertions, 0 deletions
diff --git a/vendor/github.com/glycerine/go-unsnap-stream/snap.go b/vendor/github.com/glycerine/go-unsnap-stream/snap.go new file mode 100644 index 0000000000..12a8d40b5b --- /dev/null +++ b/vendor/github.com/glycerine/go-unsnap-stream/snap.go @@ -0,0 +1,100 @@ +package unsnap + +import ( + "encoding/binary" + + // no c lib dependency + snappy "github.com/golang/snappy" + // or, use the C wrapper for speed + //snappy "github.com/dgryski/go-csnappy" +) + +// add Write() method for SnappyFile (see unsnap.go) + +// reference for snappy framing/streaming format: +// http://code.google.com/p/snappy/source/browse/trunk/framing_format.txt +// ?spec=svn68&r=71 + +// +// Write writes len(p) bytes from p to the underlying data stream. +// It returns the number of bytes written from p (0 <= n <= len(p)) and +// any error encountered that caused the write to stop early. Write +// must return a non-nil error if it returns n < len(p). +// +func (sf *SnappyFile) Write(p []byte) (n int, err error) { + + if sf.SnappyEncodeDecodeOff { + return sf.Writer.Write(p) + } + + if !sf.Writing { + panic("Writing on a read-only SnappyFile") + } + + // encoding in snappy can apparently go beyond the original size, beware. + // so our buffers must be sized 2*max snappy chunk => 2 * CHUNK_MAX(65536) + + sf.DecBuf.Reset() + sf.EncBuf.Reset() + + if !sf.HeaderChunkWritten { + sf.HeaderChunkWritten = true + _, err = sf.Writer.Write(SnappyStreamHeaderMagic) + if err != nil { + return + } + } + var chunk []byte + var chunk_type byte + var crc uint32 + + for len(p) > 0 { + + // chunk points to input p by default, unencoded input. + chunk = p[:IntMin(len(p), CHUNK_MAX)] + crc = masked_crc32c(chunk) + + writeme := chunk[:] + + // first write to EncBuf, as a temp, in case we want + // to discard and send uncompressed instead. + compressed_chunk := snappy.Encode(sf.EncBuf.GetEndmostWritableSlice(), chunk) + + if len(compressed_chunk) <= int((1-_COMPRESSION_THRESHOLD)*float64(len(chunk))) { + writeme = compressed_chunk + chunk_type = _COMPRESSED_CHUNK + } else { + // keep writeme pointing at original chunk (uncompressed) + chunk_type = _UNCOMPRESSED_CHUNK + } + + const crc32Sz = 4 + var tag32 uint32 = uint32(chunk_type) + (uint32(len(writeme)+crc32Sz) << 8) + + err = binary.Write(sf.Writer, binary.LittleEndian, tag32) + if err != nil { + return + } + + err = binary.Write(sf.Writer, binary.LittleEndian, crc) + if err != nil { + return + } + + _, err = sf.Writer.Write(writeme) + if err != nil { + return + } + + n += len(chunk) + p = p[len(chunk):] + } + return n, nil +} + +func IntMin(a int, b int) int { + if a < b { + return a + } + return b +} |