| 489 | } |
| 490 | |
| 491 | std::string ErrorMessage::toXML() const |
| 492 | { |
| 493 | tinyxml2::XMLPrinter printer(nullptr, false, 2); |
| 494 | printer.OpenElement("error", false); |
| 495 | printer.PushAttribute("id", id.c_str()); |
| 496 | if (!guideline.empty()) |
| 497 | printer.PushAttribute("guideline", guideline.c_str()); |
| 498 | printer.PushAttribute("severity", severityToString(severity).c_str()); |
| 499 | if (!classification.empty()) |
| 500 | printer.PushAttribute("classification", classification.c_str()); |
| 501 | printer.PushAttribute("msg", fixInvalidChars(mShortMessage).c_str()); |
| 502 | printer.PushAttribute("verbose", fixInvalidChars(mVerboseMessage).c_str()); |
| 503 | if (cwe.id) |
| 504 | printer.PushAttribute("cwe", cwe.id); |
| 505 | if (hash) |
| 506 | printer.PushAttribute("hash", std::to_string(hash).c_str()); |
| 507 | if (certainty == Certainty::inconclusive) |
| 508 | printer.PushAttribute("inconclusive", "true"); |
| 509 | |
| 510 | if (!file0.empty()) |
| 511 | printer.PushAttribute("file0", file0.c_str()); |
| 512 | |
| 513 | if (!remark.empty()) |
| 514 | printer.PushAttribute("remark", fixInvalidChars(remark).c_str()); |
| 515 | |
| 516 | for (auto it = callStack.crbegin(); it != callStack.crend(); ++it) { |
| 517 | printer.OpenElement("location", false); |
| 518 | const std::string origfile = it->getOrigFile(false); |
| 519 | const std::string file = it->getfile(false); |
| 520 | if (origfile != file) |
| 521 | printer.PushAttribute("origfile", origfile.c_str()); |
| 522 | printer.PushAttribute("file", file.c_str()); |
| 523 | printer.PushAttribute("line", std::max(it->line,0)); |
| 524 | printer.PushAttribute("column", it->column); |
| 525 | if (!it->getinfo().empty()) |
| 526 | printer.PushAttribute("info", fixInvalidChars(it->getinfo()).c_str()); |
| 527 | printer.CloseElement(false); |
| 528 | } |
| 529 | for (std::string::size_type pos = 0; pos < mSymbolNames.size();) { |
| 530 | const std::string::size_type pos2 = mSymbolNames.find('\n', pos); |
| 531 | std::string symbolName; |
| 532 | if (pos2 == std::string::npos) { |
| 533 | symbolName = mSymbolNames.substr(pos); |
| 534 | pos = pos2; |
| 535 | } else { |
| 536 | symbolName = mSymbolNames.substr(pos, pos2-pos); |
| 537 | pos = pos2 + 1; |
| 538 | } |
| 539 | printer.OpenElement("symbol", false); |
| 540 | printer.PushText(symbolName.c_str()); |
| 541 | printer.CloseElement(false); |
| 542 | } |
| 543 | printer.CloseElement(false); |
| 544 | return printer.CStr(); |
| 545 | } |
| 546 | |
| 547 | // TODO: read info from some shared resource instead? |
| 548 | static std::string readCode(const std::string &file, int linenr, int column, const char endl[]) |