Xml: introduce helper for attribute parsing.

pull/2966/head
Kim Kulling 2020-08-21 06:45:30 +02:00
parent cb631517a7
commit 7adfe1f2d8
3 changed files with 111 additions and 49 deletions

View File

@ -246,19 +246,18 @@ ai_real ColladaParser::ReadFloatFromTextContent() {
// Reads the contents of the file
void ColladaParser::ReadContents(XmlNode &node) {
for (pugi::xml_node &curNode : node.children()) {
pugi::xml_attribute attr = curNode.attribute("version");
if (attr) {
const char *version = attr.as_string();
std::string version;
if (XmlParser::getStdStrAttribute(curNode, "version", version)) {
aiString v;
v.Set(version);
v.Set(version.c_str());
mAssetMetaData.emplace(AI_METADATA_SOURCE_FORMAT_VERSION, v);
if (!::strncmp(version, "1.5", 3)) {
if (!::strncmp(version.c_str(), "1.5", 3)) {
mFormat = FV_1_5_n;
ASSIMP_LOG_DEBUG("Collada schema version is 1.5.n");
} else if (!::strncmp(version, "1.4", 3)) {
} else if (!::strncmp(version.c_str(), "1.4", 3)) {
mFormat = FV_1_4_n;
ASSIMP_LOG_DEBUG("Collada schema version is 1.4.n");
} else if (!::strncmp(version, "1.3", 3)) {
} else if (!::strncmp(version.c_str(), "1.3", 3)) {
mFormat = FV_1_3_n;
ASSIMP_LOG_DEBUG("Collada schema version is 1.3.n");
}
@ -1244,6 +1243,50 @@ void ColladaParser::ReadEffectColor(XmlNode &node, aiColor4D &pColor, Sampler &p
return;
}
for (XmlNode &currentNode : node.children()) {
const std::string &currentName = currentNode.name();
if (currentName == "color") {
// text content contains 4 floats
const char *content = currentNode.value();
content = fast_atoreal_move<ai_real>(content, (ai_real &)pColor.r);
SkipSpacesAndLineEnd(&content);
content = fast_atoreal_move<ai_real>(content, (ai_real &)pColor.g);
SkipSpacesAndLineEnd(&content);
content = fast_atoreal_move<ai_real>(content, (ai_real &)pColor.b);
SkipSpacesAndLineEnd(&content);
content = fast_atoreal_move<ai_real>(content, (ai_real &)pColor.a);
SkipSpacesAndLineEnd(&content);
} else if (currentName == "texture") {
// get name of source texture/sampler
int attrTex = GetAttribute("texture");
pSampler.mName = mReader->getAttributeValue(attrTex);
// get name of UV source channel. Specification demands it to be there, but some exporters
// don't write it. It will be the default UV channel in case it's missing.
attrTex = TestAttribute("texcoord");
if (attrTex >= 0)
pSampler.mUVChannel = mReader->getAttributeValue(attrTex);
//SkipElement();
// as we've read texture, the color needs to be 1,1,1,1
pColor = aiColor4D(1.f, 1.f, 1.f, 1.f);
} else if (currentName == "technique" ) {
const int _profile = GetAttribute("profile");
const char *profile = mReader->getAttributeValue(_profile);
// Some extensions are quite useful ... ReadSamplerProperties processes
// several extensions in MAYA, OKINO and MAX3D profiles.
if (!::strcmp(profile, "MAYA") || !::strcmp(profile, "MAX3D") || !::strcmp(profile, "OKINO")) {
// get more information on this sampler
ReadSamplerProperties(pSampler);
}
}
}
// Save current element name
const std::string curElem = mReader->getNodeName();

View File

@ -4,7 +4,6 @@
Copyright (c) 2006-2020, assimp team
All rights reserved.
Redistribution and use of this software in source and binary forms,

View File

@ -52,22 +52,22 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
namespace Assimp {
struct find_node_by_name_predicate {
std::string mName;
find_node_by_name_predicate(const std::string &name) :
mName(name) {
std::string mName;
find_node_by_name_predicate(const std::string &name) :
mName(name) {
// empty
}
}
bool operator()(pugi::xml_node node) const {
return node.name() == mName;
}
bool operator()(pugi::xml_node node) const {
return node.name() == mName;
}
};
template<class TNodeType>
template <class TNodeType>
struct NodeConverter {
public:
static int to_int(TNodeType &node, const char *attribName ) {
ai_assert(nullptr != attribName);
static int to_int(TNodeType &node, const char *attribName) {
ai_assert(nullptr != attribName);
return node.attribute(attribName).to_int();
}
};
@ -75,72 +75,73 @@ public:
using XmlNode = pugi::xml_node;
using XmlAttribute = pugi::xml_attribute;
template<class TNodeType>
template <class TNodeType>
class TXmlParser {
public:
TXmlParser() :
mDoc(nullptr), mRoot(nullptr), mData() {
TXmlParser() :
mDoc(nullptr),
mRoot(nullptr),
mData() {
// empty
}
}
~TXmlParser() {
clear();
clear();
}
void clear() {
mData.resize(0);
mRoot = nullptr;
delete mDoc;
mDoc = nullptr;
mData.resize(0);
mRoot = nullptr;
delete mDoc;
mDoc = nullptr;
}
TNodeType *findNode(const std::string &name) {
if (name.empty()) {
return nullptr;
}
if (name.empty()) {
return nullptr;
}
if (nullptr == mDoc) {
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 nullptr;
}
return &mCurrent;
}
bool hasNode( const std::string &name ) {
bool hasNode(const std::string &name) {
return nullptr != findNode(name);
}
TNodeType *parse(IOStream *stream) {
if (nullptr == stream) {
return nullptr;
}
if (nullptr == stream) {
return nullptr;
}
mData.resize(stream->FileSize());
stream->Read(&mData[0], mData.size(), 1);
mDoc = new pugi::xml_document();
pugi::xml_parse_result result = mDoc->load_string(&mData[0]);
stream->Read(&mData[0], mData.size(), 1);
mDoc = new pugi::xml_document();
pugi::xml_parse_result result = mDoc->load_string(&mData[0]);
if (result.status == pugi::status_ok) {
pugi::xml_node root = *(mDoc->children().begin());
mRoot = &root;
//mRoot = &mDoc->root();
}
return mRoot;
}
pugi::xml_document *getDocument() const {
return mDoc;
return mDoc;
}
const TNodeType *getRootNode() const {
return mRoot;
return mRoot;
}
TNodeType *getRootNode() {
@ -157,16 +158,35 @@ public:
return !attr.empty();
}
private:
pugi::xml_document *mDoc;
TNodeType *mRoot;
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;
}
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;
}
private:
pugi::xml_document *mDoc;
TNodeType *mRoot;
TNodeType mCurrent;
std::vector<char> mData;
std::vector<char> mData;
};
using XmlParser = TXmlParser<pugi::xml_node>;
} // namespace Assimp
#endif // !! INCLUDED_AI_IRRXML_WRAPPER