summaryrefslogtreecommitdiffstats
path: root/vendor/github.com/glycerine/go-unsnap-stream/snap.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/glycerine/go-unsnap-stream/snap.go')
-rw-r--r--vendor/github.com/glycerine/go-unsnap-stream/snap.go100
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
+}