diff options
-rw-r--r-- | src/corelib/platform/wasm/qstdweb.cpp | 45 | ||||
-rw-r--r-- | src/corelib/platform/wasm/qstdweb_p.h | 2 | ||||
-rw-r--r-- | src/gui/platform/wasm/qwasmlocalfileaccess.cpp | 40 |
3 files changed, 48 insertions, 39 deletions
diff --git a/src/corelib/platform/wasm/qstdweb.cpp b/src/corelib/platform/wasm/qstdweb.cpp index 198ce897ca..789ceda6ab 100644 --- a/src/corelib/platform/wasm/qstdweb.cpp +++ b/src/corelib/platform/wasm/qstdweb.cpp @@ -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) { diff --git a/src/corelib/platform/wasm/qstdweb_p.h b/src/corelib/platform/wasm/qstdweb_p.h index 86c9cdcabd..ff83c73dd5 100644 --- a/src/corelib/platform/wasm/qstdweb_p.h +++ b/src/corelib/platform/wasm/qstdweb_p.h @@ -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(); diff --git a/src/gui/platform/wasm/qwasmlocalfileaccess.cpp b/src/gui/platform/wasm/qwasmlocalfileaccess.cpp index a5460f0ba7..e810a1ad8e 100644 --- a/src/gui/platform/wasm/qwasmlocalfileaccess.cpp +++ b/src/gui/platform/wasm/qwasmlocalfileaccess.cpp @@ -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); }); |