Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
eclipse
GitHub Repository: eclipse/sumo
Path: blob/main/src/utils/iodevices/CSVFormatter.cpp
169678 views
1
/****************************************************************************/
2
// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3
// Copyright (C) 2012-2025 German Aerospace Center (DLR) and others.
4
// This program and the accompanying materials are made available under the
5
// terms of the Eclipse Public License 2.0 which is available at
6
// https://www.eclipse.org/legal/epl-2.0/
7
// This Source Code may also be made available under the following Secondary
8
// Licenses when the conditions for such availability set forth in the Eclipse
9
// Public License 2.0 are satisfied: GNU General Public License, version 2
10
// or later which is available at
11
// https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
12
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
13
/****************************************************************************/
14
/// @file CSVFormatter.cpp
15
/// @author Michael Behrisch
16
/// @date 2025-06-12
17
///
18
// An output formatter for CSV files
19
/****************************************************************************/
20
#include <config.h>
21
22
#include <utils/common/MsgHandler.h>
23
#include <utils/common/ToString.h>
24
#include "CSVFormatter.h"
25
26
27
// ===========================================================================
28
// member method definitions
29
// ===========================================================================
30
CSVFormatter::CSVFormatter(const std::string& columnNames, const char separator)
31
: OutputFormatter(OutputFormatterType::CSV), myHeaderFormat(columnNames), mySeparator(separator) {
32
if (myHeaderFormat == "none") {
33
myWroteHeader = true;
34
}
35
}
36
37
38
void
39
CSVFormatter::openTag(std::ostream& /* into */, const std::string& xmlElement) {
40
myCurrentDepth++;
41
if (myCurrentDepth > (int)myXMLStack.size()) {
42
myXMLStack.emplace_back(std::unique_ptr<std::ostringstream>(new std::ostringstream()));
43
}
44
if (!myWroteHeader) {
45
myCurrentTag = xmlElement;
46
}
47
if (myMaxDepth == myCurrentDepth && myWroteHeader && myCurrentTag != xmlElement) {
48
WRITE_WARNINGF("Encountered mismatch in XML tags (expected % but got %). Column names may be incorrect.", myCurrentTag, xmlElement);
49
}
50
}
51
52
53
void
54
CSVFormatter::openTag(std::ostream& /* into */, const SumoXMLTag& xmlElement) {
55
myCurrentDepth++;
56
if (myCurrentDepth > (int)myXMLStack.size()) {
57
myXMLStack.emplace_back(std::unique_ptr<std::ostringstream>(new std::ostringstream()));
58
}
59
if (!myWroteHeader) {
60
myCurrentTag = toString(xmlElement);
61
}
62
if (myMaxDepth == myCurrentDepth && myWroteHeader && myCurrentTag != toString(xmlElement)) {
63
WRITE_WARNINGF("Encountered mismatch in XML tags (expected % but got %). Column names may be incorrect.", myCurrentTag, toString(xmlElement));
64
}
65
}
66
67
68
bool
69
CSVFormatter::closeTag(std::ostream& into, const std::string& /* comment */) {
70
if (myMaxDepth == 0) {
71
myMaxDepth = myCurrentDepth;
72
}
73
if (myMaxDepth == myCurrentDepth && !myWroteHeader) {
74
if (!myCheckColumns) {
75
WRITE_WARNING("Column based formats are still experimental. Autodetection only works for homogeneous output.");
76
}
77
into << joinToString(myHeader, mySeparator) << "\n";
78
myWroteHeader = true;
79
}
80
if (myCurrentDepth == myMaxDepth) {
81
if (myCheckColumns && myExpectedAttrs != mySeenAttrs) {
82
WRITE_ERRORF("Incomplete attribute set '%', this file format does not support CSV output yet.", toString(mySeenAttrs));
83
}
84
for (auto it = myXMLStack.begin(); it != myXMLStack.end() - 1; ++it) {
85
into << (*it)->str();
86
}
87
// remove the final separator
88
std::string final = myXMLStack[myCurrentDepth - 1]->str();
89
final[final.size() - 1] = '\n';
90
into << final;
91
mySeenAttrs.reset();
92
}
93
if (myCurrentDepth > 0) {
94
if (!myWroteHeader) {
95
const std::string text = myXMLStack[myCurrentDepth - 1]->str();
96
const int count = (int)std::count(text.begin(), text.end(), mySeparator);
97
myHeader.resize(myHeader.size() - count);
98
}
99
myXMLStack[myCurrentDepth - 1]->str("");
100
myXMLStack[myCurrentDepth - 1]->clear();
101
myCurrentDepth--;
102
}
103
return false;
104
}
105
106
107
/****************************************************************************/
108
109