#pragma region CPL License
/*
Nuclex Native Framework
Copyright (C) 2002-2021 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_COMPRESSION_CSC_CSCCOMPRESSOR_H
#define NUCLEX_STORAGE_COMPRESSION_CSC_CSCCOMPRESSOR_H
#include "Nuclex/Storage/Config.h"
#if defined(NUCLEX_STORAGE_HAVE_CSC)
#include "Nuclex/Storage/Compression/Compressor.h"
#include "../../Helpers/WriteBuffer.h"
#include "CscHelper.h"
namespace Nuclex { namespace Storage { namespace Compression { namespace Csc {
// ------------------------------------------------------------------------------------------- //
/// Compresses data using the CSC library and algorithm
class CscCompressor : public Compressor {
/// Initializes a new CSC compressor
///
/// Compression level that will be passed to the CSC compressor
///
public: CscCompressor(int level = 2);
/// Frees all resources owned by the instance
public: ~CscCompressor() override;
///
/// Compresses the data in the input buffer and writes it to the output buffer
///
/// Buffer containing the uncompressed data
///
/// Number of uncompressed bytes in the uncompressed buffer. Will be set to
/// the number of remaining bytes when the method returns
///
/// Buffer in which the compressed data will be stored
///
/// Available space in the output buffer. Will be set to the bytes actually stored
/// in the output buffer when the method returns
///
///
/// The reason why the method stopped processing data. This may either be because
/// all available input was compressed, or because the compressor ran out of space
/// in the output buffer.
///
public: StopReason Process(
const std::uint8_t *uncompressedBuffer, std::size_t &uncompressedByteCount,
std::uint8_t *outputBuffer, std::size_t &outputByteCount
) override;
/// Finishes compressing and writes any remaining output bytes
/// Buffer in which the compressed data will be stored
///
/// Available space in the output buffer. Will be set to the bytes actually stored
/// in the output buffer when the method returns.
///
///
/// The reason why the method stopped processing. This should normally be the
/// value but may also be
/// if the output buffer was insufficient
/// to output all data (in which case you need to call Finish() another time).
///
public: StopReason Finish(
std::uint8_t *outputBuffer, std::size_t &outputByteCount
) override;
#pragma region class BufferedSequentialOuputStream
/// Implements a libcsc output stream into the split buffer writer>/summary>
private: class BufferedSequentialOuputStream : public ISeqOutStream {
/// Initializes a new buffered output stream
///
/// Split buffer writer into which all written data will be directed
///
public: BufferedSequentialOuputStream(Nuclex::Storage::Helpers::WriteBuffer &writeBuffer) :
writeBuffer(writeBuffer) {
this->Write = &write;
}
/// Method that is registered to libcsc as the write function pointer
/// Pointer to the output stream
/// Buffer holding the data that will be written
/// Number of bytes that will be written
/// The number of bytes actually written
private: static size_t write(void *self, const void *buffer, size_t byteCount) {
reinterpret_cast(self)->writeBuffer.Write(
reinterpret_cast(buffer), byteCount
);
return byteCount;
}
/// Split buffer writer into which all written data is directed
private: Nuclex::Storage::Helpers::WriteBuffer &writeBuffer;
};
#pragma endregion // class BufferedSequentialOuputStream
/// Allocator that allows libcsc to reuse memory
private: ReusingAllocator allocator;
/// Writes to the output buffer and holds onto data that doesn't fit
private: Nuclex::Storage::Helpers::WriteBuffer writeBuffer;
/// Holds a write function pointer and a pointer to the output buffer
private: BufferedSequentialOuputStream outputStream;
/// Properties the CSC encoder has been configured with
private: ::CSCProps encoderProperties;
/// Maintains the CSC encoder's state
private: ::CSCEncoder encoder;
/// IO handler for output data generated by the encoder
private: ::MemIO outputHandler;
/// Buffer storing data to be compressed
///
/// CSC doesn't do its own buffering and flushes the encoder after each Compress()
/// call, so compression ratio would be dependent on how you feed the compressor.
/// Thus, we collect data in this buffer until we have a full block before compressing.
///
private: std::uint8_t *inputBuffer;
/// Number of bytes currently stored in the input buffer
private: std::size_t inputBufferByteCount;
};
// ------------------------------------------------------------------------------------------- //
}}}} // namespace Nuclex::Storage::Compression::Csc
#endif // defined(NUCLEX_STORAGE_HAVE_CSC)
#endif // NUCLEX_STORAGE_COMPRESSION_CSC_CSCCOMPRESSOR_H