summaryrefslogtreecommitdiff
path: root/linkers
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
commit4e9b3247a650138c308b1f7969a6320f5d1c1a09 (patch)
tree185e2d917f692b62fbdbd0806d5b26229b98eba7 /linkers
parent74e89db40dfc2625a76bc1432e050d947e6a86a6 (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 'linkers')
-rw-r--r--linkers/rld-compression.cpp62
-rw-r--r--linkers/rld-compression.h49
2 files changed, 96 insertions, 15 deletions
diff --git a/linkers/rld-compression.cpp b/linkers/rld-compression.cpp
index ece73de..2abeff1 100644
--- a/linkers/rld-compression.cpp
+++ b/linkers/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/linkers/rld-compression.h b/linkers/rld-compression.h
index 20a1e44..9f06e0d 100644
--- a/linkers/rld-compression.h
+++ b/linkers/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