Skip to content

Commit

Permalink
config: fixed resolving local links.
Browse files Browse the repository at this point in the history
  • Loading branch information
tmayerguerr committed Mar 27, 2024
1 parent c3b5b62 commit b2cd40b
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 83 deletions.
140 changes: 58 additions & 82 deletions source/config/config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -126,51 +126,6 @@ Config::Config(FileName &fileName, const std::map<std::string, std::string> &com

/***********************************************/

XmlNodePtr Config::resolveLink(XmlNodePtr xmlNode)
{
try
{
if(!xmlNode)
return xmlNode;

XmlAttrPtr link = xmlNode->findAttribute("link");
if(link)
{
XmlNodePtr xmlNodeLink = stack.top().links[link->getText()];
if(!xmlNodeLink || xmlNodeLink->getAttribute("resolving"))
throw(Exception(std::string("cannot resolve link: ")+xmlNode->getName()+" -> "+link->getText()+"'"));

XmlNodePtr xmlNodeNew = xmlNodeLink->clone();

// add temporary resolving attribute to prevent link loops
writeAttribute(xmlNodeLink, "resolving", 1);

xmlNodeNew = resolveLink(xmlNodeNew);
xmlNodeNew->setName(xmlNode->getName());
while(xmlNode->hasAttribute())
xmlNodeNew->addAttribute(xmlNode->getNextAttribute());

// remove attributes as link was resolved successfully
xmlNodeLink->getAttribute("resolving");
xmlNodeNew->getAttribute("link");

xmlNode = xmlNodeNew;
}

// test children
for(XmlNodePtr &child : xmlNode->getChildren())
child = resolveLink(child);

return xmlNode;
}
catch(std::exception &e)
{
GROOPS_RETHROW(e)
}
}

/***********************************************/

Bool Config::hasName(const std::string &name)
{
for(;;)
Expand All @@ -185,12 +140,11 @@ Bool Config::hasName(const std::string &name)
// local variables before?
// -----------------------
XmlNodePtr xmlNode;
while((xmlNode = stack.top().xmlNode->findNextChild()))
while((xmlNode = stack.top().xmlNode->getNextChild()))
{
XmlAttrPtr label = xmlNode->getAttribute("label");
if(label) // xmlNode is local variable
{
stack.top().xmlNode->getNextChild(); // remove
xmlNode->setName(label->getText()); // replace typename with label
stack.top().links[xmlNode->getName()] = xmlNode;
if(!xmlNode->hasChildren()) // not complex type? -> variable
Expand All @@ -202,16 +156,44 @@ Bool Config::hasName(const std::string &name)
}
if(xmlNode->getName() == name)
break;
// unknown element: move to end
stack.top().xmlNode->addChild(xmlNode);
if(!stack.top().xmlNode->findChild(name))
return false;
// unkonwn element: move to end
stack.top().xmlNode->addChild(stack.top().xmlNode->getNextChild());
return FALSE;
}

if(xmlNode == nullptr)
return FALSE;

xmlNode = resolveLink(xmlNode);
// -----------------------
std::function<void(XmlNodePtr&)> resolveLink = [&](XmlNodePtr &xmlNode)
{

XmlAttrPtr link = xmlNode->getAttribute("link");
if(link)
{
XmlNodePtr xmlNodeLink = stack.top().links[link->getText()];
if(!xmlNodeLink || xmlNodeLink->getAttribute("resolving"))
throw(Exception(std::string("cannot resolve link: ")+xmlNode->getName()+" -> "+link->getText()+"'"));


// add temporary resolving attribute to prevent link loops
writeAttribute(xmlNodeLink, "resolving", 1);

XmlNodePtr xmlNodeNew = xmlNodeLink->clone();
resolveLink(xmlNodeNew);
xmlNodeNew->setName(xmlNode->getName());
while(xmlNode->hasAttribute())
xmlNodeNew->addAttribute(xmlNode->getNextAttribute());
xmlNode = xmlNodeNew;

// remove attributes as link was resolved successfully
xmlNodeLink->getAttribute("resolving");
}
};
// -----------------------

resolveLink(xmlNode);

// loop?
// -----
Expand All @@ -220,17 +202,12 @@ Bool Config::hasName(const std::string &name)
if(!stack.top().loopPtr->iteration(stack.top().varList)) // finish loop
{
stack.top().varList = stack.top().loopVarListOld; // restore old varList
stack.top().xmlNode->getChild(name); // remove child as it is finished
stack.top().loopPtr = nullptr;
continue;
}
else // next loop
stack.top().xmlLastChild = xmlNode->clone();
stack.top().xmlNode->prependChild(xmlNode->clone()); // restore for next loop
}

// get new child
// -------------
if(!stack.top().xmlLastChild)
else
{
// expand loop
XmlAttrPtr attr = xmlNode->getAttribute("loop");
Expand All @@ -247,35 +224,34 @@ Bool Config::hasName(const std::string &name)
pop();
stack.top().loopPtr = loopPtr;
stack.top().loopVarListOld = stack.top().varList;
stack.top().xmlNode->prependChild(xmlNode); // restore for next loop
continue; // start loop
}
else
stack.top().xmlLastChild = stack.top().xmlNode->getChild(name); // no loop -> remove node
}

