wasm: Move Blob creation code to qstdweb
Add Uint8Array::copyFrom() and Blob::copyFrom(), which constructs JS data containers with content copied from the C heap. These should not be confused with e.g. the Uint8Array(buffer, size) constructor, which creates a Uint8Array which references content on the heap, without making a copy. Change-Id: Id7d25d8044ee3914d74698e5a15c93226568eaf3 Reviewed-by: David Skoland <david.skoland@qt.io> Reviewed-by: Lorn Potter <lorn.potter@gmail.com>
This commit is contained in:
parent
a0f9aef11b
commit
24134d5193
@ -49,6 +49,11 @@ namespace qstdweb {
|
||||
|
||||
typedef double uint53_t; // see Number.MAX_SAFE_INTEGER
|
||||
|
||||
ArrayBuffer::ArrayBuffer(uint32_t size)
|
||||
{
|
||||
m_arrayBuffer = emscripten::val::global("ArrayBuffer").new_(size);
|
||||
}
|
||||
|
||||
ArrayBuffer::ArrayBuffer(const emscripten::val &arrayBuffer)
|
||||
:m_arrayBuffer(arrayBuffer)
|
||||
{
|
||||
@ -74,6 +79,23 @@ uint32_t Blob::size() const
|
||||
return m_blob["size"].as<uint32_t>();
|
||||
}
|
||||
|
||||
// Copies content from the given buffer into a Blob object
|
||||
Blob Blob::copyFrom(const char *buffer, uint32_t size)
|
||||
{
|
||||
Uint8Array contentCopy = Uint8Array::copyFrom(buffer, size);
|
||||
|
||||
emscripten::val contentArray = emscripten::val::array();
|
||||
contentArray.call<void>("push", contentCopy.m_uint8Array);
|
||||
emscripten::val type = emscripten::val::object();
|
||||
type.set("type","application/octet-stream");
|
||||
return Blob(emscripten::val::global("Blob").new_(contentArray, type));
|
||||
}
|
||||
|
||||
emscripten::val Blob::val()
|
||||
{
|
||||
return m_blob;
|
||||
}
|
||||
|
||||
File::File(const emscripten::val &file)
|
||||
:m_file(file)
|
||||
{
|
||||
@ -191,30 +213,41 @@ Uint8Array Uint8Array::heap()
|
||||
return Uint8Array(heap_());
|
||||
}
|
||||
|
||||
// Constructs a Uint8Array which references the given emscripten::val, which must contain a JS Unit8Array
|
||||
Uint8Array::Uint8Array(const emscripten::val &uint8Array)
|
||||
: m_uint8Array(uint8Array)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
// Constructs a Uint8Array which references an ArrayBuffer
|
||||
Uint8Array::Uint8Array(const ArrayBuffer &buffer)
|
||||
: m_uint8Array(Uint8Array::constructor_().new_(buffer.m_arrayBuffer))
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
// Constructs a Uint8Array which references a view into an ArrayBuffer
|
||||
Uint8Array::Uint8Array(const ArrayBuffer &buffer, uint32_t offset, uint32_t length)
|
||||
: m_uint8Array(Uint8Array::constructor_().new_(buffer.m_arrayBuffer, offset, length))
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
Uint8Array::Uint8Array(char *buffer, uint32_t size)
|
||||
// Constructs a Uint8Array which references an area on the heap.
|
||||
Uint8Array::Uint8Array(const char *buffer, uint32_t size)
|
||||
:m_uint8Array(Uint8Array::constructor_().new_(Uint8Array::heap().buffer().m_arrayBuffer, uint32_t(buffer), size))
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
// Constructs a Uint8Array which allocates and references a new ArrayBuffer with the given size.
|
||||
Uint8Array::Uint8Array(uint32_t size)
|
||||
: m_uint8Array(Uint8Array::constructor_().new_(size))
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
ArrayBuffer Uint8Array::buffer() const
|
||||
{
|
||||
return ArrayBuffer(m_uint8Array["buffer"]);
|
||||
@ -230,16 +263,26 @@ void Uint8Array::set(const Uint8Array &source)
|
||||
m_uint8Array.call<void>("set", source.m_uint8Array); // copies source content
|
||||
}
|
||||
|
||||
// Copies the Uint8Array conent to a destination on the heap
|
||||
void Uint8Array::copyTo(char *destination) const
|
||||
{
|
||||
Uint8Array(destination, length()).set(*this);
|
||||
}
|
||||
|
||||
// Copies the Uint8Array conent to a destination on the heap
|
||||
void Uint8Array::copy(char *destination, const Uint8Array &source)
|
||||
{
|
||||
Uint8Array(destination, source.length()).set(source);
|
||||
}
|
||||
|
||||
// Copies content from a source on the heap to a new Uint8Array object
|
||||
Uint8Array Uint8Array::copyFrom(const char *buffer, uint32_t size)
|
||||
{
|
||||
Uint8Array contentCopy(size);
|
||||
contentCopy.set(Uint8Array(buffer, size));
|
||||
return contentCopy;
|
||||
}
|
||||
|
||||
emscripten::val Uint8Array::heap_()
|
||||
{
|
||||
return emscripten::val::module_property("HEAPU8");
|
||||
|
@ -73,6 +73,7 @@ namespace qstdweb {
|
||||
|
||||
class ArrayBuffer {
|
||||
public:
|
||||
explicit ArrayBuffer(uint32_t size);
|
||||
explicit ArrayBuffer(const emscripten::val &arrayBuffer);
|
||||
uint32_t byteLength() const;
|
||||
|
||||
@ -85,6 +86,8 @@ namespace qstdweb {
|
||||
public:
|
||||
explicit Blob(const emscripten::val &blob);
|
||||
uint32_t size() const;
|
||||
static Blob copyFrom(const char *buffer, uint32_t size);
|
||||
emscripten::val val();
|
||||
|
||||
private:
|
||||
friend class FileReader;
|
||||
@ -140,8 +143,9 @@ namespace qstdweb {
|
||||
static Uint8Array heap();
|
||||
explicit Uint8Array(const emscripten::val &uint8Array);
|
||||
explicit Uint8Array(const ArrayBuffer &buffer);
|
||||
explicit Uint8Array(uint32_t size);
|
||||
Uint8Array(const ArrayBuffer &buffer, uint32_t offset, uint32_t length);
|
||||
Uint8Array(char *buffer, uint32_t size);
|
||||
Uint8Array(const char *buffer, uint32_t size);
|
||||
|
||||
ArrayBuffer buffer() const;
|
||||
uint32_t length() const;
|
||||
@ -149,7 +153,9 @@ namespace qstdweb {
|
||||
|
||||
void copyTo(char *destination) const;
|
||||
static void copy(char *destination, const Uint8Array &source);
|
||||
static Uint8Array copyFrom(const char *buffer, uint32_t size);
|
||||
private:
|
||||
friend class Blob;
|
||||
static emscripten::val heap_();
|
||||
static emscripten::val constructor_();
|
||||
emscripten::val m_uint8Array = emscripten::val::undefined();
|
||||
|
@ -129,27 +129,13 @@ void openFile(const std::string &accept,
|
||||
void saveFile(const char *content, size_t size, const std::string &fileNameHint)
|
||||
{
|
||||
// Save a file by creating programmatically clicking a download
|
||||
// link to an object url to a Blob containing the file content.
|
||||
// File content is copied once, so that the passed in content
|
||||
// buffer can be released as soon as this function returns - we
|
||||
// don't know for how long the browser will retain the TypedArray
|
||||
// view used to create the Blob.
|
||||
|
||||
// link to an object url to a Blob containing a copy of the file
|
||||
// content. The copy is made so that the passed in content buffer
|
||||
// can be released as soon as this function returns.
|
||||
qstdweb::Blob contentBlob = qstdweb::Blob::copyFrom(content, size);
|
||||
emscripten::val document = emscripten::val::global("document");
|
||||
emscripten::val window = emscripten::val::global("window");
|
||||
|
||||
emscripten::val fileContentView = emscripten::val(emscripten::typed_memory_view(size, content));
|
||||
emscripten::val fileContentCopy = emscripten::val::global("ArrayBuffer").new_(size);
|
||||
emscripten::val fileContentCopyView = emscripten::val::global("Uint8Array").new_(fileContentCopy);
|
||||
fileContentCopyView.call<void>("set", fileContentView);
|
||||
|
||||
emscripten::val contentArray = emscripten::val::array();
|
||||
contentArray.call<void>("push", fileContentCopyView);
|
||||
emscripten::val type = emscripten::val::object();
|
||||
type.set("type","application/octet-stream");
|
||||
emscripten::val contentBlob = emscripten::val::global("Blob").new_(contentArray, type);
|
||||
|
||||
emscripten::val contentUrl = window["URL"].call<emscripten::val>("createObjectURL", contentBlob);
|
||||
emscripten::val contentUrl = window["URL"].call<emscripten::val>("createObjectURL", contentBlob.val());
|
||||
emscripten::val contentLink = document.call<emscripten::val>("createElement", std::string("a"));
|
||||
contentLink.set("href", contentUrl);
|
||||
contentLink.set("download", fileNameHint);
|
||||
|
Loading…
Reference in New Issue
Block a user