#pragma region CPL License
/*
Nuclex Native Framework
Copyright (C) 2002-2013 Nuclex Development Labs
This library is free software; you can redistribute it and/or
modify it under the terms of the IBM Common Public License as
published by the IBM Corporation; either version 1.0 of the
License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
IBM Common Public License for more details.
You should have received a copy of the IBM Common Public
License along with this library
*/
#pragma endregion // CPL License
#ifndef NUCLEX_STORAGE_FILESYSTEM_SEVENZIP_DECODER_MULTIDECODERCONTEXT_H
#define NUCLEX_STORAGE_FILESYSTEM_SEVENZIP_DECODER_MULTIDECODERCONTEXT_H
#include "Nuclex/Storage/Config.h"
#include "../SevenZipArchive.h"
#include "../../../Helpers/StreamingCacheContext.h"
#include "lzma/LzmaDec.h"
namespace Nuclex { namespace Storage { namespace FileSystem { namespace SevenZip {
// ------------------------------------------------------------------------------------------- //
class StreamProcessor;
// ------------------------------------------------------------------------------------------- //
}}}} // namespace Nuclex::Storage::FileSystem::SevenZip
namespace Nuclex { namespace Storage { namespace FileSystem { namespace SevenZip {
// ------------------------------------------------------------------------------------------- //
///
/// Maintains the decompression states and buffers for multiple chained decoders
///
///
///
/// Currently this context is designed to assume one main input stream (containing
/// the data to be decompressed) and any number of control streams that are extracted
/// in full upfront (as they might contain data needed for decompression of the main
/// stream - like dictionaries, seek offsets or compression settings).
///
///
/// This assumption works for all current 7-Zip compression methods. All but one
/// operate in a single stream and the one that does not - BCJ2 - still uses
/// one main stream, one control stream and two supplemental streams that could
/// perhaps be streamed, but in practice are so small that the overhead would likely
/// offset any gain.
///
///
class MultiDecoderContext : public Helpers::StreamingCacheContext {
// LZMA requires a certain input length or there's no guarantee it can extract
// anything from the buffer (LZMA_REQUIRED_INPUT_MAX is the number of bytes the worst-case
// atomic chunk of compressed data can be long).
static_assert(
(BufferRefillSize >= LZMA_REQUIRED_INPUT_MAX),
"Low water mark for input buffer must be more than the minimum LZMA input length"
);
///
/// Initializes a new context for decoding data with multiple filters and/or
/// decompressors chained together
///
/// Archive the decoder context will work on
///
/// Index of the solid block this context will decode
///
public: MultiDecoderContext(
const std::shared_ptr &sevenZipArchive,
std::size_t solidBlockIndex
);
/// Adds a stream processor through which data will be processed
///
/// Stream processor that will be applied to data read from the context
///
public: void AddStreamProcessor(const std::shared_ptr &streamProcessor);
/// Skips forward until the specified location is reached
/// Location up to which data will be skipped
protected: void SkipTo(std::uint64_t location);
/// Extracts data directly into the caller-provided memory block
/// Location from which on extraction should begin
/// Buffer into which the data will be read
/// Number of bytes the caller wants to read
/// The number of bytes remaining to be extracted
protected: std::size_t ExtractDirectly(
std::uint8_t *indexableBuffer, std::size_t count
);
/// Extracts data using the decompression buffer and provides it
/// Location from which on extraction should begin
/// Buffer into which the data will be read
/// Number of bytes the caller wants to read
protected: void ExtractUsingBuffer(
std::uint8_t *indexableBuffer, std::size_t count
);
/// 7-zip archive the context is extracting
private: std::shared_ptr sevenZipArchive;
/// Current location within the compressed data
private: std::size_t inputBufferLocation;
/// Stream processors used by the reader to uncompress data
private: std::vector< std::shared_ptr > streamProcessors;
};
// ------------------------------------------------------------------------------------------- //
}}}} // namespace Nuclex::Storage::FileSystem::SevenZip
#endif // NUCLEX_STORAGE_FILESYSTEM_SEVENZIP_DECODER_MULTIDECODERCONTEXT_H