-
Notifications
You must be signed in to change notification settings - Fork 232
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add go-snappy package directly as we need to modify it in non-sensica…
…l ways
- Loading branch information
Showing
6 changed files
with
1,022 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
Copyright (c) 2011 The Snappy-Go Authors. All rights reserved. | ||
|
||
Redistribution and use in source and binary forms, with or without | ||
modification, are permitted provided that the following conditions are | ||
met: | ||
|
||
* Redistributions of source code must retain the above copyright | ||
notice, this list of conditions and the following disclaimer. | ||
* Redistributions in binary form must reproduce the above | ||
copyright notice, this list of conditions and the following disclaimer | ||
in the documentation and/or other materials provided with the | ||
distribution. | ||
* Neither the name of Google Inc. nor the names of its | ||
contributors may be used to endorse or promote products derived from | ||
this software without specific prior written permission. | ||
|
||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
This is a Snappy library for the Go programming language that has been modified to work with Apple files, which fail to set CRC checks and stream identifiers. This version is a total hack, so if you want to use snappy for other projects **DO NOT USE THIS VERSION**. Use the proper version as per below: | ||
|
||
To download and install from source: | ||
$ go get code.google.com/p/snappy-go/snappy | ||
|
||
|
||
|
||
Unless otherwise noted, the Snappy-Go source files are distributed | ||
under the BSD-style license found in the LICENSE file. | ||
|
||
Contributions should follow the same procedure as for the Go project: | ||
http://golang.org/doc/contribute.html | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,292 @@ | ||
// Copyright 2011 The Snappy-Go Authors. All rights reserved. | ||
// Use of this source code is governed by a BSD-style | ||
// license that can be found in the LICENSE file. | ||
|
||
package snappy | ||
|
||
import ( | ||
"encoding/binary" | ||
"errors" | ||
"io" | ||
) | ||
|
||
var ( | ||
// ErrCorrupt reports that the input is invalid. | ||
ErrCorrupt = errors.New("snappy: corrupt input") | ||
// ErrUnsupported reports that the input isn't supported. | ||
ErrUnsupported = errors.New("snappy: unsupported input") | ||
) | ||
|
||
// DecodedLen returns the length of the decoded block. | ||
func DecodedLen(src []byte) (int, error) { | ||
v, _, err := decodedLen(src) | ||
return v, err | ||
} | ||
|
||
// decodedLen returns the length of the decoded block and the number of bytes | ||
// that the length header occupied. | ||
func decodedLen(src []byte) (blockLen, headerLen int, err error) { | ||
v, n := binary.Uvarint(src) | ||
if n == 0 { | ||
return 0, 0, ErrCorrupt | ||
} | ||
if uint64(int(v)) != v { | ||
return 0, 0, errors.New("snappy: decoded block is too large") | ||
} | ||
return int(v), n, nil | ||
} | ||
|
||
// Decode returns the decoded form of src. The returned slice may be a sub- | ||
// slice of dst if dst was large enough to hold the entire decoded block. | ||
// Otherwise, a newly allocated slice will be returned. | ||
// It is valid to pass a nil dst. | ||
func Decode(dst, src []byte) ([]byte, error) { | ||
dLen, s, err := decodedLen(src) | ||
if err != nil { | ||
return nil, err | ||
} | ||
if len(dst) < dLen { | ||
dst = make([]byte, dLen) | ||
} | ||
|
||
var d, offset, length int | ||
for s < len(src) { | ||
switch src[s] & 0x03 { | ||
case tagLiteral: | ||
x := uint(src[s] >> 2) | ||
switch { | ||
case x < 60: | ||
s += 1 | ||
case x == 60: | ||
s += 2 | ||
if s > len(src) { | ||
return nil, ErrCorrupt | ||
} | ||
x = uint(src[s-1]) | ||
case x == 61: | ||
s += 3 | ||
if s > len(src) { | ||
return nil, ErrCorrupt | ||
} | ||
x = uint(src[s-2]) | uint(src[s-1])<<8 | ||
case x == 62: | ||
s += 4 | ||
if s > len(src) { | ||
return nil, ErrCorrupt | ||
} | ||
x = uint(src[s-3]) | uint(src[s-2])<<8 | uint(src[s-1])<<16 | ||
case x == 63: | ||
s += 5 | ||
if s > len(src) { | ||
return nil, ErrCorrupt | ||
} | ||
x = uint(src[s-4]) | uint(src[s-3])<<8 | uint(src[s-2])<<16 | uint(src[s-1])<<24 | ||
} | ||
length = int(x + 1) | ||
if length <= 0 { | ||
return nil, errors.New("snappy: unsupported literal length") | ||
} | ||
if length > len(dst)-d || length > len(src)-s { | ||
return nil, ErrCorrupt | ||
} | ||
copy(dst[d:], src[s:s+length]) | ||
d += length | ||
s += length | ||
continue | ||
|
||
case tagCopy1: | ||
s += 2 | ||
if s > len(src) { | ||
return nil, ErrCorrupt | ||
} | ||
length = 4 + int(src[s-2])>>2&0x7 | ||
offset = int(src[s-2])&0xe0<<3 | int(src[s-1]) | ||
|
||
case tagCopy2: | ||
s += 3 | ||
if s > len(src) { | ||
return nil, ErrCorrupt | ||
} | ||
length = 1 + int(src[s-3])>>2 | ||
offset = int(src[s-2]) | int(src[s-1])<<8 | ||
|
||
case tagCopy4: | ||
return nil, errors.New("snappy: unsupported COPY_4 tag") | ||
} | ||
|
||
end := d + length | ||
if offset > d || end > len(dst) { | ||
return nil, ErrCorrupt | ||
} | ||
for ; d < end; d++ { | ||
dst[d] = dst[d-offset] | ||
} | ||
} | ||
if d != dLen { | ||
return nil, ErrCorrupt | ||
} | ||
return dst[:d], nil | ||
} | ||
|
||
// NewReader returns a new Reader that decompresses from r, using the framing | ||
// format described at | ||
// https://code.google.com/p/snappy/source/browse/trunk/framing_format.txt | ||
func NewReader(r io.Reader) *Reader { | ||
return &Reader{ | ||
r: r, | ||
decoded: make([]byte, maxUncompressedChunkLen), | ||
buf: make([]byte, MaxEncodedLen(maxUncompressedChunkLen)+checksumSize), | ||
} | ||
} | ||
|
||
// Reader is an io.Reader than can read Snappy-compressed bytes. | ||
type Reader struct { | ||
r io.Reader | ||
err error | ||
decoded []byte | ||
buf []byte | ||
// decoded[i:j] contains decoded bytes that have not yet been passed on. | ||
i, j int | ||
readHeader bool | ||
} | ||
|
||
// Reset discards any buffered data, resets all state, and switches the Snappy | ||
// reader to read from r. This permits reusing a Reader rather than allocating | ||
// a new one. | ||
func (r *Reader) Reset(reader io.Reader) { | ||
r.r = reader | ||
r.err = nil | ||
r.i = 0 | ||
r.j = 0 | ||
r.readHeader = false | ||
} | ||
|
||
func (r *Reader) readFull(p []byte) (ok bool) { | ||
if _, r.err = io.ReadFull(r.r, p); r.err != nil { | ||
if r.err == io.ErrUnexpectedEOF { | ||
r.err = ErrCorrupt | ||
} | ||
return false | ||
} | ||
return true | ||
} | ||
|
||
// Read satisfies the io.Reader interface. | ||
func (r *Reader) Read(p []byte) (int, error) { | ||
if r.err != nil { | ||
return 0, r.err | ||
} | ||
for { | ||
if r.i < r.j { | ||
n := copy(p, r.decoded[r.i:r.j]) | ||
r.i += n | ||
return n, nil | ||
} | ||
if !r.readFull(r.buf[:4]) { | ||
return 0, r.err | ||
} | ||
chunkType := r.buf[0] | ||
if !r.readHeader { | ||
if chunkType != chunkTypeStreamIdentifier { | ||
r.err = ErrCorrupt | ||
return 0, r.err | ||
} | ||
r.readHeader = true | ||
} | ||
chunkLen := int(r.buf[1]) | int(r.buf[2])<<8 | int(r.buf[3])<<16 | ||
if chunkLen > len(r.buf) { | ||
r.err = ErrUnsupported | ||
return 0, r.err | ||
} | ||
|
||
// The chunk types are specified at | ||
// https://code.google.com/p/snappy/source/browse/trunk/framing_format.txt | ||
switch chunkType { | ||
case chunkTypeCompressedData: | ||
// Section 4.2. Compressed data (chunk type 0x00). | ||
if chunkLen < checksumSize { | ||
r.err = ErrCorrupt | ||
return 0, r.err | ||
} | ||
buf := r.buf[:chunkLen] | ||
if !r.readFull(buf) { | ||
return 0, r.err | ||
} | ||
checksum := uint32(buf[0]) | uint32(buf[1])<<8 | uint32(buf[2])<<16 | uint32(buf[3])<<24 | ||
buf = buf[checksumSize:] | ||
|
||
n, err := DecodedLen(buf) | ||
if err != nil { | ||
r.err = err | ||
return 0, r.err | ||
} | ||
if n > len(r.decoded) { | ||
r.err = ErrCorrupt | ||
return 0, r.err | ||
} | ||
if _, err := Decode(r.decoded, buf); err != nil { | ||
r.err = err | ||
return 0, r.err | ||
} | ||
if crc(r.decoded[:n]) != checksum { | ||
r.err = ErrCorrupt | ||
return 0, r.err | ||
} | ||
r.i, r.j = 0, n | ||
continue | ||
|
||
case chunkTypeUncompressedData: | ||
// Section 4.3. Uncompressed data (chunk type 0x01). | ||
if chunkLen < checksumSize { | ||
r.err = ErrCorrupt | ||
return 0, r.err | ||
} | ||
buf := r.buf[:checksumSize] | ||
if !r.readFull(buf) { | ||
return 0, r.err | ||
} | ||
checksum := uint32(buf[0]) | uint32(buf[1])<<8 | uint32(buf[2])<<16 | uint32(buf[3])<<24 | ||
// Read directly into r.decoded instead of via r.buf. | ||
n := chunkLen - checksumSize | ||
if !r.readFull(r.decoded[:n]) { | ||
return 0, r.err | ||
} | ||
if crc(r.decoded[:n]) != checksum { | ||
r.err = ErrCorrupt | ||
return 0, r.err | ||
} | ||
r.i, r.j = 0, n | ||
continue | ||
|
||
case chunkTypeStreamIdentifier: | ||
// Section 4.1. Stream identifier (chunk type 0xff). | ||
if chunkLen != len(magicBody) { | ||
r.err = ErrCorrupt | ||
return 0, r.err | ||
} | ||
if !r.readFull(r.buf[:len(magicBody)]) { | ||
return 0, r.err | ||
} | ||
for i := 0; i < len(magicBody); i++ { | ||
if r.buf[i] != magicBody[i] { | ||
r.err = ErrCorrupt | ||
return 0, r.err | ||
} | ||
} | ||
continue | ||
} | ||
|
||
if chunkType <= 0x7f { | ||
// Section 4.5. Reserved unskippable chunks (chunk types 0x02-0x7f). | ||
r.err = ErrUnsupported | ||
return 0, r.err | ||
|
||
} else { | ||
// Section 4.4 Padding (chunk type 0xfe). | ||
// Section 4.6. Reserved skippable chunks (chunk types 0x80-0xfd). | ||
if !r.readFull(r.buf[:chunkLen]) { | ||
return 0, r.err | ||
} | ||
} | ||
} | ||
} |
Oops, something went wrong.