github.com/insionng/yougam@v0.0.0-20170714101924-2bc18d833463/libraries/golang/snappy/decode_other.go (about)

     1  // Copyright 2016 The Snappy-Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  // +build !amd64 !gc
     6  
     7  package snappy
     8  
     9  // decode writes the decoding of src to dst. It assumes that the varint-encoded
    10  // length of the decompressed bytes has already been read, and that len(dst)
    11  // equals that length.
    12  //
    13  // It returns 0 on success or a decodeErrCodeXxx error code on failure.
    14  func decode(dst, src []byte) int {
    15  	var d, s, offset, length int
    16  	for s < len(src) {
    17  		switch src[s] & 0x03 {
    18  		case tagLiteral:
    19  			x := uint32(src[s] >> 2)
    20  			switch {
    21  			case x < 60:
    22  				s++
    23  			case x == 60:
    24  				s += 2
    25  				if uint(s) > uint(len(src)) { // The uint conversions catch overflow from the previous line.
    26  					return decodeErrCodeCorrupt
    27  				}
    28  				x = uint32(src[s-1])
    29  			case x == 61:
    30  				s += 3
    31  				if uint(s) > uint(len(src)) { // The uint conversions catch overflow from the previous line.
    32  					return decodeErrCodeCorrupt
    33  				}
    34  				x = uint32(src[s-2]) | uint32(src[s-1])<<8
    35  			case x == 62:
    36  				s += 4
    37  				if uint(s) > uint(len(src)) { // The uint conversions catch overflow from the previous line.
    38  					return decodeErrCodeCorrupt
    39  				}
    40  				x = uint32(src[s-3]) | uint32(src[s-2])<<8 | uint32(src[s-1])<<16
    41  			case x == 63:
    42  				s += 5
    43  				if uint(s) > uint(len(src)) { // The uint conversions catch overflow from the previous line.
    44  					return decodeErrCodeCorrupt
    45  				}
    46  				x = uint32(src[s-4]) | uint32(src[s-3])<<8 | uint32(src[s-2])<<16 | uint32(src[s-1])<<24
    47  			}
    48  			length = int(x) + 1
    49  			if length <= 0 {
    50  				return decodeErrCodeUnsupportedLiteralLength
    51  			}
    52  			if length > len(dst)-d || length > len(src)-s {
    53  				return decodeErrCodeCorrupt
    54  			}
    55  			copy(dst[d:], src[s:s+length])
    56  			d += length
    57  			s += length
    58  			continue
    59  
    60  		case tagCopy1:
    61  			s += 2
    62  			if uint(s) > uint(len(src)) { // The uint conversions catch overflow from the previous line.
    63  				return decodeErrCodeCorrupt
    64  			}
    65  			length = 4 + int(src[s-2])>>2&0x7
    66  			offset = int(src[s-2])&0xe0<<3 | int(src[s-1])
    67  
    68  		case tagCopy2:
    69  			s += 3
    70  			if uint(s) > uint(len(src)) { // The uint conversions catch overflow from the previous line.
    71  				return decodeErrCodeCorrupt
    72  			}
    73  			length = 1 + int(src[s-3])>>2
    74  			offset = int(src[s-2]) | int(src[s-1])<<8
    75  
    76  		case tagCopy4:
    77  			return decodeErrCodeUnsupportedCopy4Tag
    78  		}
    79  
    80  		if offset <= 0 || d < offset || length > len(dst)-d {
    81  			return decodeErrCodeCorrupt
    82  		}
    83  		// Copy from an earlier sub-slice of dst to a later sub-slice. Unlike
    84  		// the built-in copy function, this byte-by-byte copy always runs
    85  		// forwards, even if the slices overlap. Conceptually, this is:
    86  		//
    87  		// d += forwardCopy(dst[d:d+length], dst[d-offset:])
    88  		for end := d + length; d != end; d++ {
    89  			dst[d] = dst[d-offset]
    90  		}
    91  	}
    92  	if d != len(dst) {
    93  		return decodeErrCodeCorrupt
    94  	}
    95  	return 0
    96  }