Vince's CSV Parser
Loading...
Searching...
No Matches
csv::DelimWriter< OutputStream, Delim, Quote > Class Template Reference

Class for writing delimiter separated values files. More...

#include <csv_writer.hpp>

Public Member Functions

 DelimWriter (OutputStream &_out, bool _quote_minimal=true)
 Construct a DelimWriter over the specified output stream.
 
template<typename T = OutputStream, csv::enable_if_t< std::is_same< T, std::ofstream >::value, int > = 0>
 DelimWriter (const std::string &filename, bool _quote_minimal=true)
 Construct a DelimWriter that owns an output file stream.
 
 DelimWriter (const DelimWriter &)=delete
 
DelimWriter & operator= (const DelimWriter &)=delete
 
 DelimWriter (DelimWriter &&other) noexcept
 
DelimWriter & operator= (DelimWriter &&other) noexcept
 
DelimWriter & set_auto_flush (bool value) &noexcept
 Configure whether each write operation flushes the underlying stream.
 
DelimWriter && set_auto_flush (bool value) &&noexcept
 Configure whether each write operation flushes the underlying stream.
 
bool get_auto_flush () const noexcept
 Return whether each write operation flushes the underlying stream.
 
 ~DelimWriter ()
 Best-effort flush.
 
template<typename T , size_t N>
DelimWriter & operator<< (const T(&record)[N])
 Write a C-style array of strings as one delimited row.
 
template<typename T , size_t N>
DelimWriter & operator<< (const std::array< T, N > &record)
 Write a std::array of strings as one delimited row.
 
template<typename KeyType >
DelimWriter & operator<< (const DataFrame< KeyType > &frame)
 Write a complete DataFrame: visible column names followed by visible rows.
 
template<typename T >
auto write_row (T &&record) -> decltype(*this<< std::forward< T >(record))
 Write a row from any single argument accepted by operator<< (std::vector, std::array, std::tuple, C-array, C++20 range, etc.).
 
template<typename T , typename U , typename... Rest>
DelimWriter & write_row (T &&first, U &&second, Rest &&... rest)
 Write a row from a variadic list of mixed-type values.
 
template<std::ranges::input_range Rows>
requires internals::csv_write_rows_input_range<Rows>
DelimWriter & write_rows (Rows &&rows)
 Write many rows using a shared batch buffer.
 
template<std::ranges::input_range Range>
requires std::ranges::input_range<Range> && std::convertible_to<std::ranges::range_reference_t<Range>, csv::string_view>
DelimWriter & operator<< (Range &&container)
 Write a range of string-like fields as one delimited row.
 
template<typename RowLike >
requires internals::has_to_sv_range<RowLike> && (!internals::csv_string_field_range<RowLike>)
DelimWriter & operator<< (const RowLike &row)
 Write a row-like object that exposes to_sv_range().
 
template<typename... T>
DelimWriter & operator<< (const std::tuple< T... > &record)
 Write a C-style array of strings as one delimited row.
 
void flush ()
 Flushes the written data.
 
template<typename T , csv::enable_if_t< internals::has_checked_csv_fields< T >::value||internals::is_data_frame< typename std::decay< T >::type >::value, int > = 0>
bool try_write_row (CSVError &error, T &&record)
 Write the same inputs accepted by write_row(), reporting stream failures.
 
template<typename... Args>
auto try_write_row (CSVError &error, Args &&... args) -> decltype(this->write_row(std::forward< Args >(args)...), bool())
 
template<std::ranges::input_range Rows>
requires (internals::csv_write_rows_input_range<Rows> || internals::has_checked_csv_fields<std::ranges::range_reference_t<Rows>>::value)
bool try_write_rows (Rows &&rows, CSVError &error)
 Write a batch using the same accepted row ranges and buffering policy as write_rows().
 
bool try_flush (CSVError &error)
 Flush buffered data and the stream, reporting I/O errors.
 
template<typename T = OutputStream, csv::enable_if_t< std::is_same< T, std::ofstream >::value, int > = 0>
bool try_close (CSVError &error)
 Flush and close an owned output file, including after a flush failure.
 

Static Public Member Functions

template<typename T = OutputStream, csv::enable_if_t< std::is_same< T, std::ofstream >::value, int > = 0>
static std::unique_ptr< DelimWriter > try_open (const std::string &filename, CSVError &error, bool quote_minimal=true)
 Open an owned output file, returning null on failure.
 

Detailed Description

template<class OutputStream, char Delim, char Quote>
class csv::DelimWriter< OutputStream, Delim, Quote >

