LCOV - code coverage report
Current view: top level - include/utils - DelimitedFileReader.h (source / functions) Hit Total Coverage
Test: idaholab/moose framework: 2bf808 Lines: 9 14 64.3 %
Date: 2025-07-17 01:28:37 Functions: 9 22 40.9 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : //* This file is part of the MOOSE framework
       2             : //* https://mooseframework.inl.gov
       3             : //*
       4             : //* All rights reserved, see COPYRIGHT for full restrictions
       5             : //* https://github.com/idaholab/moose/blob/master/COPYRIGHT
       6             : //*
       7             : //* Licensed under LGPL 2.1, please see LICENSE for details
       8             : //* https://www.gnu.org/licenses/lgpl-2.1.html
       9             : 
      10             : #pragma once
      11             : 
      12             : // STL includes
      13             : #include <vector>
      14             : #include <string>
      15             : #include <fstream>
      16             : 
      17             : #include "libmesh/parallel.h"
      18             : 
      19             : // MOOSE includes
      20             : #include "MooseEnum.h"
      21             : #include "MooseTypes.h"
      22             : 
      23             : namespace MooseUtils
      24             : {
      25             : 
      26             : /**
      27             :  * Utility class for reading delimited data (e.g., CSV data).
      28             :  * @param filename A string for the filename to read.
      29             :  * @param comm A pointer to a Communicator object (see below).
      30             :  *
      31             :  * This class assumes that all data is numeric and can be converted to a C++ double. If a
      32             :  * Communicator is provide then it will only read on processor 0 and broadcast the data to all
      33             :  * processors. If not provided it will read on all processors.
      34             :  */
      35             : template <typename T>
      36             : class DelimitedFileReaderTempl
      37             : {
      38             : public:
      39             :   enum class HeaderFlag
      40             :   {
      41             :     OFF = 0,
      42             :     ON = 1,
      43             :     AUTO = 2
      44             :   };
      45             : 
      46             :   enum class FormatFlag
      47             :   {
      48             :     COLUMNS = 0,
      49             :     ROWS = 1
      50             :   };
      51             : 
      52             :   const std::size_t INVALID_SIZE = std::numeric_limits<std::size_t>::max();
      53             : 
      54             :   DelimitedFileReaderTempl(const std::string & filename,
      55             :                            const libMesh::Parallel::Communicator * comm = nullptr);
      56             : 
      57             :   /**
      58             :    * Perform the actual data reading.
      59             :    *
      60             :    * This is a separate method to allow for the filename to be read multiple times.
      61             :    */
      62             :   void read();
      63             : 
      64             :   /**
      65             :    * Get the total number of entries in the file
      66             :    * @returns number of entries in file
      67             :    */
      68             :   std::size_t numEntries() const;
      69             : 
      70             :   ///@{
      71             :   /**
      72             :    * Set/Get methods for file format controls.
      73             :    *     IgnoreEmptyLines: When true all empty lines are ignored, when false an error is produced.
      74             :    *     FormatFlag: Set the file format (rows vs. columns).
      75             :    *     Delimiter: Set the file delimiter (if unset it will be detected).
      76             :    *     HeaderFlag: Set the header flag (TRUE used the first row has header, FALSE assumes no
      77             :    *                 header, and AUTO will attempt to determine if a header exists).
      78             :    *     Comment: Set the comment character, by default no comment character is used.
      79             :    */
      80         199 :   void setIgnoreEmptyLines(bool value) { _ignore_empty_lines = value; }
      81           0 :   bool getIgnoreEmptyLines() const { return _ignore_empty_lines; }
      82             : 
      83         895 :   void setFormatFlag(FormatFlag value) { _format_flag = value; }
      84           0 :   FormatFlag getFormatFlag() const { return _format_flag; }
      85             : 
      86          37 :   void setDelimiter(const std::string & value) { _delimiter = value; }
      87           0 :   const std::string & setDelimiter() const { return _delimiter; }
      88             : 
      89          91 :   void setHeaderFlag(HeaderFlag value) { _header_flag = value; }
      90           0 :   HeaderFlag getHeaderFlag() const { return _header_flag; }
      91             : 
      92         255 :   void setComment(const std::string & value) { _row_comment = value; }
      93           0 :   const std::string & getComment() const { return _row_comment; }
      94             :   ///@}
      95             : 
      96             :   /// Set the file name, used to change the file to read from
      97             :   /// We also reset the column/row names as a second read might have different names
      98          22 :   void setFileName(const std::string & new_file)
      99             :   {
     100          22 :     _filename = new_file;
     101          22 :     _names.clear();
     102          22 :   }
     103             : 
     104             :   /**
     105             :    * Return the column/row names.
     106             :    */
     107             :   const std::vector<std::string> & getNames() const;
     108             : 
     109             :   /**
     110             :    * Return the rows/columns of data.
     111             :    *
     112             :    * The outer vector is column and the inner the rows.
     113             :    */
     114             :   const std::vector<std::vector<T>> & getData() const;
     115             : 
     116             :   /**
     117             :    * Get the data in Point format. This performs checks that the data
     118             :    * is of valid dimensions to do so.
     119             :    */
     120             :   const std::vector<Point> getDataAsPoints() const;
     121             : 
     122             :   ///@{
     123             :   /**
     124             :    * Return the row/column of data for a specified header entry
     125             :    */
     126             :   const std::vector<T> & getData(const std::string & name) const;
     127             :   const std::vector<T> & getData(std::size_t index) const;
     128             :   ///@}
     129             : 
     130             : protected:
     131             :   /// The supplied filename.
     132             :   std::string _filename;
     133             : 
     134             :   /// Flag indicating if the file contains a header.
     135             :   HeaderFlag _header_flag;
     136             : 
     137             :   /// The delimiter separating the supplied data entires.
     138             :   std::string _delimiter;
     139             : 
     140             :   /// Flag for ignoring empty lines
     141             :   bool _ignore_empty_lines;
     142             : 
     143             :   /// Storage for the read or generated column names.
     144             :   std::vector<std::string> _names;
     145             : 
     146             :   /// Storage for the read data columns.
     147             :   std::vector<std::vector<T>> _data;
     148             : 
     149             :   /// Communicator
     150             :   const libMesh::Parallel::Communicator * const _communicator;
     151             : 
     152             :   /// Format "rows" vs "columns"
     153             :   FormatFlag _format_flag;
     154             : 
     155             :   /// Row offsets (only used with _format == "rows")
     156             :   std::vector<std::size_t> _row_offsets;
     157             : 
     158             :   /// Hide row comments
     159             :   std::string _row_comment;
     160             : 
     161             : private:
     162             :   ///@{
     163             :   /**
     164             :    * Read the numeric data as rows or columns into a single vector.
     165             :    */
     166             :   void readColumnData(std::ifstream & stream_data, std::vector<T> & output);
     167             :   void readRowData(std::ifstream & stream_data, std::vector<T> & output);
     168             :   ///@}
     169             : 
     170             :   /**
     171             :    * Populate supplied vector with content from line.
     172             :    * @param line The line to extract data from.
     173             :    * @param row The vector to populate.
     174             :    * @param num The current line number.
     175             :    */
     176             :   void processLine(const std::string & line, std::vector<T> & row, const unsigned int & num);
     177             : 
     178             :   /**
     179             :    * Check the content of the line and if it should be skipped.
     180             :    * @param line Complete line being read.
     181             :    * @param num The current line number.
     182             :    * @returns True if the line should be skipped.
     183             :    */
     184             :   bool preprocessLine(std::string & line, const unsigned int & num);
     185             : 
     186             :   /**
     187             :    * Determine the delimiter.
     188             :    *
     189             :    * If the setDelimiter method is not called the data is inspected, if a ',' is found it is assumed
     190             :    * to be the delimiter as is the case for \t. Otherwise a space is used.
     191             :    */
     192             :   const std::string & delimiter(const std::string & line);
     193             : 
     194             :   /**
     195             :    * Return the header flag, if it is set to AUTO attempt to determine if a header exists in line.
     196             :    */
     197             :   bool header(const std::string & line);
     198             : };
     199             : 
     200             : typedef DelimitedFileReaderTempl<double> DelimitedFileReader;
     201             : typedef DelimitedFileReaderTempl<std::string> DelimitedFileOfStringReader;
     202             : }

Generated by: LCOV version 1.14