Reading binary files.

Support for reading binary files and some cleanup regarding the move
from manual callbacks to promises.
This commit is contained in:
peter-x 2016-01-05 18:18:58 +01:00
parent 7bb77c8e36
commit 72e4da5e02
6 changed files with 87 additions and 71 deletions

File diff suppressed because one or more lines are too long

View File

@ -517,5 +517,22 @@ define(['jquery', 'title', 'archive', 'zimArchive', 'zimDirEntry', 'util', 'geom
});
});
});
asyncTest("Image 'I/m/RayCharles_AManAndHisSoul.jpg' can be loaded", function() {
expect(6);
localZimArchive.getTitleByName("(The_Night_Time_Is)_The_Right_Time.html", function(title) {
console.log(title);
ok(title !== null, "Title found");
ok(title.isRedirect(), "Title is a redirect.");
localZimArchive.resolveRedirect(title, function(title) {
ok(title !== null, "Title found");
ok(!title.isRedirect(), "Title is not a redirect.");
localZimArchive.readBinaryFile(title, function(title, data) {
ok(data.length === 58666, "Data length is correct.");
ok(data[361] === 121, "Data is correct at some point.");
start();
});
});
});
});
};
});

View File

@ -768,24 +768,23 @@ define(['jquery', 'abstractBackend', 'util', 'cookies','geometry','osabstraction
console.log("we are asked for a content : let's try to answer to this message");
var titleName = event.data.titleName;
var messagePort = event.ports[0];
selectedArchive.getTitleByName(titleName, function(title) {
// TODO handle other content types
// TODO a Promise would avoid duplicating the code here
// Cf https://github.com/mossroy/evopedia-html5/issues/67
var readFile = function(title) {
console.log("Found title.");
if (title.isRedirect()) {
selectedArchive.resolveRedirect(title, function(title) {
selectedArchive.readArticle(title, function(readableTitleName, content) {
console.log("Following redirect...");
selectedArchive.resolveRedirect(title, readFile);
} else {
console.log("Reading binary file...");
selectedArchive.readBinaryFile(title, function(readableTitleName, content) {
messagePort.postMessage({'action': 'giveContent', 'titleName' : titleName, 'content': content});
console.log("content sent to ServiceWorker (after a redirect)");
});
console.log("content sent to ServiceWorker)");
});
}
else {
selectedArchive.readArticle(title, function(readableTitleName, content) {
messagePort.postMessage({'action': 'giveContent', 'titleName' : titleName, 'content': content});
console.log("content sent to ServiceWorker");
});
}
console.log("Fetching tile " + titleName);
selectedArchive.getTitleByName(titleName).then(readFile).fail(function() {
console.log("could not find title:" + arguments);
messagePort.postMessage({'action': 'giveContent', 'titleName' : titleName, 'content': new UInt8Array()});
});
}
else {
@ -966,7 +965,7 @@ define(['jquery', 'abstractBackend', 'util', 'cookies','geometry','osabstraction
* @param {String} titleName
*/
function goToArticle(titleName) {
selectedArchive.getTitleByName(titleName, function(title) {
selectedArchive.getTitleByName(titleName).then(function(title) {
if (title === null || title === undefined) {
$("#readingArticle").hide();
alert("Article with title " + titleName + " not found in the archive");
@ -977,7 +976,7 @@ define(['jquery', 'abstractBackend', 'util', 'cookies','geometry','osabstraction
$('#articleContent').contents().find('body').html("");
readArticle(title);
}
});
}).fail(function() { alert("Error reading title " + titleName); });
}
/**

View File

@ -332,23 +332,17 @@ define(['normalize_string', 'geometry', 'title', 'util', 'titleIterators', 'q'],
}).then(callbackFunction, errorHandler);
};
/**
* @callback callbackTitle
* @param {Title} title Title found
*/
/**
* Look for a title by its name, and call the callbackFunction with this Title
* If the title is not found, the callbackFunction is called with parameter null
* @param {String} titleName
* @param {callbackTitle} callbackFunction
*/
LocalArchive.prototype.getTitleByName = function(titleName, callbackFunction) {
LocalArchive.prototype.getTitleByName = function(titleName) {
var that = this;
var normalize = this.getNormalizeFunction();
var normalizedTitleName = normalize(titleName);
titleIterators.findPrefixOffset(this._titleFile, titleName, normalize).then(function(offset) {
return titleIterators.findPrefixOffset(this._titleFile, titleName, normalize).then(function(offset) {
var iterator = new titleIterators.SequentialTitleIterator(that, offset);
function check(title) {
if (title === null || normalize(title._name) !== normalizedTitleName) {
@ -360,7 +354,7 @@ define(['normalize_string', 'geometry', 'title', 'util', 'titleIterators', 'q'],
}
}
return iterator.advance().then(check);
}).then(callbackFunction, errorHandler);
});
};
/**

View File

@ -20,8 +20,8 @@
* along with Evopedia (file LICENSE-GPLv3.txt). If not, see <http://www.gnu.org/licenses/>
*/
'use strict';
define(['zimfile', 'zimDirEntry', 'util'],
function(zimfile, zimDirEntry, util) {
define(['zimfile', 'zimDirEntry', 'util', 'utf8'],
function(zimfile, zimDirEntry, util, utf8) {
/**
* ZIM Archive
@ -176,6 +176,22 @@ define(['zimfile', 'zimDirEntry', 'util'],
* @param {callbackStringContent} callback
*/
ZIMArchive.prototype.readArticle = function(title, callback) {
return title.readData().then(function(data) {
callback(title.name(), utf8.parse(data));
});
};
/**
* @callback callbackBinaryContent
* @param {Uint8Array} content binary content
*/
/**
* Read a binary file.
* @param {DirEntry} title
* @param {callbackBinaryContent} callback
*/
ZIMArchive.prototype.readBinaryFile = function(title, callback) {
return title.readData().then(function(data) {
callback(title.name(), data);
});
@ -184,11 +200,10 @@ define(['zimfile', 'zimDirEntry', 'util'],
/**
*
* @param {String} titleName
* @param {callbackTitle} callback
*/
ZIMArchive.prototype.getTitleByName = function(titleName, callback) {
ZIMArchive.prototype.getTitleByName = function(titleName) {
var that = this;
util.binarySearch(0, this._file.articleCount, function(i) {
return util.binarySearch(0, this._file.articleCount, function(i) {
return that._file.dirEntryByUrlIndex(i).then(function(dirEntry) {
if (titleName < dirEntry.url)
return -1;
@ -200,7 +215,7 @@ define(['zimfile', 'zimDirEntry', 'util'],
}).then(function(index) {
return that._file.dirEntryByUrlIndex(index);
}).then(function(dirEntry) {
callback(that._dirEntryToTitleObject(dirEntry));
return that._dirEntryToTitleObject(dirEntry);
});
};

View File

@ -159,17 +159,26 @@ define(['xzdec_wrapper', 'util', 'utf8'], function(xz, util, utf8) {
{
var clusterOffset = readInt(clusterOffsets, 0, 8);
var nextCluster = readInt(clusterOffsets, 8, 8);
//@todo we assume it is compressed - handle uncompressed (first byte at clusterOffset)
var reader = function(offset, size) {
return that._readSlice(clusterOffset, 1).then(function(compressionType) {
var decompressor;
var plainBlobReader = function(offset, size) {
return that._readSlice(clusterOffset + 1 + offset, size);
};
var dec = new xz.Decompressor(reader);
return dec.readSlice(blob * 4, 8).then(function(data) {
if (compressionType[0] === 0 || compressionType[0] === 1) {
// uncompressed
decompressor = { readSlice: plainBlobReader, end: function() {} };
} else if (compressionType[0] === 4) {
decompressor = new xz.Decompressor(plainBlobReader);
} else {
return new Uint8Array(); // unsupported compression type
}
return decompressor.readSlice(blob * 4, 8).then(function(data) {
var blobOffset = readInt(data, 0, 4);
var nextBlobOffset = readInt(data, 4, 4);
return dec.readSlice(blobOffset, nextBlobOffset - blobOffset).then(function(data) {
dec.end();
return utf8.parse(data);
return decompressor.readSlice(blobOffset, nextBlobOffset - blobOffset).then(function(data) {
decompressor.end();
return data;
});
});
});
});