summaryrefslogtreecommitdiffstats
path: root/o3d/import/cross/gz_decompressor.cc
diff options
context:
space:
mode:
Diffstat (limited to 'o3d/import/cross/gz_decompressor.cc')
-rw-r--r--o3d/import/cross/gz_decompressor.cc121
1 files changed, 121 insertions, 0 deletions
diff --git a/o3d/import/cross/gz_decompressor.cc b/o3d/import/cross/gz_decompressor.cc
new file mode 100644
index 0000000..333a999
--- /dev/null
+++ b/o3d/import/cross/gz_decompressor.cc
@@ -0,0 +1,121 @@
+/*
+ * Copyright 2009, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+//
+// GzDecompressor decompresses a gzip compressed byte stream
+// calling the client's ProcessBytes() method with the uncompressed stream
+//
+
+#include "import/cross/gz_decompressor.h"
+
+#include <assert.h>
+#include "import/cross/memory_stream.h"
+
+const size_t kChunkSize = 16384;
+
+namespace o3d {
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+GzDecompressor::GzDecompressor(StreamProcessor *callback_client)
+ : callback_client_(callback_client) {
+ // Initialize inflate state
+ strm_.zalloc = Z_NULL;
+ strm_.zfree = Z_NULL;
+ strm_.opaque = Z_NULL;
+ strm_.avail_in = 0;
+ strm_.next_in = Z_NULL;
+
+ // Store this, so we can later check if it's OK to start processing
+ init_result_ = inflateInit2(&strm_, 31);
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+GzDecompressor::~GzDecompressor() {
+ inflateEnd(&strm_);
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+int GzDecompressor::ProcessBytes(MemoryReadStream *stream,
+ size_t bytes_to_process) {
+ // Don't even bother trying if we didn't get initialized properly
+ if (init_result_ != Z_OK) return init_result_;
+
+ uint8 out[kChunkSize];
+ int result;
+ size_t have;
+
+ // Don't try to read more than our stream has
+ int remaining = stream->GetRemainingByteCount();
+ if (bytes_to_process > remaining) {
+ return Z_STREAM_ERROR; // could have our own error code, but good enough...
+ }
+
+ // Use direct memory access on the MemoryStream object
+ strm_.avail_in = bytes_to_process;
+ strm_.next_in = const_cast<uint8*>(stream->GetDirectMemoryPointer());
+ stream->Skip(bytes_to_process);
+
+ // Run inflate() on input until output buffer not full
+ do {
+ strm_.avail_out = kChunkSize;
+ strm_.next_out = out;
+
+ result = inflate(&strm_, Z_NO_FLUSH);
+
+ // error check here - return error codes if necessary
+ assert(result != Z_STREAM_ERROR); /* state not clobbered */
+ switch (result) {
+ case Z_NEED_DICT:
+ result = Z_DATA_ERROR; /* and fall through */
+
+ case Z_DATA_ERROR:
+ case Z_MEM_ERROR:
+ return result;
+ }
+
+ have = kChunkSize - strm_.avail_out;
+
+ // Callback with the decompressed byte stream
+ MemoryReadStream decompressed_stream(out, have);
+ if (callback_client_) {
+ int client_result =
+ callback_client_->ProcessBytes(&decompressed_stream, have);
+ if (client_result != 0) {
+ return client_result; // propagate callback errors
+ }
+ }
+ } while (strm_.avail_out == 0);
+
+ return result;
+}
+
+} // namespace o3d