summaryrefslogtreecommitdiff
path: root/rld-compression.cpp
diff options
context:
space:
mode:
authorChris Johns <chrisj@rtems.org>2012-12-21 17:08:17 +1100
committerChris Johns <chrisj@rtems.org>2012-12-21 17:08:17 +1100
commit437d1ff26efa1087407f260f4a4dffec4e849848 (patch)
tree2ef70152eda2bdcf70e54b24737997e20ff9f2de /rld-compression.cpp
parent9f45219a18a32f59c25bd78669c862c018911719 (diff)
Decompressor fixes.
Make reading compressed files more robust returning the amount of data that can be read. Also add >> operartors to get the data. Add exceptions when a read fails.
Diffstat (limited to 'rld-compression.cpp')
-rw-r--r--rld-compression.cpp62
1 files changed, 50 insertions, 12 deletions
diff --git a/rld-compression.cpp b/rld-compression.cpp
index ece73de..2abeff1 100644
--- a/rld-compression.cpp
+++ b/rld-compression.cpp
@@ -124,7 +124,7 @@ namespace rld
}
}
- void
+ size_t
compressor::read (void* data_, size_t length)
{
if (out)
@@ -132,10 +132,15 @@ namespace rld
uint8_t* data = static_cast <uint8_t*> (data_);
+ size_t amount = 0;
+
while (length)
{
input ();
+ if (level == 0)
+ break;
+
size_t appending;
if (length > level)
@@ -144,15 +149,19 @@ namespace rld
appending = length;
::memcpy (data, buffer, appending);
+ ::memmove (buffer, buffer + appending, level - appending);
data += appending;
level -= appending;
length -= appending;
total += appending;
+ amount += appending;
}
+
+ return amount;
}
- void
+ size_t
compressor::read (files::image& output_, off_t offset, size_t length)
{
if (out)
@@ -160,10 +169,24 @@ namespace rld
output_.seek (offset);
+ return read (output_, length);
+ }
+
+ size_t
+ compressor::read (files::image& output_, size_t length)
+ {
+ if (out)
+ throw rld::error ("Read on write-only", "compression");
+
+ size_t amount = 0;
+
while (length)
{
input ();
+ if (level == 0)
+ break;
+
size_t appending;
if (length > level)
@@ -173,10 +196,15 @@ namespace rld
output_.write (buffer, appending);
+ ::memmove (buffer, buffer + appending, level - appending);
+
level -= appending;
length -= appending;
total += appending;
+ amount += appending;
}
+
+ return amount;
}
void
@@ -197,6 +225,12 @@ namespace rld
return total_compressed;
}
+ off_t
+ compressor::offset () const
+ {
+ return total;
+ }
+
void
compressor::output (bool forced)
{
@@ -237,21 +271,25 @@ namespace rld
{
uint8_t header[2];
- image.read (header, 2);
-
- uint32_t block_size = (((uint32_t) header[0]) << 8) | (uint32_t) header[1];
+ if (image.read (header, 2) == 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");
+ if (block_size == 0)
+ throw rld::error ("Block size is invalid (0)", "compression");
- total_compressed += 2 + block_size;
+ total_compressed += 2 + block_size;
- if (rld::verbose () >= RLD_VERBOSE_FULL_DEBUG)
- std::cout << "rtl: decomp: block-size=" << block_size << std::endl;
+ if (rld::verbose () >= RLD_VERBOSE_FULL_DEBUG)
+ std::cout << "rtl: decomp: block-size=" << block_size
+ << std::endl;
- image.read (io, block_size);
+ if (image.read (io, block_size) != block_size)
+ throw rld::error ("Read past end", "compression");
- level = ::fastlz_decompress (io, block_size, buffer, size);
+ level = ::fastlz_decompress (io, block_size, buffer, size);
+ }
}
else
{