mirror of
https://git.rtems.org/rtems-tools/
synced 2025-06-01 02:01:27 +08:00
229 lines
7.1 KiB
C++
229 lines
7.1 KiB
C++
/*
|
|
* Copyright (c) 2012, Chris Johns <chrisj@rtems.org>
|
|
*
|
|
* Permission to use, copy, modify, and/or distribute this software for any
|
|
* purpose with or without fee is hereby granted, provided that the above
|
|
* copyright notice and this permission notice appear in all copies.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
*/
|
|
/**
|
|
* @file
|
|
*
|
|
* @ingroup rtems-ld
|
|
*
|
|
* @brief RTEMS Linker compression handles compressed images.
|
|
*
|
|
*/
|
|
|
|
#if !defined (_RLD_COMPRESSION_H_)
|
|
#define _RLD_COMPRESSION_H_
|
|
|
|
#include <rld-files.h>
|
|
|
|
namespace rld
|
|
{
|
|
namespace compress
|
|
{
|
|
/**
|
|
* A compressor.
|
|
*/
|
|
class compressor
|
|
{
|
|
public:
|
|
/**
|
|
* Construct the compressor for the given image.
|
|
*
|
|
* @param image The image to read or write to.
|
|
* @param size The size of the input and output buffers.
|
|
* @param out The compressor is compressing.
|
|
* @param compress Set to false to disable compression.
|
|
*/
|
|
compressor (files::image& image,
|
|
size_t size,
|
|
bool out = true,
|
|
bool compress = true);
|
|
|
|
/**
|
|
* Destruct the compressor.
|
|
*/
|
|
~compressor ();
|
|
|
|
/**
|
|
* Write the data to the output buffer and once the image buffer is full
|
|
* compress and write the compressed data to the image.
|
|
*
|
|
* @param data The data to write to the image compressed
|
|
* @param length The mount of data in bytes to write.
|
|
*/
|
|
void write (const void* data, size_t length);
|
|
|
|
/**
|
|
* Write the section of the input image file to the output buffer and
|
|
* once the image buffer is full compress and write the compressed data
|
|
* to the image.
|
|
*
|
|
* @param input The input image.
|
|
* @param offset The input image offset to read from.
|
|
* @param length The mount of data in bytes to write.
|
|
*/
|
|
void write (files::image& input, off_t offset, size_t length);
|
|
|
|
/**
|
|
* Flush the output buffer is data is present.
|
|
*/
|
|
void flush ();
|
|
|
|
/**
|
|
* Read the compressed data into the input buffer and return the section
|
|
* requested.
|
|
*
|
|
* @param data Write the decompressed data here.
|
|
* @param length The mount of data in bytes to read.
|
|
* @return size_t The amount of data read.
|
|
*/
|
|
size_t read (void* data, size_t length);
|
|
|
|
/**
|
|
* Read the decompressed data writing it to the image.
|
|
*
|
|
* @param output_ The output image.
|
|
* @param offset The output image offset to write from.
|
|
* @param length The mount of data in bytes to read.
|
|
* @return size_t The amount of data read.
|
|
*/
|
|
size_t read (files::image& output_, off_t offset, size_t length);
|
|
|
|
/**
|
|
* Read the decompressed data writing it to the image.
|
|
*
|
|
* @param output_ The output image.
|
|
* @param length The mount of data in bytes to read.
|
|
* @return size_t The amount of data read.
|
|
*/
|
|
size_t read (files::image& output_, size_t length);
|
|
|
|
/**
|
|
* The amount of uncompressed data transferred.
|
|
*
|
|
* @return size_t The amount of data tranferred.
|
|
*/
|
|
size_t transferred () const;
|
|
|
|
/**
|
|
* The amount of compressed data transferred.
|
|
*
|
|
* @return size_t The amount of compressed data tranferred.
|
|
*/
|
|
size_t compressed () const;
|
|
|
|
/**
|
|
* The current offset in the stream.
|
|
*
|
|
* @return off_t The current uncompressed offset.
|
|
*/
|
|
off_t offset () const;
|
|
|
|
private:
|
|
|
|
/**
|
|
* Output the block of data to the output file with the block header.
|
|
*
|
|
* @param forced If true output the buffer.
|
|
*/
|
|
void output (bool forced = false);
|
|
|
|
/**
|
|
* Input a block of compressed data and decompress it.
|
|
*/
|
|
void input ();
|
|
|
|
files::image& image; //< The image to read or write to or from.
|
|
size_t size; //< The size of the buffer.
|
|
bool out; //< If true the it is compression.
|
|
bool compress; //< If true compress the data.
|
|
uint8_t* buffer; //< The decompressed buffer
|
|
uint8_t* io; //< The I/O buffer.
|
|
size_t level; //< The amount of data in the buffer.
|
|
size_t total; //< The amount of uncompressed data
|
|
// transferred.
|
|
size_t total_compressed; //< The amount of compressed data
|
|
// transferred.
|
|
};
|
|
|
|
/**
|
|
* Compressor template function for writing data to the compressor.
|
|
*/
|
|
template < typename T >
|
|
void write (compressor& comp, const T value)
|
|
{
|
|
uint8_t bytes[sizeof (T)];
|
|
T v = value;
|
|
int b = sizeof (T) - 1;
|
|
while (b >= 0)
|
|
{
|
|
bytes[b--] = (uint8_t) v;
|
|
v >>= 8;
|
|
}
|
|
comp.write (bytes, sizeof (T));
|
|
}
|
|
|
|
/**
|
|
* Compressor template function for reading data from the compressor.
|
|
*/
|
|
template < typename T >
|
|
T read (compressor& comp)
|
|
{
|
|
uint8_t bytes[sizeof (T)];
|
|
T v = 0;
|
|
uint32_t b = 0;
|
|
if (comp.read (bytes, sizeof (T)) != sizeof (T))
|
|
throw rld::error ("Reading of value failed", "compression");
|
|
while (b < sizeof (T))
|
|
{
|
|
v = (v << 8) | ((T) bytes[b++]);
|
|
}
|
|
return v;
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
static inline rld::compress::compressor& operator<< (rld::compress::compressor& comp,
|
|
const uint64_t value) {
|
|
rld::compress::write < uint64_t > (comp, value);
|
|
return comp;
|
|
}
|
|
|
|
static inline rld::compress::compressor& operator<< (rld::compress::compressor& comp,
|
|
const uint32_t value) {
|
|
rld::compress::write < uint32_t > (comp, value);
|
|
return comp;
|
|
}
|
|
|
|
static inline rld::compress::compressor& operator<< (rld::compress::compressor& comp,
|
|
const std::string& str) {
|
|
comp.write (str.c_str (), str.size ());
|
|
return comp;
|
|
}
|
|
|
|
static inline rld::compress::compressor& operator>> (rld::compress::compressor& comp,
|
|
uint64_t& value) {
|
|
value = rld::compress::read < uint64_t > (comp);
|
|
return comp;
|
|
}
|
|
|
|
static inline rld::compress::compressor& operator>> (rld::compress::compressor& comp,
|
|
uint32_t& value) {
|
|
value = rld::compress::read < uint32_t > (comp);
|
|
return comp;
|
|
}
|
|
|
|
#endif
|