| 
							- 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
 - }
 
 
  |