Class for writing delimiter separated values files.

To write formatted strings, one should

  1. Initialize a DelimWriter with respect to some output stream
  2. Call write_row() on std::vector<std::string>s of unformatted text
Template Parameters
OutputStreamThe output stream, e.g. std::ofstream, std::stringstream
DelimThe delimiter character
QuoteThe quote character
Hint
Use the aliases csv::CSVWriter<OutputStream> to write CSV formatted strings and csv::TSVWriter<OutputStream> to write tab separated strings
Example w/ std::vector, std::deque, std::list
TEMPLATE_TEST_CASE("CSV/TSV Writer - operator <<", "[test_csv_operator<<]",
std::vector<std::string>, std::deque<std::string>, std::list<std::string>) {
std::stringstream output, correct_comma, correct_tab;
// Build correct strings
correct_comma << "A,B,C" << std::endl << "\"1,1\",2,3" << std::endl;
correct_tab << "A\tB\tC" << std::endl << "1,1\t2\t3" << std::endl;
// Test input
auto test_row_1 = TestType({ "A", "B", "C" }),
test_row_2 = TestType({ "1,1", "2", "3" });
SECTION("CSV Writer") {
auto csv_writer = make_csv_writer(output);
csv_writer << test_row_1 << test_row_2;
REQUIRE(output.str() == correct_comma.str());
}
SECTION("TSV Writer") {
auto tsv_writer = make_tsv_writer(output);
tsv_writer << test_row_1 << test_row_2;
REQUIRE(output.str() == correct_tab.str());
}
}
TSVWriter< OutputStream > make_tsv_writer(OutputStream &out, bool quote_minimal=true)
Return a csv::TSVWriter over the output stream.
CSVWriter< OutputStream > make_csv_writer(OutputStream &out, bool quote_minimal=true)
Return a csv::CSVWriter over the output stream.
Example w/ std::tuple
struct Time {
std::string hour;
std::string minute;
operator std::string() const {
std::string ret = hour;
ret += ":";
ret += minute;
return ret;
}
};
#ifndef __clang__
TEST_CASE("CSV Tuple", "[test_csv_tuple]") {
#ifdef CSV_HAS_CXX17
Time time = { "5", "30" };
#else
std::string time = "5:30";
#endif
std::stringstream output, correct_output;
auto csv_writer = make_csv_writer(output);
csv_writer << std::make_tuple("One", 2, "Three", 4.0, time)
<< std::make_tuple("One", (short)2, "Three", 4.0f, time)
<< std::make_tuple(-1, -2.0)
<< std::make_tuple(20.2, -20.3, -20.123)
<< std::make_tuple(0.0, 0.0f, 0);
correct_output << "One,2,Three,4.0,5:30" << std::endl
<< "One,2,Three,4.0,5:30" << std::endl
<< "-1,-2.0" << std::endl
<< "20.20000,-20.30000,-20.12300" << std::endl
<< "0.0,0.0,0" << std::endl;
REQUIRE(output.str() == correct_output.str());
}
#endif

Definition at line 272 of file csv_writer.hpp.

Constructor & Destructor Documentation

◆ DelimWriter() [1/3]

template<class OutputStream , char Delim, char Quote>
csv::DelimWriter< OutputStream, Delim, Quote >::DelimWriter ( OutputStream &  _out,
bool  _quote_minimal = true 
)
inline

Construct a DelimWriter over the specified output stream.

Definition at line 276 of file csv_writer.hpp.

◆ DelimWriter() [2/3]

template<class OutputStream , char Delim, char Quote>
template<typename T = OutputStream, csv::enable_if_t< std::is_same< T, std::ofstream >::value, int > = 0>
csv::DelimWriter< OutputStream, Delim, Quote >::DelimWriter ( const std::string &  filename,
bool  _quote_minimal = true 
)
inline

Construct a DelimWriter that owns an output file stream.

Definition at line 283 of file csv_writer.hpp.

◆ DelimWriter() [3/3]

template<class OutputStream , char Delim, char Quote>
csv::DelimWriter< OutputStream, Delim, Quote >::DelimWriter ( DelimWriter< OutputStream, Delim, Quote > &&  other)
inlinenoexcept

Definition at line 312 of file csv_writer.hpp.

◆ ~DelimWriter()

template<class OutputStream , char Delim, char Quote>
csv::DelimWriter< OutputStream, Delim, Quote >::~DelimWriter ( )
inline

Best-effort flush.

Use try_flush() or try_close() to observe errors.

Definition at line 361 of file csv_writer.hpp.

Member Function Documentation

◆ flush()

