libodsstream
Library for mass spectrometry
Loading...
Searching...
No Matches
tsvreader.cpp
Go to the documentation of this file.
1/**
2 * \file odsstream/tsvreader.cpp
3 * \date 11/11/2018
4 * \author Olivier Langella
5 * \brief parser for text files (tsv, csv)
6 */
7
8/*******************************************************************************
9 * Copyright (c) 2018 Olivier Langella <Olivier.Langella@u-psud.fr>.
10 *
11 * This file is part of the libodsstream library.
12 *
13 * libodsstream is a library to read and write ODS documents as streams
14 * Copyright (C) 2018 Olivier Langella <Olivier.Langella@u-psud.fr>
15 *
16 * This program is free software: you can redistribute it and/or modify
17 * it under the terms of the GNU Lesser General Public License as published
18 *by the Free Software Foundation, either version 3 of the License, or (at your
19 *option) any later version.
20 *
21 * This program is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 * GNU Lesser General Public License for more details.
25 *
26 * You should have received a copy of the GNU Lesser General Public License
27 * along with this program. If not, see <http://www.gnu.org/licenses/>.
28 *
29 * Contributors:
30 * Olivier Langella <Olivier.Langella@u-psud.fr> - initial API and
31 *implementation
32 ******************************************************************************/
33
34#include "tsvreader.h"
35#include "odsexception.h"
36#include <QFileInfo>
37#include <QChar>
38#include <QDebug>
39#include "reader/odscell.h"
40
41TsvReader::TsvReader(OdsDocHandlerInterface &handler) : m_handler(handler)
42{
43}
44
48void
50{
51
52 switch(separator)
53 {
55 m_separator = '\t';
56 break;
58 m_separator = ',';
59 break;
61 m_separator = ';';
62 break;
63 }
64}
65
66void
67TsvReader::parse(QFile &tsvFile)
68{
69 qDebug() << tsvFile.fileName();
70 QFileInfo tsv_file_info(tsvFile.fileName());
71 if(!tsv_file_info.exists())
72 {
73 throw OdsException(QObject::tr("TSV file %1 does not exists")
74 .arg(tsv_file_info.absoluteFilePath()));
75 }
76 if(!tsv_file_info.isReadable())
77 {
78 throw OdsException(QObject::tr("TSV file %1 is not readable")
79 .arg(tsv_file_info.absoluteFilePath()));
80 }
81 qDebug() << tsv_file_info.absoluteFilePath();
82 m_handler.startSheet(tsv_file_info.baseName());
83 if(!tsvFile.open(QIODevice::ReadOnly | QFile::Text))
84 {
85 throw OdsException(QObject::tr("Unable to read TSV file %1")
86 .arg(tsv_file_info.absoluteFilePath()));
87 }
88 QTextStream textStreamInput(&tsvFile);
89 parse(textStreamInput);
90 tsvFile.close();
91 qDebug();
92}
93
94void
95TsvReader::parse(QIODevice *p_inputstream)
96{
97
98 QTextStream textStreamInput(p_inputstream);
99 while(readCsvRow(textStreamInput))
100 {
101 }
103}
104
105void
106TsvReader::parse(QTextStream &textStreamInput)
107{
108 while(readCsvRow(textStreamInput))
109 {
110 }
112}
113
114bool
115TsvReader::readCsvRow(QTextStream &textStreamInput)
116{
117 qDebug() << __FILE__ << " " << __FUNCTION__ << " " << __LINE__;
118 m_columnNumber = 0;
120 m_rowNumber++;
121 static const int delta[][5] = {
122 // , " \n ? eof
123 {1, 2, -1, 0, -1}, // 0: parsing (store char)
124 {1, 2, -1, 0, -1}, // 1: parsing (store column)
125 {3, 4, 3, 3, -2}, // 2: quote entered (no-op)
126 {3, 4, 3, 3, -2}, // 3: parsing inside quotes (store char)
127 {1, 3, -1, 0, -1}, // 4: quote exited (no-op)
128 // -1: end of row, store column, success
129 // -2: eof inside quotes
130 };
131 qDebug() << __FILE__ << " " << __FUNCTION__ << " " << __LINE__;
132 if(textStreamInput.atEnd())
133 {
134 qDebug() << __FILE__ << " " << __FUNCTION__ << " " << __LINE__;
135 return false;
136 }
137
138 int state = 0, t, previous_state;
139 QChar ch;
140 QString cell;
141
142 try
143 {
144 qDebug() << __FILE__ << " " << __FUNCTION__ << " " << __LINE__;
145 while(state >= 0)
146 {
147 qDebug() << __FILE__ << " " << __FUNCTION__ << " " << __LINE__ << " "
148 << cell;
149 if(textStreamInput.atEnd())
150 t = 4;
151 else
152 {
153 textStreamInput >> ch;
154 if(ch == m_separator)
155 t = 0;
156 else if(ch == '\"')
157 t = 1;
158 else if(ch == '\n')
159 t = 2;
160 else
161 t = 3;
162 }
163
164 previous_state = state;
165 state = delta[state][t];
166
167 switch(state)
168 {
169 case 0:
170 case 3:
171 cell += ch;
172 break;
173 case -1:
174 case 1:
175 OdsCell odsCell;
177 qDebug() << __FILE__ << " " << __FUNCTION__ << " " << __LINE__
178 << " " << cell;
179 if((previous_state == 2) || (previous_state == 3))
180 {
181 odsCell.setOfficeValueType("string");
182 odsCell.setValueString(cell);
183 }
184 else
185 {
186 odsCell.setValueOfUndefinedType(cell);
187 }
188 m_handler.setCell(odsCell);
189 cell = "";
190 break;
191 }
192 }
193
194
195 if(state == -2)
196 throw OdsException(
197 QObject::tr("End-of-file found while inside quotes."));
198 }
199 catch(OdsException &error)
200 {
201 throw OdsException(QObject::tr("Text parse error at line %1, column %2:\n"
202 "%3")
203 .arg(m_rowNumber)
204 .arg(m_columnNumber)
205 .arg(error.qwhat()));
206 }
207
208 catch(std::exception &error)
209 {
210 throw OdsException(QObject::tr("Text parse error at line %1, column %2:\n"
211 "%3")
212 .arg(m_rowNumber)
213 .arg(m_columnNumber)
214 .arg(error.what()));
215 }
216
218 qDebug() << __FILE__ << " " << __FUNCTION__ << " " << __LINE__;
219 return true;
220}
void setOfficeValueType(const QString &type)
Definition odscell.cpp:33
void setValueOfUndefinedType(const QString &value)
Definition odscell.cpp:190
void setValueString(const QString &value)
Definition odscell.cpp:65
virtual void setCell(const OdsCell &)=0
virtual void endDocument()=0
virtual void startLine()=0
virtual void startSheet(const QString &sheet_name)=0
virtual void endLine()=0
const char * what() const noexcept override
virtual const QString & qwhat() const
void parse(QFile &tsvFile)
Definition tsvreader.cpp:67
virtual ~TsvReader()
Definition tsvreader.cpp:45
QChar m_separator
Definition tsvreader.h:52
OdsDocHandlerInterface & m_handler
Definition tsvreader.h:50
TsvReader(OdsDocHandlerInterface &handler)
Definition tsvreader.cpp:41
bool readCsvRow(QTextStream &in)
reads a CSV row based on https://stackoverflow.com/questions/27318631/parsing-through-a-csv-file-in-q...
void setSeparator(TsvSeparator separator)
Definition tsvreader.cpp:49
std::size_t m_columnNumber
Definition tsvreader.h:47
std::size_t m_rowNumber
Definition tsvreader.h:48
TsvSeparator
Definition config.h:11
parser for text files (tsv, csv)