wasm: Move streamFile() to qstdweb
This function is useful also outside of local file access, for example when reading clipboard (file) content. Change-Id: I132546deb6df2969467051c348c05d9331d2cfd2 Reviewed-by: David Skoland <david.skoland@qt.io> Reviewed-by: Lorn Potter <lorn.potter@gmail.com>
This commit is contained in:
parent
59600a514b
commit
f92d4ffead
@ -95,6 +95,51 @@ uint64_t File::size() const
|
||||
return uint64_t(m_file["size"].as<uint53_t>());
|
||||
}
|
||||
|
||||
// Streams partial file content into the given buffer asynchronously. The completed
|
||||
// callback is called on completion.
|
||||
void File::stream(uint32_t offset, uint32_t length, char *buffer, const std::function<void ()> &completed) const
|
||||
{
|
||||
// Read file in chunks in order to avoid holding two copies in memory at the same time
|
||||
const uint32_t chunkSize = 256 * 1024;
|
||||
const uint32_t end = offset + length;
|
||||
// assert end < file.size
|
||||
auto fileReader = std::make_shared<qstdweb::FileReader>();
|
||||
|
||||
// "this" is valid now, but may not be by the time the chunkCompleted callback
|
||||
// below is made. Make a copy of the file handle.
|
||||
const File fileHandle = *this;
|
||||
auto chunkCompleted = std::make_shared<std::function<void (uint32_t, char *buffer)>>();
|
||||
*chunkCompleted = [=](uint32_t chunkBegin, char *chunkBuffer) mutable {
|
||||
|
||||
// Copy current chunk from JS memory to Wasm memory
|
||||
qstdweb::ArrayBuffer result = fileReader->result();
|
||||
qstdweb::Uint8Array(result).copyTo(chunkBuffer);
|
||||
|
||||
// Read next chunk if not at buffer end
|
||||
uint32_t nextChunkBegin = std::min(chunkBegin + result.byteLength(), end);
|
||||
uint32_t nextChunkEnd = std::min(nextChunkBegin + chunkSize, end);
|
||||
if (nextChunkBegin == end) {
|
||||
completed();
|
||||
chunkCompleted.reset();
|
||||
return;
|
||||
}
|
||||
char *nextChunkBuffer = chunkBuffer + result.byteLength();
|
||||
fileReader->onLoad([=]() { (*chunkCompleted)(nextChunkBegin, nextChunkBuffer); });
|
||||
qstdweb::Blob blob = fileHandle.slice(nextChunkBegin, nextChunkEnd);
|
||||
fileReader->readAsArrayBuffer(blob);
|
||||
};
|
||||
|
||||
// Read first chunk. First iteration is a dummy iteration with no available data.
|
||||
(*chunkCompleted)(offset, buffer);
|
||||
}
|
||||
|
||||
// Streams file content into the given buffer asynchronously. The completed
|
||||
// callback is called on completion.
|
||||
void File::stream(char *buffer, const std::function<void ()> &completed) const
|
||||
{
|
||||
stream(0, size(), buffer, completed);
|
||||
}
|
||||
|
||||
FileList::FileList(const emscripten::val &fileList)
|
||||
:m_fileList(fileList)
|
||||
{
|
||||
|
@ -99,6 +99,8 @@ namespace qstdweb {
|
||||
Blob slice(uint64_t begin, uint64_t end) const;
|
||||
std::string name() const;
|
||||
uint64_t size() const;
|
||||
void stream(uint32_t offset, uint32_t length, char *buffer, const std::function<void ()> &completed) const;
|
||||
void stream(char *buffer, const std::function<void ()> &completed) const;
|
||||
|
||||
private:
|
||||
emscripten::val m_file = emscripten::val::undefined();
|
||||
|
@ -48,44 +48,6 @@ QT_BEGIN_NAMESPACE
|
||||
|
||||
namespace QWasmLocalFileAccess {
|
||||
|
||||
void streamFile(const qstdweb::File &file, uint32_t offset, uint32_t length, char *buffer, const std::function<void ()> &completed)
|
||||
{
|
||||
// Read file in chunks in order to avoid holding two copies in memory at the same time
|
||||
const uint32_t chunkSize = 256 * 1024;
|
||||
const uint32_t end = offset + length;
|
||||
// assert end < file.size
|
||||
auto fileReader = std::make_shared<qstdweb::FileReader>();
|
||||
|
||||
auto chunkCompleted = std::make_shared<std::function<void (uint32_t, char *buffer)>>();
|
||||
*chunkCompleted = [=](uint32_t chunkBegin, char *chunkBuffer) mutable {
|
||||
|
||||
// Copy current chunk from JS memory to Wasm memory
|
||||
qstdweb::ArrayBuffer result = fileReader->result();
|
||||
qstdweb::Uint8Array(result).copyTo(chunkBuffer);
|
||||
|
||||
// Read next chunk if not at buffer end
|
||||
uint32_t nextChunkBegin = std::min(chunkBegin + result.byteLength(), end);
|
||||
uint32_t nextChunkEnd = std::min(nextChunkBegin + chunkSize, end);
|
||||
if (nextChunkBegin == end) {
|
||||
completed();
|
||||
chunkCompleted.reset();
|
||||
return;
|
||||
}
|
||||
char *nextChunkBuffer = chunkBuffer + result.byteLength();
|
||||
fileReader->onLoad([=]() { (*chunkCompleted)(nextChunkBegin, nextChunkBuffer); });
|
||||
qstdweb::Blob blob = file.slice(nextChunkBegin, nextChunkEnd);
|
||||
fileReader->readAsArrayBuffer(blob);
|
||||
};
|
||||
|
||||
// Read first chunk. First iteration is a dummy iteration with no available data.
|
||||
(*chunkCompleted)(offset, buffer);
|
||||
}
|
||||
|
||||
void streamFile(const qstdweb::File &file, char *buffer, const std::function<void ()> &completed)
|
||||
{
|
||||
streamFile(file, 0, file.size(), buffer, completed);
|
||||
}
|
||||
|
||||
void readFiles(const qstdweb::FileList &fileList,
|
||||
const std::function<char *(uint64_t size, const std::string name)> &acceptFile,
|
||||
const std::function<void ()> &fileDataReady)
|
||||
@ -109,7 +71,7 @@ void readFiles(const qstdweb::FileList &fileList,
|
||||
}
|
||||
|
||||
// Read file data into caller-provided buffer
|
||||
streamFile(file, buffer, [=]() {
|
||||
file.stream(buffer, [=]() {
|
||||
fileDataReady();
|
||||
(*readFile)(fileIndex + 1);
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user