template<class OutputStream , char Delim, char Quote>
void csv::DelimWriter< OutputStream, Delim, Quote >::flush ( )
inline

Flushes the written data.

Definition at line 530 of file csv_writer.hpp.

◆ get_auto_flush()

template<class OutputStream , char Delim, char Quote>
bool csv::DelimWriter< OutputStream, Delim, Quote >::get_auto_flush ( ) const
inlinenoexcept

Return whether each write operation flushes the underlying stream.

Definition at line 356 of file csv_writer.hpp.

◆ operator<<() [1/6]

template<class OutputStream , char Delim, char Quote>
template<typename KeyType >
DelimWriter & csv::DelimWriter< OutputStream, Delim, Quote >::operator<< ( const DataFrame< KeyType > &  frame)
inline

Write a complete DataFrame: visible column names followed by visible rows.

Sparse edits and row selections are included. A frame with no rows still writes its header. The writer's delimiter, quoting, and buffering settings apply, and auto-flush flushes the stream once at the end of the document.

Definition at line 396 of file csv_writer.hpp.

◆ operator<<() [2/6]

template<class OutputStream , char Delim, char Quote>
template<typename RowLike >
requires internals::has_to_sv_range<RowLike> && (!internals::csv_string_field_range<RowLike>)
DelimWriter & csv::DelimWriter< OutputStream, Delim, Quote >::operator<< ( const RowLike &  row)
inline

Write a row-like object that exposes to_sv_range().

Definition at line 493 of file csv_writer.hpp.

◆ operator<<() [3/6]

template<class OutputStream , char Delim, char Quote>
template<typename T , size_t N>
DelimWriter & csv::DelimWriter< OutputStream, Delim, Quote >::operator<< ( const std::array< T, N > &  record)
inline

Write a std::array of strings as one delimited row.

Definition at line 384 of file csv_writer.hpp.

◆ operator<<() [4/6]

template<class OutputStream , char Delim, char Quote>
template<typename... T>
DelimWriter & csv::DelimWriter< OutputStream, Delim, Quote >::operator<< ( const std::tuple< T... > &  record)
inline

Write a C-style array of strings as one delimited row.

Definition at line 524 of file csv_writer.hpp.

◆ operator<<() [5/6]

template<class OutputStream , char Delim, char Quote>
template<typename T , size_t N>
DelimWriter & csv::DelimWriter< OutputStream, Delim, Quote >::operator<< ( const T(&)  record[N])
inline

Write a C-style array of strings as one delimited row.

Definition at line 377 of file csv_writer.hpp.

◆ operator<<() [6/6]

template<class OutputStream , char Delim, char Quote>
template<std::ranges::input_range Range>
requires std::ranges::input_range<Range> && std::convertible_to<std::ranges::range_reference_t<Range>, csv::string_view>
DelimWriter & csv::DelimWriter< OutputStream, Delim, Quote >::operator<< ( Range &&  container)
inline

Write a range of string-like fields as one delimited row.

Accepts any input_range whose elements are convertible to csv::string_view. This includes std::vector<std::string>, std::vector<csv::string_view>, std::array, C++20 views, etc.

Definition at line 484 of file csv_writer.hpp.

◆ operator=()

template<class OutputStream , char Delim, char Quote>
DelimWriter & csv::DelimWriter< OutputStream, Delim, Quote >::operator= ( DelimWriter< OutputStream, Delim, Quote > &&  other)
inlinenoexcept

Definition at line 325 of file csv_writer.hpp.

◆ set_auto_flush() [1/2]

template<class OutputStream , char Delim, char Quote>
DelimWriter && csv::DelimWriter< OutputStream, Delim, Quote >::set_auto_flush ( bool  value) &&
inlinenoexcept

Configure whether each write operation flushes the underlying stream.

Definition at line 350 of file csv_writer.hpp.

◆ set_auto_flush() [2/2]

template<class OutputStream , char Delim, char Quote>
DelimWriter & csv::DelimWriter< OutputStream, Delim, Quote >::set_auto_flush ( bool  value) &
inlinenoexcept

Configure whether each write operation flushes the underlying stream.

Definition at line 344 of file csv_writer.hpp.

◆ try_close()

template<class OutputStream , char Delim, char Quote>
template<typename T = OutputStream, csv::enable_if_t< std::is_same< T, std::ofstream >::value, int > = 0>
bool csv::DelimWriter< OutputStream, Delim, Quote >::try_close ( CSVError &  error)
inline

Flush and close an owned output file, including after a flush failure.

