diff --git a/source/graphics/MapReader.cpp b/source/graphics/MapReader.cpp index a195f44375..1464dcf494 100644 --- a/source/graphics/MapReader.cpp +++ b/source/graphics/MapReader.cpp @@ -599,7 +599,7 @@ void CXMLReader::ReadTerrain(XMBElement parent) int priority = 0; u16 height = 16384; - XERO_ITER_ATTR(parent, attr) + for (XMBAttribute attr : parent.GetAttributes()) { if (attr.Name == at_patches) patches = attr.Value.ToInt(); diff --git a/source/graphics/ObjectBase.cpp b/source/graphics/ObjectBase.cpp index 198f1c94d3..403dc8d47f 100644 --- a/source/graphics/ObjectBase.cpp +++ b/source/graphics/ObjectBase.cpp @@ -113,7 +113,7 @@ bool CObjectBase::Load(const CXeromyces& XeroFile, const XMBElement& root) // (This XML-reading code is rather worryingly verbose...) auto shouldSkip = [&](XMBElement& node) { - XERO_ITER_ATTR(node, attr) + for (XMBAttribute attr : node.GetAttributes()) { if (attr.Name == at_minquality && GetQuality(attr.Value) > m_QualityLevel) return true; @@ -208,7 +208,7 @@ bool CObjectBase::LoadVariant(const CXeromyces& XeroFile, const XMBElement& vari } // Load variants first, so that they can be overriden if necessary. - XERO_ITER_ATTR(variant, attr) + for (XMBAttribute attr : variant.GetAttributes()) { if (attr.Name == at_file) { @@ -231,7 +231,7 @@ bool CObjectBase::LoadVariant(const CXeromyces& XeroFile, const XMBElement& vari } } - XERO_ITER_ATTR(variant, attr) + for (XMBAttribute attr : variant.GetAttributes()) { if (attr.Name == at_name) currentVariant.m_VariantName = attr.Value.LowerCase(); @@ -258,7 +258,7 @@ bool CObjectBase::LoadVariant(const CXeromyces& XeroFile, const XMBElement& vari } Samp samp; - XERO_ITER_ATTR(textures_element, se) + for (XMBAttribute se : textures_element.GetAttributes()) { if (se.Name == at_file) samp.m_SamplerFile = VfsPath("art/textures/skins") / se.Value.FromUTF8(); @@ -304,7 +304,7 @@ bool CObjectBase::LoadVariant(const CXeromyces& XeroFile, const XMBElement& vari } Anim anim; - XERO_ITER_ATTR(anim_element, ae) + for (XMBAttribute ae : anim_element.GetAttributes()) { if (ae.Name == at_name) anim.m_AnimName = ae.Value; @@ -333,7 +333,7 @@ bool CObjectBase::LoadVariant(const CXeromyces& XeroFile, const XMBElement& vari ENSURE(prop_element.GetNodeName() == el_prop); Prop prop; - XERO_ITER_ATTR(prop_element, pe) + for (XMBAttribute pe : prop_element.GetAttributes()) { if (pe.Name == at_attachpoint) prop.m_PropPointName = pe.Value; @@ -867,7 +867,7 @@ bool CActorDef::Load(const VfsPath& pathname) } else { - XERO_ITER_ATTR(root, attr) + for (XMBAttribute attr : root.GetAttributes()) { if (attr.Name == at_version && attr.Value.ToInt() != 1) { @@ -890,7 +890,7 @@ bool CActorDef::Load(const VfsPath& pathname) bool found_quality = false; bool use_inline = false; CStr file; - XERO_ITER_ATTR(actor, attr) + for (XMBAttribute attr : actor.GetAttributes()) { if (attr.Name == at_quality) { diff --git a/source/graphics/TerrainProperties.cpp b/source/graphics/TerrainProperties.cpp index 86161fcae5..479ef825e4 100644 --- a/source/graphics/TerrainProperties.cpp +++ b/source/graphics/TerrainProperties.cpp @@ -108,7 +108,7 @@ void CTerrainProperties::LoadXml(XMBElement node, CXeromyces *pFile, const VfsPa #undef ELMT #undef ATTR - XERO_ITER_ATTR(node, attr) + for (XMBAttribute attr : node.GetAttributes()) { if (attr.Name == attr_groups) { diff --git a/source/graphics/TerrainTextureEntry.cpp b/source/graphics/TerrainTextureEntry.cpp index 39f89dc935..e5c4e5675a 100644 --- a/source/graphics/TerrainTextureEntry.cpp +++ b/source/graphics/TerrainTextureEntry.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2025 Wildfire Games. +/* Copyright (C) 2026 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -95,7 +95,7 @@ CTerrainTextureEntry::CTerrainTextureEntry(CTerrainPropertiesPtr properties, con CStr name; VfsPath terrainTexturePath; - XERO_ITER_ATTR(textures_element, relativePath) + for (XMBAttribute relativePath : textures_element.GetAttributes()) { if (relativePath.Name == at_file) terrainTexturePath = VfsPath("art/textures/terrain") / relativePath.Value.FromUTF8(); diff --git a/source/graphics/TextureConverter.cpp b/source/graphics/TextureConverter.cpp index e7d66813e0..b8880466e3 100644 --- a/source/graphics/TextureConverter.cpp +++ b/source/graphics/TextureConverter.cpp @@ -170,7 +170,7 @@ CTextureConverter::SettingsFile* CTextureConverter::LoadSettings(const VfsPath& { Match p; - XERO_ITER_ATTR(child, attr) + for (XMBAttribute attr : child.GetAttributes()) { if (attr.Name == at_pattern) { diff --git a/source/gui/ObjectTypes/COList.cpp b/source/gui/ObjectTypes/COList.cpp index 20aefc8995..fa1d2dd692 100644 --- a/source/gui/ObjectTypes/COList.cpp +++ b/source/gui/ObjectTypes/COList.cpp @@ -216,7 +216,7 @@ bool COList::HandleAdditionalChildren(const XMBData& xmb, const XMBElement& chil else if (child.GetNodeName() == elmt_column) { CStr id; - XERO_ITER_ATTR(child, attr) + for (XMBAttribute attr : child.GetAttributes()) { if (attr.Name == attr_id) id = attr.Value; diff --git a/source/ps/XML/XMLWriter.cpp b/source/ps/XML/XMLWriter.cpp index c7a89e11c5..be0931d4bd 100644 --- a/source/ps/XML/XMLWriter.cpp +++ b/source/ps/XML/XMLWriter.cpp @@ -132,7 +132,7 @@ void XMLWriter_File::ElementXMB(const XMBData& xmb, XMBElement el) { XMLWriter_Element writer(*this, xmb.GetElementString(el.GetNodeName())); - XERO_ITER_ATTR(el, attr) + for (XMBAttribute attr : el.GetAttributes()) writer.Attribute(xmb.GetAttributeString(attr.Name), attr.Value); XERO_ITER_EL(el, child) diff --git a/source/ps/XML/Xeromyces.h b/source/ps/XML/Xeromyces.h index 4ed79d1aa0..676d99219d 100644 --- a/source/ps/XML/Xeromyces.h +++ b/source/ps/XML/Xeromyces.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2025 Wildfire Games. +/* Copyright (C) 2026 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -94,7 +94,4 @@ private: #define XERO_ITER_EL(parent_element, child_element) \ for (XMBElement child_element : parent_element.GetChildNodes()) -#define XERO_ITER_ATTR(parent_element, attribute) \ - for (XMBAttribute attribute : parent_element.GetAttributes()) - #endif // INCLUDED_XEROMYCES diff --git a/source/simulation2/system/ParamNode.cpp b/source/simulation2/system/ParamNode.cpp index ed19abd6d2..a8167da5a4 100644 --- a/source/simulation2/system/ParamNode.cpp +++ b/source/simulation2/system/ParamNode.cpp @@ -109,91 +109,87 @@ void CParamNode::ApplyLayer(const XMBData& xmb, const XMBElement& element, const bool replacing = false; bool filtering = false; bool merging = false; + for (XMBAttribute attr : element.GetAttributes()) { - XERO_ITER_ATTR(element, attr) + if (attr.Name == at_disable) { - if (attr.Name == at_disable) - { - m_Childs.erase(name); + m_Childs.erase(name); + return; + } + else if (attr.Name == at_replace) + { + m_Childs.erase(name); + replacing = true; + } + else if (attr.Name == at_filtered) + { + filtering = true; + } + else if (attr.Name == at_merge) + { + if (m_Childs.find(name) == m_Childs.end()) return; - } - else if (attr.Name == at_replace) - { - m_Childs.erase(name); - replacing = true; - } - else if (attr.Name == at_filtered) - { - filtering = true; - } - else if (attr.Name == at_merge) - { - if (m_Childs.find(name) == m_Childs.end()) - return; - merging = true; - } - else if (attr.Name == at_op) - { - if (attr.Value == "add") - op = ADD; - else if (attr.Value == "mul") - op = MUL; - else if (attr.Value == "mul_round") - op = MUL_ROUND; - else - LOGWARNING("Invalid op '%ls'", attr.Value); - } + merging = true; + } + else if (attr.Name == at_op) + { + if (attr.Value == "add") + op = ADD; + else if (attr.Value == "mul") + op = MUL; + else if (attr.Value == "mul_round") + op = MUL_ROUND; + else + LOGWARNING("Invalid op '%ls'", attr.Value); } } + for (XMBAttribute attr : element.GetAttributes()) { - XERO_ITER_ATTR(element, attr) + if (attr.Name == at_datatype && attr.Value == "tokens") { - if (attr.Name == at_datatype && attr.Value == "tokens") + CParamNode& node = m_Childs[name]; + + // Split into tokens + std::vector oldTokens; + std::vector newTokens; + if (!replacing && !node.m_Value.empty()) // ignore the old tokens if replace="" was given + boost::algorithm::split(oldTokens, node.m_Value, boost::algorithm::is_space(), boost::algorithm::token_compress_on); + if (!value.empty()) + boost::algorithm::split(newTokens, value, boost::algorithm::is_space(), boost::algorithm::token_compress_on); + + // Merge the two lists + std::vector tokens = oldTokens; + for (const std::string& newToken : newTokens) { - CParamNode& node = m_Childs[name]; - - // Split into tokens - std::vector oldTokens; - std::vector newTokens; - if (!replacing && !node.m_Value.empty()) // ignore the old tokens if replace="" was given - boost::algorithm::split(oldTokens, node.m_Value, boost::algorithm::is_space(), boost::algorithm::token_compress_on); - if (!value.empty()) - boost::algorithm::split(newTokens, value, boost::algorithm::is_space(), boost::algorithm::token_compress_on); - - // Merge the two lists - std::vector tokens = oldTokens; - for (const std::string& newToken : newTokens) + if (newToken[0] == '-') { - if (newToken[0] == '-') - { - std::vector::iterator tokenIt = - std::find(tokens.begin(), tokens.end(), - std::string_view{newToken}.substr(1)); - if (tokenIt != tokens.end()) - tokens.erase(tokenIt); - else - { - const std::string identifier{ - sourceIdentifier ? (" in '" + - utf8_from_wstring(sourceIdentifier) + "'") : ""}; - LOGWARNING("[ParamNode] Could not remove token " - "'%s' from node '%s'%s; not present in " - "list nor inherited (possible typo?)", - std::string_view{newToken}.substr(1), name, - identifier); - } - } + std::vector::iterator tokenIt = + std::find(tokens.begin(), tokens.end(), + std::string_view{newToken}.substr(1)); + if (tokenIt != tokens.end()) + tokens.erase(tokenIt); else { - if (std::find(oldTokens.begin(), oldTokens.end(), newToken) == oldTokens.end()) - tokens.push_back(newToken); + const std::string identifier{ + sourceIdentifier ? (" in '" + + utf8_from_wstring(sourceIdentifier) + "'") : ""}; + LOGWARNING("[ParamNode] Could not remove token " + "'%s' from node '%s'%s; not present in " + "list nor inherited (possible typo?)", + std::string_view{newToken}.substr(1), name, + identifier); } } - - node.m_Value = boost::algorithm::join(tokens, " "); - hasSetValue = true; - break; + else + { + if (std::find(oldTokens.begin(), oldTokens.end(), newToken) == oldTokens.end()) + tokens.push_back(newToken); + } } + + node.m_Value = boost::algorithm::join(tokens, " "); + hasSetValue = true; + break; } } @@ -248,7 +244,7 @@ void CParamNode::ApplyLayer(const XMBData& xmb, const XMBElement& element, const node.m_Childs.swap(childs); // Add the element's attributes, prefixing names with "@" - XERO_ITER_ATTR(element, attr) + for (XMBAttribute attr : element.GetAttributes()) { // Skip special attributes if (attr.Name == at_replace || attr.Name == at_op || attr.Name == at_merge || attr.Name == at_filtered)