| OLD | NEW |
| (Empty) | |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. |
| 4 |
| 5 #include "bin/dartutils.h" |
| 6 #include "bin/filter.h" |
| 7 #include "bin/io_buffer.h" |
| 8 |
| 9 #include "include/dart_api.h" |
| 10 |
| 11 const int kZlibFlagMemUsage = 8; |
| 12 const int kZLibFlagWindowBits = 15; |
| 13 const int kZLibFlagUseGZipHeader = 16; |
| 14 const int kZLibFlagAcceptAnyHeader = 32; |
| 15 |
| 16 const intptr_t kFilterBufferLength = 64 * KB; |
| 17 |
| 18 static const int kFilterPointerNativeField = 0; |
| 19 |
| 20 Filter* GetFilter(Dart_Handle filter_obj) { |
| 21 Filter* filter; |
| 22 Dart_Handle result = Filter::GetFilterPointerNativeField(filter_obj, &filter); |
| 23 if (Dart_IsError(result)) { |
| 24 Dart_PropagateError(result); |
| 25 } |
| 26 if (filter == NULL) { |
| 27 Dart_ThrowException(DartUtils::NewInternalError("Filter destroyed")); |
| 28 } |
| 29 return filter; |
| 30 } |
| 31 |
| 32 void EndFilter(Dart_Handle filter_obj, Filter* filter) { |
| 33 Filter::SetFilterPointerNativeField(filter_obj, NULL); |
| 34 delete filter; |
| 35 } |
| 36 |
| 37 void FUNCTION_NAME(Filter_CreateZLibInflate)(Dart_NativeArguments args) { |
| 38 Dart_EnterScope(); |
| 39 Dart_Handle filter_obj = Dart_GetNativeArgument(args, 0); |
| 40 Filter* filter = new ZLibInflateFilter(); |
| 41 if (filter == NULL || !filter->Init()) { |
| 42 delete filter; |
| 43 Dart_ThrowException(DartUtils::NewInternalError( |
| 44 "Failed to create ZLibInflateFilter")); |
| 45 } |
| 46 Dart_Handle result = Filter::SetFilterPointerNativeField(filter_obj, filter); |
| 47 if (Dart_IsError(result)) { |
| 48 delete filter; |
| 49 Dart_PropagateError(result); |
| 50 } |
| 51 Dart_ExitScope(); |
| 52 } |
| 53 |
| 54 void FUNCTION_NAME(Filter_CreateZLibDeflate)(Dart_NativeArguments args) { |
| 55 Dart_EnterScope(); |
| 56 Dart_Handle filter_obj = Dart_GetNativeArgument(args, 0); |
| 57 Dart_Handle gzip_obj = Dart_GetNativeArgument(args, 1); |
| 58 Dart_Handle level_obj = Dart_GetNativeArgument(args, 2); |
| 59 bool gzip; |
| 60 if (Dart_IsError(Dart_BooleanValue(gzip_obj, &gzip))) { |
| 61 Dart_ThrowException(DartUtils::NewInternalError( |
| 62 "Failed to get 'gzip' parameter")); |
| 63 } |
| 64 int64_t level; |
| 65 if (Dart_IsError(Dart_IntegerToInt64(level_obj, &level))) { |
| 66 Dart_ThrowException(DartUtils::NewInternalError( |
| 67 "Failed to get 'level' parameter")); |
| 68 } |
| 69 Filter* filter = new ZLibDeflateFilter(gzip, level); |
| 70 if (filter == NULL || !filter->Init()) { |
| 71 delete filter; |
| 72 Dart_ThrowException(DartUtils::NewInternalError( |
| 73 "Failed to create ZLibDeflateFilter")); |
| 74 } |
| 75 Dart_Handle result = Filter::SetFilterPointerNativeField(filter_obj, filter); |
| 76 if (Dart_IsError(result)) { |
| 77 delete filter; |
| 78 Dart_PropagateError(result); |
| 79 } |
| 80 Dart_ExitScope(); |
| 81 } |
| 82 |
| 83 void FUNCTION_NAME(Filter_Process)(Dart_NativeArguments args) { |
| 84 Dart_EnterScope(); |
| 85 Dart_Handle filter_obj = Dart_GetNativeArgument(args, 0); |
| 86 Filter* filter = GetFilter(filter_obj); |
| 87 Dart_Handle data_obj = Dart_GetNativeArgument(args, 1); |
| 88 intptr_t length; |
| 89 Dart_TypedData_Type type; |
| 90 uint8_t* buffer = NULL; |
| 91 Dart_Handle result = Dart_TypedDataAcquireData( |
| 92 data_obj, &type, reinterpret_cast<void**>(&buffer), &length); |
| 93 if (!Dart_IsError(result)) { |
| 94 uint8_t* zlib_buffer = new uint8_t[length]; |
| 95 if (zlib_buffer == NULL) { |
| 96 Dart_TypedDataReleaseData(data_obj); |
| 97 Dart_ThrowException(DartUtils::NewInternalError( |
| 98 "Failed to allocate buffer for zlib")); |
| 99 } |
| 100 memmove(zlib_buffer, buffer, length); |
| 101 Dart_TypedDataReleaseData(data_obj); |
| 102 buffer = zlib_buffer; |
| 103 } else { |
| 104 if (Dart_IsError(Dart_ListLength(data_obj, &length))) { |
| 105 Dart_ThrowException(DartUtils::NewInternalError( |
| 106 "Failed to get list length")); |
| 107 } |
| 108 buffer = new uint8_t[length]; |
| 109 if (Dart_IsError(Dart_ListGetAsBytes(data_obj, 0, buffer, length))) { |
| 110 delete[] buffer; |
| 111 Dart_ThrowException(DartUtils::NewInternalError( |
| 112 "Failed to get list bytes")); |
| 113 } |
| 114 } |
| 115 // Process will take ownership of buffer, if successful. |
| 116 if (!filter->Process(buffer, length)) { |
| 117 delete[] buffer; |
| 118 EndFilter(filter_obj, filter); |
| 119 Dart_ThrowException(DartUtils::NewInternalError( |
| 120 "Call to Process while still processing data")); |
| 121 } |
| 122 Dart_ExitScope(); |
| 123 } |
| 124 |
| 125 |
| 126 void FUNCTION_NAME(Filter_Processed)(Dart_NativeArguments args) { |
| 127 Dart_EnterScope(); |
| 128 Dart_Handle filter_obj = Dart_GetNativeArgument(args, 0); |
| 129 Filter* filter = GetFilter(filter_obj); |
| 130 Dart_Handle flush_obj = Dart_GetNativeArgument(args, 1); |
| 131 bool flush; |
| 132 if (Dart_IsError(Dart_BooleanValue(flush_obj, &flush))) { |
| 133 Dart_ThrowException(DartUtils::NewInternalError( |
| 134 "Failed to get 'flush' parameter")); |
| 135 } |
| 136 uint8_t buffer[kFilterBufferLength]; |
| 137 intptr_t read = filter->Processed(buffer, kFilterBufferLength, flush); |
| 138 if (read < 0) { |
| 139 // Error, end filter. |
| 140 EndFilter(filter_obj, filter); |
| 141 Dart_ThrowException(DartUtils::NewInternalError( |
| 142 "Filter error, bad data")); |
| 143 } else if (read == 0) { |
| 144 Dart_SetReturnValue(args, Dart_Null()); |
| 145 } else { |
| 146 uint8_t* io_buffer; |
| 147 Dart_Handle result = IOBuffer::Allocate(read, &io_buffer); |
| 148 memmove(io_buffer, buffer, read); |
| 149 Dart_SetReturnValue(args, result); |
| 150 } |
| 151 Dart_ExitScope(); |
| 152 } |
| 153 |
| 154 |
| 155 void FUNCTION_NAME(Filter_End)(Dart_NativeArguments args) { |
| 156 Dart_EnterScope(); |
| 157 Dart_Handle filter_obj = Dart_GetNativeArgument(args, 0); |
| 158 Filter* filter = GetFilter(filter_obj); |
| 159 EndFilter(filter_obj, filter); |
| 160 Dart_ExitScope(); |
| 161 } |
| 162 |
| 163 |
| 164 Dart_Handle Filter::SetFilterPointerNativeField(Dart_Handle filter, |
| 165 Filter* filter_pointer) { |
| 166 return Dart_SetNativeInstanceField(filter, |
| 167 kFilterPointerNativeField, |
| 168 (intptr_t)filter_pointer); |
| 169 } |
| 170 |
| 171 |
| 172 Dart_Handle Filter::GetFilterPointerNativeField(Dart_Handle filter, |
| 173 Filter** filter_pointer) { |
| 174 return Dart_GetNativeInstanceField( |
| 175 filter, |
| 176 kFilterPointerNativeField, |
| 177 reinterpret_cast<intptr_t*>(filter_pointer)); |
| 178 } |
| 179 |
| 180 |
| 181 ZLibDeflateFilter::~ZLibDeflateFilter() { |
| 182 delete[] current_buffer; |
| 183 if (initialized) deflateEnd(&stream); |
| 184 } |
| 185 |
| 186 |
| 187 bool ZLibDeflateFilter::Init() { |
| 188 stream.zalloc = Z_NULL; |
| 189 stream.zfree = Z_NULL; |
| 190 stream.opaque = Z_NULL; |
| 191 int result = deflateInit2( |
| 192 &stream, |
| 193 level, |
| 194 Z_DEFLATED, |
| 195 kZLibFlagWindowBits | (gZip ? kZLibFlagUseGZipHeader : 0), |
| 196 kZlibFlagMemUsage, |
| 197 Z_DEFAULT_STRATEGY); |
| 198 if (result == Z_OK) { |
| 199 initialized = true; |
| 200 return true; |
| 201 } |
| 202 return false; |
| 203 } |
| 204 |
| 205 |
| 206 bool ZLibDeflateFilter::Process(uint8_t* data, intptr_t length) { |
| 207 if (current_buffer != NULL) return false; |
| 208 stream.avail_in = length; |
| 209 stream.next_in = current_buffer = data; |
| 210 return true; |
| 211 } |
| 212 |
| 213 intptr_t ZLibDeflateFilter::Processed(uint8_t* buffer, |
| 214 intptr_t length, |
| 215 bool flush) { |
| 216 stream.avail_out = length; |
| 217 stream.next_out = buffer; |
| 218 switch (deflate(&stream, flush ? Z_SYNC_FLUSH : Z_NO_FLUSH)) { |
| 219 case Z_OK: { |
| 220 intptr_t processed = length - stream.avail_out; |
| 221 if (processed == 0) { |
| 222 delete[] current_buffer; |
| 223 current_buffer = NULL; |
| 224 return 0; |
| 225 } else { |
| 226 // We processed data, should be called again. |
| 227 return processed; |
| 228 } |
| 229 } |
| 230 |
| 231 case Z_STREAM_END: |
| 232 case Z_BUF_ERROR: |
| 233 // We processed all available input data. |
| 234 delete[] current_buffer; |
| 235 current_buffer = NULL; |
| 236 return 0; |
| 237 |
| 238 default: |
| 239 case Z_STREAM_ERROR: |
| 240 // An error occoured. |
| 241 delete[] current_buffer; |
| 242 current_buffer = NULL; |
| 243 return -1; |
| 244 } |
| 245 } |
| 246 |
| 247 |
| 248 ZLibInflateFilter::~ZLibInflateFilter() { |
| 249 delete[] current_buffer; |
| 250 if (initialized) inflateEnd(&stream); |
| 251 } |
| 252 |
| 253 |
| 254 bool ZLibInflateFilter::Init() { |
| 255 stream.zalloc = Z_NULL; |
| 256 stream.zfree = Z_NULL; |
| 257 stream.opaque = Z_NULL; |
| 258 int result = inflateInit2(&stream, |
| 259 kZLibFlagWindowBits | kZLibFlagAcceptAnyHeader); |
| 260 if (result == Z_OK) { |
| 261 initialized = true; |
| 262 return true; |
| 263 } |
| 264 return false; |
| 265 } |
| 266 |
| 267 |
| 268 bool ZLibInflateFilter::Process(uint8_t* data, intptr_t length) { |
| 269 if (current_buffer != NULL) return false; |
| 270 stream.avail_in = length; |
| 271 stream.next_in = current_buffer = data; |
| 272 return true; |
| 273 } |
| 274 |
| 275 |
| 276 intptr_t ZLibInflateFilter::Processed(uint8_t* buffer, |
| 277 intptr_t length, |
| 278 bool flush) { |
| 279 stream.avail_out = length; |
| 280 stream.next_out = buffer; |
| 281 switch (inflate(&stream, flush ? Z_SYNC_FLUSH : Z_NO_FLUSH)) { |
| 282 case Z_OK: { |
| 283 intptr_t processed = length - stream.avail_out; |
| 284 if (processed == 0) { |
| 285 delete[] current_buffer; |
| 286 current_buffer = NULL; |
| 287 return 0; |
| 288 } else { |
| 289 // We processed data, should be called again. |
| 290 return processed; |
| 291 } |
| 292 } |
| 293 |
| 294 case Z_STREAM_END: |
| 295 case Z_BUF_ERROR: |
| 296 // We processed all available input data. |
| 297 delete[] current_buffer; |
| 298 current_buffer = NULL; |
| 299 return 0; |
| 300 |
| 301 default: |
| 302 case Z_MEM_ERROR: |
| 303 case Z_NEED_DICT: |
| 304 case Z_DATA_ERROR: |
| 305 case Z_STREAM_ERROR: |
| 306 // An error occoured. |
| 307 delete[] current_buffer; |
| 308 current_buffer = NULL; |
| 309 return -1; |
| 310 } |
| 311 } |
| 312 |
| OLD | NEW |