diff --git a/src/input_output/FGXMLParse.cpp b/src/input_output/FGXMLParse.cpp index 9fd637aa22..f57deda034 100644 --- a/src/input_output/FGXMLParse.cpp +++ b/src/input_output/FGXMLParse.cpp @@ -40,34 +40,57 @@ namespace JSBSim { CLASS IMPLEMENTATION %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ -void FGXMLParse::reset(void) -{ +void FGXMLParse::reset(void) { current_element = document = nullptr; working_string.erase(); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -void FGXMLParse::dumpDataLines(void) -{ +void FGXMLParse::dumpDataLines(void) { + if (!working_string.empty()) { - for (auto s: split(working_string, '\n')) - current_element->AddData(s); + //The following change was made by Mach: + // 1. This implemenation iterates over the input string in O(n) time. + // where n is the length of the input string. + // 2. The built in JSBSim split() method runs in O(n^2) for n is the string size, with an additional + // O(m) [for m = n/rows of a matrix] from the outer for loop. + // Overall it runs in O(n^3) time making parsing inviable for files around 90MB+ in size. + // Regression tested against 2 jsbsims with identical inputs, and validated no difference + // within epsilon = 1E-8. + size_t index = 0; + index = working_string.find('\n'); + if (index != std::string::npos && index != 0) { + size_t curr = 0; + std::string temp = ""; + while (curr < working_string.length()) { + if (working_string[curr] == '\n') { + trim(temp); + current_element->AddData(temp); + temp = ""; + } else { + temp.push_back(working_string[curr]); + } + curr++; + } + } else { + trim(working_string); + current_element->AddData(working_string); + } + working_string.erase(); } - working_string.erase(); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -void FGXMLParse::startElement (const char * name, const XMLAttributes &atts) -{ +void FGXMLParse::startElement(const char *name, const XMLAttributes &atts) { if (!document) { document = new Element(name); current_element = document; } else { dumpDataLines(); - Element* temp_element = new Element(name); + Element *temp_element = new Element(name); if (temp_element) { temp_element->SetParent(current_element); current_element->AddChildElement(temp_element); @@ -84,30 +107,27 @@ void FGXMLParse::startElement (const char * name, const XMLAttributes &atts) current_element->SetLineNumber(getLine()); current_element->SetFileName(getPath()); - for (int i=0; iAddAttribute(atts.getName(i), atts.getValue(i)); } } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -void FGXMLParse::endElement (const char * name) -{ +void FGXMLParse::endElement(const char *name) { dumpDataLines(); current_element = current_element->GetParent(); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -void FGXMLParse::data (const char * s, int length) -{ +void FGXMLParse::data(const char *s, int length) { working_string += string(s, length); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -void FGXMLParse::warning (const char * message, int line, int column) -{ +void FGXMLParse::warning(const char *message, int line, int column) { cerr << "Warning: " << message << " line: " << line << " column: " << column << endl; }