summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Johns <chrisj@rtems.org>2012-12-19 16:22:37 +1100
committerChris Johns <chrisj@rtems.org>2012-12-19 16:22:37 +1100
commitb8aa7a901ddc68c20548fa194b5d17916bb6fe45 (patch)
tree245fd0195e3b7d2ffa212c4d7ed46ed8da3ec9f8
parentf88e11c2a878be0e2babe61de2ff21bc451f03fa (diff)
Decompression support added.
The compressor can now decompress LZ77 files.
-rw-r--r--rld-compression.cpp98
-rw-r--r--rld-compression.h26
2 files changed, 123 insertions, 1 deletions
diff --git a/rld-compression.cpp b/rld-compression.cpp
index b3ceb68..0b816e7 100644
--- a/rld-compression.cpp
+++ b/rld-compression.cpp
@@ -43,9 +43,11 @@ namespace rld
{
compressor::compressor (files::image& image,
size_t size,
+ bool out,
bool compress)
: image (image),
size (size),
+ out (out),
compress (compress),
buffer (0),
io (0),
@@ -70,6 +72,9 @@ namespace rld
void
compressor::write (const void* data_, size_t length)
{
+ if (!out)
+ throw rld::error ("Write on read-only", "compression");
+
const uint8_t* data = static_cast <const uint8_t*> (data_);
while (length)
@@ -95,6 +100,9 @@ namespace rld
void
compressor::write (files::image& input, off_t offset, size_t length)
{
+ if (!out)
+ throw rld::error ("Write on read-only", "compression");
+
input.seek (offset);
while (length)
@@ -117,6 +125,61 @@ namespace rld
}
void
+ compressor::read (void* data_, size_t length)
+ {
+ if (out)
+ throw rld::error ("Read on write-only", "compression");
+
+ uint8_t* data = static_cast <uint8_t*> (data_);
+
+ while (length)
+ {
+ input ();
+
+ size_t appending;
+
+ if (length > level)
+ appending = level;
+ else
+ appending = length;
+
+ ::memcpy (data, buffer, appending);
+
+ data += appending;
+ level -= appending;
+ length -= appending;
+ total += appending;
+ }
+ }
+
+ void
+ compressor::read (files::image& output_, off_t offset, size_t length)
+ {
+ if (out)
+ throw rld::error ("Read on write-only", "compression");
+
+ output_.seek (offset);
+
+ while (length)
+ {
+ input ();
+
+ size_t appending;
+
+ if (length > level)
+ appending = level;
+ else
+ appending = length;
+
+ output_.write (buffer, appending);
+
+ level -= appending;
+ length -= appending;
+ total += appending;
+ }
+ }
+
+ void
compressor::flush ()
{
output (true);
@@ -137,7 +200,7 @@ namespace rld
void
compressor::output (bool forced)
{
- if ((forced && level) || (level >= size))
+ if (out && ((forced && level) || (level >= size)))
{
if (compress)
{
@@ -165,5 +228,38 @@ namespace rld
}
}
+ void
+ compressor::input ()
+ {
+ if (!out && (level == 0))
+ {
+ if (compress)
+ {
+ uint8_t header[2];
+
+ image.read (header, 2);
+
+ uint32_t block_size = (((uint32_t) header[0]) << 8) | (uint32_t) header[1];
+
+ if (block_size == 0)
+ throw rld::error ("Block size is invalid (0)", "compression");
+
+ total_compressed += 2 + block_size;
+
+ if (1 || rld::verbose () >= RLD_VERBOSE_FULL_DEBUG)
+ std::cout << "rtl: decomp: block-size=" << block_size << std::endl;
+
+ image.read (io, block_size);
+
+ level = ::fastlz_decompress (io, block_size, buffer, size);
+ }
+ else
+ {
+ image.read (buffer, size);
+ level = size;
+ }
+ }
+ }
+
}
}
diff --git a/rld-compression.h b/rld-compression.h
index accc177..20a1e44 100644
--- a/rld-compression.h
+++ b/rld-compression.h
@@ -42,10 +42,12 @@ namespace rld
*
* @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);
/**
@@ -79,6 +81,24 @@ namespace rld
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.
+ */
+ void 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.
+ */
+ void read (files::image& output_, off_t offset, size_t length);
+
+ /**
* The amount of uncompressed data transferred.
*
* @param return size_t The amount of data tranferred.
@@ -101,8 +121,14 @@ namespace rld
*/
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.