| Index: runtime/bin/filter.cc
|
| diff --git a/runtime/bin/filter.cc b/runtime/bin/filter.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..3515052321aaa0221069f1fabaed5963c42abc1d
|
| --- /dev/null
|
| +++ b/runtime/bin/filter.cc
|
| @@ -0,0 +1,312 @@
|
| +// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
|
| +// for details. All rights reserved. Use of this source code is governed by a
|
| +// BSD-style license that can be found in the LICENSE file.
|
| +
|
| +#include "bin/dartutils.h"
|
| +#include "bin/filter.h"
|
| +#include "bin/io_buffer.h"
|
| +
|
| +#include "include/dart_api.h"
|
| +
|
| +const int kZlibFlagMemUsage = 8;
|
| +const int kZLibFlagWindowBits = 15;
|
| +const int kZLibFlagUseGZipHeader = 16;
|
| +const int kZLibFlagAcceptAnyHeader = 32;
|
| +
|
| +const intptr_t kFilterBufferLength = 64 * KB;
|
| +
|
| +static const int kFilterPointerNativeField = 0;
|
| +
|
| +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(DartUtils::NewInternalError("Filter destroyed"));
|
| + }
|
| + return filter;
|
| +}
|
| +
|
| +void EndFilter(Dart_Handle filter_obj, Filter* filter) {
|
| + Filter::SetFilterPointerNativeField(filter_obj, NULL);
|
| + delete filter;
|
| +}
|
| +
|
| +void FUNCTION_NAME(Filter_CreateZLibInflate)(Dart_NativeArguments args) {
|
| + Dart_EnterScope();
|
| + Dart_Handle filter_obj = Dart_GetNativeArgument(args, 0);
|
| + Filter* filter = new ZLibInflateFilter();
|
| + if (filter == NULL || !filter->Init()) {
|
| + delete filter;
|
| + Dart_ThrowException(DartUtils::NewInternalError(
|
| + "Failed to create ZLibInflateFilter"));
|
| + }
|
| + Dart_Handle result = Filter::SetFilterPointerNativeField(filter_obj, filter);
|
| + if (Dart_IsError(result)) {
|
| + delete filter;
|
| + Dart_PropagateError(result);
|
| + }
|
| + Dart_ExitScope();
|
| +}
|
| +
|
| +void FUNCTION_NAME(Filter_CreateZLibDeflate)(Dart_NativeArguments args) {
|
| + Dart_EnterScope();
|
| + Dart_Handle filter_obj = Dart_GetNativeArgument(args, 0);
|
| + Dart_Handle gzip_obj = Dart_GetNativeArgument(args, 1);
|
| + Dart_Handle level_obj = Dart_GetNativeArgument(args, 2);
|
| + bool gzip;
|
| + if (Dart_IsError(Dart_BooleanValue(gzip_obj, &gzip))) {
|
| + Dart_ThrowException(DartUtils::NewInternalError(
|
| + "Failed to get 'gzip' parameter"));
|
| + }
|
| + int64_t level;
|
| + if (Dart_IsError(Dart_IntegerToInt64(level_obj, &level))) {
|
| + Dart_ThrowException(DartUtils::NewInternalError(
|
| + "Failed to get 'level' parameter"));
|
| + }
|
| + Filter* filter = new ZLibDeflateFilter(gzip, level);
|
| + if (filter == NULL || !filter->Init()) {
|
| + delete filter;
|
| + Dart_ThrowException(DartUtils::NewInternalError(
|
| + "Failed to create ZLibDeflateFilter"));
|
| + }
|
| + Dart_Handle result = Filter::SetFilterPointerNativeField(filter_obj, filter);
|
| + if (Dart_IsError(result)) {
|
| + delete filter;
|
| + Dart_PropagateError(result);
|
| + }
|
| + Dart_ExitScope();
|
| +}
|
| +
|
| +void FUNCTION_NAME(Filter_Process)(Dart_NativeArguments args) {
|
| + Dart_EnterScope();
|
| + Dart_Handle filter_obj = Dart_GetNativeArgument(args, 0);
|
| + Filter* filter = GetFilter(filter_obj);
|
| + Dart_Handle data_obj = Dart_GetNativeArgument(args, 1);
|
| + 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)) {
|
| + uint8_t* zlib_buffer = new uint8_t[length];
|
| + if (zlib_buffer == NULL) {
|
| + Dart_TypedDataReleaseData(data_obj);
|
| + Dart_ThrowException(DartUtils::NewInternalError(
|
| + "Failed to allocate buffer for zlib"));
|
| + }
|
| + memmove(zlib_buffer, buffer, length);
|
| + Dart_TypedDataReleaseData(data_obj);
|
| + buffer = zlib_buffer;
|
| + } else {
|
| + if (Dart_IsError(Dart_ListLength(data_obj, &length))) {
|
| + Dart_ThrowException(DartUtils::NewInternalError(
|
| + "Failed to get list length"));
|
| + }
|
| + buffer = new uint8_t[length];
|
| + if (Dart_IsError(Dart_ListGetAsBytes(data_obj, 0, buffer, length))) {
|
| + delete[] buffer;
|
| + Dart_ThrowException(DartUtils::NewInternalError(
|
| + "Failed to get list bytes"));
|
| + }
|
| + }
|
| + // Process will take ownership of buffer, if successful.
|
| + if (!filter->Process(buffer, length)) {
|
| + delete[] buffer;
|
| + EndFilter(filter_obj, filter);
|
| + Dart_ThrowException(DartUtils::NewInternalError(
|
| + "Call to Process while still processing data"));
|
| + }
|
| + Dart_ExitScope();
|
| +}
|
| +
|
| +
|
| +void FUNCTION_NAME(Filter_Processed)(Dart_NativeArguments args) {
|
| + Dart_EnterScope();
|
| + 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(DartUtils::NewInternalError(
|
| + "Failed to get 'flush' parameter"));
|
| + }
|
| + uint8_t buffer[kFilterBufferLength];
|
| + intptr_t read = filter->Processed(buffer, kFilterBufferLength, flush);
|
| + if (read < 0) {
|
| + // Error, end filter.
|
| + EndFilter(filter_obj, filter);
|
| + Dart_ThrowException(DartUtils::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, buffer, read);
|
| + Dart_SetReturnValue(args, result);
|
| + }
|
| + Dart_ExitScope();
|
| +}
|
| +
|
| +
|
| +void FUNCTION_NAME(Filter_End)(Dart_NativeArguments args) {
|
| + Dart_EnterScope();
|
| + Dart_Handle filter_obj = Dart_GetNativeArgument(args, 0);
|
| + Filter* filter = GetFilter(filter_obj);
|
| + EndFilter(filter_obj, filter);
|
| + Dart_ExitScope();
|
| +}
|
| +
|
| +
|
| +Dart_Handle Filter::SetFilterPointerNativeField(Dart_Handle filter,
|
| + Filter* filter_pointer) {
|
| + return Dart_SetNativeInstanceField(filter,
|
| + kFilterPointerNativeField,
|
| + (intptr_t)filter_pointer);
|
| +}
|
| +
|
| +
|
| +Dart_Handle Filter::GetFilterPointerNativeField(Dart_Handle filter,
|
| + Filter** filter_pointer) {
|
| + return Dart_GetNativeInstanceField(
|
| + filter,
|
| + kFilterPointerNativeField,
|
| + reinterpret_cast<intptr_t*>(filter_pointer));
|
| +}
|
| +
|
| +
|
| +ZLibDeflateFilter::~ZLibDeflateFilter() {
|
| + delete[] current_buffer;
|
| + if (initialized) deflateEnd(&stream);
|
| +}
|
| +
|
| +
|
| +bool ZLibDeflateFilter::Init() {
|
| + stream.zalloc = Z_NULL;
|
| + stream.zfree = Z_NULL;
|
| + stream.opaque = Z_NULL;
|
| + int result = deflateInit2(
|
| + &stream,
|
| + level,
|
| + Z_DEFLATED,
|
| + kZLibFlagWindowBits | (gZip ? kZLibFlagUseGZipHeader : 0),
|
| + kZlibFlagMemUsage,
|
| + Z_DEFAULT_STRATEGY);
|
| + if (result == Z_OK) {
|
| + initialized = true;
|
| + return true;
|
| + }
|
| + return false;
|
| +}
|
| +
|
| +
|
| +bool ZLibDeflateFilter::Process(uint8_t* data, intptr_t length) {
|
| + if (current_buffer != NULL) return false;
|
| + stream.avail_in = length;
|
| + stream.next_in = current_buffer = data;
|
| + return true;
|
| +}
|
| +
|
| +intptr_t ZLibDeflateFilter::Processed(uint8_t* buffer,
|
| + intptr_t length,
|
| + bool flush) {
|
| + stream.avail_out = length;
|
| + stream.next_out = buffer;
|
| + switch (deflate(&stream, flush ? Z_SYNC_FLUSH : Z_NO_FLUSH)) {
|
| + case Z_OK: {
|
| + intptr_t processed = length - stream.avail_out;
|
| + if (processed == 0) {
|
| + delete[] current_buffer;
|
| + current_buffer = NULL;
|
| + return 0;
|
| + } else {
|
| + // We processed data, should be called again.
|
| + return processed;
|
| + }
|
| + }
|
| +
|
| + case Z_STREAM_END:
|
| + case Z_BUF_ERROR:
|
| + // We processed all available input data.
|
| + delete[] current_buffer;
|
| + current_buffer = NULL;
|
| + return 0;
|
| +
|
| + default:
|
| + case Z_STREAM_ERROR:
|
| + // An error occoured.
|
| + delete[] current_buffer;
|
| + current_buffer = NULL;
|
| + return -1;
|
| + }
|
| +}
|
| +
|
| +
|
| +ZLibInflateFilter::~ZLibInflateFilter() {
|
| + delete[] current_buffer;
|
| + if (initialized) inflateEnd(&stream);
|
| +}
|
| +
|
| +
|
| +bool ZLibInflateFilter::Init() {
|
| + stream.zalloc = Z_NULL;
|
| + stream.zfree = Z_NULL;
|
| + stream.opaque = Z_NULL;
|
| + int result = inflateInit2(&stream,
|
| + kZLibFlagWindowBits | kZLibFlagAcceptAnyHeader);
|
| + if (result == Z_OK) {
|
| + initialized = true;
|
| + return true;
|
| + }
|
| + return false;
|
| +}
|
| +
|
| +
|
| +bool ZLibInflateFilter::Process(uint8_t* data, intptr_t length) {
|
| + if (current_buffer != NULL) return false;
|
| + stream.avail_in = length;
|
| + stream.next_in = current_buffer = data;
|
| + return true;
|
| +}
|
| +
|
| +
|
| +intptr_t ZLibInflateFilter::Processed(uint8_t* buffer,
|
| + intptr_t length,
|
| + bool flush) {
|
| + stream.avail_out = length;
|
| + stream.next_out = buffer;
|
| + switch (inflate(&stream, flush ? Z_SYNC_FLUSH : Z_NO_FLUSH)) {
|
| + case Z_OK: {
|
| + intptr_t processed = length - stream.avail_out;
|
| + if (processed == 0) {
|
| + delete[] current_buffer;
|
| + current_buffer = NULL;
|
| + return 0;
|
| + } else {
|
| + // We processed data, should be called again.
|
| + return processed;
|
| + }
|
| + }
|
| +
|
| + case Z_STREAM_END:
|
| + case Z_BUF_ERROR:
|
| + // We processed all available input data.
|
| + delete[] current_buffer;
|
| + current_buffer = NULL;
|
| + return 0;
|
| +
|
| + default:
|
| + case Z_MEM_ERROR:
|
| + case Z_NEED_DICT:
|
| + case Z_DATA_ERROR:
|
| + case Z_STREAM_ERROR:
|
| + // An error occoured.
|
| + delete[] current_buffer;
|
| + current_buffer = NULL;
|
| + return -1;
|
| + }
|
| +}
|
| +
|
|
|