Unified some previously duplicated code

This commit is contained in:
2016-01-07 14:06:14 +01:00
parent 03456ad731
commit ee83394678
3 changed files with 107 additions and 129 deletions
+46 -49
View File
@@ -2,6 +2,7 @@
#define EntityFile_h__ #define EntityFile_h__
#include <stack> #include <stack>
#include <boost/lexical_cast.hpp>
#include <xercesc/util/XercesDefs.hpp> #include <xercesc/util/XercesDefs.hpp>
#include <xercesc/util/PlatformUtils.hpp> #include <xercesc/util/PlatformUtils.hpp>
#include <xercesc/sax2/SAX2XMLReader.hpp> #include <xercesc/sax2/SAX2XMLReader.hpp>
@@ -245,58 +246,54 @@ private:
public: public:
static std::size_t GetTypeStride(std::string typeName); static std::size_t GetTypeStride(std::string typeName);
static void WriteElementData(const xercesc::DOMElement* element, std::string typeName, char* outData)
{
using namespace xercesc;
if (typeName == "Vector") { static void WriteAttributeData(char* outData, const std::string fieldType, const std::map<std::string, std::string>& attributes)
glm::vec3 vec; {
vec.x = getFloatAttribute(element, "X"); if (fieldType == "Vector") {
vec.y = getFloatAttribute(element, "Y"); glm::vec3 vec;
vec.z = getFloatAttribute(element, "Z"); vec.x = boost::lexical_cast<float>(attributes.at("X"));
memcpy(outData, reinterpret_cast<char*>(&vec), GetTypeStride(typeName)); vec.y = boost::lexical_cast<float>(attributes.at("Y"));
} else if (typeName == "Color") { vec.z = boost::lexical_cast<float>(attributes.at("Z"));
glm::vec4 vec; memcpy(outData, reinterpret_cast<char*>(&vec), EntityFile::GetTypeStride(fieldType));
vec.r = getFloatAttribute(element, "R"); } else if (fieldType == "Color") {
vec.g = getFloatAttribute(element, "G"); glm::vec4 vec;
vec.b = getFloatAttribute(element, "B"); vec.r = boost::lexical_cast<float>(attributes.at("R"));
vec.a = getFloatAttribute(element, "A"); vec.g = boost::lexical_cast<float>(attributes.at("G"));
memcpy(outData, reinterpret_cast<char*>(&vec), GetTypeStride(typeName)); vec.b = boost::lexical_cast<float>(attributes.at("B"));
} else if (typeName == "Quaternion") { vec.a = boost::lexical_cast<float>(attributes.at("A"));
glm::quat q; memcpy(outData, reinterpret_cast<char*>(&vec), EntityFile::GetTypeStride(fieldType));
q.x = getFloatAttribute(element, "X"); } else if (fieldType == "Quaternion") {
q.y = getFloatAttribute(element, "Y"); glm::quat q;
q.z = getFloatAttribute(element, "Z"); q.x = boost::lexical_cast<float>(attributes.at("X"));
q.w = getFloatAttribute(element, "W"); q.y = boost::lexical_cast<float>(attributes.at("Y"));
memcpy(outData, reinterpret_cast<char*>(&q), GetTypeStride(typeName)); q.z = boost::lexical_cast<float>(attributes.at("Z"));
} else if (typeName == "float") { q.w = boost::lexical_cast<float>(attributes.at("W"));
XSValue::Status status; memcpy(outData, reinterpret_cast<char*>(&q), EntityFile::GetTypeStride(fieldType));
XSValue* val = XSValue::getActualValue(element->getTextContent(), xercesc::XSValue::DataType::dt_float, status); } else if (!attributes.empty()) {
memcpy(outData, reinterpret_cast<char*>(&val->fData.fValue.f_float), GetTypeStride(typeName)); LOG_WARNING("%i attributes not handled by any type conversion!", attributes.size());
} else if (typeName == "double") { }
XSValue::Status status; }
XSValue* val = XSValue::getActualValue(element->getTextContent(), xercesc::XSValue::DataType::dt_double, status);
memcpy(outData, reinterpret_cast<char*>(&val->fData.fValue.f_double), GetTypeStride(typeName)); static void WriteValueData(char* outData, const std::string fieldType, const char* valueData)
} else if (typeName == "bool") { {
XSValue::Status status; if (fieldType == "int") {
XSValue* val = XSValue::getActualValue(element->getTextContent(), xercesc::XSValue::DataType::dt_boolean, status); int value = boost::lexical_cast<int>(valueData);
memcpy(outData, reinterpret_cast<char*>(&val->fData.fValue.f_bool), GetTypeStride(typeName)); memcpy(outData, reinterpret_cast<char*>(&value), EntityFile::GetTypeStride(fieldType));
} else { } else if (fieldType == "float") {
XSValue::DataType dataType = XSValue::getDataType(XS::ToXMLCh(typeName)); float value = boost::lexical_cast<float>(valueData);
if (dataType == XSValue::DataType::dt_string) { memcpy(outData, reinterpret_cast<char*>(&value), EntityFile::GetTypeStride(fieldType));
char* str = XMLString::transcode(element->getTextContent()); } else if (fieldType == "double") {
std::string standardString(str); double value = boost::lexical_cast<double>(valueData);
new (outData) std::string(str); memcpy(outData, reinterpret_cast<char*>(&value), EntityFile::GetTypeStride(fieldType));
XMLString::release(&str); } else if (fieldType == "bool") {
//memcpy(outData, reinterpret_cast<char*>(&standardString), getTypeStride(typeName)); bool value = (valueData[0] == 't'); // Lazy bool evaluation
} else { memcpy(outData, reinterpret_cast<char*>(&value), EntityFile::GetTypeStride(fieldType));
//XSValue::Status status; } else if (fieldType == "string") {
//XSValue* val = XSValue::getActualValue(element->getTextContent(), dataType, status); new (outData) std::string(valueData);
//memcpy(outData, reinterpret_cast<char*>(&val->fData.fValue), getTypeStride(typeName)); } else {
LOG_WARNING("Unknown native data type: %s", typeName.c_str()); LOG_WARNING("Unknown value data type: %s", fieldType.c_str());
} }
} }
}
void Parse(const EntityFileHandler* handler); void Parse(const EntityFileHandler* handler);
//const std::map<std::string, ::ComponentInfo>& ComponentInfo() const { return m_ComponentInfo; } //const std::map<std::string, ::ComponentInfo>& ComponentInfo() const { return m_ComponentInfo; }
+2 -40
View File
@@ -55,29 +55,7 @@ private:
} }
char* data = component.Data + component.Info.FieldOffsets.at(fieldName); char* data = component.Data + component.Info.FieldOffsets.at(fieldName);
if (fieldType == "Vector") { EntityFile::WriteAttributeData(data, fieldType, attributes);
glm::vec3 vec;
vec.x = boost::lexical_cast<float>(attributes.at("X"));
vec.y = boost::lexical_cast<float>(attributes.at("Y"));
vec.z = boost::lexical_cast<float>(attributes.at("Z"));
memcpy(data, reinterpret_cast<char*>(&vec), EntityFile::GetTypeStride(fieldType));
} else if (fieldType == "Color") {
glm::vec4 vec;
vec.r = boost::lexical_cast<float>(attributes.at("R"));
vec.g = boost::lexical_cast<float>(attributes.at("G"));
vec.b = boost::lexical_cast<float>(attributes.at("B"));
vec.a = boost::lexical_cast<float>(attributes.at("A"));
memcpy(data, reinterpret_cast<char*>(&vec), EntityFile::GetTypeStride(fieldType));
} else if (fieldType == "Quaternion") {
glm::quat q;
q.x = boost::lexical_cast<float>(attributes.at("X"));
q.y = boost::lexical_cast<float>(attributes.at("Y"));
q.z = boost::lexical_cast<float>(attributes.at("Z"));
q.w = boost::lexical_cast<float>(attributes.at("W"));
memcpy(data, reinterpret_cast<char*>(&q), EntityFile::GetTypeStride(fieldType));
} else if (!attributes.empty()) {
LOG_WARNING("%i attributes not handled by any type conversion!", attributes.size());
}
} }
void onFieldData(EntityID entity, std::string componentType, std::string fieldName, const char* fieldData) void onFieldData(EntityID entity, std::string componentType, std::string fieldName, const char* fieldData)
@@ -87,22 +65,6 @@ private:
std::string fieldType = component.Info.FieldTypes.at(fieldName); std::string fieldType = component.Info.FieldTypes.at(fieldName);
char* data = component.Data + component.Info.FieldOffsets.at(fieldName); char* data = component.Data + component.Info.FieldOffsets.at(fieldName);
if (fieldType == "int") { EntityFile::WriteValueData(data, fieldType, fieldData);
int value = boost::lexical_cast<int>(fieldData);
memcpy(data, reinterpret_cast<char*>(&value), EntityFile::GetTypeStride(fieldType));
} else if (fieldType == "float") {
float value = boost::lexical_cast<float>(fieldData);
memcpy(data, reinterpret_cast<char*>(&value), EntityFile::GetTypeStride(fieldType));
} else if (fieldType == "double") {
double value = boost::lexical_cast<double>(fieldData);
memcpy(data, reinterpret_cast<char*>(&value), EntityFile::GetTypeStride(fieldType));
} else if (fieldType == "bool") {
bool value = (fieldData[0] == 't'); // Lazy bool evaluation
memcpy(data, reinterpret_cast<char*>(&value), EntityFile::GetTypeStride(fieldType));
} else if (fieldType == "string") {
new (data) std::string(fieldData);
} else {
LOG_WARNING("Unknown data type: %s", fieldType.c_str());
}
} }
}; };
+59 -40
View File
@@ -174,53 +174,72 @@ private:
} }
} }
void parseDefaults() void parseDefaults()
{ {
using namespace xercesc; using namespace xercesc;
for (auto& ci : m_ComponentInfo) { for (auto& ci : m_ComponentInfo) {
// Allocate memory for default values // Allocate memory for default values
ci.second.Defaults = std::shared_ptr<char>(new char[ci.second.Meta.Stride]); ci.second.Defaults = std::shared_ptr<char>(new char[ci.second.Meta.Stride]);
memset(ci.second.Defaults.get(), 0, ci.second.Meta.Stride); memset(ci.second.Defaults.get(), 0, ci.second.Meta.Stride);
XercesDOMParser parser(nullptr, XMLPlatformUtils::fgMemoryManager); XercesDOMParser parser(nullptr, XMLPlatformUtils::fgMemoryManager);
//parser.setErrorHandler(m_ErrorHandler); //parser.setErrorHandler(m_ErrorHandler);
std::string componentName = ci.first; std::string componentName = ci.first;
LOG_DEBUG("Parsing defaults for component %s", componentName.c_str()); LOG_DEBUG("Parsing defaults for component %s", componentName.c_str());
boost::filesystem::path defaultsFile = "Schema/Components/" + componentName + ".xml"; boost::filesystem::path defaultsFile = "Schema/Components/" + componentName + ".xml";
parser.parse(defaultsFile.string().c_str()); parser.parse(defaultsFile.string().c_str());
auto doc = parser.getDocument(); auto doc = parser.getDocument();
if (doc == nullptr) { if (doc == nullptr) {
LOG_ERROR("%s not found! Skipping.", defaultsFile.string().c_str()); LOG_ERROR("%s not found! Skipping.", defaultsFile.string().c_str());
continue;
}
// Find the node in the components namespace matching the component name
std::string tagName = "c:" + componentName;
auto rootNodes = doc->getElementsByTagName(XS::ToXMLCh(tagName));
if (rootNodes->getLength() == 0) {
LOG_ERROR("Couldn't find defaults for component \"%s\"! Skipping.", componentName.c_str());
continue;
}
auto componentElement = dynamic_cast<DOMElement*>(rootNodes->item(0));
// Fill the default value buffer with values
for (auto& field : ci.second.FieldOffsets) {
std::string fieldName = field.first;
auto fieldNodes = componentElement->getElementsByTagName(XS::ToXMLCh(fieldName));
auto fieldNode = fieldNodes->item(0);
if (fieldNode == nullptr) {
LOG_ERROR("Defaults for component \"%s\" is missing field \"%s\"!", componentName.c_str(), fieldName.c_str());
continue; continue;
} }
auto fieldElement = dynamic_cast<DOMElement*>(fieldNode);
std::string fieldType = ci.second.FieldTypes.at(fieldName); // Find the node in the components namespace matching the component name
unsigned int fieldOffset = ci.second.FieldOffsets.at(fieldName); std::string tagName = "c:" + componentName;
EntityFile::WriteElementData(fieldElement, fieldType, ci.second.Defaults.get() + fieldOffset); auto rootNodes = doc->getElementsByTagName(XS::ToXMLCh(tagName));
if (rootNodes->getLength() == 0) {
LOG_ERROR("Couldn't find defaults for component \"%s\"! Skipping.", componentName.c_str());
continue;
}
auto componentElement = dynamic_cast<DOMElement*>(rootNodes->item(0));
// Fill the default value buffer with values
for (auto& field : ci.second.FieldOffsets) {
std::string fieldName = field.first;
auto fieldNodes = componentElement->getElementsByTagName(XS::ToXMLCh(fieldName));
auto fieldNode = fieldNodes->item(0);
if (fieldNode == nullptr) {
LOG_ERROR("Defaults for component \"%s\" is missing field \"%s\"!", componentName.c_str(), fieldName.c_str());
continue;
}
auto fieldElement = dynamic_cast<DOMElement*>(fieldNode);
std::string fieldType = ci.second.FieldTypes.at(fieldName);
unsigned int fieldOffset = ci.second.FieldOffsets.at(fieldName);
char* data = ci.second.Defaults.get() + fieldOffset;
// Handle potential field attributes
if (fieldElement->hasAttributes()) {
std::map<std::string, std::string> attributes;
auto attributeMap = fieldElement->getAttributes();
for (int i = 0; i < attributeMap->getLength(); ++i) {
auto attribItem = attributeMap->item(i);
attributes[XS::ToString(attribItem->getNodeName())] = XS::ToString(attribItem->getNodeValue());
}
EntityFile::WriteAttributeData(data, fieldType, attributes);
}
// Handle potential field values
auto childNode = fieldElement->getFirstChild();
if (childNode != nullptr && childNode->getNodeType() == DOMNode::TEXT_NODE) {
char* cstrValue = XMLString::transcode(childNode->getNodeValue());
EntityFile::WriteValueData(data, fieldType, cstrValue);
XMLString::release(&cstrValue);
}
}
} }
} }
}
}; };