blob: b755a7e63643eef5d2b8a57e2f7a606cdf50e002 [file] [log] [blame]
// Copyright 2020 The Fuchsia 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_LIB_CHUNKED_COMPRESSION_CHUNKED_DECOMPRESSOR_H_
#define SRC_LIB_CHUNKED_COMPRESSION_CHUNKED_DECOMPRESSOR_H_
#include <memory>
#include <fbl/array.h>
#include <fbl/macros.h>
#include "chunked-archive.h"
#include "status.h"
namespace chunked_compression {
// ChunkedDecompressor allows chunked archives to be decompressed (either a frame at a time, or in
// full).
//
// Usage (error checks omitted):
//
// // Load the header into memory.
// const void* header = InputDataHeader();
// size_t header_length = 8192; // Read-ahead size for the file header
//
// size_t compressed_length = InputLength(); // Assume >8192
//
// HeaderReader reader;
// SeekTable table = reader.Parse(header, header_length, compressed_length);
//
// ChunkedDecompressor decompressor;
//
// size_t target_offset = TargetOffset();
// unsigned table_index = table.EntryForDecompressedOffset(TargetOffset()).get();
// const SeekTableEntry& entry = table.Entries()[table_index];
// fbl::Array<uint8_t> output_buffer(new uint8_t[entry.decompressed_size],
// entry.decompressed_size);
//
// size_t input_chunk_size = entry.compressed_size;
// const uint8_t *input_chunk = LoadCompressedData(entry.compressed_offset, input_chunk_size);
// size_t bytes_written;
// decompressor.DecompressFrame(table, table_index, input_chunk, input_chunk_size,
// output_buffer.get(), output_buffer.size(), &bytes_written);
class ChunkedDecompressor {
public:
ChunkedDecompressor();
~ChunkedDecompressor();
ChunkedDecompressor(ChunkedDecompressor&& o) = default;
ChunkedDecompressor& operator=(ChunkedDecompressor&& o) = default;
DISALLOW_COPY_AND_ASSIGN_ALLOW_MOVE(ChunkedDecompressor);
// Convenience method to do a one-shot decompression of |input|, returning an allocated buffer
// containing the decompressed bytes.
static Status DecompressBytes(const void* input, size_t len, fbl::Array<uint8_t>* output,
size_t* bytes_written_out);
// Returns the minimum size that a buffer must be to hold the result of decompressing the archive
// described by |table|.
static size_t ComputeOutputSize(const SeekTable& table) { return table.DecompressedSize(); }
// Reads the decompressed archive described by |table| from |input|, and writes the decompressed
// data to |output|.
//
// |input| should include the full archive contents, including the table itself. The table is
// not validated (having already been validated during construction of |table|).
// |output_len| must be at least |ComputeOutputSize(table)| bytes long.
//
// Returns the number of decompressed bytes written in |bytes_written_out|.
Status Decompress(const SeekTable& table, const void* input, size_t len, void* output,
size_t output_len, size_t* bytes_written_out);
// |input_frame| should start at the frame's first byte, and |input_frame_len| must be big enough
// to span the entire frame.
// |output| starts at the first byte to write the result, and |output_len| must be the resulting
// decompressed size.
//
// Returns the number of decompressed bytes written in |bytes_written_out|.
Status DecompressFrame(const void* input_frame, size_t input_frame_len, void* output,
size_t output_len, size_t* bytes_written_out);
// Reads the |table_index|'th frame of the decompressed archive described by |table| from
// |input_frame|, and writes the decompressed frame to |output|.
//
// |input_frame| should start at the frame's first byte, and |input_frame_len| must be big enough
// to span the entire frame.
// |output_len| must be at least as big as |table.Entries()[table_index].decompressed_size|.
//
// Returns the number of decompressed bytes written in |bytes_written_out|.
Status DecompressFrame(const SeekTable& table, unsigned table_index, const void* input_frame,
size_t input_frame_len, void* output, size_t output_len,
size_t* bytes_written_out);
private:
struct DecompressionContext;
std::unique_ptr<DecompressionContext> context_;
};
} // namespace chunked_compression
#endif // SRC_LIB_CHUNKED_COMPRESSION_CHUNKED_DECOMPRESSOR_H_