Merge pie-platform-release to aosp-master - DO NOT MERGE
Change-Id: Id26ee533663ca94626093fc264a51340f3fd2d34
diff --git a/.clang-format b/.clang-format
index 3f19e61..5f6e882 100644
--- a/.clang-format
+++ b/.clang-format
@@ -1 +1,3 @@
BasedOnStyle: Chromium
+
+AllowAllParametersOfDeclarationOnNextLine: true
diff --git a/Android.bp b/Android.bp
index 5d99dcb..79d124a 100644
--- a/Android.bp
+++ b/Android.bp
@@ -14,10 +14,10 @@
cflags: [
"-DUSE_BRILLO=1",
"-D_FILE_OFFSET_BITS=64",
- "-DZLIB_CONST",
"-Wall",
"-Werror",
"-Wextra",
+ "-Wimplicit-fallthrough",
],
target: {
darwin: {
@@ -62,7 +62,6 @@
static_libs: [
"libbsdiff",
"libpuffpatch",
- "libz",
],
}
@@ -80,7 +79,6 @@
"libdivsufsort64",
"libpuffdiff",
"libpuffpatch",
- "libz",
],
}
@@ -95,15 +93,11 @@
"src/patching_unittest.cc",
"src/puff_io_unittest.cc",
"src/puffin_unittest.cc",
- "src/sample_generator.cc",
"src/stream_unittest.cc",
"src/testrunner.cc",
"src/unittest_common.cc",
"src/utils_unittest.cc",
],
- shared_libs: [
- "libz",
- ],
static_libs: [
"libbsdiff",
"libbspatch",
diff --git a/BUILD.gn b/BUILD.gn
new file mode 100644
index 0000000..f6df14b
--- /dev/null
+++ b/BUILD.gn
@@ -0,0 +1,146 @@
+# Copyright 2018 The Chromium OS Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//common-mk/pkg_config.gni")
+import("//common-mk/proto_library.gni")
+
+group("all") {
+ deps = [
+ ":libpuffin-proto",
+ ":libpuffdiff",
+ ":libpuffpatch",
+ ":puffin",
+ ]
+ if (use.test) {
+ deps += [ ":puffin_test" ]
+ }
+ if (use.fuzzer) {
+ deps += [ ":puffin_fuzzer" ]
+ }
+}
+
+pkg_config("target_defaults") {
+ pkg_deps = [
+ "libchrome-${libbase_ver}",
+ "libbrillo-${libbase_ver}",
+ "protobuf-lite",
+ ]
+ cflags = [ "-Wextra" ]
+ cflags_cc = [ "-Wnon-virtual-dtor" ]
+ include_dirs = [ "src/include" ]
+ defines = [
+ "USE_BRILLO",
+ "_FILE_OFFSET_BITS=64",
+ ]
+}
+
+proto_library("libpuffin-proto") {
+ proto_in_dir = "src"
+ proto_out_dir = "include/puffin/src"
+ sources = [
+ "src/puffin.proto",
+ ]
+}
+
+pkg_config("libpuffpatch_config") {
+ pkg_deps = [
+ "libbspatch",
+ ]
+}
+
+static_library("libpuffpatch") {
+ configs += [
+ "//common-mk:nouse_thin_archive",
+ ":target_defaults",
+ ":libpuffpatch_config",
+ ]
+ configs -= [ "//common-mk:use_thin_archive" ]
+ complete_static_lib = true
+ deps = [ ":libpuffin-proto" ]
+ sources = [
+ "src/bit_reader.cc",
+ "src/bit_writer.cc",
+ "src/huffer.cc",
+ "src/huffman_table.cc",
+ "src/puff_reader.cc",
+ "src/puff_writer.cc",
+ "src/puffer.cc",
+ "src/puffin_stream.cc",
+ "src/puffpatch.cc",
+ ]
+}
+
+pkg_config("libpuffdiff_config") {
+ pkg_deps = [
+ "libbsdiff",
+ ]
+}
+static_library("libpuffdiff") {
+ configs += [
+ "//common-mk:nouse_thin_archive",
+ ":target_defaults",
+ ":libpuffdiff_config",
+ ]
+ configs -= [ "//common-mk:use_thin_archive" ]
+ deps = [
+ ":libpuffpatch",
+ ]
+ sources = [
+ "src/file_stream.cc",
+ "src/memory_stream.cc",
+ "src/puffdiff.cc",
+ "src/utils.cc",
+ ]
+}
+
+executable("puffin") {
+ configs += [
+ ":target_defaults",
+ ]
+ deps = [
+ ":libpuffdiff",
+ ]
+ sources = [
+ "src/extent_stream.cc",
+ "src/main.cc",
+ ]
+}
+
+if (use.test) {
+ executable("puffin_test") {
+ configs += [
+ "//common-mk:test",
+ ":target_defaults",
+ ]
+ sources = [
+ "src/bit_io_unittest.cc",
+ "src/extent_stream.cc",
+ "src/patching_unittest.cc",
+ "src/puff_io_unittest.cc",
+ "src/puffin_unittest.cc",
+ "src/stream_unittest.cc",
+ "src/unittest_common.cc",
+ "src/utils_unittest.cc",
+ ]
+ deps = [
+ "//common-mk/testrunner",
+ ":libpuffdiff",
+ ]
+ }
+}
+
+if (use.fuzzer) {
+ executable("puffin_fuzzer") {
+ configs += [
+ "//common-mk/common_fuzzer",
+ ":target_defaults",
+ ]
+ deps = [
+ ":libpuffdiff",
+ ]
+ sources = [
+ "src/fuzzer.cc",
+ ]
+ }
+}
diff --git a/PRESUBMIT.cfg b/PRESUBMIT.cfg
index c1cb0d7..254479a 100644
--- a/PRESUBMIT.cfg
+++ b/PRESUBMIT.cfg
@@ -1,3 +1,6 @@
[Hook Scripts]
hook0=../../../../chromite/bin/cros lint ${PRESUBMIT_FILES}
hook1=../../../platform2/common-mk/gyplint.py ${PRESUBMIT_FILES}
+
+[Hook Overrides]
+clang_format_check: true
diff --git a/README.version b/README.version
new file mode 100644
index 0000000..387bfbf
--- /dev/null
+++ b/README.version
@@ -0,0 +1,2 @@
+Homepage: https://android.googlesource.com/platform/external/puffin/
+Version: 1.0.0
diff --git a/libpuffdiff.pc b/libpuffdiff.pc
index 50c8ca2..f75de07 100644
--- a/libpuffdiff.pc
+++ b/libpuffdiff.pc
@@ -2,5 +2,8 @@
Name: libpuffdiff
Description: Puffin library for generating delta patches
-Version: 0.0.1
-Libs: -lpuffdiff
\ No newline at end of file
+Version: 1.0.0
+# libpuffdiff library is static lib ATM, so we don't use private versions of
+# Libs and Requires fields.
+Libs: -lpuffdiff
+Requires: libpuffpatch libbsdiff
diff --git a/libpuffpatch.pc b/libpuffpatch.pc
index 2c578a1..dbb7d74 100644
--- a/libpuffpatch.pc
+++ b/libpuffpatch.pc
@@ -2,5 +2,8 @@
Name: libpuffpatch
Description: Puffin library for applying delta patches
-Version: 0.0.1
-Libs: -lpuffpatch
\ No newline at end of file
+Version: 1.0.0
+# libpuffpatch library is static lib ATM, so we don't use private versions of
+# Libs and Requires fields.
+Libs: -lpuffpatch
+Requires: libbspatch
diff --git a/puffin.gyp b/puffin.gyp
deleted file mode 100644
index 4903e00..0000000
--- a/puffin.gyp
+++ /dev/null
@@ -1,199 +0,0 @@
-# Copyright 2017 The Chromium OS Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-{
- 'target_defaults': {
- 'variables': {
- 'deps': [
- 'libbrillo-<(libbase_ver)',
- 'libchrome-<(libbase_ver)',
- ],
- },
- 'cflags': [
- '-Wextra',
- ],
- 'cflags_cc': [
- '-Wnon-virtual-dtor',
- ],
- 'include_dirs': [
- 'src/include',
- ],
- 'defines': [
- 'USE_BRILLO=1',
- '_FILE_OFFSET_BITS=64',
- 'ZLIB_CONST',
- ],
- },
- 'targets': [
- # libpuffin-proto library
- {
- 'target_name': 'libpuffin-proto',
- 'type': 'static_library',
- 'variables': {
- 'proto_in_dir': 'src',
- 'proto_out_dir': 'include/puffin/src',
- },
- 'cflags!': ['-fPIE'],
- 'cflags': ['-fPIC'],
- 'all_dependent_settings': {
- 'variables': {
- 'deps': [
- 'protobuf-lite',
- ],
- },
- },
- 'sources': [
- '<(proto_in_dir)/puffin.proto',
- ],
- 'includes': ['../../platform2/common-mk/protoc.gypi'],
- },
- # puffpatch static library. The reason to do one static and one shared is to
- # be able to run the unittest.
- {
- 'target_name': 'libpuffpatch-static',
- 'type': 'static_library',
- 'cflags!': ['-fPIE'],
- 'cflags': ['-fPIC'],
- 'sources': [
- 'src/bit_reader.cc',
- 'src/bit_writer.cc',
- 'src/huffer.cc',
- 'src/huffman_table.cc',
- 'src/puff_reader.cc',
- 'src/puff_writer.cc',
- 'src/puffer.cc',
- 'src/puffin_stream.cc',
- 'src/puffpatch.cc',
- ],
- 'dependencies': [
- 'libpuffin-proto',
- ],
- 'all_dependent_settings': {
- 'link_settings': {
- 'libraries': [
- '-lbspatch',
- ],
- },
- },
- },
- # puffdiff static library.
- {
- 'target_name': 'libpuffdiff-static',
- 'type': 'static_library',
- 'cflags!': ['-fPIE'],
- 'cflags': ['-fPIC'],
- 'sources': [
- 'src/file_stream.cc',
- 'src/memory_stream.cc',
- 'src/puffdiff.cc',
- 'src/utils.cc',
- ],
- 'dependencies': [
- 'libpuffpatch-static',
- ],
- 'all_dependent_settings': {
- 'variables': {
- 'deps': [
- 'zlib',
- ],
- },
- 'link_settings': {
- 'libraries': [
- '-lbsdiff',
- ],
- },
- },
- },
- # puffpatch shared library.
- {
- 'target_name': 'libpuffpatch',
- 'type': 'shared_library',
- 'dependencies': [
- 'libpuffpatch-static',
- ],
- },
- # puffdiff shared library.
- {
- 'target_name': 'libpuffdiff',
- 'type': 'shared_library',
- 'dependencies': [
- 'libpuffdiff-static',
- ],
- },
- # Puffin executable. We don't use the shared libraries because then we have
- # to export symbols that shouldn't be exported otherwise.
- {
- 'target_name': 'puffin',
- 'type': 'executable',
- 'dependencies': [
- 'libpuffdiff-static',
- ],
- 'sources': [
- 'src/extent_stream.cc',
- 'src/main.cc',
- ],
- },
- ],
- # unit tests.
- 'conditions': [
- ['USE_test == 1', {
- 'targets': [
- # Samples generator.
- {
- 'target_name': 'libsample_generator',
- 'type': 'static_library',
- 'sources': [
- 'src/sample_generator.cc',
- ],
- 'all_dependent_settings': {
- 'variables': {
- 'deps': [
- 'zlib',
- ],
- },
- },
- },
- # Unit tests.
- {
- 'target_name': 'puffin_unittest',
- 'type': 'executable',
- 'dependencies': [
- 'libpuffdiff-static',
- 'libsample_generator',
- '../../platform2/common-mk/testrunner.gyp:testrunner',
- ],
- 'includes': ['../../platform2/common-mk/common_test.gypi'],
- 'sources': [
- 'src/bit_io_unittest.cc',
- 'src/extent_stream.cc',
- 'src/patching_unittest.cc',
- 'src/puff_io_unittest.cc',
- 'src/puffin_unittest.cc',
- 'src/stream_unittest.cc',
- 'src/unittest_common.cc',
- 'src/utils_unittest.cc',
- ],
- },
- ],
- }],
- # fuzzer target
- ['USE_fuzzer == 1', {
- 'targets': [
- {
- 'target_name': 'puffin_fuzzer',
- 'type': 'executable',
- 'dependencies': [
- 'libpuffin-proto',
- 'libpuffdiff-static',
- 'libpuffpatch-static',
- ],
- 'includes': ['../../platform2/common-mk/common_fuzzer.gypi'],
- 'sources': [
- 'src/fuzzer.cc',
- ],
- },
- ],
- }],
- ],
-}
diff --git a/scripts/measure_patch_size.py b/scripts/measure_patch_size.py
new file mode 100755
index 0000000..252217b
--- /dev/null
+++ b/scripts/measure_patch_size.py
@@ -0,0 +1,106 @@
+#!/usr/bin/env python3
+#
+# Copyright 2018 The Chromium OS Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+#
+
+"""A tool for running diffing tools and measuring patch sizes."""
+
+import argparse
+import logging
+import os
+import subprocess
+import sys
+import tempfile
+
+
+class Error(Exception):
+ """Puffin general processing error."""
+
+
+def ParseArguments(argv):
+ """Parses and Validates command line arguments.
+
+ Args:
+ argv: command line arguments to parse.
+
+ Returns:
+ The arguments list.
+ """
+ parser = argparse.ArgumentParser()
+
+ parser.add_argument('--src-corpus', metavar='DIR',
+ help='The source corpus directory with compressed files.')
+ parser.add_argument('--tgt-corpus', metavar='DIR',
+ help='The target corpus directory with compressed files.')
+ parser.add_argument('--debug', action='store_true',
+ help='Turns on verbosity.')
+
+ # Parse command-line arguments.
+ args = parser.parse_args(argv)
+
+ for corpus in (args.src_corpus, args.tgt_corpus):
+ if not corpus or not os.path.isdir(corpus):
+ raise Error('Corpus directory {} is non-existent or inaccesible'
+ .format(corpus))
+ return args
+
+
+def main(argv):
+ """The main function."""
+ args = ParseArguments(argv[1:])
+
+ if args.debug:
+ logging.getLogger().setLevel(logging.DEBUG)
+
+ # Construct list of appropriate files.
+ src_files = list(filter(os.path.isfile,
+ [os.path.join(args.src_corpus, f)
+ for f in os.listdir(args.src_corpus)]))
+ tgt_files = list(filter(os.path.isfile,
+ [os.path.join(args.tgt_corpus, f)
+ for f in os.listdir(args.tgt_corpus)]))
+
+ # Check if all files in src_files have a target file in tgt_files.
+ files_mismatch = (set(map(os.path.basename, src_files)) -
+ set(map(os.path.basename, tgt_files)))
+ if files_mismatch:
+ raise Error('Target files {} do not exist in corpus: {}'
+ .format(files_mismatch, args.tgt_corpus))
+
+ for src in src_files:
+ with tempfile.NamedTemporaryFile() as puffdiff_patch, \
+ tempfile.NamedTemporaryFile() as bsdiff_patch:
+
+ tgt = os.path.join(args.tgt_corpus, os.path.basename(src))
+
+ operation = 'puffdiff'
+ cmd = ['puffin',
+ '--operation={}'.format(operation),
+ '--src_file={}'.format(src),
+ '--dst_file={}'.format(tgt),
+ '--patch_file={}'.format(puffdiff_patch.name)]
+ # Running the puffdiff operation
+ if subprocess.call(cmd) != 0:
+ raise Error('Puffin failed to do {} command: {}'
+ .format(operation, cmd))
+
+ operation = 'bsdiff'
+ cmd = ['bsdiff', '--type', 'bz2', src, tgt, bsdiff_patch.name]
+ # Running the bsdiff operation
+ if subprocess.call(cmd) != 0:
+ raise Error('Failed to do {} command: {}'
+ .format(operation, cmd))
+
+ logging.debug('%s(%d -> %d) : bsdiff(%d), puffdiff(%d)',
+ os.path.basename(src),
+ os.stat(src).st_size, os.stat(tgt).st_size,
+ os.stat(bsdiff_patch.name).st_size,
+ os.stat(puffdiff_patch.name).st_size)
+
+ return 0
+
+
+if __name__ == '__main__':
+ sys.exit(main(sys.argv))
diff --git a/src/bit_io_unittest.cc b/src/bit_io_unittest.cc
index e929841..87fc3f1 100644
--- a/src/bit_io_unittest.cc
+++ b/src/bit_io_unittest.cc
@@ -8,7 +8,7 @@
#include "puffin/src/bit_reader.h"
#include "puffin/src/bit_writer.h"
-#include "puffin/src/set_errors.h"
+#include "puffin/src/logging.h"
#include "puffin/src/unittest_common.h"
namespace puffin {
diff --git a/src/bit_reader.cc b/src/bit_reader.cc
index d6f6abb..27f1d8d 100644
--- a/src/bit_reader.cc
+++ b/src/bit_reader.cc
@@ -4,7 +4,7 @@
#include "puffin/src/bit_reader.h"
-#include "puffin/src/set_errors.h"
+#include "puffin/src/logging.h"
namespace puffin {
diff --git a/src/bit_writer.cc b/src/bit_writer.cc
index 5f4fdea..66d46f2 100644
--- a/src/bit_writer.cc
+++ b/src/bit_writer.cc
@@ -6,7 +6,7 @@
#include <algorithm>
-#include "puffin/src/set_errors.h"
+#include "puffin/src/logging.h"
namespace puffin {
diff --git a/src/extent_stream.cc b/src/extent_stream.cc
index d6d6060..3622125 100644
--- a/src/extent_stream.cc
+++ b/src/extent_stream.cc
@@ -7,12 +7,12 @@
#include <algorithm>
#include <utility>
-#include "puffin/src/set_errors.h"
-
-namespace puffin {
+#include "puffin/src/logging.h"
using std::vector;
+namespace puffin {
+
UniqueStreamPtr ExtentStream::CreateForWrite(
UniqueStreamPtr stream, const vector<ByteExtent>& extents) {
return UniqueStreamPtr(new ExtentStream(std::move(stream), extents, true));
diff --git a/src/file_stream.cc b/src/file_stream.cc
index 2089078..0abde31 100644
--- a/src/file_stream.cc
+++ b/src/file_stream.cc
@@ -11,12 +11,12 @@
#include <utility>
#include "puffin/src/include/puffin/common.h"
-#include "puffin/src/set_errors.h"
-
-namespace puffin {
+#include "puffin/src/logging.h"
using std::string;
+namespace puffin {
+
UniqueStreamPtr FileStream::Open(const string& path, bool read, bool write) {
TEST_AND_RETURN_VALUE(read || write, nullptr);
int flags = O_CLOEXEC;
diff --git a/src/fuzzer.cc b/src/fuzzer.cc
index 10cf7c2..b870ac4 100644
--- a/src/fuzzer.cc
+++ b/src/fuzzer.cc
@@ -17,18 +17,32 @@
#include "puffin/src/puff_reader.h"
#include "puffin/src/puff_writer.h"
-using std::vector;
-
using puffin::BitExtent;
using puffin::Buffer;
using puffin::BufferBitReader;
using puffin::BufferBitWriter;
using puffin::BufferPuffReader;
using puffin::BufferPuffWriter;
-using puffin::Error;
+using puffin::ByteExtent;
using puffin::Huffer;
using puffin::MemoryStream;
using puffin::Puffer;
+using puffin::UniqueStreamPtr;
+using std::vector;
+
+namespace puffin {
+// From puffpatch.cc
+bool DecodePatch(const uint8_t* patch,
+ size_t patch_length,
+ size_t* bsdiff_patch_offset,
+ size_t* bsdiff_patch_size,
+ vector<BitExtent>* src_deflates,
+ vector<BitExtent>* dst_deflates,
+ vector<ByteExtent>* src_puffs,
+ vector<ByteExtent>* dst_puffs,
+ uint64_t* src_puff_size,
+ uint64_t* dst_puff_size);
+} // namespace puffin
namespace {
void FuzzPuff(const uint8_t* data, size_t size) {
@@ -36,27 +50,68 @@
Buffer puff_buffer(size * 2);
BufferPuffWriter puff_writer(puff_buffer.data(), puff_buffer.size());
vector<BitExtent> bit_extents;
- Error error;
Puffer puffer;
- puffer.PuffDeflate(&bit_reader, &puff_writer, &bit_extents, &error);
+ puffer.PuffDeflate(&bit_reader, &puff_writer, &bit_extents);
}
void FuzzHuff(const uint8_t* data, size_t size) {
BufferPuffReader puff_reader(data, size);
Buffer deflate_buffer(size);
BufferBitWriter bit_writer(deflate_buffer.data(), deflate_buffer.size());
- Error error;
Huffer huffer;
- huffer.HuffDeflate(&puff_reader, &bit_writer, &error);
+ huffer.HuffDeflate(&puff_reader, &bit_writer);
+}
+
+template <typename T>
+bool TestExtentsArrayForFuzzer(const vector<T>& extents) {
+ const size_t kMaxArraySize = 100;
+ if (extents.size() > kMaxArraySize) {
+ return false;
+ }
+
+ const size_t kMaxBufferSize = 1024; // 1Kb
+ for (const auto& ext : extents) {
+ if (ext.length > kMaxBufferSize) {
+ return false;
+ }
+ }
+ return true;
}
void FuzzPuffPatch(const uint8_t* data, size_t size) {
- const size_t kBufferSize = 1000;
- Buffer src_buffer(kBufferSize);
- Buffer dst_buffer(kBufferSize);
- auto src = MemoryStream::CreateForRead(src_buffer);
- auto dst = MemoryStream::CreateForWrite(&dst_buffer);
- puffin::PuffPatch(std::move(src), std::move(dst), data, size, kBufferSize);
+ // First decode the header and make sure the deflate and puff buffer sizes do
+ // not excede some limits. This is to prevent the fuzzer complain with
+ // out-of-memory errors when the fuzz data is in such a way that causes a huge
+ // random size memory be allocated.
+
+ size_t bsdiff_patch_offset;
+ size_t bsdiff_patch_size = 0;
+ vector<BitExtent> src_deflates, dst_deflates;
+ vector<ByteExtent> src_puffs, dst_puffs;
+ uint64_t src_puff_size, dst_puff_size;
+ if (DecodePatch(data, size, &bsdiff_patch_offset, &bsdiff_patch_size,
+ &src_deflates, &dst_deflates, &src_puffs, &dst_puffs,
+ &src_puff_size, &dst_puff_size) &&
+ TestExtentsArrayForFuzzer(src_deflates) &&
+ TestExtentsArrayForFuzzer(dst_deflates) &&
+ TestExtentsArrayForFuzzer(src_puffs) &&
+ TestExtentsArrayForFuzzer(dst_puffs)) {
+ const size_t kBufferSize = 1000;
+ if ((!src_deflates.empty() &&
+ kBufferSize <
+ src_deflates.back().offset + src_deflates.back().length) ||
+ (!dst_deflates.empty() &&
+ kBufferSize <
+ dst_deflates.back().offset + dst_deflates.back().length)) {
+ return;
+ }
+
+ Buffer src_buffer(kBufferSize);
+ Buffer dst_buffer(kBufferSize);
+ auto src = MemoryStream::CreateForRead(src_buffer);
+ auto dst = MemoryStream::CreateForWrite(&dst_buffer);
+ puffin::PuffPatch(std::move(src), std::move(dst), data, size, kBufferSize);
+ }
}
struct Environment {
diff --git a/src/huffer.cc b/src/huffer.cc
index 622c2ac..6119205 100644
--- a/src/huffer.cc
+++ b/src/huffer.cc
@@ -13,31 +13,28 @@
#include "puffin/src/huffman_table.h"
#include "puffin/src/include/puffin/common.h"
#include "puffin/src/include/puffin/stream.h"
+#include "puffin/src/logging.h"
#include "puffin/src/puff_data.h"
#include "puffin/src/puff_reader.h"
-#include "puffin/src/set_errors.h"
-
-namespace puffin {
using std::string;
+namespace puffin {
+
Huffer::Huffer() : dyn_ht_(new HuffmanTable()), fix_ht_(new HuffmanTable()) {}
Huffer::~Huffer() {}
bool Huffer::HuffDeflate(PuffReaderInterface* pr,
- BitWriterInterface* bw,
- Error* error) const {
- *error = Error::kSuccess;
+ BitWriterInterface* bw) const {
PuffData pd;
HuffmanTable* cur_ht = nullptr;
// If no bytes left for PuffReader to read, bail out.
while (pr->BytesLeft() != 0) {
- TEST_AND_RETURN_FALSE(pr->GetNext(&pd, error));
+ TEST_AND_RETURN_FALSE(pr->GetNext(&pd));
// The first data should be a metadata.
- TEST_AND_RETURN_FALSE_SET_ERROR(pd.type == PuffData::Type::kBlockMetadata,
- Error::kInvalidInput);
+ TEST_AND_RETURN_FALSE(pd.type == PuffData::Type::kBlockMetadata);
auto header = pd.block_metadata[0];
auto final_bit = (header & 0x80) >> 7;
auto type = (header & 0x60) >> 5;
@@ -45,36 +42,26 @@
DVLOG(2) << "Write block type: "
<< BlockTypeToString(static_cast<BlockType>(type));
- TEST_AND_RETURN_FALSE_SET_ERROR(bw->WriteBits(1, final_bit),
- Error::kInsufficientInput);
- TEST_AND_RETURN_FALSE_SET_ERROR(bw->WriteBits(2, type),
- Error::kInsufficientInput);
+ TEST_AND_RETURN_FALSE(bw->WriteBits(1, final_bit));
+ TEST_AND_RETURN_FALSE(bw->WriteBits(2, type));
switch (static_cast<BlockType>(type)) {
case BlockType::kUncompressed:
bw->WriteBoundaryBits(skipped_bits);
- TEST_AND_RETURN_FALSE(pr->GetNext(&pd, error));
- TEST_AND_RETURN_FALSE_SET_ERROR(pd.type != PuffData::Type::kLiteral,
- Error::kInvalidInput);
+ TEST_AND_RETURN_FALSE(pr->GetNext(&pd));
+ TEST_AND_RETURN_FALSE(pd.type != PuffData::Type::kLiteral);
if (pd.type == PuffData::Type::kLiterals) {
- TEST_AND_RETURN_FALSE_SET_ERROR(bw->WriteBits(16, pd.length),
- Error::kInsufficientOutput);
- TEST_AND_RETURN_FALSE_SET_ERROR(bw->WriteBits(16, ~pd.length),
- Error::kInsufficientOutput);
- TEST_AND_RETURN_FALSE_SET_ERROR(bw->WriteBytes(pd.length, pd.read_fn),
- Error::kInsufficientOutput);
+ TEST_AND_RETURN_FALSE(bw->WriteBits(16, pd.length));
+ TEST_AND_RETURN_FALSE(bw->WriteBits(16, ~pd.length));
+ TEST_AND_RETURN_FALSE(bw->WriteBytes(pd.length, pd.read_fn));
// Reading end of block, but don't write anything.
- TEST_AND_RETURN_FALSE(pr->GetNext(&pd, error));
- TEST_AND_RETURN_FALSE_SET_ERROR(
- pd.type == PuffData::Type::kEndOfBlock, Error::kInvalidInput);
+ TEST_AND_RETURN_FALSE(pr->GetNext(&pd));
+ TEST_AND_RETURN_FALSE(pd.type == PuffData::Type::kEndOfBlock);
} else if (pd.type == PuffData::Type::kEndOfBlock) {
- TEST_AND_RETURN_FALSE_SET_ERROR(bw->WriteBits(16, 0),
- Error::kInsufficientOutput);
- TEST_AND_RETURN_FALSE_SET_ERROR(bw->WriteBits(16, ~0),
- Error::kInsufficientOutput);
+ TEST_AND_RETURN_FALSE(bw->WriteBits(16, 0));
+ TEST_AND_RETURN_FALSE(bw->WriteBits(16, ~0));
} else {
LOG(ERROR) << "Uncompressed block did not end properly!";
- *error = Error::kInvalidInput;
return false;
}
// We have to read a new block.
@@ -88,13 +75,12 @@
case BlockType::kDynamic:
cur_ht = dyn_ht_.get();
TEST_AND_RETURN_FALSE(dyn_ht_->BuildDynamicHuffmanTable(
- &pd.block_metadata[1], pd.length - 1, bw, error));
+ &pd.block_metadata[1], pd.length - 1, bw));
break;
default:
LOG(ERROR) << "Invalid block compression type: "
<< static_cast<int>(type);
- *error = Error::kInvalidInput;
return false;
}
@@ -102,19 +88,16 @@
// stream is reached.
bool block_ended = false;
while (!block_ended) {
- TEST_AND_RETURN_FALSE(pr->GetNext(&pd, error));
+ TEST_AND_RETURN_FALSE(pr->GetNext(&pd));
switch (pd.type) {
case PuffData::Type::kLiteral:
case PuffData::Type::kLiterals: {
- auto write_literal = [&cur_ht, &bw, &error](uint8_t literal) {
+ auto write_literal = [&cur_ht, &bw](uint8_t literal) {
uint16_t literal_huffman;
size_t nbits;
- TEST_AND_RETURN_FALSE_SET_ERROR(
- cur_ht->LitLenHuffman(literal, &literal_huffman, &nbits),
- Error::kInvalidInput);
- TEST_AND_RETURN_FALSE_SET_ERROR(
- bw->WriteBits(nbits, literal_huffman),
- Error::kInsufficientOutput);
+ TEST_AND_RETURN_FALSE(
+ cur_ht->LitLenHuffman(literal, &literal_huffman, &nbits));
+ TEST_AND_RETURN_FALSE(bw->WriteBits(nbits, literal_huffman));
return true;
};
@@ -133,8 +116,7 @@
case PuffData::Type::kLenDist: {
auto len = pd.length;
auto dist = pd.distance;
- TEST_AND_RETURN_FALSE_SET_ERROR(len >= 3 && len <= 258,
- Error::kInvalidInput);
+ TEST_AND_RETURN_FALSE(len >= 3 && len <= 258);
// Using a binary search here instead of the linear search may be (but
// not necessarily) faster. Needs experiment to validate.
@@ -148,17 +130,14 @@
auto extra_bits_len = kLengthExtraBits[index];
uint16_t length_huffman;
size_t nbits;
- TEST_AND_RETURN_FALSE_SET_ERROR(
- cur_ht->LitLenHuffman(index + 257, &length_huffman, &nbits),
- Error::kInvalidInput);
+ TEST_AND_RETURN_FALSE(
+ cur_ht->LitLenHuffman(index + 257, &length_huffman, &nbits));
- TEST_AND_RETURN_FALSE_SET_ERROR(bw->WriteBits(nbits, length_huffman),
- Error::kInsufficientInput);
+ TEST_AND_RETURN_FALSE(bw->WriteBits(nbits, length_huffman));
if (extra_bits_len > 0) {
- TEST_AND_RETURN_FALSE_SET_ERROR(
- bw->WriteBits(extra_bits_len, len - kLengthBases[index]),
- Error::kInsufficientInput);
+ TEST_AND_RETURN_FALSE(
+ bw->WriteBits(extra_bits_len, len - kLengthBases[index]));
}
// Same as above (binary search).
@@ -171,17 +150,13 @@
}
extra_bits_len = kDistanceExtraBits[index];
uint16_t distance_huffman;
- TEST_AND_RETURN_FALSE_SET_ERROR(
- cur_ht->DistanceHuffman(index, &distance_huffman, &nbits),
- Error::kInvalidInput);
+ TEST_AND_RETURN_FALSE(
+ cur_ht->DistanceHuffman(index, &distance_huffman, &nbits));
- TEST_AND_RETURN_FALSE_SET_ERROR(
- bw->WriteBits(nbits, distance_huffman),
- Error::kInsufficientInput);
+ TEST_AND_RETURN_FALSE(bw->WriteBits(nbits, distance_huffman));
if (extra_bits_len > 0) {
- TEST_AND_RETURN_FALSE_SET_ERROR(
- bw->WriteBits(extra_bits_len, dist - kDistanceBases[index]),
- Error::kInsufficientInput);
+ TEST_AND_RETURN_FALSE(
+ bw->WriteBits(extra_bits_len, dist - kDistanceBases[index]));
}
break;
}
@@ -189,28 +164,24 @@
case PuffData::Type::kEndOfBlock: {
uint16_t eos_huffman;
size_t nbits;
- TEST_AND_RETURN_FALSE_SET_ERROR(
- cur_ht->LitLenHuffman(256, &eos_huffman, &nbits),
- Error::kInvalidInput);
- TEST_AND_RETURN_FALSE_SET_ERROR(bw->WriteBits(nbits, eos_huffman),
- Error::kInsufficientInput);
+ TEST_AND_RETURN_FALSE(
+ cur_ht->LitLenHuffman(256, &eos_huffman, &nbits));
+ TEST_AND_RETURN_FALSE(bw->WriteBits(nbits, eos_huffman));
block_ended = true;
break;
}
case PuffData::Type::kBlockMetadata:
LOG(ERROR) << "Not expecing a metadata!";
- *error = Error::kInvalidInput;
return false;
default:
LOG(ERROR) << "Invalid block data type!";
- *error = Error::kInvalidInput;
return false;
}
}
}
- TEST_AND_RETURN_FALSE_SET_ERROR(bw->Flush(), Error::kInsufficientOutput);
+ TEST_AND_RETURN_FALSE(bw->Flush());
return true;
}
diff --git a/src/huffman_table.cc b/src/huffman_table.cc
index 6e711c6..1aeaa45 100644
--- a/src/huffman_table.cc
+++ b/src/huffman_table.cc
@@ -7,40 +7,38 @@
#include <algorithm>
#include <vector>
-#include "puffin/src/include/puffin/errors.h"
-#include "puffin/src/set_errors.h"
+#include "puffin/src/logging.h"
namespace puffin {
-// clang-format off
// Permutations of input Huffman code lengths (used only to read code lengths
// necessary for reading Huffman table.)
-const uint8_t kPermutations[19] = {
- 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
+const uint8_t kPermutations[19] = {16, 17, 18, 0, 8, 7, 9, 6, 10, 5,
+ 11, 4, 12, 3, 13, 2, 14, 1, 15};
// The bases of each alphabet which is added to the integer value of extra
// bits that comes after the Huffman code in the input to create the given
// length value. The last element is a guard.
const uint16_t kLengthBases[30] = {
- 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, 35, 43,
- 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0xFFFF};
+ 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27,
+ 31, 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0xFFFF};
// Number of extra bits that comes after the associating Huffman code.
-const uint8_t kLengthExtraBits[29] = {
- 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5,
- 5, 5, 0};
+const uint8_t kLengthExtraBits[29] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 1,
+ 1, 1, 2, 2, 2, 2, 3, 3, 3, 3,
+ 4, 4, 4, 4, 5, 5, 5, 5, 0};
// Same as |kLengthBases| but for the distances instead of lengths. The last
// element is a guard.
const uint16_t kDistanceBases[31] = {
- 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, 257, 385, 513, 769,
- 1025, 1537, 2049, 3073, 4097, 6145, 8193, 12289, 16385, 24577, 0xFFFF};
+ 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33,
+ 49, 65, 97, 129, 193, 257, 385, 513, 769, 1025, 1537,
+ 2049, 3073, 4097, 6145, 8193, 12289, 16385, 24577, 0xFFFF};
// Same as |kLengthExtraBits| but for distances instead of lengths.
-const uint8_t kDistanceExtraBits[30] = {
- 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9,
- 9, 10, 10, 11, 11, 12, 12, 13, 13};
-// clang-format on
+const uint8_t kDistanceExtraBits[30] = {0, 0, 0, 0, 1, 1, 2, 2, 3, 3,
+ 4, 4, 5, 5, 6, 6, 7, 7, 8, 8,
+ 9, 9, 10, 10, 11, 11, 12, 12, 13, 13};
// 288 is the maximum number of needed huffman codes for an alphabet. Fixed
// huffman table needs 288 and dynamic huffman table needs maximum 286.
@@ -111,8 +109,7 @@
size_t* max_bits) {
TEST_AND_RETURN_FALSE(InitHuffmanCodes(lens, max_bits));
// Sort descending based on the bit-length of the code.
- std::sort(codeindexpairs_.begin(),
- codeindexpairs_.end(),
+ std::sort(codeindexpairs_.begin(), codeindexpairs_.end(),
[&lens](const CodeIndexPair& a, const CodeIndexPair& b) {
return lens[a.index] > lens[b.index];
});
@@ -139,8 +136,7 @@
size_t* max_bits) {
TEST_AND_RETURN_FALSE(InitHuffmanCodes(lens, max_bits));
// Sort ascending based on the index.
- std::sort(codeindexpairs_.begin(),
- codeindexpairs_.end(),
+ std::sort(codeindexpairs_.begin(), codeindexpairs_.end(),
[](const CodeIndexPair& a, const CodeIndexPair& b) -> bool {
return a.index < b.index;
});
@@ -193,8 +189,8 @@
TEST_AND_RETURN_FALSE(
BuildHuffmanCodes(lit_len_lens_, &lit_len_hcodes_, &lit_len_max_bits_));
- TEST_AND_RETURN_FALSE(BuildHuffmanCodes(
- distance_lens_, &distance_hcodes_, &distance_max_bits_));
+ TEST_AND_RETURN_FALSE(BuildHuffmanCodes(distance_lens_, &distance_hcodes_,
+ &distance_max_bits_));
TEST_AND_RETURN_FALSE(BuildHuffmanReverseCodes(
lit_len_lens_, &lit_len_rcodes_, &lit_len_max_bits_));
@@ -209,8 +205,7 @@
bool HuffmanTable::BuildDynamicHuffmanTable(BitReaderInterface* br,
uint8_t* buffer,
- size_t* length,
- Error* error) {
+ size_t* length) {
// Initilize only once and reuse.
if (!initialized_) {
// Only resizing the arrays needed.
@@ -240,9 +235,9 @@
// |dynamic_lit_len_lens_| and |dynamic_distance_lens_|. Then it follows by
// reading |dynamic_code_lens_|.
- TEST_AND_RETURN_FALSE_SET_ERROR(*length >= 3, Error::kInsufficientOutput);
+ TEST_AND_RETURN_FALSE(*length >= 3);
size_t index = 0;
- TEST_AND_RETURN_FALSE_SET_ERROR(br->CacheBits(14), Error::kInsufficientInput);
+ TEST_AND_RETURN_FALSE(br->CacheBits(14));
buffer[index++] = br->ReadBits(5); // HLIST
auto num_lit_len = br->ReadBits(5) + 257;
br->DropBits(5);
@@ -255,18 +250,15 @@
auto num_codes = br->ReadBits(4) + 4;
br->DropBits(4);
- TEST_AND_RETURN_FALSE_SET_ERROR(
- CheckHuffmanArrayLengths(num_lit_len, num_distance, num_codes),
- Error::kInvalidInput);
+ TEST_AND_RETURN_FALSE(
+ CheckHuffmanArrayLengths(num_lit_len, num_distance, num_codes));
bool checked = false;
size_t idx = 0;
- TEST_AND_RETURN_FALSE_SET_ERROR(*length - index >= (num_codes + 1) / 2,
- Error::kInsufficientOutput);
+ TEST_AND_RETURN_FALSE(*length - index >= (num_codes + 1) / 2);
// Two codes per byte
for (; idx < num_codes; idx++) {
- TEST_AND_RETURN_FALSE_SET_ERROR(br->CacheBits(3),
- Error::kInsufficientInput);
+ TEST_AND_RETURN_FALSE(br->CacheBits(3));
code_lens_[kPermutations[idx]] = br->ReadBits(3);
if (checked) {
buffer[index++] |= br->ReadBits(3);
@@ -284,16 +276,15 @@
code_lens_[kPermutations[idx]] = 0;
}
- TEST_AND_RETURN_FALSE_SET_ERROR(
- BuildHuffmanCodes(code_lens_, &code_hcodes_, &code_max_bits_),
- Error::kInvalidInput);
+ TEST_AND_RETURN_FALSE(
+ BuildHuffmanCodes(code_lens_, &code_hcodes_, &code_max_bits_));
// Build literals/lengths and distance Huffman code length arrays.
auto bytes_available = (*length - index);
tmp_lens_.clear();
TEST_AND_RETURN_FALSE(BuildHuffmanCodeLengths(
br, buffer + index, &bytes_available, code_max_bits_,
- num_lit_len + num_distance, &tmp_lens_, error));
+ num_lit_len + num_distance, &tmp_lens_));
index += bytes_available;
// TODO(ahassani): Optimize this so the memcpy is not needed anymore.
@@ -305,14 +296,12 @@
distance_lens_.insert(distance_lens_.begin(), tmp_lens_.begin() + num_lit_len,
tmp_lens_.end());
- TEST_AND_RETURN_FALSE_SET_ERROR(
- BuildHuffmanCodes(lit_len_lens_, &lit_len_hcodes_, &lit_len_max_bits_),
- Error::kInvalidInput);
+ TEST_AND_RETURN_FALSE(
+ BuildHuffmanCodes(lit_len_lens_, &lit_len_hcodes_, &lit_len_max_bits_));
// Build distance Huffman codes.
- TEST_AND_RETURN_FALSE_SET_ERROR(
- BuildHuffmanCodes(distance_lens_, &distance_hcodes_, &distance_max_bits_),
- Error::kInvalidInput);
+ TEST_AND_RETURN_FALSE(BuildHuffmanCodes(distance_lens_, &distance_hcodes_,
+ &distance_max_bits_));
*length = index;
return true;
@@ -323,34 +312,29 @@
size_t* length,
size_t max_bits,
size_t num_codes,
- Buffer* lens,
- Error* error) {
+ Buffer* lens) {
size_t index = 0;
lens->clear();
for (size_t idx = 0; idx < num_codes;) {
- TEST_AND_RETURN_FALSE_SET_ERROR(br->CacheBits(max_bits),
- Error::kInsufficientInput);
+ TEST_AND_RETURN_FALSE(br->CacheBits(max_bits));
auto bits = br->ReadBits(max_bits);
uint16_t code;
size_t nbits;
- TEST_AND_RETURN_FALSE_SET_ERROR(CodeAlphabet(bits, &code, &nbits),
- Error::kInvalidInput);
- TEST_AND_RETURN_FALSE_SET_ERROR(index < *length,
- Error::kInsufficientOutput);
+ TEST_AND_RETURN_FALSE(CodeAlphabet(bits, &code, &nbits));
+ TEST_AND_RETURN_FALSE(index < *length);
br->DropBits(nbits);
if (code < 16) {
buffer[index++] = code;
lens->push_back(code);
idx++;
} else {
- TEST_AND_RETURN_FALSE_SET_ERROR(code < 19, Error::kInvalidInput);
+ TEST_AND_RETURN_FALSE(code < 19);
size_t copy_num = 0;
uint8_t copy_val;
switch (code) {
case 16:
- TEST_AND_RETURN_FALSE_SET_ERROR(idx != 0, Error::kInvalidInput);
- TEST_AND_RETURN_FALSE_SET_ERROR(br->CacheBits(2),
- Error::kInsufficientInput);
+ TEST_AND_RETURN_FALSE(idx != 0);
+ TEST_AND_RETURN_FALSE(br->CacheBits(2));
copy_num = 3 + br->ReadBits(2);
buffer[index++] = 16 + br->ReadBits(2); // 3 - 6 times
copy_val = (*lens)[idx - 1];
@@ -358,8 +342,7 @@
break;
case 17:
- TEST_AND_RETURN_FALSE_SET_ERROR(br->CacheBits(3),
- Error::kInsufficientInput);
+ TEST_AND_RETURN_FALSE(br->CacheBits(3));
copy_num = 3 + br->ReadBits(3);
buffer[index++] = 20 + br->ReadBits(3); // 3 - 10 times
copy_val = 0;
@@ -367,8 +350,7 @@
break;
case 18:
- TEST_AND_RETURN_FALSE_SET_ERROR(br->CacheBits(7),
- Error::kInsufficientInput);
+ TEST_AND_RETURN_FALSE(br->CacheBits(7));
copy_num = 11 + br->ReadBits(7);
buffer[index++] = 28 + br->ReadBits(7); // 11 - 138 times
copy_val = 0;
@@ -377,9 +359,7 @@
default:
LOG(ERROR) << "Invalid code!";
- *error = Error::kInvalidInput;
return false;
- break;
}
idx += copy_num;
while (copy_num--) {
@@ -394,8 +374,7 @@
bool HuffmanTable::BuildDynamicHuffmanTable(const uint8_t* buffer,
size_t length,
- BitWriterInterface* bw,
- Error* error) {
+ BitWriterInterface* bw) {
if (!initialized_) {
// Only resizing the arrays needed.
code_lens_.resize(19);
@@ -412,27 +391,22 @@
initialized_ = true;
}
- TEST_AND_RETURN_FALSE_SET_ERROR(length >= 3, Error::kInsufficientInput);
+ TEST_AND_RETURN_FALSE(length >= 3);
size_t index = 0;
// Write the header.
size_t num_lit_len = buffer[index] + 257;
- TEST_AND_RETURN_FALSE_SET_ERROR(bw->WriteBits(5, buffer[index++]),
- Error::kInsufficientOutput);
+ TEST_AND_RETURN_FALSE(bw->WriteBits(5, buffer[index++]));
size_t num_distance = buffer[index] + 1;
- TEST_AND_RETURN_FALSE_SET_ERROR(bw->WriteBits(5, buffer[index++]),
- Error::kInsufficientOutput);
+ TEST_AND_RETURN_FALSE(bw->WriteBits(5, buffer[index++]));
size_t num_codes = buffer[index] + 4;
- TEST_AND_RETURN_FALSE_SET_ERROR(bw->WriteBits(4, buffer[index++]),
- Error::kInsufficientOutput);
+ TEST_AND_RETURN_FALSE(bw->WriteBits(4, buffer[index++]));
- TEST_AND_RETURN_FALSE_SET_ERROR(
- CheckHuffmanArrayLengths(num_lit_len, num_distance, num_codes),
- Error::kInvalidInput);
+ TEST_AND_RETURN_FALSE(
+ CheckHuffmanArrayLengths(num_lit_len, num_distance, num_codes));
- TEST_AND_RETURN_FALSE_SET_ERROR(length - index >= (num_codes + 1) / 2,
- Error::kInsufficientInput);
+ TEST_AND_RETURN_FALSE(length - index >= (num_codes + 1) / 2);
bool checked = false;
size_t idx = 0;
for (; idx < num_codes; idx++) {
@@ -444,8 +418,7 @@
}
checked = !checked;
code_lens_[kPermutations[idx]] = len;
- TEST_AND_RETURN_FALSE_SET_ERROR(bw->WriteBits(3, len),
- Error::kInsufficientOutput);
+ TEST_AND_RETURN_FALSE(bw->WriteBits(3, len));
}
if (checked) {
index++;
@@ -454,15 +427,14 @@
code_lens_[kPermutations[idx]] = 0;
}
- TEST_AND_RETURN_FALSE_SET_ERROR(
- BuildHuffmanReverseCodes(code_lens_, &code_rcodes_, &code_max_bits_),
- Error::kInvalidInput);
+ TEST_AND_RETURN_FALSE(
+ BuildHuffmanReverseCodes(code_lens_, &code_rcodes_, &code_max_bits_));
// Build literal/lengths and distance Huffman code length arrays.
auto bytes_available = length - index;
TEST_AND_RETURN_FALSE(
BuildHuffmanCodeLengths(buffer + index, &bytes_available, bw,
- num_lit_len + num_distance, &tmp_lens_, error));
+ num_lit_len + num_distance, &tmp_lens_));
index += bytes_available;
lit_len_lens_.clear();
@@ -474,18 +446,14 @@
tmp_lens_.end());
// Build literal/lengths Huffman reverse codes.
- TEST_AND_RETURN_FALSE_SET_ERROR(
- BuildHuffmanReverseCodes(
- lit_len_lens_, &lit_len_rcodes_, &lit_len_max_bits_),
- Error::kInvalidInput);
+ TEST_AND_RETURN_FALSE(BuildHuffmanReverseCodes(
+ lit_len_lens_, &lit_len_rcodes_, &lit_len_max_bits_));
// Build distance Huffman reverse codes.
- TEST_AND_RETURN_FALSE_SET_ERROR(
- BuildHuffmanReverseCodes(
- distance_lens_, &distance_rcodes_, &distance_max_bits_),
- Error::kInvalidInput);
+ TEST_AND_RETURN_FALSE(BuildHuffmanReverseCodes(
+ distance_lens_, &distance_rcodes_, &distance_max_bits_));
- TEST_AND_RETURN_FALSE_SET_ERROR(length == index, Error::kInvalidInput);
+ TEST_AND_RETURN_FALSE(length == index);
return true;
}
@@ -494,22 +462,19 @@
size_t* length,
BitWriterInterface* bw,
size_t num_codes,
- Buffer* lens,
- Error* error) {
+ Buffer* lens) {
lens->clear();
uint16_t hcode;
size_t nbits;
size_t index = 0;
for (size_t idx = 0; idx < num_codes;) {
- TEST_AND_RETURN_FALSE_SET_ERROR(index < *length, Error::kInsufficientInput);
+ TEST_AND_RETURN_FALSE(index < *length);
auto pcode = buffer[index++];
- TEST_AND_RETURN_FALSE_SET_ERROR(pcode <= 155, Error::kInvalidInput);
+ TEST_AND_RETURN_FALSE(pcode <= 155);
auto code = pcode < 16 ? pcode : pcode < 20 ? 16 : pcode < 28 ? 17 : 18;
- TEST_AND_RETURN_FALSE_SET_ERROR(CodeHuffman(code, &hcode, &nbits),
- Error::kInvalidInput);
- TEST_AND_RETURN_FALSE_SET_ERROR(bw->WriteBits(nbits, hcode),
- Error::kInsufficientOutput);
+ TEST_AND_RETURN_FALSE(CodeHuffman(code, &hcode, &nbits));
+ TEST_AND_RETURN_FALSE(bw->WriteBits(nbits, hcode));
if (code < 16) {
lens->push_back(code);
idx++;
@@ -519,23 +484,20 @@
switch (code) {
case 16:
// Cannot repeat a non-existent last code if idx == 0.
- TEST_AND_RETURN_FALSE_SET_ERROR(idx != 0, Error::kInvalidInput);
- TEST_AND_RETURN_FALSE_SET_ERROR(bw->WriteBits(2, pcode - 16),
- Error::kInsufficientOutput);
+ TEST_AND_RETURN_FALSE(idx != 0);
+ TEST_AND_RETURN_FALSE(bw->WriteBits(2, pcode - 16));
copy_num = 3 + pcode - 16;
copy_val = (*lens)[idx - 1];
break;
case 17:
- TEST_AND_RETURN_FALSE_SET_ERROR(bw->WriteBits(3, pcode - 20),
- Error::kInsufficientOutput);
+ TEST_AND_RETURN_FALSE(bw->WriteBits(3, pcode - 20));
copy_num = 3 + pcode - 20;
copy_val = 0;
break;
case 18:
- TEST_AND_RETURN_FALSE_SET_ERROR(bw->WriteBits(7, pcode - 28),
- Error::kInsufficientOutput);
+ TEST_AND_RETURN_FALSE(bw->WriteBits(7, pcode - 28));
copy_num = 11 + pcode - 28;
copy_val = 0;
break;
diff --git a/src/huffman_table.h b/src/huffman_table.h
index b12e88b..e47f8cc 100644
--- a/src/huffman_table.h
+++ b/src/huffman_table.h
@@ -13,8 +13,7 @@
#include "puffin/src/bit_reader.h"
#include "puffin/src/bit_writer.h"
#include "puffin/src/include/puffin/common.h"
-#include "puffin/src/include/puffin/errors.h"
-#include "puffin/src/set_errors.h"
+#include "puffin/src/logging.h"
namespace puffin {
@@ -183,8 +182,7 @@
// the |buffer|.
bool BuildDynamicHuffmanTable(BitReaderInterface* br,
uint8_t* buffer,
- size_t* length,
- Error* error);
+ size_t* length);
// This functions first reads the Huffman code length arrays from the input
// puffed |buffer|, then builds both literal/length and distance Huffman code
@@ -195,11 +193,9 @@
// |length| IN The length available in the |buffer|.
// |bw| IN/OUT The |BitWriterInterface| for writing into the deflate
// stream.
- // |error| OUT The error code.
bool BuildDynamicHuffmanTable(const uint8_t* buffer,
size_t length,
- BitWriterInterface* bw,
- Error* error);
+ BitWriterInterface* bw);
protected:
// Initializes the Huffman codes from an array of lengths.
@@ -236,14 +232,12 @@
// |max_bits| IN The maximum number of bits in the Huffman codes.
// |num_codes| IN The size of the Huffman code length array in the input.
// |lens| OUT The resulting Huffman code length array.
- // |error| OUT The error code.
bool BuildHuffmanCodeLengths(BitReaderInterface* br,
uint8_t* buffer,
size_t* length,
size_t max_bits,
size_t num_codes,
- Buffer* lens,
- Error* error);
+ Buffer* lens);
// Similar to |BuildHuffmanCodeLengths| but for reading from puffed buffer and
// writing into deflate stream.
@@ -255,13 +249,11 @@
// |num_codes| IN Number of Huffman code lengths to read from the
// |buffer|.
// |lens| OUT The Huffman code lengths array.
- // |error| OUT The error code.
bool BuildHuffmanCodeLengths(const uint8_t* buffer,
size_t* length,
BitWriterInterface* bw,
size_t num_codes,
- Buffer* lens,
- Error* error);
+ Buffer* lens);
private:
// A utility struct used to create Huffman codes.
diff --git a/src/include/puffin/common.h b/src/include/puffin/common.h
index 527686f..4ead74d 100644
--- a/src/include/puffin/common.h
+++ b/src/include/puffin/common.h
@@ -28,6 +28,14 @@
#endif // USE_BRILLO
+#ifndef FALLTHROUGH_INTENDED
+#ifdef __clang__
+#define FALLTHROUGH_INTENDED [[clang::fallthrough]]
+#else
+#define FALLTHROUGH_INTENDED
+#endif // __clang__
+#endif // FALLTHROUGH_INTENDED
+
namespace puffin {
using Buffer = std::vector<uint8_t>;
diff --git a/src/include/puffin/errors.h b/src/include/puffin/errors.h
deleted file mode 100644
index 66a312f..0000000
--- a/src/include/puffin/errors.h
+++ /dev/null
@@ -1,21 +0,0 @@
-// Copyright 2017 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef SRC_INCLUDE_PUFFIN_ERRORS_H_
-#define SRC_INCLUDE_PUFFIN_ERRORS_H_
-
-namespace puffin {
-
-// The types of the errors.
-enum class Error {
- kSuccess = 0,
- kInvalidInput,
- kInsufficientInput,
- kInsufficientOutput,
- kStreamIO,
-};
-
-} // namespace puffin
-
-#endif // SRC_INCLUDE_PUFFIN_ERRORS_H_
diff --git a/src/include/puffin/huffer.h b/src/include/puffin/huffer.h
index f1da650..4e6e42f 100644
--- a/src/include/puffin/huffer.h
+++ b/src/include/puffin/huffer.h
@@ -9,7 +9,6 @@
#include <memory>
#include "puffin/common.h"
-#include "puffin/errors.h"
namespace puffin {
@@ -24,9 +23,7 @@
// Creates a deflate buffer from a puffed buffer. It is the reverse of
// |PuffDeflate|.
- bool HuffDeflate(PuffReaderInterface* pr,
- BitWriterInterface* bw,
- Error* error) const;
+ bool HuffDeflate(PuffReaderInterface* pr, BitWriterInterface* bw) const;
private:
std::unique_ptr<HuffmanTable> dyn_ht_;
diff --git a/src/include/puffin/puffdiff.h b/src/include/puffin/puffdiff.h
index 3836d03..434dac7 100644
--- a/src/include/puffin/puffdiff.h
+++ b/src/include/puffin/puffdiff.h
@@ -8,6 +8,8 @@
#include <string>
#include <vector>
+#include "bsdiff/constants.h"
+
#include "puffin/common.h"
#include "puffin/stream.h"
@@ -19,6 +21,8 @@
// |dst| IN Destination deflate stream.
// |src_deflates| IN Deflate locations in |src|.
// |dst_deflates| IN Deflate locations in |dst|.
+// |compressors| IN Compressors to use in the underlying bsdiff, e.g. bz2,
+// brotli.
// |tmp_filepath| IN A path to a temporary file. The caller has the
// responsibility of unlinking the file after the call to
// |PuffDiff| finishes.
@@ -27,11 +31,22 @@
UniqueStreamPtr dst,
const std::vector<BitExtent>& src_deflates,
const std::vector<BitExtent>& dst_deflates,
+ const std::vector<bsdiff::CompressorType>& compressors,
const std::string& tmp_filepath,
Buffer* patch);
// Similar to the function above, except that it accepts raw buffer rather than
// stream.
+bool PuffDiff(const Buffer& src,
+ const Buffer& dst,
+ const std::vector<BitExtent>& src_deflates,
+ const std::vector<BitExtent>& dst_deflates,
+ const std::vector<bsdiff::CompressorType>& compressors,
+ const std::string& tmp_filepath,
+ Buffer* patch);
+
+// The default puffdiff function that uses both bz2 and brotli to compress the
+// patch data.
PUFFIN_EXPORT
bool PuffDiff(const Buffer& src,
const Buffer& dst,
diff --git a/src/include/puffin/puffer.h b/src/include/puffin/puffer.h
index 8469abc..b9ff6bc 100644
--- a/src/include/puffin/puffer.h
+++ b/src/include/puffin/puffer.h
@@ -9,7 +9,6 @@
#include <vector>
#include "puffin/common.h"
-#include "puffin/errors.h"
#include "puffin/stream.h"
namespace puffin {
@@ -23,12 +22,18 @@
Puffer();
~Puffer();
- // Creates a puffed buffer from a deflate buffer. If |deflates| is not null,
- // it will be populated with the location of subblocks in the input data.
+ // Creates a puffed buffer from a deflate buffer.
+ //
+ // If |deflates| is not null, it will be populated with the location of the
+ // subblocks in the input data. In addition, the uncompressed deflate blocks
+ // will be ignored and will not be added to the |deflates|. For this case to
+ // happen correctly, the |pw| should write into an empty/null buffer,
+ // otherwise the created puff stream, will not match the deflate stream. In
+ // addition, in this case, the function will return when it reaches a final
+ // deflate subblock.
bool PuffDeflate(BitReaderInterface* br,
PuffWriterInterface* pw,
- std::vector<BitExtent>* deflates,
- Error* error) const;
+ std::vector<BitExtent>* deflates) const;
private:
std::unique_ptr<HuffmanTable> dyn_ht_;
diff --git a/src/include/puffin/utils.h b/src/include/puffin/utils.h
index 4c81996..f8eddbb 100644
--- a/src/include/puffin/utils.h
+++ b/src/include/puffin/utils.h
@@ -13,10 +13,6 @@
namespace puffin {
-// Counts the number of bytes in a list of |ByteExtent|s.
-PUFFIN_EXPORT
-uint64_t BytesInByteExtents(const std::vector<ByteExtent>& extents);
-
// Converts an array of |ByteExtens| or |BitExtents| to a string. Each extent
// has format "offset:length" and are comma separated.
template <typename T>
@@ -29,32 +25,45 @@
return str;
}
-// Locates deflate locations for a zlib buffer |data|. It locates by removing
-// header and footer bytes from the zlib stream.
-bool LocateDeflatesInZlib(const Buffer& data,
- std::vector<ByteExtent>* deflate_blocks);
+// Locates deflates in a deflate stream |data| with estimated minimum length of
+// |size|. The data should start with a valid deflate stream otherwise, false is
+// returned. |virtual_offset| defines the offset the |data| starts in the
+// original deflate stream. It is used to calculate the location of deflates in
+// |deflates| based on the given offset. |compressed_size| is the size of the
+// input that was determined to have valid deflate blocks (including
+// uncompressed blocks). This function does not clear the content of |deflates|
+// and will append found deflates to the end of it.
+bool LocateDeflatesInDeflateStream(const uint8_t* data,
+ uint64_t size,
+ uint64_t virtual_offset,
+ std::vector<BitExtent>* deflates,
+ uint64_t* compressed_size);
-// Similar to the function above, except that it accepts the file path to the
-// source and a list of zlib blocks and returns the deflate addresses in bit
-// extents.
+// Locates deflates in a zlib buffer |data| by removing header and footer bytes
+// from the zlib stream.
+bool LocateDeflatesInZlib(const Buffer& data, std::vector<BitExtent>* deflates);
+
+// Uses the function above, to locate deflates (bit addressed) in a given file
+// |file_path| using the list of zlib blocks |zlibs|.
PUFFIN_EXPORT
bool LocateDeflatesInZlibBlocks(const std::string& file_path,
const std::vector<ByteExtent>& zlibs,
std::vector<BitExtent>* deflates);
-// Searches for deflate locations in a gzip file. The results are
-// saved in |deflate_blocks|.
-bool LocateDeflatesInGzip(const Buffer& data,
- std::vector<ByteExtent>* deflate_blocks);
+// Searches for deflate locations in a gzip stream. The results are saved in
+// |deflates|.
+bool LocateDeflatesInGzip(const Buffer& data, std::vector<BitExtent>* deflates);
-// Search for the deflates in a zip archive, and put the result in
-// |deflate_blocks|.
-bool LocateDeflatesInZipArchive(const Buffer& data,
- std::vector<ByteExtent>* deflate_blocks);
-
+// Search for the deflates in a zip archive, and put the result in |deflates|.
PUFFIN_EXPORT
+bool LocateDeflatesInZipArchive(const Buffer& data,
+ std::vector<BitExtent>* deflates);
+
// Create a list of deflate subblock locations from the deflate blocks in a
// zip archive.
+// TODO(ahassani): Remove this function once update_engine starts to use
+// LocateDeflatesInZipArchive()
+PUFFIN_EXPORT
bool LocateDeflateSubBlocksInZipArchive(const Buffer& data,
std::vector<BitExtent>* deflates);
@@ -74,6 +83,15 @@
std::vector<ByteExtent>* puffs,
uint64_t* out_puff_size);
+// Removes any BitExtents from both |extents1| and |extents2| if the data it
+// points to is found in both |extents1| and |extents2|. The order of the
+// remaining BitExtents is preserved.
+PUFFIN_EXPORT
+void RemoveEqualBitExtents(const Buffer& data1,
+ const Buffer& data2,
+ std::vector<BitExtent>* extents1,
+ std::vector<BitExtent>* extents2);
+
} // namespace puffin
#endif // SRC_INCLUDE_PUFFIN_UTILS_H_
diff --git a/src/logging.h b/src/logging.h
new file mode 100644
index 0000000..b48fcd5
--- /dev/null
+++ b/src/logging.h
@@ -0,0 +1,30 @@
+// Copyright 2017 The Chromium OS Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef SRC_LOGGING_H_
+#define SRC_LOGGING_H_
+
+#ifdef USE_BRILLO
+#include "base/logging.h"
+#else
+#include "glog/logging.h"
+#endif
+
+#define TEST_AND_RETURN_FALSE(_x) \
+ do { \
+ if (!(_x)) { \
+ LOG(ERROR) << #_x " failed."; \
+ return false; \
+ } \
+ } while (0)
+
+#define TEST_AND_RETURN_VALUE(_x, _v) \
+ do { \
+ if (!(_x)) { \
+ LOG(ERROR) << #_x " failed."; \
+ return (_v); \
+ } \
+ } while (0)
+
+#endif // SRC_LOGGING_H_
diff --git a/src/main.cc b/src/main.cc
index c610764..12f823f 100644
--- a/src/main.cc
+++ b/src/main.cc
@@ -21,14 +21,13 @@
#include "puffin/src/include/puffin/puffer.h"
#include "puffin/src/include/puffin/puffpatch.h"
#include "puffin/src/include/puffin/utils.h"
+#include "puffin/src/logging.h"
#include "puffin/src/memory_stream.h"
#include "puffin/src/puffin_stream.h"
-#include "puffin/src/set_errors.h"
using puffin::BitExtent;
using puffin::Buffer;
using puffin::ByteExtent;
-using puffin::Error;
using puffin::ExtentStream;
using puffin::FileStream;
using puffin::Huffer;
@@ -92,7 +91,7 @@
bool LocateDeflatesBasedOnFileType(const UniqueStreamPtr& stream,
const string& file_name,
const string& file_type_to_override,
- vector<ByteExtent>* deflates) {
+ vector<BitExtent>* deflates) {
auto file_type = FileType::kUnknown;
auto last_dot = file_name.find_last_of(".");
@@ -125,15 +124,13 @@
uint64_t stream_size;
TEST_AND_RETURN_FALSE(stream->GetSize(&stream_size));
- if (file_type == FileType::kDeflate) {
- // Assume the whole stream is a deflate block.
- *deflates = {ByteExtent(0, stream_size)};
- return true;
- }
-
Buffer data(stream_size);
TEST_AND_RETURN_FALSE(stream->Read(data.data(), data.size()));
switch (file_type) {
+ case FileType::kDeflate:
+ TEST_AND_RETURN_FALSE(puffin::LocateDeflatesInDeflateStream(
+ data.data(), data.size(), 0, deflates, nullptr));
+ break;
case FileType::kZlib:
TEST_AND_RETURN_FALSE(puffin::LocateDeflatesInZlib(data, deflates));
break;
@@ -199,7 +196,7 @@
#endif
// Main entry point to the application.
-int main(int argc, char** argv) {
+bool Main(int argc, char** argv) {
#ifdef USE_BRILLO
SETUP_FLAGS;
brillo::FlagHelper::Init(argc, argv, "Puffin tool");
@@ -208,9 +205,9 @@
google::ParseCommandLineFlags(&argc, &argv, true);
#endif
- TEST_AND_RETURN_VALUE(!FLAGS_operation.empty(), -1);
- TEST_AND_RETURN_VALUE(!FLAGS_src_file.empty(), -1);
- TEST_AND_RETURN_VALUE(!FLAGS_dst_file.empty(), -1);
+ TEST_AND_RETURN_FALSE(!FLAGS_operation.empty());
+ TEST_AND_RETURN_FALSE(!FLAGS_src_file.empty());
+ TEST_AND_RETURN_FALSE(!FLAGS_dst_file.empty());
auto src_deflates_byte = StringToExtents<ByteExtent>(FLAGS_src_deflates_byte);
auto dst_deflates_byte = StringToExtents<ByteExtent>(FLAGS_dst_deflates_byte);
@@ -222,35 +219,31 @@
auto dst_extents = StringToExtents<ByteExtent>(FLAGS_dst_extents);
auto src_stream = FileStream::Open(FLAGS_src_file, true, false);
- TEST_AND_RETURN_VALUE(src_stream, -1);
+ TEST_AND_RETURN_FALSE(src_stream);
if (!src_extents.empty()) {
src_stream =
ExtentStream::CreateForRead(std::move(src_stream), src_extents);
- TEST_AND_RETURN_VALUE(src_stream, -1);
+ TEST_AND_RETURN_FALSE(src_stream);
}
if (FLAGS_operation == "puff" || FLAGS_operation == "puffhuff") {
- TEST_AND_RETURN_VALUE(
- LocateDeflatesBasedOnFileType(src_stream, FLAGS_src_file,
- FLAGS_src_file_type, &src_deflates_byte),
- -1);
+ TEST_AND_RETURN_FALSE(LocateDeflatesBasedOnFileType(
+ src_stream, FLAGS_src_file, FLAGS_src_file_type, &src_deflates_bit));
if (src_deflates_bit.empty() && src_deflates_byte.empty()) {
LOG(WARNING) << "You should pass source deflates, is this intentional?";
}
if (src_deflates_bit.empty()) {
- TEST_AND_RETURN_VALUE(FindDeflateSubBlocks(src_stream, src_deflates_byte,
- &src_deflates_bit),
- -1);
+ TEST_AND_RETURN_FALSE(FindDeflateSubBlocks(src_stream, src_deflates_byte,
+ &src_deflates_bit));
}
- TEST_AND_RETURN_VALUE(dst_puffs.empty(), -1);
+ TEST_AND_RETURN_FALSE(dst_puffs.empty());
uint64_t dst_puff_size;
- TEST_AND_RETURN_VALUE(FindPuffLocations(src_stream, src_deflates_bit,
- &dst_puffs, &dst_puff_size),
- -1);
+ TEST_AND_RETURN_FALSE(FindPuffLocations(src_stream, src_deflates_bit,
+ &dst_puffs, &dst_puff_size));
auto dst_stream = FileStream::Open(FLAGS_dst_file, false, true);
- TEST_AND_RETURN_VALUE(dst_stream, -1);
+ TEST_AND_RETURN_FALSE(dst_stream);
auto puffer = std::make_shared<Puffer>();
auto reader =
PuffinStream::CreateForPuff(std::move(src_stream), puffer,
@@ -266,8 +259,8 @@
while (bytes_wrote < dst_puff_size) {
auto write_size = std::min(static_cast<uint64_t>(buffer.size()),
dst_puff_size - bytes_wrote);
- TEST_AND_RETURN_VALUE(reader->Read(buffer.data(), write_size), -1);
- TEST_AND_RETURN_VALUE(writer->Write(buffer.data(), write_size), -1);
+ TEST_AND_RETURN_FALSE(reader->Read(buffer.data(), write_size));
+ TEST_AND_RETURN_FALSE(writer->Write(buffer.data(), write_size));
bytes_wrote += write_size;
}
@@ -288,9 +281,8 @@
while (bytes_read < dst_puff_size) {
auto read_size = std::min(static_cast<uint64_t>(buffer.size()),
dst_puff_size - bytes_read);
- TEST_AND_RETURN_VALUE(read_puff_stream->Read(buffer.data(), read_size),
- -1);
- TEST_AND_RETURN_VALUE(huff_writer->Write(buffer.data(), read_size), -1);
+ TEST_AND_RETURN_FALSE(read_puff_stream->Read(buffer.data(), read_size));
+ TEST_AND_RETURN_FALSE(huff_writer->Write(buffer.data(), read_size));
bytes_read += read_size;
}
}
@@ -299,11 +291,11 @@
LOG(WARNING) << "You should pass source puffs and destination deflates"
<< ", is this intentional?";
}
- TEST_AND_RETURN_VALUE(src_puffs.size() == dst_deflates_bit.size(), -1);
+ TEST_AND_RETURN_FALSE(src_puffs.size() == dst_deflates_bit.size());
uint64_t src_stream_size;
- TEST_AND_RETURN_VALUE(src_stream->GetSize(&src_stream_size), -1);
+ TEST_AND_RETURN_FALSE(src_stream->GetSize(&src_stream_size));
auto dst_file = FileStream::Open(FLAGS_dst_file, false, true);
- TEST_AND_RETURN_VALUE(dst_file, -1);
+ TEST_AND_RETURN_FALSE(dst_file);
auto huffer = std::make_shared<Huffer>();
auto dst_stream = PuffinStream::CreateForHuff(std::move(dst_file), huffer,
@@ -315,22 +307,18 @@
while (bytes_read < src_stream_size) {
auto read_size = std::min(static_cast<uint64_t>(buffer.size()),
src_stream_size - bytes_read);
- TEST_AND_RETURN_VALUE(src_stream->Read(buffer.data(), read_size), -1);
- TEST_AND_RETURN_VALUE(dst_stream->Write(buffer.data(), read_size), -1);
+ TEST_AND_RETURN_FALSE(src_stream->Read(buffer.data(), read_size));
+ TEST_AND_RETURN_FALSE(dst_stream->Write(buffer.data(), read_size));
bytes_read += read_size;
}
} else if (FLAGS_operation == "puffdiff") {
auto dst_stream = FileStream::Open(FLAGS_dst_file, true, false);
- TEST_AND_RETURN_VALUE(dst_stream, -1);
+ TEST_AND_RETURN_FALSE(dst_stream);
- TEST_AND_RETURN_VALUE(
- LocateDeflatesBasedOnFileType(src_stream, FLAGS_src_file,
- FLAGS_src_file_type, &src_deflates_byte),
- -1);
- TEST_AND_RETURN_VALUE(
- LocateDeflatesBasedOnFileType(dst_stream, FLAGS_dst_file,
- FLAGS_dst_file_type, &dst_deflates_byte),
- -1);
+ TEST_AND_RETURN_FALSE(LocateDeflatesBasedOnFileType(
+ src_stream, FLAGS_src_file, FLAGS_src_file_type, &src_deflates_bit));
+ TEST_AND_RETURN_FALSE(LocateDeflatesBasedOnFileType(
+ dst_stream, FLAGS_dst_file, FLAGS_dst_file_type, &dst_deflates_bit));
if (src_deflates_bit.empty() && src_deflates_byte.empty()) {
LOG(WARNING) << "You should pass source deflates, is this intentional?";
@@ -341,57 +329,54 @@
if (!dst_extents.empty()) {
dst_stream =
ExtentStream::CreateForWrite(std::move(dst_stream), dst_extents);
- TEST_AND_RETURN_VALUE(dst_stream, -1);
+ TEST_AND_RETURN_FALSE(dst_stream);
}
if (src_deflates_bit.empty()) {
- TEST_AND_RETURN_VALUE(FindDeflateSubBlocks(src_stream, src_deflates_byte,
- &src_deflates_bit),
- -1);
+ TEST_AND_RETURN_FALSE(FindDeflateSubBlocks(src_stream, src_deflates_byte,
+ &src_deflates_bit));
}
if (dst_deflates_bit.empty()) {
- TEST_AND_RETURN_VALUE(FindDeflateSubBlocks(dst_stream, dst_deflates_byte,
- &dst_deflates_bit),
- -1);
+ TEST_AND_RETURN_FALSE(FindDeflateSubBlocks(dst_stream, dst_deflates_byte,
+ &dst_deflates_bit));
}
+ // TODO(xunchang) add flags to select the bsdiff compressors.
Buffer puffdiff_delta;
- TEST_AND_RETURN_VALUE(
- puffin::PuffDiff(std::move(src_stream), std::move(dst_stream),
- src_deflates_bit, dst_deflates_bit, "/tmp/patch.tmp",
- &puffdiff_delta),
- -1);
+ TEST_AND_RETURN_FALSE(puffin::PuffDiff(
+ std::move(src_stream), std::move(dst_stream), src_deflates_bit,
+ dst_deflates_bit,
+ {bsdiff::CompressorType::kBZ2, bsdiff::CompressorType::kBrotli},
+ "/tmp/patch.tmp", &puffdiff_delta));
if (FLAGS_verbose) {
LOG(INFO) << "patch_size: " << puffdiff_delta.size();
}
auto patch_stream = FileStream::Open(FLAGS_patch_file, false, true);
- TEST_AND_RETURN_VALUE(patch_stream, -1);
- TEST_AND_RETURN_VALUE(
- patch_stream->Write(puffdiff_delta.data(), puffdiff_delta.size()), -1);
+ TEST_AND_RETURN_FALSE(patch_stream);
+ TEST_AND_RETURN_FALSE(
+ patch_stream->Write(puffdiff_delta.data(), puffdiff_delta.size()));
} else if (FLAGS_operation == "puffpatch") {
auto patch_stream = FileStream::Open(FLAGS_patch_file, true, false);
- TEST_AND_RETURN_VALUE(patch_stream, -1);
+ TEST_AND_RETURN_FALSE(patch_stream);
uint64_t patch_size;
- TEST_AND_RETURN_VALUE(patch_stream->GetSize(&patch_size), -1);
+ TEST_AND_RETURN_FALSE(patch_stream->GetSize(&patch_size));
Buffer puffdiff_delta(patch_size);
- TEST_AND_RETURN_VALUE(
- patch_stream->Read(puffdiff_delta.data(), puffdiff_delta.size()), -1);
+ TEST_AND_RETURN_FALSE(
+ patch_stream->Read(puffdiff_delta.data(), puffdiff_delta.size()));
auto dst_stream = FileStream::Open(FLAGS_dst_file, false, true);
- TEST_AND_RETURN_VALUE(dst_stream, -1);
+ TEST_AND_RETURN_FALSE(dst_stream);
if (!dst_extents.empty()) {
dst_stream =
ExtentStream::CreateForWrite(std::move(dst_stream), dst_extents);
- TEST_AND_RETURN_VALUE(dst_stream, -1);
+ TEST_AND_RETURN_FALSE(dst_stream);
}
// Apply the patch. Use 50MB cache, it should be enough for most of the
// operations.
- TEST_AND_RETURN_VALUE(
- puffin::PuffPatch(std::move(src_stream), std::move(dst_stream),
- puffdiff_delta.data(), puffdiff_delta.size(),
- FLAGS_cache_size), // max_cache_size
- -1);
+ TEST_AND_RETURN_FALSE(puffin::PuffPatch(
+ std::move(src_stream), std::move(dst_stream), puffdiff_delta.data(),
+ puffdiff_delta.size(), FLAGS_cache_size));
}
if (FLAGS_verbose) {
@@ -408,5 +393,12 @@
LOG(INFO) << "src_extents: " << puffin::ExtentsToString(src_extents);
LOG(INFO) << "dst_extents: " << puffin::ExtentsToString(dst_extents);
}
+ return true;
+}
+
+int main(int argc, char** argv) {
+ if (!Main(argc, argv)) {
+ return 1;
+ }
return 0;
}
diff --git a/src/memory_stream.cc b/src/memory_stream.cc
index 5f32a90..706f4a3 100644
--- a/src/memory_stream.cc
+++ b/src/memory_stream.cc
@@ -11,7 +11,7 @@
#include <utility>
#include "puffin/src/include/puffin/common.h"
-#include "puffin/src/set_errors.h"
+#include "puffin/src/logging.h"
namespace puffin {
diff --git a/src/patching_unittest.cc b/src/patching_unittest.cc
index d6327cf..134f137 100644
--- a/src/patching_unittest.cc
+++ b/src/patching_unittest.cc
@@ -11,18 +11,122 @@
#include "puffin/src/include/puffin/puffdiff.h"
#include "puffin/src/include/puffin/puffpatch.h"
#include "puffin/src/include/puffin/utils.h"
+#include "puffin/src/logging.h"
#include "puffin/src/memory_stream.h"
#include "puffin/src/puffin_stream.h"
-#include "puffin/src/sample_generator.h"
-#include "puffin/src/set_errors.h"
#include "puffin/src/unittest_common.h"
#define PRINT_SAMPLE 0 // Set to 1 if you want to print the generated samples.
+using std::string;
+using std::vector;
+
namespace puffin {
-using std::vector;
-using std::string;
+namespace {
+
+#if PRINT_SAMPLE
+// Print an array into hex-format to the output. This can be used to create
+// static arrays for unit testing of the puffer/huffer.
+void PrintArray(const string& name, const Buffer& array) {
+ std::cout << "const Buffer " << name << " = {" << std::endl << " ";
+ for (size_t idx = 0; idx < array.size(); idx++) {
+ std::cout << " 0x" << std::hex << std::uppercase << std::setfill('0')
+ << std::setw(2) << uint(array[idx]);
+ if (idx == array.size() - 1) {
+ std::cout << std::dec << "};" << std::endl;
+ return;
+ }
+ std::cout << ",";
+ if ((idx + 1) % 12 == 0) {
+ std::cout << std::endl << " ";
+ }
+ }
+}
+#endif
+
+const Buffer kPatch1To2 = {
+ 0x50, 0x55, 0x46, 0x31, 0x00, 0x00, 0x00, 0x51, 0x08, 0x01, 0x12, 0x27,
+ 0x0A, 0x04, 0x08, 0x10, 0x10, 0x32, 0x0A, 0x04, 0x08, 0x50, 0x10, 0x0A,
+ 0x0A, 0x04, 0x08, 0x60, 0x10, 0x12, 0x12, 0x04, 0x08, 0x10, 0x10, 0x58,
+ 0x12, 0x04, 0x08, 0x78, 0x10, 0x28, 0x12, 0x05, 0x08, 0xA8, 0x01, 0x10,
+ 0x38, 0x18, 0x1F, 0x1A, 0x24, 0x0A, 0x02, 0x10, 0x32, 0x0A, 0x04, 0x08,
+ 0x48, 0x10, 0x50, 0x0A, 0x05, 0x08, 0x98, 0x01, 0x10, 0x12, 0x12, 0x02,
+ 0x10, 0x58, 0x12, 0x04, 0x08, 0x70, 0x10, 0x58, 0x12, 0x05, 0x08, 0xC8,
+ 0x01, 0x10, 0x38, 0x18, 0x21, 0x42, 0x53, 0x44, 0x46, 0x32, 0x01, 0x01,
+ 0x01, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x42, 0x5A, 0x68, 0x39, 0x31, 0x41, 0x59, 0x26, 0x53, 0x59, 0xD1,
+ 0x20, 0xBB, 0x7E, 0x00, 0x00, 0x03, 0x60, 0x40, 0x78, 0x0E, 0x08, 0x00,
+ 0x40, 0x00, 0x20, 0x00, 0x31, 0x06, 0x4C, 0x40, 0x92, 0x8F, 0x46, 0xA7,
+ 0xA8, 0xE0, 0xF3, 0xD6, 0x21, 0x12, 0xF4, 0xBC, 0x43, 0x32, 0x1F, 0x17,
+ 0x72, 0x45, 0x38, 0x50, 0x90, 0xD1, 0x20, 0xBB, 0x7E, 0x42, 0x5A, 0x68,
+ 0x39, 0x31, 0x41, 0x59, 0x26, 0x53, 0x59, 0xF1, 0x20, 0x5F, 0x0D, 0x00,
+ 0x00, 0x02, 0x41, 0x15, 0x42, 0x08, 0x20, 0x00, 0x40, 0x00, 0x00, 0x02,
+ 0x40, 0x00, 0x20, 0x00, 0x22, 0x3D, 0x23, 0x10, 0x86, 0x03, 0x96, 0x54,
+ 0x11, 0x16, 0x5F, 0x17, 0x72, 0x45, 0x38, 0x50, 0x90, 0xF1, 0x20, 0x5F,
+ 0x0D, 0x42, 0x5A, 0x68, 0x39, 0x31, 0x41, 0x59, 0x26, 0x53, 0x59, 0x07,
+ 0xD4, 0xCB, 0x6E, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x20, 0x00,
+ 0x21, 0x18, 0x46, 0x82, 0xEE, 0x48, 0xA7, 0x0A, 0x12, 0x00, 0xFA, 0x99,
+ 0x6D, 0xC0};
+
+const Buffer kPatch2To1 = {
+ 0x50, 0x55, 0x46, 0x31, 0x00, 0x00, 0x00, 0x51, 0x08, 0x01, 0x12, 0x24,
+ 0x0A, 0x02, 0x10, 0x32, 0x0A, 0x04, 0x08, 0x48, 0x10, 0x50, 0x0A, 0x05,
+ 0x08, 0x98, 0x01, 0x10, 0x12, 0x12, 0x02, 0x10, 0x58, 0x12, 0x04, 0x08,
+ 0x70, 0x10, 0x58, 0x12, 0x05, 0x08, 0xC8, 0x01, 0x10, 0x38, 0x18, 0x21,
+ 0x1A, 0x27, 0x0A, 0x04, 0x08, 0x10, 0x10, 0x32, 0x0A, 0x04, 0x08, 0x50,
+ 0x10, 0x0A, 0x0A, 0x04, 0x08, 0x60, 0x10, 0x12, 0x12, 0x04, 0x08, 0x10,
+ 0x10, 0x58, 0x12, 0x04, 0x08, 0x78, 0x10, 0x28, 0x12, 0x05, 0x08, 0xA8,
+ 0x01, 0x10, 0x38, 0x18, 0x1F, 0x42, 0x53, 0x44, 0x46, 0x32, 0x01, 0x01,
+ 0x01, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x42, 0x5A, 0x68, 0x39, 0x31, 0x41, 0x59, 0x26, 0x53, 0x59, 0x3D,
+ 0xBD, 0x08, 0x91, 0x00, 0x00, 0x01, 0xE0, 0x40, 0x5C, 0x0A, 0x40, 0x00,
+ 0x40, 0x00, 0x20, 0x00, 0x31, 0x0C, 0x08, 0x23, 0xD2, 0x34, 0xD1, 0xB1,
+ 0x73, 0x60, 0x44, 0x54, 0xE4, 0xFC, 0x5D, 0xC9, 0x14, 0xE1, 0x42, 0x40,
+ 0xF6, 0xF4, 0x22, 0x44, 0x42, 0x5A, 0x68, 0x39, 0x31, 0x41, 0x59, 0x26,
+ 0x53, 0x59, 0x41, 0x62, 0x2E, 0xF0, 0x00, 0x00, 0x00, 0x40, 0x00, 0x40,
+ 0x20, 0x20, 0x00, 0x21, 0x00, 0x82, 0x83, 0x17, 0x72, 0x45, 0x38, 0x50,
+ 0x90, 0x41, 0x62, 0x2E, 0xF0, 0x42, 0x5A, 0x68, 0x39, 0x31, 0x41, 0x59,
+ 0x26, 0x53, 0x59, 0xE0, 0x20, 0x04, 0x57, 0x00, 0x00, 0x04, 0x76, 0x50,
+ 0xE0, 0x00, 0x20, 0x00, 0x10, 0x00, 0x04, 0x00, 0x02, 0x00, 0x20, 0x00,
+ 0x40, 0x00, 0x00, 0x00, 0xA0, 0x00, 0x21, 0xA1, 0xA3, 0x10, 0x83, 0x26,
+ 0x21, 0x5E, 0xB2, 0x69, 0xAC, 0x70, 0x60, 0x53, 0xC5, 0xDC, 0x91, 0x4E,
+ 0x14, 0x24, 0x38, 0x08, 0x01, 0x15, 0xC0};
+
+const Buffer kPatch1ToEmpty = {
+ 0x50, 0x55, 0x46, 0x31, 0x00, 0x00, 0x00, 0x2D, 0x08, 0x01, 0x12, 0x27,
+ 0x0A, 0x04, 0x08, 0x10, 0x10, 0x32, 0x0A, 0x04, 0x08, 0x50, 0x10, 0x0A,
+ 0x0A, 0x04, 0x08, 0x60, 0x10, 0x12, 0x12, 0x04, 0x08, 0x10, 0x10, 0x58,
+ 0x12, 0x04, 0x08, 0x78, 0x10, 0x28, 0x12, 0x05, 0x08, 0xA8, 0x01, 0x10,
+ 0x38, 0x18, 0x1F, 0x1A, 0x00, 0x42, 0x53, 0x44, 0x46, 0x32, 0x01, 0x01,
+ 0x01, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x42, 0x5A, 0x68, 0x39, 0x17, 0x72, 0x45, 0x38, 0x50, 0x90, 0x00,
+ 0x00, 0x00, 0x00, 0x42, 0x5A, 0x68, 0x39, 0x17, 0x72, 0x45, 0x38, 0x50,
+ 0x90, 0x00, 0x00, 0x00, 0x00, 0x42, 0x5A, 0x68, 0x39, 0x17, 0x72, 0x45,
+ 0x38, 0x50, 0x90, 0x00, 0x00, 0x00, 0x00};
+
+const Buffer kPatch1ToNoDeflate = {
+ 0x50, 0x55, 0x46, 0x31, 0x00, 0x00, 0x00, 0x2F, 0x08, 0x01, 0x12, 0x27,
+ 0x0A, 0x04, 0x08, 0x10, 0x10, 0x32, 0x0A, 0x04, 0x08, 0x50, 0x10, 0x0A,
+ 0x0A, 0x04, 0x08, 0x60, 0x10, 0x12, 0x12, 0x04, 0x08, 0x10, 0x10, 0x58,
+ 0x12, 0x04, 0x08, 0x78, 0x10, 0x28, 0x12, 0x05, 0x08, 0xA8, 0x01, 0x10,
+ 0x38, 0x18, 0x1F, 0x1A, 0x02, 0x18, 0x04, 0x42, 0x53, 0x44, 0x46, 0x32,
+ 0x01, 0x01, 0x01, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x42, 0x5A, 0x68, 0x39, 0x31, 0x41, 0x59, 0x26, 0x53,
+ 0x59, 0xBA, 0x8D, 0x7F, 0x2D, 0x00, 0x00, 0x00, 0x40, 0x00, 0x44, 0x08,
+ 0x20, 0x00, 0x30, 0xCC, 0x09, 0x32, 0x54, 0x65, 0x38, 0xBB, 0x92, 0x29,
+ 0xC2, 0x84, 0x85, 0xD4, 0x6B, 0xF9, 0x68, 0x42, 0x5A, 0x68, 0x39, 0x17,
+ 0x72, 0x45, 0x38, 0x50, 0x90, 0x00, 0x00, 0x00, 0x00, 0x42, 0x5A, 0x68,
+ 0x39, 0x31, 0x41, 0x59, 0x26, 0x53, 0x59, 0xE7, 0xAA, 0xF1, 0xFC, 0x00,
+ 0x00, 0x00, 0x70, 0x00, 0x00, 0x08, 0x01, 0x00, 0x20, 0x04, 0x20, 0x00,
+ 0x21, 0x9A, 0x68, 0x33, 0x4D, 0x13, 0x3C, 0x5D, 0xC9, 0x14, 0xE1, 0x42,
+ 0x43, 0x9E, 0xAB, 0xC7, 0xF0};
+
+} // namespace
void TestPatching(const Buffer& src_buf,
const Buffer& dst_buf,
@@ -33,45 +137,48 @@
string patch_path;
ASSERT_TRUE(MakeTempFile(&patch_path, nullptr));
ScopedPathUnlinker scoped_unlinker(patch_path);
- ASSERT_TRUE(PuffDiff(src_buf, dst_buf, src_deflates, dst_deflates, patch_path,
- &patch_out));
+ ASSERT_TRUE(PuffDiff(src_buf, dst_buf, src_deflates, dst_deflates,
+ {bsdiff::CompressorType::kBZ2}, patch_path, &patch_out));
#if PRINT_SAMPLE
- sample_generator::PrintArray("kPatchXXXXX", patch_out);
+ PrintArray("kPatchXXXXX", patch_out);
#endif
EXPECT_EQ(patch_out, patch);
auto src_stream = MemoryStream::CreateForRead(src_buf);
- Buffer dst_buf_out;
+ Buffer dst_buf_out(dst_buf.size());
auto dst_stream = MemoryStream::CreateForWrite(&dst_buf_out);
ASSERT_TRUE(PuffPatch(std::move(src_stream), std::move(dst_stream),
patch.data(), patch.size()));
EXPECT_EQ(dst_buf_out, dst_buf);
}
-TEST(PatchingTest, Patching8To9Test) {
- TestPatching(kDeflates8, kDeflates9, kSubblockDeflateExtents8,
- kSubblockDeflateExtents9, kPatch8To9);
+TEST(PatchingTest, Patching1To2Test) {
+ TestPatching(kDeflatesSample1, kDeflatesSample2,
+ kSubblockDeflateExtentsSample1, kSubblockDeflateExtentsSample2,
+ kPatch1To2);
}
-TEST(PatchingTest, Patching9To8Test) {
- TestPatching(kDeflates9, kDeflates8, kSubblockDeflateExtents9,
- kSubblockDeflateExtents8, kPatch9To8);
+TEST(PatchingTest, Patching2To1Test) {
+ TestPatching(kDeflatesSample2, kDeflatesSample1,
+ kSubblockDeflateExtentsSample2, kSubblockDeflateExtentsSample1,
+ kPatch2To1);
}
-TEST(PatchingTest, Patching8ToEmptyTest) {
- TestPatching(kDeflates8, {}, kSubblockDeflateExtents8, {}, kPatch8ToEmpty);
+TEST(PatchingTest, Patching1ToEmptyTest) {
+ TestPatching(kDeflatesSample1, {}, kSubblockDeflateExtentsSample1, {},
+ kPatch1ToEmpty);
}
-TEST(PatchingTest, Patching8ToNoDeflateTest) {
- TestPatching(kDeflates8, {11, 22, 33, 44}, kSubblockDeflateExtents8, {},
- kPatch8ToNoDeflate);
+TEST(PatchingTest, Patching1ToNoDeflateTest) {
+ TestPatching(kDeflatesSample1, {11, 22, 33, 44},
+ kSubblockDeflateExtentsSample1, {}, kPatch1ToNoDeflate);
}
// TODO(ahassani): add tests for:
-// TestPatchingEmptyTo9
-// TestPatchingNoDeflateTo9
+// TestPatchingEmptyTo2
+// TestPatchingNoDeflateTo2
// TODO(ahassani): Change tests data if you decided to compress the header of
// the patch.
diff --git a/src/puff_io_unittest.cc b/src/puff_io_unittest.cc
index 64976bd..c1178cd 100644
--- a/src/puff_io_unittest.cc
+++ b/src/puff_io_unittest.cc
@@ -4,7 +4,6 @@
#include "gtest/gtest.h"
-#include "puffin/src/include/puffin/errors.h"
#include "puffin/src/puff_reader.h"
#include "puffin/src/puff_writer.h"
#include "puffin/src/unittest_common.h"
@@ -15,16 +14,15 @@
void TestLiteralLength(size_t length) {
Buffer buf(length + 10);
PuffData pd;
- Error error;
BufferPuffWriter pw(buf.data(), buf.size());
// We need to insert a metadata otherwise it will fail.
pd.type = PuffData::Type::kBlockMetadata;
pd.length = 1;
- ASSERT_TRUE(pw.Insert(pd, &error));
+ ASSERT_TRUE(pw.Insert(pd));
BufferPuffReader pr(buf.data(), buf.size());
- ASSERT_TRUE(pr.GetNext(&pd, &error));
+ ASSERT_TRUE(pr.GetNext(&pd));
ASSERT_EQ(pd.type, PuffData::Type::kBlockMetadata);
ASSERT_EQ(pd.length, 1);
@@ -35,15 +33,15 @@
std::fill(buffer, buffer + count, 10);
return true;
};
- ASSERT_TRUE(pw.Insert(pd, &error));
- ASSERT_TRUE(pw.Flush(&error));
+ ASSERT_TRUE(pw.Insert(pd));
+ ASSERT_TRUE(pw.Flush());
pd.type = PuffData::Type::kLenDist;
pd.distance = 1;
pd.length = 3;
- ASSERT_TRUE(pw.Insert(pd, &error));
+ ASSERT_TRUE(pw.Insert(pd));
- ASSERT_TRUE(pr.GetNext(&pd, &error));
+ ASSERT_TRUE(pr.GetNext(&pd));
if (length == 0) {
// If length is zero, then nothing should've been inserted.
ASSERT_EQ(pd.type, PuffData::Type::kLenDist);
@@ -66,7 +64,6 @@
BufferPuffReader pr(buf.data(), buf.size());
BufferPuffWriter pw(buf.data(), buf.size());
BufferPuffWriter epw(nullptr, 0);
- Error error;
uint8_t block = 123;
{
@@ -75,14 +72,14 @@
pd.block_metadata[0] = 0xCC; // header
memcpy(&pd.block_metadata[1], &block, sizeof(block));
pd.length = sizeof(block) + 1;
- ASSERT_TRUE(pw.Insert(pd, &error));
- ASSERT_TRUE(epw.Insert(pd, &error));
- ASSERT_TRUE(pw.Flush(&error));
- ASSERT_TRUE(epw.Flush(&error));
+ ASSERT_TRUE(pw.Insert(pd));
+ ASSERT_TRUE(epw.Insert(pd));
+ ASSERT_TRUE(pw.Flush());
+ ASSERT_TRUE(epw.Flush());
}
{
PuffData pd;
- ASSERT_TRUE(pr.GetNext(&pd, &error));
+ ASSERT_TRUE(pr.GetNext(&pd));
ASSERT_EQ(pd.type, PuffData::Type::kBlockMetadata);
ASSERT_EQ(pd.length, sizeof(block) + 1);
ASSERT_EQ(pd.block_metadata[0], 0xCC);
@@ -93,45 +90,45 @@
pd.type = PuffData::Type::kLenDist;
pd.distance = 321;
pd.length = 3;
- ASSERT_TRUE(pw.Insert(pd, &error));
- ASSERT_TRUE(epw.Insert(pd, &error));
+ ASSERT_TRUE(pw.Insert(pd));
+ ASSERT_TRUE(epw.Insert(pd));
pd.length = 127;
- ASSERT_TRUE(pw.Insert(pd, &error));
- ASSERT_TRUE(epw.Insert(pd, &error));
+ ASSERT_TRUE(pw.Insert(pd));
+ ASSERT_TRUE(epw.Insert(pd));
pd.length = 258;
- ASSERT_TRUE(pw.Insert(pd, &error));
- ASSERT_TRUE(epw.Insert(pd, &error));
- ASSERT_TRUE(pw.Flush(&error));
- ASSERT_TRUE(epw.Flush(&error));
+ ASSERT_TRUE(pw.Insert(pd));
+ ASSERT_TRUE(epw.Insert(pd));
+ ASSERT_TRUE(pw.Flush());
+ ASSERT_TRUE(epw.Flush());
pd.length = 259;
- ASSERT_FALSE(pw.Insert(pd, &error));
- ASSERT_FALSE(epw.Insert(pd, &error));
+ ASSERT_FALSE(pw.Insert(pd));
+ ASSERT_FALSE(epw.Insert(pd));
}
{
PuffData pd;
- ASSERT_TRUE(pr.GetNext(&pd, &error));
+ ASSERT_TRUE(pr.GetNext(&pd));
ASSERT_EQ(pd.type, PuffData::Type::kLenDist);
ASSERT_EQ(pd.distance, 321);
ASSERT_EQ(pd.length, 3);
- ASSERT_TRUE(pr.GetNext(&pd, &error));
+ ASSERT_TRUE(pr.GetNext(&pd));
ASSERT_EQ(pd.type, PuffData::Type::kLenDist);
ASSERT_EQ(pd.length, 127);
- ASSERT_TRUE(pr.GetNext(&pd, &error));
+ ASSERT_TRUE(pr.GetNext(&pd));
ASSERT_EQ(pd.type, PuffData::Type::kLenDist);
ASSERT_EQ(pd.length, 258);
}
{
PuffData pd;
pd.type = PuffData::Type::kEndOfBlock;
- ASSERT_TRUE(pw.Insert(pd, &error));
- ASSERT_TRUE(epw.Insert(pd, &error));
- ASSERT_TRUE(pw.Flush(&error));
- ASSERT_TRUE(epw.Flush(&error));
+ ASSERT_TRUE(pw.Insert(pd));
+ ASSERT_TRUE(epw.Insert(pd));
+ ASSERT_TRUE(pw.Flush());
+ ASSERT_TRUE(epw.Flush());
}
{
PuffData pd;
- ASSERT_TRUE(pr.GetNext(&pd, &error));
+ ASSERT_TRUE(pr.GetNext(&pd));
ASSERT_EQ(pd.type, PuffData::Type::kEndOfBlock);
}
{
@@ -141,14 +138,14 @@
pd.block_metadata[0] = 0xCC; // header
memcpy(&pd.block_metadata[1], &block, sizeof(block));
pd.length = sizeof(block) + 1;
- ASSERT_TRUE(pw.Insert(pd, &error));
- ASSERT_TRUE(epw.Insert(pd, &error));
- ASSERT_TRUE(pw.Flush(&error));
- ASSERT_TRUE(epw.Flush(&error));
+ ASSERT_TRUE(pw.Insert(pd));
+ ASSERT_TRUE(epw.Insert(pd));
+ ASSERT_TRUE(pw.Flush());
+ ASSERT_TRUE(epw.Flush());
}
{
PuffData pd;
- ASSERT_TRUE(pr.GetNext(&pd, &error));
+ ASSERT_TRUE(pr.GetNext(&pd));
ASSERT_EQ(pd.type, PuffData::Type::kBlockMetadata);
ASSERT_EQ(pd.length, sizeof(block) + 1);
ASSERT_EQ(pd.block_metadata[0], 0xCC);
@@ -170,27 +167,27 @@
index += count;
return true;
};
- ASSERT_TRUE(pw.Insert(pd, &error));
- ASSERT_TRUE(pw.Flush(&error));
+ ASSERT_TRUE(pw.Insert(pd));
+ ASSERT_TRUE(pw.Flush());
// We have to refresh the read_fn function for the second insert.
index = 0;
- ASSERT_TRUE(epw.Insert(pd, &error));
- ASSERT_TRUE(epw.Flush(&error));
+ ASSERT_TRUE(epw.Insert(pd));
+ ASSERT_TRUE(epw.Flush());
}
{
PuffData pd;
pd.type = PuffData::Type::kLiteral;
pd.byte = 10;
- ASSERT_TRUE(pw.Insert(pd, &error));
- ASSERT_TRUE(epw.Insert(pd, &error));
- ASSERT_TRUE(pw.Flush(&error));
- ASSERT_TRUE(epw.Flush(&error));
+ ASSERT_TRUE(pw.Insert(pd));
+ ASSERT_TRUE(epw.Insert(pd));
+ ASSERT_TRUE(pw.Flush());
+ ASSERT_TRUE(epw.Flush());
}
uint8_t tmp3[3];
{
PuffData pd;
- ASSERT_TRUE(pr.GetNext(&pd, &error));
+ ASSERT_TRUE(pr.GetNext(&pd));
ASSERT_EQ(pd.type, PuffData::Type::kLiterals);
ASSERT_EQ(pd.length, 3);
ASSERT_TRUE(pd.read_fn(tmp3, 3));
@@ -199,7 +196,7 @@
}
{
PuffData pd;
- ASSERT_TRUE(pr.GetNext(&pd, &error));
+ ASSERT_TRUE(pr.GetNext(&pd));
ASSERT_EQ(pd.type, PuffData::Type::kLiterals);
ASSERT_EQ(pd.length, 1);
ASSERT_TRUE(pd.read_fn(tmp3, 1));
@@ -209,14 +206,14 @@
{
PuffData pd;
pd.type = PuffData::Type::kEndOfBlock;
- ASSERT_TRUE(pw.Insert(pd, &error));
- ASSERT_TRUE(epw.Insert(pd, &error));
- ASSERT_TRUE(pw.Flush(&error));
- ASSERT_TRUE(epw.Flush(&error));
+ ASSERT_TRUE(pw.Insert(pd));
+ ASSERT_TRUE(epw.Insert(pd));
+ ASSERT_TRUE(pw.Flush());
+ ASSERT_TRUE(epw.Flush());
}
{
PuffData pd;
- ASSERT_TRUE(pr.GetNext(&pd, &error));
+ ASSERT_TRUE(pr.GetNext(&pd));
ASSERT_EQ(pd.type, PuffData::Type::kEndOfBlock);
}
@@ -227,7 +224,6 @@
// Testing metadata boundary.
TEST(PuffIOTest, MetadataBoundaryTest) {
PuffData pd;
- Error error;
Buffer buf(3);
BufferPuffWriter pw(buf.data(), buf.size());
@@ -235,21 +231,19 @@
// bytes is left for the varied part of metadata.
pd.type = PuffData::Type::kBlockMetadata;
pd.length = 2;
- ASSERT_FALSE(pw.Insert(pd, &error));
- ASSERT_EQ(error, Error::kInsufficientOutput);
+ ASSERT_FALSE(pw.Insert(pd));
pd.length = 0; // length should be at least 1.
- ASSERT_FALSE(pw.Insert(pd, &error));
+ ASSERT_FALSE(pw.Insert(pd));
pd.length = 1;
- ASSERT_TRUE(pw.Insert(pd, &error));
+ ASSERT_TRUE(pw.Insert(pd));
Buffer puff_buffer = {0x00, 0x03, 0x02, 0x00, 0x00};
BufferPuffReader pr(puff_buffer.data(), puff_buffer.size());
- ASSERT_FALSE(pr.GetNext(&pd, &error));
+ ASSERT_FALSE(pr.GetNext(&pd));
}
TEST(PuffIOTest, InvalidCopyLengthsDistanceTest) {
PuffData pd;
- Error error;
Buffer puff_buffer(20);
BufferPuffWriter pw(puff_buffer.data(), puff_buffer.size());
@@ -257,44 +251,43 @@
pd.type = PuffData::Type::kLenDist;
pd.distance = 1;
pd.length = 0;
- EXPECT_FALSE(pw.Insert(pd, &error));
+ EXPECT_FALSE(pw.Insert(pd));
pd.length = 1;
- EXPECT_FALSE(pw.Insert(pd, &error));
+ EXPECT_FALSE(pw.Insert(pd));
pd.length = 2;
- EXPECT_FALSE(pw.Insert(pd, &error));
+ EXPECT_FALSE(pw.Insert(pd));
pd.length = 3;
- EXPECT_TRUE(pw.Insert(pd, &error));
+ EXPECT_TRUE(pw.Insert(pd));
pd.length = 259;
- EXPECT_FALSE(pw.Insert(pd, &error));
+ EXPECT_FALSE(pw.Insert(pd));
pd.length = 258;
- EXPECT_TRUE(pw.Insert(pd, &error));
+ EXPECT_TRUE(pw.Insert(pd));
// Invalid distance values.
pd.length = 3;
pd.distance = 0;
- EXPECT_FALSE(pw.Insert(pd, &error));
+ EXPECT_FALSE(pw.Insert(pd));
pd.distance = 1;
- EXPECT_TRUE(pw.Insert(pd, &error));
+ EXPECT_TRUE(pw.Insert(pd));
pd.distance = 32769;
- EXPECT_FALSE(pw.Insert(pd, &error));
+ EXPECT_FALSE(pw.Insert(pd));
pd.distance = 32768;
- EXPECT_TRUE(pw.Insert(pd, &error));
+ EXPECT_TRUE(pw.Insert(pd));
// First three bytes header, four bytes value lit/len, and four bytes
// invalid lit/len.
puff_buffer = {0x00, 0x00, 0xFF, 0xFF, 0x80, 0x00,
0x00, 0xFF, 0x82, 0x00, 0x00};
BufferPuffReader pr(puff_buffer.data(), puff_buffer.size());
- EXPECT_TRUE(pr.GetNext(&pd, &error));
+ EXPECT_TRUE(pr.GetNext(&pd));
EXPECT_EQ(pd.type, PuffData::Type::kBlockMetadata);
- EXPECT_TRUE(pr.GetNext(&pd, &error));
+ EXPECT_TRUE(pr.GetNext(&pd));
EXPECT_EQ(pd.type, PuffData::Type::kLenDist);
- EXPECT_FALSE(pr.GetNext(&pd, &error));
+ EXPECT_FALSE(pr.GetNext(&pd));
}
TEST(PuffIOTest, InvalidCopyLenghtDistanceBoundaryTest) {
PuffData pd;
- Error error;
Buffer puff_buffer(5);
pd.type = PuffData::Type::kLenDist;
@@ -302,21 +295,21 @@
pd.length = 129;
for (size_t i = 1; i < 2; i++) {
BufferPuffWriter pw(puff_buffer.data(), i);
- EXPECT_FALSE(pw.Insert(pd, &error));
+ EXPECT_FALSE(pw.Insert(pd));
}
pd.length = 130;
for (size_t i = 1; i < 3; i++) {
BufferPuffWriter pw(puff_buffer.data(), i);
- EXPECT_FALSE(pw.Insert(pd, &error));
+ EXPECT_FALSE(pw.Insert(pd));
}
// First three bytes header, three bytes value lit/len.
puff_buffer = {0x00, 0x00, 0xFF, 0xFF, 0x80, 0x00};
BufferPuffReader pr(puff_buffer.data(), puff_buffer.size());
- EXPECT_TRUE(pr.GetNext(&pd, &error));
+ EXPECT_TRUE(pr.GetNext(&pd));
EXPECT_EQ(pd.type, PuffData::Type::kBlockMetadata);
- EXPECT_FALSE(pr.GetNext(&pd, &error));
+ EXPECT_FALSE(pr.GetNext(&pd));
}
TEST(PuffIOTest, LiteralsTest) {
@@ -332,13 +325,12 @@
TEST(PuffIOTest, MaxLiteralsTest) {
Buffer buf((1 << 16) + 127 + 20);
PuffData pd;
- Error error;
BufferPuffWriter pw(buf.data(), buf.size());
// We need to insert a metadata otherwise it will fail.
pd.type = PuffData::Type::kBlockMetadata;
pd.length = 1;
- ASSERT_TRUE(pw.Insert(pd, &error));
+ ASSERT_TRUE(pw.Insert(pd));
pd.type = PuffData::Type::kLiterals;
pd.length = (1 << 16);
@@ -346,15 +338,15 @@
std::fill(buffer, buffer + count, 10);
return true;
};
- ASSERT_TRUE(pw.Insert(pd, &error));
- ASSERT_TRUE(pw.Flush(&error));
+ ASSERT_TRUE(pw.Insert(pd));
+ ASSERT_TRUE(pw.Flush());
BufferPuffReader pr(buf.data(), buf.size());
- ASSERT_TRUE(pr.GetNext(&pd, &error));
+ ASSERT_TRUE(pr.GetNext(&pd));
ASSERT_EQ(pd.type, PuffData::Type::kBlockMetadata);
ASSERT_EQ(pd.length, 1);
- ASSERT_TRUE(pr.GetNext(&pd, &error));
+ ASSERT_TRUE(pr.GetNext(&pd));
ASSERT_EQ(pd.type, PuffData::Type::kLiterals);
ASSERT_EQ(pd.length, 1 << 16);
for (size_t i = 0; i < pd.length; i++) {
@@ -366,28 +358,28 @@
BufferPuffWriter pw2(buf.data(), buf.size());
pd.type = PuffData::Type::kBlockMetadata;
pd.length = 1;
- ASSERT_TRUE(pw2.Insert(pd, &error));
+ ASSERT_TRUE(pw2.Insert(pd));
pd.type = PuffData::Type::kLiteral;
pd.length = 1;
pd.byte = 12;
// We have to be able to fill 65663 bytes.
for (size_t i = 0; i < ((1 << 16) + 127); i++) {
- ASSERT_TRUE(pw2.Insert(pd, &error));
+ ASSERT_TRUE(pw2.Insert(pd));
}
// If we add one more, then it should have been flushed.
pd.byte = 13;
- ASSERT_TRUE(pw2.Insert(pd, &error));
- ASSERT_TRUE(pw2.Flush(&error));
+ ASSERT_TRUE(pw2.Insert(pd));
+ ASSERT_TRUE(pw2.Flush());
// Now read it back.
BufferPuffReader pr2(buf.data(), buf.size());
- ASSERT_TRUE(pr2.GetNext(&pd, &error));
+ ASSERT_TRUE(pr2.GetNext(&pd));
ASSERT_EQ(pd.type, PuffData::Type::kBlockMetadata);
// Now we should read on kLiterals with lenght 1 << 16 and just one literal
// after that.
- ASSERT_TRUE(pr2.GetNext(&pd, &error));
+ ASSERT_TRUE(pr2.GetNext(&pd));
ASSERT_EQ(pd.type, PuffData::Type::kLiterals);
ASSERT_EQ(pd.length, (1 << 16) + 127);
for (size_t i = 0; i < pd.length; i++) {
@@ -396,7 +388,7 @@
ASSERT_EQ(byte, 12);
}
- ASSERT_TRUE(pr2.GetNext(&pd, &error));
+ ASSERT_TRUE(pr2.GetNext(&pd));
ASSERT_EQ(pd.type, PuffData::Type::kLiterals);
ASSERT_EQ(pd.length, 1);
uint8_t byte;
diff --git a/src/puff_reader.cc b/src/puff_reader.cc
index 34ef5c3..fcf68fd 100644
--- a/src/puff_reader.cc
+++ b/src/puff_reader.cc
@@ -9,7 +9,7 @@
#include <string>
#include <vector>
-#include "puffin/src/set_errors.h"
+#include "puffin/src/logging.h"
namespace puffin {
@@ -20,21 +20,19 @@
}
} // namespace
-bool BufferPuffReader::GetNext(PuffData* data, Error* error) {
+bool BufferPuffReader::GetNext(PuffData* data) {
PuffData& pd = *data;
size_t length = 0;
if (state_ == State::kReadingLenDist) {
// Boundary check
- TEST_AND_RETURN_FALSE_SET_ERROR(index_ < puff_size_,
- Error::kInsufficientInput);
+ TEST_AND_RETURN_FALSE(index_ < puff_size_);
if (puff_buf_in_[index_] & 0x80) { // Reading length/distance.
if ((puff_buf_in_[index_] & 0x7F) < 127) {
length = puff_buf_in_[index_] & 0x7F;
} else {
index_++;
// Boundary check
- TEST_AND_RETURN_FALSE_SET_ERROR(index_ < puff_size_,
- Error::kInsufficientInput);
+ TEST_AND_RETURN_FALSE(index_ < puff_size_);
length = puff_buf_in_[index_] + 127;
}
length += 3;
@@ -52,13 +50,11 @@
}
// Boundary check
- TEST_AND_RETURN_FALSE_SET_ERROR(index_ + 1 < puff_size_,
- Error::kInsufficientInput);
+ TEST_AND_RETURN_FALSE(index_ + 1 < puff_size_);
auto distance = ReadByteArrayToUint16(&puff_buf_in_[index_]);
// The distance in RFC is in the range [1..32768], but in the puff spec,
// we write zero-based distance in the puff stream.
- TEST_AND_RETURN_FALSE_SET_ERROR(distance < (1 << 15),
- Error::kInsufficientInput);
+ TEST_AND_RETURN_FALSE(distance < (1 << 15));
distance++;
index_ += 2;
@@ -69,24 +65,21 @@
return true;
} else { // Reading literals.
// Boundary check
- TEST_AND_RETURN_FALSE_SET_ERROR(index_ < puff_size_,
- Error::kInsufficientInput);
+ TEST_AND_RETURN_FALSE(index_ < puff_size_);
if ((puff_buf_in_[index_] & 0x7F) < 127) {
length = puff_buf_in_[index_] & 0x7F;
index_++;
} else {
index_++;
// Boundary check
- TEST_AND_RETURN_FALSE_SET_ERROR(index_ + 1 < puff_size_,
- Error::kInsufficientInput);
+ TEST_AND_RETURN_FALSE(index_ + 1 < puff_size_);
length = ReadByteArrayToUint16(&puff_buf_in_[index_]) + 127;
index_ += 2;
}
length++;
DVLOG(2) << "Read literals length: " << length;
// Boundary check
- TEST_AND_RETURN_FALSE_SET_ERROR(index_ + length <= puff_size_,
- Error::kInsufficientInput);
+ TEST_AND_RETURN_FALSE(index_ + length <= puff_size_);
pd.type = PuffData::Type::kLiterals;
pd.length = length;
pd.read_fn = [this, length](uint8_t* buffer, size_t count) mutable {
@@ -101,14 +94,12 @@
} else { // Block metadata
pd.type = PuffData::Type::kBlockMetadata;
// Boundary check
- TEST_AND_RETURN_FALSE_SET_ERROR(index_ + 2 < puff_size_,
- Error::kInsufficientInput);
+ TEST_AND_RETURN_FALSE(index_ + 2 < puff_size_);
length = ReadByteArrayToUint16(&puff_buf_in_[index_]) + 1;
index_ += 2;
DVLOG(2) << "Read block metadata length: " << length;
// Boundary check
- TEST_AND_RETURN_FALSE_SET_ERROR(index_ + length <= puff_size_,
- Error::kInsufficientInput);
+ TEST_AND_RETURN_FALSE(index_ + length <= puff_size_);
TEST_AND_RETURN_FALSE(length <= sizeof(pd.block_metadata));
memcpy(pd.block_metadata, &puff_buf_in_[index_], length);
index_ += length;
diff --git a/src/puff_reader.h b/src/puff_reader.h
index 3e6c4df..40e6bfb 100644
--- a/src/puff_reader.h
+++ b/src/puff_reader.h
@@ -9,7 +9,6 @@
#include <cstdint>
#include "puffin/src/include/puffin/common.h"
-#include "puffin/src/include/puffin/errors.h"
#include "puffin/src/puff_data.h"
namespace puffin {
@@ -26,8 +25,7 @@
// data.
//
// |data| OUT The next data available in the puffed buffer.
- // |error| OUT The error code.
- virtual bool GetNext(PuffData* data, Error* error) = 0;
+ virtual bool GetNext(PuffData* data) = 0;
// Returns the number of bytes left in the puff buffer.
virtual size_t BytesLeft() const = 0;
@@ -48,7 +46,7 @@
~BufferPuffReader() override = default;
- bool GetNext(PuffData* pd, Error* error) override;
+ bool GetNext(PuffData* pd) override;
size_t BytesLeft() const override;
private:
diff --git a/src/puff_writer.cc b/src/puff_writer.cc
index f39dad9..e26c3be 100644
--- a/src/puff_writer.cc
+++ b/src/puff_writer.cc
@@ -9,7 +9,7 @@
#include <string>
#include <vector>
-#include "puffin/src/set_errors.h"
+#include "puffin/src/logging.h"
namespace puffin {
@@ -24,13 +24,13 @@
constexpr size_t kLiteralsMaxLength = (1 << 16) + 127; // 65663
} // namespace
-bool BufferPuffWriter::Insert(const PuffData& pd, Error* error) {
+bool BufferPuffWriter::Insert(const PuffData& pd) {
switch (pd.type) {
case PuffData::Type::kLiterals:
if (pd.length == 0) {
return true;
}
- // We don't break here. It will be processed in kLiteral;
+ FALLTHROUGH_INTENDED;
case PuffData::Type::kLiteral: {
DVLOG(2) << "Write literals length: " << pd.length;
size_t length = pd.type == PuffData::Type::kLiteral ? 1 : pd.length;
@@ -43,8 +43,7 @@
if ((cur_literals_length_ + length) > 127) {
if (puff_buf_out_ != nullptr) {
// Boundary check
- TEST_AND_RETURN_FALSE_SET_ERROR(index_ + 2 <= puff_size_,
- Error::kInsufficientOutput);
+ TEST_AND_RETURN_FALSE(index_ + 2 <= puff_size_);
// Shift two bytes forward to open space for length value.
memmove(&puff_buf_out_[len_index_ + 3],
@@ -57,18 +56,14 @@
if (puff_buf_out_ != nullptr) {
// Boundary check
- TEST_AND_RETURN_FALSE_SET_ERROR(index_ + length <= puff_size_,
- Error::kInsufficientOutput);
+ TEST_AND_RETURN_FALSE(index_ + length <= puff_size_);
if (pd.type == PuffData::Type::kLiteral) {
puff_buf_out_[index_] = pd.byte;
} else {
- TEST_AND_RETURN_FALSE_SET_ERROR(
- pd.read_fn(&puff_buf_out_[index_], length),
- Error::kInsufficientInput);
+ TEST_AND_RETURN_FALSE(pd.read_fn(&puff_buf_out_[index_], length));
}
} else if (pd.type == PuffData::Type::kLiterals) {
- TEST_AND_RETURN_FALSE_SET_ERROR(pd.read_fn(nullptr, length),
- Error::kInsufficientInput);
+ TEST_AND_RETURN_FALSE(pd.read_fn(nullptr, length));
}
index_ += length;
@@ -78,22 +73,19 @@
// have total length of more than 65663 bytes for a series of literals. So
// we have to cap it at 65663 and continue afterwards.
if (cur_literals_length_ == kLiteralsMaxLength) {
- TEST_AND_RETURN_FALSE(FlushLiterals(error));
+ TEST_AND_RETURN_FALSE(FlushLiterals());
}
break;
}
case PuffData::Type::kLenDist:
DVLOG(2) << "Write length: " << pd.length << " distance: " << pd.distance;
- TEST_AND_RETURN_FALSE(FlushLiterals(error));
- TEST_AND_RETURN_FALSE_SET_ERROR(pd.length <= 258 && pd.length >= 3,
- Error::kInvalidInput);
- TEST_AND_RETURN_FALSE_SET_ERROR(pd.distance <= 32768 && pd.distance >= 1,
- Error::kInvalidInput);
+ TEST_AND_RETURN_FALSE(FlushLiterals());
+ TEST_AND_RETURN_FALSE(pd.length <= 258 && pd.length >= 3);
+ TEST_AND_RETURN_FALSE(pd.distance <= 32768 && pd.distance >= 1);
if (pd.length < 130) {
if (puff_buf_out_ != nullptr) {
// Boundary check
- TEST_AND_RETURN_FALSE_SET_ERROR(index_ + 3 <= puff_size_,
- Error::kInsufficientOutput);
+ TEST_AND_RETURN_FALSE(index_ + 3 <= puff_size_);
puff_buf_out_[index_++] =
kLenDistHeader | static_cast<uint8_t>(pd.length - 3);
@@ -103,8 +95,7 @@
} else {
if (puff_buf_out_ != nullptr) {
// Boundary check
- TEST_AND_RETURN_FALSE_SET_ERROR(index_ + 4 <= puff_size_,
- Error::kInsufficientOutput);
+ TEST_AND_RETURN_FALSE(index_ + 4 <= puff_size_);
puff_buf_out_[index_++] = kLenDistHeader | 127;
puff_buf_out_[index_++] = static_cast<uint8_t>(pd.length - 3 - 127);
@@ -124,14 +115,12 @@
case PuffData::Type::kBlockMetadata:
DVLOG(2) << "Write block metadata length: " << pd.length;
- TEST_AND_RETURN_FALSE(FlushLiterals(error));
- TEST_AND_RETURN_FALSE_SET_ERROR(
- pd.length <= sizeof(pd.block_metadata) && pd.length > 0,
- Error::kInvalidInput);
+ TEST_AND_RETURN_FALSE(FlushLiterals());
+ TEST_AND_RETURN_FALSE(pd.length <= sizeof(pd.block_metadata) &&
+ pd.length > 0);
if (puff_buf_out_ != nullptr) {
// Boundary check
- TEST_AND_RETURN_FALSE_SET_ERROR(index_ + pd.length + 2 <= puff_size_,
- Error::kInsufficientOutput);
+ TEST_AND_RETURN_FALSE(index_ + pd.length + 2 <= puff_size_);
WriteUint16ToByteArray(pd.length - 1, &puff_buf_out_[index_]);
}
@@ -147,11 +136,10 @@
case PuffData::Type::kEndOfBlock:
DVLOG(2) << "Write end of block";
- TEST_AND_RETURN_FALSE(FlushLiterals(error));
+ TEST_AND_RETURN_FALSE(FlushLiterals());
if (puff_buf_out_ != nullptr) {
// Boundary check
- TEST_AND_RETURN_FALSE_SET_ERROR(index_ + 2 <= puff_size_,
- Error::kInsufficientOutput);
+ TEST_AND_RETURN_FALSE(index_ + 2 <= puff_size_);
puff_buf_out_[index_++] = kLenDistHeader | 127;
puff_buf_out_[index_++] = static_cast<uint8_t>(259 - 3 - 127);
@@ -165,22 +153,18 @@
default:
LOG(ERROR) << "Invalid PuffData::Type";
- *error = Error::kInvalidInput;
return false;
}
- *error = Error::kSuccess;
return true;
}
-bool BufferPuffWriter::FlushLiterals(Error* error) {
+bool BufferPuffWriter::FlushLiterals() {
if (cur_literals_length_ == 0) {
return true;
}
switch (state_) {
case State::kWritingSmallLiteral:
- TEST_AND_RETURN_FALSE_SET_ERROR(
- cur_literals_length_ == (index_ - len_index_ - 1),
- Error::kInvalidInput);
+ TEST_AND_RETURN_FALSE(cur_literals_length_ == (index_ - len_index_ - 1));
if (puff_buf_out_ != nullptr) {
puff_buf_out_[len_index_] =
kLiteralsHeader | static_cast<uint8_t>(cur_literals_length_ - 1);
@@ -191,9 +175,7 @@
break;
case State::kWritingLargeLiteral:
- TEST_AND_RETURN_FALSE_SET_ERROR(
- cur_literals_length_ == (index_ - len_index_ - 3),
- Error::kInvalidInput);
+ TEST_AND_RETURN_FALSE(cur_literals_length_ == (index_ - len_index_ - 3));
if (puff_buf_out_ != nullptr) {
puff_buf_out_[len_index_++] = kLiteralsHeader | 127;
WriteUint16ToByteArray(
@@ -212,15 +194,14 @@
default:
LOG(ERROR) << "Invalid State";
- *error = Error::kInvalidInput;
return false;
}
cur_literals_length_ = 0;
return true;
}
-bool BufferPuffWriter::Flush(Error* error) {
- TEST_AND_RETURN_FALSE(FlushLiterals(error));
+bool BufferPuffWriter::Flush() {
+ TEST_AND_RETURN_FALSE(FlushLiterals());
return true;
}
diff --git a/src/puff_writer.h b/src/puff_writer.h
index 416823b..8556583 100644
--- a/src/puff_writer.h
+++ b/src/puff_writer.h
@@ -9,7 +9,6 @@
#include <cstdint>
#include "puffin/src/include/puffin/common.h"
-#include "puffin/src/include/puffin/errors.h"
#include "puffin/src/puff_data.h"
namespace puffin {
@@ -26,13 +25,12 @@
//
// |pd| IN The data to put into the puffed buffer. |pd.type|
// defines the type of the data.
- // |error| OUT The error code.
// Returns false if it fails.
- virtual bool Insert(const PuffData& pd, Error* error) = 0;
+ virtual bool Insert(const PuffData& pd) = 0;
// Fluesh any buffer or internal state to the output.
// Returns false if it fails.
- virtual bool Flush(Error* error) = 0;
+ virtual bool Flush() = 0;
// Returns the number of bytes processed and written into the puff buffer.
virtual size_t Size() = 0;
@@ -55,13 +53,13 @@
~BufferPuffWriter() override = default;
- bool Insert(const PuffData& pd, Error* error) override;
- bool Flush(Error* error) override;
+ bool Insert(const PuffData& pd) override;
+ bool Flush() override;
size_t Size() override;
private:
// Flushes the literals into the output and resets the state.
- bool FlushLiterals(Error* error);
+ bool FlushLiterals();
// The pointer to the puffed stream. This should not be deallocated.
uint8_t* puff_buf_out_;
diff --git a/src/puffdiff.cc b/src/puffdiff.cc
index 7d02085..ac2458b 100644
--- a/src/puffdiff.cc
+++ b/src/puffdiff.cc
@@ -12,23 +12,25 @@
#include <vector>
#include "bsdiff/bsdiff.h"
+#include "bsdiff/patch_writer_factory.h"
+#include "puffin/src/file_stream.h"
#include "puffin/src/include/puffin/common.h"
#include "puffin/src/include/puffin/puffer.h"
#include "puffin/src/include/puffin/puffpatch.h"
#include "puffin/src/include/puffin/utils.h"
-#include "puffin/src/file_stream.h"
+#include "puffin/src/logging.h"
#include "puffin/src/memory_stream.h"
#include "puffin/src/puffin.pb.h"
#include "puffin/src/puffin_stream.h"
-#include "puffin/src/set_errors.h"
-
-namespace puffin {
using std::string;
using std::vector;
+namespace puffin {
+
namespace {
+const int kBrotliCompressionQuality = 11;
template <typename T>
void CopyVectorToRpf(
@@ -98,6 +100,7 @@
UniqueStreamPtr dst,
const vector<BitExtent>& src_deflates,
const vector<BitExtent>& dst_deflates,
+ const std::vector<bsdiff::CompressorType>& compressors,
const string& tmp_filepath,
Buffer* patch) {
auto puffer = std::make_shared<Puffer>();
@@ -125,10 +128,13 @@
TEST_AND_RETURN_FALSE(puff_deflate_stream(std::move(dst), dst_deflates,
&dst_puff_buffer, &dst_puffs));
+ auto bsdiff_patch_writer = bsdiff::CreateBSDF2PatchWriter(
+ tmp_filepath, compressors, kBrotliCompressionQuality);
+
TEST_AND_RETURN_FALSE(
0 == bsdiff::bsdiff(src_puff_buffer.data(), src_puff_buffer.size(),
dst_puff_buffer.data(), dst_puff_buffer.size(),
- tmp_filepath.c_str(), nullptr));
+ bsdiff_patch_writer.get(), nullptr));
auto bsdiff_patch = FileStream::Open(tmp_filepath, true, false);
TEST_AND_RETURN_FALSE(bsdiff_patch);
@@ -147,13 +153,26 @@
bool PuffDiff(const Buffer& src,
const Buffer& dst,
+ const std::vector<BitExtent>& src_deflates,
+ const std::vector<BitExtent>& dst_deflates,
+ const std::vector<bsdiff::CompressorType>& compressors,
+ const std::string& tmp_filepath,
+ Buffer* patch) {
+ return PuffDiff(MemoryStream::CreateForRead(src),
+ MemoryStream::CreateForRead(dst), src_deflates, dst_deflates,
+ compressors, tmp_filepath, patch);
+}
+
+bool PuffDiff(const Buffer& src,
+ const Buffer& dst,
const vector<BitExtent>& src_deflates,
const vector<BitExtent>& dst_deflates,
const string& tmp_filepath,
Buffer* patch) {
- return PuffDiff(MemoryStream::CreateForRead(src),
- MemoryStream::CreateForRead(dst), src_deflates, dst_deflates,
- tmp_filepath, patch);
+ return PuffDiff(
+ src, dst, src_deflates, dst_deflates,
+ {bsdiff::CompressorType::kBZ2, bsdiff::CompressorType::kBrotli},
+ tmp_filepath, patch);
}
} // namespace puffin
diff --git a/src/puffer.cc b/src/puffer.cc
index 7d8a2f2..a514968 100644
--- a/src/puffer.cc
+++ b/src/puffer.cc
@@ -14,34 +14,32 @@
#include "puffin/src/huffman_table.h"
#include "puffin/src/include/puffin/common.h"
#include "puffin/src/include/puffin/stream.h"
+#include "puffin/src/logging.h"
#include "puffin/src/puff_data.h"
#include "puffin/src/puff_writer.h"
-#include "puffin/src/set_errors.h"
+
+using std::string;
+using std::vector;
namespace puffin {
-using std::vector;
-using std::string;
-
Puffer::Puffer() : dyn_ht_(new HuffmanTable()), fix_ht_(new HuffmanTable()) {}
Puffer::~Puffer() {}
bool Puffer::PuffDeflate(BitReaderInterface* br,
PuffWriterInterface* pw,
- vector<BitExtent>* deflates,
- Error* error) const {
- *error = Error::kSuccess;
+ vector<BitExtent>* deflates) const {
PuffData pd;
HuffmanTable* cur_ht;
+ bool end_loop = false;
// No bits left to read, return. We try to cache at least eight bits because
// the minimum length of a deflate bit stream is 8: (fixed huffman table) 3
// bits header + 5 bits just one len/dist symbol.
- while (br->CacheBits(8)) {
+ while (!end_loop && br->CacheBits(8)) {
auto start_bit_offset = br->OffsetInBits();
- TEST_AND_RETURN_FALSE_SET_ERROR(br->CacheBits(3),
- Error::kInsufficientInput);
+ TEST_AND_RETURN_FALSE(br->CacheBits(3));
uint8_t final_bit = br->ReadBits(1); // BFINAL
br->DropBits(1);
uint8_t type = br->ReadBits(2); // BTYPE
@@ -49,6 +47,12 @@
DVLOG(2) << "Read block type: "
<< BlockTypeToString(static_cast<BlockType>(type));
+ // If it is the final block and we are just looking for deflate locations,
+ // we consider this the end of the search.
+ if (deflates != nullptr && final_bit) {
+ end_loop = true;
+ }
+
// Header structure
// +-+-+-+-+-+-+-+-+
// |F| TP| SKIP |
@@ -61,8 +65,7 @@
case BlockType::kUncompressed: {
auto skipped_bits = br->ReadBoundaryBits();
br->SkipBoundaryBits();
- TEST_AND_RETURN_FALSE_SET_ERROR(br->CacheBits(32),
- Error::kInsufficientInput);
+ TEST_AND_RETURN_FALSE(br->CacheBits(32));
auto len = br->ReadBits(16); // LEN
br->DropBits(16);
auto nlen = br->ReadBits(16); // NLEN
@@ -71,7 +74,6 @@
if ((len ^ nlen) != 0xFFFF) {
LOG(ERROR) << "Length of uncompressed data is invalid;"
<< " LEN(" << len << ") NLEN(" << nlen << ")";
- *error = Error::kInvalidInput;
return false;
}
@@ -82,23 +84,20 @@
pd.type = PuffData::Type::kBlockMetadata;
pd.block_metadata[0] = block_header;
pd.length = 1;
- TEST_AND_RETURN_FALSE(pw->Insert(pd, error));
+ TEST_AND_RETURN_FALSE(pw->Insert(pd));
// Insert all the raw literals.
pd.type = PuffData::Type::kLiterals;
pd.length = len;
- TEST_AND_RETURN_FALSE_SET_ERROR(
- br->GetByteReaderFn(pd.length, &pd.read_fn),
- Error::kInsufficientInput);
- TEST_AND_RETURN_FALSE(pw->Insert(pd, error));
+ TEST_AND_RETURN_FALSE(br->GetByteReaderFn(pd.length, &pd.read_fn));
+ TEST_AND_RETURN_FALSE(pw->Insert(pd));
pd.type = PuffData::Type::kEndOfBlock;
- TEST_AND_RETURN_FALSE(pw->Insert(pd, error));
+ TEST_AND_RETURN_FALSE(pw->Insert(pd));
- if (deflates != nullptr) {
- deflates->emplace_back(start_bit_offset,
- br->OffsetInBits() - start_bit_offset);
- }
+ // There is no need to insert the location of uncompressed deflates
+ // because we do not want the uncompressed blocks when trying to find
+ // the bit-addressed location of deflates. They better be ignored.
// continue the loop. Do not read any literal/length/distance.
continue;
@@ -110,7 +109,7 @@
pd.type = PuffData::Type::kBlockMetadata;
pd.block_metadata[0] = block_header;
pd.length = 1;
- TEST_AND_RETURN_FALSE(pw->Insert(pd, error));
+ TEST_AND_RETURN_FALSE(pw->Insert(pd));
break;
case BlockType::kDynamic:
@@ -118,16 +117,15 @@
pd.block_metadata[0] = block_header;
pd.length = sizeof(pd.block_metadata) - 1;
TEST_AND_RETURN_FALSE(dyn_ht_->BuildDynamicHuffmanTable(
- br, &pd.block_metadata[1], &pd.length, error));
+ br, &pd.block_metadata[1], &pd.length));
pd.length += 1; // For the header.
- TEST_AND_RETURN_FALSE(pw->Insert(pd, error));
+ TEST_AND_RETURN_FALSE(pw->Insert(pd));
cur_ht = dyn_ht_.get();
break;
default:
LOG(ERROR) << "Invalid block compression type: "
<< static_cast<int>(type);
- *error = Error::kInvalidInput;
return false;
}
@@ -137,63 +135,54 @@
// It could be the end of buffer and the bit length of the end_of_block
// symbol has less than maximum bit length of current Huffman table. So
// only asking for the size of end of block symbol (256).
- TEST_AND_RETURN_FALSE_SET_ERROR(cur_ht->EndOfBlockBitLength(&max_bits),
- Error::kInvalidInput);
+ TEST_AND_RETURN_FALSE(cur_ht->EndOfBlockBitLength(&max_bits));
}
- TEST_AND_RETURN_FALSE_SET_ERROR(br->CacheBits(max_bits),
- Error::kInsufficientInput);
+ TEST_AND_RETURN_FALSE(br->CacheBits(max_bits));
auto bits = br->ReadBits(max_bits);
uint16_t lit_len_alphabet;
size_t nbits;
- TEST_AND_RETURN_FALSE_SET_ERROR(
- cur_ht->LitLenAlphabet(bits, &lit_len_alphabet, &nbits),
- Error::kInvalidInput);
+ TEST_AND_RETURN_FALSE(
+ cur_ht->LitLenAlphabet(bits, &lit_len_alphabet, &nbits));
br->DropBits(nbits);
if (lit_len_alphabet < 256) {
pd.type = PuffData::Type::kLiteral;
pd.byte = lit_len_alphabet;
- TEST_AND_RETURN_FALSE(pw->Insert(pd, error));
+ TEST_AND_RETURN_FALSE(pw->Insert(pd));
} else if (256 == lit_len_alphabet) {
pd.type = PuffData::Type::kEndOfBlock;
- TEST_AND_RETURN_FALSE(pw->Insert(pd, error));
+ TEST_AND_RETURN_FALSE(pw->Insert(pd));
if (deflates != nullptr) {
deflates->emplace_back(start_bit_offset,
br->OffsetInBits() - start_bit_offset);
}
break; // Breaks the loop.
} else {
- TEST_AND_RETURN_FALSE_SET_ERROR(lit_len_alphabet <= 285,
- Error::kInvalidInput);
+ TEST_AND_RETURN_FALSE(lit_len_alphabet <= 285);
// Reading length.
auto len_code_start = lit_len_alphabet - 257;
auto extra_bits_len = kLengthExtraBits[len_code_start];
uint16_t extra_bits_value = 0;
if (extra_bits_len) {
- TEST_AND_RETURN_FALSE_SET_ERROR(br->CacheBits(extra_bits_len),
- Error::kInsufficientInput);
+ TEST_AND_RETURN_FALSE(br->CacheBits(extra_bits_len));
extra_bits_value = br->ReadBits(extra_bits_len);
br->DropBits(extra_bits_len);
}
auto length = kLengthBases[len_code_start] + extra_bits_value;
- TEST_AND_RETURN_FALSE_SET_ERROR(
- br->CacheBits(cur_ht->DistanceMaxBits()),
- Error::kInsufficientInput);
+ TEST_AND_RETURN_FALSE(br->CacheBits(cur_ht->DistanceMaxBits()));
auto bits = br->ReadBits(cur_ht->DistanceMaxBits());
uint16_t distance_alphabet;
size_t nbits;
- TEST_AND_RETURN_FALSE_SET_ERROR(
- cur_ht->DistanceAlphabet(bits, &distance_alphabet, &nbits),
- Error::kInvalidInput);
+ TEST_AND_RETURN_FALSE(
+ cur_ht->DistanceAlphabet(bits, &distance_alphabet, &nbits));
br->DropBits(nbits);
// Reading distance.
extra_bits_len = kDistanceExtraBits[distance_alphabet];
extra_bits_value = 0;
if (extra_bits_len) {
- TEST_AND_RETURN_FALSE_SET_ERROR(br->CacheBits(extra_bits_len),
- Error::kInsufficientInput);
+ TEST_AND_RETURN_FALSE(br->CacheBits(extra_bits_len));
extra_bits_value = br->ReadBits(extra_bits_len);
br->DropBits(extra_bits_len);
}
@@ -201,11 +190,11 @@
pd.type = PuffData::Type::kLenDist;
pd.length = length;
pd.distance = kDistanceBases[distance_alphabet] + extra_bits_value;
- TEST_AND_RETURN_FALSE(pw->Insert(pd, error));
+ TEST_AND_RETURN_FALSE(pw->Insert(pd));
}
}
}
- TEST_AND_RETURN_FALSE(pw->Flush(error));
+ TEST_AND_RETURN_FALSE(pw->Flush());
return true;
}
diff --git a/src/puffin_stream.cc b/src/puffin_stream.cc
index 05dd7f6..91d0dd7 100644
--- a/src/puffin_stream.cc
+++ b/src/puffin_stream.cc
@@ -16,16 +16,16 @@
#include "puffin/src/include/puffin/huffer.h"
#include "puffin/src/include/puffin/puffer.h"
#include "puffin/src/include/puffin/stream.h"
+#include "puffin/src/logging.h"
#include "puffin/src/puff_reader.h"
#include "puffin/src/puff_writer.h"
-#include "puffin/src/set_errors.h"
+
+using std::shared_ptr;
+using std::unique_ptr;
+using std::vector;
namespace puffin {
-using std::vector;
-using std::unique_ptr;
-using std::shared_ptr;
-
namespace {
bool CheckArgsIntegrity(uint64_t puff_size,
@@ -288,9 +288,8 @@
TEST_AND_RETURN_FALSE(bit_reader.CacheBits(extra_bits_len));
bit_reader.DropBits(extra_bits_len);
- Error error;
TEST_AND_RETURN_FALSE(
- puffer_->PuffDeflate(&bit_reader, &puff_writer, nullptr, &error));
+ puffer_->PuffDeflate(&bit_reader, &puff_writer, nullptr));
TEST_AND_RETURN_FALSE(bytes_to_read == bit_reader.Offset());
TEST_AND_RETURN_FALSE(cur_puff_->length == puff_writer.Size());
} else {
@@ -385,9 +384,7 @@
bit_writer.WriteBits(cur_deflate_->offset & 7, last_byte_));
last_byte_ = 0;
- Error error;
- TEST_AND_RETURN_FALSE(
- huffer_->HuffDeflate(&puff_reader, &bit_writer, &error));
+ TEST_AND_RETURN_FALSE(huffer_->HuffDeflate(&puff_reader, &bit_writer));
TEST_AND_RETURN_FALSE(bit_writer.Size() == bytes_to_write);
TEST_AND_RETURN_FALSE(puff_reader.BytesLeft() == 0);
diff --git a/src/puffin_unittest.cc b/src/puffin_unittest.cc
index fd035bc..2ccf23f 100644
--- a/src/puffin_unittest.cc
+++ b/src/puffin_unittest.cc
@@ -14,18 +14,27 @@
#include "puffin/src/include/puffin/huffer.h"
#include "puffin/src/include/puffin/puffer.h"
#include "puffin/src/include/puffin/utils.h"
+#include "puffin/src/logging.h"
#include "puffin/src/memory_stream.h"
#include "puffin/src/puff_reader.h"
#include "puffin/src/puff_writer.h"
#include "puffin/src/puffin_stream.h"
-#include "puffin/src/sample_generator.h"
-#include "puffin/src/set_errors.h"
#include "puffin/src/unittest_common.h"
+using std::string;
+using std::vector;
+
namespace puffin {
-using std::vector;
-using std::string;
+namespace {
+
+// Uncompressed deflate block.
+const Buffer kRawEmpty = {};
+const Buffer kRaw1 = {0x01};
+const Buffer kRaw2 = {0x01, 0x01};
+const Buffer kRaw5 = {0x01, 0x02, 0x03, 0x04, 0x05};
+
+} // namespace
class PuffinTest : public ::testing::Test {
public:
@@ -39,13 +48,13 @@
auto start = static_cast<uint8_t*>(out_buf);
PuffData pd;
- Error error;
while (puff_reader.BytesLeft() != 0) {
- TEST_AND_RETURN_FALSE(puff_reader.GetNext(&pd, &error));
+ TEST_AND_RETURN_FALSE(puff_reader.GetNext(&pd));
switch (pd.type) {
case PuffData::Type::kLiteral:
*start = pd.byte;
start++;
+ FALLTHROUGH_INTENDED;
case PuffData::Type::kLiterals:
pd.read_fn(start, pd.length);
@@ -79,34 +88,27 @@
bool PuffDeflate(const uint8_t* comp_buf,
size_t comp_size,
uint8_t* puff_buf,
- size_t puff_size,
- Error* error) const {
+ size_t puff_size) const {
BufferBitReader bit_reader(comp_buf, comp_size);
BufferPuffWriter puff_writer(puff_buf, puff_size);
TEST_AND_RETURN_FALSE(
- puffer_.PuffDeflate(&bit_reader, &puff_writer, nullptr, error));
- TEST_AND_RETURN_FALSE_SET_ERROR(comp_size == bit_reader.Offset(),
- Error::kInvalidInput);
- TEST_AND_RETURN_FALSE_SET_ERROR(puff_size == puff_writer.Size(),
- Error::kInvalidInput);
+ puffer_.PuffDeflate(&bit_reader, &puff_writer, nullptr));
+ TEST_AND_RETURN_FALSE(comp_size == bit_reader.Offset());
+ TEST_AND_RETURN_FALSE(puff_size == puff_writer.Size());
return true;
}
bool HuffDeflate(const uint8_t* puff_buf,
size_t puff_size,
uint8_t* comp_buf,
- size_t comp_size,
- Error* error) const {
+ size_t comp_size) const {
BufferPuffReader puff_reader(puff_buf, puff_size);
BufferBitWriter bit_writer(comp_buf, comp_size);
- TEST_AND_RETURN_FALSE(
- huffer_.HuffDeflate(&puff_reader, &bit_writer, error));
- TEST_AND_RETURN_FALSE_SET_ERROR(comp_size == bit_writer.Size(),
- Error::kInvalidInput);
- TEST_AND_RETURN_FALSE_SET_ERROR(puff_reader.BytesLeft() == 0,
- Error::kInvalidInput);
+ TEST_AND_RETURN_FALSE(huffer_.HuffDeflate(&puff_reader, &bit_writer));
+ TEST_AND_RETURN_FALSE(comp_size == bit_writer.Size());
+ TEST_AND_RETURN_FALSE(puff_reader.BytesLeft() == 0);
return true;
}
@@ -118,25 +120,20 @@
out_puff->resize(expected_puff.size());
auto comp_size = compressed.size();
auto puff_size = out_puff->size();
- Error error;
- ASSERT_TRUE(PuffDeflate(compressed.data(), comp_size, out_puff->data(),
- puff_size, &error));
+ ASSERT_TRUE(
+ PuffDeflate(compressed.data(), comp_size, out_puff->data(), puff_size));
ASSERT_EQ(puff_size, expected_puff.size());
out_puff->resize(puff_size);
ASSERT_EQ(expected_puff, *out_puff);
}
// Should fail when trying to puff |compressed|.
- void FailPuffDeflate(const Buffer& compressed,
- Error expected_error,
- Buffer* out_puff) {
+ void FailPuffDeflate(const Buffer& compressed, Buffer* out_puff) {
out_puff->resize(compressed.size() * 2 + 10);
auto comp_size = compressed.size();
auto puff_size = out_puff->size();
- Error error;
- ASSERT_FALSE(PuffDeflate(compressed.data(), comp_size, out_puff->data(),
- puff_size, &error));
- ASSERT_EQ(error, expected_error);
+ ASSERT_FALSE(
+ PuffDeflate(compressed.data(), comp_size, out_puff->data(), puff_size));
}
// Huffs |puffed| into |out_huff| and checks its equality with
@@ -147,23 +144,18 @@
out_huff->resize(expected_huff.size());
auto huff_size = out_huff->size();
auto puffed_size = puffed.size();
- Error error;
- ASSERT_TRUE(HuffDeflate(puffed.data(), puffed_size, out_huff->data(),
- huff_size, &error));
+ ASSERT_TRUE(
+ HuffDeflate(puffed.data(), puffed_size, out_huff->data(), huff_size));
ASSERT_EQ(expected_huff, *out_huff);
}
// Should fail while huffing |puffed|
- void FailHuffDeflate(const Buffer& puffed,
- Error expected_error,
- Buffer* out_compress) {
+ void FailHuffDeflate(const Buffer& puffed, Buffer* out_compress) {
out_compress->resize(puffed.size());
auto comp_size = out_compress->size();
auto puff_size = puffed.size();
- Error error;
- ASSERT_TRUE(HuffDeflate(puffed.data(), puff_size, out_compress->data(),
- comp_size, &error));
- ASSERT_EQ(error, expected_error);
+ ASSERT_TRUE(
+ HuffDeflate(puffed.data(), puff_size, out_compress->data(), comp_size));
}
// Decompresses from |puffed| into |uncompress| and checks its equality with
@@ -174,8 +166,8 @@
uncompress->resize(original.size());
auto uncomp_size = uncompress->size();
auto puffed_size = puffed.size();
- ASSERT_TRUE(DecompressPuff(
- puffed.data(), &puffed_size, uncompress->data(), &uncomp_size));
+ ASSERT_TRUE(DecompressPuff(puffed.data(), &puffed_size, uncompress->data(),
+ &uncomp_size));
ASSERT_EQ(puffed_size, puffed.size());
ASSERT_EQ(uncomp_size, original.size());
uncompress->resize(uncomp_size);
@@ -234,76 +226,352 @@
// Tests a simple buffer with uncompressed deflate block.
TEST_F(PuffinTest, UncompressedTest) {
- CheckSample(kRaw1, kDeflate1, kPuff1);
+ const Buffer kDeflate = {0x01, 0x05, 0x00, 0xFA, 0xFF,
+ 0x01, 0x02, 0x03, 0x04, 0x05};
+ const Buffer kPuff = {0x00, 0x00, 0x80, 0x04, 0x01, 0x02,
+ 0x03, 0x04, 0x05, 0xFF, 0x81};
+ CheckSample(kRaw5, kDeflate, kPuff);
}
// Tests a simple buffer with uncompressed deflate block with length zero.
TEST_F(PuffinTest, ZeroLengthUncompressedTest) {
- CheckSample(kRaw1_1, kDeflate1_1, kPuff1_1);
+ const Buffer kDeflate = {0x01, 0x00, 0x00, 0xFF, 0xFF};
+ const Buffer kPuff = {0x00, 0x00, 0x80, 0xFF, 0x81};
+ CheckSample(kRawEmpty, kDeflate, kPuff);
}
-// Tests a dynamically compressed buffer with only one literal.
-TEST_F(PuffinTest, CompressedOneTest) {
- CheckSample(kRaw2, kDeflate2, kPuff2);
+// Tests a Fixed Huffman table compressed buffer with only one literal.
+TEST_F(PuffinTest, OneLiteralFixedHuffmanTableTest) {
+ const Buffer kDeflate = {0x63, 0x04, 0x00};
+ const Buffer kPuff = {0x00, 0x00, 0xA0, 0x00, 0x01, 0xFF, 0x81};
+ CheckSample(kRaw1, kDeflate, kPuff);
}
// Tests deflate of an empty buffer.
TEST_F(PuffinTest, EmptyTest) {
- CheckSample(kRaw3, kDeflate3, kPuff3);
+ const Buffer kDeflate = {0x03, 0x00};
+ const Buffer kPuff = {0x00, 0x00, 0xA0, 0xFF, 0x81};
+ CheckSample(kRawEmpty, kDeflate, kPuff);
}
// Tests a simple buffer with compress deflate block using fixed Huffman table.
-TEST_F(PuffinTest, FixedCompressedTest) {
- CheckSample(kRaw4, kDeflate4, kPuff4);
+TEST_F(PuffinTest, FixedHuffmanTableCompressedTest) {
+ const Buffer kDeflate = {0x63, 0x64, 0x62, 0x66, 0x61, 0x05, 0x00};
+ const Buffer kPuff = {0x00, 0x00, 0xA0, 0x04, 0x01, 0x02,
+ 0x03, 0x04, 0x05, 0xFF, 0x81};
+ CheckSample(kRaw5, kDeflate, kPuff);
}
+// Tests that uncompressed deflate blocks are not ignored when the output
+// deflate location pointer is null.
+TEST_F(PuffinTest, NoIgnoreUncompressedBlocksTest) {
+ const Buffer kDeflate = {0x01, 0x05, 0x00, 0xFA, 0xFF,
+ 0x01, 0x02, 0x03, 0x04, 0x05};
+ BufferBitReader bit_reader(kDeflate.data(), kDeflate.size());
+ Buffer puff_buffer(11); // Same size as |uncomp_puff| below.
+ BufferPuffWriter puff_writer(puff_buffer.data(), puff_buffer.size());
+ vector<BitExtent> deflates;
+ EXPECT_TRUE(puffer_.PuffDeflate(&bit_reader, &puff_writer, nullptr));
+ const Buffer kPuff = {0x00, 0x00, 0x80, 0x04, 0x01, 0x02,
+ 0x03, 0x04, 0x05, 0xFF, 0x81};
+ EXPECT_EQ(puff_writer.Size(), kPuff.size());
+ EXPECT_EQ(puff_buffer, kPuff);
+}
+
+// Tests that uncompressed deflate blocks are ignored when the output
+// deflate location pointer is valid.
+TEST_F(PuffinTest, IgnoreUncompressedBlocksTest) {
+ const Buffer kDeflate = {0x01, 0x05, 0x00, 0xFA, 0xFF,
+ 0x01, 0x02, 0x03, 0x04, 0x05};
+ BufferBitReader bit_reader(kDeflate.data(), kDeflate.size());
+ BufferPuffWriter puff_writer(nullptr, 0);
+ vector<BitExtent> deflates;
+ EXPECT_TRUE(puffer_.PuffDeflate(&bit_reader, &puff_writer, &deflates));
+ EXPECT_TRUE(deflates.empty());
+}
+
+namespace {
+// It is actuall the content of the copyright header.
+const Buffer kDynamicHTRaw = {
+ 0x0A, 0x2F, 0x2F, 0x0A, 0x2F, 0x2F, 0x20, 0x43, 0x6F, 0x70, 0x79, 0x72,
+ 0x69, 0x67, 0x68, 0x74, 0x20, 0x28, 0x43, 0x29, 0x20, 0x32, 0x30, 0x31,
+ 0x37, 0x20, 0x54, 0x68, 0x65, 0x20, 0x41, 0x6E, 0x64, 0x72, 0x6F, 0x69,
+ 0x64, 0x20, 0x4F, 0x70, 0x65, 0x6E, 0x20, 0x53, 0x6F, 0x75, 0x72, 0x63,
+ 0x65, 0x20, 0x50, 0x72, 0x6F, 0x6A, 0x65, 0x63, 0x74, 0x0A, 0x2F, 0x2F,
+ 0x0A, 0x2F, 0x2F, 0x20, 0x4C, 0x69, 0x63, 0x65, 0x6E, 0x73, 0x65, 0x64,
+ 0x20, 0x75, 0x6E, 0x64, 0x65, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x41,
+ 0x70, 0x61, 0x63, 0x68, 0x65, 0x20, 0x4C, 0x69, 0x63, 0x65, 0x6E, 0x73,
+ 0x65, 0x2C, 0x20, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6F, 0x6E, 0x20, 0x32,
+ 0x2E, 0x30, 0x20, 0x28, 0x74, 0x68, 0x65, 0x20, 0x22, 0x4C, 0x69, 0x63,
+ 0x65, 0x6E, 0x73, 0x65, 0x22, 0x29, 0x3B, 0x0A, 0x2F, 0x2F, 0x20, 0x79,
+ 0x6F, 0x75, 0x20, 0x6D, 0x61, 0x79, 0x20, 0x6E, 0x6F, 0x74, 0x20, 0x75,
+ 0x73, 0x65, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x66, 0x69, 0x6C, 0x65,
+ 0x20, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x69, 0x6E, 0x20, 0x63,
+ 0x6F, 0x6D, 0x70, 0x6C, 0x69, 0x61, 0x6E, 0x63, 0x65, 0x20, 0x77, 0x69,
+ 0x74, 0x68, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4C, 0x69, 0x63, 0x65, 0x6E,
+ 0x73, 0x65, 0x2E, 0x0A, 0x2F, 0x2F, 0x20, 0x59, 0x6F, 0x75, 0x20, 0x6D,
+ 0x61, 0x79, 0x20, 0x6F, 0x62, 0x74, 0x61, 0x69, 0x6E, 0x20, 0x61, 0x20,
+ 0x63, 0x6F, 0x70, 0x79, 0x20, 0x6F, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x4C, 0x69, 0x63, 0x65, 0x6E, 0x73, 0x65, 0x20, 0x61, 0x74, 0x0A, 0x2F,
+ 0x2F, 0x0A, 0x2F, 0x2F, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x68, 0x74,
+ 0x74, 0x70, 0x3A, 0x2F, 0x2F, 0x77, 0x77, 0x77, 0x2E, 0x61, 0x70, 0x61,
+ 0x63, 0x68, 0x65, 0x2E, 0x6F, 0x72, 0x67, 0x2F, 0x6C, 0x69, 0x63, 0x65,
+ 0x6E, 0x73, 0x65, 0x73, 0x2F, 0x4C, 0x49, 0x43, 0x45, 0x4E, 0x53, 0x45,
+ 0x2D, 0x32, 0x2E, 0x30, 0x0A, 0x2F, 0x2F, 0x0A, 0x2F, 0x2F, 0x20, 0x55,
+ 0x6E, 0x6C, 0x65, 0x73, 0x73, 0x20, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72,
+ 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x61, 0x70, 0x70, 0x6C, 0x69, 0x63,
+ 0x61, 0x62, 0x6C, 0x65, 0x20, 0x6C, 0x61, 0x77, 0x20, 0x6F, 0x72, 0x20,
+ 0x61, 0x67, 0x72, 0x65, 0x65, 0x64, 0x20, 0x74, 0x6F, 0x20, 0x69, 0x6E,
+ 0x20, 0x77, 0x72, 0x69, 0x74, 0x69, 0x6E, 0x67, 0x2C, 0x20, 0x73, 0x6F,
+ 0x66, 0x74, 0x77, 0x61, 0x72, 0x65, 0x0A, 0x2F, 0x2F, 0x20, 0x64, 0x69,
+ 0x73, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x64, 0x20, 0x75, 0x6E,
+ 0x64, 0x65, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4C, 0x69, 0x63, 0x65,
+ 0x6E, 0x73, 0x65, 0x20, 0x69, 0x73, 0x20, 0x64, 0x69, 0x73, 0x74, 0x72,
+ 0x69, 0x62, 0x75, 0x74, 0x65, 0x64, 0x20, 0x6F, 0x6E, 0x20, 0x61, 0x6E,
+ 0x20, 0x22, 0x41, 0x53, 0x20, 0x49, 0x53, 0x22, 0x20, 0x42, 0x41, 0x53,
+ 0x49, 0x53, 0x2C, 0x0A, 0x2F, 0x2F, 0x20, 0x57, 0x49, 0x54, 0x48, 0x4F,
+ 0x55, 0x54, 0x20, 0x57, 0x41, 0x52, 0x52, 0x41, 0x4E, 0x54, 0x49, 0x45,
+ 0x53, 0x20, 0x4F, 0x52, 0x20, 0x43, 0x4F, 0x4E, 0x44, 0x49, 0x54, 0x49,
+ 0x4F, 0x4E, 0x53, 0x20, 0x4F, 0x46, 0x20, 0x41, 0x4E, 0x59, 0x20, 0x4B,
+ 0x49, 0x4E, 0x44, 0x2C, 0x20, 0x65, 0x69, 0x74, 0x68, 0x65, 0x72, 0x20,
+ 0x65, 0x78, 0x70, 0x72, 0x65, 0x73, 0x73, 0x20, 0x6F, 0x72, 0x20, 0x69,
+ 0x6D, 0x70, 0x6C, 0x69, 0x65, 0x64, 0x2E, 0x0A, 0x2F, 0x2F, 0x20, 0x53,
+ 0x65, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4C, 0x69, 0x63, 0x65, 0x6E,
+ 0x73, 0x65, 0x20, 0x66, 0x6F, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73,
+ 0x70, 0x65, 0x63, 0x69, 0x66, 0x69, 0x63, 0x20, 0x6C, 0x61, 0x6E, 0x67,
+ 0x75, 0x61, 0x67, 0x65, 0x20, 0x67, 0x6F, 0x76, 0x65, 0x72, 0x6E, 0x69,
+ 0x6E, 0x67, 0x20, 0x70, 0x65, 0x72, 0x6D, 0x69, 0x73, 0x73, 0x69, 0x6F,
+ 0x6E, 0x73, 0x20, 0x61, 0x6E, 0x64, 0x0A, 0x2F, 0x2F, 0x20, 0x6C, 0x69,
+ 0x6D, 0x69, 0x74, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x73, 0x20, 0x75, 0x6E,
+ 0x64, 0x65, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4C, 0x69, 0x63, 0x65,
+ 0x6E, 0x73, 0x65, 0x2E, 0x0A};
+
+// Dynamic huffman compressed deflate.
+const Buffer kDynamicHTDeflate = {
+ 0x65, 0x91, 0x41, 0x6F, 0x9C, 0x30, 0x10, 0x85, 0xEF, 0xFB, 0x2B, 0x9E,
+ 0xF6, 0x94, 0x48, 0x5B, 0x48, 0x73, 0xA9, 0xD4, 0x9E, 0xE8, 0x66, 0xAB,
+ 0xA0, 0x46, 0x50, 0x2D, 0xA4, 0x51, 0x8E, 0x5E, 0x18, 0xD8, 0x89, 0x58,
+ 0xDB, 0xB5, 0x4D, 0xC9, 0xFE, 0xFB, 0x8E, 0x59, 0x22, 0x25, 0xAA, 0x2F,
+ 0xC8, 0xCC, 0xCC, 0x9B, 0xEF, 0x3D, 0xAF, 0xD2, 0x74, 0x95, 0xA6, 0xD8,
+ 0x1A, 0x7B, 0x76, 0xDC, 0x1F, 0x03, 0xAE, 0xB6, 0xD7, 0xB8, 0xBD, 0xF9,
+ 0xFC, 0x05, 0xF5, 0x91, 0x90, 0xE9, 0xD6, 0x19, 0x6E, 0x51, 0x5A, 0xD2,
+ 0xA8, 0xCC, 0xE8, 0x1A, 0xC2, 0x2F, 0x67, 0x5E, 0xA8, 0x09, 0xAB, 0xCB,
+ 0xE0, 0x03, 0x37, 0xA4, 0x3D, 0xB5, 0x18, 0x75, 0x4B, 0x0E, 0x21, 0x0E,
+ 0x59, 0xD5, 0xC8, 0x67, 0xA9, 0x6C, 0xF0, 0x9B, 0x9C, 0x67, 0xA3, 0x71,
+ 0x9B, 0xDC, 0xE0, 0x2A, 0x36, 0xAC, 0x97, 0xD2, 0xFA, 0xFA, 0x5B, 0x94,
+ 0x38, 0x9B, 0x11, 0x27, 0x75, 0x86, 0x36, 0x01, 0xA3, 0x27, 0xD1, 0x60,
+ 0x8F, 0x8E, 0x07, 0x02, 0xBD, 0x36, 0x64, 0x03, 0x58, 0xA3, 0x31, 0x27,
+ 0x3B, 0xB0, 0xD2, 0xB2, 0x7F, 0xE2, 0x70, 0x9C, 0xF7, 0x2C, 0x2A, 0x49,
+ 0xD4, 0x78, 0x5E, 0x34, 0xCC, 0x21, 0x28, 0x69, 0x57, 0x32, 0x60, 0xE5,
+ 0xD6, 0xBD, 0x6F, 0x84, 0x7A, 0x83, 0x9E, 0xCF, 0x31, 0x04, 0xFB, 0x35,
+ 0x4D, 0xA7, 0x69, 0x4A, 0xD4, 0x4C, 0x9C, 0x18, 0xD7, 0xA7, 0xC3, 0xA5,
+ 0xD7, 0xA7, 0x0F, 0xF9, 0x76, 0x57, 0x54, 0xBB, 0x4F, 0x42, 0xBD, 0x4C,
+ 0x3D, 0xEA, 0x81, 0xBC, 0x87, 0xA3, 0x3F, 0x23, 0x3B, 0x71, 0x7C, 0x38,
+ 0x43, 0x59, 0xA1, 0x6A, 0xD4, 0x41, 0x58, 0x07, 0x35, 0xC1, 0x38, 0xA8,
+ 0xDE, 0x91, 0xD4, 0x82, 0x89, 0xD4, 0x93, 0xE3, 0xC0, 0xBA, 0xDF, 0xC0,
+ 0x9B, 0x2E, 0x4C, 0xCA, 0x51, 0x94, 0x69, 0xD9, 0x07, 0xC7, 0x87, 0x31,
+ 0x7C, 0x08, 0xED, 0x8D, 0x51, 0xAC, 0xBF, 0x6F, 0x90, 0xD8, 0x94, 0xC6,
+ 0x3A, 0xAB, 0x90, 0x57, 0x6B, 0x7C, 0xCF, 0xAA, 0xBC, 0xDA, 0x44, 0x91,
+ 0xA7, 0xBC, 0xBE, 0x2F, 0x1F, 0x6B, 0x3C, 0x65, 0xFB, 0x7D, 0x56, 0xD4,
+ 0xF9, 0xAE, 0x42, 0xB9, 0xC7, 0xB6, 0x2C, 0xEE, 0xF2, 0x3A, 0x2F, 0x0B,
+ 0xB9, 0xFD, 0x40, 0x56, 0x3C, 0xE3, 0x67, 0x5E, 0xDC, 0x6D, 0x40, 0x12,
+ 0x99, 0xEC, 0xA1, 0x57, 0xEB, 0xA2, 0x03, 0xC1, 0xE4, 0x18, 0x27, 0xB5,
+ 0x73, 0x76, 0x15, 0xD1, 0x07, 0x84, 0xCE, 0x5C, 0x90, 0xBC, 0xA5, 0x86,
+ 0x3B, 0x6E, 0xC4, 0x9A, 0xEE, 0x47, 0xD5, 0x13, 0x7A, 0xF3, 0x97, 0x9C,
+ 0x16, 0x47, 0xB0, 0xE4, 0x4E, 0xEC, 0xE3, 0xB3, 0x7A, 0x01, 0x6C, 0xA3,
+ 0xCC, 0xC0, 0x27, 0x0E, 0x2A, 0xCC, 0xBF, 0xFE, 0xF3, 0x95, 0xAC, 0xFE,
+ 0x01};
+
+const Buffer kDynamicHTPuff = {
+ 0x00, 0x74, 0xC0, 0x0C, 0x11, 0x0C, 0x04, 0x63, 0x34, 0x32, 0x03, 0x04,
+ 0x05, 0x06, 0x1B, 0x07, 0x26, 0x03, 0x00, 0x07, 0x16, 0x08, 0x08, 0x00,
+ 0x00, 0x07, 0x09, 0x06, 0x06, 0x08, 0x09, 0x08, 0x15, 0x09, 0x00, 0x00,
+ 0x09, 0x09, 0x16, 0x06, 0x09, 0x07, 0x08, 0x07, 0x09, 0x00, 0x08, 0x06,
+ 0x00, 0x09, 0x08, 0x00, 0x06, 0x06, 0x09, 0x00, 0x07, 0x06, 0x06, 0x08,
+ 0x09, 0x08, 0x00, 0x08, 0x18, 0x05, 0x07, 0x06, 0x06, 0x04, 0x06, 0x06,
+ 0x07, 0x04, 0x08, 0x00, 0x06, 0x07, 0x05, 0x05, 0x05, 0x09, 0x05, 0x05,
+ 0x05, 0x06, 0x09, 0x06, 0x08, 0x07, 0x97, 0x09, 0x04, 0x05, 0x06, 0x07,
+ 0x06, 0x08, 0x00, 0x00, 0x08, 0x08, 0x00, 0x09, 0x05, 0x15, 0x06, 0x00,
+ 0x05, 0x06, 0x04, 0x04, 0x04, 0x03, 0x04, 0x02, 0x03, 0x03, 0x05, 0x39,
+ 0x0A, 0x2F, 0x2F, 0x0A, 0x2F, 0x2F, 0x20, 0x43, 0x6F, 0x70, 0x79, 0x72,
+ 0x69, 0x67, 0x68, 0x74, 0x20, 0x28, 0x43, 0x29, 0x20, 0x32, 0x30, 0x31,
+ 0x37, 0x20, 0x54, 0x68, 0x65, 0x20, 0x41, 0x6E, 0x64, 0x72, 0x6F, 0x69,
+ 0x64, 0x20, 0x4F, 0x70, 0x65, 0x6E, 0x20, 0x53, 0x6F, 0x75, 0x72, 0x63,
+ 0x65, 0x20, 0x50, 0x72, 0x6F, 0x6A, 0x65, 0x63, 0x74, 0x0A, 0x83, 0x00,
+ 0x38, 0x0F, 0x4C, 0x69, 0x63, 0x65, 0x6E, 0x73, 0x65, 0x64, 0x20, 0x75,
+ 0x6E, 0x64, 0x65, 0x72, 0x20, 0x74, 0x81, 0x00, 0x34, 0x02, 0x70, 0x61,
+ 0x63, 0x80, 0x00, 0x06, 0x84, 0x00, 0x19, 0x0E, 0x2C, 0x20, 0x56, 0x65,
+ 0x72, 0x73, 0x69, 0x6F, 0x6E, 0x20, 0x32, 0x2E, 0x30, 0x20, 0x28, 0x81,
+ 0x00, 0x20, 0x00, 0x22, 0x84, 0x00, 0x1A, 0x02, 0x22, 0x29, 0x3B, 0x81,
+ 0x00, 0x42, 0x0E, 0x79, 0x6F, 0x75, 0x20, 0x6D, 0x61, 0x79, 0x20, 0x6E,
+ 0x6F, 0x74, 0x20, 0x75, 0x73, 0x65, 0x80, 0x00, 0x43, 0x19, 0x69, 0x73,
+ 0x20, 0x66, 0x69, 0x6C, 0x65, 0x20, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74,
+ 0x20, 0x69, 0x6E, 0x20, 0x63, 0x6F, 0x6D, 0x70, 0x6C, 0x69, 0x61, 0x6E,
+ 0x80, 0x00, 0x7F, 0x03, 0x77, 0x69, 0x74, 0x68, 0x82, 0x00, 0x67, 0x84,
+ 0x00, 0x45, 0x00, 0x2E, 0x81, 0x00, 0x43, 0x00, 0x59, 0x84, 0x00, 0x43,
+ 0x03, 0x6F, 0x62, 0x74, 0x61, 0x80, 0x00, 0x2E, 0x00, 0x61, 0x80, 0x00,
+ 0x30, 0x00, 0x70, 0x80, 0x00, 0x0D, 0x00, 0x66, 0x89, 0x00, 0x28, 0x01,
+ 0x20, 0x61, 0x85, 0x00, 0xB4, 0x82, 0x00, 0x00, 0x0B, 0x68, 0x74, 0x74,
+ 0x70, 0x3A, 0x2F, 0x2F, 0x77, 0x77, 0x77, 0x2E, 0x61, 0x82, 0x00, 0xB1,
+ 0x05, 0x2E, 0x6F, 0x72, 0x67, 0x2F, 0x6C, 0x83, 0x00, 0x2B, 0x09, 0x73,
+ 0x2F, 0x4C, 0x49, 0x43, 0x45, 0x4E, 0x53, 0x45, 0x2D, 0x80, 0x00, 0xB5,
+ 0x84, 0x00, 0x35, 0x0C, 0x55, 0x6E, 0x6C, 0x65, 0x73, 0x73, 0x20, 0x72,
+ 0x65, 0x71, 0x75, 0x69, 0x72, 0x80, 0x00, 0xF1, 0x04, 0x62, 0x79, 0x20,
+ 0x61, 0x70, 0x80, 0x00, 0x95, 0x02, 0x63, 0x61, 0x62, 0x80, 0x00, 0xAB,
+ 0x0A, 0x6C, 0x61, 0x77, 0x20, 0x6F, 0x72, 0x20, 0x61, 0x67, 0x72, 0x65,
+ 0x80, 0x00, 0x1B, 0x01, 0x74, 0x6F, 0x81, 0x00, 0xB5, 0x10, 0x77, 0x72,
+ 0x69, 0x74, 0x69, 0x6E, 0x67, 0x2C, 0x20, 0x73, 0x6F, 0x66, 0x74, 0x77,
+ 0x61, 0x72, 0x65, 0x81, 0x00, 0x46, 0x08, 0x64, 0x69, 0x73, 0x74, 0x72,
+ 0x69, 0x62, 0x75, 0x74, 0x8A, 0x01, 0x34, 0x85, 0x00, 0xA3, 0x80, 0x00,
+ 0xFA, 0x89, 0x00, 0x20, 0x80, 0x01, 0x36, 0x10, 0x61, 0x6E, 0x20, 0x22,
+ 0x41, 0x53, 0x20, 0x49, 0x53, 0x22, 0x20, 0x42, 0x41, 0x53, 0x49, 0x53,
+ 0x2C, 0x81, 0x00, 0x44, 0x1E, 0x57, 0x49, 0x54, 0x48, 0x4F, 0x55, 0x54,
+ 0x20, 0x57, 0x41, 0x52, 0x52, 0x41, 0x4E, 0x54, 0x49, 0x45, 0x53, 0x20,
+ 0x4F, 0x52, 0x20, 0x43, 0x4F, 0x4E, 0x44, 0x49, 0x54, 0x49, 0x4F, 0x4E,
+ 0x80, 0x00, 0x0D, 0x0C, 0x46, 0x20, 0x41, 0x4E, 0x59, 0x20, 0x4B, 0x49,
+ 0x4E, 0x44, 0x2C, 0x20, 0x65, 0x80, 0x01, 0x32, 0x80, 0x00, 0x67, 0x03,
+ 0x65, 0x78, 0x70, 0x72, 0x81, 0x00, 0xC1, 0x80, 0x00, 0xA6, 0x00, 0x69,
+ 0x81, 0x01, 0x4E, 0x01, 0x65, 0x64, 0x82, 0x01, 0x3B, 0x02, 0x53, 0x65,
+ 0x65, 0x8A, 0x00, 0x82, 0x01, 0x66, 0x6F, 0x83, 0x00, 0x92, 0x07, 0x73,
+ 0x70, 0x65, 0x63, 0x69, 0x66, 0x69, 0x63, 0x80, 0x00, 0xDA, 0x0C, 0x6E,
+ 0x67, 0x75, 0x61, 0x67, 0x65, 0x20, 0x67, 0x6F, 0x76, 0x65, 0x72, 0x6E,
+ 0x80, 0x00, 0xD1, 0x06, 0x20, 0x70, 0x65, 0x72, 0x6D, 0x69, 0x73, 0x81,
+ 0x01, 0xD6, 0x00, 0x73, 0x80, 0x00, 0xA0, 0x00, 0x64, 0x81, 0x00, 0x46,
+ 0x06, 0x6C, 0x69, 0x6D, 0x69, 0x74, 0x61, 0x74, 0x82, 0x00, 0x12, 0x8E,
+ 0x00, 0xD7, 0x01, 0x2E, 0x0A, 0xFF, 0x81};
+} // namespace
+
// Tests a compressed deflate block using dynamic Huffman table.
-TEST_F(PuffinTest, DynamicHuffmanTest) {
- CheckSample(kRaw10, kDeflate10, kPuff10);
+TEST_F(PuffinTest, DynamicHuffmanTableTest) {
+ CheckSample(kDynamicHTRaw, kDynamicHTDeflate, kDynamicHTPuff);
}
// Tests an uncompressed deflate block with invalid LEN/NLEN.
-TEST_F(PuffinTest, PuffDeflateFailedTest) {
+TEST_F(PuffinTest, PuffInvalidUncompressedLengthDeflateTest) {
+ const Buffer kDeflate = {0x01, 0x05, 0x00, 0xFF, 0xFF,
+ 0x01, 0x02, 0x03, 0x04, 0x05};
Buffer puffed;
- FailPuffDeflate(kDeflate5, Error::kInvalidInput, &puffed);
+ FailPuffDeflate(kDeflate, &puffed);
}
// Tests puffing a block with invalid block header.
-TEST_F(PuffinTest, PuffDeflateHeaderFailedTest) {
+TEST_F(PuffinTest, PuffInvalidBlockHeaderDeflateTest) {
+ const Buffer kDeflate = {0x07};
Buffer puffed;
- FailPuffDeflate(kDeflate6, Error::kInvalidInput, &puffed);
+ FailPuffDeflate(kDeflate, &puffed);
}
-// Tests puffing a block with final block bit unset so it returns
-// Error::kInsufficientInput.
+// Tests puffing a block with final block bit unset so it returns false.
TEST_F(PuffinTest, PuffDeflateNoFinalBlockBitTest) {
- CheckSample(kRaw7, kDeflate7, kPuff7);
+ const Buffer kDeflate = {0x62, 0x04, 0x00};
+ const Buffer kPuff = {0x00, 0x00, 0x20, 0x00, 0x01, 0xFF, 0x81};
+ CheckSample(kRaw1, kDeflate, kPuff);
}
+// Tests two deflate buffers concatenated, neither have their final bit set. It
+// is a valid deflate and puff buffer.
TEST_F(PuffinTest, MultipleDeflateBufferNoFinabBitsTest) {
- CheckSample(kRaw7_2, kDeflate7_2, kPuff7_2);
+ const Buffer kDeflate = {0x62, 0x04, 0x88, 0x11, 0x00};
+ const Buffer kPuff = {0x00, 0x00, 0x20, 0x00, 0x01, 0xFF, 0x81,
+ 0x00, 0x00, 0x20, 0x00, 0x01, 0xFF, 0x81};
+ CheckSample(kRaw2, kDeflate, kPuff);
}
+// Tests two deflate buffers concatenated, the first one has final bit set,
+// second one not. It is a valid deflate and puff buffer.
TEST_F(PuffinTest, MultipleDeflateBufferOneFinalBitTest) {
- CheckSample(kRaw7_3, kDeflate7_3, kPuff7_3);
+ const Buffer kDeflate = {0x63, 0x04, 0x88, 0x11, 0x00};
+ const Buffer kPuff = {0x00, 0x00, 0xA0, 0x00, 0x01, 0xFF, 0x81,
+ 0x00, 0x00, 0x20, 0x00, 0x01, 0xFF, 0x81};
+ CheckSample(kRaw2, kDeflate, kPuff);
}
+// Tests two deflate buffers concatenated, both have final bits set. It is a
+// valid deflate and puff buffer.
TEST_F(PuffinTest, MultipleDeflateBufferBothFinalBitTest) {
- CheckSample(kRaw7_4, kDeflate7_4, kPuff7_4);
+ const Buffer kDeflate = {0x63, 0x04, 0x8C, 0x11, 0x00};
+ const Buffer kPuff = {0x00, 0x00, 0xA0, 0x00, 0x01, 0xFF, 0x81,
+ 0x00, 0x00, 0xA0, 0x00, 0x01, 0xFF, 0x81};
+ CheckSample(kRaw2, kDeflate, kPuff);
+}
+
+// When locating deflates, the puffer has to end when it hit a final block. Test
+// that with two deflate buffers concatenated and both have final bits set.
+TEST_F(PuffinTest, EndOnFinalBitTest) {
+ const Buffer kDeflate = {0x63, 0x04, 0x8C, 0x11, 0x00};
+ BufferBitReader bit_reader(kDeflate.data(), kDeflate.size());
+ BufferPuffWriter puff_writer(nullptr, 0);
+ vector<BitExtent> deflates;
+ EXPECT_TRUE(puffer_.PuffDeflate(&bit_reader, &puff_writer, &deflates));
+ const vector<BitExtent> kExpectedDeflates = {{0, 18}};
+ EXPECT_EQ(deflates, kExpectedDeflates);
+ EXPECT_EQ(bit_reader.Offset(), 3);
}
// TODO(ahassani): Add unittests for Failhuff too.
+namespace {
+// The following is a sequence of bits starting from the top right and ends in
+// bottom left. It represents the bits in |kGapDeflates|. Bits inside the
+// brackets (including bits exactly under brackets) represent a deflate stream.
+//
+// } { } { }{ }
+// 11000101 10000000 10001100 01010000 00010001 10001000 00000100 01100010
+// 0xC5 0x80 0x8C 0x50 0x11 0x88 0x04 0x62
+//
+// } { } { } {
+// 10001011 11111100 00000100 01100010 00000001 00011000 10111000 00001000
+// 0x8B 0xFC 0x04 0x62 0x01 0x18 0xB8 0x08
+//
+// } { } { }{
+// 10001011 00000001 00011000 10111111 11000000 01000110 00100000 00010001
+// 0x8B 0x01 0x18 0xBF 0xC0 0x46 0x20 0x11
+//
+// { } { } {
+// 11111100 00000100 01100010 11111111 00000001 00011000 10110000 00010001
+// 0xFC 0x04 0x62 0xFF 0x01 0x18 0xB0 0x11
+//
+const Buffer kGapDeflates = {0x62, 0x04, 0x88, 0x11, 0x50, 0x8C, 0x80, 0xC5,
+ 0x08, 0xB8, 0x18, 0x01, 0x62, 0x04, 0xFC, 0x8B,
+ 0x11, 0x20, 0x46, 0xC0, 0xBF, 0x18, 0x01, 0x8B,
+ 0x11, 0xB0, 0x18, 0x01, 0xFF, 0x62, 0x04, 0xFC};
+
+const Buffer kGapPuffs = {0x00, 0x00, 0x20, 0x00, 0x01, 0xFF, 0x81, // puff 0
+ 0x00, 0x00, 0x20, 0x00, 0x01, 0xFF, 0x81, // puff 7
+ 0x01, // raw 14
+ 0x00, 0x00, 0x20, 0x00, 0x01, 0xFF, 0x81, // puff 15
+ 0x01, 0x01, // raw 22
+ 0x00, 0x00, 0x20, 0x00, 0x01, 0xFF, 0x81, // puff 24
+ 0x07, // raw 31
+ 0x00, 0x00, 0x20, 0x00, 0x01, 0xFF, 0x81, // puff 32
+ 0x00, 0x00, 0x20, 0x00, 0x01, 0xFF, 0x81, // puff 39
+ 0x3F, 0x03, // raw 46
+ 0x00, 0x00, 0x20, 0x00, 0x01, 0xFF, 0x81, // puff 48
+ 0x00, 0x00, 0x20, 0x00, 0x01, 0xFF, 0x81, // puff 55
+ 0x03, 0x3F, // raw 62
+ 0x00, 0x00, 0x20, 0x00, 0x01, 0xFF, 0x81, // puff 64
+ 0x03, // raw 71
+ 0x00, 0x00, 0x20, 0x00, 0x01, 0xFF, 0x81, // puff 72
+ 0x03, // raw 79
+ 0x00, 0x00, 0x20, 0x00, 0x01, 0xFF, 0x81, // puff 80
+ 0xFF, // raw 87
+ 0x00, 0x00, 0x20, 0x00, 0x01, 0xFF, 0x81, // puff 88
+ 0x3F}; // raw 95
+
+// The fifth deflate (and its puff in kGapPuffExtents) is for zero length
+// deflate corner case.
+const std::vector<BitExtent> kGapSubblockDeflateExtents = {
+ {0, 18}, {18, 18}, {37, 18}, {57, 18}, {75, 0}, {78, 18}, {96, 18},
+ {122, 18}, {140, 18}, {166, 18}, {186, 18}, {206, 18}, {232, 18}};
+
+const std::vector<ByteExtent> kGapPuffExtents = {
+ {0, 7}, {7, 7}, {15, 7}, {24, 7}, {31, 0}, {32, 7}, {39, 7},
+ {48, 7}, {55, 7}, {64, 7}, {72, 7}, {80, 7}, {88, 7}};
+} // namespace
+
TEST_F(PuffinTest, BitExtentPuffAndHuffTest) {
- CheckBitExtentsPuffAndHuff(kDeflate11, kSubblockDeflateExtents11, kPuff11,
- kPuffExtents11);
+ CheckBitExtentsPuffAndHuff(kGapDeflates, kGapSubblockDeflateExtents,
+ kGapPuffs, kGapPuffExtents);
}
-// TODO(ahassani): add tests for:
-// TestPatchingEmptyTo9
-// TestPatchingNoDeflateTo9
-
-// TODO(ahassani): Change tests data if you decided to compress the header of
-// the patch.
-
} // namespace puffin
diff --git a/src/puffpatch.cc b/src/puffpatch.cc
index 185b1dd..2dd3a29 100644
--- a/src/puffpatch.cc
+++ b/src/puffpatch.cc
@@ -19,15 +19,15 @@
#include "puffin/src/include/puffin/huffer.h"
#include "puffin/src/include/puffin/puffer.h"
#include "puffin/src/include/puffin/stream.h"
+#include "puffin/src/logging.h"
#include "puffin/src/puffin.pb.h"
#include "puffin/src/puffin_stream.h"
-#include "puffin/src/set_errors.h"
-
-namespace puffin {
using std::string;
using std::vector;
+namespace puffin {
+
const char kMagic[] = "PUF1";
const size_t kMagicLength = 4;
@@ -44,6 +44,55 @@
}
}
+class BsdiffStream : public bsdiff::FileInterface {
+ public:
+ ~BsdiffStream() override = default;
+
+ static std::unique_ptr<bsdiff::FileInterface> Create(UniqueStreamPtr stream) {
+ TEST_AND_RETURN_VALUE(stream, nullptr);
+ return std::unique_ptr<bsdiff::FileInterface>(
+ new BsdiffStream(std::move(stream)));
+ }
+
+ bool Read(void* buf, size_t count, size_t* bytes_read) override {
+ *bytes_read = 0;
+ if (stream_->Read(buf, count)) {
+ *bytes_read = count;
+ return true;
+ }
+ return false;
+ }
+
+ bool Write(const void* buf, size_t count, size_t* bytes_written) override {
+ *bytes_written = 0;
+ if (stream_->Write(buf, count)) {
+ *bytes_written = count;
+ return true;
+ }
+ return false;
+ }
+
+ bool Seek(off_t pos) override { return stream_->Seek(pos); }
+
+ bool Close() override { return stream_->Close(); }
+
+ bool GetSize(uint64_t* size) override {
+ uint64_t my_size;
+ TEST_AND_RETURN_FALSE(stream_->GetSize(&my_size));
+ *size = my_size;
+ return true;
+ }
+
+ private:
+ explicit BsdiffStream(UniqueStreamPtr stream) : stream_(std::move(stream)) {}
+
+ UniqueStreamPtr stream_;
+
+ DISALLOW_COPY_AND_ASSIGN(BsdiffStream);
+};
+
+} // namespace
+
bool DecodePatch(const uint8_t* patch,
size_t patch_length,
size_t* bsdiff_patch_offset,
@@ -88,48 +137,6 @@
return true;
}
-class BsdiffStream : public bsdiff::FileInterface {
- public:
- explicit BsdiffStream(UniqueStreamPtr stream) : stream_(std::move(stream)) {}
- ~BsdiffStream() override = default;
-
- bool Read(void* buf, size_t count, size_t* bytes_read) override {
- *bytes_read = 0;
- if (stream_->Read(buf, count)) {
- *bytes_read = count;
- return true;
- }
- return false;
- }
-
- bool Write(const void* buf, size_t count, size_t* bytes_written) override {
- *bytes_written = 0;
- if (stream_->Write(buf, count)) {
- *bytes_written = count;
- return true;
- }
- return false;
- }
-
- bool Seek(off_t pos) override { return stream_->Seek(pos); }
-
- bool Close() override { return stream_->Close(); }
-
- bool GetSize(uint64_t* size) override {
- uint64_t my_size;
- TEST_AND_RETURN_FALSE(stream_->GetSize(&my_size));
- *size = my_size;
- return true;
- }
-
- private:
- UniqueStreamPtr stream_;
-
- DISALLOW_COPY_AND_ASSIGN(BsdiffStream);
-};
-
-} // namespace
-
bool PuffPatch(UniqueStreamPtr src,
UniqueStreamPtr dst,
const uint8_t* patch,
@@ -150,19 +157,20 @@
auto huffer = std::make_shared<Huffer>();
// For reading from source.
- std::unique_ptr<bsdiff::FileInterface> reader(new BsdiffStream(
+ auto reader = BsdiffStream::Create(
PuffinStream::CreateForPuff(std::move(src), puffer, src_puff_size,
- src_deflates, src_puffs, max_cache_size)));
+ src_deflates, src_puffs, max_cache_size));
+ TEST_AND_RETURN_FALSE(reader);
// For writing into destination.
- std::unique_ptr<bsdiff::FileInterface> writer(
- new BsdiffStream(PuffinStream::CreateForHuff(
- std::move(dst), huffer, dst_puff_size, dst_deflates, dst_puffs)));
+ auto writer = BsdiffStream::Create(PuffinStream::CreateForHuff(
+ std::move(dst), huffer, dst_puff_size, dst_deflates, dst_puffs));
+ TEST_AND_RETURN_FALSE(writer);
// Running bspatch itself.
- TEST_AND_RETURN_FALSE(
- 0 ==
- bspatch(reader, writer, &patch[bsdiff_patch_offset], bsdiff_patch_size));
+ TEST_AND_RETURN_FALSE(0 == bspatch(reader, writer,
+ &patch[bsdiff_patch_offset],
+ bsdiff_patch_size));
return true;
}
diff --git a/src/sample_generator.cc b/src/sample_generator.cc
deleted file mode 100644
index a2bc7e2..0000000
--- a/src/sample_generator.cc
+++ /dev/null
@@ -1,94 +0,0 @@
-// Copyright 2017 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "puffin/src/sample_generator.h"
-
-#include <malloc.h>
-#include <zlib.h>
-
-#include <fstream>
-#include <iomanip>
-#include <iostream>
-#include <string>
-
-#include "puffin/src/bit_reader.h"
-#include "puffin/src/puff_writer.h"
-#include "puffin/src/set_errors.h"
-
-namespace puffin {
-namespace sample_generator {
-
-using std::cerr;
-using std::cout;
-using std::endl;
-using std::string;
-
-bool CompressToDeflate(const Buffer& uncomp,
- Buffer* comp,
- int compression,
- int strategy) {
- z_stream stream;
- stream.next_in = (z_const Bytef*)uncomp.data();
- stream.avail_in = static_cast<unsigned int>(uncomp.size());
- stream.next_out = comp->data();
- stream.avail_out = comp->size();
-
- stream.zalloc = nullptr;
- stream.zfree = nullptr;
- stream.opaque = nullptr;
-
- TEST_AND_RETURN_FALSE(
- Z_OK == deflateInit2(&stream, compression, Z_DEFLATED, -15, 8, strategy));
- // If there was not enough output available return error.
- TEST_AND_RETURN_FALSE(Z_STREAM_END == deflate(&stream, Z_FINISH));
- TEST_AND_RETURN_FALSE(Z_OK == deflateEnd(&stream));
- comp->resize(stream.total_out);
- return true;
-}
-
-// Print an array into hex-format to the output. This can be used to create
-// static arrays for unit testing of the puffer/huffer.
-void PrintArray(const string& name, const Buffer& array) {
- cout << "const Buffer " << name << " = {" << endl << " ";
- for (size_t idx = 0; idx < array.size(); idx++) {
- cout << " 0x" << std::hex << std::uppercase << std::setfill('0')
- << std::setw(2) << uint(array[idx]);
- if (idx == array.size() - 1) {
- cout << std::dec << "};" << endl;
- return;
- }
- cout << ",";
- if ((idx + 1) % 12 == 0) {
- cout << endl << " ";
- }
- }
-}
-
-bool PrintSample(Puffer* puffer,
- int compression,
- int strategy,
- const Buffer& original) {
- PrintArray("original", original);
-
- Buffer comp(original.size() * 4 + 10);
- TEST_AND_RETURN_FALSE(
- CompressToDeflate(original, &comp, compression, strategy));
- PrintArray("compressed", comp);
-
- Buffer puff(original.size() * 3 + 10);
- puffin::Error error;
-
- BufferBitReader bit_reader(comp.data(), comp.size());
- BufferPuffWriter puff_writer(puff.data(), puff.size());
- TEST_AND_RETURN_FALSE(
- puffer->PuffDeflate(&bit_reader, &puff_writer, nullptr, &error));
- TEST_AND_RETURN_FALSE(comp.size() == bit_reader.Offset());
-
- puff.resize(puff_writer.Size());
- PrintArray("puffed", puff);
- return true;
-}
-
-} // namespace sample_generator
-} // namespace puffin
diff --git a/src/sample_generator.h b/src/sample_generator.h
deleted file mode 100644
index 1029d83..0000000
--- a/src/sample_generator.h
+++ /dev/null
@@ -1,34 +0,0 @@
-// Copyright 2017 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef SRC_SAMPLE_GENERATOR_H_
-#define SRC_SAMPLE_GENERATOR_H_
-
-#include <string>
-#include <vector>
-
-#include "puffin/src/include/puffin/puffer.h"
-
-namespace puffin {
-namespace sample_generator {
-
-void PrintArray(const std::string& name, const Buffer& array);
-
-// Creates and prints a sample for for adding to the list of unit tests for
-// puffer/huffer.
-//
-// Example:
-// Buffer orig = {1, 2, 3, 4, 5};
-// Puffer puffer;
-// sample_generator::PrintSample(
-// &puffer, Z_DEFAULT_COMPRESSION, Z_FIXED, orig);
-bool PrintSample(Puffer* puffer,
- int compression,
- int strategy,
- const Buffer& original);
-
-} // namespace sample_generator
-} // namespace puffin
-
-#endif // SRC_SAMPLE_GENERATOR_H_
diff --git a/src/set_errors.h b/src/set_errors.h
deleted file mode 100644
index 2cbd665..0000000
--- a/src/set_errors.h
+++ /dev/null
@@ -1,43 +0,0 @@
-// Copyright 2017 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef SRC_SET_ERRORS_H_
-#define SRC_SET_ERRORS_H_
-
-#ifdef USE_BRILLO
-#include "base/logging.h"
-#else
-#include "glog/logging.h"
-#endif
-
-namespace puffin {
-
-#define TEST_AND_RETURN_FALSE(_x) \
- do { \
- if (!(_x)) { \
- LOG(ERROR) << #_x " failed."; \
- return false; \
- } \
- } while (0)
-
-#define TEST_AND_RETURN_VALUE(_x, _v) \
- do { \
- if (!(_x)) { \
- LOG(ERROR) << #_x " failed."; \
- return (_v); \
- } \
- } while (0)
-
-#define TEST_AND_RETURN_FALSE_SET_ERROR(_x, _error) \
- do { \
- if (!(_x)) { \
- (*error) = (_error); \
- LOG(ERROR) << #_x " failed."; \
- return false; \
- } \
- } while (0)
-
-} // namespace puffin
-
-#endif // SRC_SET_ERRORS_H_
diff --git a/src/stream_unittest.cc b/src/stream_unittest.cc
index 0a7c7b3..76fe34b 100644
--- a/src/stream_unittest.cc
+++ b/src/stream_unittest.cc
@@ -6,20 +6,20 @@
#include "gtest/gtest.h"
-#include "puffin/src/include/puffin/huffer.h"
-#include "puffin/src/include/puffin/puffer.h"
#include "puffin/src/extent_stream.h"
#include "puffin/src/file_stream.h"
+#include "puffin/src/include/puffin/huffer.h"
+#include "puffin/src/include/puffin/puffer.h"
#include "puffin/src/memory_stream.h"
#include "puffin/src/puffin_stream.h"
#include "puffin/src/unittest_common.h"
-namespace puffin {
-
-using std::string;
using std::shared_ptr;
+using std::string;
using std::vector;
+namespace puffin {
+
class StreamTest : public ::testing::Test {
public:
// |data| is the content of stream as a buffer.
@@ -175,7 +175,8 @@
}
TEST_F(StreamTest, FileStreamTest) {
- string filepath("/tmp/test_filepath");
+ string filepath;
+ ASSERT_TRUE(MakeTempFile(&filepath, nullptr));
ScopedPathUnlinker scoped_unlinker(filepath);
ASSERT_FALSE(FileStream::Open(filepath, false, false));
@@ -197,47 +198,49 @@
TEST_F(StreamTest, PuffinStreamTest) {
shared_ptr<Puffer> puffer(new Puffer());
auto read_stream = PuffinStream::CreateForPuff(
- MemoryStream::CreateForRead(kDeflates8), puffer, kPuffs8.size(),
- kSubblockDeflateExtents8, kPuffExtents8);
- TestRead(read_stream.get(), kPuffs8);
+ MemoryStream::CreateForRead(kDeflatesSample1), puffer,
+ kPuffsSample1.size(), kSubblockDeflateExtentsSample1,
+ kPuffExtentsSample1);
+ TestRead(read_stream.get(), kPuffsSample1);
TestSeek(read_stream.get(), false);
TestClose(read_stream.get());
// Test the stream with puff cache.
read_stream = PuffinStream::CreateForPuff(
- MemoryStream::CreateForRead(kDeflates8), puffer, kPuffs8.size(),
- kSubblockDeflateExtents8, kPuffExtents8, 8 /* max_cache_size */);
- TestRead(read_stream.get(), kPuffs8);
+ MemoryStream::CreateForRead(kDeflatesSample1), puffer,
+ kPuffsSample1.size(), kSubblockDeflateExtentsSample1, kPuffExtentsSample1,
+ 8 /* max_cache_size */);
+ TestRead(read_stream.get(), kPuffsSample1);
TestSeek(read_stream.get(), false);
TestClose(read_stream.get());
- Buffer buf(kDeflates8.size());
+ Buffer buf(kDeflatesSample1.size());
shared_ptr<Huffer> huffer(new Huffer());
auto write_stream = PuffinStream::CreateForHuff(
- MemoryStream::CreateForWrite(&buf), huffer, kPuffs8.size(),
- kSubblockDeflateExtents8, kPuffExtents8);
+ MemoryStream::CreateForWrite(&buf), huffer, kPuffsSample1.size(),
+ kSubblockDeflateExtentsSample1, kPuffExtentsSample1);
ASSERT_TRUE(write_stream->Seek(0));
- for (size_t idx = 0; idx < kPuffs8.size(); idx++) {
- ASSERT_TRUE(write_stream->Write(&kPuffs8[idx], 1));
+ for (size_t idx = 0; idx < kPuffsSample1.size(); idx++) {
+ ASSERT_TRUE(write_stream->Write(&kPuffsSample1[idx], 1));
}
// Make sure the write works
- ASSERT_EQ(buf, kDeflates8);
+ ASSERT_EQ(buf, kDeflatesSample1);
std::fill(buf.begin(), buf.end(), 0);
ASSERT_TRUE(write_stream->Seek(0));
- ASSERT_TRUE(write_stream->Write(kPuffs8.data(), kPuffs8.size()));
+ ASSERT_TRUE(write_stream->Write(kPuffsSample1.data(), kPuffsSample1.size()));
// Check its correctness.
- ASSERT_EQ(buf, kDeflates8);
+ ASSERT_EQ(buf, kDeflatesSample1);
// Write entire buffer one byte at a time. (all zeros).
std::fill(buf.begin(), buf.end(), 0);
ASSERT_TRUE(write_stream->Seek(0));
- for (const auto& byte : kPuffs8) {
+ for (const auto& byte : kPuffsSample1) {
ASSERT_TRUE(write_stream->Write(&byte, 1));
}
// Check its correctness.
- ASSERT_EQ(buf, kDeflates8);
+ ASSERT_EQ(buf, kDeflatesSample1);
// No TestSeek is needed as PuffinStream is not supposed to seek to anywhere
// except 0.
diff --git a/src/unittest_common.cc b/src/unittest_common.cc
index b542740..7b16011 100644
--- a/src/unittest_common.cc
+++ b/src/unittest_common.cc
@@ -4,12 +4,16 @@
#include "puffin/src/unittest_common.h"
-namespace puffin {
-
using std::string;
+namespace puffin {
+
bool MakeTempFile(string* filename, int* fd) {
+#ifdef __ANDROID__
+ char tmp_template[] = "/data/local/tmp/puffin-XXXXXX";
+#else
char tmp_template[] = "/tmp/puffin-XXXXXX";
+#endif // __ANDROID__
int mkstemp_fd = mkstemp(tmp_template);
TEST_AND_RETURN_FALSE(mkstemp_fd >= 0);
if (filename) {
@@ -23,4 +27,53 @@
return true;
}
+// clang-format off
+const Buffer kDeflatesSample1 = {
+ /* raw 0 */ 0x11, 0x22,
+ /* def 2 */ 0x63, 0x64, 0x62, 0x66, 0x61, 0x05, 0x00,
+ /* raw 9 */ 0x33,
+ /* def 10 */ 0x03, 0x00,
+ /* raw 12 */
+ /* def 12 */ 0x63, 0x04, 0x00,
+ /* raw 15 */ 0x44, 0x55
+};
+const Buffer kPuffsSample1 = {
+ /* raw 0 */ 0x11, 0x22,
+ /* puff 2 */ 0x00, 0x00, 0xA0, 0x04, 0x01, 0x02, 0x03, 0x04, 0x05, 0xFF,
+ 0x81,
+ /* raw 13 */ 0x00, 0x33,
+ /* puff 15 */ 0x00, 0x00, 0xA0, 0xFF, 0x81,
+ /* raw 20 */ 0x00,
+ /* puff 21 */ 0x00, 0x00, 0xA0, 0x00, 0x01, 0xFF, 0x81,
+ /* raw 28 */ 0x00, 0x44, 0x55
+};
+const std::vector<ByteExtent> kDeflateExtentsSample1 = {
+ {2, 7}, {10, 2}, {12, 3}};
+const std::vector<BitExtent> kSubblockDeflateExtentsSample1 = {
+ {16, 50}, {80, 10}, {96, 18}};
+const std::vector<ByteExtent> kPuffExtentsSample1 = {{2, 11}, {15, 5}, {21, 7}};
+
+const Buffer kDeflatesSample2 = {
+ /* def 0 */ 0x63, 0x64, 0x62, 0x66, 0x61, 0x05, 0x00,
+ /* raw 7 */ 0x33, 0x66,
+ /* def 9 */ 0x01, 0x05, 0x00, 0xFA, 0xFF, 0x01, 0x02, 0x03, 0x04, 0x05,
+ /* def 19 */ 0x63, 0x04, 0x00
+};
+const Buffer kPuffsSample2 = {
+ /* puff 0 */ 0x00, 0x00, 0xA0, 0x04, 0x01, 0x02, 0x03, 0x04, 0x05, 0xFF,
+ 0x81,
+ /* raw 11 */ 0x00, 0x33, 0x66,
+ /* puff 14 */ 0x00, 0x00, 0x80, 0x04, 0x01, 0x02, 0x03, 0x04, 0x05, 0xFF,
+ 0x81,
+ /* puff 25 */ 0x00, 0x00, 0xA0, 0x00, 0x01, 0xFF, 0x81,
+ /* raw 32 */ 0x00,
+};
+const std::vector<ByteExtent> kDeflateExtentsSample2 = {
+ {0, 7}, {9, 10}, {19, 3}};
+const std::vector<BitExtent> kSubblockDeflateExtentsSample2 = {
+ {0, 50}, {72, 80}, {152, 18}};
+const std::vector<ByteExtent> kPuffExtentsSample2 = {
+ {0, 11}, {14, 11}, {25, 7}};
+// clang-format on
+
} // namespace puffin
diff --git a/src/unittest_common.h b/src/unittest_common.h
index c03aea4..c73d9b3 100644
--- a/src/unittest_common.h
+++ b/src/unittest_common.h
@@ -9,7 +9,7 @@
#include <vector>
#include "puffin/src/include/puffin/common.h"
-#include "puffin/src/set_errors.h"
+#include "puffin/src/logging.h"
namespace puffin {
@@ -34,408 +34,17 @@
// values.
bool MakeTempFile(std::string* filename, int* fd);
-// clang-format off
-// Uncompressed deflate block.
-const Buffer kRaw1 = {0x01, 0x02, 0x03, 0x04, 0x05};
-const Buffer kDeflate1 = {
- 0x01, 0x05, 0x00, 0xFA, 0xFF, 0x01, 0x02, 0x03, 0x04, 0x05};
-const Buffer kPuff1 = {
- 0x00, 0x00, 0x80, 0x04, 0x01, 0x02, 0x03, 0x04, 0x05, 0xFF, 0x81};
+extern const Buffer kDeflatesSample1;
+extern const Buffer kPuffsSample1;
+extern const std::vector<ByteExtent> kDeflateExtentsSample1;
+extern const std::vector<BitExtent> kSubblockDeflateExtentsSample1;
+extern const std::vector<ByteExtent> kPuffExtentsSample1;
-// Uncompressed deflate block with zero length.
-const Buffer kRaw1_1 = {};
-const Buffer kDeflate1_1 = {0x01, 0x00, 0x00, 0xFF, 0xFF};
-const Buffer kPuff1_1 = {0x00, 0x00, 0x80, 0xFF, 0x81};
-
-// Fixed huffman table compressed deflate.
-const Buffer kRaw2 = {0x01};
-const Buffer kDeflate2 = {0x63, 0x04, 0x00};
-const Buffer kPuff2 = {0x00, 0x00, 0xA0, 0x00, 0x01, 0xFF, 0x81};
-
-// Deflate of an empty buffer.
-const Buffer kRaw3 = {};
-const Buffer kDeflate3 = {0x03, 0x00};
-const Buffer kPuff3 = {0x00, 0x00, 0xA0, 0xFF, 0x81};
-
-// Deflate with fixed Huffman table.
-const Buffer kRaw4 = {0x01, 0x02, 0x03, 0x04, 0x05};
-const Buffer kDeflate4 = {0x63, 0x64, 0x62, 0x66, 0x61, 0x05, 0x00};
-const Buffer kPuff4 = {
- 0x00, 0x00, 0xA0, 0x04, 0x01, 0x02, 0x03, 0x04, 0x05, 0xFF, 0x81};
-
-// Invalid LEN/NLEN for uncompressed deflate block.
-const Buffer kDeflate5 = {
- 0x01, 0x05, 0x00, 0xFF, 0xFF, 0x01, 0x02, 0x03, 0x04, 0x05};
-
-// Deflate with invalid block header.
-const Buffer kDeflate6 = {0x07};
-
-// Deflate with final block bit unset.
-const Buffer kRaw7 = {0x01};
-const Buffer kDeflate7 = {0x62, 0x04, 0x00};
-const Buffer kPuff7 = {0x00, 0x00, 0x20, 0x00, 0x01, 0xFF, 0x81};
-
-// Two deflate buffers concatenated, neither have their final bit set. It is a
-// valid deflate and puff buffer.
-const Buffer kRaw7_2 = {0x01, 0x01};
-const Buffer kDeflate7_2 = {0x62, 0x04, 0x88, 0x11, 0x00};
-const Buffer kPuff7_2 = {
- 0x00, 0x00, 0x20, 0x00, 0x01, 0xFF, 0x81,
- 0x00, 0x00, 0x20, 0x00, 0x01, 0xFF, 0x81};
-
-// Two deflate buffers concatenated, the first one has final bit set, second one
-// not. It is a valid deflate and puff buffer.
-const Buffer kRaw7_3 = {0x01, 0x01};
-const Buffer kDeflate7_3 = {0x63, 0x04, 0x88, 0x11, 0x00};
-const Buffer kPuff7_3 = {
- 0x00, 0x00, 0xA0, 0x00, 0x01, 0xFF, 0x81,
- 0x00, 0x00, 0x20, 0x00, 0x01, 0xFF, 0x81};
-
-// Two deflate buffers concatenated, both have final bits set. It is a valid
-// deflate and puff buffer.
-const Buffer kRaw7_4 = {0x01, 0x01};
-const Buffer kDeflate7_4 = {0x63, 0x04, 0x8C, 0x11, 0x00};
-const Buffer kPuff7_4 = {
- 0x00, 0x00, 0xA0, 0x00, 0x01, 0xFF, 0x81,
- 0x00, 0x00, 0xA0, 0x00, 0x01, 0xFF, 0x81};
-
-const Buffer kDeflates8 = {
- /* raw 0 */ 0x11, 0x22,
- /* deflate 2 */ 0x63, 0x64, 0x62, 0x66, 0x61, 0x05, 0x00,
- /* raw 9 */ 0x33,
- /* deflate 10 */ 0x03, 0x00,
- /* raw 12 */
- /* deflate 12 */ 0x63, 0x04, 0x00,
- /* raw 15 */ 0x44, 0x55
-};
-
-const Buffer kPuffs8 = {
- /* raw 0 */ 0x11, 0x22,
- /* puff 2 */ 0x00, 0x00, 0xA0, 0x04, 0x01, 0x02, 0x03, 0x04, 0x05, 0xFF,
- 0x81,
- /* raw 13 */ 0x00, 0x33,
- /* puff 15 */ 0x00, 0x00, 0xA0, 0xFF, 0x81,
- /* raw 20 */ 0x00,
- /* puff 21 */ 0x00, 0x00, 0xA0, 0x00, 0x01, 0xFF, 0x81,
- /* raw 28 */ 0x00, 0x44, 0x55
-};
-
-const std::vector<ByteExtent> kDeflateExtents8 = {{2, 7}, {10, 2}, {12, 3}};
-const std::vector<BitExtent> kSubblockDeflateExtents8 = {
- {16, 50}, {80, 10}, {96, 18}};
-const std::vector<ByteExtent> kPuffExtents8 = {{2, 11}, {15, 5}, {21, 7}};
-
-const Buffer kDeflates9 = {
- /* deflate 0 */ 0x63, 0x64, 0x62, 0x66, 0x61, 0x05, 0x00,
- /* raw 7 */ 0x33, 0x66,
- /* deflate 9 */ 0x01, 0x05, 0x00, 0xFA, 0xFF, 0x01, 0x02, 0x03, 0x04, 0x05,
- /* deflate 19 */ 0x63, 0x04, 0x00
-};
-
-const Buffer kPuffs9 = {
- /* puff 0 */ 0x00, 0x00, 0xA0, 0x04, 0x01, 0x02, 0x03, 0x04, 0x05, 0xFF,
- 0x81,
- /* raw 11 */ 0x00, 0x33, 0x66,
- /* puff 14 */ 0x00, 0x00, 0x80, 0x04, 0x01, 0x02, 0x03, 0x04, 0x05, 0xFF,
- 0x81,
- /* puff 25 */ 0x00, 0x00, 0xA0, 0x00, 0x01, 0xFF, 0x81,
- /* raw 32 */ 0x00,
-};
-
-const std::vector<ByteExtent> kDeflateExtents9 = {{0, 7}, {9, 10}, {19, 3}};
-const std::vector<BitExtent> kSubblockDeflateExtents9 = {
- {0, 50}, {72, 80}, {152, 18}};
-const std::vector<ByteExtent> kPuffExtents9 = {{0, 11}, {14, 11}, {25, 7}};
-
-const Buffer kPatch8To9 = {
- 0x50, 0x55, 0x46, 0x31, 0x00, 0x00, 0x00, 0x51, 0x08, 0x01, 0x12, 0x27,
- 0x0A, 0x04, 0x08, 0x10, 0x10, 0x32, 0x0A, 0x04, 0x08, 0x50, 0x10, 0x0A,
- 0x0A, 0x04, 0x08, 0x60, 0x10, 0x12, 0x12, 0x04, 0x08, 0x10, 0x10, 0x58,
- 0x12, 0x04, 0x08, 0x78, 0x10, 0x28, 0x12, 0x05, 0x08, 0xA8, 0x01, 0x10,
- 0x38, 0x18, 0x1F, 0x1A, 0x24, 0x0A, 0x02, 0x10, 0x32, 0x0A, 0x04, 0x08,
- 0x48, 0x10, 0x50, 0x0A, 0x05, 0x08, 0x98, 0x01, 0x10, 0x12, 0x12, 0x02,
- 0x10, 0x58, 0x12, 0x04, 0x08, 0x70, 0x10, 0x58, 0x12, 0x05, 0x08, 0xC8,
- 0x01, 0x10, 0x38, 0x18, 0x21, 0x42, 0x53, 0x44, 0x49, 0x46, 0x46, 0x34,
- 0x30, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x42, 0x5A, 0x68, 0x39, 0x31, 0x41, 0x59, 0x26, 0x53, 0x59, 0xD1,
- 0x20, 0xBB, 0x7E, 0x00, 0x00, 0x03, 0x60, 0x40, 0x78, 0x0E, 0x08, 0x00,
- 0x40, 0x00, 0x20, 0x00, 0x31, 0x06, 0x4C, 0x40, 0x92, 0x8F, 0x46, 0xA7,
- 0xA8, 0xE0, 0xF3, 0xD6, 0x21, 0x12, 0xF4, 0xBC, 0x43, 0x32, 0x1F, 0x17,
- 0x72, 0x45, 0x38, 0x50, 0x90, 0xD1, 0x20, 0xBB, 0x7E, 0x42, 0x5A, 0x68,
- 0x39, 0x31, 0x41, 0x59, 0x26, 0x53, 0x59, 0xF1, 0x20, 0x5F, 0x0D, 0x00,
- 0x00, 0x02, 0x41, 0x15, 0x42, 0x08, 0x20, 0x00, 0x40, 0x00, 0x00, 0x02,
- 0x40, 0x00, 0x20, 0x00, 0x22, 0x3D, 0x23, 0x10, 0x86, 0x03, 0x96, 0x54,
- 0x11, 0x16, 0x5F, 0x17, 0x72, 0x45, 0x38, 0x50, 0x90, 0xF1, 0x20, 0x5F,
- 0x0D, 0x42, 0x5A, 0x68, 0x39, 0x31, 0x41, 0x59, 0x26, 0x53, 0x59, 0x07,
- 0xD4, 0xCB, 0x6E, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x20, 0x00,
- 0x21, 0x18, 0x46, 0x82, 0xEE, 0x48, 0xA7, 0x0A, 0x12, 0x00, 0xFA, 0x99,
- 0x6D, 0xC0};
-
-const Buffer kPatch9To8 = {
- 0x50, 0x55, 0x46, 0x31, 0x00, 0x00, 0x00, 0x51, 0x08, 0x01, 0x12, 0x24,
- 0x0A, 0x02, 0x10, 0x32, 0x0A, 0x04, 0x08, 0x48, 0x10, 0x50, 0x0A, 0x05,
- 0x08, 0x98, 0x01, 0x10, 0x12, 0x12, 0x02, 0x10, 0x58, 0x12, 0x04, 0x08,
- 0x70, 0x10, 0x58, 0x12, 0x05, 0x08, 0xC8, 0x01, 0x10, 0x38, 0x18, 0x21,
- 0x1A, 0x27, 0x0A, 0x04, 0x08, 0x10, 0x10, 0x32, 0x0A, 0x04, 0x08, 0x50,
- 0x10, 0x0A, 0x0A, 0x04, 0x08, 0x60, 0x10, 0x12, 0x12, 0x04, 0x08, 0x10,
- 0x10, 0x58, 0x12, 0x04, 0x08, 0x78, 0x10, 0x28, 0x12, 0x05, 0x08, 0xA8,
- 0x01, 0x10, 0x38, 0x18, 0x1F, 0x42, 0x53, 0x44, 0x49, 0x46, 0x46, 0x34,
- 0x30, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x42, 0x5A, 0x68, 0x39, 0x31, 0x41, 0x59, 0x26, 0x53, 0x59, 0x3D,
- 0xBD, 0x08, 0x91, 0x00, 0x00, 0x01, 0xE0, 0x40, 0x5C, 0x0A, 0x40, 0x00,
- 0x40, 0x00, 0x20, 0x00, 0x31, 0x0C, 0x08, 0x23, 0xD2, 0x34, 0xD1, 0xB1,
- 0x73, 0x60, 0x44, 0x54, 0xE4, 0xFC, 0x5D, 0xC9, 0x14, 0xE1, 0x42, 0x40,
- 0xF6, 0xF4, 0x22, 0x44, 0x42, 0x5A, 0x68, 0x39, 0x31, 0x41, 0x59, 0x26,
- 0x53, 0x59, 0x41, 0x62, 0x2E, 0xF0, 0x00, 0x00, 0x00, 0x40, 0x00, 0x40,
- 0x20, 0x20, 0x00, 0x21, 0x00, 0x82, 0x83, 0x17, 0x72, 0x45, 0x38, 0x50,
- 0x90, 0x41, 0x62, 0x2E, 0xF0, 0x42, 0x5A, 0x68, 0x39, 0x31, 0x41, 0x59,
- 0x26, 0x53, 0x59, 0xE0, 0x20, 0x04, 0x57, 0x00, 0x00, 0x04, 0x76, 0x50,
- 0xE0, 0x00, 0x20, 0x00, 0x10, 0x00, 0x04, 0x00, 0x02, 0x00, 0x20, 0x00,
- 0x40, 0x00, 0x00, 0x00, 0xA0, 0x00, 0x21, 0xA1, 0xA3, 0x10, 0x83, 0x26,
- 0x21, 0x5E, 0xB2, 0x69, 0xAC, 0x70, 0x60, 0x53, 0xC5, 0xDC, 0x91, 0x4E,
- 0x14, 0x24, 0x38, 0x08, 0x01, 0x15, 0xC0};
-
-const Buffer kPatch8ToEmpty = {
- 0x50, 0x55, 0x46, 0x31, 0x00, 0x00, 0x00, 0x2D, 0x08, 0x01, 0x12, 0x27,
- 0x0A, 0x04, 0x08, 0x10, 0x10, 0x32, 0x0A, 0x04, 0x08, 0x50, 0x10, 0x0A,
- 0x0A, 0x04, 0x08, 0x60, 0x10, 0x12, 0x12, 0x04, 0x08, 0x10, 0x10, 0x58,
- 0x12, 0x04, 0x08, 0x78, 0x10, 0x28, 0x12, 0x05, 0x08, 0xA8, 0x01, 0x10,
- 0x38, 0x18, 0x1F, 0x1A, 0x00, 0x42, 0x53, 0x44, 0x49, 0x46, 0x46, 0x34,
- 0x30, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x42, 0x5A, 0x68, 0x39, 0x17, 0x72, 0x45, 0x38, 0x50, 0x90, 0x00,
- 0x00, 0x00, 0x00, 0x42, 0x5A, 0x68, 0x39, 0x17, 0x72, 0x45, 0x38, 0x50,
- 0x90, 0x00, 0x00, 0x00, 0x00, 0x42, 0x5A, 0x68, 0x39, 0x17, 0x72, 0x45,
- 0x38, 0x50, 0x90, 0x00, 0x00, 0x00, 0x00};
-
-const Buffer kPatch8ToNoDeflate = {
- 0x50, 0x55, 0x46, 0x31, 0x00, 0x00, 0x00, 0x2F, 0x08, 0x01, 0x12, 0x27,
- 0x0A, 0x04, 0x08, 0x10, 0x10, 0x32, 0x0A, 0x04, 0x08, 0x50, 0x10, 0x0A,
- 0x0A, 0x04, 0x08, 0x60, 0x10, 0x12, 0x12, 0x04, 0x08, 0x10, 0x10, 0x58,
- 0x12, 0x04, 0x08, 0x78, 0x10, 0x28, 0x12, 0x05, 0x08, 0xA8, 0x01, 0x10,
- 0x38, 0x18, 0x1F, 0x1A, 0x02, 0x18, 0x04, 0x42, 0x53, 0x44, 0x49, 0x46,
- 0x46, 0x34, 0x30, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x42, 0x5A, 0x68, 0x39, 0x31, 0x41, 0x59, 0x26, 0x53,
- 0x59, 0xBA, 0x8D, 0x7F, 0x2D, 0x00, 0x00, 0x00, 0x40, 0x00, 0x44, 0x08,
- 0x20, 0x00, 0x30, 0xCC, 0x09, 0x32, 0x54, 0x65, 0x38, 0xBB, 0x92, 0x29,
- 0xC2, 0x84, 0x85, 0xD4, 0x6B, 0xF9, 0x68, 0x42, 0x5A, 0x68, 0x39, 0x17,
- 0x72, 0x45, 0x38, 0x50, 0x90, 0x00, 0x00, 0x00, 0x00, 0x42, 0x5A, 0x68,
- 0x39, 0x31, 0x41, 0x59, 0x26, 0x53, 0x59, 0xE7, 0xAA, 0xF1, 0xFC, 0x00,
- 0x00, 0x00, 0x70, 0x00, 0x00, 0x08, 0x01, 0x00, 0x20, 0x04, 0x20, 0x00,
- 0x21, 0x9A, 0x68, 0x33, 0x4D, 0x13, 0x3C, 0x5D, 0xC9, 0x14, 0xE1, 0x42,
- 0x43, 0x9E, 0xAB, 0xC7, 0xF0};
-
-// It is actuall the content of the copyright header.
-const Buffer kRaw10 = {
- 0x0A, 0x2F, 0x2F, 0x0A, 0x2F, 0x2F, 0x20, 0x43, 0x6F, 0x70, 0x79, 0x72,
- 0x69, 0x67, 0x68, 0x74, 0x20, 0x28, 0x43, 0x29, 0x20, 0x32, 0x30, 0x31,
- 0x37, 0x20, 0x54, 0x68, 0x65, 0x20, 0x41, 0x6E, 0x64, 0x72, 0x6F, 0x69,
- 0x64, 0x20, 0x4F, 0x70, 0x65, 0x6E, 0x20, 0x53, 0x6F, 0x75, 0x72, 0x63,
- 0x65, 0x20, 0x50, 0x72, 0x6F, 0x6A, 0x65, 0x63, 0x74, 0x0A, 0x2F, 0x2F,
- 0x0A, 0x2F, 0x2F, 0x20, 0x4C, 0x69, 0x63, 0x65, 0x6E, 0x73, 0x65, 0x64,
- 0x20, 0x75, 0x6E, 0x64, 0x65, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x41,
- 0x70, 0x61, 0x63, 0x68, 0x65, 0x20, 0x4C, 0x69, 0x63, 0x65, 0x6E, 0x73,
- 0x65, 0x2C, 0x20, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6F, 0x6E, 0x20, 0x32,
- 0x2E, 0x30, 0x20, 0x28, 0x74, 0x68, 0x65, 0x20, 0x22, 0x4C, 0x69, 0x63,
- 0x65, 0x6E, 0x73, 0x65, 0x22, 0x29, 0x3B, 0x0A, 0x2F, 0x2F, 0x20, 0x79,
- 0x6F, 0x75, 0x20, 0x6D, 0x61, 0x79, 0x20, 0x6E, 0x6F, 0x74, 0x20, 0x75,
- 0x73, 0x65, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x66, 0x69, 0x6C, 0x65,
- 0x20, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x69, 0x6E, 0x20, 0x63,
- 0x6F, 0x6D, 0x70, 0x6C, 0x69, 0x61, 0x6E, 0x63, 0x65, 0x20, 0x77, 0x69,
- 0x74, 0x68, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4C, 0x69, 0x63, 0x65, 0x6E,
- 0x73, 0x65, 0x2E, 0x0A, 0x2F, 0x2F, 0x20, 0x59, 0x6F, 0x75, 0x20, 0x6D,
- 0x61, 0x79, 0x20, 0x6F, 0x62, 0x74, 0x61, 0x69, 0x6E, 0x20, 0x61, 0x20,
- 0x63, 0x6F, 0x70, 0x79, 0x20, 0x6F, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20,
- 0x4C, 0x69, 0x63, 0x65, 0x6E, 0x73, 0x65, 0x20, 0x61, 0x74, 0x0A, 0x2F,
- 0x2F, 0x0A, 0x2F, 0x2F, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x68, 0x74,
- 0x74, 0x70, 0x3A, 0x2F, 0x2F, 0x77, 0x77, 0x77, 0x2E, 0x61, 0x70, 0x61,
- 0x63, 0x68, 0x65, 0x2E, 0x6F, 0x72, 0x67, 0x2F, 0x6C, 0x69, 0x63, 0x65,
- 0x6E, 0x73, 0x65, 0x73, 0x2F, 0x4C, 0x49, 0x43, 0x45, 0x4E, 0x53, 0x45,
- 0x2D, 0x32, 0x2E, 0x30, 0x0A, 0x2F, 0x2F, 0x0A, 0x2F, 0x2F, 0x20, 0x55,
- 0x6E, 0x6C, 0x65, 0x73, 0x73, 0x20, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72,
- 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x61, 0x70, 0x70, 0x6C, 0x69, 0x63,
- 0x61, 0x62, 0x6C, 0x65, 0x20, 0x6C, 0x61, 0x77, 0x20, 0x6F, 0x72, 0x20,
- 0x61, 0x67, 0x72, 0x65, 0x65, 0x64, 0x20, 0x74, 0x6F, 0x20, 0x69, 0x6E,
- 0x20, 0x77, 0x72, 0x69, 0x74, 0x69, 0x6E, 0x67, 0x2C, 0x20, 0x73, 0x6F,
- 0x66, 0x74, 0x77, 0x61, 0x72, 0x65, 0x0A, 0x2F, 0x2F, 0x20, 0x64, 0x69,
- 0x73, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x64, 0x20, 0x75, 0x6E,
- 0x64, 0x65, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4C, 0x69, 0x63, 0x65,
- 0x6E, 0x73, 0x65, 0x20, 0x69, 0x73, 0x20, 0x64, 0x69, 0x73, 0x74, 0x72,
- 0x69, 0x62, 0x75, 0x74, 0x65, 0x64, 0x20, 0x6F, 0x6E, 0x20, 0x61, 0x6E,
- 0x20, 0x22, 0x41, 0x53, 0x20, 0x49, 0x53, 0x22, 0x20, 0x42, 0x41, 0x53,
- 0x49, 0x53, 0x2C, 0x0A, 0x2F, 0x2F, 0x20, 0x57, 0x49, 0x54, 0x48, 0x4F,
- 0x55, 0x54, 0x20, 0x57, 0x41, 0x52, 0x52, 0x41, 0x4E, 0x54, 0x49, 0x45,
- 0x53, 0x20, 0x4F, 0x52, 0x20, 0x43, 0x4F, 0x4E, 0x44, 0x49, 0x54, 0x49,
- 0x4F, 0x4E, 0x53, 0x20, 0x4F, 0x46, 0x20, 0x41, 0x4E, 0x59, 0x20, 0x4B,
- 0x49, 0x4E, 0x44, 0x2C, 0x20, 0x65, 0x69, 0x74, 0x68, 0x65, 0x72, 0x20,
- 0x65, 0x78, 0x70, 0x72, 0x65, 0x73, 0x73, 0x20, 0x6F, 0x72, 0x20, 0x69,
- 0x6D, 0x70, 0x6C, 0x69, 0x65, 0x64, 0x2E, 0x0A, 0x2F, 0x2F, 0x20, 0x53,
- 0x65, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4C, 0x69, 0x63, 0x65, 0x6E,
- 0x73, 0x65, 0x20, 0x66, 0x6F, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73,
- 0x70, 0x65, 0x63, 0x69, 0x66, 0x69, 0x63, 0x20, 0x6C, 0x61, 0x6E, 0x67,
- 0x75, 0x61, 0x67, 0x65, 0x20, 0x67, 0x6F, 0x76, 0x65, 0x72, 0x6E, 0x69,
- 0x6E, 0x67, 0x20, 0x70, 0x65, 0x72, 0x6D, 0x69, 0x73, 0x73, 0x69, 0x6F,
- 0x6E, 0x73, 0x20, 0x61, 0x6E, 0x64, 0x0A, 0x2F, 0x2F, 0x20, 0x6C, 0x69,
- 0x6D, 0x69, 0x74, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x73, 0x20, 0x75, 0x6E,
- 0x64, 0x65, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4C, 0x69, 0x63, 0x65,
- 0x6E, 0x73, 0x65, 0x2E, 0x0A};
-
-// Dynamic huffman compressed deflate.
-const Buffer kDeflate10 = {
- 0x65, 0x91, 0x41, 0x6F, 0x9C, 0x30, 0x10, 0x85, 0xEF, 0xFB, 0x2B, 0x9E,
- 0xF6, 0x94, 0x48, 0x5B, 0x48, 0x73, 0xA9, 0xD4, 0x9E, 0xE8, 0x66, 0xAB,
- 0xA0, 0x46, 0x50, 0x2D, 0xA4, 0x51, 0x8E, 0x5E, 0x18, 0xD8, 0x89, 0x58,
- 0xDB, 0xB5, 0x4D, 0xC9, 0xFE, 0xFB, 0x8E, 0x59, 0x22, 0x25, 0xAA, 0x2F,
- 0xC8, 0xCC, 0xCC, 0x9B, 0xEF, 0x3D, 0xAF, 0xD2, 0x74, 0x95, 0xA6, 0xD8,
- 0x1A, 0x7B, 0x76, 0xDC, 0x1F, 0x03, 0xAE, 0xB6, 0xD7, 0xB8, 0xBD, 0xF9,
- 0xFC, 0x05, 0xF5, 0x91, 0x90, 0xE9, 0xD6, 0x19, 0x6E, 0x51, 0x5A, 0xD2,
- 0xA8, 0xCC, 0xE8, 0x1A, 0xC2, 0x2F, 0x67, 0x5E, 0xA8, 0x09, 0xAB, 0xCB,
- 0xE0, 0x03, 0x37, 0xA4, 0x3D, 0xB5, 0x18, 0x75, 0x4B, 0x0E, 0x21, 0x0E,
- 0x59, 0xD5, 0xC8, 0x67, 0xA9, 0x6C, 0xF0, 0x9B, 0x9C, 0x67, 0xA3, 0x71,
- 0x9B, 0xDC, 0xE0, 0x2A, 0x36, 0xAC, 0x97, 0xD2, 0xFA, 0xFA, 0x5B, 0x94,
- 0x38, 0x9B, 0x11, 0x27, 0x75, 0x86, 0x36, 0x01, 0xA3, 0x27, 0xD1, 0x60,
- 0x8F, 0x8E, 0x07, 0x02, 0xBD, 0x36, 0x64, 0x03, 0x58, 0xA3, 0x31, 0x27,
- 0x3B, 0xB0, 0xD2, 0xB2, 0x7F, 0xE2, 0x70, 0x9C, 0xF7, 0x2C, 0x2A, 0x49,
- 0xD4, 0x78, 0x5E, 0x34, 0xCC, 0x21, 0x28, 0x69, 0x57, 0x32, 0x60, 0xE5,
- 0xD6, 0xBD, 0x6F, 0x84, 0x7A, 0x83, 0x9E, 0xCF, 0x31, 0x04, 0xFB, 0x35,
- 0x4D, 0xA7, 0x69, 0x4A, 0xD4, 0x4C, 0x9C, 0x18, 0xD7, 0xA7, 0xC3, 0xA5,
- 0xD7, 0xA7, 0x0F, 0xF9, 0x76, 0x57, 0x54, 0xBB, 0x4F, 0x42, 0xBD, 0x4C,
- 0x3D, 0xEA, 0x81, 0xBC, 0x87, 0xA3, 0x3F, 0x23, 0x3B, 0x71, 0x7C, 0x38,
- 0x43, 0x59, 0xA1, 0x6A, 0xD4, 0x41, 0x58, 0x07, 0x35, 0xC1, 0x38, 0xA8,
- 0xDE, 0x91, 0xD4, 0x82, 0x89, 0xD4, 0x93, 0xE3, 0xC0, 0xBA, 0xDF, 0xC0,
- 0x9B, 0x2E, 0x4C, 0xCA, 0x51, 0x94, 0x69, 0xD9, 0x07, 0xC7, 0x87, 0x31,
- 0x7C, 0x08, 0xED, 0x8D, 0x51, 0xAC, 0xBF, 0x6F, 0x90, 0xD8, 0x94, 0xC6,
- 0x3A, 0xAB, 0x90, 0x57, 0x6B, 0x7C, 0xCF, 0xAA, 0xBC, 0xDA, 0x44, 0x91,
- 0xA7, 0xBC, 0xBE, 0x2F, 0x1F, 0x6B, 0x3C, 0x65, 0xFB, 0x7D, 0x56, 0xD4,
- 0xF9, 0xAE, 0x42, 0xB9, 0xC7, 0xB6, 0x2C, 0xEE, 0xF2, 0x3A, 0x2F, 0x0B,
- 0xB9, 0xFD, 0x40, 0x56, 0x3C, 0xE3, 0x67, 0x5E, 0xDC, 0x6D, 0x40, 0x12,
- 0x99, 0xEC, 0xA1, 0x57, 0xEB, 0xA2, 0x03, 0xC1, 0xE4, 0x18, 0x27, 0xB5,
- 0x73, 0x76, 0x15, 0xD1, 0x07, 0x84, 0xCE, 0x5C, 0x90, 0xBC, 0xA5, 0x86,
- 0x3B, 0x6E, 0xC4, 0x9A, 0xEE, 0x47, 0xD5, 0x13, 0x7A, 0xF3, 0x97, 0x9C,
- 0x16, 0x47, 0xB0, 0xE4, 0x4E, 0xEC, 0xE3, 0xB3, 0x7A, 0x01, 0x6C, 0xA3,
- 0xCC, 0xC0, 0x27, 0x0E, 0x2A, 0xCC, 0xBF, 0xFE, 0xF3, 0x95, 0xAC, 0xFE,
- 0x01};
-
-const Buffer kPuff10 = {
- 0x00, 0x74, 0xC0, 0x0C, 0x11, 0x0C, 0x04, 0x63, 0x34, 0x32, 0x03, 0x04,
- 0x05, 0x06, 0x1B, 0x07, 0x26, 0x03, 0x00, 0x07, 0x16, 0x08, 0x08, 0x00,
- 0x00, 0x07, 0x09, 0x06, 0x06, 0x08, 0x09, 0x08, 0x15, 0x09, 0x00, 0x00,
- 0x09, 0x09, 0x16, 0x06, 0x09, 0x07, 0x08, 0x07, 0x09, 0x00, 0x08, 0x06,
- 0x00, 0x09, 0x08, 0x00, 0x06, 0x06, 0x09, 0x00, 0x07, 0x06, 0x06, 0x08,
- 0x09, 0x08, 0x00, 0x08, 0x18, 0x05, 0x07, 0x06, 0x06, 0x04, 0x06, 0x06,
- 0x07, 0x04, 0x08, 0x00, 0x06, 0x07, 0x05, 0x05, 0x05, 0x09, 0x05, 0x05,
- 0x05, 0x06, 0x09, 0x06, 0x08, 0x07, 0x97, 0x09, 0x04, 0x05, 0x06, 0x07,
- 0x06, 0x08, 0x00, 0x00, 0x08, 0x08, 0x00, 0x09, 0x05, 0x15, 0x06, 0x00,
- 0x05, 0x06, 0x04, 0x04, 0x04, 0x03, 0x04, 0x02, 0x03, 0x03, 0x05, 0x39,
- 0x0A, 0x2F, 0x2F, 0x0A, 0x2F, 0x2F, 0x20, 0x43, 0x6F, 0x70, 0x79, 0x72,
- 0x69, 0x67, 0x68, 0x74, 0x20, 0x28, 0x43, 0x29, 0x20, 0x32, 0x30, 0x31,
- 0x37, 0x20, 0x54, 0x68, 0x65, 0x20, 0x41, 0x6E, 0x64, 0x72, 0x6F, 0x69,
- 0x64, 0x20, 0x4F, 0x70, 0x65, 0x6E, 0x20, 0x53, 0x6F, 0x75, 0x72, 0x63,
- 0x65, 0x20, 0x50, 0x72, 0x6F, 0x6A, 0x65, 0x63, 0x74, 0x0A, 0x83, 0x00,
- 0x38, 0x0F, 0x4C, 0x69, 0x63, 0x65, 0x6E, 0x73, 0x65, 0x64, 0x20, 0x75,
- 0x6E, 0x64, 0x65, 0x72, 0x20, 0x74, 0x81, 0x00, 0x34, 0x02, 0x70, 0x61,
- 0x63, 0x80, 0x00, 0x06, 0x84, 0x00, 0x19, 0x0E, 0x2C, 0x20, 0x56, 0x65,
- 0x72, 0x73, 0x69, 0x6F, 0x6E, 0x20, 0x32, 0x2E, 0x30, 0x20, 0x28, 0x81,
- 0x00, 0x20, 0x00, 0x22, 0x84, 0x00, 0x1A, 0x02, 0x22, 0x29, 0x3B, 0x81,
- 0x00, 0x42, 0x0E, 0x79, 0x6F, 0x75, 0x20, 0x6D, 0x61, 0x79, 0x20, 0x6E,
- 0x6F, 0x74, 0x20, 0x75, 0x73, 0x65, 0x80, 0x00, 0x43, 0x19, 0x69, 0x73,
- 0x20, 0x66, 0x69, 0x6C, 0x65, 0x20, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74,
- 0x20, 0x69, 0x6E, 0x20, 0x63, 0x6F, 0x6D, 0x70, 0x6C, 0x69, 0x61, 0x6E,
- 0x80, 0x00, 0x7F, 0x03, 0x77, 0x69, 0x74, 0x68, 0x82, 0x00, 0x67, 0x84,
- 0x00, 0x45, 0x00, 0x2E, 0x81, 0x00, 0x43, 0x00, 0x59, 0x84, 0x00, 0x43,
- 0x03, 0x6F, 0x62, 0x74, 0x61, 0x80, 0x00, 0x2E, 0x00, 0x61, 0x80, 0x00,
- 0x30, 0x00, 0x70, 0x80, 0x00, 0x0D, 0x00, 0x66, 0x89, 0x00, 0x28, 0x01,
- 0x20, 0x61, 0x85, 0x00, 0xB4, 0x82, 0x00, 0x00, 0x0B, 0x68, 0x74, 0x74,
- 0x70, 0x3A, 0x2F, 0x2F, 0x77, 0x77, 0x77, 0x2E, 0x61, 0x82, 0x00, 0xB1,
- 0x05, 0x2E, 0x6F, 0x72, 0x67, 0x2F, 0x6C, 0x83, 0x00, 0x2B, 0x09, 0x73,
- 0x2F, 0x4C, 0x49, 0x43, 0x45, 0x4E, 0x53, 0x45, 0x2D, 0x80, 0x00, 0xB5,
- 0x84, 0x00, 0x35, 0x0C, 0x55, 0x6E, 0x6C, 0x65, 0x73, 0x73, 0x20, 0x72,
- 0x65, 0x71, 0x75, 0x69, 0x72, 0x80, 0x00, 0xF1, 0x04, 0x62, 0x79, 0x20,
- 0x61, 0x70, 0x80, 0x00, 0x95, 0x02, 0x63, 0x61, 0x62, 0x80, 0x00, 0xAB,
- 0x0A, 0x6C, 0x61, 0x77, 0x20, 0x6F, 0x72, 0x20, 0x61, 0x67, 0x72, 0x65,
- 0x80, 0x00, 0x1B, 0x01, 0x74, 0x6F, 0x81, 0x00, 0xB5, 0x10, 0x77, 0x72,
- 0x69, 0x74, 0x69, 0x6E, 0x67, 0x2C, 0x20, 0x73, 0x6F, 0x66, 0x74, 0x77,
- 0x61, 0x72, 0x65, 0x81, 0x00, 0x46, 0x08, 0x64, 0x69, 0x73, 0x74, 0x72,
- 0x69, 0x62, 0x75, 0x74, 0x8A, 0x01, 0x34, 0x85, 0x00, 0xA3, 0x80, 0x00,
- 0xFA, 0x89, 0x00, 0x20, 0x80, 0x01, 0x36, 0x10, 0x61, 0x6E, 0x20, 0x22,
- 0x41, 0x53, 0x20, 0x49, 0x53, 0x22, 0x20, 0x42, 0x41, 0x53, 0x49, 0x53,
- 0x2C, 0x81, 0x00, 0x44, 0x1E, 0x57, 0x49, 0x54, 0x48, 0x4F, 0x55, 0x54,
- 0x20, 0x57, 0x41, 0x52, 0x52, 0x41, 0x4E, 0x54, 0x49, 0x45, 0x53, 0x20,
- 0x4F, 0x52, 0x20, 0x43, 0x4F, 0x4E, 0x44, 0x49, 0x54, 0x49, 0x4F, 0x4E,
- 0x80, 0x00, 0x0D, 0x0C, 0x46, 0x20, 0x41, 0x4E, 0x59, 0x20, 0x4B, 0x49,
- 0x4E, 0x44, 0x2C, 0x20, 0x65, 0x80, 0x01, 0x32, 0x80, 0x00, 0x67, 0x03,
- 0x65, 0x78, 0x70, 0x72, 0x81, 0x00, 0xC1, 0x80, 0x00, 0xA6, 0x00, 0x69,
- 0x81, 0x01, 0x4E, 0x01, 0x65, 0x64, 0x82, 0x01, 0x3B, 0x02, 0x53, 0x65,
- 0x65, 0x8A, 0x00, 0x82, 0x01, 0x66, 0x6F, 0x83, 0x00, 0x92, 0x07, 0x73,
- 0x70, 0x65, 0x63, 0x69, 0x66, 0x69, 0x63, 0x80, 0x00, 0xDA, 0x0C, 0x6E,
- 0x67, 0x75, 0x61, 0x67, 0x65, 0x20, 0x67, 0x6F, 0x76, 0x65, 0x72, 0x6E,
- 0x80, 0x00, 0xD1, 0x06, 0x20, 0x70, 0x65, 0x72, 0x6D, 0x69, 0x73, 0x81,
- 0x01, 0xD6, 0x00, 0x73, 0x80, 0x00, 0xA0, 0x00, 0x64, 0x81, 0x00, 0x46,
- 0x06, 0x6C, 0x69, 0x6D, 0x69, 0x74, 0x61, 0x74, 0x82, 0x00, 0x12, 0x8E,
- 0x00, 0xD7, 0x01, 0x2E, 0x0A, 0xFF, 0x81};
-
-// The following is a sequence of bits starting from the top right and ends in
-// bottom left. It represents the bits in |kDeflate11|. Bits inside the brackets
-// (including bits exactly under brackets) represent a deflate stream.
-//
-// } { } { }{ }
-// 11000101 10000000 10001100 01010000 00010001 10001000 00000100 01100010
-// 0xC5 0x80 0x8C 0x50 0x11 0x88 0x04 0x62
-//
-// } { } { } {
-// 10001011 11111100 00000100 01100010 00000001 00011000 10111000 00001000
-// 0x8B 0xFC 0x04 0x62 0x01 0x18 0xB8 0x08
-//
-// } { } { }{
-// 10001011 00000001 00011000 10111111 11000000 01000110 00100000 00010001
-// 0x8B 0x01 0x18 0xBF 0xC0 0x46 0x20 0x11
-//
-// { } { } {
-// 11111100 00000100 01100010 11111111 00000001 00011000 10110000 00010001
-// 0xFC 0x04 0x62 0xFF 0x01 0x18 0xB0 0x11
-//
-const Buffer kDeflate11 = {
- 0x62, 0x04, 0x88, 0x11, 0x50, 0x8C, 0x80, 0xC5, 0x08, 0xB8, 0x18, 0x01,
- 0x62, 0x04, 0xFC, 0x8B, 0x11, 0x20, 0x46, 0xC0, 0xBF, 0x18, 0x01, 0x8B,
- 0x11, 0xB0, 0x18, 0x01, 0xFF, 0x62, 0x04, 0xFC};
-
-const Buffer kPuff11 = {
- /* puff 0 */ 0x00, 0x00, 0x20, 0x00, 0x01, 0xFF, 0x81,
- /* puff 7 */ 0x00, 0x00, 0x20, 0x00, 0x01, 0xFF, 0x81,
- /* raw 14 */ 0x01,
- /* puff 15 */ 0x00, 0x00, 0x20, 0x00, 0x01, 0xFF, 0x81,
- /* raw 22 */ 0x01, 0x01,
- /* puff 24 */ 0x00, 0x00, 0x20, 0x00, 0x01, 0xFF, 0x81,
- /* raw 31 */ 0x07,
- /* puff 32 */ 0x00, 0x00, 0x20, 0x00, 0x01, 0xFF, 0x81,
- /* puff 39 */ 0x00, 0x00, 0x20, 0x00, 0x01, 0xFF, 0x81,
- /* raw 46 */ 0x3F, 0x03,
- /* puff 48 */ 0x00, 0x00, 0x20, 0x00, 0x01, 0xFF, 0x81,
- /* puff 55 */ 0x00, 0x00, 0x20, 0x00, 0x01, 0xFF, 0x81,
- /* raw 62 */ 0x03, 0x3F,
- /* puff 64 */ 0x00, 0x00, 0x20, 0x00, 0x01, 0xFF, 0x81,
- /* raw 71 */ 0x03,
- /* puff 72 */ 0x00, 0x00, 0x20, 0x00, 0x01, 0xFF, 0x81,
- /* raw 79 */ 0x03,
- /* puff 80 */ 0x00, 0x00, 0x20, 0x00, 0x01, 0xFF, 0x81,
- /* raw 87 */ 0xFF,
- /* puff 88 */ 0x00, 0x00, 0x20, 0x00, 0x01, 0xFF, 0x81,
- /* raw 95 */ 0x3F};
-
-// The fifth deflate (and its puff in kPuffExtents11) is for zero length deflate
-// corner case.
-const std::vector<BitExtent> kSubblockDeflateExtents11 = {
- {0, 18}, {18, 18}, {37, 18}, {57, 18}, {75, 0}, {78, 18}, {96, 18}, {122, 18},
- {140, 18}, {166, 18}, {186, 18}, {206, 18}, {232, 18}};
-
-const std::vector<ByteExtent> kPuffExtents11 = {
- {0, 7}, {7, 7}, {15, 7}, {24, 7}, {31, 0}, {32, 7}, {39, 7}, {48, 7}, {55, 7},
- {64, 7}, {72, 7}, {80, 7}, {88, 7}};
-
-// clang-format on
+extern const Buffer kDeflatesSample2;
+extern const Buffer kPuffsSample2;
+extern const std::vector<ByteExtent> kDeflateExtentsSample2;
+extern const std::vector<BitExtent> kSubblockDeflateExtentsSample2;
+extern const std::vector<ByteExtent> kPuffExtentsSample2;
} // namespace puffin
diff --git a/src/utils.cc b/src/utils.cc
index 5019d0b..668ec3f 100644
--- a/src/utils.cc
+++ b/src/utils.cc
@@ -6,19 +6,22 @@
#include <inttypes.h>
+#include <algorithm>
+#include <set>
#include <string>
#include <vector>
-#include <zlib.h>
-
#include "puffin/src/bit_reader.h"
#include "puffin/src/file_stream.h"
#include "puffin/src/include/puffin/common.h"
-#include "puffin/src/include/puffin/errors.h"
#include "puffin/src/include/puffin/puffer.h"
+#include "puffin/src/logging.h"
#include "puffin/src/memory_stream.h"
#include "puffin/src/puff_writer.h"
-#include "puffin/src/set_errors.h"
+
+using std::set;
+using std::string;
+using std::vector;
namespace {
// Use memcpy to access the unaligned data of type |T|.
@@ -29,62 +32,62 @@
return result;
}
-// Calculate both the compressed size and uncompressed size of the deflate
-// block that starts from the offset |start| of buffer |data|.
-bool CalculateSizeOfDeflateBlock(const puffin::Buffer& data,
- uint64_t start,
- uint64_t* compressed_size,
- uint64_t* uncompressed_size) {
- TEST_AND_RETURN_FALSE(compressed_size != nullptr &&
- uncompressed_size != nullptr);
+struct ExtentData {
+ puffin::BitExtent extent;
+ uint64_t byte_offset;
+ uint64_t byte_length;
+ const puffin::Buffer& data;
- TEST_AND_RETURN_FALSE(start < data.size());
-
- z_stream strm = {};
- strm.avail_in = data.size() - start;
- strm.next_in = data.data() + start;
-
- // -15 means we are decoding a 'raw' stream without zlib headers.
- if (inflateInit2(&strm, -15)) {
- LOG(ERROR) << "Failed to initialize inflate: " << strm.msg;
- return false;
+ ExtentData(const puffin::BitExtent& in_extent, const puffin::Buffer& in_data)
+ : extent(in_extent), data(in_data) {
+ // Round start offset up and end offset down to exclude bits not in this
+ // extent. We simply ignore the bits at start and end that's not on byte
+ // boundary because as long as the majority of the bytes are the same,
+ // bsdiff will be able to reference it.
+ byte_offset = (extent.offset + 7) / 8;
+ uint64_t byte_end_offset = (extent.offset + extent.length) / 8;
+ CHECK(byte_end_offset <= data.size());
+ if (byte_end_offset > byte_offset) {
+ byte_length = byte_end_offset - byte_offset;
+ } else {
+ byte_length = 0;
+ }
}
- const unsigned int kBufferSize = 32768;
- std::vector<uint8_t> uncompressed_data(kBufferSize);
- *uncompressed_size = 0;
- int status = Z_OK;
- do {
- // Overwrite the same buffer since we don't need the uncompressed data.
- strm.avail_out = kBufferSize;
- strm.next_out = uncompressed_data.data();
- status = inflate(&strm, Z_NO_FLUSH);
- if (status < 0) {
- LOG(ERROR) << "Inflate failed: " << strm.msg << ", has decompressed "
- << *uncompressed_size << " bytes.";
- return false;
+ int Compare(const ExtentData& other) const {
+ if (extent.length != other.extent.length) {
+ return extent.length < other.extent.length ? -1 : 1;
}
- *uncompressed_size += kBufferSize - strm.avail_out;
- } while (status != Z_STREAM_END);
-
- *compressed_size = data.size() - start - strm.avail_in;
- TEST_AND_RETURN_FALSE(inflateEnd(&strm) == Z_OK);
- return true;
-}
+ return memcmp(data.data() + byte_offset,
+ other.data.data() + other.byte_offset,
+ std::min(byte_length, other.byte_length));
+ }
+ bool operator<(const ExtentData& other) const { return Compare(other) < 0; }
+ bool operator==(const ExtentData& other) const { return Compare(other) == 0; }
+};
} // namespace
namespace puffin {
-using std::string;
-using std::vector;
-
-uint64_t BytesInByteExtents(const vector<ByteExtent>& extents) {
- uint64_t bytes = 0;
- for (const auto& extent : extents) {
- bytes += extent.length;
+bool LocateDeflatesInDeflateStream(const uint8_t* data,
+ uint64_t size,
+ uint64_t virtual_offset,
+ vector<BitExtent>* deflates,
+ uint64_t* compressed_size) {
+ Puffer puffer;
+ BufferBitReader bit_reader(data, size);
+ BufferPuffWriter puff_writer(nullptr, 0);
+ vector<BitExtent> sub_deflates;
+ TEST_AND_RETURN_FALSE(
+ puffer.PuffDeflate(&bit_reader, &puff_writer, &sub_deflates));
+ for (const auto& deflate : sub_deflates) {
+ deflates->emplace_back(deflate.offset + virtual_offset * 8, deflate.length);
}
- return bytes;
+ if (compressed_size) {
+ *compressed_size = bit_reader.Offset();
+ }
+ return true;
}
// This function uses RFC1950 (https://www.ietf.org/rfc/rfc1950.txt) for the
@@ -93,7 +96,7 @@
// stream should be known before hand. Otherwise we need to parse the stream and
// find the location of compressed blocks using CalculateSizeOfDeflateBlock().
bool LocateDeflatesInZlib(const Buffer& data,
- std::vector<ByteExtent>* deflate_blocks) {
+ std::vector<BitExtent>* deflates) {
// A zlib stream has the following format:
// 0 1 compression method and flag
// 1 1 flag
@@ -119,7 +122,9 @@
}
// 4 is for ADLER32.
- deflate_blocks->emplace_back(header_len, data.size() - header_len - 4);
+ TEST_AND_RETURN_FALSE(LocateDeflatesInDeflateStream(
+ data.data() + header_len, data.size() - header_len - 4, header_len,
+ deflates, nullptr));
return true;
}
@@ -136,11 +141,13 @@
// Find all the subblocks.
BufferBitReader bit_reader(deflate_buffer.data(), deflate.length);
+ // The uncompressed blocks will be ignored since we are passing a null
+ // buffered puff writer and a valid deflate locations output array. This
+ // should not happen in the puffdiff or anywhere else by default.
BufferPuffWriter puff_writer(nullptr, 0);
- Error error;
vector<BitExtent> subblocks;
TEST_AND_RETURN_FALSE(
- puffer.PuffDeflate(&bit_reader, &puff_writer, &subblocks, &error));
+ puffer.PuffDeflate(&bit_reader, &puff_writer, &subblocks));
TEST_AND_RETURN_FALSE(deflate.length == bit_reader.Offset());
for (const auto& subblock : subblocks) {
subblock_deflates->emplace_back(subblock.offset + deflate.offset * 8,
@@ -157,22 +164,14 @@
TEST_AND_RETURN_FALSE(src);
Buffer buffer;
- for (auto& zlib : zlibs) {
+ for (const auto& zlib : zlibs) {
buffer.resize(zlib.length);
TEST_AND_RETURN_FALSE(src->Seek(zlib.offset));
TEST_AND_RETURN_FALSE(src->Read(buffer.data(), buffer.size()));
-
- vector<ByteExtent> deflate_blocks;
- TEST_AND_RETURN_FALSE(LocateDeflatesInZlib(buffer, &deflate_blocks));
-
- vector<BitExtent> deflate_subblocks;
- auto zlib_blc_src = MemoryStream::CreateForRead(buffer);
- TEST_AND_RETURN_FALSE(
- FindDeflateSubBlocks(zlib_blc_src, deflate_blocks, &deflate_subblocks));
-
- // Relocated based on the offset of the zlib.
- for (const auto& def : deflate_subblocks) {
- deflates->emplace_back(zlib.offset * 8 + def.offset, def.length);
+ vector<BitExtent> tmp_deflates;
+ TEST_AND_RETURN_FALSE(LocateDeflatesInZlib(buffer, &tmp_deflates));
+ for (const auto& deflate : tmp_deflates) {
+ deflates->emplace_back(deflate.offset + zlib.offset * 8, deflate.length);
}
}
return true;
@@ -180,8 +179,7 @@
// For more information about gzip format, refer to RFC 1952 located at:
// https://www.ietf.org/rfc/rfc1952.txt
-bool LocateDeflatesInGzip(const Buffer& data,
- vector<ByteExtent>* deflate_blocks) {
+bool LocateDeflatesInGzip(const Buffer& data, vector<BitExtent>* deflates) {
uint64_t member_start = 0;
while (member_start < data.size()) {
// Each member entry has the following format
@@ -230,21 +228,15 @@
offset += 2;
}
- uint64_t compressed_size, uncompressed_size;
- TEST_AND_RETURN_FALSE(CalculateSizeOfDeflateBlock(
- data, offset, &compressed_size, &uncompressed_size));
- TEST_AND_RETURN_FALSE(offset + compressed_size <= data.size());
- deflate_blocks->push_back(ByteExtent(offset, compressed_size));
+ uint64_t compressed_size = 0;
+ TEST_AND_RETURN_FALSE(LocateDeflatesInDeflateStream(
+ data.data() + offset, data.size() - offset, offset, deflates,
+ &compressed_size));
offset += compressed_size;
- // Ignore CRC32;
+ // Ignore CRC32 and uncompressed size.
TEST_AND_RETURN_FALSE(offset + 8 <= data.size());
- offset += 4;
- uint32_t u_size = 0;
- for (size_t i = 0; i < 4; i++) {
- u_size |= static_cast<uint32_t>(data[offset++]) << (i * 8);
- }
- TEST_AND_RETURN_FALSE(uncompressed_size % (1 << 31) == u_size);
+ offset += 8;
member_start = offset;
}
return true;
@@ -253,7 +245,7 @@
// For more information about the zip format, refer to
// https://support.pkware.com/display/PKZIP/APPNOTE
bool LocateDeflatesInZipArchive(const Buffer& data,
- vector<ByteExtent>* deflate_blocks) {
+ vector<BitExtent>* deflates) {
uint64_t pos = 0;
while (pos <= data.size() - 30) {
// TODO(xunchang) add support for big endian system when searching for
@@ -283,7 +275,6 @@
}
auto compressed_size = get_unaligned<uint32_t>(data.data() + pos + 18);
- auto uncompressed_size = get_unaligned<uint32_t>(data.data() + pos + 22);
auto file_name_length = get_unaligned<uint16_t>(data.data() + pos + 26);
auto extra_field_length = get_unaligned<uint16_t>(data.data() + pos + 28);
uint64_t header_size = 30 + file_name_length + extra_field_length;
@@ -295,33 +286,26 @@
continue;
}
- uint64_t calculated_compressed_size;
- uint64_t calculated_uncompressed_size;
- if (!CalculateSizeOfDeflateBlock(data, pos + header_size,
- &calculated_compressed_size,
- &calculated_uncompressed_size)) {
+ vector<BitExtent> tmp_deflates;
+ uint64_t offset = pos + header_size;
+ uint64_t calculated_compressed_size = 0;
+ if (!LocateDeflatesInDeflateStream(
+ data.data() + offset, data.size() - offset, offset, &tmp_deflates,
+ &calculated_compressed_size)) {
LOG(ERROR) << "Failed to decompress the zip entry starting from: " << pos
<< ", skip adding deflates for this entry.";
pos += 4;
continue;
}
- // Double check the compressed size and uncompressed size if they are
- // available in the file header.
+ // Double check the compressed size if it is available in the file header.
if (compressed_size > 0 && compressed_size != calculated_compressed_size) {
LOG(WARNING) << "Compressed size in the file header: " << compressed_size
<< " doesn't equal the real size: "
<< calculated_compressed_size;
}
- if (uncompressed_size > 0 &&
- uncompressed_size != calculated_uncompressed_size) {
- LOG(WARNING) << "Uncompressed size in the file header: "
- << uncompressed_size << " doesn't equal the real size: "
- << calculated_uncompressed_size;
- }
-
- deflate_blocks->emplace_back(pos + header_size, calculated_compressed_size);
+ deflates->insert(deflates->end(), tmp_deflates.begin(), tmp_deflates.end());
pos += header_size + calculated_compressed_size;
}
@@ -330,13 +314,7 @@
bool LocateDeflateSubBlocksInZipArchive(const Buffer& data,
vector<BitExtent>* deflates) {
- vector<ByteExtent> deflate_blocks;
- if (!LocateDeflatesInZipArchive(data, &deflate_blocks)) {
- return false;
- }
-
- auto src = MemoryStream::CreateForRead(data);
- return FindDeflateSubBlocks(src, deflate_blocks, deflates);
+ return LocateDeflatesInZipArchive(data, deflates);
}
bool FindPuffLocations(const UniqueStreamPtr& src,
@@ -366,9 +344,8 @@
bit_reader.DropBits(bits_to_skip);
BufferPuffWriter puff_writer(nullptr, 0);
- Error error;
TEST_AND_RETURN_FALSE(
- puffer.PuffDeflate(&bit_reader, &puff_writer, nullptr, &error));
+ puffer.PuffDeflate(&bit_reader, &puff_writer, nullptr));
TEST_AND_RETURN_FALSE(deflate_buffer.size() == bit_reader.Offset());
// 1 if a deflate ends at the same byte that the next deflate starts and
@@ -409,4 +386,31 @@
return true;
}
+void RemoveEqualBitExtents(const Buffer& data1,
+ const Buffer& data2,
+ std::vector<BitExtent>* extents1,
+ std::vector<BitExtent>* extents2) {
+ set<ExtentData> extent1_set, equal_extents;
+ for (const BitExtent& ext : *extents1) {
+ extent1_set.emplace(ext, data1);
+ }
+
+ auto new_extents2_end = extents2->begin();
+ for (const BitExtent& ext : *extents2) {
+ ExtentData extent_data(ext, data2);
+ if (extent1_set.find(extent_data) != extent1_set.end()) {
+ equal_extents.insert(extent_data);
+ } else {
+ *new_extents2_end++ = ext;
+ }
+ }
+ extents2->erase(new_extents2_end, extents2->end());
+ extents1->erase(
+ std::remove_if(extents1->begin(), extents1->end(),
+ [&equal_extents, &data1](const BitExtent& ext) {
+ return equal_extents.find(ExtentData(ext, data1)) !=
+ equal_extents.end();
+ }),
+ extents1->end());
+}
} // namespace puffin
diff --git a/src/utils_unittest.cc b/src/utils_unittest.cc
index e1fbb25..737b765 100644
--- a/src/utils_unittest.cc
+++ b/src/utils_unittest.cc
@@ -14,11 +14,11 @@
#include "puffin/src/memory_stream.h"
#include "puffin/src/unittest_common.h"
-namespace puffin {
-
using std::string;
using std::vector;
+namespace puffin {
+
namespace {
const uint8_t kZipEntries[] = {
0x50, 0x4b, 0x03, 0x04, 0x14, 0x00, 0x02, 0x00, 0x08, 0x00, 0xfc, 0x88,
@@ -79,9 +79,9 @@
// echo "0123456789" | zlib-flate -compress |
// hexdump -v -e '12/1 "0x%02x, " "\n"'
-const uint8_t kZlibEntry[] = {
- 0x78, 0x9c, 0x33, 0x30, 0x34, 0x32, 0x36, 0x31, 0x35, 0x33, 0xb7, 0xb0,
- 0xe4, 0x02, 0x00, 0x0d, 0x17, 0x02, 0x18};
+const uint8_t kZlibEntry[] = {0x78, 0x9c, 0x33, 0x30, 0x34, 0x32, 0x36,
+ 0x31, 0x35, 0x33, 0xb7, 0xb0, 0xe4, 0x02,
+ 0x00, 0x0d, 0x17, 0x02, 0x18};
void FindDeflatesInZlibBlocks(const Buffer& src,
const vector<ByteExtent>& zlibs,
@@ -114,21 +114,21 @@
// Test Simple Puffing of the source.
TEST(UtilsTest, FindPuffLocations1Test) {
- CheckFindPuffLocation(kDeflates8, kSubblockDeflateExtents8, kPuffExtents8,
- kPuffs8.size());
+ CheckFindPuffLocation(kDeflatesSample1, kSubblockDeflateExtentsSample1,
+ kPuffExtentsSample1, kPuffsSample1.size());
}
TEST(UtilsTest, FindPuffLocations2Test) {
- CheckFindPuffLocation(kDeflates9, kSubblockDeflateExtents9, kPuffExtents9,
- kPuffs9.size());
+ CheckFindPuffLocation(kDeflatesSample2, kSubblockDeflateExtentsSample2,
+ kPuffExtentsSample2, kPuffsSample2.size());
}
TEST(UtilsTest, LocateDeflatesInZlib) {
Buffer zlib_data(kZlibEntry, std::end(kZlibEntry));
- vector<ByteExtent> deflates;
+ vector<BitExtent> deflates;
+ vector<BitExtent> expected_deflates = {{16, 98}};
EXPECT_TRUE(LocateDeflatesInZlib(zlib_data, &deflates));
- EXPECT_EQ(static_cast<size_t>(1), deflates.size());
- EXPECT_EQ(ByteExtent(2, 13), deflates[0]);
+ EXPECT_EQ(deflates, expected_deflates);
}
TEST(UtilsTest, LocateDeflatesInEmptyZlib) {
@@ -143,7 +143,7 @@
auto cmf = zlib_data[0];
auto flag = zlib_data[1];
- vector<ByteExtent> deflates;
+ vector<BitExtent> deflates;
zlib_data[0] = cmf & 0xF0;
EXPECT_FALSE(LocateDeflatesInZlib(zlib_data, &deflates));
zlib_data[0] = cmf | (8 << 4);
@@ -156,55 +156,72 @@
TEST(UtilsTest, LocateDeflatesInZipArchiveSmoke) {
Buffer zip_entries(kZipEntries, std::end(kZipEntries));
- vector<ByteExtent> deflates;
+ vector<BitExtent> deflates;
+ vector<BitExtent> expected_deflates = {{472, 46}, {992, 46}};
EXPECT_TRUE(LocateDeflatesInZipArchive(zip_entries, &deflates));
- EXPECT_EQ(static_cast<size_t>(2), deflates.size());
- EXPECT_EQ(ByteExtent(59, 6), deflates[0]);
- EXPECT_EQ(ByteExtent(124, 6), deflates[1]);
+ EXPECT_EQ(deflates, expected_deflates);
}
TEST(UtilsTest, LocateDeflatesInZipArchiveWithDataDescriptor) {
Buffer zip_entries(kZipEntryWithDataDescriptor,
std::end(kZipEntryWithDataDescriptor));
- vector<ByteExtent> deflates;
+ vector<BitExtent> deflates;
+ vector<BitExtent> expected_deflates = {{472, 46}, {1120, 46}};
EXPECT_TRUE(LocateDeflatesInZipArchive(zip_entries, &deflates));
- EXPECT_EQ(static_cast<size_t>(2), deflates.size());
- EXPECT_EQ(ByteExtent(59, 6), deflates[0]);
- EXPECT_EQ(ByteExtent(140, 6), deflates[1]);
+ EXPECT_EQ(deflates, expected_deflates);
}
TEST(UtilsTest, LocateDeflatesInZipArchiveErrorChecks) {
Buffer zip_entries(kZipEntries, std::end(kZipEntries));
// Construct a invalid zip entry whose size overflows.
zip_entries[29] = 0xff;
- vector<ByteExtent> deflates_overflow;
+ vector<BitExtent> deflates_overflow;
+ vector<BitExtent> expected_deflates = {{992, 46}};
EXPECT_TRUE(LocateDeflatesInZipArchive(zip_entries, &deflates_overflow));
- EXPECT_EQ(static_cast<size_t>(1), deflates_overflow.size());
- EXPECT_EQ(ByteExtent(124, 6), deflates_overflow[0]);
+ EXPECT_EQ(deflates_overflow, expected_deflates);
zip_entries.resize(128);
- vector<ByteExtent> deflates_incomplete;
+ vector<BitExtent> deflates_incomplete;
EXPECT_TRUE(LocateDeflatesInZipArchive(zip_entries, &deflates_incomplete));
- EXPECT_EQ(static_cast<size_t>(0), deflates_incomplete.size());
+ EXPECT_TRUE(deflates_incomplete.empty());
}
TEST(UtilsTest, LocateDeflatesInGzip) {
Buffer gzip_data(kGzipEntryWithMultipleMembers,
std::end(kGzipEntryWithMultipleMembers));
- vector<ByteExtent> deflates;
+ vector<BitExtent> deflates;
+ vector<BitExtent> expected_deflates = {{160, 98}, {488, 98}};
EXPECT_TRUE(LocateDeflatesInGzip(gzip_data, &deflates));
- EXPECT_EQ(static_cast<size_t>(2), deflates.size());
- EXPECT_EQ(ByteExtent(20, 13), deflates[0]);
- EXPECT_EQ(ByteExtent(61, 13), deflates[1]);
+ EXPECT_EQ(deflates, expected_deflates);
}
TEST(UtilsTest, LocateDeflatesInGzipWithExtraField) {
Buffer gzip_data(kGzipEntryWithExtraField,
std::end(kGzipEntryWithExtraField));
- vector<ByteExtent> deflates;
+ vector<BitExtent> deflates;
+ vector<BitExtent> expected_deflates = {{256, 98}};
EXPECT_TRUE(LocateDeflatesInGzip(gzip_data, &deflates));
- EXPECT_EQ(static_cast<size_t>(1), deflates.size());
- EXPECT_EQ(ByteExtent(32, 13), deflates[0]);
+ EXPECT_EQ(deflates, expected_deflates);
+}
+
+TEST(UtilsTest, RemoveEqualBitExtents) {
+ Buffer data1 = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
+ Buffer data2 = {1, 2, 3, 4, 5, 5, 6, 7, 8, 9};
+ vector<BitExtent> ext1 = {{0, 10}, {10, 14}, {25, 15}, {40, 8}, {50, 23}};
+ vector<BitExtent> ext2 = {{0, 10}, {17, 15}, {32, 8}, {40, 8}, {50, 23}};
+ RemoveEqualBitExtents(data1, data2, &ext1, &ext2);
+ vector<BitExtent> expected_ext1 = {{0, 10}, {10, 14}};
+ EXPECT_EQ(expected_ext1, ext1);
+ vector<BitExtent> expected_ext2 = {{0, 10}};
+ EXPECT_EQ(expected_ext2, ext2);
+ RemoveEqualBitExtents(data1, data2, &ext1, &ext1);
+ EXPECT_EQ(expected_ext1, ext1);
+ RemoveEqualBitExtents(data1, data1, &ext1, &ext1);
+ EXPECT_TRUE(ext1.empty());
+ expected_ext1 = ext1 = {{0, 0}, {1, 1}, {2, 7}};
+ RemoveEqualBitExtents(data1, data2, &ext1, &ext2);
+ EXPECT_EQ(expected_ext1, ext1);
+ EXPECT_EQ(expected_ext2, ext2);
}
} // namespace puffin