Fix a memory leak
parent
038ae8c028
commit
9063216893
|
@ -74,6 +74,8 @@ namespace XmlTag {
|
||||||
const char* const pid = "pid";
|
const char* const pid = "pid";
|
||||||
const char* const pindex = "pindex";
|
const char* const pindex = "pindex";
|
||||||
const char* const p1 = "p1";
|
const char* const p1 = "p1";
|
||||||
|
const char *const p2 = "p2";
|
||||||
|
const char *const p3 = "p3";
|
||||||
const char* const name = "name";
|
const char* const name = "name";
|
||||||
const char* const type = "type";
|
const char* const type = "type";
|
||||||
const char* const build = "build";
|
const char* const build = "build";
|
||||||
|
|
|
@ -64,7 +64,7 @@ bool validateColorString(const char *color) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
aiFace ReadTriangle(XmlNode &node) {
|
aiFace ReadTriangle(XmlNode &node, unsigned int &texId0, unsigned int &texId1, unsigned int &texId2) {
|
||||||
aiFace face;
|
aiFace face;
|
||||||
|
|
||||||
face.mNumIndices = 3;
|
face.mNumIndices = 3;
|
||||||
|
@ -73,6 +73,10 @@ aiFace ReadTriangle(XmlNode &node) {
|
||||||
face.mIndices[1] = static_cast<unsigned int>(std::atoi(node.attribute(XmlTag::v2).as_string()));
|
face.mIndices[1] = static_cast<unsigned int>(std::atoi(node.attribute(XmlTag::v2).as_string()));
|
||||||
face.mIndices[2] = static_cast<unsigned int>(std::atoi(node.attribute(XmlTag::v3).as_string()));
|
face.mIndices[2] = static_cast<unsigned int>(std::atoi(node.attribute(XmlTag::v3).as_string()));
|
||||||
|
|
||||||
|
texId0 = static_cast<unsigned int>(std::atoi(node.attribute(XmlTag::p1).as_string()));
|
||||||
|
texId1 = static_cast<unsigned int>(std::atoi(node.attribute(XmlTag::p2).as_string()));
|
||||||
|
texId2 = static_cast<unsigned int>(std::atoi(node.attribute(XmlTag::p3).as_string()));
|
||||||
|
|
||||||
return face;
|
return face;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -412,6 +416,8 @@ void XmlSerializer::ImportTriangles(XmlNode &node, aiMesh *mesh) {
|
||||||
bool hasPid = getNodeAttribute(currentNode, D3MF::XmlTag::pid, pid);
|
bool hasPid = getNodeAttribute(currentNode, D3MF::XmlTag::pid, pid);
|
||||||
bool hasP1 = getNodeAttribute(currentNode, D3MF::XmlTag::p1, p1);
|
bool hasP1 = getNodeAttribute(currentNode, D3MF::XmlTag::p1, p1);
|
||||||
|
|
||||||
|
unsigned int texId[3];
|
||||||
|
aiFace face = ReadTriangle(currentNode, texId[0], texId[1], texId[2]);
|
||||||
if (hasPid && hasP1) {
|
if (hasPid && hasP1) {
|
||||||
auto it = mResourcesDictionnary.find(pid);
|
auto it = mResourcesDictionnary.find(pid);
|
||||||
if (it != mResourcesDictionnary.end()) {
|
if (it != mResourcesDictionnary.end()) {
|
||||||
|
@ -420,6 +426,11 @@ void XmlSerializer::ImportTriangles(XmlNode &node, aiMesh *mesh) {
|
||||||
mesh->mMaterialIndex = baseMaterials->mMaterialIndex[p1];
|
mesh->mMaterialIndex = baseMaterials->mMaterialIndex[p1];
|
||||||
} else if (it->second->getType() == ResourceType::RT_Texture2DGroup) {
|
} else if (it->second->getType() == ResourceType::RT_Texture2DGroup) {
|
||||||
if (mesh->mTextureCoords[0] == nullptr) {
|
if (mesh->mTextureCoords[0] == nullptr) {
|
||||||
|
mesh->mNumUVComponents[0] = 2;
|
||||||
|
for (unsigned int i = 1; i < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++i) {
|
||||||
|
mesh->mNumUVComponents[i] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
Texture2DGroup *group = static_cast<Texture2DGroup *>(it->second);
|
Texture2DGroup *group = static_cast<Texture2DGroup *>(it->second);
|
||||||
const std::string name = ai_to_string(group->mTexId);
|
const std::string name = ai_to_string(group->mTexId);
|
||||||
for (size_t i = 0; i < mMaterials.size(); ++i) {
|
for (size_t i = 0; i < mMaterials.size(); ++i) {
|
||||||
|
@ -427,8 +438,9 @@ void XmlSerializer::ImportTriangles(XmlNode &node, aiMesh *mesh) {
|
||||||
mesh->mMaterialIndex = static_cast<unsigned int>(i);
|
mesh->mMaterialIndex = static_cast<unsigned int>(i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mesh->mTextureCoords[0] = new aiVector3D[group->mTex2dCoords.size()];
|
mesh->mTextureCoords[0] = new aiVector3D[mesh->mNumVertices];
|
||||||
for (unsigned int i = 0; i < group->mTex2dCoords.size(); ++i) {
|
for (unsigned int i = 0; i < mesh->mNumVertices; ++i) {
|
||||||
|
|
||||||
mesh->mTextureCoords[0][i] = aiVector3D(group->mTex2dCoords[i].x, group->mTex2dCoords[i].y, 0);
|
mesh->mTextureCoords[0][i] = aiVector3D(group->mTex2dCoords[i].x, group->mTex2dCoords[i].y, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -436,7 +448,6 @@ void XmlSerializer::ImportTriangles(XmlNode &node, aiMesh *mesh) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
aiFace face = ReadTriangle(currentNode);
|
|
||||||
faces.push_back(face);
|
faces.push_back(face);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -578,11 +589,15 @@ aiMaterial *XmlSerializer::readMaterialDef(XmlNode &node, unsigned int basemater
|
||||||
}
|
}
|
||||||
|
|
||||||
void XmlSerializer::StoreMaterialsInScene(aiScene *scene) {
|
void XmlSerializer::StoreMaterialsInScene(aiScene *scene) {
|
||||||
if (nullptr == scene || mMaterials.empty()) {
|
if (nullptr == scene) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
scene->mNumMaterials = static_cast<unsigned int>(mMaterials.size());
|
scene->mNumMaterials = static_cast<unsigned int>(mMaterials.size());
|
||||||
|
if (scene->mNumMaterials == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
scene->mMaterials = new aiMaterial *[scene->mNumMaterials];
|
scene->mMaterials = new aiMaterial *[scene->mNumMaterials];
|
||||||
for (size_t i = 0; i < mMaterials.size(); ++i) {
|
for (size_t i = 0; i < mMaterials.size(); ++i) {
|
||||||
scene->mMaterials[i] = mMaterials[i];
|
scene->mMaterials[i] = mMaterials[i];
|
||||||
|
|
|
@ -874,7 +874,7 @@ void IRRImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy
|
||||||
|
|
||||||
// Batch loader used to load external models
|
// Batch loader used to load external models
|
||||||
BatchLoader batch(pIOHandler);
|
BatchLoader batch(pIOHandler);
|
||||||
// batch.SetBasePath(pFile);
|
//batch.SetBasePath(pFile);
|
||||||
|
|
||||||
cameras.reserve(5);
|
cameras.reserve(5);
|
||||||
lights.reserve(5);
|
lights.reserve(5);
|
||||||
|
|
|
@ -105,36 +105,39 @@ void ScenePreprocessor::ProcessMesh(aiMesh *mesh) {
|
||||||
for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++i) {
|
for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++i) {
|
||||||
if (!mesh->mTextureCoords[i]) {
|
if (!mesh->mTextureCoords[i]) {
|
||||||
mesh->mNumUVComponents[i] = 0;
|
mesh->mNumUVComponents[i] = 0;
|
||||||
} else {
|
continue;
|
||||||
if (!mesh->mNumUVComponents[i]) {
|
}
|
||||||
mesh->mNumUVComponents[i] = 2;
|
|
||||||
|
if (!mesh->mNumUVComponents[i]) {
|
||||||
|
mesh->mNumUVComponents[i] = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
aiVector3D *p = mesh->mTextureCoords[i], *end = p + mesh->mNumVertices;
|
||||||
|
|
||||||
|
// Ensure unused components are zeroed. This will make 1D texture channels work
|
||||||
|
// as if they were 2D channels .. just in case an application doesn't handle
|
||||||
|
// this case
|
||||||
|
if (2 == mesh->mNumUVComponents[i]) {
|
||||||
|
size_t num = 0;
|
||||||
|
for (; p != end; ++p) {
|
||||||
|
p->z = 0.f;
|
||||||
|
num++;
|
||||||
}
|
}
|
||||||
|
} else if (1 == mesh->mNumUVComponents[i]) {
|
||||||
aiVector3D *p = mesh->mTextureCoords[i], *end = p + mesh->mNumVertices;
|
for (; p != end; ++p) {
|
||||||
|
p->z = p->y = 0.f;
|
||||||
// Ensure unused components are zeroed. This will make 1D texture channels work
|
}
|
||||||
// as if they were 2D channels .. just in case an application doesn't handle
|
} else if (3 == mesh->mNumUVComponents[i]) {
|
||||||
// this case
|
// Really 3D coordinates? Check whether the third coordinate is != 0 for at least one element
|
||||||
if (2 == mesh->mNumUVComponents[i]) {
|
for (; p != end; ++p) {
|
||||||
for (; p != end; ++p) {
|
if (p->z != 0) {
|
||||||
p->z = 0.f;
|
break;
|
||||||
}
|
|
||||||
} else if (1 == mesh->mNumUVComponents[i]) {
|
|
||||||
for (; p != end; ++p) {
|
|
||||||
p->z = p->y = 0.f;
|
|
||||||
}
|
|
||||||
} else if (3 == mesh->mNumUVComponents[i]) {
|
|
||||||
// Really 3D coordinates? Check whether the third coordinate is != 0 for at least one element
|
|
||||||
for (; p != end; ++p) {
|
|
||||||
if (p->z != 0) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (p == end) {
|
|
||||||
ASSIMP_LOG_WARN("ScenePreprocessor: UVs are declared to be 3D but they're obviously not. Reverting to 2D.");
|
|
||||||
mesh->mNumUVComponents[i] = 2;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (p == end) {
|
||||||
|
ASSIMP_LOG_WARN("ScenePreprocessor: UVs are declared to be 3D but they're obviously not. Reverting to 2D.");
|
||||||
|
mesh->mNumUVComponents[i] = 2;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -99,295 +99,129 @@ template <class TNodeType>
|
||||||
class TXmlParser {
|
class TXmlParser {
|
||||||
public:
|
public:
|
||||||
/// @brief The default class constructor.
|
/// @brief The default class constructor.
|
||||||
TXmlParser() :
|
TXmlParser();
|
||||||
mDoc(nullptr),
|
|
||||||
mData() {
|
|
||||||
// empty
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @brief The class destructor.
|
/// @brief The class destructor.
|
||||||
~TXmlParser() {
|
~TXmlParser();
|
||||||
clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @brief Will clear the parsed xml-file.
|
/// @brief Will clear the parsed xml-file.
|
||||||
void clear() {
|
void clear();
|
||||||
if (mData.empty()) {
|
|
||||||
mDoc = nullptr;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
mData.clear();
|
|
||||||
delete mDoc;
|
|
||||||
mDoc = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @brief Will search for a child-node by its name
|
/// @brief Will search for a child-node by its name
|
||||||
/// @param name [in] The name of the child-node.
|
/// @param name [in] The name of the child-node.
|
||||||
/// @return The node instance or nullptr, if nothing was found.
|
/// @return The node instance or nullptr, if nothing was found.
|
||||||
TNodeType *findNode(const std::string &name) {
|
TNodeType *findNode(const std::string &name);
|
||||||
if (name.empty()) {
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (nullptr == mDoc) {
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
find_node_by_name_predicate predicate(name);
|
|
||||||
mCurrent = mDoc->find_node(predicate);
|
|
||||||
if (mCurrent.empty()) {
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
return &mCurrent;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @brief Will return true, if the node is a child-node.
|
/// @brief Will return true, if the node is a child-node.
|
||||||
/// @param name [in] The name of the child node to look for.
|
/// @param name [in] The name of the child node to look for.
|
||||||
/// @return true, if the node is a child-node or false if not.
|
/// @return true, if the node is a child-node or false if not.
|
||||||
bool hasNode(const std::string &name) {
|
bool hasNode(const std::string &name);
|
||||||
return nullptr != findNode(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @brief Will parse an xml-file from a given stream.
|
/// @brief Will parse an xml-file from a given stream.
|
||||||
/// @param stream The input stream.
|
/// @param stream The input stream.
|
||||||
/// @return true, if the parsing was successful, false if not.
|
/// @return true, if the parsing was successful, false if not.
|
||||||
bool parse(IOStream *stream) {
|
bool parse(IOStream *stream);
|
||||||
if (nullptr == stream) {
|
|
||||||
ASSIMP_LOG_DEBUG("Stream is nullptr.");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
const size_t len = stream->FileSize();
|
/// @brief Will return true if a root node is there.
|
||||||
mData.resize(len + 1);
|
|
||||||
memset(&mData[0], '\0', len + 1);
|
|
||||||
stream->Read(&mData[0], 1, len);
|
|
||||||
|
|
||||||
mDoc = new pugi::xml_document();
|
|
||||||
pugi::xml_parse_result parse_result = mDoc->load_string(&mData[0], pugi::parse_full);
|
|
||||||
if (parse_result.status == pugi::status_ok) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
ASSIMP_LOG_DEBUG("Error while parse xml.", std::string(parse_result.description()), " @ ", parse_result.offset);
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @brief Will return truem if a root node is there.
|
|
||||||
/// @return true in case of an existing root.
|
/// @return true in case of an existing root.
|
||||||
bool hasRoot() const {
|
bool hasRoot() const;
|
||||||
return nullptr != mDoc;
|
|
||||||
}
|
|
||||||
/// @brief Will return the document pointer, is nullptr if no xml-file was parsed.
|
/// @brief Will return the document pointer, is nullptr if no xml-file was parsed.
|
||||||
/// @return The pointer showing to the document.
|
/// @return The pointer showing to the document.
|
||||||
pugi::xml_document *getDocument() const {
|
pugi::xml_document *getDocument() const;
|
||||||
return mDoc;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @brief Will return the root node, const version.
|
/// @brief Will return the root node, const version.
|
||||||
/// @return The root node.
|
/// @return The root node.
|
||||||
const TNodeType getRootNode() const {
|
const TNodeType getRootNode() const;
|
||||||
static pugi::xml_node none;
|
|
||||||
if (nullptr == mDoc) {
|
|
||||||
return none;
|
|
||||||
}
|
|
||||||
return mDoc->root();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @brief Will return the root node, non-const version.
|
/// @brief Will return the root node, non-const version.
|
||||||
/// @return The root node.
|
/// @return The root node.
|
||||||
TNodeType getRootNode() {
|
TNodeType getRootNode();
|
||||||
static pugi::xml_node none;
|
|
||||||
if (nullptr == mDoc) {
|
|
||||||
return none;
|
|
||||||
}
|
|
||||||
return mDoc->root();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @brief Will check if a node with the given name is in.
|
/// @brief Will check if a node with the given name is in.
|
||||||
/// @param node [in] The node to look in.
|
/// @param node [in] The node to look in.
|
||||||
/// @param name [in] The name of the child-node.
|
/// @param name [in] The name of the child-node.
|
||||||
/// @return true, if node was found, false if not.
|
/// @return true, if node was found, false if not.
|
||||||
static inline bool hasNode(XmlNode &node, const char *name) {
|
static inline bool hasNode(XmlNode &node, const char *name);
|
||||||
pugi::xml_node child = node.find_child(find_node_by_name_predicate(name));
|
|
||||||
return !child.empty();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @brief Will check if an attribute is part of the XmlNode.
|
/// @brief Will check if an attribute is part of the XmlNode.
|
||||||
/// @param xmlNode [in] The node to search in.
|
/// @param xmlNode [in] The node to search in.
|
||||||
/// @param name [in} The attribute name to look for.
|
/// @param name [in} The attribute name to look for.
|
||||||
/// @return true, if the was found, false if not.
|
/// @return true, if the was found, false if not.
|
||||||
static inline bool hasAttribute(XmlNode &xmlNode, const char *name) {
|
static inline bool hasAttribute(XmlNode &xmlNode, const char *name);
|
||||||
pugi::xml_attribute attr = xmlNode.attribute(name);
|
|
||||||
return !attr.empty();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @brief Will try to get an unsigned int attribute value.
|
/// @brief Will try to get an unsigned int attribute value.
|
||||||
/// @param xmlNode [in] The node to search in.
|
/// @param xmlNode [in] The node to search in.
|
||||||
/// @param name [in] The attribute name to look for.
|
/// @param name [in] The attribute name to look for.
|
||||||
/// @param val [out] The unsigned int value from the attribute.
|
/// @param val [out] The unsigned int value from the attribute.
|
||||||
/// @return true, if the node contains an attribute with the given name and if the value is an unsigned int.
|
/// @return true, if the node contains an attribute with the given name and if the value is an unsigned int.
|
||||||
static inline bool getUIntAttribute(XmlNode &xmlNode, const char *name, unsigned int &val) {
|
static inline bool getUIntAttribute(XmlNode &xmlNode, const char *name, unsigned int &val);
|
||||||
pugi::xml_attribute attr = xmlNode.attribute(name);
|
|
||||||
if (attr.empty()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
val = attr.as_uint();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @brief Will try to get an int attribute value.
|
/// @brief Will try to get an int attribute value.
|
||||||
/// @param xmlNode [in] The node to search in.
|
/// @param xmlNode [in] The node to search in.
|
||||||
/// @param name [in] The attribute name to look for.
|
/// @param name [in] The attribute name to look for.
|
||||||
/// @param val [out] The int value from the attribute.
|
/// @param val [out] The int value from the attribute.
|
||||||
/// @return true, if the node contains an attribute with the given name and if the value is an int.
|
/// @return true, if the node contains an attribute with the given name and if the value is an int.
|
||||||
static inline bool getIntAttribute(XmlNode &xmlNode, const char *name, int &val) {
|
static inline bool getIntAttribute(XmlNode &xmlNode, const char *name, int &val);
|
||||||
pugi::xml_attribute attr = xmlNode.attribute(name);
|
|
||||||
if (attr.empty()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
val = attr.as_int();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @brief Will try to get a real attribute value.
|
/// @brief Will try to get a real attribute value.
|
||||||
/// @param xmlNode [in] The node to search in.
|
/// @param xmlNode [in] The node to search in.
|
||||||
/// @param name [in] The attribute name to look for.
|
/// @param name [in] The attribute name to look for.
|
||||||
/// @param val [out] The real value from the attribute.
|
/// @param val [out] The real value from the attribute.
|
||||||
/// @return true, if the node contains an attribute with the given name and if the value is a real.
|
/// @return true, if the node contains an attribute with the given name and if the value is a real.
|
||||||
static inline bool getRealAttribute(XmlNode &xmlNode, const char *name, ai_real &val) {
|
static inline bool getRealAttribute(XmlNode &xmlNode, const char *name, ai_real &val);
|
||||||
pugi::xml_attribute attr = xmlNode.attribute(name);
|
|
||||||
if (attr.empty()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
#ifdef ASSIMP_DOUBLE_PRECISION
|
|
||||||
val = attr.as_double();
|
|
||||||
#else
|
|
||||||
val = attr.as_float();
|
|
||||||
#endif
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @brief Will try to get a float attribute value.
|
/// @brief Will try to get a float attribute value.
|
||||||
/// @param xmlNode [in] The node to search in.
|
/// @param xmlNode [in] The node to search in.
|
||||||
/// @param name [in] The attribute name to look for.
|
/// @param name [in] The attribute name to look for.
|
||||||
/// @param val [out] The float value from the attribute.
|
/// @param val [out] The float value from the attribute.
|
||||||
/// @return true, if the node contains an attribute with the given name and if the value is a float.
|
/// @return true, if the node contains an attribute with the given name and if the value is a float.
|
||||||
static inline bool getFloatAttribute(XmlNode &xmlNode, const char *name, float &val) {
|
static inline bool getFloatAttribute(XmlNode &xmlNode, const char *name, float &val);
|
||||||
pugi::xml_attribute attr = xmlNode.attribute(name);
|
|
||||||
if (attr.empty()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
val = attr.as_float();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @brief Will try to get a double attribute value.
|
/// @brief Will try to get a double attribute value.
|
||||||
/// @param xmlNode [in] The node to search in.
|
/// @param xmlNode [in] The node to search in.
|
||||||
/// @param name [in] The attribute name to look for.
|
/// @param name [in] The attribute name to look for.
|
||||||
/// @param val [out] The double value from the attribute.
|
/// @param val [out] The double value from the attribute.
|
||||||
/// @return true, if the node contains an attribute with the given name and if the value is a double.
|
/// @return true, if the node contains an attribute with the given name and if the value is a double.
|
||||||
static inline bool getDoubleAttribute(XmlNode &xmlNode, const char *name, double &val) {
|
static inline bool getDoubleAttribute(XmlNode &xmlNode, const char *name, double &val);
|
||||||
pugi::xml_attribute attr = xmlNode.attribute(name);
|
|
||||||
if (attr.empty()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
val = attr.as_double();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @brief Will try to get a std::string attribute value.
|
/// @brief Will try to get a std::string attribute value.
|
||||||
/// @param xmlNode [in] The node to search in.
|
/// @param xmlNode [in] The node to search in.
|
||||||
/// @param name [in] The attribute name to look for.
|
/// @param name [in] The attribute name to look for.
|
||||||
/// @param val [out] The std::string value from the attribute.
|
/// @param val [out] The std::string value from the attribute.
|
||||||
/// @return true, if the node contains an attribute with the given name and if the value is a std::string.
|
/// @return true, if the node contains an attribute with the given name and if the value is a std::string.
|
||||||
static inline bool getStdStrAttribute(XmlNode &xmlNode, const char *name, std::string &val) {
|
static inline bool getStdStrAttribute(XmlNode &xmlNode, const char *name, std::string &val);
|
||||||
pugi::xml_attribute attr = xmlNode.attribute(name);
|
|
||||||
if (attr.empty()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
val = attr.as_string();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @brief Will try to get a bool attribute value.
|
/// @brief Will try to get a bool attribute value.
|
||||||
/// @param xmlNode [in] The node to search in.
|
/// @param xmlNode [in] The node to search in.
|
||||||
/// @param name [in] The attribute name to look for.
|
/// @param name [in] The attribute name to look for.
|
||||||
/// @param val [out] The bool value from the attribute.
|
/// @param val [out] The bool value from the attribute.
|
||||||
/// @return true, if the node contains an attribute with the given name and if the value is a bool.
|
/// @return true, if the node contains an attribute with the given name and if the value is a bool.
|
||||||
static inline bool getBoolAttribute(XmlNode &xmlNode, const char *name, bool &val) {
|
static inline bool getBoolAttribute(XmlNode &xmlNode, const char *name, bool &val);
|
||||||
pugi::xml_attribute attr = xmlNode.attribute(name);
|
|
||||||
if (attr.empty()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
val = attr.as_bool();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @brief Will try to get the value of the node as a string.
|
/// @brief Will try to get the value of the node as a string.
|
||||||
/// @param node [in] The node to search in.
|
/// @param node [in] The node to search in.
|
||||||
/// @param text [out] The value as a text.
|
/// @param text [out] The value as a text.
|
||||||
/// @return true, if the value can be read out.
|
/// @return true, if the value can be read out.
|
||||||
static inline bool getValueAsString(XmlNode &node, std::string &text) {
|
static inline bool getValueAsString(XmlNode &node, std::string &text);
|
||||||
text = std::string();
|
|
||||||
if (node.empty()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
text = node.text().as_string();
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @brief Will try to get the value of the node as a float.
|
/// @brief Will try to get the value of the node as a float.
|
||||||
/// @param node [in] The node to search in.
|
/// @param node [in] The node to search in.
|
||||||
/// @param text [out] The value as a float.
|
/// @param text [out] The value as a float.
|
||||||
/// @return true, if the value can be read out.
|
/// @return true, if the value can be read out.
|
||||||
static inline bool getValueAsFloat(XmlNode &node, ai_real &v) {
|
static inline bool getValueAsFloat(XmlNode &node, ai_real &v);
|
||||||
if (node.empty()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
v = node.text().as_float();
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @brief Will try to get the value of the node as an integer.
|
/// @brief Will try to get the value of the node as an integer.
|
||||||
/// @param node [in] The node to search in.
|
/// @param node [in] The node to search in.
|
||||||
/// @param text [out] The value as a int.
|
/// @param text [out] The value as a int.
|
||||||
/// @return true, if the value can be read out.
|
/// @return true, if the value can be read out.
|
||||||
static inline bool getValueAsInt(XmlNode &node, int &v) {
|
static inline bool getValueAsInt(XmlNode &node, int &v);
|
||||||
if (node.empty()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
v = node.text().as_int();
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @brief Will try to get the value of the node as an bool.
|
/// @brief Will try to get the value of the node as an bool.
|
||||||
/// @param node [in] The node to search in.
|
/// @param node [in] The node to search in.
|
||||||
/// @param text [out] The value as a bool.
|
/// @param text [out] The value as a bool.
|
||||||
/// @return true, if the value can be read out.
|
/// @return true, if the value can be read out.
|
||||||
static inline bool getValueAsBool(XmlNode& node, bool& v)
|
static inline bool getValueAsBool(XmlNode &node, bool &v);
|
||||||
{
|
|
||||||
if (node.empty()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
v = node.text().as_bool();
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
pugi::xml_document *mDoc;
|
pugi::xml_document *mDoc;
|
||||||
|
@ -395,6 +229,254 @@ private:
|
||||||
std::vector<char> mData;
|
std::vector<char> mData;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <class TNodeType>
|
||||||
|
inline TXmlParser<TNodeType>::TXmlParser() :
|
||||||
|
mDoc(nullptr),
|
||||||
|
mData() {
|
||||||
|
// empty
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class TNodeType>
|
||||||
|
inline TXmlParser<TNodeType>::~TXmlParser() {
|
||||||
|
clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class TNodeType>
|
||||||
|
inline void TXmlParser<TNodeType>::clear() {
|
||||||
|
if (mData.empty()) {
|
||||||
|
if (mDoc) {
|
||||||
|
delete mDoc;
|
||||||
|
}
|
||||||
|
mDoc = nullptr;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
mData.clear();
|
||||||
|
delete mDoc;
|
||||||
|
mDoc = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class TNodeType>
|
||||||
|
inline TNodeType *TXmlParser<TNodeType>::findNode(const std::string &name) {
|
||||||
|
if (name.empty()) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nullptr == mDoc) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
find_node_by_name_predicate predicate(name);
|
||||||
|
mCurrent = mDoc->find_node(predicate);
|
||||||
|
if (mCurrent.empty()) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return &mCurrent;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class TNodeType>
|
||||||
|
bool TXmlParser<TNodeType>::hasNode(const std::string &name) {
|
||||||
|
return nullptr != findNode(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class TNodeType>
|
||||||
|
bool TXmlParser<TNodeType>::parse(IOStream *stream) {
|
||||||
|
if (hasRoot()) {
|
||||||
|
clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nullptr == stream) {
|
||||||
|
ASSIMP_LOG_DEBUG("Stream is nullptr.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const size_t len = stream->FileSize();
|
||||||
|
mData.resize(len + 1);
|
||||||
|
memset(&mData[0], '\0', len + 1);
|
||||||
|
stream->Read(&mData[0], 1, len);
|
||||||
|
|
||||||
|
mDoc = new pugi::xml_document();
|
||||||
|
pugi::xml_parse_result parse_result = mDoc->load_string(&mData[0], pugi::parse_full);
|
||||||
|
if (parse_result.status == pugi::status_ok) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
ASSIMP_LOG_DEBUG("Error while parse xml.", std::string(parse_result.description()), " @ ", parse_result.offset);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class TNodeType>
|
||||||
|
bool TXmlParser<TNodeType>::hasRoot() const {
|
||||||
|
return nullptr != mDoc;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class TNodeType>
|
||||||
|
pugi::xml_document *TXmlParser<TNodeType>::getDocument() const {
|
||||||
|
return mDoc;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class TNodeType>
|
||||||
|
const TNodeType TXmlParser<TNodeType>::getRootNode() const {
|
||||||
|
static pugi::xml_node none;
|
||||||
|
if (nullptr == mDoc) {
|
||||||
|
return none;
|
||||||
|
}
|
||||||
|
return mDoc->root();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class TNodeType>
|
||||||
|
TNodeType TXmlParser<TNodeType>::getRootNode() {
|
||||||
|
static pugi::xml_node none;
|
||||||
|
if (nullptr == mDoc) {
|
||||||
|
return none;
|
||||||
|
}
|
||||||
|
|
||||||
|
return mDoc->root();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class TNodeType>
|
||||||
|
inline bool TXmlParser<TNodeType>::hasNode(XmlNode &node, const char *name) {
|
||||||
|
pugi::xml_node child = node.find_child(find_node_by_name_predicate(name));
|
||||||
|
return !child.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class TNodeType>
|
||||||
|
inline bool TXmlParser<TNodeType>::hasAttribute(XmlNode &xmlNode, const char *name) {
|
||||||
|
pugi::xml_attribute attr = xmlNode.attribute(name);
|
||||||
|
return !attr.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class TNodeType>
|
||||||
|
inline bool TXmlParser<TNodeType>::getUIntAttribute(XmlNode &xmlNode, const char *name, unsigned int &val) {
|
||||||
|
pugi::xml_attribute attr = xmlNode.attribute(name);
|
||||||
|
if (attr.empty()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
val = attr.as_uint();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class TNodeType>
|
||||||
|
inline bool TXmlParser<TNodeType>::getIntAttribute(XmlNode &xmlNode, const char *name, int &val) {
|
||||||
|
pugi::xml_attribute attr = xmlNode.attribute(name);
|
||||||
|
if (attr.empty()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
val = attr.as_int();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class TNodeType>
|
||||||
|
inline bool TXmlParser<TNodeType>::getRealAttribute(XmlNode &xmlNode, const char *name, ai_real &val) {
|
||||||
|
pugi::xml_attribute attr = xmlNode.attribute(name);
|
||||||
|
if (attr.empty()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
#ifdef ASSIMP_DOUBLE_PRECISION
|
||||||
|
val = attr.as_double();
|
||||||
|
#else
|
||||||
|
val = attr.as_float();
|
||||||
|
#endif
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class TNodeType>
|
||||||
|
inline bool TXmlParser<TNodeType>::getFloatAttribute(XmlNode &xmlNode, const char *name, float &val) {
|
||||||
|
pugi::xml_attribute attr = xmlNode.attribute(name);
|
||||||
|
if (attr.empty()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
val = attr.as_float();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class TNodeType>
|
||||||
|
inline bool TXmlParser<TNodeType>::getDoubleAttribute(XmlNode &xmlNode, const char *name, double &val) {
|
||||||
|
pugi::xml_attribute attr = xmlNode.attribute(name);
|
||||||
|
if (attr.empty()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
val = attr.as_double();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class TNodeType>
|
||||||
|
inline bool TXmlParser<TNodeType>::getStdStrAttribute(XmlNode &xmlNode, const char *name, std::string &val) {
|
||||||
|
pugi::xml_attribute attr = xmlNode.attribute(name);
|
||||||
|
if (attr.empty()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
val = attr.as_string();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class TNodeType>
|
||||||
|
inline bool TXmlParser<TNodeType>::getBoolAttribute(XmlNode &xmlNode, const char *name, bool &val) {
|
||||||
|
pugi::xml_attribute attr = xmlNode.attribute(name);
|
||||||
|
if (attr.empty()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
val = attr.as_bool();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class TNodeType>
|
||||||
|
inline bool TXmlParser<TNodeType>::getValueAsString(XmlNode &node, std::string &text) {
|
||||||
|
text = std::string();
|
||||||
|
if (node.empty()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
text = node.text().as_string();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class TNodeType>
|
||||||
|
inline bool TXmlParser<TNodeType>::getValueAsFloat(XmlNode &node, ai_real &v) {
|
||||||
|
if (node.empty()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
v = node.text().as_float();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class TNodeType>
|
||||||
|
inline bool TXmlParser<TNodeType>::getValueAsInt(XmlNode &node, int &v) {
|
||||||
|
if (node.empty()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
v = node.text().as_int();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class TNodeType>
|
||||||
|
inline bool TXmlParser<TNodeType>::getValueAsBool(XmlNode &node, bool &v) {
|
||||||
|
if (node.empty()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
v = node.text().as_bool();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
using XmlParser = TXmlParser<pugi::xml_node>;
|
using XmlParser = TXmlParser<pugi::xml_node>;
|
||||||
|
|
||||||
/// @brief This class declares an iterator to loop through all children of the root node.
|
/// @brief This class declares an iterator to loop through all children of the root node.
|
||||||
|
|
Loading…
Reference in New Issue