Index: runtime/bin/main.cc |
diff --git a/runtime/bin/main.cc b/runtime/bin/main.cc |
index f8ef12f0fc5fb1b1bcb469e9aa8ce66bc4119806..3c42d8b2828fe43af330bbeae488536b7eb51317 100644 |
--- a/runtime/bin/main.cc |
+++ b/runtime/bin/main.cc |
@@ -26,6 +26,7 @@ |
#include "platform/globals.h" |
#include "platform/hashmap.h" |
#include "platform/text_buffer.h" |
+#include "zlib/zlib.h" |
namespace dart { |
namespace bin { |
@@ -1282,10 +1283,83 @@ bool RunMainIsolate(const char* script_name, |
extern unsigned int observatory_assets_archive_len; |
extern const uint8_t* observatory_assets_archive; |
+ |
+// |input| is assumed to be a gzipped stream. |
+// This function allocates the output buffer in the C heap and the caller |
+// is responsible for freeing it. |
+void Decompress(const uint8_t* input, unsigned int input_len, |
+ uint8_t** output, unsigned int* output_length) { |
+ ASSERT(input != NULL); |
+ ASSERT(input_len > 0); |
+ ASSERT(output != NULL); |
+ ASSERT(output_length != NULL); |
+ |
+ // Initialize output. |
+ *output = NULL; |
+ *output_length = 0; |
+ |
+ const intptr_t kChunkSize = 256 * 1024; |
+ uint8_t chunk_out[kChunkSize]; |
+ z_stream strm; |
+ strm.zalloc = Z_NULL; |
+ strm.zfree = Z_NULL; |
+ strm.opaque = Z_NULL; |
+ strm.avail_in = 0; |
+ strm.next_in = 0; |
+ int ret = inflateInit2(&strm, 32 + MAX_WBITS); |
+ ASSERT(ret == Z_OK); |
+ |
+ unsigned int input_cursor = 0; |
+ unsigned int output_cursor = 0; |
+ do { |
+ // Setup input. |
+ unsigned int size_in = input_len - input_cursor; |
+ if (size_in > kChunkSize) { |
+ size_in = kChunkSize; |
+ } |
+ strm.avail_in = size_in; |
+ strm.next_in = const_cast<uint8_t*>(&input[input_cursor]); |
+ |
+ // Inflate until we've exhausted the current input chunk. |
+ do { |
+ // Setup output. |
+ strm.avail_out = kChunkSize; |
+ strm.next_out = &chunk_out[0]; |
+ // Inflate. |
+ ret = inflate(&strm, Z_SYNC_FLUSH); |
+ // We either hit the end of the stream or made forward progress. |
+ ASSERT((ret == Z_STREAM_END) || (ret == Z_OK)); |
+ // Grow output buffer size. |
+ unsigned int size_out = kChunkSize - strm.avail_out; |
+ *output_length += size_out; |
+ *output = reinterpret_cast<uint8_t*>(realloc(*output, *output_length)); |
+ // Copy output. |
+ memmove(&((*output)[output_cursor]), &chunk_out[0], size_out); |
+ output_cursor += size_out; |
+ } while (strm.avail_out == 0); |
+ |
+ // We've processed size_in bytes. |
+ input_cursor += size_in; |
+ |
+ // We're finished decompressing when zlib tells us. |
+ } while (ret != Z_STREAM_END); |
+ |
+ inflateEnd(&strm); |
+} |
+ |
+ |
Dart_Handle GetVMServiceAssetsArchiveCallback() { |
- return DartUtils::MakeUint8Array( |
- observatory_assets_archive, |
- observatory_assets_archive_len); |
+ uint8_t* decompressed = NULL; |
+ unsigned int decompressed_len = 0; |
+ Decompress(observatory_assets_archive, |
+ observatory_assets_archive_len, |
+ &decompressed, |
+ &decompressed_len); |
+ Dart_Handle tar_file = DartUtils::MakeUint8Array(decompressed, |
+ decompressed_len); |
+ // Free decompressed memory as it has been copied into a Dart array. |
+ free(decompressed); |
+ return tar_file; |
} |