summaryrefslogtreecommitdiff
path: root/indra/llkdu
diff options
context:
space:
mode:
authorRider Linden <rider@lindenlab.com>2017-01-25 11:13:59 -0800
committerRider Linden <rider@lindenlab.com>2017-01-25 11:13:59 -0800
commit25cd2ed2052b0d30d61e8b81df151993983f561b (patch)
tree7f9b29356b658303bdf7608a25ccb23c8e6130da /indra/llkdu
parent8d86f5a0c457fceff5923fb7ca32259b2718addc (diff)
parent68413474c4479eee9bdbeb34ea131475ba1d646e (diff)
Merge
Diffstat (limited to 'indra/llkdu')
-rw-r--r--indra/llkdu/llimagej2ckdu.cpp105
1 files changed, 90 insertions, 15 deletions
diff --git a/indra/llkdu/llimagej2ckdu.cpp b/indra/llkdu/llimagej2ckdu.cpp
index d9f0935712..dce4216320 100644
--- a/indra/llkdu/llimagej2ckdu.cpp
+++ b/indra/llkdu/llimagej2ckdu.cpp
@@ -1,4 +1,4 @@
- /**
+/**
* @file llimagej2ckdu.cpp
* @brief This is an implementation of JPEG2000 encode/decode using Kakadu
*
@@ -35,18 +35,51 @@
#include "kdu_block_coding.h"
-#include <stdexcept>
-#include <iostream>
#include "llexception.h"
-#include <boost/throw_exception.hpp>
+#include <boost/exception/diagnostic_information.hpp>
+#include <sstream>
+#include <iomanip>
namespace {
-// exception used to keep KDU from terminating entire program -- see comments
-// in LLKDUMessageError::flush()
-struct KDUError: public LLException
+// Failure to load an image shouldn't crash the whole viewer.
+struct KDUError: public LLContinueError
{
- KDUError(const std::string& msg): LLException(msg) {}
+ KDUError(const std::string& msg): LLContinueError(msg) {}
};
+
+// KDU defines int error codes as hex values, so we should log them in hex
+// so we can grep KDU headers for the hex. However those hex values
+// generally "happen" to encode big-endian multibyte character sequences,
+// e.g. KDU_ERROR_EXCEPTION is 0x6b647545: 'kduE'
+// But beware because KDU_NULL_EXCEPTION is simply 0 -- which doesn't
+// preclude somebody from throwing it.
+std::string report_kdu_exception(kdu_exception mb)
+{
+ std::ostringstream out;
+ // always report mb in hex
+ out << "kdu_exception " << std::hex << mb;
+
+ // Also display as many chars as are encoded in the kdu_exception
+ // value. Make a char array; reserve 1 extra byte for nul terminator.
+ char bytes[sizeof(kdu_exception) + 1];
+ // Back up through 'bytes'
+ char *bptr = bytes + sizeof(bytes);
+ *(--bptr) = '\0';
+ while (mb)
+ {
+ // store low-order byte of mb in next-left char
+ *(--bptr) = char(mb & 0xFF);
+ // then shift mb right by one byte
+ mb >>= 8;
+ }
+ // did that produce any characters?
+ if (*bptr)
+ {
+ out << " (" << bptr << ')';
+ }
+
+ return out.str();
+}
} // anonymous namespace
// stream kdu_dims to std::ostream
@@ -198,7 +231,7 @@ struct LLKDUMessageError : public LLKDUMessage
// shutdown will NOT engage the behavior described above.
if (end_of_message)
{
- throw "KDU throwing an exception";
+ LLTHROW(KDUError("LLKDUMessageError::flush()"));
}
}
};
@@ -312,10 +345,10 @@ void LLImageJ2CKDU::setupCodeStream(LLImageJ2C &base, bool keep_codestream, ECod
{
// This method is only called from methods that catch KDUError.
// We want to fail the image load, not crash the viewer.
- throw KDUError(STRINGIZE("Component " << idx << " dimensions "
+ LLTHROW(KDUError(STRINGIZE("Component " << idx << " dimensions "
<< other_dims
<< " do not match component 0 dimensions "
- << dims << "!"));
+ << dims << "!")));
}
}
@@ -442,9 +475,19 @@ bool LLImageJ2CKDU::initDecode(LLImageJ2C &base, LLImageRaw &raw_image, F32 deco
base.setLastError(msg.what());
return false;
}
+ catch (kdu_exception kdu_value)
+ {
+ // KDU internally throws kdu_exception. It's possible that such an
+ // exception might leak out into our code. Catch kdu_exception
+ // specially because boost::current_exception_diagnostic_information()
+ // could do nothing with it.
+ base.setLastError(report_kdu_exception(kdu_value));
+ return false;
+ }
catch (...)
{
- base.setLastError("Unknown J2C error");
+ base.setLastError("Unknown J2C error: " +
+ boost::current_exception_diagnostic_information());
return false;
}
@@ -540,9 +583,21 @@ bool LLImageJ2CKDU::decodeImpl(LLImageJ2C &base, LLImageRaw &raw_image, F32 deco
cleanupCodeStream();
return true; // done
}
+ catch (kdu_exception kdu_value)
+ {
+ // KDU internally throws kdu_exception. It's possible that such an
+ // exception might leak out into our code. Catch kdu_exception
+ // specially because boost::current_exception_diagnostic_information()
+ // could do nothing with it.
+ base.setLastError(report_kdu_exception(kdu_value));
+ base.decodeFailed();
+ cleanupCodeStream();
+ return true; // done
+ }
catch (...)
{
- base.setLastError( "Unknown J2C error" );
+ base.setLastError("Unknown J2C error: " +
+ boost::current_exception_diagnostic_information());
base.decodeFailed();
cleanupCodeStream();
return true; // done
@@ -731,9 +786,19 @@ bool LLImageJ2CKDU::encodeImpl(LLImageJ2C &base, const LLImageRaw &raw_image, co
base.setLastError(msg.what());
return false;
}
+ catch (kdu_exception kdu_value)
+ {
+ // KDU internally throws kdu_exception. It's possible that such an
+ // exception might leak out into our code. Catch kdu_exception
+ // specially because boost::current_exception_diagnostic_information()
+ // could do nothing with it.
+ base.setLastError(report_kdu_exception(kdu_value));
+ return false;
+ }
catch( ... )
{
- base.setLastError( "Unknown J2C error" );
+ base.setLastError("Unknown J2C error: " +
+ boost::current_exception_diagnostic_information());
return false;
}
@@ -755,9 +820,19 @@ bool LLImageJ2CKDU::getMetadata(LLImageJ2C &base)
base.setLastError(msg.what());
return false;
}
+ catch (kdu_exception kdu_value)
+ {
+ // KDU internally throws kdu_exception. It's possible that such an
+ // exception might leak out into our code. Catch kdu_exception
+ // specially because boost::current_exception_diagnostic_information()
+ // could do nothing with it.
+ base.setLastError(report_kdu_exception(kdu_value));
+ return false;
+ }
catch (...)
{
- base.setLastError( "Unknown J2C error" );
+ base.setLastError("Unknown J2C error: " +
+ boost::current_exception_diagnostic_information());
return false;
}
}