diff options
author | Chris Johns <chrisj@rtems.org> | 2012-12-21 17:08:17 +1100 |
---|---|---|
committer | Chris Johns <chrisj@rtems.org> | 2012-12-21 17:08:17 +1100 |
commit | 437d1ff26efa1087407f260f4a4dffec4e849848 (patch) | |
tree | 2ef70152eda2bdcf70e54b24737997e20ff9f2de | |
parent | 9f45219a18a32f59c25bd78669c862c018911719 (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.
-rw-r--r-- | rld-compression.cpp | 62 | ||||
-rw-r--r-- | rld-compression.h | 49 |
2 files changed, 96 insertions, 15 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 { diff --git a/rld-compression.h b/rld-compression.h index 20a1e44..9f06e0d 100644 --- a/rld-compression.h +++ b/rld-compression.h @@ -87,7 +87,7 @@ namespace rld * @param data Write the decompressed data here. * @param length The mount of data in bytes to read. */ - void read (void* data, size_t length); + size_t read (void* data, size_t length); /** * Read the decompressed data writing it to the image. @@ -96,7 +96,15 @@ namespace rld * @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); + 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. + */ + size_t read (files::image& output_, size_t length); /** * The amount of uncompressed data transferred. @@ -112,6 +120,11 @@ namespace rld */ size_t compressed () const; + /** + * The current offset in the stream. + */ + off_t offset () const; + private: /** @@ -140,7 +153,7 @@ namespace rld }; /** - * Compressor template function for writing data to the compressor.. + * Compressor template function for writing data to the compressor. */ template < typename T > void write (compressor& comp, const T value) @@ -156,6 +169,24 @@ namespace rld 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; + } + } } @@ -177,4 +208,16 @@ static inline rld::compress::compressor& operator<< (rld::compress::compressor& 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 |