//
// Copyright (c) 2010, Brian Frank and Andy Frank
// Licensed under the Academic Free License version 3.0
//
// History:
// 20 Mar 10 Brian Frank Creation
//
**
** CsvOutStream is used to write delimiter-separated values
** as specified by RFC 4180. Format details:
** - rows are delimited by a newline
** - cells are separated by `delimiter` char
** - cells containing the delimiter, '"' double quote, or
** newline are quoted; quotes are escaped as '""'
**
** Also see `CsvInStream`.
**
@Js
class CsvOutStream : OutStream
{
**
** Wrap the underlying output stream.
**
new make(OutStream out) : super(out) {}
**
** Delimiter character; defaults to comma.
**
Int delimiter := ','
**
** Write the row of cells with the configured delimiter.
** Also see `writeCell`.
**
virtual This writeRow(Str[] row)
{
row.each |cell, i|
{
if (i > 0) writeChar(delimiter)
writeCell(cell)
}
return writeChar('\n')
}
**
** Write a single cell. If `isQuoteRequired` returns true,
** then quote it.
**
virtual This writeCell(Str cell)
{
if (!isQuoteRequired(cell)) return print(cell)
writeChar('"')
cell.each |ch|
{
if (ch == '"') writeChar('"')
writeChar(ch)
}
return writeChar('"')
}
**
** Return if the given cell string contains:
** - the configured delimiter
** - double quote '"' char
** - leading/trailing whitespace
** - newlines
**
Bool isQuoteRequired(Str cell)
{
if (cell.isEmpty) return true
if (cell[0].isSpace || cell[-1].isSpace) return true
return cell.any |ch| { ch == delimiter || ch == '"' || ch == '\n' || ch == '\r' }
}
}