24#include <ql/errors.hpp>
25#include <ql/math/comparison.hpp>
26#include <ql/math/rounding.hpp>
28#include <boost/filesystem/operations.hpp>
29#include <boost/filesystem/path.hpp>
30#include <boost/variant/static_visitor.hpp>
31#include <boost/algorithm/string/join.hpp>
39class ReportTypePrinter :
public boost::static_visitor<> {
41 ReportTypePrinter(FILE* fp,
int prec,
char quoteChar =
'\0',
const string& nullString =
"#N/A")
42 : fp_(fp), rounding_(prec,
QuantLib::Rounding::Closest), quoteChar_(quoteChar), null_(nullString) {}
44 void operator()(
const Size i)
const {
45 if (i == QuantLib::Null<Size>()) {
48 fprintf(fp_,
"%zu", i);
51 void operator()(
const Real d)
const {
52 if (d == QuantLib::Null<Real>() || !std::isfinite(d)) {
55 Real r = rounding_(d);
56 fprintf(fp_,
"%.*f", rounding_.precision(), QuantLib::close_enough(r, 0.0) ? 0.0 : r);
59 void operator()(
const string& s)
const { fprintString(s); }
60 void operator()(
const Date& d)
const {
61 if (d == QuantLib::Null<Date>()) {
68 void operator()(
const Period& p)
const {
73 void updateFile(FILE* fp) { fp_ = fp; }
76 void fprintNull()
const { fprintf(fp_,
"%s", null_.c_str()); }
79 void fprintString(
const string& s)
const {
80 bool quoted = s.size() > 1 && s[0] == quoteChar_ && s[s.size() - 1] == quoteChar_;
81 if (!quoted && quoteChar_ !=
'\0')
82 fputc(quoteChar_, fp_);
83 fprintf(fp_,
"%s", s.c_str());
84 if (!quoted && quoteChar_ !=
'\0')
85 fputc(quoteChar_, fp_);
89 QuantLib::Rounding rounding_;
95 const string& nullString,
bool lowerHeader, QuantLib::Size rolloverSize)
96 : filename_(filename), sep_(sep), commentCharacter_(commentCharacter), quoteChar_(quoteChar),
97 nullString_(nullString), lowerHeader_(lowerHeader), rolloverSize_(rolloverSize), i_(0), fp_(NULL) {
104 WLOG(
"CSV file report '" <<
filename_ <<
"' was not finalized, call end() on the report instance.");
112 QL_REQUIRE(
fp_,
"Error opening file '" <<
filename_ <<
"'");
123 boost::filesystem::path newFilepath =
125 boost::filesystem::path(p.stem().string() +
"_" +
to_string(
version_) + p.extension().string());
132 LOG(
"CVS file report '" <<
filename_ <<
"' is flushed");
145 string cpName =
name;
147 cpName[0] = std::tolower(
static_cast<unsigned char>(cpName[0]));
148 fprintf(
fp_,
"%s", cpName.c_str());
157 auto fileSize = boost::filesystem::file_size(
filename_);
167 QL_REQUIRE(
i_ ==
columnTypes_.size(),
"Cannot go to next line, only "
169 <<
" entries filled, report headers are: " << boost::join(
headers_,
","));
178 "No column to add [" << rt <<
"] to, report headers are: " << boost::join(
headers_,
","));
179 QL_REQUIRE(rt.which() ==
columnTypes_[
i_].which(),
"Cannot add value "
180 << rt <<
" of type " << rt.which() <<
" to column " <<
i_
182 <<
", report headers are: " << boost::join(
headers_,
","));
196 if (
int rc = fclose(
fp_)) {
197 ALOG(
"CSV file report '" <<
filename_ <<
"' can not be closed (return code " << rc <<
")");
202 ALOG(
"CSV file report '" <<
filename_ <<
"' can not be closed (file handle is null).");
205 QL_REQUIRE(
i_ ==
columnTypes_.size() ||
i_ == 0,
"csv report is finalized with incomplete row, got data for "
207 <<
", report headers are: " << boost::join(
headers_,
","));
212 QL_REQUIRE(!
finalized_,
"CSV file report '" <<
filename_ <<
"' is already finalized, can not process operation "
213 << op <<
", report headers are: " << boost::join(
headers_,
","));
std::string baseFilename_
Report & add(const ReportType &rt) override
std::vector< ReportTypePrinter > printers_
std::vector< std::string > headers_
CSVFileReport(const string &filename, const char sep=',', const bool commentCharacter=true, char quoteChar='\0', const std::string &nullString="#N/A", bool lowerHeader=false, QuantLib::Size rolloverSize=QuantLib::Null< QuantLib::Size >())
void checkIsOpen(const std::string &op) const
QuantLib::Size rolloverSize_
Report & addColumn(const string &name, const ReportType &rt, Size precision=0) override
std::vector< ReportType > columnTypes_
static FILE * fopen(const char *, const char *)
Retry wrapper for std::fopen.
boost::variant< Size, Real, string, Date, Period > ReportType
Wrapper class for retrying file IO operations.
Classes and functions for log message handling.
#define LOG(text)
Logging Macro (Level = Notice)
#define ALOG(text)
Logging Macro (Level = Alert)
#define WLOG(text)
Logging Macro (Level = Warning)
#define TLOG(text)
Logging Macro (Level = Data)
std::string to_string(const LocationInfo &l)
Serializable Credit Default Swap.
string conversion utilities