Chromium Code Reviews| 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 if (Dart_IsError(Filter::GetFilterPointerNativeField(filter_obj, &filter)) | |
| 23 || filter == NULL) { | |
|
Søren Gjesse
2013/03/05 15:59:05
Shouldn't we call Dart_PropagateError when we Dart
Anders Johnsen
2013/03/06 10:32:46
Done.
| |
| 24 Dart_ThrowException(DartUtils::NewInternalError("Failed to get filter")); | |
| 25 } | |
| 26 return filter; | |
| 27 } | |
| 28 | |
| 29 void EndFilter(Dart_Handle filter_obj, Filter* filter) { | |
| 30 Filter::SetFilterPointerNativeField(filter_obj, NULL); | |
| 31 delete filter; | |
| 32 } | |
| 33 | |
| 34 void FUNCTION_NAME(Filter_CreateZLibInflate)(Dart_NativeArguments args) { | |
| 35 Dart_EnterScope(); | |
| 36 Dart_Handle filter_obj = Dart_GetNativeArgument(args, 0); | |
| 37 Filter* filter = new ZLibInflateFilter(); | |
| 38 if (!filter->Init() || | |
|
Søren Gjesse
2013/03/05 15:59:05
NULL check as well.
Anders Johnsen
2013/03/06 10:32:46
Done.
| |
| 39 Dart_IsError(Filter::SetFilterPointerNativeField(filter_obj, filter))) { | |
| 40 delete filter; | |
| 41 Dart_ThrowException(DartUtils::NewInternalError( | |
| 42 "Failed to create ZLibInflateFilter")); | |
| 43 } | |
| 44 Dart_ExitScope(); | |
| 45 } | |
| 46 | |
| 47 void FUNCTION_NAME(Filter_CreateZLibDeflate)(Dart_NativeArguments args) { | |
| 48 Dart_EnterScope(); | |
| 49 Dart_Handle filter_obj = Dart_GetNativeArgument(args, 0); | |
| 50 Dart_Handle gzip_obj = Dart_GetNativeArgument(args, 1); | |
| 51 Dart_Handle level_obj = Dart_GetNativeArgument(args, 2); | |
| 52 bool gzip; | |
| 53 if (Dart_IsError(Dart_BooleanValue(gzip_obj, &gzip))) { | |
| 54 Dart_ThrowException(DartUtils::NewInternalError( | |
| 55 "Failed to get 'gzip' parameter")); | |
| 56 } | |
| 57 int64_t level; | |
| 58 if (Dart_IsError(Dart_IntegerToInt64(level_obj, &level))) { | |
| 59 Dart_ThrowException(DartUtils::NewInternalError( | |
| 60 "Failed to get 'level' parameter")); | |
| 61 } | |
| 62 Filter* filter = new ZLibDeflateFilter(gzip, level); | |
| 63 if (!filter->Init() || | |
|
Søren Gjesse
2013/03/05 15:59:05
NULL check here as well.
Anders Johnsen
2013/03/06 10:32:46
Done.
| |
| 64 Dart_IsError(Filter::SetFilterPointerNativeField(filter_obj, filter))) { | |
| 65 delete filter; | |
| 66 Dart_ThrowException(DartUtils::NewInternalError( | |
| 67 "Failed to create ZLibDeflateFilter")); | |
| 68 } | |
| 69 Dart_ExitScope(); | |
| 70 } | |
| 71 | |
| 72 void FUNCTION_NAME(Filter_Process)(Dart_NativeArguments args) { | |
| 73 Dart_EnterScope(); | |
| 74 Dart_Handle filter_obj = Dart_GetNativeArgument(args, 0); | |
| 75 Filter* filter = GetFilter(filter_obj); | |
| 76 Dart_Handle data_obj = Dart_GetNativeArgument(args, 1); | |
| 77 intptr_t length; | |
| 78 if (Dart_IsError(Dart_ListLength(data_obj, &length))) { | |
| 79 Dart_ThrowException(DartUtils::NewInternalError( | |
| 80 "Failed to get data length")); | |
| 81 } | |
| 82 uint8_t* data = new uint8_t[length]; | |
| 83 if (Dart_IsError(Dart_ListGetAsBytes(data_obj, 0, data, length))) { | |
|
Søren Gjesse
2013/03/05 15:59:05
Before using ListGetAsBytes you should try Dart_Ty
Anders Johnsen
2013/03/06 10:32:46
Done.
| |
| 84 delete[] data; | |
| 85 Dart_ThrowException(DartUtils::NewInternalError( | |
| 86 "Failed to get data bytes")); | |
| 87 } | |
| 88 if (!filter->Process(data, length)) { | |
| 89 delete[] data; | |
| 90 Dart_ThrowException(DartUtils::NewInternalError( | |
| 91 "Call to Process while still processing data")); | |
| 92 } | |
| 93 Dart_ExitScope(); | |
| 94 } | |
| 95 | |
| 96 | |
| 97 void FUNCTION_NAME(Filter_Processed)(Dart_NativeArguments args) { | |
| 98 Dart_EnterScope(); | |
| 99 Dart_Handle filter_obj = Dart_GetNativeArgument(args, 0); | |
| 100 Filter* filter = GetFilter(filter_obj); | |
| 101 Dart_Handle flush_obj = Dart_GetNativeArgument(args, 1); | |
| 102 bool flush; | |
| 103 if (Dart_IsError(Dart_BooleanValue(flush_obj, &flush))) { | |
| 104 Dart_ThrowException(DartUtils::NewInternalError( | |
| 105 "Failed to get 'flush' parameter")); | |
| 106 } | |
| 107 uint8_t buffer[kFilterBufferLength]; | |
| 108 intptr_t read = filter->Processed(buffer, kFilterBufferLength, flush); | |
| 109 if (read < 0) { | |
| 110 // Error, end filter. | |
| 111 EndFilter(filter_obj, filter); | |
| 112 Dart_ThrowException(DartUtils::NewInternalError( | |
| 113 "Filter error, bad data")); | |
| 114 } else if (read == 0) { | |
| 115 Dart_SetReturnValue(args, Dart_Null()); | |
| 116 } else { | |
| 117 uint8_t* io_buffer; | |
| 118 Dart_Handle result = IOBuffer::Allocate(read, &io_buffer); | |
| 119 memmove(io_buffer, buffer, read); | |
| 120 Dart_SetReturnValue(args, result); | |
| 121 } | |
| 122 Dart_ExitScope(); | |
| 123 } | |
| 124 | |
| 125 | |
| 126 void FUNCTION_NAME(Filter_End)(Dart_NativeArguments args) { | |
| 127 Dart_EnterScope(); | |
| 128 Dart_Handle filter_obj = Dart_GetNativeArgument(args, 0); | |
| 129 Filter* filter = GetFilter(filter_obj); | |
| 130 EndFilter(filter_obj, filter); | |
| 131 Dart_ExitScope(); | |
| 132 } | |
| 133 | |
| 134 | |
| 135 Dart_Handle Filter::SetFilterPointerNativeField(Dart_Handle filter, | |
| 136 Filter* filter_pointer) { | |
| 137 return Dart_SetNativeInstanceField(filter, | |
| 138 kFilterPointerNativeField, | |
| 139 (intptr_t)filter_pointer); | |
| 140 } | |
| 141 | |
| 142 | |
| 143 Dart_Handle Filter::GetFilterPointerNativeField(Dart_Handle filter, | |
| 144 Filter** filter_pointer) { | |
| 145 return Dart_GetNativeInstanceField( | |
| 146 filter, | |
| 147 kFilterPointerNativeField, | |
| 148 reinterpret_cast<intptr_t*>(filter_pointer)); | |
| 149 } | |
| 150 | |
| 151 | |
| 152 ZLibDeflateFilter::~ZLibDeflateFilter() { | |
| 153 delete[] current_buffer; | |
| 154 deflateEnd(&stream); | |
| 155 } | |
| 156 | |
| 157 | |
| 158 bool ZLibDeflateFilter::Init() { | |
| 159 stream.zalloc = Z_NULL; | |
| 160 stream.zfree = Z_NULL; | |
| 161 stream.opaque = Z_NULL; | |
| 162 return deflateInit2(&stream, | |
| 163 level, | |
| 164 Z_DEFLATED, | |
| 165 kZLibFlagWindowBits | (gZip ? kZLibFlagUseGZipHeader : 0), | |
| 166 kZlibFlagMemUsage, | |
| 167 Z_DEFAULT_STRATEGY) == Z_OK; | |
| 168 } | |
| 169 | |
| 170 | |
| 171 bool ZLibDeflateFilter::Process(uint8_t* data, intptr_t length) { | |
| 172 if (current_buffer != NULL) return false; | |
| 173 stream.avail_in = length; | |
| 174 stream.next_in = current_buffer = data; | |
| 175 return true; | |
| 176 } | |
| 177 | |
| 178 intptr_t ZLibDeflateFilter::Processed(uint8_t* buffer, | |
| 179 intptr_t length, | |
| 180 bool flush) { | |
| 181 stream.avail_out = length; | |
| 182 stream.next_out = buffer; | |
| 183 switch (deflate(&stream, flush ? Z_SYNC_FLUSH : Z_NO_FLUSH)) { | |
| 184 case Z_OK: | |
| 185 // We processed data, should be called again. | |
| 186 return length - stream.avail_out; | |
| 187 | |
| 188 case Z_STREAM_END: | |
| 189 case Z_BUF_ERROR: | |
| 190 // We processed all available input data. | |
| 191 delete[] current_buffer; | |
| 192 current_buffer = NULL; | |
| 193 return 0; | |
| 194 | |
| 195 default: | |
| 196 case Z_STREAM_ERROR: | |
| 197 // An error occoured. | |
| 198 delete[] current_buffer; | |
| 199 current_buffer = NULL; | |
| 200 return -1; | |
| 201 } | |
| 202 } | |
| 203 | |
| 204 | |
| 205 ZLibInflateFilter::~ZLibInflateFilter() { | |
| 206 delete[] current_buffer; | |
| 207 inflateEnd(&stream); | |
| 208 } | |
| 209 | |
| 210 | |
| 211 bool ZLibInflateFilter::Init() { | |
| 212 stream.zalloc = Z_NULL; | |
| 213 stream.zfree = Z_NULL; | |
| 214 stream.opaque = Z_NULL; | |
| 215 return inflateInit2(&stream, | |
| 216 kZLibFlagWindowBits | kZLibFlagAcceptAnyHeader) == Z_OK; | |
| 217 } | |
| 218 | |
| 219 | |
| 220 bool ZLibInflateFilter::Process(uint8_t* data, intptr_t length) { | |
| 221 if (current_buffer != NULL) return false; | |
| 222 stream.avail_in = length; | |
| 223 stream.next_in = current_buffer = data; | |
| 224 return true; | |
| 225 } | |
| 226 | |
| 227 | |
| 228 intptr_t ZLibInflateFilter::Processed(uint8_t* buffer, | |
| 229 intptr_t length, | |
| 230 bool flush) { | |
| 231 stream.avail_out = length; | |
| 232 stream.next_out = buffer; | |
| 233 switch (inflate(&stream, flush ? Z_SYNC_FLUSH : Z_NO_FLUSH)) { | |
| 234 case Z_OK: { | |
| 235 intptr_t processed = length - stream.avail_out; | |
| 236 if (processed == 0) { | |
| 237 delete[] current_buffer; | |
| 238 current_buffer = NULL; | |
| 239 return 0; | |
| 240 } else { | |
| 241 // We processed data, should be called again. | |
| 242 return processed; | |
| 243 } | |
| 244 } | |
| 245 | |
| 246 case Z_STREAM_END: | |
| 247 case Z_BUF_ERROR: | |
| 248 // We processed all available input data. | |
| 249 delete[] current_buffer; | |
| 250 current_buffer = NULL; | |
| 251 return 0; | |
| 252 | |
| 253 default: | |
| 254 case Z_MEM_ERROR: | |
| 255 case Z_NEED_DICT: | |
| 256 case Z_DATA_ERROR: | |
| 257 case Z_STREAM_ERROR: | |
| 258 // An error occoured. | |
| 259 delete[] current_buffer; | |
| 260 current_buffer = NULL; | |
| 261 return -1; | |
| 262 } | |
| 263 } | |
| 264 | |
| OLD | NEW |