Merge pull request #3375 from MalcolmTyrrell/makeInternalErrorsAccessible

Make internal errors accessible
pull/3383/head^2
Kim Kulling 2020-09-14 08:59:09 +02:00 committed by GitHub
commit 3e5feb4320
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
82 changed files with 577 additions and 399 deletions

View File

@ -147,7 +147,7 @@ void Discreet3DSImporter::InternReadFile(const std::string &pFile,
// We should have at least one chunk // We should have at least one chunk
if (theStream.GetRemainingSize() < 16) { if (theStream.GetRemainingSize() < 16) {
throw DeadlyImportError("3DS file is either empty or corrupt: " + pFile); throw DeadlyImportError("3DS file is either empty or corrupt: ", pFile);
} }
this->stream = &theStream; this->stream = &theStream;
@ -178,7 +178,7 @@ void Discreet3DSImporter::InternReadFile(const std::string &pFile,
// file. // file.
for (auto &mesh : mScene->mMeshes) { for (auto &mesh : mScene->mMeshes) {
if (mesh.mFaces.size() > 0 && mesh.mPositions.size() == 0) { if (mesh.mFaces.size() > 0 && mesh.mPositions.size() == 0) {
throw DeadlyImportError("3DS file contains faces but no vertices: " + pFile); throw DeadlyImportError("3DS file contains faces but no vertices: ", pFile);
} }
CheckIndices(mesh); CheckIndices(mesh);
MakeUnique(mesh); MakeUnique(mesh);

View File

@ -118,7 +118,7 @@ D3MFOpcPackage::D3MFOpcPackage(IOSystem *pIOHandler, const std::string &rFile) :
mRootStream(nullptr), mZipArchive() { mRootStream(nullptr), mZipArchive() {
mZipArchive.reset(new ZipArchiveIOSystem(pIOHandler, rFile)); mZipArchive.reset(new ZipArchiveIOSystem(pIOHandler, rFile));
if (!mZipArchive->isOpen()) { if (!mZipArchive->isOpen()) {
throw DeadlyImportError("Failed to open file " + rFile + "."); throw DeadlyImportError("Failed to open file ", rFile, ".");
} }
std::vector<std::string> fileList; std::vector<std::string> fileList;
@ -192,7 +192,7 @@ std::string D3MFOpcPackage::ReadPackageRootRelationship(IOStream *stream) {
}); });
if (itr == reader.m_relationShips.end()) { if (itr == reader.m_relationShips.end()) {
throw DeadlyImportError("Cannot find " + XmlTag::PACKAGE_START_PART_RELATIONSHIP_TYPE); throw DeadlyImportError("Cannot find ", XmlTag::PACKAGE_START_PART_RELATIONSHIP_TYPE);
} }
return (*itr)->target; return (*itr)->target;

View File

@ -762,7 +762,7 @@ void AC3DImporter::InternReadFile(const std::string &pFile,
// Check whether we can read from the file // Check whether we can read from the file
if (file.get() == nullptr) { if (file.get() == nullptr) {
throw DeadlyImportError("Failed to open AC3D file " + pFile + "."); throw DeadlyImportError("Failed to open AC3D file ", pFile, ".");
} }
// allocate storage and copy the contents of the file to a memory buffer // allocate storage and copy the contents of the file to a memory buffer

View File

@ -143,23 +143,23 @@ bool AMFImporter::Find_ConvertedMaterial(const std::string &pID, const SPP_Mater
/*********************************************************************************************************************************************/ /*********************************************************************************************************************************************/
void AMFImporter::Throw_CloseNotFound(const std::string &pNode) { void AMFImporter::Throw_CloseNotFound(const std::string &pNode) {
throw DeadlyImportError("Close tag for node <" + pNode + "> not found. Seems file is corrupt."); throw DeadlyImportError("Close tag for node <", pNode, "> not found. Seems file is corrupt.");
} }
void AMFImporter::Throw_IncorrectAttr(const std::string &pAttrName) { void AMFImporter::Throw_IncorrectAttr(const std::string &pAttrName) {
throw DeadlyImportError("Node <" + std::string(mReader->getNodeName()) + "> has incorrect attribute \"" + pAttrName + "\"."); throw DeadlyImportError("Node <", mReader->getNodeName(), "> has incorrect attribute \"", pAttrName, "\".");
} }
void AMFImporter::Throw_IncorrectAttrValue(const std::string &pAttrName) { void AMFImporter::Throw_IncorrectAttrValue(const std::string &pAttrName) {
throw DeadlyImportError("Attribute \"" + pAttrName + "\" in node <" + std::string(mReader->getNodeName()) + "> has incorrect value."); throw DeadlyImportError("Attribute \"", pAttrName, "\" in node <", mReader->getNodeName(), "> has incorrect value.");
} }
void AMFImporter::Throw_MoreThanOnceDefined(const std::string &pNodeType, const std::string &pDescription) { void AMFImporter::Throw_MoreThanOnceDefined(const std::string &pNodeType, const std::string &pDescription) {
throw DeadlyImportError("\"" + pNodeType + "\" node can be used only once in " + mReader->getNodeName() + ". Description: " + pDescription); throw DeadlyImportError("\"", pNodeType, "\" node can be used only once in ", mReader->getNodeName(), ". Description: ", pDescription);
} }
void AMFImporter::Throw_ID_NotFound(const std::string &pID) const { void AMFImporter::Throw_ID_NotFound(const std::string &pID) const {
throw DeadlyImportError("Not found node with name \"" + pID + "\"."); throw DeadlyImportError("Not found node with name \"", pID, "\".");
} }
/*********************************************************************************************************************************************/ /*********************************************************************************************************************************************/
@ -167,7 +167,7 @@ void AMFImporter::Throw_ID_NotFound(const std::string &pID) const {
/*********************************************************************************************************************************************/ /*********************************************************************************************************************************************/
void AMFImporter::XML_CheckNode_MustHaveChildren() { void AMFImporter::XML_CheckNode_MustHaveChildren() {
if (mReader->isEmptyElement()) throw DeadlyImportError(std::string("Node <") + mReader->getNodeName() + "> must have children."); if (mReader->isEmptyElement()) throw DeadlyImportError("Node <", mReader->getNodeName(), "> must have children.");
} }
void AMFImporter::XML_CheckNode_SkipUnsupported(const std::string &pParentNodeName) { void AMFImporter::XML_CheckNode_SkipUnsupported(const std::string &pParentNodeName) {
@ -202,7 +202,7 @@ void AMFImporter::XML_CheckNode_SkipUnsupported(const std::string &pParentNodeNa
casu_cres: casu_cres:
if (!found) throw DeadlyImportError("Unknown node \"" + nn + "\" in " + pParentNodeName + "."); if (!found) throw DeadlyImportError("Unknown node \"", nn, "\" in ", pParentNodeName, ".");
if (!close_found) Throw_CloseNotFound(nn); if (!close_found) Throw_CloseNotFound(nn);
if (!skipped_before[sk_idx]) { if (!skipped_before[sk_idx]) {
@ -227,7 +227,7 @@ bool AMFImporter::XML_ReadNode_GetAttrVal_AsBool(const int pAttrIdx) {
else if ((val == "true") || (val == "1")) else if ((val == "true") || (val == "1"))
return true; return true;
else else
throw DeadlyImportError("Bool attribute value can contain \"false\"/\"0\" or \"true\"/\"1\" not the \"" + val + "\""); throw DeadlyImportError("Bool attribute value can contain \"false\"/\"0\" or \"true\"/\"1\" not the \"", val, "\"");
} }
float AMFImporter::XML_ReadNode_GetAttrVal_AsFloat(const int pAttrIdx) { float AMFImporter::XML_ReadNode_GetAttrVal_AsFloat(const int pAttrIdx) {
@ -367,13 +367,13 @@ void AMFImporter::ParseFile(const std::string &pFile, IOSystem *pIOHandler) {
// Check whether we can read from the file // Check whether we can read from the file
if (file.get() == nullptr) { if (file.get() == nullptr) {
throw DeadlyImportError("Failed to open AMF file " + pFile + "."); throw DeadlyImportError("Failed to open AMF file ", pFile, ".");
} }
// generate a XML reader for it // generate a XML reader for it
std::unique_ptr<CIrrXML_IOStreamReader> mIOWrapper(new CIrrXML_IOStreamReader(file.get())); std::unique_ptr<CIrrXML_IOStreamReader> mIOWrapper(new CIrrXML_IOStreamReader(file.get()));
mReader = irr::io::createIrrXMLReader(mIOWrapper.get()); mReader = irr::io::createIrrXMLReader(mIOWrapper.get());
if (!mReader) throw DeadlyImportError("Failed to create XML reader for file" + pFile + "."); if (!mReader) throw DeadlyImportError("Failed to create XML reader for file", pFile, ".");
// //
// start reading // start reading
// search for root tag <amf> // search for root tag <amf>

View File

@ -137,7 +137,7 @@ void ASEImporter::InternReadFile(const std::string &pFile,
// Check whether we can read from the file // Check whether we can read from the file
if (file.get() == nullptr) { if (file.get() == nullptr) {
throw DeadlyImportError("Failed to open ASE file " + pFile + "."); throw DeadlyImportError("Failed to open ASE file ", pFile, ".");
} }
// Allocate storage and copy the contents of the file to a memory buffer // Allocate storage and copy the contents of the file to a memory buffer

View File

@ -119,7 +119,7 @@ void B3DImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy
// Check whether we can read from the file // Check whether we can read from the file
if (file.get() == nullptr) { if (file.get() == nullptr) {
throw DeadlyImportError("Failed to open B3D file " + pFile + "."); throw DeadlyImportError("Failed to open B3D file ", pFile, ".");
} }
// check whether the .b3d file is large enough to contain // check whether the .b3d file is large enough to contain
@ -147,7 +147,7 @@ AI_WONT_RETURN void B3DImporter::Fail(string str) {
#ifdef DEBUG_B3D #ifdef DEBUG_B3D
ASSIMP_LOG_ERROR_F("Error in B3D file data: ", str); ASSIMP_LOG_ERROR_F("Error in B3D file data: ", str);
#endif #endif
throw DeadlyImportError("B3D Importer - error in B3D file data: " + str); throw DeadlyImportError("B3D Importer - error in B3D file data: ", str);
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------

View File

@ -71,6 +71,13 @@ static const aiImporterDesc desc = {
"bvh" "bvh"
}; };
// ------------------------------------------------------------------------------------------------
// Aborts the file reading with an exception
template<typename... T>
AI_WONT_RETURN void BVHLoader::ThrowException(T&&... args) {
throw DeadlyImportError(mFileName, ":", mLine, " - ", args...);
}
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Constructor to be privately used by Importer // Constructor to be privately used by Importer
BVHLoader::BVHLoader() : BVHLoader::BVHLoader() :
@ -118,7 +125,7 @@ void BVHLoader::InternReadFile(const std::string &pFile, aiScene *pScene, IOSyst
// read file into memory // read file into memory
std::unique_ptr<IOStream> file(pIOHandler->Open(pFile)); std::unique_ptr<IOStream> file(pIOHandler->Open(pFile));
if (file.get() == nullptr) { if (file.get() == nullptr) {
throw DeadlyImportError("Failed to open file " + pFile + "."); throw DeadlyImportError("Failed to open file ", pFile, ".");
} }
size_t fileSize = file->FileSize(); size_t fileSize = file->FileSize();
@ -176,12 +183,12 @@ aiNode *BVHLoader::ReadNode() {
// first token is name // first token is name
std::string nodeName = GetNextToken(); std::string nodeName = GetNextToken();
if (nodeName.empty() || nodeName == "{") if (nodeName.empty() || nodeName == "{")
ThrowException(format() << "Expected node name, but found \"" << nodeName << "\"."); ThrowException("Expected node name, but found \"", nodeName, "\".");
// then an opening brace should follow // then an opening brace should follow
std::string openBrace = GetNextToken(); std::string openBrace = GetNextToken();
if (openBrace != "{") if (openBrace != "{")
ThrowException(format() << "Expected opening brace \"{\", but found \"" << openBrace << "\"."); ThrowException("Expected opening brace \"{\", but found \"", openBrace, "\".");
// Create a node // Create a node
aiNode *node = new aiNode(nodeName); aiNode *node = new aiNode(nodeName);
@ -211,7 +218,7 @@ aiNode *BVHLoader::ReadNode() {
siteToken.clear(); siteToken.clear();
siteToken = GetNextToken(); siteToken = GetNextToken();
if (siteToken != "Site") if (siteToken != "Site")
ThrowException(format() << "Expected \"End Site\" keyword, but found \"" << token << " " << siteToken << "\"."); ThrowException("Expected \"End Site\" keyword, but found \"", token, " ", siteToken, "\".");
aiNode *child = ReadEndSite(nodeName); aiNode *child = ReadEndSite(nodeName);
child->mParent = node; child->mParent = node;
@ -221,7 +228,7 @@ aiNode *BVHLoader::ReadNode() {
break; break;
} else { } else {
// everything else is a parse error // everything else is a parse error
ThrowException(format() << "Unknown keyword \"" << token << "\"."); ThrowException("Unknown keyword \"", token, "\".");
} }
} }
@ -242,7 +249,7 @@ aiNode *BVHLoader::ReadEndSite(const std::string &pParentName) {
// check opening brace // check opening brace
std::string openBrace = GetNextToken(); std::string openBrace = GetNextToken();
if (openBrace != "{") if (openBrace != "{")
ThrowException(format() << "Expected opening brace \"{\", but found \"" << openBrace << "\"."); ThrowException("Expected opening brace \"{\", but found \"", openBrace, "\".");
// Create a node // Create a node
aiNode *node = new aiNode("EndSite_" + pParentName); aiNode *node = new aiNode("EndSite_" + pParentName);
@ -261,7 +268,7 @@ aiNode *BVHLoader::ReadEndSite(const std::string &pParentName) {
break; break;
} else { } else {
// everything else is a parse error // everything else is a parse error
ThrowException(format() << "Unknown keyword \"" << token << "\"."); ThrowException("Unknown keyword \"", token, "\".");
} }
} }
@ -307,7 +314,7 @@ void BVHLoader::ReadNodeChannels(BVHLoader::Node &pNode) {
else if (channelToken == "Zrotation") else if (channelToken == "Zrotation")
pNode.mChannels.push_back(Channel_RotationZ); pNode.mChannels.push_back(Channel_RotationZ);
else else
ThrowException(format() << "Invalid channel specifier \"" << channelToken << "\"."); ThrowException("Invalid channel specifier \"", channelToken, "\".");
} }
} }
@ -317,7 +324,7 @@ void BVHLoader::ReadMotion(aiScene * /*pScene*/) {
// Read number of frames // Read number of frames
std::string tokenFrames = GetNextToken(); std::string tokenFrames = GetNextToken();
if (tokenFrames != "Frames:") if (tokenFrames != "Frames:")
ThrowException(format() << "Expected frame count \"Frames:\", but found \"" << tokenFrames << "\"."); ThrowException("Expected frame count \"Frames:\", but found \"", tokenFrames, "\".");
float numFramesFloat = GetNextTokenAsFloat(); float numFramesFloat = GetNextTokenAsFloat();
mAnimNumFrames = (unsigned int)numFramesFloat; mAnimNumFrames = (unsigned int)numFramesFloat;
@ -326,7 +333,7 @@ void BVHLoader::ReadMotion(aiScene * /*pScene*/) {
std::string tokenDuration1 = GetNextToken(); std::string tokenDuration1 = GetNextToken();
std::string tokenDuration2 = GetNextToken(); std::string tokenDuration2 = GetNextToken();
if (tokenDuration1 != "Frame" || tokenDuration2 != "Time:") if (tokenDuration1 != "Frame" || tokenDuration2 != "Time:")
ThrowException(format() << "Expected frame duration \"Frame Time:\", but found \"" << tokenDuration1 << " " << tokenDuration2 << "\"."); ThrowException("Expected frame duration \"Frame Time:\", but found \"", tokenDuration1, " ", tokenDuration2, "\".");
mAnimTickDuration = GetNextTokenAsFloat(); mAnimTickDuration = GetNextTokenAsFloat();
@ -393,17 +400,11 @@ float BVHLoader::GetNextTokenAsFloat() {
ctoken = fast_atoreal_move<float>(ctoken, result); ctoken = fast_atoreal_move<float>(ctoken, result);
if (ctoken != token.c_str() + token.length()) if (ctoken != token.c_str() + token.length())
ThrowException(format() << "Expected a floating point number, but found \"" << token << "\"."); ThrowException("Expected a floating point number, but found \"", token, "\".");
return result; return result;
} }
// ------------------------------------------------------------------------------------------------
// Aborts the file reading with an exception
AI_WONT_RETURN void BVHLoader::ThrowException(const std::string &pError) {
throw DeadlyImportError(format() << mFileName << ":" << mLine << " - " << pError);
}
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Constructs an animation for the motion data and stores it in the given scene // Constructs an animation for the motion data and stores it in the given scene
void BVHLoader::CreateAnimation(aiScene *pScene) { void BVHLoader::CreateAnimation(aiScene *pScene) {
@ -453,7 +454,7 @@ void BVHLoader::CreateAnimation(aiScene *pScene) {
std::map<BVHLoader::ChannelType, int>::iterator mapIter = channelMap.find(channel); std::map<BVHLoader::ChannelType, int>::iterator mapIter = channelMap.find(channel);
if (mapIter == channelMap.end()) if (mapIter == channelMap.end())
throw DeadlyImportError("Missing position channel in node " + nodeName); throw DeadlyImportError("Missing position channel in node ", nodeName);
else { else {
int channelIdx = mapIter->second; int channelIdx = mapIter->second;
switch (channel) { switch (channel) {

View File

@ -134,7 +134,8 @@ protected:
float GetNextTokenAsFloat(); float GetNextTokenAsFloat();
/** Aborts the file reading with an exception */ /** Aborts the file reading with an exception */
AI_WONT_RETURN void ThrowException(const std::string &pError) AI_WONT_RETURN_SUFFIX; template<typename... T>
AI_WONT_RETURN void ThrowException(T&&... args) AI_WONT_RETURN_SUFFIX;
/** Constructs an animation for the motion data and stores it in the given scene */ /** Constructs an animation for the motion data and stores it in the given scene */
void CreateAnimation(aiScene *pScene); void CreateAnimation(aiScene *pScene);

View File

@ -149,7 +149,7 @@ bool isValidCustomDataType(const int cdtype) {
bool readCustomData(std::shared_ptr<ElemBase> &out, const int cdtype, const size_t cnt, const FileDatabase &db) { bool readCustomData(std::shared_ptr<ElemBase> &out, const int cdtype, const size_t cnt, const FileDatabase &db) {
if (!isValidCustomDataType(cdtype)) { if (!isValidCustomDataType(cdtype)) {
throw Error((Formatter::format(), "CustomData.type ", cdtype, " out of index")); throw Error("CustomData.type ", cdtype, " out of index");
} }
const CustomDataTypeDescription cdtd = customDataTypeDescriptions[cdtype]; const CustomDataTypeDescription cdtd = customDataTypeDescriptions[cdtype];

View File

@ -130,9 +130,7 @@ void DNAParser::Parse() {
uint16_t n = stream.GetI2(); uint16_t n = stream.GetI2();
if (n >= types.size()) { if (n >= types.size()) {
throw DeadlyImportError((format(), throw DeadlyImportError("BlenderDNA: Invalid type index in structure name", n, " (there are only ", types.size(), " entries)");
"BlenderDNA: Invalid type index in structure name", n,
" (there are only ", types.size(), " entries)"));
} }
// maintain separate indexes // maintain separate indexes
@ -151,9 +149,7 @@ void DNAParser::Parse() {
uint16_t j = stream.GetI2(); uint16_t j = stream.GetI2();
if (j >= types.size()) { if (j >= types.size()) {
throw DeadlyImportError((format(), throw DeadlyImportError("BlenderDNA: Invalid type index in structure field ", j, " (there are only ", types.size(), " entries)");
"BlenderDNA: Invalid type index in structure field ", j,
" (there are only ", types.size(), " entries)"));
} }
s.fields.push_back(Field()); s.fields.push_back(Field());
Field &f = s.fields.back(); Field &f = s.fields.back();
@ -164,9 +160,7 @@ void DNAParser::Parse() {
j = stream.GetI2(); j = stream.GetI2();
if (j >= names.size()) { if (j >= names.size()) {
throw DeadlyImportError((format(), throw DeadlyImportError("BlenderDNA: Invalid name index in structure field ", j, " (there are only ", names.size(), " entries)");
"BlenderDNA: Invalid name index in structure field ", j,
" (there are only ", names.size(), " entries)"));
} }
f.name = names[j]; f.name = names[j];
@ -188,9 +182,7 @@ void DNAParser::Parse() {
if (*f.name.rbegin() == ']') { if (*f.name.rbegin() == ']') {
const std::string::size_type rb = f.name.find('['); const std::string::size_type rb = f.name.find('[');
if (rb == std::string::npos) { if (rb == std::string::npos) {
throw DeadlyImportError((format(), throw DeadlyImportError("BlenderDNA: Encountered invalid array declaration ", f.name);
"BlenderDNA: Encountered invalid array declaration ",
f.name));
} }
f.flags |= FieldFlag_Array; f.flags |= FieldFlag_Array;

View File

@ -83,9 +83,10 @@ class ObjectCache;
* ancestry. */ * ancestry. */
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------
struct Error : DeadlyImportError { struct Error : DeadlyImportError {
Error(const std::string &s) : template<typename... T>
DeadlyImportError(s) { explicit Error(T&&... args)
// empty : DeadlyImportError(args...)
{
} }
}; };

View File

@ -57,9 +57,7 @@ const Field& Structure :: operator [] (const std::string& ss) const
{ {
std::map<std::string, size_t>::const_iterator it = indices.find(ss); std::map<std::string, size_t>::const_iterator it = indices.find(ss);
if (it == indices.end()) { if (it == indices.end()) {
throw Error((Formatter::format(), throw Error("BlendDNA: Did not find a field named `",ss,"` in structure `",name,"`");
"BlendDNA: Did not find a field named `",ss,"` in structure `",name,"`"
));
} }
return fields[(*it).second]; return fields[(*it).second];
@ -76,9 +74,7 @@ const Field* Structure :: Get (const std::string& ss) const
const Field& Structure :: operator [] (const size_t i) const const Field& Structure :: operator [] (const size_t i) const
{ {
if (i >= fields.size()) { if (i >= fields.size()) {
throw Error((Formatter::format(), throw Error("BlendDNA: There is no field with index `",i,"` in structure `",name,"`");
"BlendDNA: There is no field with index `",i,"` in structure `",name,"`"
));
} }
return fields[i]; return fields[i];
@ -109,9 +105,7 @@ void Structure :: ReadFieldArray(T (& out)[M], const char* name, const FileDatab
// is the input actually an array? // is the input actually an array?
if (!(f.flags & FieldFlag_Array)) { if (!(f.flags & FieldFlag_Array)) {
throw Error((Formatter::format(),"Field `",name,"` of structure `", throw Error("Field `",name,"` of structure `",this->name,"` ought to be an array of size ",M);
this->name,"` ought to be an array of size ",M
));
} }
db.reader->IncPtr(f.offset); db.reader->IncPtr(f.offset);
@ -148,9 +142,9 @@ void Structure :: ReadFieldArray2(T (& out)[M][N], const char* name, const FileD
// is the input actually an array? // is the input actually an array?
if (!(f.flags & FieldFlag_Array)) { if (!(f.flags & FieldFlag_Array)) {
throw Error((Formatter::format(),"Field `",name,"` of structure `", throw Error("Field `",name,"` of structure `",
this->name,"` ought to be an array of size ",M,"*",N this->name,"` ought to be an array of size ",M,"*",N
)); );
} }
db.reader->IncPtr(f.offset); db.reader->IncPtr(f.offset);
@ -195,8 +189,8 @@ bool Structure :: ReadFieldPtr(TOUT<T>& out, const char* name, const FileDatabas
// sanity check, should never happen if the genblenddna script is right // sanity check, should never happen if the genblenddna script is right
if (!(f->flags & FieldFlag_Pointer)) { if (!(f->flags & FieldFlag_Pointer)) {
throw Error((Formatter::format(),"Field `",name,"` of structure `", throw Error("Field `",name,"` of structure `",
this->name,"` ought to be a pointer")); this->name,"` ought to be a pointer");
} }
db.reader->IncPtr(f->offset); db.reader->IncPtr(f->offset);
@ -241,8 +235,8 @@ bool Structure :: ReadFieldPtr(TOUT<T> (&out)[N], const char* name,
#ifdef _DEBUG #ifdef _DEBUG
// sanity check, should never happen if the genblenddna script is right // sanity check, should never happen if the genblenddna script is right
if ((FieldFlag_Pointer|FieldFlag_Pointer) != (f->flags & (FieldFlag_Pointer|FieldFlag_Pointer))) { if ((FieldFlag_Pointer|FieldFlag_Pointer) != (f->flags & (FieldFlag_Pointer|FieldFlag_Pointer))) {
throw Error((Formatter::format(),"Field `",name,"` of structure `", throw Error("Field `",name,"` of structure `",
this->name,"` ought to be a pointer AND an array")); this->name,"` ought to be a pointer AND an array");
} }
#endif // _DEBUG #endif // _DEBUG
@ -322,8 +316,8 @@ bool Structure::ReadCustomDataPtr(std::shared_ptr<ElemBase>&out, int cdtype, con
// sanity check, should never happen if the genblenddna script is right // sanity check, should never happen if the genblenddna script is right
if (!(f->flags & FieldFlag_Pointer)) { if (!(f->flags & FieldFlag_Pointer)) {
throw Error((Formatter::format(), "Field `", name, "` of structure `", throw Error("Field `", name, "` of structure `",
this->name, "` ought to be a pointer")); this->name, "` ought to be a pointer");
} }
db.reader->IncPtr(f->offset); db.reader->IncPtr(f->offset);
@ -369,8 +363,8 @@ bool Structure::ReadFieldPtrVector(vector<TOUT<T>>&out, const char* name, const
// sanity check, should never happen if the genblenddna script is right // sanity check, should never happen if the genblenddna script is right
if (!(f->flags & FieldFlag_Pointer)) { if (!(f->flags & FieldFlag_Pointer)) {
throw Error((Formatter::format(), "Field `", name, "` of structure `", throw Error("Field `", name, "` of structure `",
this->name, "` ought to be a pointer")); this->name, "` ought to be a pointer");
} }
db.reader->IncPtr(f->offset); db.reader->IncPtr(f->offset);
@ -428,9 +422,9 @@ bool Structure :: ResolvePointer(TOUT<T>& out, const Pointer & ptrval, const Fil
// and check if it matches the type which we expect. // and check if it matches the type which we expect.
const Structure& ss = db.dna[block->dna_index]; const Structure& ss = db.dna[block->dna_index];
if (ss != s) { if (ss != s) {
throw Error((Formatter::format(),"Expected target to be of type `",s.name, throw Error("Expected target to be of type `",s.name,
"` but seemingly it is a `",ss.name,"` instead" "` but seemingly it is a `",ss.name,"` instead"
)); );
} }
// try to retrieve the object from the cache // try to retrieve the object from the cache
@ -614,16 +608,14 @@ const FileBlockHead* Structure :: LocateFileBlockForAddress(const Pointer & ptrv
if (it == db.entries.end()) { if (it == db.entries.end()) {
// this is crucial, pointers may not be invalid. // this is crucial, pointers may not be invalid.
// this is either a corrupted file or an attempted attack. // this is either a corrupted file or an attempted attack.
throw DeadlyImportError((Formatter::format(),"Failure resolving pointer 0x", throw DeadlyImportError("Failure resolving pointer 0x",
std::hex,ptrval.val,", no file block falls into this address range" std::hex,ptrval.val,", no file block falls into this address range");
));
} }
if (ptrval.val >= (*it).address.val + (*it).size) { if (ptrval.val >= (*it).address.val + (*it).size) {
throw DeadlyImportError((Formatter::format(),"Failure resolving pointer 0x", throw DeadlyImportError("Failure resolving pointer 0x",
std::hex,ptrval.val,", nearest file block starting at 0x", std::hex,ptrval.val,", nearest file block starting at 0x",
(*it).address.val," ends at 0x", (*it).address.val," ends at 0x",
(*it).address.val + (*it).size (*it).address.val + (*it).size);
));
} }
return &*it; return &*it;
} }
@ -676,7 +668,7 @@ template <typename T> inline void ConvertDispatcher(T& out, const Structure& in,
out = static_cast<T>(db.reader->GetF8()); out = static_cast<T>(db.reader->GetF8());
} }
else { else {
throw DeadlyImportError("Unknown source for conversion to primitive data type: "+in.name); throw DeadlyImportError("Unknown source for conversion to primitive data type: ", in.name);
} }
} }
@ -784,9 +776,7 @@ const Structure& DNA :: operator [] (const std::string& ss) const
{ {
std::map<std::string, size_t>::const_iterator it = indices.find(ss); std::map<std::string, size_t>::const_iterator it = indices.find(ss);
if (it == indices.end()) { if (it == indices.end()) {
throw Error((Formatter::format(), throw Error("BlendDNA: Did not find a structure named `",ss,"`");
"BlendDNA: Did not find a structure named `",ss,"`"
));
} }
return structures[(*it).second]; return structures[(*it).second];
@ -803,9 +793,7 @@ const Structure* DNA :: Get (const std::string& ss) const
const Structure& DNA :: operator [] (const size_t i) const const Structure& DNA :: operator [] (const size_t i) const
{ {
if (i >= structures.size()) { if (i >= structures.size()) {
throw Error((Formatter::format(), throw Error("BlendDNA: There is no structure with index `",i,"`");
"BlendDNA: There is no structure with index `",i,"`"
));
} }
return structures[i]; return structures[i];

View File

@ -748,9 +748,8 @@ void BlenderImporter::BuildMaterials(ConversionData &conv_data) {
void BlenderImporter::CheckActualType(const ElemBase *dt, const char *check) { void BlenderImporter::CheckActualType(const ElemBase *dt, const char *check) {
ai_assert(dt); ai_assert(dt);
if (strcmp(dt->dna_type, check)) { if (strcmp(dt->dna_type, check)) {
ThrowException((format(), ThrowException("Expected object at ", std::hex, dt, " to be of type `", check,
"Expected object at ", std::hex, dt, " to be of type `", check, "`, but it claims to be a `", dt->dna_type, "`instead");
"`, but it claims to be a `", dt->dna_type, "`instead"));
} }
} }

View File

@ -125,7 +125,7 @@ void COBImporter::SetupProperties(const Importer * /*pImp*/) {
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
/*static*/ AI_WONT_RETURN void COBImporter::ThrowException(const std::string &msg) { /*static*/ AI_WONT_RETURN void COBImporter::ThrowException(const std::string &msg) {
throw DeadlyImportError("COB: " + msg); throw DeadlyImportError("COB: ", msg);
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------

View File

@ -128,7 +128,7 @@ void CSMImporter::InternReadFile( const std::string& pFile,
// Check whether we can read from the file // Check whether we can read from the file
if( file.get() == nullptr) { if( file.get() == nullptr) {
throw DeadlyImportError( "Failed to open CSM file " + pFile + "."); throw DeadlyImportError( "Failed to open CSM file ", pFile, ".");
} }
// allocate storage and copy the contents of the file to a memory buffer // allocate storage and copy the contents of the file to a memory buffer

View File

@ -1251,7 +1251,7 @@ void ColladaLoader::CreateAnimation(aiScene *pScene, const ColladaParser &pParse
// time count and value count must match // time count and value count must match
if (e.mTimeAccessor->mCount != e.mValueAccessor->mCount) if (e.mTimeAccessor->mCount != e.mValueAccessor->mCount)
throw DeadlyImportError(format() << "Time count / value count mismatch in animation channel \"" << e.mChannel->mTarget << "\"."); throw DeadlyImportError("Time count / value count mismatch in animation channel \"", e.mChannel->mTarget, "\".");
if (e.mTimeAccessor->mCount > 0) { if (e.mTimeAccessor->mCount > 0) {
// find bounding times // find bounding times

View File

@ -66,6 +66,13 @@ using namespace Assimp;
using namespace Assimp::Collada; using namespace Assimp::Collada;
using namespace Assimp::Formatter; using namespace Assimp::Formatter;
// ------------------------------------------------------------------------------------------------
// Aborts the file reading with an exception
template<typename... T>
AI_WONT_RETURN void ColladaParser::ThrowException(T&&... args) const {
throw DeadlyImportError("Collada: ", mFileName, " - ", args...);
}
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Constructor to be privately used by Importer // Constructor to be privately used by Importer
ColladaParser::ColladaParser(IOSystem *pIOHandler, const std::string &pFile) : ColladaParser::ColladaParser(IOSystem *pIOHandler, const std::string &pFile) :
@ -116,7 +123,7 @@ ColladaParser::ColladaParser(IOSystem *pIOHandler, const std::string &pFile) :
// attempt to open the file directly // attempt to open the file directly
daefile.reset(pIOHandler->Open(pFile)); daefile.reset(pIOHandler->Open(pFile));
if (daefile.get() == nullptr) { if (daefile.get() == nullptr) {
throw DeadlyImportError("Failed to open file '" + pFile + "'."); throw DeadlyImportError("Failed to open file '", pFile, "'.");
} }
} }
@ -853,7 +860,7 @@ void ColladaParser::ReadControllerJoints(Collada::Controller &pController) {
// local URLS always start with a '#'. We don't support global URLs // local URLS always start with a '#'. We don't support global URLs
if (attrSource[0] != '#') if (attrSource[0] != '#')
ThrowException(format() << "Unsupported URL format in \"" << attrSource << "\" in source attribute of <joints> data <input> element"); ThrowException("Unsupported URL format in \"", attrSource, "\" in source attribute of <joints> data <input> element");
attrSource++; attrSource++;
// parse source URL to corresponding source // parse source URL to corresponding source
@ -862,7 +869,7 @@ void ColladaParser::ReadControllerJoints(Collada::Controller &pController) {
else if (strcmp(attrSemantic, "INV_BIND_MATRIX") == 0) else if (strcmp(attrSemantic, "INV_BIND_MATRIX") == 0)
pController.mJointOffsetMatrixSource = attrSource; pController.mJointOffsetMatrixSource = attrSource;
else else
ThrowException(format() << "Unknown semantic \"" << attrSemantic << "\" in <joints> data <input> element"); ThrowException("Unknown semantic \"", attrSemantic, "\" in <joints> data <input> element");
// skip inner data, if present // skip inner data, if present
if (!mReader->isEmptyElement()) if (!mReader->isEmptyElement())
@ -904,7 +911,7 @@ void ColladaParser::ReadControllerWeights(Collada::Controller &pController) {
// local URLS always start with a '#'. We don't support global URLs // local URLS always start with a '#'. We don't support global URLs
if (attrSource[0] != '#') if (attrSource[0] != '#')
ThrowException(format() << "Unsupported URL format in \"" << attrSource << "\" in source attribute of <vertex_weights> data <input> element"); ThrowException("Unsupported URL format in \"", attrSource, "\" in source attribute of <vertex_weights> data <input> element");
channel.mAccessor = attrSource + 1; channel.mAccessor = attrSource + 1;
// parse source URL to corresponding source // parse source URL to corresponding source
@ -913,7 +920,7 @@ void ColladaParser::ReadControllerWeights(Collada::Controller &pController) {
else if (strcmp(attrSemantic, "WEIGHT") == 0) else if (strcmp(attrSemantic, "WEIGHT") == 0)
pController.mWeightInputWeights = channel; pController.mWeightInputWeights = channel;
else else
ThrowException(format() << "Unknown semantic \"" << attrSemantic << "\" in <vertex_weights> data <input> element"); ThrowException("Unknown semantic \"", attrSemantic, "\" in <vertex_weights> data <input> element");
// skip inner data, if present // skip inner data, if present
if (!mReader->isEmptyElement()) if (!mReader->isEmptyElement())
@ -1901,7 +1908,7 @@ void ColladaParser::ReadAccessor(const std::string &pID) {
int attrSource = GetAttribute("source"); int attrSource = GetAttribute("source");
const char *source = mReader->getAttributeValue(attrSource); const char *source = mReader->getAttributeValue(attrSource);
if (source[0] != '#') if (source[0] != '#')
ThrowException(format() << "Unknown reference format in url \"" << source << "\" in source attribute of <accessor> element."); ThrowException("Unknown reference format in url \"", source, "\" in source attribute of <accessor> element.");
int attrCount = GetAttribute("count"); int attrCount = GetAttribute("count");
unsigned int count = (unsigned int)mReader->getAttributeValueAsInt(attrCount); unsigned int count = (unsigned int)mReader->getAttributeValueAsInt(attrCount);
int attrOffset = TestAttribute("offset"); int attrOffset = TestAttribute("offset");
@ -1968,7 +1975,7 @@ void ColladaParser::ReadAccessor(const std::string &pID) {
else if (name == "V") else if (name == "V")
acc.mSubOffset[1] = acc.mParams.size(); acc.mSubOffset[1] = acc.mParams.size();
//else //else
// DefaultLogger::get()->warn( format() << "Unknown accessor parameter \"" << name << "\". Ignoring data channel." ); // DefaultLogger::get()->warn( "Unknown accessor parameter \"", name, "\". Ignoring data channel." );
} }
// read data type // read data type
@ -1989,7 +1996,7 @@ void ColladaParser::ReadAccessor(const std::string &pID) {
// skip remaining stuff of this element, if any // skip remaining stuff of this element, if any
SkipElement(); SkipElement();
} else { } else {
ThrowException(format() << "Unexpected sub element <" << mReader->getNodeName() << "> in tag <accessor>"); ThrowException("Unexpected sub element <", mReader->getNodeName(), "> in tag <accessor>");
} }
} else if (mReader->getNodeType() == irr::io::EXN_ELEMENT_END) { } else if (mReader->getNodeType() == irr::io::EXN_ELEMENT_END) {
if (strcmp(mReader->getNodeName(), "accessor") != 0) if (strcmp(mReader->getNodeName(), "accessor") != 0)
@ -2012,7 +2019,7 @@ void ColladaParser::ReadVertexData(Mesh &pMesh) {
if (IsElement("input")) { if (IsElement("input")) {
ReadInputChannel(pMesh.mPerVertexData); ReadInputChannel(pMesh.mPerVertexData);
} else { } else {
ThrowException(format() << "Unexpected sub element <" << mReader->getNodeName() << "> in tag <vertices>"); ThrowException("Unexpected sub element <", mReader->getNodeName(), "> in tag <vertices>");
} }
} else if (mReader->getNodeType() == irr::io::EXN_ELEMENT_END) { } else if (mReader->getNodeType() == irr::io::EXN_ELEMENT_END) {
if (strcmp(mReader->getNodeName(), "vertices") != 0) if (strcmp(mReader->getNodeName(), "vertices") != 0)
@ -2096,11 +2103,11 @@ void ColladaParser::ReadIndexData(Mesh &pMesh) {
} else if (IsElement("ph")) { } else if (IsElement("ph")) {
SkipElement("ph"); SkipElement("ph");
} else { } else {
ThrowException(format() << "Unexpected sub element <" << mReader->getNodeName() << "> in tag <" << elementName << ">"); ThrowException("Unexpected sub element <", mReader->getNodeName(), "> in tag <", elementName, ">");
} }
} else if (mReader->getNodeType() == irr::io::EXN_ELEMENT_END) { } else if (mReader->getNodeType() == irr::io::EXN_ELEMENT_END) {
if (mReader->getNodeName() != elementName) if (mReader->getNodeName() != elementName)
ThrowException(format() << "Expected end of <" << elementName << "> element."); ThrowException("Expected end of <", elementName, "> element.");
break; break;
} }
@ -2132,7 +2139,7 @@ void ColladaParser::ReadInputChannel(std::vector<InputChannel> &poChannels) {
int attrSource = GetAttribute("source"); int attrSource = GetAttribute("source");
const char *source = mReader->getAttributeValue(attrSource); const char *source = mReader->getAttributeValue(attrSource);
if (source[0] != '#') if (source[0] != '#')
ThrowException(format() << "Unknown reference format in url \"" << source << "\" in source attribute of <input> element."); ThrowException("Unknown reference format in url \"", source, "\" in source attribute of <input> element.");
channel.mAccessor = source + 1; // skipping the leading #, hopefully the remaining text is the accessor ID only channel.mAccessor = source + 1; // skipping the leading #, hopefully the remaining text is the accessor ID only
// read index offset, if per-index <input> // read index offset, if per-index <input>
@ -2146,7 +2153,7 @@ void ColladaParser::ReadInputChannel(std::vector<InputChannel> &poChannels) {
if (attrSet > -1) { if (attrSet > -1) {
attrSet = mReader->getAttributeValueAsInt(attrSet); attrSet = mReader->getAttributeValueAsInt(attrSet);
if (attrSet < 0) if (attrSet < 0)
ThrowException(format() << "Invalid index \"" << (attrSet) << "\" in set attribute of <input> element"); ThrowException("Invalid index \"", (attrSet), "\" in set attribute of <input> element");
channel.mIndex = attrSet; channel.mIndex = attrSet;
} }
@ -2369,7 +2376,7 @@ void ColladaParser::ExtractDataObjectFromChannel(const InputChannel &pInput, siz
const Accessor &acc = *pInput.mResolved; const Accessor &acc = *pInput.mResolved;
if (pLocalIndex >= acc.mCount) if (pLocalIndex >= acc.mCount)
ThrowException(format() << "Invalid data index (" << pLocalIndex << "/" << acc.mCount << ") in primitive specification"); ThrowException("Invalid data index (", pLocalIndex, "/", acc.mCount, ") in primitive specification");
// get a pointer to the start of the data object referred to by the accessor and the local index // get a pointer to the start of the data object referred to by the accessor and the local index
const ai_real *dataObject = &(acc.mData->mValues[0]) + acc.mOffset + pLocalIndex * acc.mStride; const ai_real *dataObject = &(acc.mData->mValues[0]) + acc.mOffset + pLocalIndex * acc.mStride;
@ -2781,12 +2788,6 @@ void ColladaParser::ReadScene() {
} }
} }
// ------------------------------------------------------------------------------------------------
// Aborts the file reading with an exception
AI_WONT_RETURN void ColladaParser::ThrowException(const std::string &pError) const {
throw DeadlyImportError(format() << "Collada: " << mFileName << " - " << pError);
}
void ColladaParser::ReportWarning(const char *msg, ...) { void ColladaParser::ReportWarning(const char *msg, ...) {
ai_assert(nullptr != msg); ai_assert(nullptr != msg);
@ -2833,17 +2834,17 @@ void ColladaParser::SkipElement(const char *pElement) {
void ColladaParser::TestOpening(const char *pName) { void ColladaParser::TestOpening(const char *pName) {
// read element start // read element start
if (!mReader->read()) { if (!mReader->read()) {
ThrowException(format() << "Unexpected end of file while beginning of <" << pName << "> element."); ThrowException("Unexpected end of file while beginning of <", pName, "> element.");
} }
// whitespace in front is ok, just read again if found // whitespace in front is ok, just read again if found
if (mReader->getNodeType() == irr::io::EXN_TEXT) { if (mReader->getNodeType() == irr::io::EXN_TEXT) {
if (!mReader->read()) { if (!mReader->read()) {
ThrowException(format() << "Unexpected end of file while reading beginning of <" << pName << "> element."); ThrowException("Unexpected end of file while reading beginning of <", pName, "> element.");
} }
} }
if (mReader->getNodeType() != irr::io::EXN_ELEMENT || strcmp(mReader->getNodeName(), pName) != 0) { if (mReader->getNodeType() != irr::io::EXN_ELEMENT || strcmp(mReader->getNodeName(), pName) != 0) {
ThrowException(format() << "Expected start of <" << pName << "> element."); ThrowException("Expected start of <", pName, "> element.");
} }
} }
@ -2862,18 +2863,18 @@ void ColladaParser::TestClosing(const char *pName) {
// if not, read some more // if not, read some more
if (!mReader->read()) { if (!mReader->read()) {
ThrowException(format() << "Unexpected end of file while reading end of <" << pName << "> element."); ThrowException("Unexpected end of file while reading end of <", pName, "> element.");
} }
// whitespace in front is ok, just read again if found // whitespace in front is ok, just read again if found
if (mReader->getNodeType() == irr::io::EXN_TEXT) { if (mReader->getNodeType() == irr::io::EXN_TEXT) {
if (!mReader->read()) { if (!mReader->read()) {
ThrowException(format() << "Unexpected end of file while reading end of <" << pName << "> element."); ThrowException("Unexpected end of file while reading end of <", pName, "> element.");
} }
} }
// but this has the be the closing tag, or we're lost // but this has the be the closing tag, or we're lost
if (mReader->getNodeType() != irr::io::EXN_ELEMENT_END || strcmp(mReader->getNodeName(), pName) != 0) { if (mReader->getNodeType() != irr::io::EXN_ELEMENT_END || strcmp(mReader->getNodeName(), pName) != 0) {
ThrowException(format() << "Expected end of <" << pName << "> element."); ThrowException("Expected end of <", pName, "> element.");
} }
} }
@ -2882,7 +2883,7 @@ void ColladaParser::TestClosing(const char *pName) {
int ColladaParser::GetAttribute(const char *pAttr) const { int ColladaParser::GetAttribute(const char *pAttr) const {
int index = TestAttribute(pAttr); int index = TestAttribute(pAttr);
if (index == -1) { if (index == -1) {
ThrowException(format() << "Expected attribute \"" << pAttr << "\" for element <" << mReader->getNodeName() << ">."); ThrowException("Expected attribute \"", pAttr, "\" for element <", mReader->getNodeName(), ">.");
} }
// attribute not found -> throw an exception // attribute not found -> throw an exception

View File

@ -242,7 +242,9 @@ protected:
protected: protected:
/** Aborts the file reading with an exception */ /** Aborts the file reading with an exception */
AI_WONT_RETURN void ThrowException(const std::string &pError) const AI_WONT_RETURN_SUFFIX; template<typename... T>
AI_WONT_RETURN void ThrowException(T&&... args) const AI_WONT_RETURN_SUFFIX;
void ReportWarning(const char *msg, ...); void ReportWarning(const char *msg, ...);
/** Skips all data until the end node of the current element */ /** Skips all data until the end node of the current element */
@ -383,7 +385,7 @@ template <typename Type>
const Type &ColladaParser::ResolveLibraryReference(const std::map<std::string, Type> &pLibrary, const std::string &pURL) const { const Type &ColladaParser::ResolveLibraryReference(const std::map<std::string, Type> &pLibrary, const std::string &pURL) const {
typename std::map<std::string, Type>::const_iterator it = pLibrary.find(pURL); typename std::map<std::string, Type>::const_iterator it = pLibrary.find(pURL);
if (it == pLibrary.end()) if (it == pLibrary.end())
ThrowException(Formatter::format() << "Unable to resolve library reference \"" << pURL << "\"."); ThrowException("Unable to resolve library reference \"", pURL, "\".");
return it->second; return it->second;
} }

View File

@ -152,7 +152,7 @@ void DXFImporter::InternReadFile( const std::string& filename, aiScene* pScene,
// Check whether we can read the file // Check whether we can read the file
if( file.get() == nullptr ) { if( file.get() == nullptr ) {
throw DeadlyImportError( "Failed to open DXF file " + filename + ""); throw DeadlyImportError( "Failed to open DXF file ", filename, "");
} }
// Check whether this is a binary DXF file - we can't read binary DXF files :-( // Check whether this is a binary DXF file - we can't read binary DXF files :-(

View File

@ -127,7 +127,7 @@ namespace {
AI_WONT_RETURN void TokenizeError(const std::string& message, size_t offset) AI_WONT_RETURN_SUFFIX; AI_WONT_RETURN void TokenizeError(const std::string& message, size_t offset) AI_WONT_RETURN_SUFFIX;
AI_WONT_RETURN void TokenizeError(const std::string& message, size_t offset) AI_WONT_RETURN void TokenizeError(const std::string& message, size_t offset)
{ {
throw DeadlyImportError(Util::AddOffset("FBX-Tokenize",message,offset)); throw DeadlyImportError("FBX-Tokenize", Util::GetOffsetText(offset), message);
} }
@ -468,7 +468,7 @@ void TokenizeBinary(TokenList& output_tokens, const char* input, size_t length)
catch (const DeadlyImportError& e) catch (const DeadlyImportError& e)
{ {
if (!is64bits && (length > std::numeric_limits<std::uint32_t>::max())) { if (!is64bits && (length > std::numeric_limits<std::uint32_t>::max())) {
throw DeadlyImportError("The FBX file is invalid. This may be because the content is too big for this older version (" + to_string(version) + ") of the FBX format. (" + e.what() + ")"); throw DeadlyImportError("The FBX file is invalid. This may be because the content is too big for this older version (", to_string(version), ") of the FBX format. (", e.what(), ")");
} }
throw; throw;
} }

View File

@ -61,7 +61,7 @@ namespace Util {
// signal DOM construction error, this is always unrecoverable. Throws DeadlyImportError. // signal DOM construction error, this is always unrecoverable. Throws DeadlyImportError.
void DOMError(const std::string& message, const Token& token) void DOMError(const std::string& message, const Token& token)
{ {
throw DeadlyImportError(Util::AddTokenText("FBX-DOM",message,&token)); throw DeadlyImportError("FBX-DOM", Util::GetTokenText(&token), message);
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
@ -70,7 +70,7 @@ void DOMError(const std::string& message, const Element* element /*= nullptr*/)
if(element) { if(element) {
DOMError(message,element->KeyToken()); DOMError(message,element->KeyToken());
} }
throw DeadlyImportError("FBX-DOM " + message); throw DeadlyImportError("FBX-DOM ", message);
} }
@ -79,7 +79,7 @@ void DOMError(const std::string& message, const Element* element /*= nullptr*/)
void DOMWarning(const std::string& message, const Token& token) void DOMWarning(const std::string& message, const Token& token)
{ {
if(DefaultLogger::get()) { if(DefaultLogger::get()) {
ASSIMP_LOG_WARN(Util::AddTokenText("FBX-DOM",message,&token)); ASSIMP_LOG_WARN_F("FBX-DOM", Util::GetTokenText(&token), message);
} }
} }

View File

@ -73,7 +73,7 @@ namespace {
AI_WONT_RETURN void ParseError(const std::string& message, const Token& token) AI_WONT_RETURN_SUFFIX; AI_WONT_RETURN void ParseError(const std::string& message, const Token& token) AI_WONT_RETURN_SUFFIX;
AI_WONT_RETURN void ParseError(const std::string& message, const Token& token) AI_WONT_RETURN void ParseError(const std::string& message, const Token& token)
{ {
throw DeadlyImportError(Util::AddTokenText("FBX-Parser",message,&token)); throw DeadlyImportError("FBX-Parser", Util::GetTokenText(&token), message);
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
@ -83,7 +83,7 @@ namespace {
if(element) { if(element) {
ParseError(message,element->KeyToken()); ParseError(message,element->KeyToken());
} }
throw DeadlyImportError("FBX-Parser " + message); throw DeadlyImportError("FBX-Parser ", message);
} }

View File

@ -90,7 +90,7 @@ namespace {
AI_WONT_RETURN void TokenizeError(const std::string& message, unsigned int line, unsigned int column) AI_WONT_RETURN_SUFFIX; AI_WONT_RETURN void TokenizeError(const std::string& message, unsigned int line, unsigned int column) AI_WONT_RETURN_SUFFIX;
AI_WONT_RETURN void TokenizeError(const std::string& message, unsigned int line, unsigned int column) AI_WONT_RETURN void TokenizeError(const std::string& message, unsigned int line, unsigned int column)
{ {
throw DeadlyImportError(Util::AddLineAndColumn("FBX-Tokenize",message,line,column)); throw DeadlyImportError("FBX-Tokenize", Util::GetLineAndColumnText(line,column), message);
} }

View File

@ -86,32 +86,30 @@ const char* TokenTypeString(TokenType t)
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
std::string AddOffset(const std::string& prefix, const std::string& text, size_t offset) std::string GetOffsetText(size_t offset)
{ {
return static_cast<std::string>( (Formatter::format() << prefix << " (offset 0x" << std::hex << offset << ") " << text) ); return static_cast<std::string>( Formatter::format() << " (offset 0x" << std::hex << offset << ") " );
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
std::string AddLineAndColumn(const std::string& prefix, const std::string& text, unsigned int line, unsigned int column) std::string GetLineAndColumnText(unsigned int line, unsigned int column)
{ {
return static_cast<std::string>( (Formatter::format() << prefix << " (line " << line << " << col " << column << ") " << text) ); return static_cast<std::string>( Formatter::format() << " (line " << line << " << col " << column << ") " );
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
std::string AddTokenText(const std::string& prefix, const std::string& text, const Token* tok) std::string GetTokenText(const Token* tok)
{ {
if(tok->IsBinary()) { if(tok->IsBinary()) {
return static_cast<std::string>( (Formatter::format() << prefix << return static_cast<std::string>( Formatter::format() <<
" (" << TokenTypeString(tok->Type()) << " (" << TokenTypeString(tok->Type()) <<
", offset 0x" << std::hex << tok->Offset() << ") " << ", offset 0x" << std::hex << tok->Offset() << ") " );
text) );
} }
return static_cast<std::string>( (Formatter::format() << prefix << return static_cast<std::string>( Formatter::format() <<
" (" << TokenTypeString(tok->Type()) << " (" << TokenTypeString(tok->Type()) <<
", line " << tok->Line() << ", line " << tok->Line() <<
", col " << tok->Column() << ") " << ", col " << tok->Column() << ") " );
text) );
} }
// Generated by this formula: T["ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[i]] = i; // Generated by this formula: T["ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[i]] = i;

View File

@ -73,31 +73,24 @@ const char* TokenTypeString(TokenType t);
/** Format log/error messages using a given offset in the source binary file /** Format log/error messages using a given offset in the source binary file
* *
* @param prefix Message prefix to be preprended to the location info. * @param offset offset within the file
* @param text Message text * @return A string of the following format: " (offset 0x{offset}) "*/
* @param line Line index, 1-based std::string GetOffsetText(size_t offset);
* @param column Column index, 1-based
* @return A string of the following format: {prefix} (offset 0x{offset}) {text}*/
std::string AddOffset(const std::string& prefix, const std::string& text, size_t offset);
/** Format log/error messages using a given line location in the source file. /** Format log/error messages using a given line location in the source file.
* *
* @param prefix Message prefix to be preprended to the location info.
* @param text Message text
* @param line Line index, 1-based * @param line Line index, 1-based
* @param column Column index, 1-based * @param column Column index, 1-based
* @return A string of the following format: {prefix} (line {line}, col {column}) {text}*/ * @return A string of the following format: " (line {line}, col {column}) "*/
std::string AddLineAndColumn(const std::string& prefix, const std::string& text, unsigned int line, unsigned int column); std::string GetLineAndColumnText(unsigned int line, unsigned int column);
/** Format log/error messages using a given cursor token. /** Format log/error messages using a given cursor token.
* *
* @param prefix Message prefix to be preprended to the location info.
* @param text Message text
* @param tok Token where parsing/processing stopped * @param tok Token where parsing/processing stopped
* @return A string of the following format: {prefix} ({token-type}, line {line}, col {column}) {text}*/ * @return A string of the following format: " ({token-type}, line {line}, col {column}) "*/
std::string AddTokenText(const std::string& prefix, const std::string& text, const Token* tok); std::string GetTokenText(const Token* tok);
/** Decode a single Base64-encoded character. /** Decode a single Base64-encoded character.
* *

View File

@ -115,7 +115,7 @@ void HMPImporter::InternReadFile(const std::string &pFile,
// Check whether we can read from the file // Check whether we can read from the file
if (file.get() == nullptr) { if (file.get() == nullptr) {
throw DeadlyImportError("Failed to open HMP file " + pFile + "."); throw DeadlyImportError("Failed to open HMP file ", pFile, ".");
} }
// Check whether the HMP file is large enough to contain // Check whether the HMP file is large enough to contain
@ -159,8 +159,8 @@ void HMPImporter::InternReadFile(const std::string &pFile,
szBuffer[4] = '\0'; szBuffer[4] = '\0';
// We're definitely unable to load this file // We're definitely unable to load this file
throw DeadlyImportError("Unknown HMP subformat " + pFile + throw DeadlyImportError("Unknown HMP subformat ", pFile,
". Magic word (" + szBuffer + ") is not known"); ". Magic word (", szBuffer, ") is not known");
} }
// Set the AI_SCENE_FLAGS_TERRAIN bit // Set the AI_SCENE_FLAGS_TERRAIN bit

View File

@ -867,7 +867,7 @@ void IRRImporter::InternReadFile(const std::string &pFile,
// Check whether we can read from the file // Check whether we can read from the file
if (file.get() == nullptr) { if (file.get() == nullptr) {
throw DeadlyImportError("Failed to open IRR file " + pFile + ""); throw DeadlyImportError("Failed to open IRR file ", pFile, "");
} }
// Construct the irrXML parser // Construct the irrXML parser

View File

@ -140,7 +140,7 @@ void IRRMeshImporter::InternReadFile( const std::string& pFile,
// Check whether we can read from the file // Check whether we can read from the file
if (file.get() == nullptr) { if (file.get() == nullptr) {
throw DeadlyImportError("Failed to open IRRMESH file " + pFile + "."); throw DeadlyImportError("Failed to open IRRMESH file ", pFile, ".");
} }
// Construct the irrXML parser // Construct the irrXML parser

View File

@ -145,7 +145,7 @@ void LWOImporter::InternReadFile(const std::string &pFile,
// Check whether we can read from the file // Check whether we can read from the file
if (file.get() == nullptr) { if (file.get() == nullptr) {
throw DeadlyImportError("Failed to open LWO file " + pFile + "."); throw DeadlyImportError("Failed to open LWO file ", pFile, ".");
} }
if ((this->fileSize = (unsigned int)file->FileSize()) < 12) { if ((this->fileSize = (unsigned int)file->FileSize()) < 12) {
@ -212,7 +212,7 @@ void LWOImporter::InternReadFile(const std::string &pFile,
szBuff[2] = (char)(fileType >> 8u); szBuff[2] = (char)(fileType >> 8u);
szBuff[3] = (char)(fileType); szBuff[3] = (char)(fileType);
szBuff[4] = '\0'; szBuff[4] = '\0';
throw DeadlyImportError(std::string("Unknown LWO sub format: ") + szBuff); throw DeadlyImportError("Unknown LWO sub format: ", szBuff);
} }
if (AI_LWO_FOURCC_LWOB != fileType) { if (AI_LWO_FOURCC_LWOB != fileType) {
@ -232,7 +232,7 @@ void LWOImporter::InternReadFile(const std::string &pFile,
} }
if (configLayerName.length() && !hasNamedLayer) { if (configLayerName.length() && !hasNamedLayer) {
throw DeadlyImportError("LWO2: Unable to find the requested layer: " + configLayerName); throw DeadlyImportError("LWO2: Unable to find the requested layer: ", configLayerName);
} }
} }

View File

@ -502,7 +502,7 @@ void LWSImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy
// Check whether we can read from the file // Check whether we can read from the file
if (file.get() == nullptr) { if (file.get() == nullptr) {
throw DeadlyImportError("Failed to open LWS file " + pFile + "."); throw DeadlyImportError("Failed to open LWS file ", pFile, ".");
} }
// Allocate storage and copy the contents of the file to a memory buffer // Allocate storage and copy the contents of the file to a memory buffer

View File

@ -160,21 +160,21 @@ void M3DImporter::InternReadFile(const std::string &file, aiScene *pScene, IOSys
// Read file into memory // Read file into memory
std::unique_ptr<IOStream> pStream(pIOHandler->Open(file, "rb")); std::unique_ptr<IOStream> pStream(pIOHandler->Open(file, "rb"));
if (!pStream.get()) { if (!pStream.get()) {
throw DeadlyImportError("Failed to open file " + file + "."); throw DeadlyImportError("Failed to open file ", file, ".");
} }
// Get the file-size and validate it, throwing an exception when fails // Get the file-size and validate it, throwing an exception when fails
size_t fileSize = pStream->FileSize(); size_t fileSize = pStream->FileSize();
if (fileSize < 8) { if (fileSize < 8) {
throw DeadlyImportError("M3D-file " + file + " is too small."); throw DeadlyImportError("M3D-file ", file, " is too small.");
} }
std::vector<unsigned char> buffer(fileSize); std::vector<unsigned char> buffer(fileSize);
if (fileSize != pStream->Read(buffer.data(), 1, fileSize)) { if (fileSize != pStream->Read(buffer.data(), 1, fileSize)) {
throw DeadlyImportError("Failed to read the file " + file + "."); throw DeadlyImportError("Failed to read the file ", file, ".");
} }
// extra check for binary format's first 8 bytes. Not done for the ASCII variant // extra check for binary format's first 8 bytes. Not done for the ASCII variant
if (!memcmp(buffer.data(), "3DMO", 4) && memcmp(buffer.data() + 4, &fileSize, 4)) { if (!memcmp(buffer.data(), "3DMO", 4) && memcmp(buffer.data() + 4, &fileSize, 4)) {
throw DeadlyImportError("Bad binary header in file " + file + "."); throw DeadlyImportError("Bad binary header in file ", file, ".");
} }
#ifdef M3D_ASCII #ifdef M3D_ASCII
// make sure there's a terminator zero character, as input must be ASCIIZ // make sure there's a terminator zero character, as input must be ASCIIZ
@ -200,7 +200,7 @@ void M3DImporter::InternReadFile(const std::string &file, aiScene *pScene, IOSys
M3DWrapper m3d(pIOHandler, buffer); M3DWrapper m3d(pIOHandler, buffer);
if (!m3d) { if (!m3d) {
throw DeadlyImportError("Unable to parse " + file + " as M3D."); throw DeadlyImportError("Unable to parse ", file, " as M3D.");
} }
// create the root node // create the root node

View File

@ -222,7 +222,7 @@ void MD2Importer::InternReadFile( const std::string& pFile,
// Check whether we can read from the file // Check whether we can read from the file
if (file.get() == nullptr) { if (file.get() == nullptr) {
throw DeadlyImportError("Failed to open MD2 file " + pFile + ""); throw DeadlyImportError("Failed to open MD2 file ", pFile, "");
} }
// check whether the md3 file is large enough to contain // check whether the md3 file is large enough to contain

View File

@ -715,7 +715,7 @@ void MD3Importer::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy
// Check whether we can read from the file // Check whether we can read from the file
if (file.get() == nullptr) { if (file.get() == nullptr) {
throw DeadlyImportError("Failed to open MD3 file " + pFile + "."); throw DeadlyImportError("Failed to open MD3 file ", pFile, ".");
} }
// Check whether the md3 file is large enough to contain the header // Check whether the md3 file is large enough to contain the header

View File

@ -675,7 +675,7 @@ void MD5Importer::LoadMD5CameraFile() {
// Check whether we can read from the file // Check whether we can read from the file
if (!file.get() || !file->FileSize()) { if (!file.get() || !file->FileSize()) {
throw DeadlyImportError("Failed to read MD5CAMERA file: " + pFile); throw DeadlyImportError("Failed to read MD5CAMERA file: ", pFile);
} }
mHadMD5Camera = true; mHadMD5Camera = true;
LoadFileIntoMemory(file.get()); LoadFileIntoMemory(file.get());

View File

@ -219,7 +219,7 @@ void MDCImporter::InternReadFile(
// Check whether we can read from the file // Check whether we can read from the file
if (file.get() == nullptr) { if (file.get() == nullptr) {
throw DeadlyImportError("Failed to open MDC file " + pFile + "."); throw DeadlyImportError("Failed to open MDC file ", pFile, ".");
} }
// check whether the mdc file is large enough to contain the file header // check whether the mdc file is large enough to contain the file header

View File

@ -218,12 +218,12 @@ private:
template <typename MDLFileHeader> template <typename MDLFileHeader>
void HL1MDLLoader::load_file_into_buffer(const std::string &file_path, unsigned char *&buffer) { void HL1MDLLoader::load_file_into_buffer(const std::string &file_path, unsigned char *&buffer) {
if (!io_->Exists(file_path)) if (!io_->Exists(file_path))
throw DeadlyImportError("Missing file " + DefaultIOSystem::fileName(file_path) + "."); throw DeadlyImportError("Missing file ", DefaultIOSystem::fileName(file_path), ".");
std::unique_ptr<IOStream> file(io_->Open(file_path)); std::unique_ptr<IOStream> file(io_->Open(file_path));
if (file.get() == nullptr) { if (file.get() == nullptr) {
throw DeadlyImportError("Failed to open MDL file " + DefaultIOSystem::fileName(file_path) + "."); throw DeadlyImportError("Failed to open MDL file ", DefaultIOSystem::fileName(file_path), ".");
} }
const size_t file_size = file->FileSize(); const size_t file_size = file->FileSize();

View File

@ -167,7 +167,7 @@ void MDLImporter::InternReadFile(const std::string &pFile,
// Check whether we can read from the file // Check whether we can read from the file
if (file.get() == nullptr) { if (file.get() == nullptr) {
throw DeadlyImportError("Failed to open MDL file " + pFile + "."); throw DeadlyImportError("Failed to open MDL file ", pFile, ".");
} }
// This should work for all other types of MDL files, too ... // This should work for all other types of MDL files, too ...
@ -251,8 +251,8 @@ void MDLImporter::InternReadFile(const std::string &pFile,
} }
} else { } else {
// print the magic word to the log file // print the magic word to the log file
throw DeadlyImportError("Unknown MDL subformat " + pFile + throw DeadlyImportError("Unknown MDL subformat ", pFile,
". Magic word (" + std::string((char *)&iMagicWord, 4) + ") is not known"); ". Magic word (", std::string((char *)&iMagicWord, 4), ") is not known");
} }
// Now rotate the whole scene 90 degrees around the x axis to convert to internal coordinate system // Now rotate the whole scene 90 degrees around the x axis to convert to internal coordinate system

View File

@ -111,7 +111,7 @@ void MMDImporter::InternReadFile(const std::string &file, aiScene *pScene,
// Read file by istream // Read file by istream
std::filebuf fb; std::filebuf fb;
if (!fb.open(file, std::ios::in | std::ios::binary)) { if (!fb.open(file, std::ios::in | std::ios::binary)) {
throw DeadlyImportError("Failed to open file " + file + "."); throw DeadlyImportError("Failed to open file ", file, ".");
} }
std::istream fileStream(&fb); std::istream fileStream(&fb);
@ -122,7 +122,7 @@ void MMDImporter::InternReadFile(const std::string &file, aiScene *pScene,
fileStream.seekg(0, fileStream.beg); fileStream.seekg(0, fileStream.beg);
if (fileSize < sizeof(pmx::PmxModel)) { if (fileSize < sizeof(pmx::PmxModel)) {
throw DeadlyImportError(file + " is too small."); throw DeadlyImportError(file, " is too small.");
} }
pmx::PmxModel model; pmx::PmxModel model;

View File

@ -524,7 +524,7 @@ namespace pmx
if (version != 2.0f && version != 2.1f) if (version != 2.0f && version != 2.1f)
{ {
std::cerr << "this is not ver2.0 or ver2.1 but " << version << "." << std::endl; std::cerr << "this is not ver2.0 or ver2.1 but " << version << "." << std::endl;
throw DeadlyImportError("MMD: this is not ver2.0 or ver2.1 but " + to_string(version)); throw DeadlyImportError("MMD: this is not ver2.0 or ver2.1 but ", to_string(version));
} }
this->setting.Read(stream); this->setting.Read(stream);

View File

@ -229,7 +229,7 @@ void MS3DImporter::InternReadFile( const std::string& pFile,
stream.CopyAndAdvance(head,10); stream.CopyAndAdvance(head,10);
stream >> version; stream >> version;
if (strncmp(head,"MS3D000000",10)) { if (strncmp(head,"MS3D000000",10)) {
throw DeadlyImportError("Not a MS3D file, magic string MS3D000000 not found: "+pFile); throw DeadlyImportError("Not a MS3D file, magic string MS3D000000 not found: ", pFile);
} }
if (version != 4) { if (version != 4) {

View File

@ -214,7 +214,7 @@ void NFFImporter::InternReadFile(const std::string &pFile,
// Check whether we can read from the file // Check whether we can read from the file
if (!file.get()) if (!file.get())
throw DeadlyImportError("Failed to open NFF file " + pFile + "."); throw DeadlyImportError("Failed to open NFF file ", pFile, ".");
// allocate storage and copy the contents of the file to a memory buffer // allocate storage and copy the contents of the file to a memory buffer
// (terminate it with zero) // (terminate it with zero)

View File

@ -123,7 +123,7 @@ void OFFImporter::InternReadFile( const std::string& pFile, aiScene* pScene, IOS
// Check whether we can read from the file // Check whether we can read from the file
if( file.get() == nullptr) { if( file.get() == nullptr) {
throw DeadlyImportError( "Failed to open OFF file " + pFile + "."); throw DeadlyImportError( "Failed to open OFF file ", pFile, ".");
} }
// allocate storage and copy the contents of the file to a memory buffer // allocate storage and copy the contents of the file to a memory buffer

View File

@ -112,7 +112,7 @@ void ObjFileImporter::InternReadFile(const std::string &file, aiScene *pScene, I
}; };
std::unique_ptr<IOStream, decltype(streamCloser)> fileStream(pIOHandler->Open(file, mode), streamCloser); std::unique_ptr<IOStream, decltype(streamCloser)> fileStream(pIOHandler->Open(file, mode), streamCloser);
if (!fileStream.get()) { if (!fileStream.get()) {
throw DeadlyImportError("Failed to open file " + file + "."); throw DeadlyImportError("Failed to open file ", file, ".");
} }
// Get the file-size and validate it, throwing an exception when fails // Get the file-size and validate it, throwing an exception when fails

View File

@ -187,8 +187,8 @@ Mesh *OgreBinarySerializer::ImportMesh(MemoryStreamReader *stream) {
/// @todo Check what we can actually support. /// @todo Check what we can actually support.
std::string version = serializer.ReadLine(); std::string version = serializer.ReadLine();
if (version != MESH_VERSION_1_8) { if (version != MESH_VERSION_1_8) {
throw DeadlyExportError(Formatter::format() << "Mesh version " << version << " not supported by this importer. Run OgreMeshUpgrader tool on the file and try again." throw DeadlyExportError("Mesh version ", version, " not supported by this importer. Run OgreMeshUpgrader tool on the file and try again.",
<< " Supported versions: " << MESH_VERSION_1_8); " Supported versions: ", MESH_VERSION_1_8);
} }
Mesh *mesh = new Mesh(); Mesh *mesh = new Mesh();
@ -471,7 +471,7 @@ void OgreBinarySerializer::ReadSubMeshNames(Mesh *mesh) {
uint16_t submeshIndex = Read<uint16_t>(); uint16_t submeshIndex = Read<uint16_t>();
SubMesh *submesh = mesh->GetSubMesh(submeshIndex); SubMesh *submesh = mesh->GetSubMesh(submeshIndex);
if (!submesh) { if (!submesh) {
throw DeadlyImportError(Formatter::format() << "Ogre Mesh does not include submesh " << submeshIndex << " referenced in M_SUBMESH_NAME_TABLE_ELEMENT. Invalid mesh file."); throw DeadlyImportError("Ogre Mesh does not include submesh ", submeshIndex, " referenced in M_SUBMESH_NAME_TABLE_ELEMENT. Invalid mesh file.");
} }
submesh->name = ReadLine(); submesh->name = ReadLine();
@ -788,7 +788,7 @@ MemoryStreamReaderPtr OgreBinarySerializer::OpenReader(Assimp::IOSystem *pIOHand
IOStream *f = pIOHandler->Open(filename, "rb"); IOStream *f = pIOHandler->Open(filename, "rb");
if (!f) { if (!f) {
throw DeadlyImportError("Failed to open skeleton file " + filename); throw DeadlyImportError("Failed to open skeleton file ", filename);
} }
return MemoryStreamReaderPtr(new MemoryStreamReader(f)); return MemoryStreamReaderPtr(new MemoryStreamReader(f));
@ -803,8 +803,8 @@ void OgreBinarySerializer::ReadSkeleton(Skeleton *skeleton) {
// This deserialization supports both versions of the skeleton spec // This deserialization supports both versions of the skeleton spec
std::string version = ReadLine(); std::string version = ReadLine();
if (version != SKELETON_VERSION_1_8 && version != SKELETON_VERSION_1_1) { if (version != SKELETON_VERSION_1_8 && version != SKELETON_VERSION_1_1) {
throw DeadlyExportError(Formatter::format() << "Skeleton version " << version << " not supported by this importer." throw DeadlyExportError("Skeleton version ", version, " not supported by this importer.",
<< " Supported versions: " << SKELETON_VERSION_1_8 << " and " << SKELETON_VERSION_1_1); " Supported versions: ", SKELETON_VERSION_1_8, " and ", SKELETON_VERSION_1_1);
} }
ASSIMP_LOG_VERBOSE_DEBUG("Reading Skeleton"); ASSIMP_LOG_VERBOSE_DEBUG("Reading Skeleton");
@ -871,7 +871,7 @@ void OgreBinarySerializer::ReadBone(Skeleton *skeleton) {
// Bone indexes need to start from 0 and be contiguous // Bone indexes need to start from 0 and be contiguous
if (bone->id != skeleton->bones.size()) { if (bone->id != skeleton->bones.size()) {
throw DeadlyImportError(Formatter::format() << "Ogre Skeleton bone indexes not contiguous. Error at bone index " << bone->id); throw DeadlyImportError("Ogre Skeleton bone indexes not contiguous. Error at bone index ", bone->id);
} }
ASSIMP_LOG_VERBOSE_DEBUG_F(" ", bone->id, " ", bone->name); ASSIMP_LOG_VERBOSE_DEBUG_F(" ", bone->id, " ", bone->name);
@ -889,7 +889,7 @@ void OgreBinarySerializer::ReadBoneParent(Skeleton *skeleton) {
if (child && parent) if (child && parent)
parent->AddChild(child); parent->AddChild(child);
else else
throw DeadlyImportError(Formatter::format() << "Failed to find bones for parenting: Child id " << childId << " for parent id " << parentId); throw DeadlyImportError("Failed to find bones for parenting: Child id ", childId, " for parent id ", parentId);
} }
void OgreBinarySerializer::ReadSkeletonAnimation(Skeleton *skeleton) { void OgreBinarySerializer::ReadSkeletonAnimation(Skeleton *skeleton) {
@ -926,7 +926,7 @@ void OgreBinarySerializer::ReadSkeletonAnimationTrack(Skeleton * /*skeleton*/, A
uint16_t boneId = Read<uint16_t>(); uint16_t boneId = Read<uint16_t>();
Bone *bone = dest->parentSkeleton->BoneById(boneId); Bone *bone = dest->parentSkeleton->BoneById(boneId);
if (!bone) { if (!bone) {
throw DeadlyImportError(Formatter::format() << "Cannot read animation track, target bone " << boneId << " not in target Skeleton"); throw DeadlyImportError("Cannot read animation track, target bone ", boneId, " not in target Skeleton");
} }
VertexAnimationTrack track; VertexAnimationTrack track;

View File

@ -100,7 +100,7 @@ void OgreImporter::InternReadFile(const std::string &pFile, aiScene *pScene, Ass
// Open source file // Open source file
IOStream *f = pIOHandler->Open(pFile, "rb"); IOStream *f = pIOHandler->Open(pFile, "rb");
if (!f) { if (!f) {
throw DeadlyImportError("Failed to open file " + pFile); throw DeadlyImportError("Failed to open file ", pFile);
} }
// Binary .mesh import // Binary .mesh import

View File

@ -476,7 +476,7 @@ void SubMesh::Reset(){
aiMesh *SubMesh::ConvertToAssimpMesh(Mesh *parent) { aiMesh *SubMesh::ConvertToAssimpMesh(Mesh *parent) {
if (operationType != OT_TRIANGLE_LIST) { if (operationType != OT_TRIANGLE_LIST) {
throw DeadlyImportError(Formatter::format() << "Only mesh operation type OT_TRIANGLE_LIST is supported. Found " << operationType); throw DeadlyImportError("Only mesh operation type OT_TRIANGLE_LIST is supported. Found ", operationType);
} }
aiMesh *dest = new aiMesh(); aiMesh *dest = new aiMesh();
@ -944,7 +944,7 @@ void Bone::AddChild(Bone *bone) {
if (!bone) if (!bone)
return; return;
if (bone->IsParented()) if (bone->IsParented())
throw DeadlyImportError("Attaching child Bone that is already parented: " + bone->name); throw DeadlyImportError("Attaching child Bone that is already parented: ", bone->name);
bone->parent = this; bone->parent = this;
bone->parentId = id; bone->parentId = id;
@ -963,7 +963,7 @@ void Bone::CalculateWorldMatrixAndDefaultPose(Skeleton *skeleton) {
for (auto boneId : children) { for (auto boneId : children) {
Bone *child = skeleton->BoneById(boneId); Bone *child = skeleton->BoneById(boneId);
if (!child) { if (!child) {
throw DeadlyImportError(Formatter::format() << "CalculateWorldMatrixAndDefaultPose: Failed to find child bone " << boneId << " for parent " << id << " " << name); throw DeadlyImportError("CalculateWorldMatrixAndDefaultPose: Failed to find child bone ", boneId, " for parent ", id, " ", name);
} }
child->CalculateWorldMatrixAndDefaultPose(skeleton); child->CalculateWorldMatrixAndDefaultPose(skeleton);
} }
@ -983,7 +983,7 @@ aiNode *Bone::ConvertToAssimpNode(Skeleton *skeleton, aiNode *parentNode) {
for (size_t i = 0, len = children.size(); i < len; ++i) { for (size_t i = 0, len = children.size(); i < len; ++i) {
Bone *child = skeleton->BoneById(children[i]); Bone *child = skeleton->BoneById(children[i]);
if (!child) { if (!child) {
throw DeadlyImportError(Formatter::format() << "ConvertToAssimpNode: Failed to find child bone " << children[i] << " for parent " << id << " " << name); throw DeadlyImportError("ConvertToAssimpNode: Failed to find child bone ", children[i], " for parent ", id, " ", name);
} }
node->mChildren[i] = child->ConvertToAssimpNode(skeleton, node); node->mChildren[i] = child->ConvertToAssimpNode(skeleton, node);
} }
@ -1022,7 +1022,7 @@ aiNodeAnim *VertexAnimationTrack::ConvertToAssimpAnimationNode(Skeleton *skeleto
Bone *bone = skeleton->BoneByName(boneName); Bone *bone = skeleton->BoneByName(boneName);
if (!bone) { if (!bone) {
throw DeadlyImportError("VertexAnimationTrack::ConvertToAssimpAnimationNode: Failed to find bone " + boneName + " from parent Skeleton"); throw DeadlyImportError("VertexAnimationTrack::ConvertToAssimpAnimationNode: Failed to find bone ", boneName, " from parent Skeleton");
} }
// Keyframes // Keyframes

View File

@ -59,9 +59,9 @@ namespace Ogre {
AI_WONT_RETURN void ThrowAttibuteError(const XmlReader *reader, const std::string &name, const std::string &error = "") AI_WONT_RETURN_SUFFIX; AI_WONT_RETURN void ThrowAttibuteError(const XmlReader *reader, const std::string &name, const std::string &error = "") AI_WONT_RETURN_SUFFIX;
AI_WONT_RETURN void ThrowAttibuteError(const XmlReader *reader, const std::string &name, const std::string &error) { AI_WONT_RETURN void ThrowAttibuteError(const XmlReader *reader, const std::string &name, const std::string &error) {
if (!error.empty()) { if (!error.empty()) {
throw DeadlyImportError(error + " in node '" + std::string(reader->getNodeName()) + "' and attribute '" + name + "'"); throw DeadlyImportError(error, " in node '", reader->getNodeName(), "' and attribute '", name, "'");
} else { } else {
throw DeadlyImportError("Attribute '" + name + "' does not exist in node '" + std::string(reader->getNodeName()) + "'"); throw DeadlyImportError("Attribute '", name, "' does not exist in node '", reader->getNodeName(), "'");
} }
} }
@ -265,7 +265,7 @@ MeshXml *OgreXmlSerializer::ImportMesh(XmlReader *reader) {
void OgreXmlSerializer::ReadMesh(MeshXml *mesh) { void OgreXmlSerializer::ReadMesh(MeshXml *mesh) {
if (NextNode() != nnMesh) { if (NextNode() != nnMesh) {
throw DeadlyImportError("Root node is <" + m_currentNodeName + "> expecting <mesh>"); throw DeadlyImportError("Root node is <", m_currentNodeName, "> expecting <mesh>");
} }
ASSIMP_LOG_VERBOSE_DEBUG("Reading Mesh"); ASSIMP_LOG_VERBOSE_DEBUG("Reading Mesh");
@ -430,18 +430,18 @@ void OgreXmlSerializer::ReadGeometryVertexBuffer(VertexDataXml *dest) {
// Sanity checks // Sanity checks
if (dest->positions.size() != dest->count) { if (dest->positions.size() != dest->count) {
throw DeadlyImportError(Formatter::format() << "Read only " << dest->positions.size() << " positions when should have read " << dest->count); throw DeadlyImportError("Read only ", dest->positions.size(), " positions when should have read ", dest->count);
} }
if (normals && dest->normals.size() != dest->count) { if (normals && dest->normals.size() != dest->count) {
throw DeadlyImportError(Formatter::format() << "Read only " << dest->normals.size() << " normals when should have read " << dest->count); throw DeadlyImportError("Read only ", dest->normals.size(), " normals when should have read ", dest->count);
} }
if (tangents && dest->tangents.size() != dest->count) { if (tangents && dest->tangents.size() != dest->count) {
throw DeadlyImportError(Formatter::format() << "Read only " << dest->tangents.size() << " tangents when should have read " << dest->count); throw DeadlyImportError("Read only ", dest->tangents.size(), " tangents when should have read ", dest->count);
} }
for (unsigned int i = 0; i < dest->uvs.size(); ++i) { for (unsigned int i = 0; i < dest->uvs.size(); ++i) {
if (dest->uvs[i].size() != dest->count) { if (dest->uvs[i].size() != dest->count) {
throw DeadlyImportError(Formatter::format() << "Read only " << dest->uvs[i].size() throw DeadlyImportError("Read only ", dest->uvs[i].size(),
<< " uvs for uv index " << i << " when should have read " << dest->count); " uvs for uv index ", i, " when should have read ", dest->count);
} }
} }
} }
@ -507,7 +507,7 @@ void OgreXmlSerializer::ReadSubMesh(MeshXml *mesh) {
if (submesh->indexData->faces.size() == submesh->indexData->faceCount) { if (submesh->indexData->faces.size() == submesh->indexData->faceCount) {
ASSIMP_LOG_VERBOSE_DEBUG_F(" - Faces ", submesh->indexData->faceCount); ASSIMP_LOG_VERBOSE_DEBUG_F(" - Faces ", submesh->indexData->faceCount);
} else { } else {
throw DeadlyImportError(Formatter::format() << "Read only " << submesh->indexData->faces.size() << " faces when should have read " << submesh->indexData->faceCount); throw DeadlyImportError("Read only ", submesh->indexData->faces.size(), " faces when should have read ", submesh->indexData->faceCount);
} }
} else if (m_currentNodeName == nnGeometry) { } else if (m_currentNodeName == nnGeometry) {
if (submesh->usesSharedVertexData) { if (submesh->usesSharedVertexData) {
@ -632,20 +632,20 @@ XmlReaderPtr OgreXmlSerializer::OpenReader(Assimp::IOSystem *pIOHandler, const s
std::unique_ptr<IOStream> file(pIOHandler->Open(filename)); std::unique_ptr<IOStream> file(pIOHandler->Open(filename));
if (!file.get()) { if (!file.get()) {
throw DeadlyImportError("Failed to open skeleton file " + filename); throw DeadlyImportError("Failed to open skeleton file ", filename);
} }
std::unique_ptr<CIrrXML_IOStreamReader> stream(new CIrrXML_IOStreamReader(file.get())); std::unique_ptr<CIrrXML_IOStreamReader> stream(new CIrrXML_IOStreamReader(file.get()));
XmlReaderPtr reader = XmlReaderPtr(irr::io::createIrrXMLReader(stream.get())); XmlReaderPtr reader = XmlReaderPtr(irr::io::createIrrXMLReader(stream.get()));
if (!reader.get()) { if (!reader.get()) {
throw DeadlyImportError("Failed to create XML reader for skeleton file " + filename); throw DeadlyImportError("Failed to create XML reader for skeleton file ", filename);
} }
return reader; return reader;
} }
void OgreXmlSerializer::ReadSkeleton(Skeleton *skeleton) { void OgreXmlSerializer::ReadSkeleton(Skeleton *skeleton) {
if (NextNode() != nnSkeleton) { if (NextNode() != nnSkeleton) {
throw DeadlyImportError("Root node is <" + m_currentNodeName + "> expecting <skeleton>"); throw DeadlyImportError("Root node is <", m_currentNodeName, "> expecting <skeleton>");
} }
ASSIMP_LOG_VERBOSE_DEBUG("Reading Skeleton"); ASSIMP_LOG_VERBOSE_DEBUG("Reading Skeleton");
@ -687,7 +687,7 @@ void OgreXmlSerializer::ReadAnimations(Skeleton *skeleton) {
anim->length = ReadAttribute<float>("length"); anim->length = ReadAttribute<float>("length");
if (NextNode() != nnTracks) { if (NextNode() != nnTracks) {
throw DeadlyImportError(Formatter::format() << "No <tracks> found in <animation> " << anim->name); throw DeadlyImportError("No <tracks> found in <animation> ", anim->name);
} }
ReadAnimationTracks(anim); ReadAnimationTracks(anim);
@ -705,7 +705,7 @@ void OgreXmlSerializer::ReadAnimationTracks(Animation *dest) {
track.boneName = ReadAttribute<std::string>("bone"); track.boneName = ReadAttribute<std::string>("bone");
if (NextNode() != nnKeyFrames) { if (NextNode() != nnKeyFrames) {
throw DeadlyImportError(Formatter::format() << "No <keyframes> found in <track> " << dest->name); throw DeadlyImportError("No <keyframes> found in <track> ", dest->name);
} }
ReadAnimationKeyFrames(dest, &track); ReadAnimationKeyFrames(dest, &track);
@ -732,7 +732,7 @@ void OgreXmlSerializer::ReadAnimationKeyFrames(Animation *anim, VertexAnimationT
float angle = ReadAttribute<float>("angle"); float angle = ReadAttribute<float>("angle");
if (NextNode() != nnAxis) { if (NextNode() != nnAxis) {
throw DeadlyImportError("No axis specified for keyframe rotation in animation " + anim->name); throw DeadlyImportError("No axis specified for keyframe rotation in animation ", anim->name);
} }
aiVector3D axis; aiVector3D axis;
@ -774,7 +774,7 @@ void OgreXmlSerializer::ReadBoneHierarchy(Skeleton *skeleton) {
if (bone && parent) if (bone && parent)
parent->AddChild(bone); parent->AddChild(bone);
else else
throw DeadlyImportError("Failed to find bones for parenting: Child " + name + " for parent " + parentName); throw DeadlyImportError("Failed to find bones for parenting: Child ", name, " for parent ", parentName);
} }
// Calculate bone matrices for root bones. Recursively calculates their children. // Calculate bone matrices for root bones. Recursively calculates their children.
@ -813,7 +813,7 @@ void OgreXmlSerializer::ReadBones(Skeleton *skeleton) {
float angle = ReadAttribute<float>("angle"); float angle = ReadAttribute<float>("angle");
if (NextNode() != nnAxis) { if (NextNode() != nnAxis) {
throw DeadlyImportError(Formatter::format() << "No axis specified for bone rotation in bone " << bone->id); throw DeadlyImportError("No axis specified for bone rotation in bone ", bone->id);
} }
aiVector3D axis; aiVector3D axis;
@ -854,7 +854,7 @@ void OgreXmlSerializer::ReadBones(Skeleton *skeleton) {
ASSIMP_LOG_VERBOSE_DEBUG_F(" ", b->id, " ", b->name); ASSIMP_LOG_VERBOSE_DEBUG_F(" ", b->id, " ", b->name);
if (b->id != static_cast<uint16_t>(i)) { if (b->id != static_cast<uint16_t>(i)) {
throw DeadlyImportError(Formatter::format() << "Bone ids are not in sequence starting from 0. Missing index " << i); throw DeadlyImportError("Bone ids are not in sequence starting from 0. Missing index ", i);
} }
} }
} }

View File

@ -302,7 +302,7 @@ void OpenGEXImporter::InternReadFile( const std::string &filename, aiScene *pSce
// open source file // open source file
IOStream *file = pIOHandler->Open( filename, "rb" ); IOStream *file = pIOHandler->Open( filename, "rb" );
if( !file ) { if( !file ) {
throw DeadlyImportError( "Failed to open file " + filename ); throw DeadlyImportError( "Failed to open file ", filename );
} }
std::vector<char> buffer; std::vector<char> buffer;

View File

@ -151,13 +151,13 @@ void PLYImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy
const std::string mode = "rb"; const std::string mode = "rb";
std::unique_ptr<IOStream> fileStream(pIOHandler->Open(pFile, mode)); std::unique_ptr<IOStream> fileStream(pIOHandler->Open(pFile, mode));
if (!fileStream.get()) { if (!fileStream.get()) {
throw DeadlyImportError("Failed to open file " + pFile + "."); throw DeadlyImportError("Failed to open file ", pFile, ".");
} }
// Get the file-size // Get the file-size
const size_t fileSize(fileStream->FileSize()); const size_t fileSize(fileStream->FileSize());
if (0 == fileSize) { if (0 == fileSize) {
throw DeadlyImportError("File " + pFile + " is empty."); throw DeadlyImportError("File ", pFile, " is empty.");
} }
IOStreamBuffer<char> streamedBuffer(1024 * 1024); IOStreamBuffer<char> streamedBuffer(1024 * 1024);

View File

@ -180,7 +180,7 @@ const aiImporterDesc *Q3BSPFileImporter::GetInfo() const {
void Q3BSPFileImporter::InternReadFile(const std::string &rFile, aiScene *scene, IOSystem *ioHandler) { void Q3BSPFileImporter::InternReadFile(const std::string &rFile, aiScene *scene, IOSystem *ioHandler) {
ZipArchiveIOSystem Archive(ioHandler, rFile); ZipArchiveIOSystem Archive(ioHandler, rFile);
if (!Archive.isOpen()) { if (!Archive.isOpen()) {
throw DeadlyImportError("Failed to open file " + rFile + "."); throw DeadlyImportError("Failed to open file ", rFile, ".");
} }
std::string archiveName(""), mapName(""); std::string archiveName(""), mapName("");

View File

@ -110,13 +110,12 @@ void Q3DImporter::InternReadFile(const std::string &pFile,
// The header is 22 bytes large // The header is 22 bytes large
if (stream.GetRemainingSize() < 22) if (stream.GetRemainingSize() < 22)
throw DeadlyImportError("File is either empty or corrupt: " + pFile); throw DeadlyImportError("File is either empty or corrupt: ", pFile);
// Check the file's signature // Check the file's signature
if (ASSIMP_strincmp((const char *)stream.GetPtr(), "quick3Do", 8) && if (ASSIMP_strincmp((const char *)stream.GetPtr(), "quick3Do", 8) &&
ASSIMP_strincmp((const char *)stream.GetPtr(), "quick3Ds", 8)) { ASSIMP_strincmp((const char *)stream.GetPtr(), "quick3Ds", 8)) {
throw DeadlyImportError("Not a Quick3D file. Signature string is: " + throw DeadlyImportError("Not a Quick3D file. Signature string is: ", std::string((const char *)stream.GetPtr(), 8));
std::string((const char *)stream.GetPtr(), 8));
} }
// Print the file format version // Print the file format version

View File

@ -101,7 +101,7 @@ void RAWImporter::InternReadFile(const std::string &pFile,
// Check whether we can read from the file // Check whether we can read from the file
if (file.get() == nullptr) { if (file.get() == nullptr) {
throw DeadlyImportError("Failed to open RAW file " + pFile + "."); throw DeadlyImportError("Failed to open RAW file ", pFile, ".");
} }
// allocate storage and copy the contents of the file to a memory buffer // allocate storage and copy the contents of the file to a memory buffer

View File

@ -808,7 +808,7 @@ void SIBImporter::InternReadFile(const std::string &pFile,
// We should have at least one chunk // We should have at least one chunk
if (stream.GetRemainingSize() < 16) if (stream.GetRemainingSize() < 16)
throw DeadlyImportError("SIB file is either empty or corrupt: " + pFile); throw DeadlyImportError("SIB file is either empty or corrupt: ", pFile);
SIB sib; SIB sib;

View File

@ -695,7 +695,7 @@ void SMDImporter::ReadSmd(const std::string &pFile, IOSystem* pIOHandler) {
// Check whether we can read from the file // Check whether we can read from the file
if (file.get() == nullptr) { if (file.get() == nullptr) {
throw DeadlyImportError("Failed to open SMD/VTA file " + pFile + "."); throw DeadlyImportError("Failed to open SMD/VTA file ", pFile, ".");
} }
iFileSize = (unsigned int)file->FileSize(); iFileSize = (unsigned int)file->FileSize();

View File

@ -181,7 +181,7 @@ void STLImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy
// Check whether we can read from the file // Check whether we can read from the file
if (file.get() == nullptr) { if (file.get() == nullptr) {
throw DeadlyImportError("Failed to open STL file " + pFile + "."); throw DeadlyImportError("Failed to open STL file ", pFile, ".");
} }
mFileSize = (unsigned int)file->FileSize(); mFileSize = (unsigned int)file->FileSize();
@ -207,7 +207,7 @@ void STLImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy
} else if (IsAsciiSTL(mBuffer, mFileSize)) { } else if (IsAsciiSTL(mBuffer, mFileSize)) {
LoadASCIIFile(mScene->mRootNode); LoadASCIIFile(mScene->mRootNode);
} else { } else {
throw DeadlyImportError("Failed to determine STL storage representation for " + pFile + "."); throw DeadlyImportError("Failed to determine STL storage representation for ", pFile, ".");
} }
// create a single default material, using a white diffuse color for consistency with // create a single default material, using a white diffuse color for consistency with

View File

@ -121,7 +121,7 @@ void TerragenImporter::InternReadFile(const std::string &pFile,
// Check whether we can read from the file // Check whether we can read from the file
if (file == nullptr) if (file == nullptr)
throw DeadlyImportError("Failed to open TERRAGEN TERRAIN file " + pFile + "."); throw DeadlyImportError("Failed to open TERRAGEN TERRAIN file ", pFile, ".");
// Construct a stream reader to read all data in the correct endianness // Construct a stream reader to read all data in the correct endianness
StreamReaderLE reader(file); StreamReaderLE reader(file);

View File

@ -114,7 +114,7 @@ void XFileImporter::InternReadFile( const std::string& pFile, aiScene* pScene, I
// read file into memory // read file into memory
std::unique_ptr<IOStream> file( pIOHandler->Open( pFile)); std::unique_ptr<IOStream> file( pIOHandler->Open( pFile));
if ( file.get() == nullptr ) { if ( file.get() == nullptr ) {
throw DeadlyImportError( "Failed to open file " + pFile + "." ); throw DeadlyImportError( "Failed to open file ", pFile, "." );
} }
static const size_t MinSize = 16; static const size_t MinSize = 16;

View File

@ -82,6 +82,17 @@ static void dummy_free(void * /*opaque*/, void *address) {
#endif // !! ASSIMP_BUILD_NO_COMPRESSED_X #endif // !! ASSIMP_BUILD_NO_COMPRESSED_X
// ------------------------------------------------------------------------------------------------
// Throws an exception with a line number and the given text.
template<typename... T>
AI_WONT_RETURN void XFileParser::ThrowException(T&&... args) {
if (mIsBinaryFormat) {
throw DeadlyImportError(args...);
} else {
throw DeadlyImportError("Line ", mLineNumber, ": ", args...);
}
}
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Constructor. Creates a data structure out of the XFile given in the memory block. // Constructor. Creates a data structure out of the XFile given in the memory block.
XFileParser::XFileParser(const std::vector<char> &pBuffer) : XFileParser::XFileParser(const std::vector<char> &pBuffer) :
@ -122,13 +133,13 @@ XFileParser::XFileParser(const std::vector<char> &pBuffer) :
mIsBinaryFormat = true; mIsBinaryFormat = true;
compressed = true; compressed = true;
} else } else
ThrowException(format() << "Unsupported xfile format '" << mP[8] << mP[9] << mP[10] << mP[11] << "'"); ThrowException("Unsupported xfile format '", mP[8], mP[9], mP[10], mP[11], "'");
// float size // float size
mBinaryFloatSize = (unsigned int)(mP[12] - 48) * 1000 + (unsigned int)(mP[13] - 48) * 100 + (unsigned int)(mP[14] - 48) * 10 + (unsigned int)(mP[15] - 48); mBinaryFloatSize = (unsigned int)(mP[12] - 48) * 1000 + (unsigned int)(mP[13] - 48) * 100 + (unsigned int)(mP[14] - 48) * 10 + (unsigned int)(mP[15] - 48);
if (mBinaryFloatSize != 32 && mBinaryFloatSize != 64) if (mBinaryFloatSize != 32 && mBinaryFloatSize != 64)
ThrowException(format() << "Unknown float size " << mBinaryFloatSize << " specified in xfile header."); ThrowException("Unknown float size ", mBinaryFloatSize, " specified in xfile header.");
// The x format specifies size in bits, but we work in bytes // The x format specifies size in bits, but we work in bytes
mBinaryFloatSize /= 8; mBinaryFloatSize /= 8;
@ -864,7 +875,7 @@ void XFileParser::ParseDataObjectAnimationKey(AnimBone *pAnimBone) {
} }
default: default:
ThrowException(format() << "Unknown key type " << keyType << " in animation."); ThrowException("Unknown key type ", keyType, " in animation.");
break; break;
} // end switch } // end switch
@ -1355,16 +1366,6 @@ aiColor3D XFileParser::ReadRGB() {
return color; return color;
} }
// ------------------------------------------------------------------------------------------------
// Throws an exception with a line number and the given text.
AI_WONT_RETURN void XFileParser::ThrowException(const std::string &pText) {
if (mIsBinaryFormat) {
throw DeadlyImportError(pText);
} else {
throw DeadlyImportError(format() << "Line " << mLineNumber << ": " << pText);
}
}
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Filters the imported hierarchy for some degenerated cases that some exporters produce. // Filters the imported hierarchy for some degenerated cases that some exporters produce.
void XFileParser::FilterHierarchy(XFile::Node *pNode) { void XFileParser::FilterHierarchy(XFile::Node *pNode) {

View File

@ -133,7 +133,8 @@ protected:
aiColor4D ReadRGBA(); aiColor4D ReadRGBA();
/** Throws an exception with a line number and the given text. */ /** Throws an exception with a line number and the given text. */
AI_WONT_RETURN void ThrowException( const std::string& pText) AI_WONT_RETURN_SUFFIX; template<typename... T>
AI_WONT_RETURN void ThrowException(T&&... args) AI_WONT_RETURN_SUFFIX;
/** /**
* @brief Filters the imported hierarchy for some degenerated cases that some exporters produce. * @brief Filters the imported hierarchy for some degenerated cases that some exporters produce.

View File

@ -997,18 +997,18 @@ private:
if (index < 32) { if (index < 32) {
FIDecoder *decoder = defaultDecoder[index]; FIDecoder *decoder = defaultDecoder[index];
if (!decoder) { if (!decoder) {
throw DeadlyImportError("Invalid encoding algorithm index " + to_string(index)); throw DeadlyImportError("Invalid encoding algorithm index ", to_string(index));
} }
return decoder->decode(dataP, len); return decoder->decode(dataP, len);
} }
else { else {
if (index - 32 >= vocabulary.encodingAlgorithmTable.size()) { if (index - 32 >= vocabulary.encodingAlgorithmTable.size()) {
throw DeadlyImportError("Invalid encoding algorithm index " + to_string(index)); throw DeadlyImportError("Invalid encoding algorithm index ", to_string(index));
} }
std::string uri = vocabulary.encodingAlgorithmTable[index - 32]; std::string uri = vocabulary.encodingAlgorithmTable[index - 32];
auto it = decoderMap.find(uri); auto it = decoderMap.find(uri);
if (it == decoderMap.end()) { if (it == decoderMap.end()) {
throw DeadlyImportError("Unsupported encoding algorithm " + uri); throw DeadlyImportError("Unsupported encoding algorithm ", uri);
} }
else { else {
return it->second->decode(dataP, len); return it->second->decode(dataP, len);
@ -1027,12 +1027,12 @@ private:
alphabet = "0123456789-:TZ "; alphabet = "0123456789-:TZ ";
break; break;
default: default:
throw DeadlyImportError("Invalid restricted alphabet index " + to_string(index)); throw DeadlyImportError("Invalid restricted alphabet index ", to_string(index));
} }
} }
else { else {
if (index - 16 >= vocabulary.restrictedAlphabetTable.size()) { if (index - 16 >= vocabulary.restrictedAlphabetTable.size()) {
throw DeadlyImportError("Invalid restricted alphabet index " + to_string(index)); throw DeadlyImportError("Invalid restricted alphabet index ", to_string(index));
} }
alphabet = vocabulary.restrictedAlphabetTable[index - 16]; alphabet = vocabulary.restrictedAlphabetTable[index - 16];
} }
@ -1040,7 +1040,7 @@ private:
utf8::utf8to32(alphabet.begin(), alphabet.end(), back_inserter(alphabetUTF32)); utf8::utf8to32(alphabet.begin(), alphabet.end(), back_inserter(alphabetUTF32));
std::string::size_type alphabetLength = alphabetUTF32.size(); std::string::size_type alphabetLength = alphabetUTF32.size();
if (alphabetLength < 2) { if (alphabetLength < 2) {
throw DeadlyImportError("Invalid restricted alphabet length " + to_string(alphabetLength)); throw DeadlyImportError("Invalid restricted alphabet length ", to_string(alphabetLength));
} }
std::string::size_type bitsPerCharacter = 1; std::string::size_type bitsPerCharacter = 1;
while ((1ull << bitsPerCharacter) <= alphabetLength) { while ((1ull << bitsPerCharacter) <= alphabetLength) {
@ -1442,7 +1442,7 @@ private:
std::string uri = parseNonEmptyOctetString2(); std::string uri = parseNonEmptyOctetString2();
auto it = vocabularyMap.find(uri); auto it = vocabularyMap.find(uri);
if (it == vocabularyMap.end()) { if (it == vocabularyMap.end()) {
throw DeadlyImportError("Unknown vocabulary " + uri); throw DeadlyImportError("Unknown vocabulary ", uri);
} }
const FIVocabulary *externalVocabulary = it->second; const FIVocabulary *externalVocabulary = it->second;
if (externalVocabulary->restrictedAlphabetTable) { if (externalVocabulary->restrictedAlphabetTable) {

View File

@ -233,48 +233,48 @@ bool X3DImporter::FindNodeElement(const std::string& pID, const CX3DImporter_Nod
void X3DImporter::Throw_ArgOutOfRange(const std::string& pArgument) void X3DImporter::Throw_ArgOutOfRange(const std::string& pArgument)
{ {
throw DeadlyImportError("Argument value is out of range for: \"" + pArgument + "\"."); throw DeadlyImportError("Argument value is out of range for: \"", pArgument, "\".");
} }
void X3DImporter::Throw_CloseNotFound(const std::string& pNode) void X3DImporter::Throw_CloseNotFound(const std::string& pNode)
{ {
throw DeadlyImportError("Close tag for node <" + pNode + "> not found. Seems file is corrupt."); throw DeadlyImportError("Close tag for node <", pNode, "> not found. Seems file is corrupt.");
} }
void X3DImporter::Throw_ConvertFail_Str2ArrF(const std::string& pAttrValue) void X3DImporter::Throw_ConvertFail_Str2ArrF(const std::string& pAttrValue)
{ {
throw DeadlyImportError("In <" + std::string(mReader->getNodeName()) + "> failed to convert attribute value \"" + pAttrValue + throw DeadlyImportError("In <", mReader->getNodeName(), "> failed to convert attribute value \"", pAttrValue,
"\" from string to array of floats."); "\" from string to array of floats.");
} }
void X3DImporter::Throw_DEF_And_USE() void X3DImporter::Throw_DEF_And_USE()
{ {
throw DeadlyImportError("\"DEF\" and \"USE\" can not be defined both in <" + std::string(mReader->getNodeName()) + ">."); throw DeadlyImportError("\"DEF\" and \"USE\" can not be defined both in <", mReader->getNodeName(), ">.");
} }
void X3DImporter::Throw_IncorrectAttr(const std::string& pAttrName) void X3DImporter::Throw_IncorrectAttr(const std::string& pAttrName)
{ {
throw DeadlyImportError("Node <" + std::string(mReader->getNodeName()) + "> has incorrect attribute \"" + pAttrName + "\"."); throw DeadlyImportError("Node <", mReader->getNodeName(), "> has incorrect attribute \"", pAttrName, "\".");
} }
void X3DImporter::Throw_IncorrectAttrValue(const std::string& pAttrName) void X3DImporter::Throw_IncorrectAttrValue(const std::string& pAttrName)
{ {
throw DeadlyImportError("Attribute \"" + pAttrName + "\" in node <" + std::string(mReader->getNodeName()) + "> has incorrect value."); throw DeadlyImportError("Attribute \"", pAttrName, "\" in node <", mReader->getNodeName(), "> has incorrect value.");
} }
void X3DImporter::Throw_MoreThanOnceDefined(const std::string& pNodeType, const std::string& pDescription) void X3DImporter::Throw_MoreThanOnceDefined(const std::string& pNodeType, const std::string& pDescription)
{ {
throw DeadlyImportError("\"" + pNodeType + "\" node can be used only once in " + mReader->getNodeName() + ". Description: " + pDescription); throw DeadlyImportError("\"", pNodeType, "\" node can be used only once in ", mReader->getNodeName(), ". Description: ", pDescription);
} }
void X3DImporter::Throw_TagCountIncorrect(const std::string& pNode) void X3DImporter::Throw_TagCountIncorrect(const std::string& pNode)
{ {
throw DeadlyImportError("Count of open and close tags for node <" + pNode + "> are not equivalent. Seems file is corrupt."); throw DeadlyImportError("Count of open and close tags for node <", pNode, "> are not equivalent. Seems file is corrupt.");
} }
void X3DImporter::Throw_USE_NotFound(const std::string& pAttrValue) void X3DImporter::Throw_USE_NotFound(const std::string& pAttrValue)
{ {
throw DeadlyImportError("Not found node with name \"" + pAttrValue + "\" in <" + std::string(mReader->getNodeName()) + ">."); throw DeadlyImportError("Not found node with name \"", pAttrValue, "\" in <", mReader->getNodeName(), ">.");
} }
/*********************************************************************************************************************************************/ /*********************************************************************************************************************************************/
@ -283,7 +283,7 @@ void X3DImporter::Throw_USE_NotFound(const std::string& pAttrValue)
void X3DImporter::XML_CheckNode_MustBeEmpty() void X3DImporter::XML_CheckNode_MustBeEmpty()
{ {
if(!mReader->isEmptyElement()) throw DeadlyImportError(std::string("Node <") + mReader->getNodeName() + "> must be empty."); if(!mReader->isEmptyElement()) throw DeadlyImportError("Node <", mReader->getNodeName(), "> must be empty.");
} }
void X3DImporter::XML_CheckNode_SkipUnsupported(const std::string& pParentNodeName) void X3DImporter::XML_CheckNode_SkipUnsupported(const std::string& pParentNodeName)
@ -395,7 +395,7 @@ void X3DImporter::XML_CheckNode_SkipUnsupported(const std::string& pParentNodeNa
casu_cres: casu_cres:
if(!found) throw DeadlyImportError("Unknown node \"" + nn + "\" in " + pParentNodeName + "."); if(!found) throw DeadlyImportError("Unknown node \"", nn, "\" in ", pParentNodeName, ".");
if(close_found) if(close_found)
LogInfo("Skipping node \"" + nn + "\" in " + pParentNodeName + "."); LogInfo("Skipping node \"" + nn + "\" in " + pParentNodeName + ".");
@ -430,7 +430,7 @@ bool X3DImporter::XML_ReadNode_GetAttrVal_AsBool(const int pAttrIdx)
else if(val == "true") else if(val == "true")
return true; return true;
else else
throw DeadlyImportError("Bool attribute value can contain \"false\" or \"true\" not the \"" + val + "\""); throw DeadlyImportError("Bool attribute value can contain \"false\" or \"true\" not the \"", val, "\"");
} }
} }
@ -971,8 +971,8 @@ void X3DImporter::MeshGeometry_AddColor(aiMesh& pMesh, const std::list<aiColor4D
{ {
if(pColors.size() < pMesh.mNumVertices) if(pColors.size() < pMesh.mNumVertices)
{ {
throw DeadlyImportError("MeshGeometry_AddColor1. Colors count(" + to_string(pColors.size()) + ") can not be less than Vertices count(" + throw DeadlyImportError("MeshGeometry_AddColor1. Colors count(", to_string(pColors.size()), ") can not be less than Vertices count(",
to_string(pMesh.mNumVertices) + ")."); to_string(pMesh.mNumVertices), ").");
} }
// copy colors to mesh // copy colors to mesh
@ -983,8 +983,8 @@ void X3DImporter::MeshGeometry_AddColor(aiMesh& pMesh, const std::list<aiColor4D
{ {
if(pColors.size() < pMesh.mNumFaces) if(pColors.size() < pMesh.mNumFaces)
{ {
throw DeadlyImportError("MeshGeometry_AddColor1. Colors count(" + to_string(pColors.size()) + ") can not be less than Faces count(" + throw DeadlyImportError("MeshGeometry_AddColor1. Colors count(", to_string(pColors.size()), ") can not be less than Faces count(",
to_string(pMesh.mNumFaces) + ")."); to_string(pMesh.mNumFaces), ").");
} }
// copy colors to mesh // copy colors to mesh
@ -1043,8 +1043,8 @@ void X3DImporter::MeshGeometry_AddColor(aiMesh& pMesh, const std::vector<int32_t
// check indices array count. // check indices array count.
if(pColorIdx.size() < pCoordIdx.size()) if(pColorIdx.size() < pCoordIdx.size())
{ {
throw DeadlyImportError("MeshGeometry_AddColor2. Colors indices count(" + to_string(pColorIdx.size()) + throw DeadlyImportError("MeshGeometry_AddColor2. Colors indices count(", to_string(pColorIdx.size()),
") can not be less than Coords inidces count(" + to_string(pCoordIdx.size()) + ")."); ") can not be less than Coords inidces count(", to_string(pCoordIdx.size()), ").");
} }
// create list with colors for every vertex. // create list with colors for every vertex.
col_tgt_arr.resize(pMesh.mNumVertices); col_tgt_arr.resize(pMesh.mNumVertices);
@ -1072,8 +1072,8 @@ void X3DImporter::MeshGeometry_AddColor(aiMesh& pMesh, const std::vector<int32_t
// check indices array count. // check indices array count.
if(pColors.size() < pMesh.mNumVertices) if(pColors.size() < pMesh.mNumVertices)
{ {
throw DeadlyImportError("MeshGeometry_AddColor2. Colors count(" + to_string(pColors.size()) + ") can not be less than Vertices count(" + throw DeadlyImportError("MeshGeometry_AddColor2. Colors count(", to_string(pColors.size()), ") can not be less than Vertices count(",
to_string(pMesh.mNumVertices) + ")."); to_string(pMesh.mNumVertices), ").");
} }
// create list with colors for every vertex. // create list with colors for every vertex.
col_tgt_arr.resize(pMesh.mNumVertices); col_tgt_arr.resize(pMesh.mNumVertices);
@ -1090,8 +1090,8 @@ void X3DImporter::MeshGeometry_AddColor(aiMesh& pMesh, const std::vector<int32_t
// check indices array count. // check indices array count.
if(pColorIdx.size() < pMesh.mNumFaces) if(pColorIdx.size() < pMesh.mNumFaces)
{ {
throw DeadlyImportError("MeshGeometry_AddColor2. Colors indices count(" + to_string(pColorIdx.size()) + throw DeadlyImportError("MeshGeometry_AddColor2. Colors indices count(", to_string(pColorIdx.size()),
") can not be less than Faces count(" + to_string(pMesh.mNumFaces) + ")."); ") can not be less than Faces count(", to_string(pMesh.mNumFaces), ").");
} }
// create list with colors for every vertex using faces indices. // create list with colors for every vertex using faces indices.
col_tgt_arr.resize(pMesh.mNumFaces); col_tgt_arr.resize(pMesh.mNumFaces);
@ -1110,8 +1110,8 @@ void X3DImporter::MeshGeometry_AddColor(aiMesh& pMesh, const std::vector<int32_t
// check indices array count. // check indices array count.
if(pColors.size() < pMesh.mNumFaces) if(pColors.size() < pMesh.mNumFaces)
{ {
throw DeadlyImportError("MeshGeometry_AddColor2. Colors count(" + to_string(pColors.size()) + ") can not be less than Faces count(" + throw DeadlyImportError("MeshGeometry_AddColor2. Colors count(", to_string(pColors.size()), ") can not be less than Faces count(",
to_string(pMesh.mNumFaces) + ")."); to_string(pMesh.mNumFaces), ").");
} }
// create list with colors for every vertex using faces indices. // create list with colors for every vertex using faces indices.
col_tgt_arr.resize(pMesh.mNumFaces); col_tgt_arr.resize(pMesh.mNumFaces);
@ -1157,8 +1157,8 @@ void X3DImporter::MeshGeometry_AddNormal(aiMesh& pMesh, const std::vector<int32_
for(size_t i = 0; (i < pMesh.mNumVertices) && (i < tind.size()); i++) for(size_t i = 0; (i < pMesh.mNumVertices) && (i < tind.size()); i++)
{ {
if(tind[i] >= norm_arr_copy.size()) if(tind[i] >= norm_arr_copy.size())
throw DeadlyImportError("MeshGeometry_AddNormal. Normal index(" + to_string(tind[i]) + throw DeadlyImportError("MeshGeometry_AddNormal. Normal index(", to_string(tind[i]),
") is out of range. Normals count: " + to_string(norm_arr_copy.size()) + "."); ") is out of range. Normals count: ", to_string(norm_arr_copy.size()), ".");
pMesh.mNormals[i] = norm_arr_copy[tind[i]]; pMesh.mNormals[i] = norm_arr_copy[tind[i]];
} }
@ -1268,7 +1268,7 @@ void X3DImporter::MeshGeometry_AddTexCoord(aiMesh& pMesh, const std::vector<int3
for(size_t fi = 0, fi_e = faces.size(); fi < fi_e; fi++) for(size_t fi = 0, fi_e = faces.size(); fi < fi_e; fi++)
{ {
if(pMesh.mFaces[fi].mNumIndices != faces.at(fi).mNumIndices) if(pMesh.mFaces[fi].mNumIndices != faces.at(fi).mNumIndices)
throw DeadlyImportError("Number of indices in texture face and mesh face must be equal. Invalid face index: " + to_string(fi) + "."); throw DeadlyImportError("Number of indices in texture face and mesh face must be equal. Invalid face index: ", to_string(fi), ".");
for(size_t ii = 0; ii < pMesh.mFaces[fi].mNumIndices; ii++) for(size_t ii = 0; ii < pMesh.mFaces[fi].mNumIndices; ii++)
{ {
@ -1419,12 +1419,12 @@ void X3DImporter::ParseFile(const std::string& pFile, IOSystem* pIOHandler)
// Check whether we can read from the file // Check whether we can read from the file
if ( file.get() == nullptr ) if ( file.get() == nullptr )
{ {
throw DeadlyImportError( "Failed to open X3D file " + pFile + "." ); throw DeadlyImportError( "Failed to open X3D file ", pFile, "." );
} }
mReader = FIReader::create(file.get()); mReader = FIReader::create(file.get());
if ( !mReader ) if ( !mReader )
{ {
throw DeadlyImportError( "Failed to create XML reader for file" + pFile + "." ); throw DeadlyImportError( "Failed to create XML reader for file", pFile, "." );
} }
mReader->registerVocabulary("urn:web3d:x3d:fi-vocabulary-3.2", &X3D_vocabulary_3_2); mReader->registerVocabulary("urn:web3d:x3d:fi-vocabulary-3.2", &X3D_vocabulary_3_2);
mReader->registerVocabulary("urn:web3d:x3d:fi-vocabulary-3.3", &X3D_vocabulary_3_3); mReader->registerVocabulary("urn:web3d:x3d:fi-vocabulary-3.3", &X3D_vocabulary_3_3);
@ -1519,7 +1519,7 @@ void X3DImporter::ParseNode_Scene()
auto GroupCounter_Increase = [](size_t& pCounter, const char* pGroupName) -> void auto GroupCounter_Increase = [](size_t& pCounter, const char* pGroupName) -> void
{ {
pCounter++; pCounter++;
if(pCounter == 0) throw DeadlyImportError("Group counter overflow. Too much groups with type: " + std::string(pGroupName) + "."); if(pCounter == 0) throw DeadlyImportError("Group counter overflow. Too much groups with type: ", pGroupName, ".");
}; };
auto GroupCounter_Decrease = [&](size_t& pCounter, const char* pGroupName) -> void auto GroupCounter_Decrease = [&](size_t& pCounter, const char* pGroupName) -> void

View File

@ -178,7 +178,7 @@ void X3DImporter::Postprocess_BuildLight(const CX3DImporter_NodeElement& pNodeEl
break; break;
default: default:
throw DeadlyImportError("Postprocess_BuildLight. Unknown type of light: " + to_string(pNodeElement.Type) + "."); throw DeadlyImportError("Postprocess_BuildLight. Unknown type of light: ", to_string(pNodeElement.Type), ".");
} }
pSceneLightList.push_back(new_light); pSceneLightList.push_back(new_light);
@ -300,7 +300,7 @@ void X3DImporter::Postprocess_BuildMesh(const CX3DImporter_NodeElement& pNodeEle
else if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_TextureCoordinate) else if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_TextureCoordinate)
MeshGeometry_AddTexCoord(**pMesh, ((CX3DImporter_NodeElement_TextureCoordinate*)*ch_it)->Value); MeshGeometry_AddTexCoord(**pMesh, ((CX3DImporter_NodeElement_TextureCoordinate*)*ch_it)->Value);
else else
throw DeadlyImportError("Postprocess_BuildMesh. Unknown child of ElevationGrid: " + to_string((*ch_it)->Type) + "."); throw DeadlyImportError("Postprocess_BuildMesh. Unknown child of ElevationGrid: ", to_string((*ch_it)->Type), ".");
}// for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ++ch_it) }// for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ++ch_it)
return;// mesh is build, nothing to do anymore. return;// mesh is build, nothing to do anymore.
@ -337,7 +337,7 @@ void X3DImporter::Postprocess_BuildMesh(const CX3DImporter_NodeElement& pNodeEle
else if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_TextureCoordinate) else if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_TextureCoordinate)
MeshGeometry_AddTexCoord(**pMesh, tnemesh.CoordIndex, tnemesh.TexCoordIndex, ((CX3DImporter_NodeElement_TextureCoordinate*)*ch_it)->Value); MeshGeometry_AddTexCoord(**pMesh, tnemesh.CoordIndex, tnemesh.TexCoordIndex, ((CX3DImporter_NodeElement_TextureCoordinate*)*ch_it)->Value);
else else
throw DeadlyImportError("Postprocess_BuildMesh. Unknown child of IndexedFaceSet: " + to_string((*ch_it)->Type) + "."); throw DeadlyImportError("Postprocess_BuildMesh. Unknown child of IndexedFaceSet: ", to_string((*ch_it)->Type), ".");
}// for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ++ch_it) }// for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ++ch_it)
return;// mesh is build, nothing to do anymore. return;// mesh is build, nothing to do anymore.
@ -368,7 +368,7 @@ void X3DImporter::Postprocess_BuildMesh(const CX3DImporter_NodeElement& pNodeEle
else if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_Coordinate) else if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_Coordinate)
{} // skip because already read when mesh created. {} // skip because already read when mesh created.
else else
throw DeadlyImportError("Postprocess_BuildMesh. Unknown child of IndexedLineSet: " + to_string((*ch_it)->Type) + "."); throw DeadlyImportError("Postprocess_BuildMesh. Unknown child of IndexedLineSet: ", to_string((*ch_it)->Type), ".");
}// for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ++ch_it) }// for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ++ch_it)
return;// mesh is build, nothing to do anymore. return;// mesh is build, nothing to do anymore.
@ -458,7 +458,7 @@ void X3DImporter::Postprocess_BuildMesh(const CX3DImporter_NodeElement& pNodeEle
else if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_Coordinate) else if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_Coordinate)
{} // skip because already read when mesh created. {} // skip because already read when mesh created.
else else
throw DeadlyImportError("Postprocess_BuildMesh. Unknown child of PointSet: " + to_string((*ch_it)->Type) + "."); throw DeadlyImportError("Postprocess_BuildMesh. Unknown child of PointSet: ", to_string((*ch_it)->Type), ".");
}// for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ++ch_it) }// for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ++ch_it)
return;// mesh is build, nothing to do anymore. return;// mesh is build, nothing to do anymore.
@ -488,7 +488,7 @@ void X3DImporter::Postprocess_BuildMesh(const CX3DImporter_NodeElement& pNodeEle
else if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_Coordinate) else if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_Coordinate)
{} // skip because already read when mesh created. {} // skip because already read when mesh created.
else else
throw DeadlyImportError("Postprocess_BuildMesh. Unknown child of LineSet: " + to_string((*ch_it)->Type) + "."); throw DeadlyImportError("Postprocess_BuildMesh. Unknown child of LineSet: ", to_string((*ch_it)->Type), ".");
}// for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ++ch_it) }// for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ++ch_it)
return;// mesh is build, nothing to do anymore. return;// mesh is build, nothing to do anymore.
@ -525,7 +525,7 @@ void X3DImporter::Postprocess_BuildMesh(const CX3DImporter_NodeElement& pNodeEle
else if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_TextureCoordinate) else if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_TextureCoordinate)
MeshGeometry_AddTexCoord(**pMesh, tnemesh.CoordIndex, tnemesh.TexCoordIndex, ((CX3DImporter_NodeElement_TextureCoordinate*)*ch_it)->Value); MeshGeometry_AddTexCoord(**pMesh, tnemesh.CoordIndex, tnemesh.TexCoordIndex, ((CX3DImporter_NodeElement_TextureCoordinate*)*ch_it)->Value);
else else
throw DeadlyImportError("Postprocess_BuildMesh. Unknown child of TrianlgeFanSet: " + to_string((*ch_it)->Type) + "."); throw DeadlyImportError("Postprocess_BuildMesh. Unknown child of TriangleFanSet: ", to_string((*ch_it)->Type), ".");
}// for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ++ch_it) }// for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ++ch_it)
return;// mesh is build, nothing to do anymore. return;// mesh is build, nothing to do anymore.
@ -569,7 +569,7 @@ void X3DImporter::Postprocess_BuildMesh(const CX3DImporter_NodeElement& pNodeEle
else if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_TextureCoordinate) else if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_TextureCoordinate)
MeshGeometry_AddTexCoord(**pMesh, tnemesh.CoordIndex, tnemesh.TexCoordIndex, ((CX3DImporter_NodeElement_TextureCoordinate*)*ch_it)->Value); MeshGeometry_AddTexCoord(**pMesh, tnemesh.CoordIndex, tnemesh.TexCoordIndex, ((CX3DImporter_NodeElement_TextureCoordinate*)*ch_it)->Value);
else else
throw DeadlyImportError("Postprocess_BuildMesh. Unknown child of TrianlgeSet: " + to_string((*ch_it)->Type) + "."); throw DeadlyImportError("Postprocess_BuildMesh. Unknown child of TrianlgeSet: ", to_string((*ch_it)->Type), ".");
}// for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ++ch_it) }// for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ++ch_it)
return;// mesh is build, nothing to do anymore. return;// mesh is build, nothing to do anymore.
@ -604,13 +604,13 @@ void X3DImporter::Postprocess_BuildMesh(const CX3DImporter_NodeElement& pNodeEle
else if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_TextureCoordinate) else if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_TextureCoordinate)
MeshGeometry_AddTexCoord(**pMesh, tnemesh.CoordIndex, tnemesh.TexCoordIndex, ((CX3DImporter_NodeElement_TextureCoordinate*)*ch_it)->Value); MeshGeometry_AddTexCoord(**pMesh, tnemesh.CoordIndex, tnemesh.TexCoordIndex, ((CX3DImporter_NodeElement_TextureCoordinate*)*ch_it)->Value);
else else
throw DeadlyImportError("Postprocess_BuildMesh. Unknown child of TriangleStripSet: " + to_string((*ch_it)->Type) + "."); throw DeadlyImportError("Postprocess_BuildMesh. Unknown child of TriangleStripSet: ", to_string((*ch_it)->Type), ".");
}// for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ++ch_it) }// for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ++ch_it)
return;// mesh is build, nothing to do anymore. return;// mesh is build, nothing to do anymore.
}// if(pNodeElement.Type == CX3DImporter_NodeElement::ENET_TriangleStripSet) }// if(pNodeElement.Type == CX3DImporter_NodeElement::ENET_TriangleStripSet)
throw DeadlyImportError("Postprocess_BuildMesh. Unknown mesh type: " + to_string(pNodeElement.Type) + "."); throw DeadlyImportError("Postprocess_BuildMesh. Unknown mesh type: ", to_string(pNodeElement.Type), ".");
} }
void X3DImporter::Postprocess_BuildNode(const CX3DImporter_NodeElement& pNodeElement, aiNode& pSceneNode, std::list<aiMesh*>& pSceneMeshList, void X3DImporter::Postprocess_BuildNode(const CX3DImporter_NodeElement& pNodeElement, aiNode& pSceneNode, std::list<aiMesh*>& pSceneMeshList,
@ -672,7 +672,7 @@ void X3DImporter::Postprocess_BuildNode(const CX3DImporter_NodeElement& pNodeEle
} }
else if(!PostprocessHelper_ElementIsMetadata((*it)->Type))// skip metadata else if(!PostprocessHelper_ElementIsMetadata((*it)->Type))// skip metadata
{ {
throw DeadlyImportError("Postprocess_BuildNode. Unknown type: " + to_string((*it)->Type) + "."); throw DeadlyImportError("Postprocess_BuildNode. Unknown type: ", to_string((*it)->Type), ".");
} }
}// for(std::list<CX3DImporter_NodeElement*>::const_iterator it = chit_begin; it != chit_end; it++) }// for(std::list<CX3DImporter_NodeElement*>::const_iterator it = chit_begin; it != chit_end; it++)

View File

@ -144,7 +144,7 @@ void XGLImporter::InternReadFile(const std::string &pFile,
// check whether we can read from the file // check whether we can read from the file
if (stream.get() == nullptr) { if (stream.get() == nullptr) {
throw DeadlyImportError("Failed to open XGL/ZGL file " + pFile + ""); throw DeadlyImportError("Failed to open XGL/ZGL file ", pFile, "");
} }
// see if its compressed, if so uncompress it // see if its compressed, if so uncompress it

View File

@ -235,15 +235,15 @@ Ref<T> LazyDict<T>::Get(const char *id) {
// read it from the JSON object // read it from the JSON object
if (!mDict) { if (!mDict) {
throw DeadlyImportError("GLTF: Missing section \"" + std::string(mDictId) + "\""); throw DeadlyImportError("GLTF: Missing section \"", mDictId, "\"");
} }
Value::MemberIterator obj = mDict->FindMember(id); Value::MemberIterator obj = mDict->FindMember(id);
if (obj == mDict->MemberEnd()) { if (obj == mDict->MemberEnd()) {
throw DeadlyImportError("GLTF: Missing object with id \"" + std::string(id) + "\" in \"" + mDictId + "\""); throw DeadlyImportError("GLTF: Missing object with id \"", id, "\" in \"", mDictId, "\"");
} }
if (!obj->value.IsObject()) { if (!obj->value.IsObject()) {
throw DeadlyImportError("GLTF: Object with id \"" + std::string(id) + "\" is not a JSON object"); throw DeadlyImportError("GLTF: Object with id \"", id, "\" is not a JSON object");
} }
// create an instance of the given type // create an instance of the given type
@ -317,13 +317,13 @@ inline void Buffer::Read(Value &obj, Asset &r) {
this->mData.reset(data, std::default_delete<uint8_t[]>()); this->mData.reset(data, std::default_delete<uint8_t[]>());
if (statedLength > 0 && this->byteLength != statedLength) { if (statedLength > 0 && this->byteLength != statedLength) {
throw DeadlyImportError("GLTF: buffer \"" + id + "\", expected " + to_string(statedLength) + throw DeadlyImportError("GLTF: buffer \"", id, "\", expected ", to_string(statedLength),
" bytes, but found " + to_string(dataURI.dataLength)); " bytes, but found ", to_string(dataURI.dataLength));
} }
} else { // assume raw data } else { // assume raw data
if (statedLength != dataURI.dataLength) { if (statedLength != dataURI.dataLength) {
throw DeadlyImportError("GLTF: buffer \"" + id + "\", expected " + to_string(statedLength) + throw DeadlyImportError("GLTF: buffer \"", id, "\", expected ", to_string(statedLength),
" bytes, but found " + to_string(dataURI.dataLength)); " bytes, but found ", to_string(dataURI.dataLength));
} }
this->mData.reset(new uint8_t[dataURI.dataLength], std::default_delete<uint8_t[]>()); this->mData.reset(new uint8_t[dataURI.dataLength], std::default_delete<uint8_t[]>());
@ -339,9 +339,9 @@ inline void Buffer::Read(Value &obj, Asset &r) {
delete file; delete file;
if (!ok) if (!ok)
throw DeadlyImportError("GLTF: error while reading referenced file \"" + std::string(uri) + "\""); throw DeadlyImportError("GLTF: error while reading referenced file \"", uri, "\"");
} else { } else {
throw DeadlyImportError("GLTF: could not open referenced file \"" + std::string(uri) + "\""); throw DeadlyImportError("GLTF: could not open referenced file \"", uri, "\"");
} }
} }
} }
@ -373,7 +373,7 @@ inline void Buffer::EncodedRegion_Mark(const size_t pOffset, const size_t pEncod
char val[val_size]; char val[val_size];
ai_snprintf(val, val_size, AI_SIZEFMT, pOffset); ai_snprintf(val, val_size, AI_SIZEFMT, pOffset);
throw DeadlyImportError(std::string("GLTF: incorrect offset value (") + val + ") for marking encoded region."); throw DeadlyImportError("GLTF: incorrect offset value (", val, ") for marking encoded region.");
} }
// Check length // Check length
@ -383,7 +383,7 @@ inline void Buffer::EncodedRegion_Mark(const size_t pOffset, const size_t pEncod
char val[val_size]; char val[val_size];
ai_snprintf(val, val_size, AI_SIZEFMT "/" AI_SIZEFMT, pOffset, pEncodedData_Length); ai_snprintf(val, val_size, AI_SIZEFMT "/" AI_SIZEFMT, pOffset, pEncodedData_Length);
throw DeadlyImportError(std::string("GLTF: encoded region with offset/length (") + val + ") is out of range."); throw DeadlyImportError("GLTF: encoded region with offset/length (", val, ") is out of range.");
} }
// Add new region // Add new region
@ -403,7 +403,7 @@ inline void Buffer::EncodedRegion_SetCurrent(const std::string &pID) {
} }
} }
throw DeadlyImportError("GLTF: EncodedRegion with ID: \"" + pID + "\" not found."); throw DeadlyImportError("GLTF: EncodedRegion with ID: \"", pID, "\" not found.");
} }
inline bool Buffer::ReplaceData(const size_t pBufferData_Offset, const size_t pBufferData_Count, const uint8_t *pReplace_Data, const size_t pReplace_Count) { inline bool Buffer::ReplaceData(const size_t pBufferData_Offset, const size_t pBufferData_Count, const uint8_t *pReplace_Data, const size_t pReplace_Count) {
@ -851,7 +851,7 @@ inline void Mesh::Read(Value &pJSON_Object, Asset &pAsset_Root) {
/************** Read data from JSON-document **************/ /************** Read data from JSON-document **************/
#define MESH_READ_COMPRESSEDDATA_MEMBER(pFieldName, pOut) \ #define MESH_READ_COMPRESSEDDATA_MEMBER(pFieldName, pOut) \
if (!ReadMember(*comp_data, pFieldName, pOut)) { \ if (!ReadMember(*comp_data, pFieldName, pOut)) { \
throw DeadlyImportError(std::string("GLTF: \"compressedData\" must has \"") + pFieldName + "\"."); \ throw DeadlyImportError("GLTF: \"compressedData\" must has \"", pFieldName, "\"."); \
} }
const char *mode_str; const char *mode_str;
@ -880,7 +880,7 @@ inline void Mesh::Read(Value &pJSON_Object, Asset &pAsset_Root) {
else if (strcmp(mode_str, "ascii") == 0) else if (strcmp(mode_str, "ascii") == 0)
ext_o3dgc->Binary = false; ext_o3dgc->Binary = false;
else else
throw DeadlyImportError(std::string("GLTF: for compressed data supported modes is: \"ascii\", \"binary\". Not the: \"") + mode_str + "\"."); throw DeadlyImportError("GLTF: for compressed data supported modes is: \"ascii\", \"binary\". Not the: \"", mode_str, "\".");
/************************ Decoding ************************/ /************************ Decoding ************************/
Decode_O3DGC(*ext_o3dgc, pAsset_Root); Decode_O3DGC(*ext_o3dgc, pAsset_Root);
@ -888,7 +888,7 @@ inline void Mesh::Read(Value &pJSON_Object, Asset &pAsset_Root) {
} // if(it_memb->name.GetString() == "Open3DGC-compression") } // if(it_memb->name.GetString() == "Open3DGC-compression")
else else
{ {
throw DeadlyImportError(std::string("GLTF: Unknown mesh extension: \"") + it_memb->name.GetString() + "\"."); throw DeadlyImportError("GLTF: Unknown mesh extension: \"", it_memb->name.GetString(), "\".");
} }
} // for(Value::MemberIterator it_memb = json_extensions->MemberBegin(); it_memb != json_extensions->MemberEnd(); json_extensions++) } // for(Value::MemberIterator it_memb = json_extensions->MemberBegin(); it_memb != json_extensions->MemberEnd(); json_extensions++)
#endif #endif
@ -923,24 +923,24 @@ inline void Mesh::Decode_O3DGC(const SCompression_Open3DGC &pCompression_Open3DG
size_t size_coordindex = ifs.GetNCoordIndex() * 3; // See float attributes note. size_t size_coordindex = ifs.GetNCoordIndex() * 3; // See float attributes note.
if (primitives[0].indices->count != size_coordindex) if (primitives[0].indices->count != size_coordindex)
throw DeadlyImportError("GLTF: Open3DGC. Compressed indices count (" + to_string(size_coordindex) + throw DeadlyImportError("GLTF: Open3DGC. Compressed indices count (", to_string(size_coordindex),
") not equal to uncompressed (" + to_string(primitives[0].indices->count) + ")."); ") not equal to uncompressed (", to_string(primitives[0].indices->count), ").");
size_coordindex *= sizeof(IndicesType); size_coordindex *= sizeof(IndicesType);
// Coordinates // Coordinates
size_t size_coord = ifs.GetNCoord(); // See float attributes note. size_t size_coord = ifs.GetNCoord(); // See float attributes note.
if (primitives[0].attributes.position[0]->count != size_coord) if (primitives[0].attributes.position[0]->count != size_coord)
throw DeadlyImportError("GLTF: Open3DGC. Compressed positions count (" + to_string(size_coord) + throw DeadlyImportError("GLTF: Open3DGC. Compressed positions count (", to_string(size_coord),
") not equal to uncompressed (" + to_string(primitives[0].attributes.position[0]->count) + ")."); ") not equal to uncompressed (", to_string(primitives[0].attributes.position[0]->count), ").");
size_coord *= 3 * sizeof(float); size_coord *= 3 * sizeof(float);
// Normals // Normals
size_t size_normal = ifs.GetNNormal(); // See float attributes note. size_t size_normal = ifs.GetNNormal(); // See float attributes note.
if (primitives[0].attributes.normal[0]->count != size_normal) if (primitives[0].attributes.normal[0]->count != size_normal)
throw DeadlyImportError("GLTF: Open3DGC. Compressed normals count (" + to_string(size_normal) + throw DeadlyImportError("GLTF: Open3DGC. Compressed normals count (", to_string(size_normal),
") not equal to uncompressed (" + to_string(primitives[0].attributes.normal[0]->count) + ")."); ") not equal to uncompressed (", to_string(primitives[0].attributes.normal[0]->count), ").");
size_normal *= 3 * sizeof(float); size_normal *= 3 * sizeof(float);
// Additional attributes. // Additional attributes.
@ -961,8 +961,8 @@ inline void Mesh::Decode_O3DGC(const SCompression_Open3DGC &pCompression_Open3DG
// Check situation when encoded data contain texture coordinates but primitive not. // Check situation when encoded data contain texture coordinates but primitive not.
if (idx_texcoord < primitives[0].attributes.texcoord.size()) { if (idx_texcoord < primitives[0].attributes.texcoord.size()) {
if (primitives[0].attributes.texcoord[idx]->count != tval) if (primitives[0].attributes.texcoord[idx]->count != tval)
throw DeadlyImportError("GLTF: Open3DGC. Compressed texture coordinates count (" + to_string(tval) + throw DeadlyImportError("GLTF: Open3DGC. Compressed texture coordinates count (", to_string(tval),
") not equal to uncompressed (" + to_string(primitives[0].attributes.texcoord[idx]->count) + ")."); ") not equal to uncompressed (", to_string(primitives[0].attributes.texcoord[idx]->count), ").");
idx_texcoord++; idx_texcoord++;
} else { } else {
@ -971,7 +971,7 @@ inline void Mesh::Decode_O3DGC(const SCompression_Open3DGC &pCompression_Open3DG
break; break;
default: default:
throw DeadlyImportError("GLTF: Open3DGC. Unsupported type of float attribute: " + to_string(ifs.GetFloatAttributeType(static_cast<unsigned long>(idx)))); throw DeadlyImportError("GLTF: Open3DGC. Unsupported type of float attribute: ", to_string(ifs.GetFloatAttributeType(static_cast<unsigned long>(idx))));
} }
tval *= ifs.GetFloatAttributeDim(static_cast<unsigned long>(idx)) * sizeof(o3dgc::Real); // After checking count of objects we can get size of array. tval *= ifs.GetFloatAttributeDim(static_cast<unsigned long>(idx)) * sizeof(o3dgc::Real); // After checking count of objects we can get size of array.
@ -990,7 +990,7 @@ inline void Mesh::Decode_O3DGC(const SCompression_Open3DGC &pCompression_Open3DG
break; break;
default: default:
throw DeadlyImportError("GLTF: Open3DGC. Unsupported type of int attribute: " + to_string(ifs.GetIntAttributeType(static_cast<unsigned long>(idx)))); throw DeadlyImportError("GLTF: Open3DGC. Unsupported type of int attribute: ", to_string(ifs.GetIntAttributeType(static_cast<unsigned long>(idx))));
} }
tval *= ifs.GetIntAttributeDim(static_cast<unsigned long>(idx)) * sizeof(long); // See float attributes note. tval *= ifs.GetIntAttributeDim(static_cast<unsigned long>(idx)) * sizeof(long); // See float attributes note.
@ -1025,7 +1025,7 @@ inline void Mesh::Decode_O3DGC(const SCompression_Open3DGC &pCompression_Open3DG
break; break;
default: default:
throw DeadlyImportError("GLTF: Open3DGC. Unsupported type of float attribute: " + to_string(ifs.GetFloatAttributeType(static_cast<unsigned long>(idx)))); throw DeadlyImportError("GLTF: Open3DGC. Unsupported type of float attribute: ", to_string(ifs.GetFloatAttributeType(static_cast<unsigned long>(idx))));
} }
} }
@ -1039,7 +1039,7 @@ inline void Mesh::Decode_O3DGC(const SCompression_Open3DGC &pCompression_Open3DG
// ifs.SetIntAttribute(idx, (long* const)(decoded_data + get_buf_offset(primitives[0].attributes.joint))); // ifs.SetIntAttribute(idx, (long* const)(decoded_data + get_buf_offset(primitives[0].attributes.joint)));
default: default:
throw DeadlyImportError("GLTF: Open3DGC. Unsupported type of int attribute: " + to_string(ifs.GetIntAttributeType(static_cast<unsigned long>(idx)))); throw DeadlyImportError("GLTF: Open3DGC. Unsupported type of int attribute: ", to_string(ifs.GetIntAttributeType(static_cast<unsigned long>(idx))));
} }
} }
@ -1231,7 +1231,7 @@ inline void AssetMetadata::Read(Document &doc) {
} }
if (version.empty() || version[0] != '1') { if (version.empty() || version[0] != '1') {
throw DeadlyImportError("GLTF: Unsupported glTF version: " + version); throw DeadlyImportError("GLTF: Unsupported glTF version: ", version);
} }
} }
@ -1309,7 +1309,7 @@ inline void Asset::Load(const std::string &pFile, bool isBinary) {
if (doc.HasParseError()) { if (doc.HasParseError()) {
char buffer[32]; char buffer[32];
ai_snprintf(buffer, 32, "%d", static_cast<int>(doc.GetErrorOffset())); ai_snprintf(buffer, 32, "%d", static_cast<int>(doc.GetErrorOffset()));
throw DeadlyImportError(std::string("GLTF: JSON parse error, offset ") + buffer + ": " + GetParseError_En(doc.GetParseError())); throw DeadlyImportError("GLTF: JSON parse error, offset ", buffer, ": ", GetParseError_En(doc.GetParseError()));
} }
if (!doc.IsObject()) { if (!doc.IsObject()) {

View File

@ -234,7 +234,7 @@ void glTFImporter::ImportMeshes(glTF::Asset &r) {
buf->EncodedRegion_SetCurrent(mesh.id); buf->EncodedRegion_SetCurrent(mesh.id);
} else } else
{ {
throw DeadlyImportError("GLTF: Can not import mesh: unknown mesh extension (code: \"" + to_string(cur_ext->Type) + throw DeadlyImportError("GLTF: Can not import mesh: unknown mesh extension (code: \"", to_string(cur_ext->Type),
"\"), only Open3DGC is supported."); "\"), only Open3DGC is supported.");
} }
} }

View File

@ -202,7 +202,7 @@ inline unsigned int ComponentTypeSize(ComponentType t) {
case ComponentType_UNSIGNED_BYTE: case ComponentType_UNSIGNED_BYTE:
return 1; return 1;
default: default:
throw DeadlyImportError("GLTF: Unsupported Component Type " + to_string(t)); throw DeadlyImportError("GLTF: Unsupported Component Type ", to_string(t));
} }
} }

View File

@ -269,21 +269,21 @@ Ref<T> LazyDict<T>::Retrieve(unsigned int i) {
// read it from the JSON object // read it from the JSON object
if (!mDict) { if (!mDict) {
throw DeadlyImportError("GLTF: Missing section \"" + std::string(mDictId) + "\""); throw DeadlyImportError("GLTF: Missing section \"", mDictId, "\"");
} }
if (!mDict->IsArray()) { if (!mDict->IsArray()) {
throw DeadlyImportError("GLTF: Field is not an array \"" + std::string(mDictId) + "\""); throw DeadlyImportError("GLTF: Field is not an array \"", mDictId, "\"");
} }
Value &obj = (*mDict)[i]; Value &obj = (*mDict)[i];
if (!obj.IsObject()) { if (!obj.IsObject()) {
throw DeadlyImportError("GLTF: Object at index \"" + to_string(i) + "\" is not a JSON object"); throw DeadlyImportError("GLTF: Object at index \"", to_string(i), "\" is not a JSON object");
} }
if (mRecursiveReferenceCheck.find(i) != mRecursiveReferenceCheck.end()) { if (mRecursiveReferenceCheck.find(i) != mRecursiveReferenceCheck.end()) {
throw DeadlyImportError("GLTF: Object at index \"" + to_string(i) + "\" has recursive reference to itself"); throw DeadlyImportError("GLTF: Object at index \"", to_string(i), "\" has recursive reference to itself");
} }
mRecursiveReferenceCheck.insert(i); mRecursiveReferenceCheck.insert(i);
@ -381,13 +381,13 @@ inline void Buffer::Read(Value &obj, Asset &r) {
this->mData.reset(data, std::default_delete<uint8_t[]>()); this->mData.reset(data, std::default_delete<uint8_t[]>());
if (statedLength > 0 && this->byteLength != statedLength) { if (statedLength > 0 && this->byteLength != statedLength) {
throw DeadlyImportError("GLTF: buffer \"" + id + "\", expected " + to_string(statedLength) + throw DeadlyImportError("GLTF: buffer \"", id, "\", expected ", to_string(statedLength),
" bytes, but found " + to_string(dataURI.dataLength)); " bytes, but found ", to_string(dataURI.dataLength));
} }
} else { // assume raw data } else { // assume raw data
if (statedLength != dataURI.dataLength) { if (statedLength != dataURI.dataLength) {
throw DeadlyImportError("GLTF: buffer \"" + id + "\", expected " + to_string(statedLength) + throw DeadlyImportError("GLTF: buffer \"", id, "\", expected ", to_string(statedLength),
" bytes, but found " + to_string(dataURI.dataLength)); " bytes, but found ", to_string(dataURI.dataLength));
} }
this->mData.reset(new uint8_t[dataURI.dataLength], std::default_delete<uint8_t[]>()); this->mData.reset(new uint8_t[dataURI.dataLength], std::default_delete<uint8_t[]>());
@ -403,9 +403,9 @@ inline void Buffer::Read(Value &obj, Asset &r) {
delete file; delete file;
if (!ok) if (!ok)
throw DeadlyImportError("GLTF: error while reading referenced file \"" + std::string(uri) + "\""); throw DeadlyImportError("GLTF: error while reading referenced file \"", uri, "\"");
} else { } else {
throw DeadlyImportError("GLTF: could not open referenced file \"" + std::string(uri) + "\""); throw DeadlyImportError("GLTF: could not open referenced file \"", uri, "\"");
} }
} }
} }
@ -437,7 +437,7 @@ inline void Buffer::EncodedRegion_Mark(const size_t pOffset, const size_t pEncod
char val[val_size]; char val[val_size];
ai_snprintf(val, val_size, AI_SIZEFMT, pOffset); ai_snprintf(val, val_size, AI_SIZEFMT, pOffset);
throw DeadlyImportError(std::string("GLTF: incorrect offset value (") + val + ") for marking encoded region."); throw DeadlyImportError("GLTF: incorrect offset value (", val, ") for marking encoded region.");
} }
// Check length // Check length
@ -447,7 +447,7 @@ inline void Buffer::EncodedRegion_Mark(const size_t pOffset, const size_t pEncod
char val[val_size]; char val[val_size];
ai_snprintf(val, val_size, AI_SIZEFMT "/" AI_SIZEFMT, pOffset, pEncodedData_Length); ai_snprintf(val, val_size, AI_SIZEFMT "/" AI_SIZEFMT, pOffset, pEncodedData_Length);
throw DeadlyImportError(std::string("GLTF: encoded region with offset/length (") + val + ") is out of range."); throw DeadlyImportError("GLTF: encoded region with offset/length (", val, ") is out of range.");
} }
// Add new region // Add new region
@ -467,7 +467,7 @@ inline void Buffer::EncodedRegion_SetCurrent(const std::string &pID) {
} }
} }
throw DeadlyImportError("GLTF: EncodedRegion with ID: \"" + pID + "\" not found."); throw DeadlyImportError("GLTF: EncodedRegion with ID: \"", pID, "\" not found.");
} }
inline bool Buffer::ReplaceData(const size_t pBufferData_Offset, const size_t pBufferData_Count, const uint8_t *pReplace_Data, const size_t pReplace_Count) { inline bool Buffer::ReplaceData(const size_t pBufferData_Offset, const size_t pBufferData_Count, const uint8_t *pReplace_Data, const size_t pReplace_Count) {
@ -1458,7 +1458,7 @@ inline void AssetMetadata::Read(Document &doc) {
} }
if (version.empty() || version[0] != '2') { if (version.empty() || version[0] != '2') {
throw DeadlyImportError("GLTF: Unsupported glTF version: " + version); throw DeadlyImportError("GLTF: Unsupported glTF version: ", version);
} }
} }
@ -1570,7 +1570,7 @@ inline void Asset::Load(const std::string &pFile, bool isBinary) {
if (doc.HasParseError()) { if (doc.HasParseError()) {
char buffer[32]; char buffer[32];
ai_snprintf(buffer, 32, "%d", static_cast<int>(doc.GetErrorOffset())); ai_snprintf(buffer, 32, "%d", static_cast<int>(doc.GetErrorOffset()));
throw DeadlyImportError(std::string("GLTF: JSON parse error, offset ") + buffer + ": " + GetParseError_En(doc.GetParseError())); throw DeadlyImportError("GLTF: JSON parse error, offset ", buffer, ": ", GetParseError_En(doc.GetParseError()));
} }
if (!doc.IsObject()) { if (!doc.IsObject()) {

View File

@ -668,7 +668,7 @@ void glTF2Importer::ImportMeshes(glTF2::Asset &r) {
} }
if (actualNumFaces == 0) if (actualNumFaces == 0)
{ {
throw DeadlyImportError(std::string("Mesh \"") + aim->mName.C_Str() + "\" has no faces"); throw DeadlyImportError("Mesh \"", aim->mName.C_Str(), "\" has no faces");
} }
aim->mNumFaces = actualNumFaces; aim->mNumFaces = actualNumFaces;
ai_assert(CheckValidFacesIndices(faces, actualNumFaces, aim->mNumVertices)); ai_assert(CheckValidFacesIndices(faces, actualNumFaces, aim->mNumVertices));

View File

@ -200,6 +200,7 @@ SET( Common_SRCS
Common/simd.cpp Common/simd.cpp
Common/material.cpp Common/material.cpp
Common/AssertHandler.cpp Common/AssertHandler.cpp
Common/Exceptional.cpp
) )
SOURCE_GROUP(Common FILES ${Common_SRCS}) SOURCE_GROUP(Common FILES ${Common_SRCS})

View File

@ -133,7 +133,8 @@ aiScene *BaseImporter::ReadFile(Importer *pImp, const std::string &pFile, IOSyst
} catch( const std::exception &err ) { } catch( const std::exception &err ) {
// extract error description // extract error description
m_ErrorText = err.what(); m_ErrorText = err.what();
ASSIMP_LOG_ERROR(m_ErrorText); ASSIMP_LOG_ERROR(err.what());
m_Exception = std::current_exception();
return nullptr; return nullptr;
} }

View File

@ -0,0 +1,52 @@
/*
---------------------------------------------------------------------------
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
Copyright (c) 2006-2020, assimp team
All rights reserved.
Redistribution and use of this software in source and binary forms,
with or without modification, are permitted provided that the following
conditions are met:
* Redistributions of source code must retain the above
copyright notice, this list of conditions and the
following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the
following disclaimer in the documentation and/or other
materials provided with the distribution.
* Neither the name of the assimp team, nor the names of its
contributors may be used to endorse or promote products
derived from this software without specific prior
written permission of the assimp team.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---------------------------------------------------------------------------
*/
/** @file Exceptional.cpp
Implementations of the exception classes.
*/
#include <assimp/Exceptional.h>
#include <assimp/TinyFormatter.h>
DeadlyErrorBase::DeadlyErrorBase(Assimp::Formatter::format f) :
runtime_error(std::string(f)){}

View File

@ -387,6 +387,7 @@ void Importer::FreeScene( ) {
pimpl->mScene = nullptr; pimpl->mScene = nullptr;
pimpl->mErrorString = ""; pimpl->mErrorString = "";
pimpl->mException = std::exception_ptr();
ASSIMP_END_EXCEPTION_REGION(void); ASSIMP_END_EXCEPTION_REGION(void);
} }
@ -399,6 +400,13 @@ const char* Importer::GetErrorString() const {
return pimpl->mErrorString.c_str(); return pimpl->mErrorString.c_str();
} }
const std::exception_ptr& Importer::GetException() const {
ai_assert(nullptr != pimpl);
// Must remain valid as long as ReadFile() or FreeFile() are not called
return pimpl->mException;
}
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Enable extra-verbose mode // Enable extra-verbose mode
void Importer::SetExtraVerbose(bool bDo) { void Importer::SetExtraVerbose(bool bDo) {
@ -426,6 +434,7 @@ aiScene* Importer::GetOrphanedScene() {
pimpl->mScene = nullptr; pimpl->mScene = nullptr;
pimpl->mErrorString = ""; // reset error string pimpl->mErrorString = ""; // reset error string
pimpl->mException = std::exception_ptr();
ASSIMP_END_EXCEPTION_REGION(aiScene*); ASSIMP_END_EXCEPTION_REGION(aiScene*);
return s; return s;
@ -502,7 +511,7 @@ const aiScene* Importer::ReadFileFromMemory( const void* pBuffer,
ReadFile(fbuff,pFlags); ReadFile(fbuff,pFlags);
SetIOHandler(io); SetIOHandler(io);
ASSIMP_END_EXCEPTION_REGION_WITH_ERROR_STRING(const aiScene*, pimpl->mErrorString); ASSIMP_END_EXCEPTION_REGION_WITH_ERROR_STRING(const aiScene*, pimpl->mErrorString, pimpl->mException);
return pimpl->mScene; return pimpl->mScene;
} }
@ -709,6 +718,7 @@ const aiScene* Importer::ReadFile( const char* _pFile, unsigned int pFlags) {
// if failed, extract the error string // if failed, extract the error string
else if( !pimpl->mScene) { else if( !pimpl->mScene) {
pimpl->mErrorString = imp->GetErrorText(); pimpl->mErrorString = imp->GetErrorText();
pimpl->mException = imp->GetException();
} }
// clear any data allocated by post-process steps // clear any data allocated by post-process steps
@ -733,7 +743,7 @@ const aiScene* Importer::ReadFile( const char* _pFile, unsigned int pFlags) {
#endif // ! ASSIMP_CATCH_GLOBAL_EXCEPTIONS #endif // ! ASSIMP_CATCH_GLOBAL_EXCEPTIONS
// either successful or failure - the pointer expresses it anyways // either successful or failure - the pointer expresses it anyways
ASSIMP_END_EXCEPTION_REGION_WITH_ERROR_STRING(const aiScene*, pimpl->mErrorString); ASSIMP_END_EXCEPTION_REGION_WITH_ERROR_STRING(const aiScene*, pimpl->mErrorString, pimpl->mException);
return pimpl->mScene; return pimpl->mScene;
} }

View File

@ -4,7 +4,6 @@ Open Asset Import Library (assimp)
Copyright (c) 2006-2020, assimp team Copyright (c) 2006-2020, assimp team
All rights reserved. All rights reserved.
Redistribution and use of this software in source and binary forms, Redistribution and use of this software in source and binary forms,
@ -97,9 +96,13 @@ public:
/** The imported data, if ReadFile() was successful, nullptr otherwise. */ /** The imported data, if ReadFile() was successful, nullptr otherwise. */
aiScene* mScene; aiScene* mScene;
/** The error description, if there was one. */ /** The error description, if there was one. In the case of an exception,
* mException will carry the full details. */
std::string mErrorString; std::string mErrorString;
/** Any exception which occurred */
std::exception_ptr mException;
/** List of integer properties */ /** List of integer properties */
IntPropertyMap mIntProperties; IntPropertyMap mIntProperties;
@ -124,26 +127,26 @@ public:
}; };
inline inline
ImporterPimpl::ImporterPimpl() AI_NO_EXCEPT ImporterPimpl::ImporterPimpl() AI_NO_EXCEPT :
: mIOHandler( nullptr ) mIOHandler( nullptr ),
, mIsDefaultHandler( false ) mIsDefaultHandler( false ),
, mProgressHandler( nullptr ) mProgressHandler( nullptr ),
, mIsDefaultProgressHandler( false ) mIsDefaultProgressHandler( false ),
, mImporter() mImporter(),
, mPostProcessingSteps() mPostProcessingSteps(),
, mScene( nullptr ) mScene( nullptr ),
, mErrorString() mErrorString(),
, mIntProperties() mException(),
, mFloatProperties() mIntProperties(),
, mStringProperties() mFloatProperties(),
, mMatrixProperties() mStringProperties(),
, bExtraVerbose( false ) mMatrixProperties(),
, mPPShared( nullptr ) { bExtraVerbose( false ),
mPPShared( nullptr ) {
// empty // empty
} }
//! @endcond //! @endcond
struct BatchData; struct BatchData;
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
@ -154,17 +157,13 @@ struct BatchData;
* could, this has not yet been implemented at the moment). * could, this has not yet been implemented at the moment).
* *
* @note The class may not be used by more than one thread*/ * @note The class may not be used by more than one thread*/
class ASSIMP_API BatchLoader class ASSIMP_API BatchLoader {
{
// friend of Importer
public: public:
//! @cond never //! @cond never
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Wraps a full list of configuration properties for an importer. /** Wraps a full list of configuration properties for an importer.
* Properties can be set using SetGenericProperty */ * Properties can be set using SetGenericProperty */
struct PropertyMap struct PropertyMap {
{
ImporterPimpl::IntPropertyMap ints; ImporterPimpl::IntPropertyMap ints;
ImporterPimpl::FloatPropertyMap floats; ImporterPimpl::FloatPropertyMap floats;
ImporterPimpl::StringPropertyMap strings; ImporterPimpl::StringPropertyMap strings;
@ -181,7 +180,6 @@ public:
}; };
//! @endcond //! @endcond
public:
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Construct a batch loader from a given IO system to be used /** Construct a batch loader from a given IO system to be used
* to access external files * to access external files

View File

@ -85,7 +85,7 @@ AI_WONT_RETURN void ValidateDSProcess::ReportError(const char *msg, ...) {
va_end(args); va_end(args);
throw DeadlyImportError("Validation failed: " + std::string(szBuffer, iLen)); throw DeadlyImportError("Validation failed: ", std::string(szBuffer, iLen));
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void ValidateDSProcess::ReportWarning(const char *msg, ...) { void ValidateDSProcess::ReportWarning(const char *msg, ...) {

View File

@ -1626,7 +1626,7 @@ void xxxxImporter::InternReadFile( const std::string& pFile,
// Check whether we can read from the file // Check whether we can read from the file
if( file.get() == NULL) { if( file.get() == NULL) {
throw DeadlyImportError( "Failed to open xxxx file " + pFile + "."); throw DeadlyImportError( "Failed to open xxxx file ", pFile, ".");
} }
// Your task: fill pScene // Your task: fill pScene

View File

@ -143,6 +143,8 @@ public:
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Returns the error description of the last error that occurred. /** Returns the error description of the last error that occurred.
* If the error is due to a std::exception, this will return the message.
* Exceptions can also be accessed with GetException().
* @return A description of the last error that occurred. An empty * @return A description of the last error that occurred. An empty
* string if there was no error. * string if there was no error.
*/ */
@ -150,6 +152,16 @@ public:
return m_ErrorText; return m_ErrorText;
} }
// -------------------------------------------------------------------
/** Returns the exception of the last exception that occurred.
* Note: Exceptions are not the only source of error details, so GetErrorText
* should be consulted too.
* @return The last exception that occurred.
*/
const std::exception_ptr& GetException() const {
return m_Exception;
}
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Called prior to ReadFile(). /** Called prior to ReadFile().
* The function is a request to the importer to update its configuration * The function is a request to the importer to update its configuration
@ -413,6 +425,8 @@ private:
protected: protected:
/// Error description in case there was one. /// Error description in case there was one.
std::string m_ErrorText; std::string m_ErrorText;
/// The exception, in case there was one.
std::exception_ptr m_Exception;
/// Currently set progress handler. /// Currently set progress handler.
ProgressHandler *m_progress; ProgressHandler *m_progress;
}; };

View File

@ -47,6 +47,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#endif #endif
#include <assimp/DefaultIOStream.h> #include <assimp/DefaultIOStream.h>
#include <assimp/TinyFormatter.h>
#include <stdexcept> #include <stdexcept>
using std::runtime_error; using std::runtime_error;
@ -55,26 +56,33 @@ using std::runtime_error;
#pragma warning(disable : 4275) #pragma warning(disable : 4275)
#endif #endif
class ASSIMP_API DeadlyErrorBase : public runtime_error {
protected:
DeadlyErrorBase(Assimp::Formatter::format f);
template<typename... T, typename U>
DeadlyErrorBase(Assimp::Formatter::format f, U&& u, T&&... args) :
DeadlyErrorBase(std::move(f << std::forward<U>(u)), std::forward<T>(args)...) {}
};
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
/** FOR IMPORTER PLUGINS ONLY: Simple exception class to be thrown if an /** FOR IMPORTER PLUGINS ONLY: Simple exception class to be thrown if an
* unrecoverable error occurs while importing. Loading APIs return * unrecoverable error occurs while importing. Loading APIs return
* nullptr instead of a valid aiScene then. */ * nullptr instead of a valid aiScene then. */
class DeadlyImportError : public runtime_error { class ASSIMP_API DeadlyImportError : public DeadlyErrorBase {
public: public:
/** Constructor with arguments */ /** Constructor with arguments */
explicit DeadlyImportError(const std::string &errorText) : template<typename... T>
runtime_error(errorText) { explicit DeadlyImportError(T&&... args) :
// empty DeadlyErrorBase(Assimp::Formatter::format(), std::forward<T>(args)...) {}
}
}; };
class DeadlyExportError : public runtime_error { class ASSIMP_API DeadlyExportError : public DeadlyErrorBase {
public: public:
/** Constructor with arguments */ /** Constructor with arguments */
explicit DeadlyExportError(const std::string &errorText) : template<typename... T>
runtime_error(errorText) { explicit DeadlyExportError(T&&... args) :
// empty DeadlyErrorBase(Assimp::Formatter::format(), std::forward<T>(args)...) {}
}
}; };
#ifdef _MSC_VER #ifdef _MSC_VER
@ -123,14 +131,16 @@ struct ExceptionSwallower<void> {
{ \ { \
try { try {
#define ASSIMP_END_EXCEPTION_REGION_WITH_ERROR_STRING(type, ASSIMP_END_EXCEPTION_REGION_errorString) \ #define ASSIMP_END_EXCEPTION_REGION_WITH_ERROR_STRING(type, ASSIMP_END_EXCEPTION_REGION_errorString, ASSIMP_END_EXCEPTION_REGION_exception) \
} \ } \
catch (const DeadlyImportError &e) { \ catch (const DeadlyImportError &e) { \
ASSIMP_END_EXCEPTION_REGION_errorString = e.what(); \ ASSIMP_END_EXCEPTION_REGION_errorString = e.what(); \
ASSIMP_END_EXCEPTION_REGION_exception = std::current_exception(); \
return ExceptionSwallower<type>()(); \ return ExceptionSwallower<type>()(); \
} \ } \
catch (...) { \ catch (...) { \
ASSIMP_END_EXCEPTION_REGION_errorString = "Unknown exception"; \ ASSIMP_END_EXCEPTION_REGION_errorString = "Unknown exception"; \
ASSIMP_END_EXCEPTION_REGION_exception = std::current_exception(); \
return ExceptionSwallower<type>()(); \ return ExceptionSwallower<type>()(); \
} \ } \
} }

View File

@ -495,6 +495,15 @@ public:
* following methods is called: #ReadFile(), #FreeScene(). */ * following methods is called: #ReadFile(), #FreeScene(). */
const char *GetErrorString() const; const char *GetErrorString() const;
// -------------------------------------------------------------------
/** Returns an exception if one occurred during import.
*
* @return The last exception which occurred.
*
* @note The returned value remains valid until one of the
* following methods is called: #ReadFile(), #FreeScene(). */
const std::exception_ptr& GetException() const;
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Returns the scene loaded by the last successful call to ReadFile() /** Returns the scene loaded by the last successful call to ReadFile()
* *

View File

@ -61,9 +61,10 @@ template<class TDeriving>
class LogFunctions { class LogFunctions {
public: public:
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
static void ThrowException(const std::string& msg) template<typename... T>
static void ThrowException(T&&... args)
{ {
throw DeadlyImportError(Prefix()+msg); throw DeadlyImportError(Prefix(), args...);
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------

View File

@ -88,6 +88,9 @@ public:
underlying << sin; underlying << sin;
} }
basic_formatter(basic_formatter&& other)
: underlying(std::move(other.underlying)) {
}
// The problem described here: // The problem described here:
// https://sourceforge.net/tracker/?func=detail&atid=1067632&aid=3358562&group_id=226462 // https://sourceforge.net/tracker/?func=detail&atid=1067632&aid=3358562&group_id=226462

View File

@ -64,7 +64,7 @@ namespace Assimp {
* // open the file * // open the file
* std::unique_ptr<IOStream> file( pIOHandler->Open( pFile)); * std::unique_ptr<IOStream> file( pIOHandler->Open( pFile));
* if( file.get() == nullptr ) { * if( file.get() == nullptr ) {
* throw DeadlyImportError( "Failed to open file " + pFile + "."); * throw DeadlyImportError( "Failed to open file ", pFile, ".");
* } * }
* *
* // generate a XML reader for it * // generate a XML reader for it

View File

@ -279,3 +279,105 @@ TEST_F(ImporterTest, SearchFileHeaderForTokenTest) {
//DefaultIOSystem ioSystem; //DefaultIOSystem ioSystem;
// BaseImporter::SearchFileHeaderForToken( &ioSystem, assetPath, Token, 2 ) // BaseImporter::SearchFileHeaderForToken( &ioSystem, assetPath, Token, 2 )
} }
namespace
{
// Description for an importer which fails in specific ways.
aiImporterDesc s_failingImporterDescription = {
"Failing importer",
"assimp team",
"",
"",
0,
1,
0,
1,
0,
"fail"
};
// This importer fails in specific ways.
class FailingImporter : public Assimp::BaseImporter {
public:
virtual ~FailingImporter() = default;
virtual bool CanRead( const std::string&, Assimp::IOSystem*, bool ) const override
{
return true;
}
protected:
virtual const aiImporterDesc* GetInfo() const override { return &s_failingImporterDescription; }
virtual void InternReadFile( const std::string& pFile, aiScene*, Assimp::IOSystem* ) override
{
if (pFile == "deadlyImportError.fail")
{
throw DeadlyImportError("Deadly import error test. Details: ", 42, " More Details: ", "Failure");
}
else if (pFile == "stdException.fail")
{
throw std::runtime_error("std::exception test");
}
else if (pFile == "unexpectedException.fail")
{
throw 5;
}
}
};
}
TEST_F(ImporterTest, deadlyImportError)
{
pImp->RegisterLoader(new FailingImporter);
pImp->SetIOHandler(new TestIOSystem);
const aiScene* scene = pImp->ReadFile("deadlyImportError.fail", 0);
EXPECT_EQ(scene, nullptr);
EXPECT_STREQ(pImp->GetErrorString(), "Deadly import error test. Details: 42 More Details: Failure");
EXPECT_NE(pImp->GetException(), std::exception_ptr());
}
TEST_F(ImporterTest, stdException)
{
pImp->RegisterLoader(new FailingImporter);
pImp->SetIOHandler(new TestIOSystem);
const aiScene* scene = pImp->ReadFile("stdException.fail", 0);
EXPECT_EQ(scene, nullptr);
EXPECT_STREQ(pImp->GetErrorString(), "std::exception test");
EXPECT_NE(pImp->GetException(), std::exception_ptr());
try
{
std::rethrow_exception(pImp->GetException());
}
catch(const std::exception& e)
{
EXPECT_STREQ(e.what(), "std::exception test");
}
catch(...)
{
EXPECT_TRUE(false);
}
}
TEST_F(ImporterTest, unexpectedException)
{
pImp->RegisterLoader(new FailingImporter);
pImp->SetIOHandler(new TestIOSystem);
const aiScene* scene = pImp->ReadFile("unexpectedException.fail", 0);
EXPECT_EQ(scene, nullptr);
EXPECT_STREQ(pImp->GetErrorString(), "Unknown exception");
ASSERT_NE(pImp->GetException(), std::exception_ptr());
try
{
std::rethrow_exception(pImp->GetException());
}
catch(int x)
{
EXPECT_EQ(x, 5);
}
catch(...)
{
EXPECT_TRUE(false);
}
}