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-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/****************************************************************************/
18// Output formatter for CSV output
19/****************************************************************************/
20#pragma once
21#include <config.h>
22
23#include <memory>
24#ifdef HAVE_FMT
25#include <fmt/ostream.h>
26#endif
27
28#include "OutputFormatter.h"
29
30
31// ===========================================================================
32// class definitions
33// ===========================================================================
39public:
41 CSVFormatter(const std::string& columnNames, const char separator = ';');
42
44 virtual ~CSVFormatter() { }
45
52 void openTag(std::ostream& into, const std::string& xmlElement);
53
59 void openTag(std::ostream& into, const SumoXMLTag& xmlElement);
60
67 bool closeTag(std::ostream& into, const std::string& comment = "");
68
75 template <class T>
76 void writeAttr(std::ostream& into, const SumoXMLAttr attr, const T& val) {
77 checkAttr(attr);
78 *myXMLStack[myCurrentDepth - 1] << toString(val, into.precision()) << mySeparator;
79 }
80
81 template <class T>
82 void writeAttr(std::ostream& into, const std::string& attr, const T& val) {
83 assert(!myCheckColumns);
84 if (!myWroteHeader) {
85 if (std::find(myHeader.begin(), myHeader.end(), attr) != myHeader.end()) {
86 myHeader.push_back(myCurrentTag + "_" + attr);
87 } else {
88 myHeader.push_back(attr);
89 }
90 }
91 *myXMLStack[myCurrentDepth - 1] << toString(val, into.precision()) << mySeparator;
92 }
93
94 void writeNull(std::ostream& /* into */, const SumoXMLAttr attr) {
95 checkAttr(attr);
97 }
98
99 void writeTime(std::ostream& /* into */, const SumoXMLAttr attr, const SUMOTime val) {
100 checkAttr(attr);
102 }
103
104 bool wroteHeader() const {
105 return myWroteHeader;
106 }
107
108 void setExpectedAttributes(const SumoXMLAttrMask& expected, const int depth = 2) {
109 myExpectedAttrs = expected;
110 myMaxDepth = depth;
111 myCheckColumns = expected.any();
112 }
113
114private:
121 inline void checkAttr(const SumoXMLAttr attr) {
123 mySeenAttrs.set(attr);
124 if (!myExpectedAttrs.test(attr)) {
125 throw ProcessError(TLF("Unexpected attribute '%', this file format does not support CSV output yet.", toString(attr)));
126 }
127 }
128 if (!myWroteHeader) {
129 const std::string attrString = toString(attr);
130 if (myHeaderFormat == "plain" || (myHeaderFormat == "auto" && std::find(myHeader.begin(), myHeader.end(), attrString) == myHeader.end())) {
131 myHeader.push_back(attrString);
132 } else {
133 myHeader.push_back(myCurrentTag + "_" + attrString);
134 }
135 }
136 }
137
139 const std::string myHeaderFormat;
140
142 const char mySeparator;
143
145 std::vector<std::string> myHeader;
146
148 std::string myCurrentTag;
149
151 std::vector<std::unique_ptr<std::ostringstream>> myXMLStack;
152
154 int myMaxDepth = 0;
155
158
160 bool myWroteHeader = false;
161
163 bool myCheckColumns = false;
164
167
170};
171
172
173// ===========================================================================
174// specialized template implementations (for speedup)
175// ===========================================================================
176template <>
177inline void CSVFormatter::writeAttr(std::ostream& into, const SumoXMLAttr attr, const double& val) {
178 checkAttr(attr);
179#ifdef HAVE_FMT
180 fmt::print(*myXMLStack[myCurrentDepth - 1], "{:.{}f}{}", val, into.precision(), mySeparator);
181#else
182 *myXMLStack[myCurrentDepth - 1] << toString(val, into.precision()) << mySeparator;
183#endif
184}
185
186
187template <>
188inline void CSVFormatter::writeAttr(std::ostream& /* into */, const SumoXMLAttr attr, const std::string& val) {
189 checkAttr(attr);
190 *myXMLStack[myCurrentDepth - 1] << val << mySeparator;
191}
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:46
Output formatter for CSV output.
const std::string myHeaderFormat
the format to use for the column names
int myCurrentDepth
the current depth of the XML hierarchy (excluding the root element)
std::string myCurrentTag
the currently read tag (only valid when generating the header)
bool wroteHeader() const
Returns whether a header has been written. Useful to detect whether a file is being used by multiple ...
void writeNull(std::ostream &, const SumoXMLAttr attr)
SumoXMLAttrMask myExpectedAttrs
which CSV columns are expected (just for checking completeness)
void setExpectedAttributes(const SumoXMLAttrMask &expected, const int depth=2)
Set the expected attributes to write. This is used for tracking which attributes are expected in tabl...
SumoXMLAttrMask mySeenAttrs
which CSV columns have been set (just for checking completeness)
void writeAttr(std::ostream &into, const SumoXMLAttr attr, const T &val)
writes a named attribute
std::vector< std::string > myHeader
the CSV header
virtual ~CSVFormatter()
Destructor.
void writeAttr(std::ostream &into, const std::string &attr, const T &val)
int myMaxDepth
the maximum depth of the XML hierarchy (excluding the root element)
bool myCheckColumns
whether the columns should be checked for completeness
const char mySeparator
The value separator.
bool closeTag(std::ostream &into, const std::string &comment="")
Closes the most recently opened tag.
void openTag(std::ostream &into, const std::string &xmlElement)
Keeps track of an open XML tag by adding a new element to the stack.
std::vector< std::unique_ptr< std::ostringstream > > myXMLStack
The attributes to write for each begun xml element (excluding the root element)
void writeTime(std::ostream &, const SumoXMLAttr attr, const SUMOTime val)
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
Abstract base class for output formatters.