Program Listing for File csv_sink.hpp

Return to documentation for file (rcppsw/metrics/csv_sink.hpp)

#pragma once

/*******************************************************************************
 * Includes
 ******************************************************************************/
#include <boost/optional.hpp>
#include <list>
#include <string>
#include <filesystem>
#include <memory>

#include "rcppsw/metrics/file_sink.hpp"
#include "rcppsw/metrics/output_mode.hpp"

/*******************************************************************************
 * Namespaces/Decls
 ******************************************************************************/
namespace rcppsw::metrics {
namespace fs = std::filesystem;

/*******************************************************************************
 * Class Definitions
 ******************************************************************************/
class csv_sink : public rmetrics::file_sink,
                 public rer::client<csv_sink> {
 public:
  csv_sink(fs::path fpath,
           const rmetrics::output_mode& mode,
           const rtypes::timestep& interval);

  virtual ~csv_sink(void) = default;

  /* base metrics sink overrides */
  void finalize(void) override;
  void initialize(const rmetrics::base_data* data) override;
  write_status flush(const rmetrics::base_data* data,
                     const rtypes::timestep& t) override;

 protected:
  virtual std::list<std::string> csv_header_cols(
      const rmetrics::base_data* data) const = 0;

  virtual boost::optional<std::string> csv_line_build(
      const rmetrics::base_data* data,
      const rtypes::timestep& t) = 0;

  std::list<std::string> dflt_csv_header_cols(void) const { return { "clock" }; }

  const std::string& separator(void) const { return mc_separator; }

  template <class T, class U>
  std::string
  csv_entry_domavg(const T& sum, const U& count, bool last = false) const {
    std::string tmp;
    if (count > 0) {
      /*
       * If the thing we have summed is int, size_t, etc., casting the count to
       * double makes sure we get good averages. This form also supports
       * non-primitive types that are summable and define an appropriate
       * operator/() and can be converted to a string.
       */
      tmp = rcppsw::to_string(sum / static_cast<double>(count));
    } else {
      tmp = "0";
    }
    return tmp + ((last) ? "" : separator());
  }

  template <class T>
  std::string csv_entry_intavg(const T& sum, bool last = false) const {
    /*
     * If the thing we have summed is int, size_t, etc., casting the count to
     * double makes sure we get good averages. This form also supports
     * non-primitive types that are summable and define an appropriate
     * operator/() and can be converted to a string.
     */
    return  rcppsw::to_string(sum / static_cast<double>(output_interval().v())) +
        ((last) ? "" : separator());
  }

  template <class T>
  std::string csv_entry_tsavg(const T& sum,
                              const rtypes::timestep& t,
                              bool last = false) const {
    return rcppsw::to_string(sum / static_cast<double>(t.v())) +
        ((last) ? "" : separator());
  }

  void csv_header_write(const rmetrics::base_data* data);


  /* clang-format off */
  const std::string mc_separator{";"};
  /* clang-format on */
};

} /* namespace rcppsw::metrics */