summaryrefslogtreecommitdiff
path: root/linkers/rld-compression.h
diff options
context:
space:
mode:
Diffstat (limited to 'linkers/rld-compression.h')
-rw-r--r--linkers/rld-compression.h228
1 files changed, 228 insertions, 0 deletions
diff --git a/linkers/rld-compression.h b/linkers/rld-compression.h
new file mode 100644
index 0000000..4710845
--- /dev/null
+++ b/linkers/rld-compression.h
@@ -0,0 +1,228 @@
+/*
+ * 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