mirror of
https://github.com/idanoo/GoScrobble.git
synced 2024-11-25 09:55:15 +00:00
170 lines
5.2 KiB
JavaScript
170 lines
5.2 KiB
JavaScript
|
/* -*- Mode: js; js-indent-level: 2; -*- */
|
||
|
/*
|
||
|
* Copyright 2011 Mozilla Foundation and contributors
|
||
|
* Licensed under the New BSD license. See LICENSE or:
|
||
|
* http://opensource.org/licenses/BSD-3-Clause
|
||
|
*
|
||
|
* Based on the Base 64 VLQ implementation in Closure Compiler:
|
||
|
* https://code.google.com/p/closure-compiler/source/browse/trunk/src/com/google/debugging/sourcemap/Base64VLQ.java
|
||
|
*
|
||
|
* Copyright 2011 The Closure Compiler 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.
|
||
|
*/
|
||
|
|
||
|
/*eslint no-bitwise:0,quotes:0,global-strict:0*/
|
||
|
|
||
|
var charToIntMap = {};
|
||
|
var intToCharMap = {};
|
||
|
|
||
|
'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
|
||
|
.split('')
|
||
|
.forEach(function (ch, index) {
|
||
|
charToIntMap[ch] = index;
|
||
|
intToCharMap[index] = ch;
|
||
|
});
|
||
|
|
||
|
var base64 = {};
|
||
|
/**
|
||
|
* Encode an integer in the range of 0 to 63 to a single base 64 digit.
|
||
|
*/
|
||
|
base64.encode = function base64_encode(aNumber) {
|
||
|
if (aNumber in intToCharMap) {
|
||
|
return intToCharMap[aNumber];
|
||
|
}
|
||
|
throw new TypeError("Must be between 0 and 63: " + aNumber);
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* Decode a single base 64 digit to an integer.
|
||
|
*/
|
||
|
base64.decode = function base64_decode(aChar) {
|
||
|
if (aChar in charToIntMap) {
|
||
|
return charToIntMap[aChar];
|
||
|
}
|
||
|
throw new TypeError("Not a valid base 64 digit: " + aChar);
|
||
|
};
|
||
|
|
||
|
|
||
|
|
||
|
// A single base 64 digit can contain 6 bits of data. For the base 64 variable
|
||
|
// length quantities we use in the source map spec, the first bit is the sign,
|
||
|
// the next four bits are the actual value, and the 6th bit is the
|
||
|
// continuation bit. The continuation bit tells us whether there are more
|
||
|
// digits in this value following this digit.
|
||
|
//
|
||
|
// Continuation
|
||
|
// | Sign
|
||
|
// | |
|
||
|
// V V
|
||
|
// 101011
|
||
|
|
||
|
var VLQ_BASE_SHIFT = 5;
|
||
|
|
||
|
// binary: 100000
|
||
|
var VLQ_BASE = 1 << VLQ_BASE_SHIFT;
|
||
|
|
||
|
// binary: 011111
|
||
|
var VLQ_BASE_MASK = VLQ_BASE - 1;
|
||
|
|
||
|
// binary: 100000
|
||
|
var VLQ_CONTINUATION_BIT = VLQ_BASE;
|
||
|
|
||
|
/**
|
||
|
* Converts from a two-complement value to a value where the sign bit is
|
||
|
* placed in the least significant bit. For example, as decimals:
|
||
|
* 1 becomes 2 (10 binary), -1 becomes 3 (11 binary)
|
||
|
* 2 becomes 4 (100 binary), -2 becomes 5 (101 binary)
|
||
|
*/
|
||
|
function toVLQSigned(aValue) {
|
||
|
return aValue < 0
|
||
|
? ((-aValue) << 1) + 1
|
||
|
: (aValue << 1) + 0;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Converts to a two-complement value from a value where the sign bit is
|
||
|
* placed in the least significant bit. For example, as decimals:
|
||
|
* 2 (10 binary) becomes 1, 3 (11 binary) becomes -1
|
||
|
* 4 (100 binary) becomes 2, 5 (101 binary) becomes -2
|
||
|
*/
|
||
|
function fromVLQSigned(aValue) {
|
||
|
var isNegative = (aValue & 1) === 1;
|
||
|
var shifted = aValue >> 1;
|
||
|
return isNegative
|
||
|
? -shifted
|
||
|
: shifted;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Returns the base 64 VLQ encoded value.
|
||
|
*/
|
||
|
exports.encode = function base64VLQ_encode(aValue) {
|
||
|
var encoded = "";
|
||
|
var digit;
|
||
|
|
||
|
var vlq = toVLQSigned(aValue);
|
||
|
|
||
|
do {
|
||
|
digit = vlq & VLQ_BASE_MASK;
|
||
|
vlq >>>= VLQ_BASE_SHIFT;
|
||
|
if (vlq > 0) {
|
||
|
// There are still more digits in this value, so we must make sure the
|
||
|
// continuation bit is marked.
|
||
|
digit |= VLQ_CONTINUATION_BIT;
|
||
|
}
|
||
|
encoded += base64.encode(digit);
|
||
|
} while (vlq > 0);
|
||
|
|
||
|
return encoded;
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* Decodes the next base 64 VLQ value from the given string and returns the
|
||
|
* value and the rest of the string via the out parameter.
|
||
|
*/
|
||
|
exports.decode = function base64VLQ_decode(aStr, aOutParam) {
|
||
|
var i = 0;
|
||
|
var strLen = aStr.length;
|
||
|
var result = 0;
|
||
|
var shift = 0;
|
||
|
var continuation, digit;
|
||
|
|
||
|
do {
|
||
|
if (i >= strLen) {
|
||
|
throw new Error("Expected more digits in base 64 VLQ value.");
|
||
|
}
|
||
|
digit = base64.decode(aStr.charAt(i++));
|
||
|
continuation = !!(digit & VLQ_CONTINUATION_BIT);
|
||
|
digit &= VLQ_BASE_MASK;
|
||
|
result = result + (digit << shift);
|
||
|
shift += VLQ_BASE_SHIFT;
|
||
|
} while (continuation);
|
||
|
|
||
|
aOutParam.value = fromVLQSigned(result);
|
||
|
aOutParam.rest = aStr.slice(i);
|
||
|
};
|