Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 // Copyright (c) 2012, 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/filter.h" | |
| 6 #include "bin/dartutils.h" | |
| 7 | |
| 8 #include "include/dart_api.h" | |
| 9 | |
| 10 const int kZlibFlagMemUsage = 8; | |
| 11 const int kZLibFlagWindowBits = 15; | |
| 12 const int kZLibFlagUseGZipHeader = 16; | |
| 13 const int kZLibFlagAcceptAnyHeader = 32; | |
| 14 | |
| 15 const intptr_t kFilterBufferLength = 64 * KB; | |
| 16 | |
| 17 static const int kFilterPointerNativeField = 0; | |
| 18 | |
| 19 void DeleteBuffer(void* buffer) { | |
| 20 delete[] reinterpret_cast<uint8_t*>(buffer); | |
| 21 } | |
| 22 | |
| 23 Filter* GetFilter(Dart_Handle filter_obj) { | |
| 24 Filter* filter; | |
| 25 if (Dart_IsError(Filter::GetFilterPointerNativeField(filter_obj, &filter)) | |
| 26 || filter == NULL) { | |
| 27 OSError os_error(-1, "Failed to get filter", OSError::kUnknown); | |
| 28 Dart_Handle err = DartUtils::NewDartOSError(&os_error); | |
| 29 Dart_ThrowException(err); | |
| 30 } | |
| 31 return filter; | |
| 32 } | |
| 33 | |
| 34 void EndFilter(Dart_Handle filter_obj, Filter* filter) { | |
| 35 Filter::SetFilterPointerNativeField(filter_obj, NULL); | |
| 36 delete filter; | |
| 37 } | |
| 38 | |
| 39 void FUNCTION_NAME(Filter_CreateZLibInflate)(Dart_NativeArguments args) { | |
| 40 Dart_EnterScope(); | |
| 41 Dart_Handle filter_obj = Dart_GetNativeArgument(args, 0); | |
| 42 Filter* filter = new ZLibInflateFilter(); | |
| 43 if (!filter->Init() || | |
| 44 Dart_IsError(Filter::SetFilterPointerNativeField(filter_obj, filter))) { | |
| 45 delete filter; | |
| 46 OSError os_error(-1, "Failed to create ZLibInflateFilter", | |
| 47 OSError::kUnknown); | |
| 48 Dart_Handle err = DartUtils::NewDartOSError(&os_error); | |
| 49 Dart_ThrowException(err); | |
| 50 } | |
| 51 Dart_ExitScope(); | |
| 52 } | |
| 53 | |
| 54 void FUNCTION_NAME(Filter_CreateGZipDeflate)(Dart_NativeArguments args) { | |
| 55 Dart_EnterScope(); | |
| 56 Dart_Handle filter_obj = Dart_GetNativeArgument(args, 0); | |
| 57 Filter* filter = new ZLibDeflateFilter(true); | |
| 58 if (!filter->Init() || | |
| 59 Dart_IsError(Filter::SetFilterPointerNativeField(filter_obj, filter))) { | |
| 60 delete filter; | |
| 61 OSError os_error(-1, "Failed to create GZipDeflateFilter", | |
| 62 OSError::kUnknown); | |
| 63 Dart_Handle err = DartUtils::NewDartOSError(&os_error); | |
|
Søren Gjesse
2012/10/25 11:01:44
I am sorry for leading you down this path, but the
Anders Johnsen
2012/10/25 13:10:56
I've added an InternalError class and used it acco
| |
| 64 Dart_ThrowException(err); | |
| 65 } | |
| 66 Dart_ExitScope(); | |
| 67 } | |
| 68 | |
| 69 void FUNCTION_NAME(Filter_Process)(Dart_NativeArguments args) { | |
| 70 Dart_EnterScope(); | |
| 71 Dart_Handle filter_obj = Dart_GetNativeArgument(args, 0); | |
| 72 Filter* filter = GetFilter(filter_obj); | |
| 73 Dart_Handle data_obj = Dart_GetNativeArgument(args, 1); | |
| 74 intptr_t length; | |
| 75 if (Dart_IsError(Dart_ListLength(data_obj, &length))) { | |
| 76 OSError os_error(-1, "Failed to get data length", OSError::kUnknown); | |
| 77 Dart_Handle err = DartUtils::NewDartOSError(&os_error); | |
| 78 Dart_ThrowException(err); | |
| 79 } | |
| 80 uint8_t* data = new uint8_t[length]; | |
| 81 if (Dart_IsError(Dart_ListGetAsBytes(data_obj, 0, data, length))) { | |
| 82 delete[] data; | |
|
Søren Gjesse
2012/10/25 11:01:44
Maybe use DeleteBuffer here (and in the other plac
Anders Johnsen
2012/10/25 13:10:56
Done.
| |
| 83 OSError os_error(-1, "Failed to get data bytes", OSError::kUnknown); | |
| 84 Dart_Handle err = DartUtils::NewDartOSError(&os_error); | |
| 85 Dart_ThrowException(err); | |
| 86 } | |
| 87 if (!filter->Process(data, length)) { | |
| 88 OSError os_error(-1, | |
| 89 "Call to Process while still processing data", | |
| 90 OSError::kUnknown); | |
| 91 Dart_Handle err = DartUtils::NewDartOSError(&os_error); | |
| 92 Dart_ThrowException(err); | |
| 93 } | |
| 94 Dart_ExitScope(); | |
| 95 } | |
| 96 | |
| 97 | |
| 98 void FUNCTION_NAME(Filter_Processed)(Dart_NativeArguments args) { | |
| 99 Dart_EnterScope(); | |
| 100 Dart_Handle filter_obj = Dart_GetNativeArgument(args, 0); | |
| 101 Filter* filter = GetFilter(filter_obj); | |
| 102 Dart_Handle flush_obj = Dart_GetNativeArgument(args, 1); | |
| 103 bool flush; | |
| 104 if (Dart_IsError(Dart_BooleanValue(flush_obj, &flush))) { | |
| 105 OSError os_error(-1, "Failed to get 'flush' parameter", OSError::kUnknown); | |
| 106 Dart_Handle err = DartUtils::NewDartOSError(&os_error); | |
| 107 Dart_ThrowException(err); | |
| 108 } | |
| 109 uint8_t* buffer = new uint8_t[kFilterBufferLength]; | |
| 110 intptr_t read = filter->Processed(buffer, kFilterBufferLength, flush); | |
| 111 if (read < 0) { | |
| 112 // Error, end filter. | |
| 113 EndFilter(filter_obj, filter); | |
| 114 delete[] buffer; | |
| 115 OSError os_error(-1, "Filter error, bad data", OSError::kUnknown); | |
| 116 Dart_Handle err = DartUtils::NewDartOSError(&os_error); | |
| 117 Dart_ThrowException(err); | |
| 118 } else if (read == 0) { | |
| 119 delete[] buffer; | |
| 120 Dart_SetReturnValue(args, Dart_Null()); | |
| 121 } else { | |
| 122 Dart_Handle result; | |
| 123 if (read == kFilterBufferLength) { | |
| 124 result = Dart_NewExternalByteArray(buffer, read, buffer, DeleteBuffer); | |
| 125 } else { | |
|
Søren Gjesse
2012/10/25 11:01:44
Can't you create an external byte array here as we
Anders Johnsen
2012/10/25 13:10:56
I like this idea! We are currently using buffers w
Søren Gjesse
2012/10/25 13:54:45
At some point we probable need to give the VM some
| |
| 126 result = Dart_NewByteArray(read); | |
| 127 Dart_ListSetAsBytes(result, 0, buffer, read); | |
| 128 delete[] buffer; | |
| 129 } | |
| 130 Dart_SetReturnValue(args, result); | |
| 131 } | |
| 132 Dart_ExitScope(); | |
| 133 } | |
| 134 | |
| 135 | |
| 136 void FUNCTION_NAME(Filter_End)(Dart_NativeArguments args) { | |
| 137 Dart_EnterScope(); | |
| 138 Dart_Handle filter_obj = Dart_GetNativeArgument(args, 0); | |
| 139 Filter* filter = GetFilter(filter_obj); | |
| 140 EndFilter(filter_obj, filter); | |
| 141 Dart_ExitScope(); | |
| 142 } | |
| 143 | |
| 144 | |
| 145 Dart_Handle Filter::SetFilterPointerNativeField(Dart_Handle filter, | |
| 146 Filter* filter_pointer) { | |
| 147 return Dart_SetNativeInstanceField(filter, | |
| 148 kFilterPointerNativeField, | |
| 149 (intptr_t)filter_pointer); | |
| 150 } | |
| 151 | |
| 152 | |
| 153 Dart_Handle Filter::GetFilterPointerNativeField(Dart_Handle filter, | |
| 154 Filter** filter_pointer) { | |
| 155 return Dart_GetNativeInstanceField( | |
| 156 filter, | |
| 157 kFilterPointerNativeField, | |
| 158 reinterpret_cast<intptr_t*>(filter_pointer)); | |
| 159 } | |
| 160 | |
| 161 | |
| 162 ZLibDeflateFilter::~ZLibDeflateFilter() { | |
| 163 delete[] current_buffer; | |
| 164 deflateEnd(&stream); | |
| 165 } | |
| 166 | |
| 167 | |
| 168 bool ZLibDeflateFilter::Init() { | |
| 169 stream.zalloc = Z_NULL; | |
| 170 stream.zfree = Z_NULL; | |
| 171 stream.opaque = Z_NULL; | |
| 172 return deflateInit2(&stream, | |
| 173 level, | |
| 174 Z_DEFLATED, | |
| 175 kZLibFlagWindowBits + (gZip ? kZLibFlagUseGZipHeader : 0), | |
|
Søren Gjesse
2012/10/25 11:01:44
Maybe | here instead of +
Anders Johnsen
2012/10/25 13:10:56
Done.
| |
| 176 kZlibFlagMemUsage, | |
| 177 Z_DEFAULT_STRATEGY) == Z_OK; | |
| 178 } | |
| 179 | |
| 180 | |
| 181 bool ZLibDeflateFilter::Process(uint8_t* data, intptr_t length) { | |
| 182 if (current_buffer != NULL) return false; | |
| 183 stream.avail_in = length; | |
| 184 stream.next_in = current_buffer = data; | |
| 185 return true; | |
| 186 } | |
| 187 | |
| 188 intptr_t ZLibDeflateFilter::Processed(uint8_t* buffer, | |
| 189 intptr_t length, | |
| 190 bool flush) { | |
| 191 stream.avail_out = length; | |
| 192 stream.next_out = buffer; | |
| 193 switch (deflate(&stream, flush ? Z_SYNC_FLUSH : Z_NO_FLUSH)) { | |
| 194 case Z_OK: | |
| 195 // We processed data, should be called again. | |
| 196 return length - stream.avail_out; | |
| 197 | |
| 198 case Z_STREAM_END: | |
| 199 case Z_BUF_ERROR: | |
| 200 // We processed all available input data. | |
| 201 delete[] current_buffer; | |
| 202 current_buffer = NULL; | |
| 203 return 0; | |
| 204 | |
| 205 default: | |
| 206 case Z_STREAM_ERROR: | |
| 207 // An error occoured. | |
| 208 delete[] current_buffer; | |
| 209 current_buffer = NULL; | |
| 210 return -1; | |
| 211 } | |
| 212 } | |
| 213 | |
| 214 | |
| 215 ZLibInflateFilter::~ZLibInflateFilter() { | |
| 216 delete[] current_buffer; | |
| 217 inflateEnd(&stream); | |
| 218 } | |
| 219 | |
| 220 | |
| 221 bool ZLibInflateFilter::Init() { | |
| 222 stream.zalloc = Z_NULL; | |
| 223 stream.zfree = Z_NULL; | |
| 224 stream.opaque = Z_NULL; | |
| 225 return inflateInit2(&stream, | |
| 226 kZLibFlagWindowBits + kZLibFlagAcceptAnyHeader) == Z_OK; | |
|
Søren Gjesse
2012/10/25 11:01:44
Maybe | here instead of +
Anders Johnsen
2012/10/25 13:10:56
Done.
| |
| 227 } | |
| 228 | |
| 229 | |
| 230 bool ZLibInflateFilter::Process(uint8_t* data, intptr_t length) { | |
| 231 if (current_buffer != NULL) return false; | |
| 232 stream.avail_in = length; | |
| 233 stream.next_in = current_buffer = data; | |
| 234 return true; | |
| 235 } | |
| 236 | |
| 237 | |
| 238 intptr_t ZLibInflateFilter::Processed(uint8_t* buffer, | |
| 239 intptr_t length, | |
| 240 bool flush) { | |
| 241 stream.avail_out = length; | |
| 242 stream.next_out = buffer; | |
| 243 switch (inflate(&stream, flush ? Z_SYNC_FLUSH : Z_NO_FLUSH)) { | |
| 244 case Z_OK: | |
| 245 // We processed data, should be called again. | |
| 246 return length - stream.avail_out; | |
| 247 | |
| 248 case Z_STREAM_END: | |
| 249 case Z_BUF_ERROR: | |
| 250 // We processed all available input data. | |
| 251 delete[] current_buffer; | |
| 252 current_buffer = NULL; | |
| 253 return 0; | |
| 254 | |
| 255 default: | |
| 256 case Z_MEM_ERROR: | |
| 257 case Z_NEED_DICT: | |
| 258 case Z_DATA_ERROR: | |
| 259 case Z_STREAM_ERROR: | |
| 260 // An error occoured. | |
| 261 delete[] current_buffer; | |
| 262 current_buffer = NULL; | |
| 263 return -1; | |
| 264 } | |
| 265 } | |
| 266 | |
| OLD | NEW |