* Improved error messages
* Throw instead of asserts on invalid file inputpull/3514/head
parent
9ae112309f
commit
6ed1488e6e
|
@ -49,7 +49,9 @@ using namespace glTFCommon::Util;
|
||||||
namespace Util {
|
namespace Util {
|
||||||
|
|
||||||
size_t DecodeBase64(const char *in, size_t inLength, uint8_t *&out) {
|
size_t DecodeBase64(const char *in, size_t inLength, uint8_t *&out) {
|
||||||
ai_assert(inLength % 4 == 0);
|
if (inLength % 4 != 0) {
|
||||||
|
throw DeadlyImportError("Invalid base64 encoded data: \"", std::string(in, std::min(size_t(32), inLength)), "\", length:", inLength);
|
||||||
|
}
|
||||||
|
|
||||||
if (inLength < 4) {
|
if (inLength < 4) {
|
||||||
out = 0;
|
out = 0;
|
||||||
|
|
|
@ -249,7 +249,10 @@ inline char EncodeCharBase64(uint8_t b) {
|
||||||
}
|
}
|
||||||
|
|
||||||
inline uint8_t DecodeCharBase64(char c) {
|
inline uint8_t DecodeCharBase64(char c) {
|
||||||
return DATA<true>::tableDecodeBase64[size_t(c)]; // TODO faster with lookup table or ifs?
|
if (c & 0xF0) {
|
||||||
|
throw DeadlyImportError("Invalid base64 char value: ", size_t(c));
|
||||||
|
}
|
||||||
|
return DATA<true>::tableDecodeBase64[size_t(c & 0x0F)]; // TODO faster with lookup table or ifs?
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t DecodeBase64(const char *in, size_t inLength, uint8_t *&out);
|
size_t DecodeBase64(const char *in, size_t inLength, uint8_t *&out);
|
||||||
|
|
|
@ -1124,6 +1124,14 @@ private:
|
||||||
IOStream *OpenFile(std::string path, const char *mode, bool absolute = false);
|
IOStream *OpenFile(std::string path, const char *mode, bool absolute = false);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
inline std::string getContextForErrorMessages(const std::string &id, const std::string &name) {
|
||||||
|
std::string context = id;
|
||||||
|
if (!name.empty()) {
|
||||||
|
context += " (\"" + name + "\")";
|
||||||
|
}
|
||||||
|
return context;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace glTF2
|
} // namespace glTF2
|
||||||
|
|
||||||
// Include the implementation of the methods
|
// Include the implementation of the methods
|
||||||
|
|
|
@ -273,17 +273,21 @@ Ref<T> LazyDict<T>::Retrieve(unsigned int i) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!mDict->IsArray()) {
|
if (!mDict->IsArray()) {
|
||||||
throw DeadlyImportError("GLTF: Field is not an array \"", mDictId, "\"");
|
throw DeadlyImportError("GLTF: Field \"", mDictId, "\" is not an array");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i >= mDict->Size()) {
|
||||||
|
throw DeadlyImportError("GLTF: Array index ", i, " is out of bounds (", mDict->Size(), ") for \"", 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);
|
||||||
|
|
||||||
|
@ -741,14 +745,6 @@ inline void CopyData(size_t count,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline std::string getContextForErrorMessages(const std::string& id, const std::string& name) {
|
|
||||||
std::string context = id;
|
|
||||||
if (!name.empty()) {
|
|
||||||
context += " (\"" + name + "\")";
|
|
||||||
}
|
|
||||||
return context;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
|
@ -766,11 +762,11 @@ void Accessor::ExtractData(T *&outData) {
|
||||||
const size_t targetElemSize = sizeof(T);
|
const size_t targetElemSize = sizeof(T);
|
||||||
|
|
||||||
if (elemSize > targetElemSize) {
|
if (elemSize > targetElemSize) {
|
||||||
throw DeadlyImportError("GLTF: elemSize > targetElemSize");
|
throw DeadlyImportError("GLTF: elemSize ", elemSize, " > targetElemSize ", targetElemSize, " in ", getContextForErrorMessages(id, name));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (count*stride > (bufferView ? bufferView->byteLength : sparse->data.size())) {
|
if (count*stride > (bufferView ? bufferView->byteLength : sparse->data.size())) {
|
||||||
throw DeadlyImportError("GLTF: count*stride out of range");
|
throw DeadlyImportError("GLTF: count*stride ", (count * stride), " > bufferView->byteLength ", bufferView->byteLength, " in ", getContextForErrorMessages(id, name));
|
||||||
}
|
}
|
||||||
|
|
||||||
outData = new T[count];
|
outData = new T[count];
|
||||||
|
|
|
@ -918,7 +918,10 @@ aiNode *ImportNode(aiScene *pScene, glTF2::Asset &r, std::vector<unsigned int> &
|
||||||
|
|
||||||
if (!node.meshes.empty()) {
|
if (!node.meshes.empty()) {
|
||||||
// GLTF files contain at most 1 mesh per node.
|
// GLTF files contain at most 1 mesh per node.
|
||||||
assert(node.meshes.size() == 1);
|
if (node.meshes.size() > 1)
|
||||||
|
{
|
||||||
|
throw DeadlyImportError("GLTF: Invalid input, found ", node.meshes.size(), " meshes in ", getContextForErrorMessages(node.id, node.name), ", but only 1 mesh per node allowed.");
|
||||||
|
}
|
||||||
int mesh_idx = node.meshes[0].GetIndex();
|
int mesh_idx = node.meshes[0].GetIndex();
|
||||||
int count = meshOffsets[mesh_idx + 1] - meshOffsets[mesh_idx];
|
int count = meshOffsets[mesh_idx + 1] - meshOffsets[mesh_idx];
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue