| Index: mojo/dart/embedder/mojo_io_natives.cc
|
| diff --git a/mojo/dart/embedder/mojo_io_natives.cc b/mojo/dart/embedder/mojo_io_natives.cc
|
| index dd18a868e661935a18429c4b1a3c8e9d8d4e16d3..80f283a8875aed4052cdeec5005325151195215c 100644
|
| --- a/mojo/dart/embedder/mojo_io_natives.cc
|
| +++ b/mojo/dart/embedder/mojo_io_natives.cc
|
| @@ -4,10 +4,12 @@
|
|
|
| #include <stdio.h>
|
| #include <string.h>
|
| +#include <limits>
|
|
|
| #include "dart/runtime/include/dart_api.h"
|
| #include "mojo/dart/embedder/builtin.h"
|
| #include "mojo/dart/embedder/common.h"
|
| +#include "mojo/dart/embedder/io/filter.h"
|
| #include "mojo/dart/embedder/io/internet_address.h"
|
| #include "mojo/dart/embedder/mojo_dart_state.h"
|
| #include "mojo/public/cpp/system/macros.h"
|
| @@ -16,6 +18,11 @@ namespace mojo {
|
| namespace dart {
|
|
|
| #define MOJO_IO_NATIVE_LIST(V) \
|
| + V(Filter_CreateZLibDeflate, 8) \
|
| + V(Filter_CreateZLibInflate, 4) \
|
| + V(Filter_End, 1) \
|
| + V(Filter_Process, 4) \
|
| + V(Filter_Processed, 3) \
|
| V(InternetAddress_Parse, 1) \
|
| V(InternetAddress_Reverse, 1) \
|
| V(Platform_NumberOfProcessors, 0) \
|
| @@ -68,6 +75,266 @@ const uint8_t* MojoIoNativeSymbol(Dart_NativeFunction nf) {
|
| return nullptr;
|
| }
|
|
|
| +class IOBuffer {
|
| + public:
|
| + static Dart_Handle Allocate(intptr_t size, uint8_t **buffer) {
|
| + uint8_t* data = Allocate(size);
|
| + Dart_Handle result = Dart_NewExternalTypedData(
|
| + Dart_TypedData_kUint8, data, size);
|
| + Dart_NewWeakPersistentHandle(result, data, size, IOBuffer::Finalizer);
|
| +
|
| + if (Dart_IsError(result)) {
|
| + Free(data);
|
| + Dart_PropagateError(result);
|
| + }
|
| + if (buffer != NULL) {
|
| + *buffer = data;
|
| + }
|
| + return result;
|
| + }
|
| +
|
| + // Allocate IO buffer storage.
|
| + static uint8_t* Allocate(intptr_t size) {
|
| + return new uint8_t[size];
|
| + }
|
| +
|
| + // Function for disposing of IO buffer storage. All backing storage
|
| + // for IO buffers must be freed using this function.
|
| + static void Free(void* buffer) {
|
| + delete[] reinterpret_cast<uint8_t*>(buffer);
|
| + }
|
| +
|
| + // Function for finalizing external byte arrays used as IO buffers.
|
| + static void Finalizer(void* isolate_callback_data,
|
| + Dart_WeakPersistentHandle handle,
|
| + void* buffer) {
|
| + Free(buffer);
|
| + }
|
| +
|
| + private:
|
| + DISALLOW_IMPLICIT_CONSTRUCTORS(IOBuffer);
|
| +};
|
| +
|
| +static Filter* GetFilter(Dart_Handle filter_obj) {
|
| + Filter* filter;
|
| + Dart_Handle result = Filter::GetFilterPointerNativeField(filter_obj, &filter);
|
| + if (Dart_IsError(result)) {
|
| + Dart_PropagateError(result);
|
| + }
|
| + if (filter == NULL) {
|
| + Dart_ThrowException(DartEmbedder::NewInternalError("Filter destroyed"));
|
| + }
|
| + return filter;
|
| +}
|
| +
|
| +static void EndFilter(Dart_Handle filter_obj, Filter* filter) {
|
| + Filter::SetFilterPointerNativeField(filter_obj, NULL);
|
| + delete filter;
|
| +}
|
| +
|
| +static uint8_t* copyDictionary(Dart_Handle dictionary_obj) {
|
| + uint8_t* src = NULL;
|
| + intptr_t size;
|
| + Dart_TypedData_Type type;
|
| +
|
| + if (Dart_IsError(Dart_ListLength(dictionary_obj, &size))) {
|
| + Dart_ThrowException(DartEmbedder::NewInternalError(
|
| + "Failed to get the zlib dictionary length"));
|
| + }
|
| +
|
| + uint8_t* dictionary = new uint8_t[size];
|
| +
|
| + if (dictionary == NULL) {
|
| + Dart_ThrowException(DartEmbedder::NewInternalError(
|
| + "Failed to allocate buffer for the zlib dictionary"));
|
| + }
|
| +
|
| + Dart_Handle result = Dart_TypedDataAcquireData(
|
| + dictionary_obj, &type, reinterpret_cast<void**>(&src), &size);
|
| + if (!Dart_IsError(result)) {
|
| + memmove(dictionary, src, size);
|
| + Dart_TypedDataReleaseData(dictionary_obj);
|
| + } else {
|
| + if (Dart_IsError(Dart_ListGetAsBytes(dictionary_obj, 0, dictionary,
|
| + size))) {
|
| + Dart_ThrowException(DartEmbedder::NewInternalError(
|
| + "Failed to get the zlib dictionary"));
|
| + }
|
| + }
|
| +
|
| + return dictionary;
|
| +}
|
| +
|
| +void Filter_CreateZLibInflate(Dart_NativeArguments args) {
|
| + Dart_Handle filter_obj = Dart_GetNativeArgument(args, 0);
|
| + Dart_Handle window_bits_obj = Dart_GetNativeArgument(args, 1);
|
| + int64_t window_bits = DartEmbedder::GetIntegerValue(window_bits_obj);
|
| + Dart_Handle dict_obj = Dart_GetNativeArgument(args, 2);
|
| + uint8_t* dictionary = NULL;
|
| + intptr_t dictionary_length = 0;
|
| + if (!Dart_IsNull(dict_obj)) {
|
| + dictionary = copyDictionary(dict_obj);
|
| + if (dictionary != NULL) {
|
| + dictionary_length = 0;
|
| + Dart_ListLength(dict_obj, &dictionary_length);
|
| + }
|
| + }
|
| + Dart_Handle raw_obj = Dart_GetNativeArgument(args, 3);
|
| + bool raw;
|
| + if (Dart_IsError(Dart_BooleanValue(raw_obj, &raw))) {
|
| + Dart_ThrowException(DartEmbedder::NewInternalError(
|
| + "Failed to get 'raw' parameter"));
|
| + }
|
| + Filter* filter = new ZLibInflateFilter(static_cast<int32_t>(window_bits),
|
| + dictionary, dictionary_length, raw);
|
| + if (!filter->Init()) {
|
| + delete filter;
|
| + Dart_ThrowException(DartEmbedder::NewInternalError(
|
| + "Failed to create ZLibInflateFilter"));
|
| + }
|
| + Dart_Handle result = Filter::SetFilterPointerNativeField(filter_obj, filter);
|
| + if (Dart_IsError(result)) {
|
| + delete filter;
|
| + Dart_PropagateError(result);
|
| + }
|
| +}
|
| +
|
| +void Filter_CreateZLibDeflate(Dart_NativeArguments args) {
|
| + Dart_Handle filter_obj = Dart_GetNativeArgument(args, 0);
|
| + Dart_Handle gzip_obj = Dart_GetNativeArgument(args, 1);
|
| + bool gzip = DartEmbedder::GetBooleanValue(gzip_obj);
|
| + Dart_Handle level_obj = Dart_GetNativeArgument(args, 2);
|
| + int64_t level = DartEmbedder::GetInt64ValueCheckRange(
|
| + level_obj,
|
| + std::numeric_limits<int32_t>::min(),
|
| + std::numeric_limits<int32_t>::max());
|
| + Dart_Handle window_bits_obj = Dart_GetNativeArgument(args, 3);
|
| + int64_t window_bits = DartEmbedder::GetIntegerValue(window_bits_obj);
|
| + Dart_Handle mLevel_obj = Dart_GetNativeArgument(args, 4);
|
| + int64_t mem_level = DartEmbedder::GetIntegerValue(mLevel_obj);
|
| + Dart_Handle strategy_obj = Dart_GetNativeArgument(args, 5);
|
| + int64_t strategy = DartEmbedder::GetIntegerValue(strategy_obj);
|
| + Dart_Handle dict_obj = Dart_GetNativeArgument(args, 6);
|
| + uint8_t* dictionary = NULL;
|
| + intptr_t dictionary_length = 0;
|
| + if (!Dart_IsNull(dict_obj)) {
|
| + dictionary = copyDictionary(dict_obj);
|
| + if (dictionary != NULL) {
|
| + dictionary_length = 0;
|
| + Dart_ListLength(dict_obj, &dictionary_length);
|
| + }
|
| + }
|
| + Dart_Handle raw_obj = Dart_GetNativeArgument(args, 7);
|
| + bool raw = DartEmbedder::GetBooleanValue(raw_obj);
|
| + Filter* filter = new ZLibDeflateFilter(gzip, static_cast<int32_t>(level),
|
| + static_cast<int32_t>(window_bits),
|
| + static_cast<int32_t>(mem_level),
|
| + static_cast<int32_t>(strategy),
|
| + dictionary, dictionary_length, raw);
|
| + if (!filter->Init()) {
|
| + delete filter;
|
| + Dart_ThrowException(DartEmbedder::NewInternalError(
|
| + "Failed to create ZLibDeflateFilter"));
|
| + }
|
| + Dart_Handle result = Filter::SetFilterPointerNativeField(filter_obj, filter);
|
| + if (Dart_IsError(result)) {
|
| + delete filter;
|
| + Dart_PropagateError(result);
|
| + }
|
| +}
|
| +
|
| +void Filter_Process(Dart_NativeArguments args) {
|
| + Dart_Handle filter_obj = Dart_GetNativeArgument(args, 0);
|
| + Filter* filter = GetFilter(filter_obj);
|
| + Dart_Handle data_obj = Dart_GetNativeArgument(args, 1);
|
| + intptr_t start =
|
| + DartEmbedder::GetIntptrValue(Dart_GetNativeArgument(args, 2));
|
| + intptr_t end = DartEmbedder::GetIntptrValue(Dart_GetNativeArgument(args, 3));
|
| + intptr_t chunk_length = end - start;
|
| + intptr_t length;
|
| + Dart_TypedData_Type type;
|
| + uint8_t* buffer = NULL;
|
| + Dart_Handle result = Dart_TypedDataAcquireData(
|
| + data_obj, &type, reinterpret_cast<void**>(&buffer), &length);
|
| +
|
| + if (!Dart_IsError(result)) {
|
| + DCHECK(type == Dart_TypedData_kUint8 || type == Dart_TypedData_kInt8);
|
| + if (type != Dart_TypedData_kUint8 && type != Dart_TypedData_kInt8) {
|
| + Dart_TypedDataReleaseData(data_obj);
|
| + Dart_ThrowException(DartEmbedder::NewInternalError(
|
| + "Invalid argument passed to Filter_Process"));
|
| + }
|
| + uint8_t* zlib_buffer = new uint8_t[chunk_length];
|
| + if (zlib_buffer == NULL) {
|
| + Dart_TypedDataReleaseData(data_obj);
|
| + Dart_ThrowException(DartEmbedder::NewInternalError(
|
| + "Failed to allocate buffer for zlib"));
|
| + }
|
| + memmove(zlib_buffer, buffer + start, chunk_length);
|
| + Dart_TypedDataReleaseData(data_obj);
|
| + buffer = zlib_buffer;
|
| + } else {
|
| + if (Dart_IsError(Dart_ListLength(data_obj, &length))) {
|
| + Dart_ThrowException(DartEmbedder::NewInternalError(
|
| + "Failed to get list length"));
|
| + }
|
| + buffer = new uint8_t[chunk_length];
|
| + if (Dart_IsError(Dart_ListGetAsBytes(
|
| + data_obj, start, buffer, chunk_length))) {
|
| + delete[] buffer;
|
| + Dart_ThrowException(DartEmbedder::NewInternalError(
|
| + "Failed to get list bytes"));
|
| + }
|
| + }
|
| + // Process will take ownership of buffer, if successful.
|
| + if (!filter->Process(buffer, chunk_length)) {
|
| + delete[] buffer;
|
| + EndFilter(filter_obj, filter);
|
| + Dart_ThrowException(DartEmbedder::NewInternalError(
|
| + "Call to Process while still processing data"));
|
| + }
|
| +}
|
| +
|
| +void Filter_Processed(Dart_NativeArguments args) {
|
| + Dart_Handle filter_obj = Dart_GetNativeArgument(args, 0);
|
| + Filter* filter = GetFilter(filter_obj);
|
| + Dart_Handle flush_obj = Dart_GetNativeArgument(args, 1);
|
| + bool flush;
|
| + if (Dart_IsError(Dart_BooleanValue(flush_obj, &flush))) {
|
| + Dart_ThrowException(DartEmbedder::NewInternalError(
|
| + "Failed to get 'flush' parameter"));
|
| + }
|
| + Dart_Handle end_obj = Dart_GetNativeArgument(args, 2);
|
| + bool end;
|
| + if (Dart_IsError(Dart_BooleanValue(end_obj, &end))) {
|
| + Dart_ThrowException(DartEmbedder::NewInternalError(
|
| + "Failed to get 'end' parameter"));
|
| + }
|
| + intptr_t read = filter->Processed(filter->processed_buffer(),
|
| + filter->processed_buffer_size(),
|
| + flush,
|
| + end);
|
| + if (read < 0) {
|
| + // Error, end filter.
|
| + EndFilter(filter_obj, filter);
|
| + Dart_ThrowException(DartEmbedder::NewInternalError(
|
| + "Filter error, bad data"));
|
| + } else if (read == 0) {
|
| + Dart_SetReturnValue(args, Dart_Null());
|
| + } else {
|
| + uint8_t* io_buffer;
|
| + Dart_Handle result = IOBuffer::Allocate(read, &io_buffer);
|
| + memmove(io_buffer, filter->processed_buffer(), read);
|
| + Dart_SetReturnValue(args, result);
|
| + }
|
| +}
|
| +
|
| +void Filter_End(Dart_NativeArguments args) {
|
| + Dart_Handle filter_obj = Dart_GetNativeArgument(args, 0);
|
| + Filter* filter = GetFilter(filter_obj);
|
| + EndFilter(filter_obj, filter);
|
| +}
|
| +
|
| void InternetAddress_Parse(Dart_NativeArguments arguments) {
|
| const char* address = DartEmbedder::GetStringArgument(arguments, 0);
|
| CHECK(address != nullptr);
|
|
|