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"); console.log("we are asked for a content : let's try to answer to this message");
var titleName = event.data.titleName; var titleName = event.data.titleName;
var messagePort = event.ports[0]; var messagePort = event.ports[0];
selectedArchive.getTitleByName(titleName, function(title) { var readFile = function(title) {
// TODO handle other content types console.log("Found title.");
// TODO a Promise would avoid duplicating the code here
// Cf https://github.com/mossroy/evopedia-html5/issues/67
if (title.isRedirect()) { if (title.isRedirect()) {
selectedArchive.resolveRedirect(title, function(title) { console.log("Following redirect...");
selectedArchive.readArticle(title, function(readableTitleName, content) { selectedArchive.resolveRedirect(title, readFile);
} else {
console.log("Reading binary file...");
selectedArchive.readBinaryFile(title, function(readableTitleName, content) {
messagePort.postMessage({'action': 'giveContent', 'titleName' : titleName, 'content': 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 { else {
@ -966,7 +965,7 @@ define(['jquery', 'abstractBackend', 'util', 'cookies','geometry','osabstraction
* @param {String} titleName * @param {String} titleName
*/ */
function goToArticle(titleName) { function goToArticle(titleName) {
selectedArchive.getTitleByName(titleName, function(title) { selectedArchive.getTitleByName(titleName).then(function(title) {
if (title === null || title === undefined) { if (title === null || title === undefined) {
$("#readingArticle").hide(); $("#readingArticle").hide();
alert("Article with title " + titleName + " not found in the archive"); 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(""); $('#articleContent').contents().find('body').html("");
readArticle(title); 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); }).then(callbackFunction, errorHandler);
}; };
/**
* @callback callbackTitle
* @param {Title} title Title found
*/
/** /**
* Look for a title by its name, and call the callbackFunction with this Title * 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 * If the title is not found, the callbackFunction is called with parameter null
* @param {String} titleName * @param {String} titleName
* @param {callbackTitle} callbackFunction
*/ */
LocalArchive.prototype.getTitleByName = function(titleName, callbackFunction) { LocalArchive.prototype.getTitleByName = function(titleName) {
var that = this; var that = this;
var normalize = this.getNormalizeFunction(); var normalize = this.getNormalizeFunction();
var normalizedTitleName = normalize(titleName); 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); var iterator = new titleIterators.SequentialTitleIterator(that, offset);
function check(title) { function check(title) {
if (title === null || normalize(title._name) !== normalizedTitleName) { if (title === null || normalize(title._name) !== normalizedTitleName) {
@ -360,7 +354,7 @@ define(['normalize_string', 'geometry', 'title', 'util', 'titleIterators', 'q'],
} }
} }
return iterator.advance().then(check); 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/> * along with Evopedia (file LICENSE-GPLv3.txt). If not, see <http://www.gnu.org/licenses/>
*/ */
'use strict'; 'use strict';
define(['zimfile', 'zimDirEntry', 'util'], define(['zimfile', 'zimDirEntry', 'util', 'utf8'],
function(zimfile, zimDirEntry, util) { function(zimfile, zimDirEntry, util, utf8) {
/** /**
* ZIM Archive * ZIM Archive
@ -176,6 +176,22 @@ define(['zimfile', 'zimDirEntry', 'util'],
* @param {callbackStringContent} callback * @param {callbackStringContent} callback
*/ */
ZIMArchive.prototype.readArticle = function(title, 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) { return title.readData().then(function(data) {
callback(title.name(), data); callback(title.name(), data);
}); });
@ -184,11 +200,10 @@ define(['zimfile', 'zimDirEntry', 'util'],
/** /**
* *
* @param {String} titleName * @param {String} titleName
* @param {callbackTitle} callback
*/ */
ZIMArchive.prototype.getTitleByName = function(titleName, callback) { ZIMArchive.prototype.getTitleByName = function(titleName) {
var that = this; 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) { return that._file.dirEntryByUrlIndex(i).then(function(dirEntry) {
if (titleName < dirEntry.url) if (titleName < dirEntry.url)
return -1; return -1;
@ -200,7 +215,7 @@ define(['zimfile', 'zimDirEntry', 'util'],
}).then(function(index) { }).then(function(index) {
return that._file.dirEntryByUrlIndex(index); return that._file.dirEntryByUrlIndex(index);
}).then(function(dirEntry) { }).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 clusterOffset = readInt(clusterOffsets, 0, 8);
var nextCluster = readInt(clusterOffsets, 8, 8); var nextCluster = readInt(clusterOffsets, 8, 8);
//@todo we assume it is compressed - handle uncompressed (first byte at clusterOffset) return that._readSlice(clusterOffset, 1).then(function(compressionType) {
var reader = function(offset, size) { var decompressor;
var plainBlobReader = function(offset, size) {
return that._readSlice(clusterOffset + 1 + offset, size); return that._readSlice(clusterOffset + 1 + offset, size);
}; };
var dec = new xz.Decompressor(reader); if (compressionType[0] === 0 || compressionType[0] === 1) {
return dec.readSlice(blob * 4, 8).then(function(data) { // 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 blobOffset = readInt(data, 0, 4);
var nextBlobOffset = readInt(data, 4, 4); var nextBlobOffset = readInt(data, 4, 4);
return dec.readSlice(blobOffset, nextBlobOffset - blobOffset).then(function(data) { return decompressor.readSlice(blobOffset, nextBlobOffset - blobOffset).then(function(data) {
dec.end(); decompressor.end();
return utf8.parse(data); return data;
});
}); });
}); });
}); });