/* * Copyright (c) 2012, Chris Johns * * 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 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