diff options
author | Chris Johns <chrisj@rtems.org> | 2012-12-19 16:22:37 +1100 |
---|---|---|
committer | Chris Johns <chrisj@rtems.org> | 2012-12-19 16:22:37 +1100 |
commit | b8aa7a901ddc68c20548fa194b5d17916bb6fe45 (patch) | |
tree | 245fd0195e3b7d2ffa212c4d7ed46ed8da3ec9f8 /rld-compression.cpp | |
parent | f88e11c2a878be0e2babe61de2ff21bc451f03fa (diff) |
Decompression support added.
The compressor can now decompress LZ77 files.
Diffstat (limited to 'rld-compression.cpp')
-rw-r--r-- | rld-compression.cpp | 98 |
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; + } + } + } + } } |