void OTMLNode::addChild(const OTMLNodePtr& newChild) { // replace is needed when the tag is marked as unique if(newChild->hasTag()) { for(const OTMLNodePtr& node : m_children) { if(node->tag() == newChild->tag() && (node->isUnique() || newChild->isUnique())) { newChild->setUnique(true); if(node->hasChildren() && newChild->hasChildren()) { OTMLNodePtr tmpNode = node->clone(); tmpNode->merge(newChild); newChild->copy(tmpNode); } replaceChild(node, newChild); // remove any other child with the same tag auto it = m_children.begin(); while(it != m_children.end()) { OTMLNodePtr node = (*it); if(node != newChild && node->tag() == newChild->tag()) { it = m_children.erase(it); } else ++it; } return; } } } m_children.push_back(newChild); }
void OTMLNode::copy(const OTMLNodePtr& node) { setTag(node->tag()); setValue(node->rawValue()); setUnique(node->isUnique()); setNull(node->isNull()); setSource(node->source()); clear(); for(const OTMLNodePtr& child : node->m_children) addChild(child->clone()); }
std::string OTMLEmitter::emitNode(const OTMLNodePtr& node, int currentDepth) { std::stringstream ss; // emit nodes if(currentDepth >= 0) { // fill spaces for current depth for(int i=0;i<currentDepth;++i) ss << " "; // emit node tag if(node->hasTag()) { ss << node->tag(); // add ':' to if the node is unique or has value if(node->hasValue() || node->isUnique() || node->isNull()) ss << ":"; } else ss << "-"; // emit node value if(node->isNull()) ss << " ~"; else if(node->hasValue()) { ss << " "; std::string value = node->value(); // emit multiline values if(value.find("\n") != std::string::npos) { if(value[value.length()-1] == '\n' && value[value.length()-2] == '\n') ss << "|+"; else if(value[value.length()-1] == '\n') ss << "|"; else ss << "|-"; // multilines for(std::size_t pos = 0; pos < value.length(); ++pos) { ss << "\n"; // fill spaces for multiline depth for(int i=0;i<currentDepth+1;++i) ss << " "; // fill until a new line while(pos < value.length()) { if(value[pos] == '\n') break; ss << value[pos++]; } } // emit inline values } else ss << value; } } // emit children for(int i=0;i<node->size();++i) { if(currentDepth >= 0 || i != 0) ss << "\n"; ss << emitNode(node->atIndex(i), currentDepth+1); } return ss.str(); }