mirror of
https://gitlab.com/kicad/code/kicad.git
synced 2025-09-14 02:03:12 +02:00
Avoids having to reason about locales where the decimal separator is a comma. This should still work for IO purposes (checked in LibreOffice, numbers still end up right aligned as expected).
103 lines
2.5 KiB
C++
103 lines
2.5 KiB
C++
|
|
|
|
#include "csv.h"
|
|
|
|
#include <wx/txtstrm.h>
|
|
|
|
#include <rapidcsv/rapidcsv.h>
|
|
|
|
|
|
CSV_WRITER::CSV_WRITER( wxOutputStream& aStream ) :
|
|
m_stream( aStream ), m_delimiter( wxT( "," ) ),
|
|
m_quote( wxT( "\"" ) ), m_lineTerminator( wxT( "\n" ) ),
|
|
m_escape( wxEmptyString )
|
|
{
|
|
}
|
|
|
|
|
|
void CSV_WRITER::WriteLines( const std::vector<std::vector<wxString>>& aRows )
|
|
{
|
|
for( const auto& row : aRows )
|
|
{
|
|
WriteLine( row );
|
|
}
|
|
}
|
|
|
|
|
|
void CSV_WRITER::WriteLine( const std::vector<wxString>& cols )
|
|
{
|
|
wxString line;
|
|
|
|
for( size_t i = 0; i < cols.size(); ++i )
|
|
{
|
|
wxString colVal = cols[i];
|
|
|
|
if( i > 0 )
|
|
line += m_delimiter;
|
|
|
|
|
|
const bool useEscape = m_escape.size();
|
|
|
|
if( useEscape )
|
|
{
|
|
colVal.Replace( m_quote, m_escape + m_quote, true );
|
|
}
|
|
else
|
|
{
|
|
colVal.Replace( m_quote, m_quote + m_quote, true );
|
|
}
|
|
|
|
// Always quote - if that's a problem, we can only quote if the
|
|
// delimiter (or newlines?) are present in the string.
|
|
colVal = m_quote + colVal + m_quote;
|
|
|
|
|
|
line += colVal;
|
|
}
|
|
|
|
line += m_lineTerminator;
|
|
|
|
// Always write text on file using UTF8 encoding
|
|
std::string utf8str( line.utf8_string() );
|
|
m_stream.Write( utf8str.data(), utf8str.length() );
|
|
}
|
|
|
|
|
|
bool AutoDecodeCSV( const wxString& aInput, std::vector<std::vector<wxString>>& aData )
|
|
{
|
|
// Read the first line to determine the delimiter
|
|
bool trimCells = true;
|
|
bool skipCommentLines = true;
|
|
bool skipEmptyLines = true;
|
|
char commentPrefix = '#';
|
|
char delimiter = ',';
|
|
|
|
// Assume if we find a tab, we are dealing with a TSV file
|
|
if( aInput.find( '\t' ) != std::string::npos )
|
|
{
|
|
delimiter = '\t';
|
|
}
|
|
|
|
std::istringstream inputStream( aInput.ToStdString() );
|
|
|
|
rapidcsv::Document doc( inputStream, rapidcsv::LabelParams( -1, -1 ),
|
|
rapidcsv::SeparatorParams( delimiter, trimCells ), rapidcsv::ConverterParams(),
|
|
rapidcsv::LineReaderParams( skipCommentLines, commentPrefix, skipEmptyLines ) );
|
|
|
|
// Read the data into aData
|
|
aData.clear();
|
|
|
|
for( size_t i = 0; i < doc.GetRowCount(); ++i )
|
|
{
|
|
std::vector<wxString>& row = aData.emplace_back();
|
|
for( size_t j = 0; j < doc.GetColumnCount(); ++j )
|
|
{
|
|
std::string cell = doc.GetCell<std::string>( j, i );
|
|
row.emplace_back( cell );
|
|
}
|
|
}
|
|
|
|
// Anything in the first row?
|
|
return aData[0].size() > 0;
|
|
}
|