#include <config.h>
#include <utils/common/MsgHandler.h>
#include <utils/common/ToString.h>
#include "CSVFormatter.h"
CSVFormatter::CSVFormatter(const std::string& columnNames, const char separator)
: OutputFormatter(OutputFormatterType::CSV), myHeaderFormat(columnNames), mySeparator(separator) {
if (myHeaderFormat == "none") {
myWroteHeader = true;
}
}
void
CSVFormatter::openTag(std::ostream& , const std::string& xmlElement) {
myCurrentDepth++;
if (myCurrentDepth > (int)myXMLStack.size()) {
myXMLStack.emplace_back(std::unique_ptr<std::ostringstream>(new std::ostringstream()));
}
if (!myWroteHeader) {
myCurrentTag = xmlElement;
}
if (myMaxDepth == myCurrentDepth && myWroteHeader && myCurrentTag != xmlElement) {
WRITE_WARNINGF("Encountered mismatch in XML tags (expected % but got %). Column names may be incorrect.", myCurrentTag, xmlElement);
}
}
void
CSVFormatter::openTag(std::ostream& , const SumoXMLTag& xmlElement) {
myCurrentDepth++;
if (myCurrentDepth > (int)myXMLStack.size()) {
myXMLStack.emplace_back(std::unique_ptr<std::ostringstream>(new std::ostringstream()));
}
if (!myWroteHeader) {
myCurrentTag = toString(xmlElement);
}
if (myMaxDepth == myCurrentDepth && myWroteHeader && myCurrentTag != toString(xmlElement)) {
WRITE_WARNINGF("Encountered mismatch in XML tags (expected % but got %). Column names may be incorrect.", myCurrentTag, toString(xmlElement));
}
}
bool
CSVFormatter::closeTag(std::ostream& into, const std::string& ) {
if (myMaxDepth == 0) {
myMaxDepth = myCurrentDepth;
}
if (myMaxDepth == myCurrentDepth && !myWroteHeader) {
if (!myCheckColumns) {
WRITE_WARNING("Column based formats are still experimental. Autodetection only works for homogeneous output.");
}
into << joinToString(myHeader, mySeparator) << "\n";
myWroteHeader = true;
}
if (myCurrentDepth == myMaxDepth) {
if (myCheckColumns && myExpectedAttrs != mySeenAttrs) {
WRITE_ERRORF("Incomplete attribute set '%', this file format does not support CSV output yet.", toString(mySeenAttrs));
}
for (auto it = myXMLStack.begin(); it != myXMLStack.end() - 1; ++it) {
into << (*it)->str();
}
std::string final = myXMLStack[myCurrentDepth - 1]->str();
final[final.size() - 1] = '\n';
into << final;
mySeenAttrs.reset();
}
if (myCurrentDepth > 0) {
if (!myWroteHeader) {
const std::string text = myXMLStack[myCurrentDepth - 1]->str();
const int count = (int)std::count(text.begin(), text.end(), mySeparator);
myHeader.resize(myHeader.size() - count);
}
myXMLStack[myCurrentDepth - 1]->str("");
myXMLStack[myCurrentDepth - 1]->clear();
myCurrentDepth--;
}
return false;
}