Eclipse SUMO - Simulation of Urban MObility
Loading...
Searching...
No Matches
CSVFormatter.h
Go to the documentation of this file.
1/****************************************************************************/
2// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3// Copyright (C) 2012-2026 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/****************************************************************************/
18// Output formatter for CSV output
19/****************************************************************************/
20#pragma once
21#include <config.h>
22
23#include <memory>
24#include <algorithm>
25#include "OutputFormatter.h"
28
29
30// ===========================================================================
31// class definitions
32// ===========================================================================
38public:
40 CSVFormatter(const std::string& columnNames, const char separator = ';');
41
43 virtual ~CSVFormatter() override { }
44
54 bool writeXMLHeader(std::ostream& into, const std::string& rootElement,
55 const std::map<SumoXMLAttr, std::string>& attrs, bool /* writeMetadata */,
56 bool /* includeConfig */) override;
57
63 void openTag(std::ostream& into, const std::string& xmlElement) override;
64
70 void openTag(std::ostream& into, const SumoXMLTag& xmlElement) override;
71
80 bool closeTag(std::ostream& into, const std::string& comment = "") override;
81
92 template <class T>
93 void writeAttr(std::ostream& into, const SumoXMLAttr attr, const T& val, const bool isNull, const bool escape) {
94 UNUSED_PARAMETER(escape);
95 checkAttr(attr);
96 myValues.emplace_back(isNull ? "" : toString(val, into.precision()));
97 }
98
109 template <class T>
110 void writeAttr(std::ostream& into, const std::string& attr, const T& val, const bool isNull, const bool escape) {
111 UNUSED_PARAMETER(escape);
112 assert(!myCheckColumns);
113 checkHeader(attr);
114 myValues.emplace_back(isNull ? "" : toString(val, into.precision()));
115 }
116
118 void writeAttr(std::ostream& /* into */, const SumoXMLAttr attr, const std::string& val, const bool isNull, const bool escape) {
119 checkAttr(attr);
120 myValues.emplace_back(isNull ? "" : (escape ? StringUtils::escapeCSV(val, mySeparator) : val));
121 }
122 void writeAttr(std::ostream& /* into */, const std::string& attr, const std::string& val, const bool isNull, const bool escape) {
123 assert(!myCheckColumns);
124 checkHeader(attr);
125 myValues.emplace_back(isNull ? "" : (escape ? StringUtils::escapeCSV(val, mySeparator) : val));
126 }
127
134 void writeTime(std::ostream& /* into */, const SumoXMLAttr attr, const SUMOTime val) override {
135 checkAttr(attr);
136 myValues.emplace_back(time2string(val));
137 }
138
143 bool wroteHeader() const override {
144 return myWroteHeader;
145 }
146
161 void setExpectedAttributes(const SumoXMLAttrMask& expected, const int depth) override {
162 myExpectedAttrs = expected;
163 myMaxDepth = depth;
164 myCheckColumns = expected.any();
165 }
166
167private:
174 inline void checkAttr(const SumoXMLAttr attr) {
175 if (myCheckColumns && myMaxDepth == (int)myXMLStack.size()) {
176 mySeenAttrs.set(attr);
177 if (!myExpectedAttrs.test(attr)) {
178 throw ProcessError(TLF("Unexpected attribute '%', this file format does not support CSV output yet.", toString(attr)));
179 }
180 }
181 checkHeader(attr);
182 }
183
184 template <class ATTR_TYPE>
185 inline void checkHeader(const ATTR_TYPE& attr) {
186 myNeedsWrite = true;
187 if (!myWroteHeader) {
188 std::string headerName = toString(attr);
189 std::string prefix;
190 for (const auto& entry : myXMLStack) {
191 prefix += entry.first + "_";
192 }
193 const std::string fullHeaderName = prefix + headerName;
194 if (myHeaderFormat != "plain") {
195 headerName = myXMLStack.back().first + "_" + headerName;
196 }
197 const auto colIt = std::find(myFullHeader.begin(), myFullHeader.end(), fullHeaderName);
198 if (colIt == myFullHeader.end()) {
199 for (std::string& row : myBufferedRows) {
200 row += mySeparator;
201 }
202 myValues.resize(myHeader.size());
203 myHeader.emplace_back(headerName);
204 myFullHeader.emplace_back(fullHeaderName);
205 } else {
206 // there might be missing attributes inbetween, so make sure header position and value size match
207 myValues.resize(std::distance(myFullHeader.begin(), colIt));
208 }
209 }
210 }
211
213 const std::string myHeaderFormat;
214
216 const char mySeparator;
217
219 std::vector<std::string> myHeader;
220
222 std::vector<std::string> myFullHeader;
223
225 std::vector<std::pair<const std::string, int> > myXMLStack;
226
228 std::vector<std::string> myValues;
229
231 int myMaxDepth = 1000;
232
234 bool myWroteHeader = false;
235
237 bool myNeedsWrite = false;
238
240 bool myHaveRootAttrs = false;
241
243 std::vector<std::string> myBufferedRows;
244
246 bool myCheckColumns = false;
247
250
253};
long long int SUMOTime
Definition GUI.h:36
#define TLF(string,...)
Definition MsgHandler.h:306
std::string time2string(SUMOTime t, bool humanReadable)
convert SUMOTime to string (independently of global format setting)
Definition SUMOTime.cpp:91
SumoXMLTag
Numbers representing SUMO-XML - element names.
std::bitset< 96 > SumoXMLAttrMask
SumoXMLAttr
Numbers representing SUMO-XML - attributes.
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition ToString.h:49
Output formatter for CSV output.
const std::string myHeaderFormat
the format to use for the column names
bool myHaveRootAttrs
whether any root attribute have been encountered
void writeAttr(std::ostream &, const SumoXMLAttr attr, const std::string &val, const bool isNull, const bool escape)
typed overloads (non-template) – picked by overload resolution over the template
void openTag(std::ostream &into, const std::string &xmlElement) override
Keeps track of an open XML tag by adding a new element to the stack.
bool wroteHeader() const override
Whether a complete row has been encountered and triggered header writing.
bool myNeedsWrite
whether any attribute has been written since the last row was emitted
void writeAttr(std::ostream &, const std::string &attr, const std::string &val, const bool isNull, const bool escape)
void writeAttr(std::ostream &into, const SumoXMLAttr attr, const T &val, const bool isNull, const bool escape)
Writes a named attribute.
SumoXMLAttrMask myExpectedAttrs
which CSV columns are expected (just for checking completeness)
void writeTime(std::ostream &, const SumoXMLAttr attr, const SUMOTime val) override
Writes a time value using time2string.
bool closeTag(std::ostream &into, const std::string &comment="") override
Closes the most recently opened tag.
SumoXMLAttrMask mySeenAttrs
which CSV columns have been set (just for checking completeness)
std::vector< std::string > myHeader
the CSV header
virtual ~CSVFormatter() override
Destructor.
void setExpectedAttributes(const SumoXMLAttrMask &expected, const int depth) override
Which elements are expected and which maximum depth the XML tree has.
int myMaxDepth
the maximum depth of the XML hierarchy (excluding the root element)
bool writeXMLHeader(std::ostream &into, const std::string &rootElement, const std::map< SumoXMLAttr, std::string > &attrs, bool, bool) override
Writes an "XML header".
bool myCheckColumns
whether the columns should be checked for completeness
const char mySeparator
The value separator.
std::vector< std::pair< const std::string, int > > myXMLStack
The name and number of attributes in the currently open XML elements.
void writeAttr(std::ostream &into, const std::string &attr, const T &val, const bool isNull, const bool escape)
Writes a named attribute.
void checkHeader(const ATTR_TYPE &attr)
std::vector< std::string > myFullHeader
the CSV header if we write the full name
void checkAttr(const SumoXMLAttr attr)
Helper function to keep track of the written attributes and accumulate the header....
bool myWroteHeader
whether the CSV header line has been written
std::vector< std::string > myValues
the current attribute / column values
std::vector< std::string > myBufferedRows
partial rows buffered before the schema is known (depth < myMaxDepth)
Abstract base class for output formatters.
static std::string escapeCSV(const std::string &orig, const char separator, const char quote='"')
Adds quotes to strings containing the separator or the quote char and escapes the quote char with a b...
#define UNUSED_PARAMETER(x)