LCOV - code coverage report
Current view: top level - src/utils/iodevices - CSVFormatter.cpp (source / functions) Coverage Total Hit
Test: lcov.info Lines: 94.7 % 38 36
Test Date: 2026-03-26 16:31:35 Functions: 100.0 % 4 4

            Line data    Source code
       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              : /****************************************************************************/
      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              : #ifdef HAVE_FMT
      23              : #include <fmt/ostream.h>
      24              : #include <fmt/ranges.h>
      25              : #endif
      26              : #include <utils/common/MsgHandler.h>
      27              : #include <utils/common/ToString.h>
      28              : #include "CSVFormatter.h"
      29              : 
      30              : 
      31              : // ===========================================================================
      32              : // member method definitions
      33              : // ===========================================================================
      34           28 : CSVFormatter::CSVFormatter(const std::string& columnNames, const char separator)
      35           28 :     : OutputFormatter(OutputFormatterType::CSV), myHeaderFormat(columnNames), mySeparator(separator) {
      36           28 :     if (myHeaderFormat == "none") {
      37            0 :         myWroteHeader = true;
      38              :     }
      39           28 : }
      40              : 
      41              : 
      42              : void
      43         6567 : CSVFormatter::openTag(std::ostream& /* into */, const std::string& xmlElement) {
      44         6567 :     myXMLStack.push_back((int)myValues.size());
      45         6567 :     if (!myWroteHeader) {
      46         5501 :         myCurrentTag = xmlElement;
      47              :     }
      48         6567 :     if (myMaxDepth == (int)myXMLStack.size() && myWroteHeader && myCurrentTag != xmlElement) {
      49          699 :         WRITE_WARNINGF("Encountered mismatch in XML tags (expected % but got %). Column names may be incorrect.", myCurrentTag, xmlElement);
      50              :     }
      51         6567 : }
      52              : 
      53              : 
      54              : void
      55         1612 : CSVFormatter::openTag(std::ostream& /* into */, const SumoXMLTag& xmlElement) {
      56         1612 :     myXMLStack.push_back((int)myValues.size());
      57         1612 :     if (!myWroteHeader) {
      58          516 :         myCurrentTag = toString(xmlElement);
      59              :     }
      60         2746 :     if (myMaxDepth == (int)myXMLStack.size() && myWroteHeader && myCurrentTag != toString(xmlElement)) {
      61           33 :         WRITE_WARNINGF("Encountered mismatch in XML tags (expected % but got %). Column names may be incorrect.", myCurrentTag, toString(xmlElement));
      62              :     }
      63         1612 : }
      64              : 
      65              : 
      66              : bool
      67         8207 : CSVFormatter::closeTag(std::ostream& into, const std::string& /* comment */) {
      68         8207 :     if (myMaxDepth == 0) {
      69              :         // the auto detection case: the first closed tag determines the depth
      70            0 :         myMaxDepth = (int)myXMLStack.size();
      71              :     }
      72         8207 :     if ((myMaxDepth == (int)myXMLStack.size() || myXMLStack.empty()) && !myWroteHeader) {
      73              :         // First complete row or EOF: write the header
      74           28 :         if (!myCheckColumns) {
      75           42 :             WRITE_WARNING("Column based formats are still experimental. Autodetection only works for homogeneous output.");
      76              :         }
      77              : #ifdef HAVE_FMT
      78              :         fmt::print(into, "{}\n", fmt::join(myHeader, std::string_view(&mySeparator, 1)));
      79              : #else
      80           56 :         into << joinToString(myHeader, mySeparator) << "\n";
      81              : #endif
      82           28 :         myWroteHeader = true;
      83              :     }
      84         8207 :     if (myNeedsWrite) {
      85              : #ifdef HAVE_FMT
      86              :         const std::string row = fmt::format("{}", fmt::join(myValues, std::string_view(&mySeparator, 1)));
      87              : #else
      88         7285 :         const std::string row = joinToString(myValues, mySeparator);
      89              : #endif
      90         7285 :         myBufferedRows.emplace_back(row);
      91              :         mySeenAttrs.reset();
      92         7285 :         myNeedsWrite = false;
      93              :     }
      94         8207 :     if (myWroteHeader && !myBufferedRows.empty()) {
      95         9002 :         for (const std::string& row : myBufferedRows) {
      96         7285 :             into << row << '\n';
      97              :         }
      98              :         myBufferedRows.clear();
      99              :     }
     100         8207 :     if (!myXMLStack.empty()) {
     101         8179 :         if ((int)myValues.size() > myXMLStack.back()) {
     102         7979 :             myValues.resize(myXMLStack.back());
     103              :         }
     104              :         myXMLStack.pop_back();
     105              :     }
     106         8207 :     return false;
     107              : }
     108              : 
     109              : 
     110              : /****************************************************************************/
        

Generated by: LCOV version 2.0-1