| Index: runtime/bin/filter.cc
|
| diff --git a/runtime/bin/filter.cc b/runtime/bin/filter.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..b011042964499111872c84d10873dca68e3fe8be
|
| --- /dev/null
|
| +++ b/runtime/bin/filter.cc
|
| @@ -0,0 +1,250 @@
|
| +// Copyright (c) 2012, 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/filter.h"
|
| +#include "bin/dartutils.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;
|
| +
|
| +void DeleteBuffer(void* buffer) {
|
| + delete[] reinterpret_cast<uint8_t*>(buffer);
|
| +}
|
| +
|
| +Filter* GetFilter(Dart_Handle filter_obj) {
|
| + Filter* filter;
|
| + if (Dart_IsError(Filter::GetFilterPointerNativeField(filter_obj, &filter))
|
| + || filter == NULL) {
|
| + Dart_ThrowException(DartUtils::NewInternalError("Failed to get filter"));
|
| + }
|
| + 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->Init() ||
|
| + Dart_IsError(Filter::SetFilterPointerNativeField(filter_obj, filter))) {
|
| + delete filter;
|
| + Dart_ThrowException(DartUtils::NewInternalError(
|
| + "Failed to create ZLibInflateFilter"));
|
| + }
|
| + Dart_ExitScope();
|
| +}
|
| +
|
| +void FUNCTION_NAME(Filter_CreateGZipDeflate)(Dart_NativeArguments args) {
|
| + Dart_EnterScope();
|
| + Dart_Handle filter_obj = Dart_GetNativeArgument(args, 0);
|
| + Filter* filter = new ZLibDeflateFilter(true);
|
| + if (!filter->Init() ||
|
| + Dart_IsError(Filter::SetFilterPointerNativeField(filter_obj, filter))) {
|
| + delete filter;
|
| + Dart_ThrowException(DartUtils::NewInternalError(
|
| + "Failed to create GZipDeflateFilter"));
|
| + }
|
| + 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;
|
| + if (Dart_IsError(Dart_ListLength(data_obj, &length))) {
|
| + Dart_ThrowException(DartUtils::NewInternalError(
|
| + "Failed to get data length"));
|
| + }
|
| + uint8_t* data = new uint8_t[length];
|
| + if (Dart_IsError(Dart_ListGetAsBytes(data_obj, 0, data, length))) {
|
| + DeleteBuffer(data);
|
| + Dart_ThrowException(DartUtils::NewInternalError(
|
| + "Failed to get data bytes"));
|
| + }
|
| + if (!filter->Process(data, length)) {
|
| + DeleteBuffer(data);
|
| + 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 = new uint8_t[kFilterBufferLength];
|
| + intptr_t read = filter->Processed(buffer, kFilterBufferLength, flush);
|
| + if (read < 0) {
|
| + // Error, end filter.
|
| + EndFilter(filter_obj, filter);
|
| + DeleteBuffer(buffer);
|
| + Dart_ThrowException(DartUtils::NewInternalError(
|
| + "Filter error, bad data"));
|
| + } else if (read == 0) {
|
| + DeleteBuffer(buffer);
|
| + Dart_SetReturnValue(args, Dart_Null());
|
| + } else {
|
| + Dart_Handle result = Dart_NewExternalByteArray(buffer,
|
| + read,
|
| + buffer,
|
| + DeleteBuffer);
|
| + 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;
|
| + deflateEnd(&stream);
|
| +}
|
| +
|
| +
|
| +bool ZLibDeflateFilter::Init() {
|
| + stream.zalloc = Z_NULL;
|
| + stream.zfree = Z_NULL;
|
| + stream.opaque = Z_NULL;
|
| + return deflateInit2(&stream,
|
| + level,
|
| + Z_DEFLATED,
|
| + kZLibFlagWindowBits | (gZip ? kZLibFlagUseGZipHeader : 0),
|
| + kZlibFlagMemUsage,
|
| + Z_DEFAULT_STRATEGY) == Z_OK;
|
| +}
|
| +
|
| +
|
| +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:
|
| + // We processed data, should be called again.
|
| + return length - stream.avail_out;
|
| +
|
| + 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;
|
| + inflateEnd(&stream);
|
| +}
|
| +
|
| +
|
| +bool ZLibInflateFilter::Init() {
|
| + stream.zalloc = Z_NULL;
|
| + stream.zfree = Z_NULL;
|
| + stream.opaque = Z_NULL;
|
| + return inflateInit2(&stream,
|
| + kZLibFlagWindowBits | kZLibFlagAcceptAnyHeader) == Z_OK;
|
| +}
|
| +
|
| +
|
| +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:
|
| + // We processed data, should be called again.
|
| + return length - stream.avail_out;
|
| +
|
| + 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;
|
| + }
|
| +}
|
| +
|
|
|