• Skip to content
  • Skip to link menu
KDE API Reference
  • KDE API Reference
  • kdeedu API Reference
  • KDE Home
  • Contact Us
 

kstars

  • sources
  • kde-4.12
  • kdeedu
  • kstars
  • datahandlers
ksparser.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  KSParser.cpp - K Desktop Planetarium
3  -------------------
4  begin : 2012/24/06
5  copyright : (C) 2012 by Rishab Arora
6  email : ra.rishab@gmail.com
7  ***************************************************************************/
8 
9 /***************************************************************************
10  * *
11  * This program is free software; you can redistribute it and/or modify *
12  * it under the terms of the GNU General Public License as published by *
13  * the Free Software Foundation; either version 2 of the License, or *
14  * (at your option) any later version. *
15  * *
16  ***************************************************************************/
17 
18 #include "ksparser.h"
19 #include <kdebug.h>
20 #include <klocale.h>
21 
22 const int KSParser::EBROKEN_INT = 0;
23 const double KSParser::EBROKEN_DOUBLE = 0.0;
24 const float KSParser::EBROKEN_FLOAT = 0.0;
25 const QString KSParser::EBROKEN_QSTRING = "Null";
26 const bool KSParser::parser_debug_mode_ = false;
27 
28 KSParser::KSParser(const QString &filename, const char comment_char,
29  const QList< QPair<QString, DataTypes> > &sequence,
30  const char delimiter)
31  : filename_(filename), comment_char_(comment_char),
32  name_type_sequence_(sequence), delimiter_(delimiter) {
33  if (!file_reader_.openFullPath(filename_)) {
34  kWarning() <<"Unable to open file: "<< filename;
35  readFunctionPtr = &KSParser::DummyRow;
36  } else {
37  readFunctionPtr = &KSParser::ReadCSVRow;
38  kDebug() <<"File opened: "<< filename;
39  }
40 }
41 
42 KSParser::KSParser(const QString &filename, const char comment_char,
43  const QList< QPair<QString, DataTypes> > &sequence,
44  const QList<int> &widths)
45  : filename_(filename), comment_char_(comment_char),
46  name_type_sequence_(sequence), width_sequence_(widths) {
47  if (!file_reader_.openFullPath(filename_)) {
48  kWarning() <<"Unable to open file: "<< filename;
49  readFunctionPtr = &KSParser::DummyRow;
50  } else {
51  readFunctionPtr = &KSParser::ReadFixedWidthRow;
52  kDebug() <<"File opened: "<< filename;
53  }
54 }
55 
56 QHash<QString, QVariant> KSParser::ReadNextRow() {
57  return (this->*readFunctionPtr)();
58 }
59 
60 QHash<QString, QVariant> KSParser::ReadCSVRow() {
66  bool read_success = false;
67  QString next_line;
68  QStringList separated;
69  QHash<QString, QVariant> newRow;
70 
71  while (file_reader_.hasMoreLines() && read_success == false) {
72  next_line = file_reader_.readLine();
73  if (next_line.mid(0,1)[0] == comment_char_) continue;
74  separated = next_line.split(delimiter_);
75  /*
76  * 1) split along delimiter eg. comma (,)
77  * 2) check first and last characters.
78  * if the first letter is '"',
79  * then combine the nexto ones in it till
80  * till you come across the next word which
81  * has the last character as '"'
82  * (CombineQuoteParts
83  *
84  */
85  if (separated.length() == 1) continue; // Length will be 1 if there
86  // is no delimiter
87 
88  separated = CombineQuoteParts(separated); // At this point, the
89  // string has been split
90  // taking the quote marks into account
91 
92  // Check if the generated list has correct size
93  // If not, continue to next row. (i.e SKIP INCOMPLETE ROW)
94  if (separated.length() != name_type_sequence_.length())
95  continue;
96 
97  for (int i = 0; i < name_type_sequence_.length(); i++) {
98  bool ok;
99  newRow[name_type_sequence_[i].first] =
100  ConvertToQVariant(separated[i], name_type_sequence_[i].second, ok);
101  if (!ok && parser_debug_mode_) {
102  kDebug() << name_type_sequence_[i].second
103  <<"Failed at field: "
104  << name_type_sequence_[i].first
105  << " & next_line : " << next_line;
106  }
107  }
108  read_success = true;
109  }
110  /*
111  * This signifies that someone tried to read a row
112  * without checking if HasNextRow is true.
113  * OR
114  * The file was truncated OR the file ends with one or more '\n'
115  */
116  if (file_reader_.hasMoreLines() == false && newRow.size()<=1)
117  newRow = DummyRow();
118  return newRow;
119 }
120 
121 QHash<QString, QVariant> KSParser::ReadFixedWidthRow() {
122  if (name_type_sequence_.length() != (width_sequence_.length() + 1)) {
123  // line length is appendeded to width_sequence_ by default.
124  // Hence, the length of width_sequence_ is one less than
125  // name_type_sequence_
126  kWarning() << "Unequal fields and widths! Returning dummy row!";
127  Q_ASSERT( false ); // Make sure that in Debug mode, this condition generates an abort.
128  return DummyRow();
129  }
130 
136  bool read_success = false;
137  QString next_line;
138  QStringList separated;
139  QHash<QString, QVariant> newRow;
140  int total_min_length = 0;
141 
142  foreach(const int width_value, width_sequence_) {
143  total_min_length += width_value;
144  }
145  while (file_reader_.hasMoreLines() && read_success == false) {
146  /*
147  * Steps:
148  * 1) Read Line
149  * 2) If it is a comment, loop again
150  * 3) If it is too small, loop again
151  * 4) Else, a) Break it down according to widths
152  * b) Convert each broken down unit to appropriate value
153  * c) set read_success to True denoting we have a valid
154  * conversion
155  */
156  next_line = file_reader_.readLine();
157  if (next_line.mid(0,1)[0] == comment_char_) continue;
158  if (next_line.length() < total_min_length) continue;
159 
160  int curr_width = 0;
161  for (int n_split = 0; n_split < width_sequence_.length(); n_split++) {
162  // Build separated stringlist. Then assign it afterwards.
163  QString temp_split;
164  temp_split = next_line.mid(curr_width, width_sequence_[n_split]);
165  // Don't use at(), because it crashes on invalid index
166  curr_width += width_sequence_[n_split];
167  separated.append(temp_split.trimmed());
168  }
169  separated.append(next_line.mid(curr_width).trimmed()); // Append last segment
170 
171  // Conversions
172  for (int i = 0; i < name_type_sequence_.length(); ++i) {
173  bool ok;
174  newRow[name_type_sequence_[i].first] =
175  ConvertToQVariant(separated[i], name_type_sequence_[i].second, ok);
176  if (!ok && parser_debug_mode_) {
177  kDebug() << name_type_sequence_[i].second
178  <<"Failed at field: "
179  << name_type_sequence_[i].first
180  << " & next_line : " << next_line;
181  }
182  }
183  read_success = true;
184  }
185  /*
186  * This signifies that someone tried to read a row
187  * without checking if HasNextRow is true.
188  * OR
189  * The file was truncated OR the file ends with one or more '\n'
190  */
191  if (file_reader_.hasMoreLines() == false && newRow.size()<=1)
192  newRow = DummyRow();
193  return newRow;
194 }
195 
196 QHash<QString, QVariant> KSParser::DummyRow() {
197  kWarning() << "File named " << filename_ << " encountered an error while reading";
198  QHash<QString, QVariant> newRow;
199  for (int i = 0; i < name_type_sequence_.length(); ++i) {
200  switch (name_type_sequence_[i].second) {
201  case D_QSTRING:
202  newRow[name_type_sequence_[i].first] = EBROKEN_QSTRING;
203  break;
204  case D_DOUBLE:
205  newRow[name_type_sequence_[i].first] = EBROKEN_DOUBLE;
206  break;
207  case D_INT:
208  newRow[name_type_sequence_[i].first] = EBROKEN_INT;
209  break;
210  case D_FLOAT:
211  newRow[name_type_sequence_[i].first] = EBROKEN_FLOAT;
212  break;
213  }
214  }
215  return newRow;
216 }
217 
218 bool KSParser::HasNextRow() {
219  return file_reader_.hasMoreLines();
220 }
221 
222 void KSParser::SetProgress(QString msg, int total_lines, int step_size) {
223  file_reader_.setProgress(i18n("Loading NGC/IC objects"),
224  total_lines, step_size);
225 }
226 
227 void KSParser::ShowProgress() {
228  file_reader_.showProgress();
229 }
230 
231 QList< QString > KSParser::CombineQuoteParts(QList<QString> &separated) {
232  QString iter_string;
233  QList<QString> quoteCombined;
234  QStringList::const_iterator iter;
235 
236  if (separated.length() == 0) {
237  kDebug() << "Cannot Combine empty list";
238  } else {
239  /* Algorithm:
240  * In the following steps, 'word' implies a unit from 'separated'.
241  * i.e. separated[0], separated[1] etc are 'words'
242  *
243  * 1) Read a word
244  * 2) If word does not start with \" add to final expression. Goto 1)
245  * 3) If word starts with \", push to queue
246  * 4) If word ends with \", empty queue and join each with delimiter.
247  * Add this to final expression. Go to 6)
248  * 5) Read next word. Goto 3) until end of list of words is reached
249  * 6) Goto 1) until end of list of words is reached
250  */
251  iter = separated.constBegin();
252 
253  while (iter != separated.constEnd()) {
254  QList <QString> queue;
255  iter_string = *iter;
256 
257  if (iter_string.indexOf("\"") == 0) { // if (quote mark is the first character)
258  iter_string = (iter_string).remove(0,1); // remove the quote at the start
259  while (iter_string.lastIndexOf('\"') != (iter_string.length()-1) &&
260  iter != separated.constEnd()) { // handle stuff between parent quotes
261  queue.append((iter_string));
262  ++iter;
263  iter_string = *iter;
264  }
265  iter_string.chop(1); // remove the quote at the end
266  queue.append(iter_string);
267  } else {
268  queue.append(iter_string);
269  }
270 
271  QString col_result;
272  foreach(const QString &join, queue)
273  col_result += (join + delimiter_);
274  col_result.chop(1); // remove extra delimiter
275  quoteCombined.append(col_result);
276  ++iter;
277  }
278  }
279  return quoteCombined;
280 }
281 
282 QVariant KSParser::ConvertToQVariant(const QString &input_string,
283  const KSParser::DataTypes &data_type,
284  bool &ok) {
285  ok = true;
286  QVariant converted_object;
287  switch (data_type) {
288  case D_QSTRING:
289  case D_SKIP:
290  converted_object = input_string;
291  break;
292  case D_DOUBLE:
293  converted_object = input_string.trimmed().toDouble(&ok);
294  if (!ok)
295  converted_object = EBROKEN_DOUBLE;
296  break;
297  case D_INT:
298  converted_object = input_string.trimmed().toInt(&ok);
299  if (!ok)
300  converted_object = EBROKEN_INT;
301  break;
302  case D_FLOAT:
303  converted_object = input_string.trimmed().toFloat(&ok);
304  if (!ok)
305  converted_object = EBROKEN_FLOAT;
306  break;
307  }
308  return converted_object;
309 }
KSFileReader::hasMoreLines
bool hasMoreLines()
Definition: ksfilereader.h:108
KSParser::HasNextRow
bool HasNextRow()
Returns True if there are more rows to be read.
Definition: ksparser.cpp:218
KSParser::EBROKEN_DOUBLE
static const double EBROKEN_DOUBLE
These are the values used in case of error in conversion.
Definition: ksparser.h:54
KSParser::EBROKEN_QSTRING
static const QString EBROKEN_QSTRING
Definition: ksparser.h:57
KSParser::D_DOUBLE
Definition: ksparser.h:71
KSParser::DataTypes
DataTypes
DataTypes for building sequence D_QSTRING QString Type D_INT Integer Type D_FLOAT Floating Point Type...
Definition: ksparser.h:67
KSParser::KSParser
KSParser(const QString &filename, const char comment_char, const QList< QPair< QString, DataTypes > > &sequence, const char delimiter= ',')
Returns a CSV parsing instance of a KSParser type object.
Definition: ksparser.cpp:28
KSParser::ShowProgress
void ShowProgress()
Wrapper function for KSFileReader showProgress.
Definition: ksparser.cpp:227
KSParser::EBROKEN_INT
static const int EBROKEN_INT
Definition: ksparser.h:56
KSParser::D_FLOAT
Definition: ksparser.h:70
KSFileReader::showProgress
void showProgress()
Definition: ksfilereader.cpp:83
KSParser::SetProgress
void SetProgress(QString msg, int total_lines, int step_size)
Wrapper function for KSFileReader setProgress.
Definition: ksparser.cpp:222
KSParser::EBROKEN_FLOAT
static const float EBROKEN_FLOAT
Definition: ksparser.h:55
KSParser::D_INT
Definition: ksparser.h:69
KSFileReader::readLine
QString readLine()
Definition: ksfilereader.h:113
KSFileReader::setProgress
void setProgress(QString label, unsigned int lastLine, unsigned int numUpdates=10)
Definition: ksfilereader.cpp:69
ksparser.h
KSFileReader::openFullPath
bool openFullPath(const QString &fname)
Definition: ksfilereader.cpp:57
KSParser::ReadNextRow
QHash< QString, QVariant > ReadNextRow()
Generic function used to read the next row of a text file.
Definition: ksparser.cpp:56
KSParser::D_SKIP
Definition: ksparser.h:72
KSParser::D_QSTRING
Definition: ksparser.h:68
QList
This file is part of the KDE documentation.
Documentation copyright © 1996-2014 The KDE developers.
Generated on Tue Oct 14 2014 22:36:20 by doxygen 1.8.7 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

kstars

Skip menu "kstars"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members
  • Related Pages

kdeedu API Reference

Skip menu "kdeedu API Reference"
  • Analitza
  •     lib
  • kalgebra
  • kalzium
  •   libscience
  • kanagram
  • kig
  •   lib
  • klettres
  • kstars
  • libkdeedu
  •   keduvocdocument
  • marble
  • parley
  • rocs
  •   App
  •   RocsCore
  •   VisualEditor
  •   stepcore

Search



Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal