File indexing completed on 2024-05-12 05:10:09
0001 /*************************************************************************** 0002 Copyright (C) 2009 Robby Stephenson <robby@periapsis.org> 0003 ***************************************************************************/ 0004 0005 /*************************************************************************** 0006 * * 0007 * This program is free software; you can redistribute it and/or * 0008 * modify it under the terms of the GNU General Public License as * 0009 * published by the Free Software Foundation; either version 2 of * 0010 * the License or (at your option) version 3 or any later version * 0011 * accepted by the membership of KDE e.V. (or its successor approved * 0012 * by the membership of KDE e.V.), which shall act as a proxy * 0013 * defined in Section 14 of version 3 of the license. * 0014 * * 0015 * This program is distributed in the hope that it will be useful, * 0016 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 0017 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 0018 * GNU General Public License for more details. * 0019 * * 0020 * You should have received a copy of the GNU General Public License * 0021 * along with this program. If not, see <http://www.gnu.org/licenses/>. * 0022 * * 0023 ***************************************************************************/ 0024 0025 #include "csvparser.h" 0026 0027 #include <QTextStream> 0028 #include <QStringList> 0029 0030 #include <config.h> 0031 0032 extern "C" { 0033 #ifdef HAVE_LIBCSV 0034 #include <csv.h> 0035 #else 0036 #include "libcsv/libcsv.h" 0037 #endif 0038 } 0039 0040 typedef int(*SpaceFunc)(char); 0041 0042 static void writeToken(void* buffer, size_t len, void* data); 0043 static void writeRow(int buffer, void* data); 0044 static int isSpace(unsigned char c); 0045 static int isSpaceOrTab(unsigned char c); 0046 static int isTab(unsigned char c); 0047 0048 using Tellico::CSVParser; 0049 0050 class CSVParser::Private { 0051 public: 0052 Private() : stream(nullptr), done(false) { 0053 csv_init(&parser, 0); 0054 } 0055 ~Private() { 0056 csv_free(&parser); 0057 delete stream; 0058 } 0059 0060 struct csv_parser parser; 0061 QString str; 0062 QTextStream* stream; 0063 QStringList tokens; 0064 bool done; 0065 }; 0066 0067 CSVParser::CSVParser(QString str) : d(new Private()) { 0068 reset(str); 0069 } 0070 0071 CSVParser::~CSVParser() { 0072 delete d; 0073 } 0074 0075 void CSVParser::setDelimiter(const QString& s) { 0076 Q_ASSERT(s.length() == 1); 0077 csv_set_delim(&d->parser, s[0].toLatin1()); 0078 if(s[0] == QLatin1Char('\t')) csv_set_space_func(&d->parser, isSpace); 0079 else if(s[0] == QLatin1Char(' ')) csv_set_space_func(&d->parser, isTab); 0080 else csv_set_space_func(&d->parser, isSpaceOrTab); 0081 } 0082 0083 void CSVParser::reset(QString str) { 0084 delete d->stream; 0085 d->str = str; 0086 d->stream = new QTextStream(&d->str); 0087 } 0088 0089 bool CSVParser::hasNext() const { 0090 return !d->stream->atEnd(); 0091 } 0092 0093 void CSVParser::skipLine() { 0094 d->stream->readLine(); 0095 } 0096 0097 void CSVParser::addToken(const QString& t) { 0098 d->tokens += t; 0099 } 0100 0101 void CSVParser::setRowDone(bool b) { 0102 d->done = b; 0103 } 0104 0105 QStringList CSVParser::nextTokens() { 0106 d->tokens.clear(); 0107 d->done = false; 0108 while(hasNext() && !d->done) { 0109 QByteArray line = d->stream->readLine().toUtf8() + '\n'; // need the eol char 0110 csv_parse(&d->parser, line.constData(), line.length(), &writeToken, &writeRow, this); 0111 } 0112 csv_fini(&d->parser, &writeToken, &writeRow, this); 0113 return d->tokens; 0114 } 0115 0116 static void writeToken(void* buffer, size_t len, void* data) { 0117 CSVParser* p = static_cast<CSVParser*>(data); 0118 p->addToken(QString::fromUtf8((char *)buffer, len)); 0119 } 0120 0121 static void writeRow(int c, void* data) { 0122 Q_UNUSED(c); 0123 CSVParser* p = static_cast<CSVParser*>(data); 0124 p->setRowDone(true); 0125 } 0126 0127 static int isSpace(unsigned char c) { 0128 if (c == CSV_SPACE) return 1; 0129 return 0; 0130 } 0131 0132 static int isSpaceOrTab(unsigned char c) { 0133 if (c == CSV_SPACE || c == CSV_TAB) return 1; 0134 return 0; 0135 } 0136 0137 static int isTab(unsigned char c) { 0138 if (c == CSV_TAB) return 1; 0139 return 0; 0140 }