snappyjs
Version:
JavaScript implementation of Google's Snappy compression library
133 lines (122 loc) • 3.72 kB
JavaScript
// The MIT License (MIT)
//
// Copyright (c) 2016 Zhipeng Jia
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
'use strict'
var WORD_MASK = [0, 0xff, 0xffff, 0xffffff, 0xffffffff]
function copyBytes (fromArray, fromPos, toArray, toPos, length) {
var i
for (i = 0; i < length; i++) {
toArray[toPos + i] = fromArray[fromPos + i]
}
}
function selfCopyBytes (array, pos, offset, length) {
var i
for (i = 0; i < length; i++) {
array[pos + i] = array[pos - offset + i]
}
}
function SnappyDecompressor (compressed) {
this.array = compressed
this.pos = 0
}
SnappyDecompressor.prototype.readUncompressedLength = function () {
var result = 0
var shift = 0
var c, val
while (shift < 32 && this.pos < this.array.length) {
c = this.array[this.pos]
this.pos += 1
val = c & 0x7f
if (((val << shift) >>> shift) !== val) {
return -1
}
result |= val << shift
if (c < 128) {
return result
}
shift += 7
}
return -1
}
SnappyDecompressor.prototype.uncompressToBuffer = function (outBuffer) {
var array = this.array
var arrayLength = array.length
var pos = this.pos
var outPos = 0
var c, len, smallLen
var offset
while (pos < array.length) {
c = array[pos]
pos += 1
if ((c & 0x3) === 0) {
// Literal
len = (c >>> 2) + 1
if (len > 60) {
if (pos + 3 >= arrayLength) {
return false
}
smallLen = len - 60
len = array[pos] + (array[pos + 1] << 8) + (array[pos + 2] << 16) + (array[pos + 3] << 24)
len = (len & WORD_MASK[smallLen]) + 1
pos += smallLen
}
if (pos + len > arrayLength) {
return false
}
copyBytes(array, pos, outBuffer, outPos, len)
pos += len
outPos += len
} else {
switch (c & 0x3) {
case 1:
len = ((c >>> 2) & 0x7) + 4
offset = array[pos] + ((c >>> 5) << 8)
pos += 1
break
case 2:
if (pos + 1 >= arrayLength) {
return false
}
len = (c >>> 2) + 1
offset = array[pos] + (array[pos + 1] << 8)
pos += 2
break
case 3:
if (pos + 3 >= arrayLength) {
return false
}
len = (c >>> 2) + 1
offset = array[pos] + (array[pos + 1] << 8) + (array[pos + 2] << 16) + (array[pos + 3] << 24)
pos += 4
break
default:
break
}
if (offset === 0 || offset > outPos) {
return false
}
selfCopyBytes(outBuffer, outPos, offset, len)
outPos += len
}
}
return true
}
exports.SnappyDecompressor = SnappyDecompressor