Commit 7982ed87 authored by subdiox's avatar subdiox

Downgrade bitjs to es5 branch

parent c0d136cc
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
...@@ -14,60 +14,42 @@ ...@@ -14,60 +14,42 @@
importScripts('../io/bytestream.js'); importScripts('../io/bytestream.js');
importScripts('archive.js'); importScripts('archive.js');
const UnarchiveState = {
NOT_STARTED: 0,
UNARCHIVING: 1,
WAITING: 2,
FINISHED: 3,
};
// State - consider putting these into a class.
let unarchiveState = UnarchiveState.NOT_STARTED;
let bytestream = null;
let allLocalFiles = null;
let logToConsole = false;
// Progress variables. // Progress variables.
let currentFilename = ""; var currentFilename = "";
let currentFileNumber = 0; var currentFileNumber = 0;
let currentBytesUnarchivedInFile = 0; var currentBytesUnarchivedInFile = 0;
let currentBytesUnarchived = 0; var currentBytesUnarchived = 0;
let totalUncompressedBytesInArchive = 0; var totalUncompressedBytesInArchive = 0;
let totalFilesInArchive = 0; var totalFilesInArchive = 0;
// Helper functions. // Helper functions.
const info = function(str) { var info = function(str) {
postMessage(new bitjs.archive.UnarchiveInfoEvent(str)); postMessage(new bitjs.archive.UnarchiveInfoEvent(str));
}; };
const err = function(str) { var err = function(str) {
postMessage(new bitjs.archive.UnarchiveErrorEvent(str)); postMessage(new bitjs.archive.UnarchiveErrorEvent(str));
}; };
const postProgress = function() { var postProgress = function() {
postMessage(new bitjs.archive.UnarchiveProgressEvent( postMessage(new bitjs.archive.UnarchiveProgressEvent(
currentFilename, currentFilename,
currentFileNumber, currentFileNumber,
currentBytesUnarchivedInFile, currentBytesUnarchivedInFile,
currentBytesUnarchived, currentBytesUnarchived,
totalUncompressedBytesInArchive, totalUncompressedBytesInArchive,
totalFilesInArchive, totalFilesInArchive));
bytestream.getNumBytesRead(),
));
}; };
// Removes all characters from the first zero-byte in the string onwards. // Removes all characters from the first zero-byte in the string onwards.
const readCleanString = function(bstr, numBytes) { var readCleanString = function(bstr, numBytes) {
const str = bstr.readString(numBytes); var str = bstr.readString(numBytes);
const zIndex = str.indexOf(String.fromCharCode(0)); var zIndex = str.indexOf(String.fromCharCode(0));
return zIndex != -1 ? str.substr(0, zIndex) : str; return zIndex != -1 ? str.substr(0, zIndex) : str;
}; };
class TarLocalFile { // takes a ByteStream and parses out the local file information
// takes a ByteStream and parses out the local file information var TarLocalFile = function(bstream) {
constructor(bstream) {
this.isValid = false; this.isValid = false;
let bytesRead = 0;
// Read in the header block // Read in the header block
this.name = readCleanString(bstream, 100); this.name = readCleanString(bstream, 100);
this.mode = readCleanString(bstream, 8); this.mode = readCleanString(bstream, 8);
...@@ -96,8 +78,6 @@ class TarLocalFile { ...@@ -96,8 +78,6 @@ class TarLocalFile {
bstream.readBytes(255); // 512 - 257 bstream.readBytes(255); // 512 - 257
} }
bytesRead += 512;
// Done header, now rest of blocks are the file contents. // Done header, now rest of blocks are the file contents.
this.filename = this.name; this.filename = this.name;
this.fileData = null; this.fileData = null;
...@@ -109,98 +89,102 @@ class TarLocalFile { ...@@ -109,98 +89,102 @@ class TarLocalFile {
// A regular file. // A regular file.
if (this.typeflag == 0) { if (this.typeflag == 0) {
info(" This is a regular file."); info(" This is a regular file.");
const sizeInBytes = parseInt(this.size); var sizeInBytes = parseInt(this.size);
this.fileData = new Uint8Array(bstream.readBytes(sizeInBytes)); this.fileData = new Uint8Array(bstream.bytes.buffer, bstream.ptr, this.size);
bytesRead += sizeInBytes;
if (this.name.length > 0 && this.size > 0 && this.fileData && this.fileData.buffer) { if (this.name.length > 0 && this.size > 0 && this.fileData && this.fileData.buffer) {
this.isValid = true; this.isValid = true;
} }
bstream.readBytes(this.size);
// Round up to 512-byte blocks. // Round up to 512-byte blocks.
const remaining = 512 - bytesRead % 512; var remaining = 512 - bstream.ptr % 512;
if (remaining > 0 && remaining < 512) { if (remaining > 0 && remaining < 512) {
bstream.readBytes(remaining); bstream.readBytes(remaining);
} }
} else if (this.typeflag == 5) { } else if (this.typeflag == 5) {
info(" This is a directory.") info(" This is a directory.")
} }
} };
}
const untar = function() { // Takes an ArrayBuffer of a tar file in
let bstream = bytestream.tee(); // returns null on error
// returns an array of DecompressedFile objects on success
var untar = function(arrayBuffer) {
currentFilename = "";
currentFileNumber = 0;
currentBytesUnarchivedInFile = 0;
currentBytesUnarchived = 0;
totalUncompressedBytesInArchive = 0;
totalFilesInArchive = 0;
postMessage(new bitjs.archive.UnarchiveStartEvent());
var bstream = new bitjs.io.ByteStream(arrayBuffer);
var localFiles = [];
// While we don't encounter an empty block, keep making TarLocalFiles. // While we don't encounter an empty block, keep making TarLocalFiles.
while (bstream.peekNumber(4) != 0) { while (bstream.peekNumber(4) != 0) {
const oneLocalFile = new TarLocalFile(bstream); var oneLocalFile = new TarLocalFile(bstream);
if (oneLocalFile && oneLocalFile.isValid) { if (oneLocalFile && oneLocalFile.isValid) {
// If we make it to this point and haven't thrown an error, we have successfully localFiles.push(oneLocalFile);
// read in the data for a local file, so we can update the actual bytestream.
bytestream = bstream.tee();
allLocalFiles.push(oneLocalFile);
totalUncompressedBytesInArchive += oneLocalFile.size; totalUncompressedBytesInArchive += oneLocalFile.size;
// update progress
currentFilename = oneLocalFile.filename;
currentFileNumber = totalFilesInArchive++;
currentBytesUnarchivedInFile = oneLocalFile.size;
currentBytesUnarchived += oneLocalFile.size;
postMessage(new bitjs.archive.UnarchiveExtractEvent(oneLocalFile));
postProgress();
} }
} }
totalFilesInArchive = allLocalFiles.length; totalFilesInArchive = localFiles.length;
// got all local files, now sort them
localFiles.sort(function(a,b) {
var aname = a.filename;
var bname = b.filename;
return aname > bname ? 1 : -1;
// extract the number at the end of both filenames
/*
var aname = a.filename;
var bname = b.filename;
var aindex = aname.length, bindex = bname.length;
// Find the last number character from the back of the filename.
while (aname[aindex-1] < '0' || aname[aindex-1] > '9') --aindex;
while (bname[bindex-1] < '0' || bname[bindex-1] > '9') --bindex;
// Find the first number character from the back of the filename
while (aname[aindex-1] >= '0' && aname[aindex-1] <= '9') --aindex;
while (bname[bindex-1] >= '0' && bname[bindex-1] <= '9') --bindex;
// parse them into numbers and return comparison
var anum = parseInt(aname.substr(aindex), 10),
bnum = parseInt(bname.substr(bindex), 10);
return anum - bnum;
*/
});
// report # files and total length
if (localFiles.length > 0) {
postProgress(); postProgress();
bytestream = bstream.tee();
};
// event.data.file has the first ArrayBuffer.
// event.data.bytes has all subsequent ArrayBuffers.
onmessage = function(event) {
const bytes = event.data.file || event.data.bytes;
logToConsole = !!event.data.logToConsole;
// This is the very first time we have been called. Initialize the bytestream.
if (!bytestream) {
bytestream = new bitjs.io.ByteStream(bytes);
} else {
bytestream.push(bytes);
} }
if (unarchiveState === UnarchiveState.NOT_STARTED) { // now do the shipping of each file
currentFilename = ""; for (var i = 0; i < localFiles.length; ++i) {
currentFileNumber = 0; var localfile = localFiles[i];
currentBytesUnarchivedInFile = 0; info("Sending file '" + localfile.filename + "' up");
currentBytesUnarchived = 0;
totalUncompressedBytesInArchive = 0;
totalFilesInArchive = 0;
allLocalFiles = [];
postMessage(new bitjs.archive.UnarchiveStartEvent());
unarchiveState = UnarchiveState.UNARCHIVING;
// update progress
currentFilename = localfile.filename;
currentFileNumber = i;
currentBytesUnarchivedInFile = localfile.size;
currentBytesUnarchived += localfile.size;
postMessage(new bitjs.archive.UnarchiveExtractEvent(localfile));
postProgress(); postProgress();
} }
if (unarchiveState === UnarchiveState.UNARCHIVING || postProgress();
unarchiveState === UnarchiveState.WAITING) {
try {
untar();
unarchiveState = UnarchiveState.FINISHED;
postMessage(new bitjs.archive.UnarchiveFinishEvent()); postMessage(new bitjs.archive.UnarchiveFinishEvent());
} catch (e) { };
if (typeof e === 'string' && e.startsWith('Error! Overflowed')) {
// Overrun the buffer. // event.data.file has the ArrayBuffer.
unarchiveState = UnarchiveState.WAITING; onmessage = function(event) {
} else { var ab = event.data.file;
console.error('Found an error while untarring'); untar(ab);
console.dir(e);
throw e;
}
}
}
}; };
This diff is collapsed.
This diff is collapsed.
...@@ -12,48 +12,50 @@ ...@@ -12,48 +12,50 @@
var bitjs = bitjs || {}; var bitjs = bitjs || {};
bitjs.io = bitjs.io || {}; bitjs.io = bitjs.io || {};
(function() {
/** /**
* A write-only Byte buffer which uses a Uint8 Typed Array as a backing store. * A write-only Byte buffer which uses a Uint8 Typed Array as a backing store.
*/
bitjs.io.ByteBuffer = class {
/**
* @param {number} numBytes The number of bytes to allocate. * @param {number} numBytes The number of bytes to allocate.
* @constructor
*/ */
constructor(numBytes) { bitjs.io.ByteBuffer = function(numBytes) {
if (typeof numBytes != typeof 1 || numBytes <= 0) { if (typeof numBytes != typeof 1 || numBytes <= 0) {
throw "Error! ByteBuffer initialized with '" + numBytes + "'"; throw "Error! ByteBuffer initialized with '" + numBytes + "'";
} }
this.data = new Uint8Array(numBytes); this.data = new Uint8Array(numBytes);
this.ptr = 0; this.ptr = 0;
} };
/** /**
* @param {number} b The byte to insert. * @param {number} b The byte to insert.
*/ */
insertByte(b) { bitjs.io.ByteBuffer.prototype.insertByte = function(b) {
// TODO: throw if byte is invalid? // TODO: throw if byte is invalid?
this.data[this.ptr++] = b; this.data[this.ptr++] = b;
} };
/**
/**
* @param {Array.<number>|Uint8Array|Int8Array} bytes The bytes to insert. * @param {Array.<number>|Uint8Array|Int8Array} bytes The bytes to insert.
*/ */
insertBytes(bytes) { bitjs.io.ByteBuffer.prototype.insertBytes = function(bytes) {
// TODO: throw if bytes is invalid? // TODO: throw if bytes is invalid?
this.data.set(bytes, this.ptr); this.data.set(bytes, this.ptr);
this.ptr += bytes.length; this.ptr += bytes.length;
} };
/** /**
* Writes an unsigned number into the next n bytes. If the number is too large * Writes an unsigned number into the next n bytes. If the number is too large
* to fit into n bytes or is negative, an error is thrown. * to fit into n bytes or is negative, an error is thrown.
* @param {number} num The unsigned number to write. * @param {number} num The unsigned number to write.
* @param {number} numBytes The number of bytes to write the number into. * @param {number} numBytes The number of bytes to write the number into.
*/ */
writeNumber(num, numBytes) { bitjs.io.ByteBuffer.prototype.writeNumber = function(num, numBytes) {
if (numBytes < 1 || !numBytes) { if (numBytes < 1) {
throw 'Trying to write into too few bytes: ' + numBytes; throw 'Trying to write into too few bytes: ' + numBytes;
} }
if (num < 0) { if (num < 0) {
...@@ -65,53 +67,56 @@ bitjs.io.ByteBuffer = class { ...@@ -65,53 +67,56 @@ bitjs.io.ByteBuffer = class {
} }
// Roll 8-bits at a time into an array of bytes. // Roll 8-bits at a time into an array of bytes.
const bytes = []; var bytes = [];
while (numBytes-- > 0) { while (numBytes-- > 0) {
const eightBits = num & 255; var eightBits = num & 255;
bytes.push(eightBits); bytes.push(eightBits);
num >>= 8; num >>= 8;
} }
this.insertBytes(bytes); this.insertBytes(bytes);
} };
/**
/**
* Writes a signed number into the next n bytes. If the number is too large * Writes a signed number into the next n bytes. If the number is too large
* to fit into n bytes, an error is thrown. * to fit into n bytes, an error is thrown.
* @param {number} num The signed number to write. * @param {number} num The signed number to write.
* @param {number} numBytes The number of bytes to write the number into. * @param {number} numBytes The number of bytes to write the number into.
*/ */
writeSignedNumber(num, numBytes) { bitjs.io.ByteBuffer.prototype.writeSignedNumber = function(num, numBytes) {
if (numBytes < 1) { if (numBytes < 1) {
throw 'Trying to write into too few bytes: ' + numBytes; throw 'Trying to write into too few bytes: ' + numBytes;
} }
const HALF = Math.pow(2, (numBytes * 8) - 1); var HALF = Math.pow(2, (numBytes * 8) - 1);
if (num >= HALF || num < -HALF) { if (num >= HALF || num < -HALF) {
throw 'Trying to write ' + num + ' into only ' + numBytes + ' bytes'; throw 'Trying to write ' + num + ' into only ' + numBytes + ' bytes';
} }
// Roll 8-bits at a time into an array of bytes. // Roll 8-bits at a time into an array of bytes.
const bytes = []; var bytes = [];
while (numBytes-- > 0) { while (numBytes-- > 0) {
const eightBits = num & 255; var eightBits = num & 255;
bytes.push(eightBits); bytes.push(eightBits);
num >>= 8; num >>= 8;
} }
this.insertBytes(bytes); this.insertBytes(bytes);
} };
/** /**
* @param {string} str The ASCII string to write. * @param {string} str The ASCII string to write.
*/ */
writeASCIIString(str) { bitjs.io.ByteBuffer.prototype.writeASCIIString = function(str) {
for (let i = 0; i < str.length; ++i) { for (var i = 0; i < str.length; ++i) {
const curByte = str.charCodeAt(i); var curByte = str.charCodeAt(i);
if (curByte < 0 || curByte > 255) { if (curByte < 0 || curByte > 255) {
throw 'Trying to write a non-ASCII string!'; throw 'Trying to write a non-ASCII string!';
} }
this.insertByte(curByte); this.insertByte(curByte);
} }
}; };
}
})();
This diff is collapsed.
...@@ -160,7 +160,7 @@ function initProgressClick() { ...@@ -160,7 +160,7 @@ function initProgressClick() {
function loadFromArrayBuffer(ab) { function loadFromArrayBuffer(ab) {
var start = (new Date).getTime(); var start = (new Date).getTime();
var h = new Uint8Array(ab, 0, 10); var h = new Uint8Array(ab, 0, 10);
var pathToBitJS = "../../static/js/"; var pathToBitJS = "../../static/js/archive/";
if (h[0] === 0x52 && h[1] === 0x61 && h[2] === 0x72 && h[3] === 0x21) { //Rar! if (h[0] === 0x52 && h[1] === 0x61 && h[2] === 0x72 && h[3] === 0x21) { //Rar!
unarchiver = new bitjs.archive.Unrarrer(ab, pathToBitJS); unarchiver = new bitjs.archive.Unrarrer(ab, pathToBitJS);
} else if (h[0] === 80 && h[1] === 75) { //PK (Zip) } else if (h[0] === 80 && h[1] === 75) { //PK (Zip)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment