Use iterators for XMBAttributeList and XMBElementList. Fixes #3269.
This was SVN commit r16704.
This commit is contained in:
parent
d3da00dc99
commit
f71be3c764
@ -442,8 +442,8 @@ private:
|
||||
XMBElementList nodes; // children of root
|
||||
|
||||
// loop counters
|
||||
int node_idx;
|
||||
int entity_idx;
|
||||
size_t node_idx;
|
||||
size_t entity_idx;
|
||||
|
||||
// # entities+nonentities processed and total (for progress calc)
|
||||
int completed_jobs, total_jobs;
|
||||
@ -500,8 +500,8 @@ void CXMLReader::Init(const VfsPath& xml_filename)
|
||||
// (used when calculating progress)
|
||||
completed_jobs = 0;
|
||||
total_jobs = 0;
|
||||
for (int i = 0; i < nodes.Count; i++)
|
||||
total_jobs += nodes.Item(i).GetChildNodes().Count;
|
||||
for (XMBElement node : nodes)
|
||||
total_jobs += node.GetChildNodes().size();
|
||||
|
||||
// Find the maximum entity ID, so we can safely allocate new IDs without conflicts
|
||||
|
||||
@ -967,12 +967,12 @@ int CXMLReader::ReadEntities(XMBElement parent, double end_time)
|
||||
CSimulation2& sim = *m_MapReader.pSimulation2;
|
||||
CmpPtr<ICmpPlayerManager> cmpPlayerManager(sim, SYSTEM_ENTITY);
|
||||
|
||||
while (entity_idx < entities.Count)
|
||||
while (entity_idx < entities.size())
|
||||
{
|
||||
// all new state at this scope and below doesn't need to be
|
||||
// wrapped, since we only yield after a complete iteration.
|
||||
|
||||
XMBElement entity = entities.Item(entity_idx++);
|
||||
XMBElement entity = entities[entity_idx++];
|
||||
ENSURE(entity.GetNodeName() == el_entity);
|
||||
|
||||
XMBAttributeList attrs = entity.GetAttributes();
|
||||
@ -1100,9 +1100,8 @@ int CXMLReader::ReadEntities(XMBElement parent, double end_time)
|
||||
|
||||
void CXMLReader::ReadXML()
|
||||
{
|
||||
for (int i = 0; i < nodes.Count; ++i)
|
||||
for (XMBElement node : nodes)
|
||||
{
|
||||
XMBElement node = nodes.Item(i);
|
||||
CStr name = xmb_file.GetElementString(node.GetNodeName());
|
||||
if (name == "Terrain")
|
||||
{
|
||||
@ -1153,9 +1152,9 @@ int CXMLReader::ProgressiveReadEntities()
|
||||
|
||||
int ret;
|
||||
|
||||
while (node_idx < nodes.Count)
|
||||
while (node_idx < nodes.size())
|
||||
{
|
||||
XMBElement node = nodes.Item(node_idx);
|
||||
XMBElement node = nodes[node_idx];
|
||||
CStr name = xmb_file.GetElementString(node.GetNodeName());
|
||||
if (name == "Entities")
|
||||
{
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2013 Wildfire Games.
|
||||
/* Copyright (C) 2015 Wildfire Games.
|
||||
* This file is part of 0 A.D.
|
||||
*
|
||||
* 0 A.D. is free software: you can redistribute it and/or modify
|
||||
@ -109,9 +109,7 @@ bool CObjectBase::Load(const VfsPath& pathname)
|
||||
XERO_ITER_EL(root, child)
|
||||
{
|
||||
if (child.GetNodeName() == el_group)
|
||||
{
|
||||
variantGroupSizes.push_back(child.GetChildNodes().Count);
|
||||
}
|
||||
variantGroupSizes.push_back(child.GetChildNodes().size());
|
||||
}
|
||||
|
||||
m_VariantGroups.resize(variantGroupSizes.size());
|
||||
|
@ -989,12 +989,8 @@ void CGUI::Xeromyces_ReadRootObjects(XMBElement Element, CXeromyces* pFile, boos
|
||||
|
||||
// Iterate main children
|
||||
// they should all be <object> or <script> elements
|
||||
XMBElementList children = Element.GetChildNodes();
|
||||
for (int i=0; i<children.Count; ++i)
|
||||
for (XMBElement child : Element.GetChildNodes())
|
||||
{
|
||||
//debug_printf("Object %d\n", i);
|
||||
XMBElement child = children.Item(i);
|
||||
|
||||
if (child.GetNodeName() == el_script)
|
||||
// Execute the inline script
|
||||
Xeromyces_ReadScript(child, pFile, Paths);
|
||||
@ -1008,39 +1004,26 @@ void CGUI::Xeromyces_ReadRootSprites(XMBElement Element, CXeromyces* pFile)
|
||||
{
|
||||
// Iterate main children
|
||||
// they should all be <sprite> elements
|
||||
XMBElementList children = Element.GetChildNodes();
|
||||
for (int i=0; i<children.Count; ++i)
|
||||
{
|
||||
XMBElement child = children.Item(i);
|
||||
|
||||
for (XMBElement child : Element.GetChildNodes())
|
||||
// Read in this whole object into the GUI
|
||||
Xeromyces_ReadSprite(child, pFile);
|
||||
}
|
||||
}
|
||||
|
||||
void CGUI::Xeromyces_ReadRootStyles(XMBElement Element, CXeromyces* pFile)
|
||||
{
|
||||
// Iterate main children
|
||||
// they should all be <styles> elements
|
||||
XMBElementList children = Element.GetChildNodes();
|
||||
for (int i=0; i<children.Count; ++i)
|
||||
{
|
||||
XMBElement child = children.Item(i);
|
||||
|
||||
for (XMBElement child : Element.GetChildNodes())
|
||||
// Read in this whole object into the GUI
|
||||
Xeromyces_ReadStyle(child, pFile);
|
||||
}
|
||||
}
|
||||
|
||||
void CGUI::Xeromyces_ReadRootSetup(XMBElement Element, CXeromyces* pFile)
|
||||
{
|
||||
// Iterate main children
|
||||
// they should all be <icon>, <scrollbar> or <tooltip>.
|
||||
XMBElementList children = Element.GetChildNodes();
|
||||
for (int i=0; i<children.Count; ++i)
|
||||
for (XMBElement child : Element.GetChildNodes())
|
||||
{
|
||||
XMBElement child = children.Item(i);
|
||||
|
||||
// Read in this whole object into the GUI
|
||||
|
||||
CStr name(pFile->GetElementString(child.GetNodeName()));
|
||||
@ -1074,7 +1057,6 @@ void CGUI::Xeromyces_ReadRootSetup(XMBElement Element, CXeromyces* pFile)
|
||||
void CGUI::Xeromyces_ReadObject(XMBElement Element, CXeromyces* pFile, IGUIObject *pParent, std::vector<std::pair<CStr, CStr> >& NameSubst, boost::unordered_set<VfsPath>& Paths, u32 nesting_depth)
|
||||
{
|
||||
ENSURE(pParent);
|
||||
int i;
|
||||
|
||||
// Our object we are going to create
|
||||
IGUIObject *object = NULL;
|
||||
@ -1152,10 +1134,8 @@ void CGUI::Xeromyces_ReadObject(XMBElement Element, CXeromyces* pFile, IGUIObjec
|
||||
CStr hotkeyTag;
|
||||
|
||||
// Now we can iterate all attributes and store
|
||||
for (i=0; i<attributes.Count; ++i)
|
||||
for (XMBAttribute attr : attributes)
|
||||
{
|
||||
XMBAttribute attr = attributes.Item(i);
|
||||
|
||||
// If value is "null", then it is equivalent as never being entered
|
||||
if (CStr(attr.Value) == "null")
|
||||
continue;
|
||||
@ -1219,14 +1199,8 @@ void CGUI::Xeromyces_ReadObject(XMBElement Element, CXeromyces* pFile, IGUIObjec
|
||||
// Read Children
|
||||
//
|
||||
|
||||
XMBElementList children = Element.GetChildNodes();
|
||||
|
||||
// Iterate children
|
||||
for (i=0; i<children.Count; ++i)
|
||||
for (XMBElement child : Element.GetChildNodes())
|
||||
{
|
||||
// Get node
|
||||
XMBElement child = children.Item(i);
|
||||
|
||||
// Check what name the elements got
|
||||
int element_name = child.GetNodeName();
|
||||
|
||||
@ -1259,26 +1233,17 @@ void CGUI::Xeromyces_ReadObject(XMBElement Element, CXeromyces* pFile, IGUIObjec
|
||||
}
|
||||
|
||||
XMBElementList grandchildren = child.GetChildNodes();
|
||||
if (grandchildren.Count > 0) // The <action> element contains <keep> and <translate> tags.
|
||||
{
|
||||
for (int i = 0; i < grandchildren.Count; ++i)
|
||||
if (!grandchildren.empty()) // The <action> element contains <keep> and <translate> tags.
|
||||
for (XMBElement grandchild : grandchildren)
|
||||
{
|
||||
XMBElement grandchild = grandchildren.Item(i);
|
||||
if (grandchild.GetNodeName() == elmt_translate)
|
||||
{
|
||||
code += g_L10n.Translate(grandchild.GetText());
|
||||
}
|
||||
else if (grandchild.GetNodeName() == elmt_keep)
|
||||
{
|
||||
code += grandchild.GetText();
|
||||
}
|
||||
}
|
||||
}
|
||||
else // It’s pure JavaScript code.
|
||||
{
|
||||
// Read the inline code (concatenating to the file code, if both are specified)
|
||||
code += CStr(child.GetText());
|
||||
}
|
||||
|
||||
CStr action = CStr(child.GetAttributes().GetNamedItem(attr_on));
|
||||
|
||||
@ -1329,18 +1294,12 @@ void CGUI::Xeromyces_ReadObject(XMBElement Element, CXeromyces* pFile, IGUIObjec
|
||||
|
||||
CStr translatedValue;
|
||||
|
||||
XMBElementList grandchildren = child.GetChildNodes();
|
||||
for (int i = 0; i < grandchildren.Count; ++i)
|
||||
for (XMBElement grandchild : child.GetChildNodes())
|
||||
{
|
||||
XMBElement grandchild = grandchildren.Item(i);
|
||||
if (grandchild.GetNodeName() == elmt_translate)
|
||||
{
|
||||
translatedValue += g_L10n.Translate(grandchild.GetText());
|
||||
}
|
||||
else if (grandchild.GetNodeName() == elmt_keep)
|
||||
{
|
||||
translatedValue += grandchild.GetText();
|
||||
}
|
||||
}
|
||||
object->SetSetting(attributeName, translatedValue.FromUTF8(), true);
|
||||
}
|
||||
@ -1565,14 +1524,8 @@ void CGUI::Xeromyces_ReadSprite(XMBElement Element, CXeromyces* pFile)
|
||||
|
||||
SGUIImageEffects* effects = NULL;
|
||||
|
||||
// Iterate children
|
||||
XMBElementList children = Element.GetChildNodes();
|
||||
|
||||
for (int i=0; i<children.Count; ++i)
|
||||
for (XMBElement child : Element.GetChildNodes())
|
||||
{
|
||||
// Get node
|
||||
XMBElement child = children.Item(i);
|
||||
|
||||
CStr ElementName(pFile->GetElementString(child.GetNodeName()));
|
||||
|
||||
if (ElementName == "image")
|
||||
@ -1630,10 +1583,8 @@ void CGUI::Xeromyces_ReadImage(XMBElement Element, CXeromyces* pFile, CGUISprite
|
||||
//
|
||||
|
||||
// Now we can iterate all attributes and store
|
||||
XMBAttributeList attributes = Element.GetAttributes();
|
||||
for (int i=0; i<attributes.Count; ++i)
|
||||
for (XMBAttribute attr : Element.GetAttributes())
|
||||
{
|
||||
XMBAttribute attr = attributes.Item(i);
|
||||
CStr attr_name(pFile->GetAttributeString(attr.Name));
|
||||
CStrW attr_value(attr.Value.FromUTF8());
|
||||
|
||||
@ -1740,10 +1691,8 @@ void CGUI::Xeromyces_ReadImage(XMBElement Element, CXeromyces* pFile, CGUISprite
|
||||
}
|
||||
|
||||
// Look for effects
|
||||
XMBElementList children = Element.GetChildNodes();
|
||||
for (int i=0; i<children.Count; ++i)
|
||||
for (XMBElement child : Element.GetChildNodes())
|
||||
{
|
||||
XMBElement child = children.Item(i);
|
||||
CStr ElementName(pFile->GetElementString(child.GetNodeName()));
|
||||
if (ElementName == "effect")
|
||||
{
|
||||
@ -1772,10 +1721,8 @@ void CGUI::Xeromyces_ReadImage(XMBElement Element, CXeromyces* pFile, CGUISprite
|
||||
|
||||
void CGUI::Xeromyces_ReadEffects(XMBElement Element, CXeromyces* pFile, SGUIImageEffects &effects)
|
||||
{
|
||||
XMBAttributeList attributes = Element.GetAttributes();
|
||||
for (int i=0; i<attributes.Count; ++i)
|
||||
for (XMBAttribute attr : Element.GetAttributes())
|
||||
{
|
||||
XMBAttribute attr = attributes.Item(i);
|
||||
CStr attr_name(pFile->GetAttributeString(attr.Name));
|
||||
CStrW attr_value(attr.Value.FromUTF8());
|
||||
|
||||
@ -1808,10 +1755,8 @@ void CGUI::Xeromyces_ReadStyle(XMBElement Element, CXeromyces* pFile)
|
||||
//
|
||||
|
||||
// Now we can iterate all attributes and store
|
||||
XMBAttributeList attributes = Element.GetAttributes();
|
||||
for (int i=0; i<attributes.Count; ++i)
|
||||
for (XMBAttribute attr : Element.GetAttributes())
|
||||
{
|
||||
XMBAttribute attr = attributes.Item(i);
|
||||
CStr attr_name(pFile->GetAttributeString(attr.Name));
|
||||
|
||||
// The "name" setting is actually the name of the style
|
||||
@ -1846,10 +1791,8 @@ void CGUI::Xeromyces_ReadScrollBarStyle(XMBElement Element, CXeromyces* pFile)
|
||||
//
|
||||
|
||||
// Now we can iterate all attributes and store
|
||||
XMBAttributeList attributes = Element.GetAttributes();
|
||||
for (int i=0; i<attributes.Count; ++i)
|
||||
for (XMBAttribute attr : Element.GetAttributes())
|
||||
{
|
||||
XMBAttribute attr = attributes.Item(i);
|
||||
CStr attr_name = pFile->GetAttributeString(attr.Name);
|
||||
CStr attr_value(attr.Value);
|
||||
|
||||
@ -1944,10 +1887,8 @@ void CGUI::Xeromyces_ReadIcon(XMBElement Element, CXeromyces* pFile)
|
||||
SGUIIcon icon;
|
||||
CStr name;
|
||||
|
||||
XMBAttributeList attributes = Element.GetAttributes();
|
||||
for (int i=0; i<attributes.Count; ++i)
|
||||
for (XMBAttribute attr : Element.GetAttributes())
|
||||
{
|
||||
XMBAttribute attr = attributes.Item(i);
|
||||
CStr attr_name(pFile->GetAttributeString(attr.Name));
|
||||
CStr attr_value(attr.Value);
|
||||
|
||||
@ -1989,10 +1930,8 @@ void CGUI::Xeromyces_ReadTooltip(XMBElement Element, CXeromyces* pFile)
|
||||
|
||||
IGUIObject* object = new CTooltip;
|
||||
|
||||
XMBAttributeList attributes = Element.GetAttributes();
|
||||
for (int i=0; i<attributes.Count; ++i)
|
||||
for (XMBAttribute attr : Element.GetAttributes())
|
||||
{
|
||||
XMBAttribute attr = attributes.Item(i);
|
||||
CStr attr_name(pFile->GetAttributeString(attr.Name));
|
||||
CStr attr_value(attr.Value);
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2014 Wildfire Games.
|
||||
/* Copyright (C) 2015 Wildfire Games.
|
||||
* This file is part of 0 A.D.
|
||||
*
|
||||
* 0 A.D. is free software: you can redistribute it and/or modify
|
||||
@ -147,10 +147,8 @@ bool COList::HandleAdditionalChildren(const XMBElement& child, CXeromyces* pFile
|
||||
{
|
||||
ObjectDef oDef;
|
||||
|
||||
XMBAttributeList attributes = child.GetAttributes();
|
||||
for (int i=0; i<attributes.Count; ++i)
|
||||
for (XMBAttribute attr : child.GetAttributes())
|
||||
{
|
||||
XMBAttribute attr = attributes.Item(i);
|
||||
CStr attr_name (pFile->GetAttributeString(attr.Name));
|
||||
CStr attr_value (attr.Value);
|
||||
|
||||
@ -187,10 +185,8 @@ bool COList::HandleAdditionalChildren(const XMBElement& child, CXeromyces* pFile
|
||||
|
||||
}
|
||||
|
||||
XMBElementList grandchildren = child.GetChildNodes();
|
||||
for (int i = 0; i < grandchildren.Count; ++i)
|
||||
for (XMBElement grandchild : child.GetChildNodes())
|
||||
{
|
||||
XMBElement grandchild = grandchildren.Item(i);
|
||||
if (grandchild.GetNodeName() == elmt_translatableAttribute)
|
||||
{
|
||||
CStr attributeName(grandchild.GetAttributes().GetNamedItem(attr_id));
|
||||
|
@ -1145,20 +1145,17 @@ CStr8 LoadSettingsOfScenarioMap(const VfsPath &mapPath)
|
||||
XMBElement mapElement = mapFile.GetRoot();
|
||||
|
||||
// Select the ScriptSettings node in the map file...
|
||||
for (int i = 0; pathToSettings[i][0]; i++)
|
||||
for (int i = 0; pathToSettings[i][0]; ++i)
|
||||
{
|
||||
int childId = mapFile.GetElementID(pathToSettings[i]);
|
||||
|
||||
XMBElementList children = mapElement.GetChildNodes();
|
||||
for (int childIndex = 0; childIndex < children.Count; childIndex++)
|
||||
{
|
||||
XMBElement child = children.Item(childIndex);
|
||||
if (child.GetNodeName() == childId)
|
||||
{
|
||||
mapElement = child;
|
||||
break;
|
||||
}
|
||||
}
|
||||
XMBElementList nodes = mapElement.GetChildNodes();
|
||||
auto it = std::find_if(nodes.begin(), nodes.end(), [&childId](const XMBElement& child) {
|
||||
return child.GetNodeName() == childId;
|
||||
});
|
||||
|
||||
if (it != nodes.end())
|
||||
mapElement = *it;
|
||||
}
|
||||
// ... they contain a JSON document to initialize the game setup
|
||||
// screen
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2014 Wildfire Games.
|
||||
/* Copyright (C) 2015 Wildfire Games.
|
||||
* This file is part of 0 A.D.
|
||||
*
|
||||
* 0 A.D. is free software: you can redistribute it and/or modify
|
||||
@ -187,22 +187,24 @@ int XMBElement::GetNodeName() const
|
||||
XMBElementList XMBElement::GetChildNodes() const
|
||||
{
|
||||
if (m_Pointer == NULL)
|
||||
return XMBElementList(NULL, 0);
|
||||
return XMBElementList(NULL, 0, NULL);
|
||||
|
||||
return XMBElementList(
|
||||
m_Pointer + 20 + read<int>(m_Pointer + 16), // == Children[]
|
||||
read<int>(m_Pointer + 12) // == ChildCount
|
||||
read<int>(m_Pointer + 12), // == ChildCount
|
||||
m_Pointer + read<int>(m_Pointer) // == &Children[ChildCount]
|
||||
);
|
||||
}
|
||||
|
||||
XMBAttributeList XMBElement::GetAttributes() const
|
||||
{
|
||||
if (m_Pointer == NULL)
|
||||
return XMBAttributeList(NULL, 0);
|
||||
return XMBAttributeList(NULL, 0, NULL);
|
||||
|
||||
return XMBAttributeList(
|
||||
m_Pointer + 24 + read<int>(m_Pointer + 20), // == Attributes[]
|
||||
read<int>(m_Pointer + 8) // == AttributeCount
|
||||
read<int>(m_Pointer + 8), // == AttributeCount
|
||||
m_Pointer + 20 + read<int>(m_Pointer + 16) // == &Attributes[AttributeCount] ( == &Children[])
|
||||
);
|
||||
}
|
||||
|
||||
@ -230,7 +232,7 @@ XMBElement XMBElementList::GetFirstNamedItem(const int ElementName) const
|
||||
|
||||
// Maybe not the cleverest algorithm, but it should be
|
||||
// fast enough with half a dozen attributes:
|
||||
for (int i = 0; i < Count; ++i)
|
||||
for (size_t i = 0; i < m_Size; ++i)
|
||||
{
|
||||
int Length = read<int>(Pos);
|
||||
int Name = read<int>(Pos+4);
|
||||
@ -243,28 +245,39 @@ XMBElement XMBElementList::GetFirstNamedItem(const int ElementName) const
|
||||
return XMBElement();
|
||||
}
|
||||
|
||||
XMBElement XMBElementList::Item(const int id)
|
||||
XMBElementList::iterator& XMBElementList::iterator::operator++()
|
||||
{
|
||||
ENSURE(id >= 0 && id < Count && "Element ID out of range");
|
||||
const char* Pos;
|
||||
m_CurPointer += read<int>(m_CurPointer);
|
||||
++m_CurItemID;
|
||||
return (*this);
|
||||
}
|
||||
|
||||
// If access is sequential, don't bother scanning
|
||||
// through all the nodes to find the next one
|
||||
if (id == m_LastItemID+1)
|
||||
XMBElement XMBElementList::operator[](size_t id)
|
||||
{
|
||||
ENSURE(id < m_Size && "Element ID out of range");
|
||||
const char* Pos;
|
||||
size_t i;
|
||||
|
||||
if (id < m_CurItemID)
|
||||
{
|
||||
Pos = m_LastPointer;
|
||||
Pos += read<int>(Pos); // skip over the last node
|
||||
Pos = m_Pointer;
|
||||
i = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
Pos = m_Pointer;
|
||||
// Skip over each preceding node
|
||||
for (int i=0; i<id; ++i)
|
||||
Pos += read<int>(Pos);
|
||||
// If access is sequential, don't bother scanning
|
||||
// through all the nodes to find the next one
|
||||
Pos = m_CurPointer;
|
||||
i = m_CurItemID;
|
||||
}
|
||||
|
||||
// Skip over each preceding node
|
||||
for (; i < id; ++i)
|
||||
Pos += read<int>(Pos);
|
||||
|
||||
// Cache information about this node
|
||||
m_LastItemID = id;
|
||||
m_LastPointer = Pos;
|
||||
m_CurItemID = id;
|
||||
m_CurPointer = Pos;
|
||||
|
||||
return XMBElement(Pos);
|
||||
}
|
||||
@ -275,7 +288,7 @@ CStr8 XMBAttributeList::GetNamedItem(const int AttributeName) const
|
||||
|
||||
// Maybe not the cleverest algorithm, but it should be
|
||||
// fast enough with half a dozen attributes:
|
||||
for (int i = 0; i < Count; ++i)
|
||||
for (size_t i = 0; i < m_Size; ++i)
|
||||
{
|
||||
if (read<int>(Pos) == AttributeName)
|
||||
return CStr8(Pos+8);
|
||||
@ -286,29 +299,44 @@ CStr8 XMBAttributeList::GetNamedItem(const int AttributeName) const
|
||||
return CStr8();
|
||||
}
|
||||
|
||||
XMBAttribute XMBAttributeList::Item(const int id)
|
||||
XMBAttribute XMBAttributeList::iterator::operator*() const
|
||||
{
|
||||
ENSURE(id >= 0 && id < Count && "Attribute ID out of range");
|
||||
const char* Pos;
|
||||
return XMBAttribute(read<int>(m_CurPointer), CStr8(m_CurPointer+8));
|
||||
}
|
||||
|
||||
// If access is sequential, don't bother scanning through
|
||||
// all the nodes to find the right one
|
||||
if (id == m_LastItemID+1)
|
||||
XMBAttributeList::iterator& XMBAttributeList::iterator::operator++()
|
||||
{
|
||||
m_CurPointer += 8 + read<int>(m_CurPointer+4); // skip ID, length, and string data
|
||||
++m_CurItemID;
|
||||
return (*this);
|
||||
}
|
||||
|
||||
XMBAttribute XMBAttributeList::operator[](size_t id)
|
||||
{
|
||||
ENSURE(id < m_Size && "Attribute ID out of range");
|
||||
const char* Pos;
|
||||
size_t i;
|
||||
|
||||
if (id < m_CurItemID)
|
||||
{
|
||||
Pos = m_LastPointer;
|
||||
// Skip over the last attribute
|
||||
Pos += 8 + read<int>(Pos+4);
|
||||
Pos = m_Pointer;
|
||||
i = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
Pos = m_Pointer;
|
||||
// Skip over each preceding attribute
|
||||
for (int i=0; i<id; ++i)
|
||||
Pos += 8 + read<int>(Pos+4); // skip ID, length, and string data
|
||||
// If access is sequential, don't bother scanning
|
||||
// through all the nodes to find the next one
|
||||
Pos = m_CurPointer;
|
||||
i = m_CurItemID;
|
||||
}
|
||||
|
||||
// Skip over each preceding attribute
|
||||
for (; i < id; ++i)
|
||||
Pos += 8 + read<int>(Pos+4); // skip ID, length, and string data
|
||||
|
||||
// Cache information about this attribute
|
||||
m_LastItemID = id;
|
||||
m_LastPointer = Pos;
|
||||
m_CurItemID = id;
|
||||
m_CurPointer = Pos;
|
||||
|
||||
return XMBAttribute(read<int>(Pos), CStr8(Pos+8));
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2014 Wildfire Games.
|
||||
/* Copyright (C) 2015 Wildfire Games.
|
||||
* This file is part of 0 A.D.
|
||||
*
|
||||
* 0 A.D. is free software: you can redistribute it and/or modify
|
||||
@ -182,28 +182,62 @@ private:
|
||||
class XMBElementList
|
||||
{
|
||||
public:
|
||||
XMBElementList()
|
||||
: Count(0), m_Pointer(0), m_LastItemID(-2) {}
|
||||
|
||||
XMBElementList(const char* offset, int count)
|
||||
: Count(count),
|
||||
m_Pointer(offset),
|
||||
m_LastItemID(-2) {} // use -2 because it isn't x-1 where x is a non-negative integer
|
||||
XMBElementList() : XMBElementList(NULL, 0, NULL) {}
|
||||
XMBElementList(const char* offset, size_t count, const char* endoffset)
|
||||
: m_Size(count), m_Pointer(offset), m_CurItemID(0), m_CurPointer(offset), m_EndPointer(endoffset) {}
|
||||
|
||||
// Get first element in list with the given name.
|
||||
// Performance is linear in the number of elements in the list.
|
||||
XMBElement GetFirstNamedItem(const int ElementName) const;
|
||||
|
||||
XMBElement Item(const int id); // returns Children[id]
|
||||
// Linear in the number of elements in the list
|
||||
XMBElement operator[](size_t id); // returns Children[id]
|
||||
|
||||
int Count;
|
||||
class iterator
|
||||
{
|
||||
public:
|
||||
typedef ptrdiff_t difference_type;
|
||||
typedef XMBElement value_type;
|
||||
typedef XMBElement reference; // Because we need to construct the object
|
||||
typedef XMBElement pointer; // Because we need to construct the object
|
||||
typedef std::forward_iterator_tag iterator_category;
|
||||
|
||||
iterator() : iterator(0, NULL) {}
|
||||
iterator(size_t size, const char* ptr, const char* endptr = NULL)
|
||||
: m_Size(size), m_CurItemID(endptr ? size : 0), m_CurPointer(endptr ? endptr : ptr), m_Pointer(ptr) {}
|
||||
XMBElement operator*() const { return XMBElement(m_CurPointer); }
|
||||
XMBElement operator->() const { return **this; }
|
||||
iterator& operator++();
|
||||
|
||||
bool operator==(const iterator& rhs) const
|
||||
{
|
||||
return m_Size == rhs.m_Size &&
|
||||
m_CurItemID == rhs.m_CurItemID &&
|
||||
m_CurPointer == rhs.m_CurPointer;
|
||||
}
|
||||
bool operator!=(const iterator& rhs) const { return !(*this == rhs); }
|
||||
private:
|
||||
size_t m_Size;
|
||||
size_t m_CurItemID;
|
||||
const char* m_CurPointer;
|
||||
const char* m_Pointer;
|
||||
};
|
||||
iterator begin() { return iterator(m_Size, m_Pointer); }
|
||||
iterator end() { return iterator(m_Size, m_Pointer, m_EndPointer); }
|
||||
|
||||
size_t size() const { return m_Size; }
|
||||
bool empty() const { return m_Size == 0; }
|
||||
|
||||
private:
|
||||
size_t m_Size;
|
||||
|
||||
const char* m_Pointer;
|
||||
|
||||
// For optimised sequential access:
|
||||
int m_LastItemID;
|
||||
const char* m_LastPointer;
|
||||
size_t m_CurItemID;
|
||||
const char* m_CurPointer;
|
||||
|
||||
const char* m_EndPointer;
|
||||
};
|
||||
|
||||
|
||||
@ -220,24 +254,61 @@ struct XMBAttribute
|
||||
class XMBAttributeList
|
||||
{
|
||||
public:
|
||||
XMBAttributeList(const char* offset, int count)
|
||||
: Count(count), m_Pointer(offset), m_LastItemID(-2) {};
|
||||
XMBAttributeList(const char* offset, size_t count, const char* endoffset)
|
||||
: m_Size(count), m_Pointer(offset), m_CurItemID(0), m_CurPointer(offset), m_EndPointer(endoffset) {}
|
||||
|
||||
// Get the attribute value directly
|
||||
CStr8 GetNamedItem(const int AttributeName) const;
|
||||
|
||||
// Returns an attribute by position in the list
|
||||
XMBAttribute Item(const int id);
|
||||
// Linear in the number of elements in the list
|
||||
XMBAttribute operator[](size_t id); // returns Children[id]
|
||||
|
||||
int Count;
|
||||
class iterator
|
||||
{
|
||||
public:
|
||||
typedef ptrdiff_t difference_type;
|
||||
typedef XMBAttribute value_type;
|
||||
typedef XMBAttribute reference; // Because we need to construct the object
|
||||
typedef XMBAttribute pointer; // Because we need to construct the object
|
||||
typedef std::forward_iterator_tag iterator_category;
|
||||
|
||||
iterator() : iterator(0, NULL) {}
|
||||
iterator(size_t size, const char* ptr, const char* endptr = NULL)
|
||||
: m_Size(size), m_CurItemID(endptr ? size : 0), m_CurPointer(endptr ? endptr : ptr), m_Pointer(ptr) {}
|
||||
XMBAttribute operator*() const;
|
||||
XMBAttribute operator->() const { return **this; }
|
||||
iterator& operator++();
|
||||
|
||||
bool operator==(const iterator& rhs) const
|
||||
{
|
||||
return m_Size == rhs.m_Size &&
|
||||
m_CurItemID == rhs.m_CurItemID &&
|
||||
m_CurPointer == rhs.m_CurPointer;
|
||||
}
|
||||
bool operator!=(const iterator& rhs) const { return !(*this == rhs); }
|
||||
private:
|
||||
size_t m_Size;
|
||||
size_t m_CurItemID;
|
||||
const char* m_CurPointer;
|
||||
const char* m_Pointer;
|
||||
};
|
||||
iterator begin() const { return iterator(m_Size, m_Pointer); }
|
||||
iterator end() const { return iterator(m_Size, m_Pointer, m_EndPointer); }
|
||||
|
||||
size_t size() const { return m_Size; }
|
||||
bool empty() const { return m_Size == 0; }
|
||||
|
||||
private:
|
||||
size_t m_Size;
|
||||
|
||||
// Pointer to start of attribute list
|
||||
const char* m_Pointer;
|
||||
|
||||
// For optimised sequential access:
|
||||
int m_LastItemID;
|
||||
const char* m_LastPointer;
|
||||
size_t m_CurItemID;
|
||||
const char* m_CurPointer;
|
||||
|
||||
const char* m_EndPointer;
|
||||
};
|
||||
|
||||
#endif // INCLUDED_XEROXMB
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2010 Wildfire Games.
|
||||
/* Copyright (C) 2015 Wildfire Games.
|
||||
* This file is part of 0 A.D.
|
||||
*
|
||||
* 0 A.D. is free software: you can redistribute it and/or modify
|
||||
@ -89,19 +89,9 @@ private:
|
||||
#define _XERO_I _XERO_MAKE_UID1__(_i_, __LINE__)
|
||||
|
||||
#define XERO_ITER_EL(parent_element, child_element) \
|
||||
XMBElementList _XERO_CHILDREN = parent_element.GetChildNodes(); \
|
||||
XMBElement child_element (0); \
|
||||
for (int _XERO_I = 0; \
|
||||
_XERO_I < _XERO_CHILDREN.Count \
|
||||
&& (child_element = _XERO_CHILDREN.Item(_XERO_I), 1); \
|
||||
++_XERO_I)
|
||||
for (XMBElement child_element : parent_element.GetChildNodes())
|
||||
|
||||
#define XERO_ITER_ATTR(parent_element, attribute) \
|
||||
XMBAttributeList _XERO_CHILDREN = parent_element.GetAttributes(); \
|
||||
XMBAttribute attribute; \
|
||||
for (int _XERO_I = 0; \
|
||||
_XERO_I < _XERO_CHILDREN.Count \
|
||||
&& (attribute = _XERO_CHILDREN.Item(_XERO_I), 1); \
|
||||
++_XERO_I)
|
||||
for (XMBAttribute attribute : parent_element.GetAttributes())
|
||||
|
||||
#endif // INCLUDED_XEROMYCES
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2009 Wildfire Games.
|
||||
/* Copyright (C) 2015 Wildfire Games.
|
||||
* This file is part of 0 A.D.
|
||||
*
|
||||
* 0 A.D. is free software: you can redistribute it and/or modify
|
||||
@ -71,17 +71,17 @@ public:
|
||||
TS_ASSERT_EQUALS(root.GetLineNumber(), -1);
|
||||
TS_ASSERT_EQUALS(CStr(root.GetText()), "");
|
||||
|
||||
TS_ASSERT_EQUALS(root.GetChildNodes().Count, 2);
|
||||
XMBElement child = root.GetChildNodes().Item(0);
|
||||
TS_ASSERT_EQUALS(root.GetChildNodes().size(), 2);
|
||||
XMBElement child = root.GetChildNodes()[0];
|
||||
TS_ASSERT_EQUALS(child.GetNodeName(), el_foo);
|
||||
TS_ASSERT_EQUALS(child.GetLineNumber(), 2);
|
||||
TS_ASSERT_EQUALS(child.GetChildNodes().Count, 0);
|
||||
TS_ASSERT_EQUALS(child.GetChildNodes().size(), 0);
|
||||
TS_ASSERT_EQUALS(CStr(child.GetText()), "bar");
|
||||
|
||||
TS_ASSERT_EQUALS(root.GetChildNodes().Item(1).GetLineNumber(), 5);
|
||||
TS_ASSERT_EQUALS(root.GetChildNodes()[1].GetLineNumber(), 5);
|
||||
|
||||
TS_ASSERT_EQUALS(child.GetAttributes().Count, 1);
|
||||
XMBAttribute attr = child.GetAttributes().Item(0);
|
||||
TS_ASSERT_EQUALS(child.GetAttributes().size(), 1);
|
||||
XMBAttribute attr = child.GetAttributes()[0];
|
||||
TS_ASSERT_EQUALS(attr.Name, at_x);
|
||||
TS_ASSERT_EQUALS(CStr(attr.Value), " y ");
|
||||
}
|
||||
@ -91,7 +91,7 @@ public:
|
||||
XMBFile xmb (parse("<test> <x>A</x> <x>B</x> <y>C</y> <z>D</z> </test>"));
|
||||
|
||||
XMBElement root = xmb.GetRoot();
|
||||
TS_ASSERT_EQUALS(root.GetChildNodes().Count, 4);
|
||||
TS_ASSERT_EQUALS(root.GetChildNodes().size(), 4);
|
||||
|
||||
XMBElement x = root.GetChildNodes().GetFirstNamedItem(xmb.GetElementID("x"));
|
||||
XMBElement y = root.GetChildNodes().GetFirstNamedItem(xmb.GetElementID("y"));
|
||||
@ -106,8 +106,8 @@ public:
|
||||
TS_ASSERT_EQUALS(w.GetNodeName(), -1);
|
||||
TS_ASSERT_EQUALS(CStr(w.GetText()), "");
|
||||
TS_ASSERT_EQUALS(w.GetLineNumber(), -1);
|
||||
TS_ASSERT_EQUALS(w.GetChildNodes().Count, 0);
|
||||
TS_ASSERT_EQUALS(w.GetAttributes().Count, 0);
|
||||
TS_ASSERT_EQUALS(w.GetChildNodes().size(), 0);
|
||||
TS_ASSERT_EQUALS(w.GetAttributes().size(), 0);
|
||||
}
|
||||
|
||||
void test_doctype_ignored()
|
||||
@ -133,7 +133,7 @@ public:
|
||||
TS_ASSERT_EQUALS(text[0], 0x1234);
|
||||
TS_ASSERT_EQUALS(text[1], 0x1234);
|
||||
|
||||
text = xmb.GetRoot().GetAttributes().Item(0).Value.FromUTF8();
|
||||
text = xmb.GetRoot().GetAttributes()[0].Value.FromUTF8();
|
||||
TS_ASSERT_EQUALS((int)text.length(), 2);
|
||||
TS_ASSERT_EQUALS(text[0], 0x1234);
|
||||
TS_ASSERT_EQUALS(text[1], 0x1234);
|
||||
@ -151,7 +151,7 @@ public:
|
||||
TS_ASSERT_EQUALS(text[2], 0x0088);
|
||||
TS_ASSERT_EQUALS(text[3], 0x00B4);
|
||||
|
||||
text = xmb.GetRoot().GetAttributes().Item(0).Value.FromUTF8();
|
||||
text = xmb.GetRoot().GetAttributes()[0].Value.FromUTF8();
|
||||
TS_ASSERT_EQUALS((int)text.length(), 4);
|
||||
TS_ASSERT_EQUALS(text[0], 0x1234);
|
||||
TS_ASSERT_EQUALS(text[1], 0x00E1);
|
||||
|
Loading…
Reference in New Issue
Block a user