// check condition
XmlAttrPtr attr = stack.top().xmlLastChild->getAttribute("condition");
if(!attr)
return TRUE;

// expand condition
XmlNodePtr xmlNodeCondition = stack.top().links[attr->getText()];
if(!xmlNodeCondition)
throw(Exception(std::string("cannot resolve condition link: '")+stack.top().xmlLastChild->getName()+"' -> '"+attr->getText()+"'"));
attr = nullptr;
XmlNodePtr tmp = XmlNode::create("tmp");
tmp->addChild(xmlNodeCondition->clone()); // make copy
push(tmp, SEQUENCE, currentNodeName());
ConditionPtr condition;
readConfig(*this, xmlNodeCondition->getName(), condition, Config::MUSTSET, "", "");
pop();

// check condition
if(condition->condition(stack.top().varList))
return TRUE;
XmlAttrPtr attr = xmlNode->getAttribute("condition");
if(attr)
{
// expand condition
XmlNodePtr xmlNodeCondition = stack.top().links[attr->getText()];
if(!xmlNodeCondition)
throw(Exception(std::string("cannot resolve condition link: '")+xmlNode->getName()+"' -> '"+attr->getText()+"'"));
attr = nullptr;
XmlNodePtr tmp = XmlNode::create("tmp");
tmp->addChild(xmlNodeCondition->clone()); // make copy
push(tmp, SEQUENCE, currentNodeName());
ConditionPtr condition;
readConfig(*this, xmlNodeCondition->getName(), condition, Config::MUSTSET, "", "");
pop();

// check condition
if(!condition->condition(stack.top().varList))
continue; // node disabled -> try next element
}

// node disabled -> try next element
stack.top().xmlLastChild = nullptr;
stack.top().xmlLastChild = xmlNode;
return TRUE;
} // for(;;)
}

Expand Down Expand Up @@ -346,7 +322,7 @@ Bool Config::getConfigValue(const std::string &name, const std::string &type, Co
}
catch(std::exception &e)
{
GROOPS_RETHROW_EXTRA("'"+name+"' = ' "+text+"'", e)
GROOPS_RETHROW_EXTRA("'"+name+"' = '"+text+"'", e)
}
}

Expand Down
1 change: 0 additions & 1 deletion source/config/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,6 @@ class Config
void pop();

// normal mode
XmlNodePtr resolveLink(XmlNodePtr xmlNode);
Bool hasName(const std::string &name);
XmlNodePtr getChild(const std::string &name);
void notEmptyWarning();
Expand Down

0 comments on commit b2cd40b

Please sign in to comment.