Borrowed streams remain the caller's responsibility to close. Further checked operations on a closed writer report InvalidArgument.

Definition at line 586 of file csv_writer.hpp.

◆ try_flush()

template<class OutputStream , char Delim, char Quote>
bool csv::DelimWriter< OutputStream, Delim, Quote >::try_flush ( CSVError &  error)
inline

Flush buffered data and the stream, reporting I/O errors.

Definition at line 573 of file csv_writer.hpp.

◆ try_open()

template<class OutputStream , char Delim, char Quote>
template<typename T = OutputStream, csv::enable_if_t< std::is_same< T, std::ofstream >::value, int > = 0>
static std::unique_ptr< DelimWriter > csv::DelimWriter< OutputStream, Delim, Quote >::try_open ( const std::string &  filename,
CSVError &  error,
bool  quote_minimal = true 
)
inlinestatic

Open an owned output file, returning null on failure.

The returned writer owns its stream. Use try_close() to observe final I/O errors.

Definition at line 296 of file csv_writer.hpp.

◆ try_write_row() [1/2]

template<class OutputStream , char Delim, char Quote>
template<typename... Args>
auto csv::DelimWriter< OutputStream, Delim, Quote >::try_write_row ( CSVError &  error,
Args &&...  args 
) -> decltype(this->write_row(std::forward<Args>(args)...), bool())
inline

Definition at line 549 of file csv_writer.hpp.

◆ try_write_row() [2/2]

template<class OutputStream , char Delim, char Quote>
template<typename T , csv::enable_if_t< internals::has_checked_csv_fields< T >::value||internals::is_data_frame< typename std::decay< T >::type >::value, int > = 0>
bool csv::DelimWriter< OutputStream, Delim, Quote >::try_write_row ( CSVError &  error,
T &&  record 
)
inline

Write the same inputs accepted by write_row(), reporting stream failures.

With buffering enabled, success means accepted into the buffer; try_flush() or try_close() observes completion. Output already written is not rolled back. Checked operations require a stream exposing fail(). In exception-disabled builds, standard streams must have their exception mask disabled.

Definition at line 544 of file csv_writer.hpp.

◆ try_write_rows()

template<class OutputStream , char Delim, char Quote>
template<std::ranges::input_range Rows>
requires (internals::csv_write_rows_input_range<Rows> || internals::has_checked_csv_fields<std::ranges::range_reference_t<Rows>>::value)
bool csv::DelimWriter< OutputStream, Delim, Quote >::try_write_rows ( Rows &&  rows,
CSVError &  error 
)
inline

Write a batch using the same accepted row ranges and buffering policy as write_rows().

Definition at line 559 of file csv_writer.hpp.

◆ write_row() [1/2]

template<class OutputStream , char Delim, char Quote>
template<typename T , typename U , typename... Rest>
DelimWriter & csv::DelimWriter< OutputStream, Delim, Quote >::write_row ( T &&  first,
U &&  second,
Rest &&...  rest 
)
inline

Write a row from a variadic list of mixed-type values.

Requires at least two arguments; for a single container or tuple, use the single-argument overload above.

writer.write_row("Alice", 30, 1.75, "Paris");

Definition at line 443 of file csv_writer.hpp.

◆ write_row() [2/2]

template<class OutputStream , char Delim, char Quote>
template<typename T >
auto csv::DelimWriter< OutputStream, Delim, Quote >::write_row ( T &&  record) -> decltype(*this << std::forward<T>(record))
inline

Write a row from any single argument accepted by operator<< (std::vector, std::array, std::tuple, C-array, C++20 range, etc.).

writer.write_row(my_vector);
writer.write_row(my_tuple);

SFINAE ensures this overload is only viable when the argument type is accepted by an existing operator<< overload.

Definition at line 429 of file csv_writer.hpp.

◆ write_rows()

template<class OutputStream , char Delim, char Quote>
template<std::ranges::input_range Rows>
requires internals::csv_write_rows_input_range<Rows>
DelimWriter & csv::DelimWriter< OutputStream, Delim, Quote >::write_rows ( Rows &&  rows)
inline

Write many rows using a shared batch buffer.

Accepts any input_range whose elements are either:

  • ranges of string-like fields, or
  • row-like objects exposing to_sv_range().

Buffered writers flush the batch when it grows large or when this call ends. Auto-flushing writers additionally flush the underlying stream once at the end of the bulk call.

Passing a DataFrame writes data rows only. Use operator<< to include its column names as a header.

Note
Requires C++20 or later.

Definition at line 467 of file csv_writer.hpp.


The documentation for this class was generated from the following file: