bool CTaskFileHelper::SaveTaskRule(XMLNode node) { if (!node) { return false; } XMLNode FinishNode = node.AddChild(ToString(_T("finish")), false); if (!FinishNode) { return false; } SetAttribute(FinishNode, _T("fai-height"), EnableFAIFinishHeight); SetAttribute(FinishNode, _T("min-height"), FinishMinHeight); XMLNode StartNode = node.AddChild(ToString(_T("start")), false); if (!StartNode) { return false; } SetAttribute(StartNode, _T("max-height"), StartMaxHeight); SetAttribute(StartNode, _T("max-height-margin"), StartMaxHeightMargin); SetAttribute(StartNode, _T("max-speed"), StartMaxSpeed); SetAttribute(StartNode, _T("max-speed-margin"), StartMaxSpeedMargin); switch (StartHeightRef) { case 0: SetAttribute(StartNode, _T("height-ref"), _T("AGL")); break; case 1: SetAttribute(StartNode, _T("height-ref"), _T("ASL")); break; } return true; }
bool CTaskFileHelper::SaveOption(XMLNode node) { if (!node) { return false; } XMLNode OptNode = node.AddChild(ToString(_T("options")), false); if (!OptNode) { return false; } switch (AutoAdvance) { case 0: SetAttribute(OptNode, _T("auto-advance"), _T("Manual")); break; case 1: SetAttribute(OptNode, _T("auto-advance"), _T("Auto")); break; case 2: SetAttribute(OptNode, _T("auto-advance"), _T("Arm")); break; case 3: SetAttribute(OptNode, _T("auto-advance"), _T("ArmStart")); break; case 4: SetAttribute(OptNode, _T("auto-advance"), _T("ArmTPs")); break; } if (AATEnabled && !DoOptimizeRoute()) { // AAT Task SetAttribute(node, _T("type"), _T("AAT")); if (!SaveOptionAAT(OptNode)) { return false; } } else if (DoOptimizeRoute()) { // Paraglider optimized Task SetAttribute(node, _T("type"), _T("Race")); if (!SaveOptionRace(OptNode)) { return false; } } else { // default Task SetAttribute(node, _T("type"), _T("Default")); if (!SaveOptionDefault(OptNode)) { return false; } } if (!SaveTaskRule(OptNode.AddChild(ToString(_T("rules")), false))) { return false; } return true; }
bool CTaskFileHelper::SaveWayPointList(XMLNode node) { for (std::set<size_t>::const_iterator it = mWayPointToSave.begin(); it != mWayPointToSave.end(); ++it) { if (!SaveWayPoint(node.AddChild(ToString(_T("point")), false), WayPointList[*it])) { return false; } } return true; }
bool CTaskFileHelper::SaveOptionRace(XMLNode node) { if (!node) { return false; } if (PGNumberOfGates > 0) { if (!SaveTimeGate(node.AddChild(ToString(_T("time-gate")), false))) { return false; } } return true; }
void XMLDocument::ParseNodeTree(XMLNode &parentNode, rapidxml::xml_node<> *rapidxmlNode) { while(rapidxmlNode) { XMLNode node(rapidxmlNode->name(), rapidxmlNode->value()); rapidxml::xml_attribute<> *attr = rapidxmlNode->first_attribute(0); while(attr) { node.SetAttribute(std::string(attr->name()), std::string(attr->value())); attr = attr->next_attribute(); } this->ParseNodeTree(node, rapidxmlNode->first_node(0)); parentNode.AddChild(node); rapidxmlNode = rapidxmlNode->next_sibling(); } }
bool CTaskFileHelper::SaveStartPointList(XMLNode node) { if (!node) { return false; } for (unsigned long i = 0; ValidStartPoint(i); ++i) { XMLNode PointNode = node.AddChild(ToString(_T("point")), false); if (!PointNode) { return false; } SetAttribute(PointNode, _T("idx"), i); RenameIfVirtual(i); // TODO: check code is unique ? if (!SaveStartPoint(PointNode, StartPoints[i])) { return false; } } return true; }
LPVOID TVTCreateXMLPacket4FinalizeSession( TCHAR* sessionName, int failureCount, int summaryCount, int numberOfTests, int numberOfSuccessfulTests, int numberOfUnsuccessfulTests) { TCHAR* result = null, templatePath[MAX_PATH], tempText[MAX_PATH] ; if (!GetTemplateActionPath(templatePath) ) return result ; // This open and parse the XML file: XMLNode xRootNode = XMLNode::openFileHelper(templatePath,"easyTest"); XMLNode xAction = xRootNode.getChildNode("Action"); XMLAttribute* xAttribute = xAction.AddAttribute(stringDup("command",0),stringDup("updateObject", 0)); XMLNode xAttributes = xAction.getChildNode("Attributes"); xAttribute = xAttributes.AddAttribute(stringDup("object", 0),stringDup("session", 0)); xAttribute = xAttributes.AddAttribute(stringDup("session", 0),stringDup(sessionName, 0)); XMLNode xEntity = xAction.AddChild(stringDup("Entity"),0); // Line 'Conclusion' XMLNode xLine = TVTAddXMLLine(xEntity); TVTAddXMLToken(xLine,"Conclusion: "); TVTAddXMLToken(xLine,itoa(summaryCount,tempText,10)); TVTAddXMLToken(xLine," checks were made. There were "); TVTAddXMLToken(xLine,itoa(failureCount,tempText,10)); TVTAddXMLToken(xLine," failures."); // Line 'Statistics' xLine = TVTAddXMLLine(xEntity); TVTAddXMLToken(xLine,"Statistics:"); // Line # tests are executes. xLine = TVTAddXMLLine(xEntity); TVTAddXMLToken(xLine,itoa(numberOfTests,tempText,10)); if (numberOfTests == 1) TVTAddXMLToken(xLine," test is executed."); else TVTAddXMLToken(xLine," tests are executed.") ; xLine = TVTAddXMLLine(xEntity); if (!numberOfUnsuccessfulTests) { TVTAddXMLToken(xLine,"No errors detected."); } else { TVTAddXMLToken(xLine,itoa(numberOfSuccessfulTests,tempText,10)); if (numberOfSuccessfulTests == 1) TVTAddXMLToken(xLine," test is completed successfully. "); else TVTAddXMLToken(xLine," tests are completed successfully. ") ; xLine = TVTAddXMLLine(xEntity); TVTAddXMLToken(xLine,itoa(numberOfUnsuccessfulTests,tempText,10)); if (numberOfUnsuccessfulTests == 1) TVTAddXMLToken(xLine," test failed."); else TVTAddXMLToken(xLine," tests failed.") ; } // Line int size; LPTSTR pText = xRootNode.createXMLString(1,&size); result = new TCHAR [size+1]; if (result) { _tcscpy(result,pText); } free(pText); return result; }
/** * Recursively parse an XML element. */ static bool XML::ParseXMLElement(XMLNode &node, Parser *pXML) { bool is_declaration; const TCHAR *text = nullptr; XMLNode *pNew; enum Status status; // inside or outside a tag enum Attrib attrib = eAttribName; /* the name of the attribute that is currently being */ tstring attribute_name; assert(pXML); // If this is the first call to the function if (pXML->nFirst) { // Assume we are outside of a tag definition pXML->nFirst = false; status = eOutsideTag; } else { // If this is not the first call then we should only be called when inside a tag. status = eInsideTag; } // Iterate through the tokens in the document while (true) { // Obtain the next token NextToken token = GetNextToken(pXML); if (gcc_unlikely(token.type == eTokenError)) return false; // Check the current status switch (status) { // If we are outside of a tag definition case eOutsideTag: // Check what type of token we obtained switch (token.type) { // If we have found text or quoted text case eTokenText: case eTokenQuotedText: case eTokenEquals: if (text == nullptr) text = token.pStr; break; // If we found a start tag '<' and declarations '<?' case eTokenTagStart: case eTokenDeclaration: // Cache whether this new element is a declaration or not is_declaration = token.type == eTokenDeclaration; // If we have node text then add this to the element if (text != nullptr) { size_t length = StripRight(text, token.pStr - text); node.AddText(text, length); text = nullptr; } // Find the name of the tag token = GetNextToken(pXML); // Return an error if we couldn't obtain the next token or // it wasnt text if (token.type != eTokenText) { pXML->error = eXMLErrorMissingTagName; return false; } // If the name of the new element differs from the name of // the current element we need to add the new element to // the current one and recurse pNew = &node.AddChild(token.pStr, token.length, is_declaration); while (true) { // Callself to process the new node. If we return // FALSE this means we dont have any more // processing to do... if (!ParseXMLElement(*pNew, pXML)) { return false; } else { // If the call to recurse this function // evented in a end tag specified in XML then // we need to unwind the calls to this // function until we find the appropriate node // (the element name and end tag name must // match) if (pXML->cbEndTag) { // If we are back at the root node then we // have an unmatched end tag if (node.GetName() == nullptr) { pXML->error = eXMLErrorUnmatchedEndTag; return false; } // If the end tag matches the name of this // element then we only need to unwind // once more... if (CompareTagName(node.GetName(), pXML->lpEndTag)) { pXML->cbEndTag = 0; } return true; } else { // If we didn't have a new element to create break; } } } break; // If we found an end tag case eTokenTagEnd: // If we have node text then add this to the element if (text != nullptr) { size_t length = StripRight(text, token.pStr - text); TCHAR *text2 = FromXMLString(text, length); if (text2 == nullptr) { pXML->error = eXMLErrorUnexpectedToken; return false; } node.AddText(text2); free(text2); text = nullptr; } // Find the name of the end tag token = GetNextToken(pXML); // The end tag should be text if (token.type != eTokenText) { pXML->error = eXMLErrorMissingEndTagName; return false; } // After the end tag we should find a closing tag if (GetNextToken(pXML).type != eTokenCloseTag) { pXML->error = eXMLErrorMissingEndTagName; return false; } // We need to return to the previous caller. If the name // of the tag cannot be found we need to keep returning to // caller until we find a match if (!CompareTagName(node.GetName(), token.pStr)) { pXML->lpEndTag = token.pStr; pXML->cbEndTag = token.length; } // Return to the caller return true; // Errors... case eTokenCloseTag: /* '>' */ case eTokenShortHandClose: /* '/>' */ pXML->error = eXMLErrorUnexpectedToken; return false; default: break; } break; // If we are inside a tag definition we need to search for attributes case eInsideTag: // Check what part of the attribute (name, equals, value) we // are looking for. switch (attrib) { // If we are looking for a new attribute case eAttribName: // Check what the current token type is switch (token.type) { // If the current type is text... // Eg. 'attribute' case eTokenText: // Cache the token then indicate that we are next to // look for the equals attribute_name.assign(token.pStr, token.length); attrib = eAttribEquals; break; // If we found a closing tag... // Eg. '>' case eTokenCloseTag: // We are now outside the tag status = eOutsideTag; break; // If we found a short hand '/>' closing tag then we can // return to the caller case eTokenShortHandClose: return true; // Errors... case eTokenQuotedText: /* '"SomeText"' */ case eTokenTagStart: /* '<' */ case eTokenTagEnd: /* '</' */ case eTokenEquals: /* '=' */ case eTokenDeclaration: /* '<?' */ pXML->error = eXMLErrorUnexpectedToken; return false; default: break; } break; // If we are looking for an equals case eAttribEquals: // Check what the current token type is switch (token.type) { // If the current type is text... // Eg. 'Attribute AnotherAttribute' case eTokenText: // Add the unvalued attribute to the list node.AddAttribute(std::move(attribute_name), _T(""), 0); // Cache the token then indicate. We are next to // look for the equals attribute attribute_name.assign(token.pStr, token.length); break; // If we found a closing tag 'Attribute >' or a short hand // closing tag 'Attribute />' case eTokenShortHandClose: case eTokenCloseTag: assert(!attribute_name.empty()); // If we are a declaration element '<?' then we need // to remove extra closing '?' if it exists if (node.IsDeclaration() && attribute_name.back() == _T('?')) { attribute_name.pop_back(); } if (!attribute_name.empty()) // Add the unvalued attribute to the list node.AddAttribute(std::move(attribute_name), _T(""), 0); // If this is the end of the tag then return to the caller if (token.type == eTokenShortHandClose) return true; // We are now outside the tag status = eOutsideTag; break; // If we found the equals token... // Eg. 'Attribute =' case eTokenEquals: // Indicate that we next need to search for the value // for the attribute attrib = eAttribValue; break; // Errors... case eTokenQuotedText: /* 'Attribute "InvalidAttr"'*/ case eTokenTagStart: /* 'Attribute <' */ case eTokenTagEnd: /* 'Attribute </' */ case eTokenDeclaration: /* 'Attribute <?' */ pXML->error = eXMLErrorUnexpectedToken; return false; default: break; } break; // If we are looking for an attribute value case eAttribValue: // Check what the current token type is switch (token.type) { // If the current type is text or quoted text... // Eg. 'Attribute = "Value"' or 'Attribute = Value' or // 'Attribute = 'Value''. case eTokenText: case eTokenQuotedText: // If we are a declaration element '<?' then we need // to remove extra closing '?' if it exists if (node.IsDeclaration() && (token.pStr[token.length - 1]) == _T('?')) { token.length--; } // Add the valued attribute to the list if (token.type == eTokenQuotedText) { token.pStr++; token.length -= 2; } assert(!attribute_name.empty()); { TCHAR *value = FromXMLString(token.pStr, token.length); if (value == nullptr) { pXML->error = eXMLErrorUnexpectedToken; return false; } node.AddAttribute(std::move(attribute_name), value, _tcslen(value)); free(value); } // Indicate we are searching for a new attribute attrib = eAttribName; break; // Errors... case eTokenTagStart: /* 'Attr = <' */ case eTokenTagEnd: /* 'Attr = </' */ case eTokenCloseTag: /* 'Attr = >' */ case eTokenShortHandClose: /* "Attr = />" */ case eTokenEquals: /* 'Attr = =' */ case eTokenDeclaration: /* 'Attr = <?' */ pXML->error = eXMLErrorUnexpectedToken; return false; default: break; } } } } }
XMLNode* XMLParser::_Parse(wchar_t* buf) { std::wstring token; eCurState state = NONE; attrMap attributeMap; std::wstring attrKey; XMLNode* curNode = new XMLNode; while( _mParsingIndex < _mBufSize ) { switch( buf[_mParsingIndex] ) { case L'<': if( state == ELEMENT ) // After element, It could be either closing node or new child node { if( _IsTokenTab(token) ) // At first, delete the all gap (similar to trim function) { token.clear(); } if( buf[_mParsingIndex+1] == L'/' ) // In case of closing the node { curNode->SetElement( token ); token.clear(); state = CLOSING_NODE; ++_mParsingIndex; } else // In case of new child node { curNode->AddChild( _Parse(buf) ); } } else // In case of new node { ++_mParsingIndex; if( buf[_mParsingIndex] == L'?' || buf[_mParsingIndex] == L'!') // if new node is about xml information { _GetTokenWith(buf, L'>'); } else // Read the new node's name { token += buf[_mParsingIndex]; state = OPENING_NODE; } } break; case L'>': switch( state ) { case ATTR_VALUE: // In case that new node's attr setting is all set curNode->SetAttrMap(attributeMap); attributeMap.clear(); state = ELEMENT; break; case CLOSING_NODE: // In case that making node is all set if( curNode->GetName().compare(token) != 0 ) { delete curNode; wprintf(L"XML ERROR ( closing element's name isn't correct [%s] ) - line %d", curNode->GetName().c_str(), _mLine ); return nullptr; } return curNode; case OPENING_NODE: // In case that new node's name setting is all set curNode->SetName( token ); token.clear(); state = ELEMENT; break; default: std::wcerr<<L"SWITCH_DEFAULT : "<<__FILE__<<L" "<<__LINE__<<std::endl; return nullptr; } break; case L' ': switch( state ) { case OPENING_NODE: // After setting the name of new node curNode->SetName( token ); token.clear(); state = ATTR_VALUE; break; case ELEMENT : // if ' ' is used for element, then just use that token += L' '; break; default: std::wcerr<<L"SWITCH_DEFAULT : "<<__FILE__<<L" "<<__LINE__<<std::endl; return nullptr; } break; case L'=': switch( state ) { case ELEMENT: // If '=' is used for element, then just use that token += L'='; break; case ATTR_VALUE: // In case of setting the attribute, attribute's key will come next attrKey = token; token.clear(); state = ATTR_KEY; break; default: std::wcerr<<L"SWITCH_DEFAULT : "<<__FILE__<<L" "<<__LINE__<<std::endl; return nullptr; } break; case L'\"': switch( state ) { case ATTR_KEY: // Set the attribute's key ++_mParsingIndex; token = _GetTokenWith(buf, L'\"'); attributeMap[attrKey] = token; attrKey.clear(); token.clear(); state = ATTR_VALUE; break; default: std::wcerr<<L"SWITCH_DEFAULT : "<<__FILE__<<L" "<<__LINE__<<std::endl; return nullptr; } break; case L'/': // If node is closed by using '/>' if( state == ATTR_VALUE && buf[_mParsingIndex+1] == L'>' ) { curNode->SetAttrMap(attributeMap); attributeMap.clear(); ++_mParsingIndex; return curNode; } break; default: if( buf[_mParsingIndex] == L'\n' ) ++_mLine; else token += buf[_mParsingIndex]; break; } ++_mParsingIndex; } return nullptr; }
bool CTaskFileHelper::SaveOptionDefault(XMLNode node) { if (!node) { return false; } XMLNode nodeStart = node.AddChild(ToString(_T("start")), false); if (nodeStart) { switch (StartLine) { case 0: //circle SetAttribute(nodeStart, _T("type"), _T("circle")); break; case 1: //line SetAttribute(nodeStart, _T("type"), _T("line")); break; case 2: //sector SetAttribute(nodeStart, _T("type"), _T("sector")); break; } SetAttribute(nodeStart, _T("radius"), StartRadius); } else { return false; } XMLNode nodeFinish = node.AddChild(ToString(_T("finish")), false); if (nodeFinish) { switch (FinishLine) { case 0: //circle SetAttribute(nodeFinish, _T("type"), _T("circle")); break; case 1: //line SetAttribute(nodeFinish, _T("type"), _T("line")); break; case 2: //sector SetAttribute(nodeFinish, _T("type"), _T("sector")); break; } SetAttribute(nodeFinish, _T("Radius"), FinishRadius); } else { return false; } XMLNode nodeSector = node.AddChild(ToString(_T("sector")), false); if (nodeSector) { switch (SectorType) { case 0: //circle SetAttribute(nodeSector, _T("type"), _T("circle")); SetAttribute(nodeSector, _T("Radius"), SectorRadius); break; case 1: //sector SetAttribute(nodeSector, _T("type"), _T("sector")); SetAttribute(nodeSector, _T("Radius"), SectorRadius); break; case 2: //DAe SetAttribute(nodeSector, _T("type"), _T("DAe")); break; } } else { return false; } return true; }
bool CTaskFileHelper::Save(const TCHAR* szFileName) { if (!WayPointList) return false; // this should never happen, but just to be safe... CScopeLock LockTask(LockTaskData, UnlockTaskData); StartupStore(_T(". SaveTask : saving <%s>%s"), szFileName, NEWLINE); /////////////////////////////////////////////////////////////// // TODO : this code is temporary before rewriting task system if (AATEnabled || DoOptimizeRoute()) { for (unsigned i = 0; ValidTaskPoint(i); ++i) { int type = -1; if (i == 0) { // Start Task[0].AATCircleRadius = StartRadius; Task[0].AATSectorRadius = StartRadius; Task[0].OutCircle = !PGStartOut; type = StartLine; } else if (!ValidTaskPoint(i + 1)) { //Finish Task[i].AATCircleRadius = FinishRadius; Task[i].AATSectorRadius = FinishRadius; type = FinishLine; } if (type != -1) { switch (type) { case 0: //circle Task[i].AATType = CIRCLE; break; case 1: //line Task[i].AATType = LINE; break; case 2: //sector Task[i].AATType = SECTOR; break; } } } } /////////////////////////////////////////////////////////////// XMLNode topNode = XMLNode::createXMLTopNode(); XMLNode rootNode = topNode.AddChild(ToString(_T("lk-task")), false); if (!SaveOption(rootNode)) { return false; } if (!SaveTaskPointList(rootNode.AddChild(ToString(_T("taskpoints")), false))) { return false; } if (EnableMultipleStartPoints && ValidStartPoint(0)) { if (!SaveStartPointList(rootNode.AddChild(ToString(_T("startpoints")), false))) { return false; } } if (!SaveWayPointList(rootNode.AddChild(ToString(_T("waypoints")), false))) { return false; } int ContentSize = 0; LPCTSTR szContent = topNode.createXMLString(1, &ContentSize); Utf8File file; if (!file.Open(szFileName, Utf8File::io_create)) { return false; } file.WriteLn(szContent); file.Close(); return true; }