summaryrefslogtreecommitdiff
path: root/rld-compression.cpp
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 /rld-compression.cpp
parentf88e11c2a878be0e2babe61de2ff21bc451f03fa (diff)
Decompression support added.
The compressor can now decompress LZ77 files.
Diffstat (limited to 'rld-compression.cpp')
-rw-r--r--rld-compression.cpp98
1 files changed, 97 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;
+ }
+ }
+ }
+
}
}