Loading...
Searching...
No Matches
tsvreader.cpp
Go to the documentation of this file.
/**
* \file odsstream/tsvreader.cpp
* \date 11/11/2018
* \author Olivier Langella
* \brief parser for text files (tsv, csv)
*/
/*******************************************************************************
* Copyright (c) 2018 Olivier Langella <Olivier.Langella@u-psud.fr>.
*
* This file is part of the libodsstream library.
*
* libodsstream is a library to read and write ODS documents as streams
* Copyright (C) 2018 Olivier Langella <Olivier.Langella@u-psud.fr>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published
*by the Free Software Foundation, either version 3 of the License, or (at your
*option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* Contributors:
* Olivier Langella <Olivier.Langella@u-psud.fr> - initial API and
*implementation
******************************************************************************/
#include "tsvreader.h"
#include "odsexception.h"
#include <QFileInfo>
#include <QChar>
#include <QDebug>
#include "reader/odscell.h"
TsvReader::TsvReader(OdsDocHandlerInterface &handler) : m_handler(handler)
{
}
TsvReader::~TsvReader()
{
}
void
TsvReader::setSeparator(TsvSeparator separator)
{
switch(separator)
{
case TsvSeparator::tab:
m_separator = '\t';
break;
case TsvSeparator::comma:
m_separator = ',';
break;
case TsvSeparator::semicolon:
m_separator = ';';
break;
}
}
void
TsvReader::parse(QFile &tsvFile)
{
qDebug() << tsvFile.fileName();
QFileInfo tsv_file_info(tsvFile.fileName());
if(!tsv_file_info.exists())
{
throw OdsException(QObject::tr("TSV file %1 does not exists")
.arg(tsv_file_info.absoluteFilePath()));
}
if(!tsv_file_info.isReadable())
{
throw OdsException(QObject::tr("TSV file %1 is not readable")
.arg(tsv_file_info.absoluteFilePath()));
}
qDebug() << tsv_file_info.absoluteFilePath();
m_handler.startSheet(tsv_file_info.baseName());
if(!tsvFile.open(QIODevice::ReadOnly | QFile::Text))
{
throw OdsException(QObject::tr("Unable to read TSV file %1")
.arg(tsv_file_info.absoluteFilePath()));
}
QTextStream textStreamInput(&tsvFile);
parse(textStreamInput);
tsvFile.close();
qDebug();
}
void
TsvReader::parse(QIODevice *p_inputstream)
{
QTextStream textStreamInput(p_inputstream);
while(readCsvRow(textStreamInput))
{
}
m_handler.endDocument();
}
void
TsvReader::parse(QTextStream &textStreamInput)
{
while(readCsvRow(textStreamInput))
{
}
m_handler.endDocument();
}
bool
TsvReader::readCsvRow(QTextStream &textStreamInput)
{
qDebug() << __FILE__ << " " << __FUNCTION__ << " " << __LINE__;
m_columnNumber = 0;
m_handler.startLine();
m_rowNumber++;
static const int delta[][5] = {
// , " \n ? eof
{1, 2, -1, 0, -1}, // 0: parsing (store char)
{1, 2, -1, 0, -1}, // 1: parsing (store column)
{3, 4, 3, 3, -2}, // 2: quote entered (no-op)
{3, 4, 3, 3, -2}, // 3: parsing inside quotes (store char)
{1, 3, -1, 0, -1}, // 4: quote exited (no-op)
// -1: end of row, store column, success
// -2: eof inside quotes
};
qDebug() << __FILE__ << " " << __FUNCTION__ << " " << __LINE__;
if(textStreamInput.atEnd())
{
qDebug() << __FILE__ << " " << __FUNCTION__ << " " << __LINE__;
return false;
}
int state = 0, t, previous_state;
QChar ch;
QString cell;
try
{
qDebug() << __FILE__ << " " << __FUNCTION__ << " " << __LINE__;
while(state >= 0)
{
qDebug() << __FILE__ << " " << __FUNCTION__ << " " << __LINE__ << " "
<< cell;
if(textStreamInput.atEnd())
t = 4;
else
{
textStreamInput >> ch;
if(ch == m_separator)
t = 0;
else if(ch == '\"')
t = 1;
else if(ch == '\n')
t = 2;
else
t = 3;
}
previous_state = state;
state = delta[state][t];
switch(state)
{
case 0:
case 3:
cell += ch;
break;
case -1:
case 1:
OdsCell odsCell;
m_columnNumber++;
qDebug() << __FILE__ << " " << __FUNCTION__ << " " << __LINE__
<< " " << cell;
if((previous_state == 2) || (previous_state == 3))
{
odsCell.setOfficeValueType("string");
odsCell.setValueString(cell);
}
else
{
odsCell.setValueOfUndefinedType(cell);
}
m_handler.setCell(odsCell);
cell = "";
break;
}
}
if(state == -2)
throw OdsException(
QObject::tr("End-of-file found while inside quotes."));
}
catch(OdsException &error)
{
throw OdsException(QObject::tr("Text parse error at line %1, column %2:\n"
"%3")
.arg(m_rowNumber)
.arg(m_columnNumber)
.arg(error.qwhat()));
}
catch(std::exception &error)
{
throw OdsException(QObject::tr("Text parse error at line %1, column %2:\n"
"%3")
.arg(m_rowNumber)
.arg(m_columnNumber)
.arg(error.what()));
}
m_handler.endLine();
qDebug() << __FILE__ << " " << __FUNCTION__ << " " << __LINE__;
return true;
}
OdsCell
Definition odscell.h:29
OdsCell::setOfficeValueType
void setOfficeValueType(const QString &type)
Definition odscell.cpp:33
OdsCell::setValueOfUndefinedType
void setValueOfUndefinedType(const QString &value)
Definition odscell.cpp:190
OdsCell::setValueString
void setValueString(const QString &value)
Definition odscell.cpp:65
OdsDocHandlerInterface
Definition odsdochandlerinterface.h:43
OdsException
Definition odsexception.h:27
OdsException::what
const char * what() const noexcept override
Definition odsexception.h:59
OdsException::qwhat
virtual const QString & qwhat() const
Definition odsexception.h:53
TsvReader::parse
void parse(QFile &tsvFile)
Definition tsvreader.cpp:67
TsvReader::~TsvReader
virtual ~TsvReader()
Definition tsvreader.cpp:45
TsvReader::m_separator
QChar m_separator
Definition tsvreader.h:52
TsvReader::m_handler
OdsDocHandlerInterface & m_handler
Definition tsvreader.h:50
TsvReader::TsvReader
TsvReader(OdsDocHandlerInterface &handler)
Definition tsvreader.cpp:41
TsvReader::readCsvRow
bool readCsvRow(QTextStream &in)
reads a CSV row based on https://stackoverflow.com/questions/27318631/parsing-through-a-csv-file-in-q...
Definition tsvreader.cpp:115
TsvReader::setSeparator
void setSeparator(TsvSeparator separator)
Definition tsvreader.cpp:49
TsvReader::m_columnNumber
std::size_t m_columnNumber
Definition tsvreader.h:47
TsvReader::m_rowNumber
std::size_t m_rowNumber
Definition tsvreader.h:48
TsvSeparator
TsvSeparator
Definition config.h:11
TsvSeparator::semicolon
@ semicolon
Definition config.h:11
TsvSeparator::comma
@ comma
Definition config.h:11
TsvSeparator::tab
@ tab
Definition config.h:11
odscell.h
odsexception.h
tsvreader.h
parser for text files (tsv, csv)