176 lines
3.7 KiB
JavaScript
176 lines
3.7 KiB
JavaScript
|
"use strict";
|
||
|
|
||
|
function pushBits(arr, n, value) {
|
||
|
for (var bit = 1 << (n - 1); bit; bit = bit >>> 1) {
|
||
|
arr.push(bit & value ? 1 : 0);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// {{{1 8bit encode
|
||
|
function encode_8bit(data) {
|
||
|
var len = data.length;
|
||
|
var bits = [];
|
||
|
|
||
|
for (var i = 0; i < len; i++) {
|
||
|
pushBits(bits, 8, data[i]);
|
||
|
}
|
||
|
|
||
|
var res = {};
|
||
|
|
||
|
var d = [0, 1, 0, 0];
|
||
|
pushBits(d, 16, len);
|
||
|
res.data10 = res.data27 = d.concat(bits);
|
||
|
|
||
|
if (len < 256) {
|
||
|
var d = [0, 1, 0, 0];
|
||
|
pushBits(d, 8, len);
|
||
|
res.data1 = d.concat(bits);
|
||
|
}
|
||
|
|
||
|
return res;
|
||
|
}
|
||
|
|
||
|
// {{{1 alphanumeric encode
|
||
|
var ALPHANUM = (function (s) {
|
||
|
var res = {};
|
||
|
for (var i = 0; i < s.length; i++) {
|
||
|
res[s[i]] = i;
|
||
|
}
|
||
|
return res;
|
||
|
})('0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ $%*+-./:');
|
||
|
|
||
|
function encode_alphanum(str) {
|
||
|
var len = str.length;
|
||
|
var bits = [];
|
||
|
|
||
|
for (var i = 0; i < len; i += 2) {
|
||
|
var b = 6;
|
||
|
var n = ALPHANUM[str[i]];
|
||
|
if (str[i + 1]) {
|
||
|
b = 11;
|
||
|
n = n * 45 + ALPHANUM[str[i + 1]];
|
||
|
}
|
||
|
pushBits(bits, b, n);
|
||
|
}
|
||
|
|
||
|
var res = {};
|
||
|
|
||
|
var d = [0, 0, 1, 0];
|
||
|
pushBits(d, 13, len);
|
||
|
res.data27 = d.concat(bits);
|
||
|
|
||
|
if (len < 2048) {
|
||
|
var d = [0, 0, 1, 0];
|
||
|
pushBits(d, 11, len);
|
||
|
res.data10 = d.concat(bits);
|
||
|
}
|
||
|
|
||
|
if (len < 512) {
|
||
|
var d = [0, 0, 1, 0];
|
||
|
pushBits(d, 9, len);
|
||
|
res.data1 = d.concat(bits);
|
||
|
}
|
||
|
|
||
|
return res;
|
||
|
}
|
||
|
|
||
|
// {{{1 numeric encode
|
||
|
function encode_numeric(str) {
|
||
|
var len = str.length;
|
||
|
var bits = [];
|
||
|
|
||
|
for (var i = 0; i < len; i += 3) {
|
||
|
var s = str.substr(i, 3);
|
||
|
var b = Math.ceil(s.length * 10 / 3);
|
||
|
pushBits(bits, b, parseInt(s, 10));
|
||
|
}
|
||
|
|
||
|
var res = {};
|
||
|
|
||
|
var d = [0, 0, 0, 1];
|
||
|
pushBits(d, 14, len);
|
||
|
res.data27 = d.concat(bits);
|
||
|
|
||
|
if (len < 4096) {
|
||
|
var d = [0, 0, 0, 1];
|
||
|
pushBits(d, 12, len);
|
||
|
res.data10 = d.concat(bits);
|
||
|
}
|
||
|
|
||
|
if (len < 1024) {
|
||
|
var d = [0, 0, 0, 1];
|
||
|
pushBits(d, 10, len);
|
||
|
res.data1 = d.concat(bits);
|
||
|
}
|
||
|
|
||
|
return res;
|
||
|
}
|
||
|
|
||
|
// {{{1 url encode
|
||
|
function encode_url(str) {
|
||
|
var slash = str.indexOf('/', 8) + 1 || str.length;
|
||
|
var res = encode(str.slice(0, slash).toUpperCase(), false);
|
||
|
|
||
|
if (slash >= str.length) {
|
||
|
return res;
|
||
|
}
|
||
|
|
||
|
var path_res = encode(str.slice(slash), false);
|
||
|
|
||
|
res.data27 = res.data27.concat(path_res.data27);
|
||
|
|
||
|
if (res.data10 && path_res.data10) {
|
||
|
res.data10 = res.data10.concat(path_res.data10);
|
||
|
}
|
||
|
|
||
|
if (res.data1 && path_res.data1) {
|
||
|
res.data1 = res.data1.concat(path_res.data1);
|
||
|
}
|
||
|
|
||
|
return res;
|
||
|
}
|
||
|
|
||
|
// {{{1 Choose encode mode and generates struct with data for different version
|
||
|
function encode(data, parse_url) {
|
||
|
var str;
|
||
|
var t = typeof data;
|
||
|
|
||
|
if (t == 'string' || t == 'number') {
|
||
|
str = '' + data;
|
||
|
data = Buffer.from(str);
|
||
|
} else if (Buffer.isBuffer(data)) {
|
||
|
str = data.toString();
|
||
|
} else if (Array.isArray(data)) {
|
||
|
data = Buffer.from(data);
|
||
|
str = data.toString();
|
||
|
} else {
|
||
|
throw new Error("Bad data");
|
||
|
}
|
||
|
|
||
|
if (/^[0-9]+$/.test(str)) {
|
||
|
if (data.length > 7089) {
|
||
|
throw new Error("Too much data");
|
||
|
}
|
||
|
return encode_numeric(str);
|
||
|
}
|
||
|
|
||
|
if (/^[0-9A-Z \$%\*\+\.\/\:\-]+$/.test(str)) {
|
||
|
if (data.length > 4296) {
|
||
|
throw new Error("Too much data");
|
||
|
}
|
||
|
return encode_alphanum(str);
|
||
|
}
|
||
|
|
||
|
if (parse_url && /^https?:/i.test(str)) {
|
||
|
return encode_url(str);
|
||
|
}
|
||
|
|
||
|
if (data.length > 2953) {
|
||
|
throw new Error("Too much data");
|
||
|
}
|
||
|
return encode_8bit(data);
|
||
|
}
|
||
|
|
||
|
// {{{1 export functions
|
||
|
module.exports = encode;
|