Changeset View
Changeset View
Standalone View
Standalone View
source/simulation2/system/ParamNode.cpp
Show All 22 Lines | |||||
#include "ps/CLogger.h" | #include "ps/CLogger.h" | ||||
#include "ps/CStr.h" | #include "ps/CStr.h" | ||||
#include "ps/Filesystem.h" | #include "ps/Filesystem.h" | ||||
#include "ps/XML/Xeromyces.h" | #include "ps/XML/Xeromyces.h" | ||||
#include "scriptinterface/ScriptInterface.h" | #include "scriptinterface/ScriptInterface.h" | ||||
#include <sstream> | #include <sstream> | ||||
#include "js/Array.h" | |||||
#include <boost/algorithm/string.hpp> | #include <boost/algorithm/string.hpp> | ||||
#include <boost/algorithm/string/join.hpp> // this isn't in string.hpp in old Boosts | #include <boost/algorithm/string/join.hpp> // this isn't in string.hpp in old Boosts | ||||
static CParamNode g_NullNode(false); | static CParamNode g_NullNode(false); | ||||
CParamNode::CParamNode(bool isOk) : | CParamNode::CParamNode(bool isOk) : | ||||
m_IsOk(isOk) | m_IsOk(isOk) | ||||
{ | { | ||||
▲ Show 20 Lines • Show All 125 Lines • ▼ Show 20 Lines | XERO_ITER_ATTR(element, attr) | ||||
node.m_Value = boost::algorithm::join(tokens, L" "); | node.m_Value = boost::algorithm::join(tokens, L" "); | ||||
hasSetValue = true; | hasSetValue = true; | ||||
break; | break; | ||||
} | } | ||||
} | } | ||||
} | } | ||||
// Add this element as a child node | // Add this element as a child node | ||||
CParamNode& node = m_Childs[name]; | int index = 0; | ||||
for (const auto& child : m_Childs) | |||||
if (child.first.name == name) | |||||
index++; | |||||
CParamNode& node = m_Childs.try_emplace(Node(name, index)).first->second; | |||||
if (op != INVALID) | if (op != INVALID) | ||||
{ | { | ||||
// TODO: Support parsing of data types other than fixed; log warnings in other cases | // TODO: Support parsing of data types other than fixed; log warnings in other cases | ||||
fixed oldval = node.ToFixed(); | fixed oldval = node.ToFixed(); | ||||
fixed mod = fixed::FromString(CStrW(value)); | fixed mod = fixed::FromString(CStrW(value)); | ||||
switch (op) | switch (op) | ||||
{ | { | ||||
▲ Show 20 Lines • Show All 44 Lines • ▼ Show 20 Lines | XERO_ITER_ATTR(element, attr) | ||||
if (attr.Name == at_replace || attr.Name == at_op || attr.Name == at_merge || attr.Name == at_filtered) | if (attr.Name == at_replace || attr.Name == at_op || attr.Name == at_merge || attr.Name == at_filtered) | ||||
continue; | continue; | ||||
// Add any others | // Add any others | ||||
std::string attrName = xmb.GetAttributeString(attr.Name); | std::string attrName = xmb.GetAttributeString(attr.Name); | ||||
node.m_Childs["@" + attrName].m_Value = attr.Value.FromUTF8(); | node.m_Childs["@" + attrName].m_Value = attr.Value.FromUTF8(); | ||||
} | } | ||||
} | } | ||||
void CParamNode::ApplyLayer(const ScriptInterface& scriptInterface, JS::HandleValue value) | |||||
{ | |||||
ResetScriptVal(); | |||||
ScriptRequest rq(scriptInterface); | |||||
std::vector<std::string> props; | |||||
if (!scriptInterface.EnumeratePropertyNames(value, true, props)) | |||||
{ | |||||
ScriptException::Raise(rq, "Failed to enumerate component properties."); | |||||
return; | |||||
} | |||||
for (const std::string& prop : props) | |||||
{ | |||||
LOGWARNING("prop %s", prop); | |||||
JS::RootedValue child(rq.cx); | |||||
scriptInterface.GetProperty(value, prop.c_str(), &child); | |||||
switch (JS_TypeOfValue(rq.cx, child)) | |||||
{ | |||||
case JSTYPE_STRING: | |||||
case JSTYPE_NUMBER: | |||||
{ | |||||
ScriptInterface::FromJSVal(rq, child, m_Childs[prop].m_Value); | |||||
break; | |||||
} | |||||
case JSTYPE_OBJECT: | |||||
{ | |||||
bool isArray = false; | |||||
JS::IsArrayObject(rq.cx, child, &isArray); | |||||
if (!isArray) | |||||
m_Childs[prop].ApplyLayer(scriptInterface, child); | |||||
else | |||||
{ | |||||
JS::RootedObject obj(rq.cx); | |||||
JS_ValueToObject(rq.cx, child, &obj); | |||||
u32 length; | |||||
JS::GetArrayLength(rq.cx, obj, &length); | |||||
for (size_t i = 0; i < length; ++i) | |||||
{ | |||||
JS::RootedValue arrayChild(rq.cx); | |||||
scriptInterface.GetPropertyInt(child, i, &arrayChild); | |||||
m_Childs.try_emplace(Node(prop, i)).first->second.ApplyLayer(scriptInterface, arrayChild); | |||||
} | |||||
} | |||||
break; | |||||
} | |||||
} | |||||
} | |||||
} | |||||
const CParamNode& CParamNode::GetChild(const char* name) const | const CParamNode& CParamNode::GetChild(const char* name) const | ||||
{ | { | ||||
ChildrenMap::const_iterator it = m_Childs.find(name); | ChildrenMap::const_iterator it = m_Childs.find(name); | ||||
if (it == m_Childs.end()) | if (it == m_Childs.end()) | ||||
return g_NullNode; | return g_NullNode; | ||||
return it->second; | return it->second; | ||||
} | } | ||||
▲ Show 20 Lines • Show All 89 Lines • ▼ Show 20 Lines | |||||
void CParamNode::ToXML(std::wostream& strm) const | void CParamNode::ToXML(std::wostream& strm) const | ||||
{ | { | ||||
strm << m_Value; | strm << m_Value; | ||||
ChildrenMap::const_iterator it = m_Childs.begin(); | ChildrenMap::const_iterator it = m_Childs.begin(); | ||||
for (; it != m_Childs.end(); ++it) | for (; it != m_Childs.end(); ++it) | ||||
{ | { | ||||
// Skip attributes here (they were handled when the caller output the tag) | // Skip attributes here (they were handled when the caller output the tag) | ||||
if (it->first.length() && it->first[0] == '@') | if (it->first.attribute) | ||||
continue; | continue; | ||||
std::wstring name (it->first.begin(), it->first.end()); | std::wstring name (it->first.name.begin(), it->first.name.end()); | ||||
strm << L"<" << name; | strm << L"<" << name; | ||||
// Output the child's attributes first | // Output the child's attributes first | ||||
ChildrenMap::const_iterator cit = it->second.m_Childs.begin(); | ChildrenMap::const_iterator cit = it->second.m_Childs.begin(); | ||||
for (; cit != it->second.m_Childs.end(); ++cit) | for (; cit != it->second.m_Childs.end(); ++cit) | ||||
{ | { | ||||
if (cit->first.length() && cit->first[0] == '@') | if (cit->first.attribute) | ||||
{ | { | ||||
std::wstring attrname (cit->first.begin()+1, cit->first.end()); | std::wstring attrname (cit->first.name.begin()+1, cit->first.name.end()); | ||||
strm << L" " << attrname << L"=\"" << EscapeXMLString(cit->second.m_Value) << L"\""; | strm << L" " << attrname << L"=\"" << EscapeXMLString(cit->second.m_Value) << L"\""; | ||||
} | } | ||||
} | } | ||||
strm << L">"; | strm << L">"; | ||||
it->second.ToXML(strm); | it->second.ToXML(strm); | ||||
▲ Show 20 Lines • Show All 44 Lines • ▼ Show 20 Lines | void CParamNode::ConstructJSVal(const ScriptRequest& rq, JS::MutableHandleValue ret) const | ||||
JS::RootedObject obj(rq.cx, JS_NewPlainObject(rq.cx)); | JS::RootedObject obj(rq.cx, JS_NewPlainObject(rq.cx)); | ||||
if (!obj) | if (!obj) | ||||
{ | { | ||||
ret.setUndefined(); | ret.setUndefined(); | ||||
return; // TODO: report error | return; // TODO: report error | ||||
} | } | ||||
JS::RootedValue childVal(rq.cx); | JS::RootedValue childVal(rq.cx); | ||||
for (std::map<std::string, CParamNode>::const_iterator it = m_Childs.begin(); it != m_Childs.end(); ++it) | for (ChildrenMap::const_iterator it = m_Childs.begin(); it != m_Childs.end(); ++it) | ||||
{ | { | ||||
it->second.ConstructJSVal(rq, &childVal); | it->second.ConstructJSVal(rq, &childVal); | ||||
if (!JS_SetProperty(rq.cx, obj, it->first.c_str(), childVal)) | if (!JS_SetProperty(rq.cx, obj, std::string(it->first).c_str(), childVal)) | ||||
{ | { | ||||
ret.setUndefined(); | ret.setUndefined(); | ||||
return; // TODO: report error | return; // TODO: report error | ||||
} | } | ||||
} | } | ||||
// If the node has a string too, add that as an extra property | // If the node has a string too, add that as an extra property | ||||
if (!m_Value.empty()) | if (!m_Value.empty()) | ||||
Show All 24 Lines |
Wildfire Games · Phabricator