Chromium Code Reviews| 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) { |
|
zra
2016/03/02 23:30:40
This method of deleting the filter relies on the D
Cutch
2016/03/03 15:46:56
Acknowledged.
|
| + 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); |