File indexing completed on 2024-05-05 07:40:27
0001 /* 0002 SPDX-FileCopyrightText: 2012 Rishab Arora <ra.rishab@gmail.com> 0003 0004 SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 #pragma once 0008 0009 #include <QHash> 0010 #include <QList> 0011 #include <QVariant> 0012 0013 #include "ksfilereader.h" 0014 0015 /** 0016 * @brief Generic class for text file parsers used in KStars. 0017 * Read rows using ReadCSVRow() regardless of the type of parser. 0018 * Usage: 0019 * 1) initialize KSParser 0020 * 2) while (KSParserObject.HasNextRow()) { 0021 * QHash < Qstring, QVariant > read_stuff = KSParserObject.ReadNextRow(); 0022 * ... 0023 * do what you need to do... 0024 * ... 0025 * } 0026 * 0027 * Debugging Information: 0028 * In case of read errors, the parsers emit a warning. 0029 * In case of conversion errors, the warnings are toggled by setting 0030 * const bool KSParser::parser_debug_mode_ = true; in ksparser.cpp 0031 * 0032 * In case of failure, the parser returns a Dummy Row. So if you see the 0033 * string "Null" in the returned QHash, it signifies the parserencountered an 0034 * unexpected error. 0035 **/ 0036 class KSParser 0037 { 0038 public: 0039 /** 0040 * These are the values used in case of error in conversion 0041 **/ 0042 static const double EBROKEN_DOUBLE; 0043 static const float EBROKEN_FLOAT; 0044 static const int EBROKEN_INT; 0045 static const QString EBROKEN_QSTRING; 0046 0047 /** 0048 * @brief DataTypes for building sequence 0049 * D_QSTRING QString Type 0050 * D_INT Integer Type 0051 * D_FLOAT Floating Point Type 0052 * D_DOUBLE Double PRecision Type 0053 * D_SKIP Unused Field. This string is not converted from QString 0054 **/ 0055 enum DataTypes 0056 { 0057 D_QSTRING, 0058 D_INT, 0059 D_FLOAT, 0060 D_DOUBLE, 0061 D_SKIP 0062 }; 0063 0064 /** 0065 * @brief Returns a CSV parsing instance of a KSParser type object. 0066 * 0067 * Behavior: 0068 * 1) In case of attempt to read a non existent file, will return 0069 * dummy row (not empty) 0070 * 2) In case of incomplete row, the whole row is ignored 0071 * 3) In case of missing values, parser will return empty string, 0072 * or 0 or 0.0 0073 * 4) If you keep reading ignoring the HasNextRow you get dummy rows 0074 * 0075 * @param filename Full Path (Dir + Filename) of source file 0076 * @param comment_char Character signifying a comment line 0077 * @param sequence QList of QPairs of the form "field name,data type" 0078 * @param delimiter separate on which character. default ',' 0079 **/ 0080 KSParser(const QString &filename, const char comment_char, const QList<QPair<QString, DataTypes>> &sequence, 0081 const char delimiter = ','); 0082 0083 /** 0084 * @brief Returns a Fixed Width parsing instance of a KSParser type object. 0085 * 0086 * Usage: 0087 * Important! The last value in width sequence is taken till the end of 0088 * line by default. This is done as the last line may or may not be padded 0089 * on the right. 0090 * Important! For backward compatibility, all string outputs are not 0091 * trimmed. Hence reading "hello " will return "hello " _not_ "hello" 0092 * If you need trimmed values like "hello" , use QString.trimmed() 0093 * 0094 * Behavior: 0095 * 1) In case of attempt to read a non existent file, will return 0096 * dummy row (not empty!) 0097 * 2) In case of missing fields at the end, the line length is smaller 0098 * than expected so it is skipped. 0099 * 3) If an integer or floating point value is empty (e.g. " ") 0100 * it is replaced by 0 or 0.0 0101 * 4) If you keep reading the file ignoring the HasNextRow(), you get 0102 * Dummy Rows 0103 * @param filename Full Path (Dir + Filename) of source file 0104 * @param comment_char Character signifying a comment line 0105 * @param sequence QList of QPairs of the form "field name,data type" 0106 * @param widths width sequence. Last value is line.length() by default 0107 * Hence, sequence.length() should be (width.length()+1) 0108 **/ 0109 KSParser(const QString &filename, const char comment_char, const QList<QPair<QString, DataTypes>> &sequence, 0110 const QList<int> &widths); 0111 0112 /** 0113 * @brief Generic function used to read the next row of a text file. 0114 * The constructor changes the function pointer to the appropriate function. 0115 * Returns the row as <"column name", value> 0116 * 0117 * @return QHash< QString, QVariant > 0118 **/ 0119 QHash<QString, QVariant> ReadNextRow(); 0120 0121 /** 0122 * @brief Returns True if there are more rows to be read 0123 * 0124 * @return bool 0125 **/ 0126 bool HasNextRow(); 0127 // Too many warnings when const: datahandlers/ksparser.h:131:27: warning: 0128 // type qualifiers ignored on function return type [-Wignored-qualifiers] 0129 0130 /** 0131 * @brief Wrapper function for KSFileReader setProgress 0132 * 0133 * @param msg What message to display 0134 * @param total_lines Total number of lines in file 0135 * @param step_size Size of step in emitting progress 0136 * @return void 0137 **/ 0138 void SetProgress(QString msg, int total_lines, int step_size); 0139 0140 /** 0141 * @brief Wrapper function for KSFileReader showProgress 0142 * 0143 * @return void 0144 **/ 0145 void ShowProgress(); 0146 0147 private: 0148 /** 0149 * @brief Function Pointer used by ReadNextRow 0150 * to call the appropriate function among ReadCSVRow and ReadFixedWidthRow 0151 * 0152 * @return QHash< QString, QVariant > 0153 **/ 0154 QHash<QString, QVariant> (KSParser::*readFunctionPtr)(); 0155 0156 /** 0157 * @brief Returns a single row from CSV. 0158 * If HasNextRow is false, returns a row with default values. 0159 * 0160 * @return QHash< QString, QVariant > 0161 **/ 0162 QHash<QString, QVariant> ReadCSVRow(); 0163 0164 /** 0165 * @brief Returns a single row from Fixed Width File. 0166 * If HasNextRow is false, returns a row with default values. 0167 * 0168 * @return QHash< QString, QVariant > 0169 **/ 0170 QHash<QString, QVariant> ReadFixedWidthRow(); 0171 0172 /** 0173 * @brief Returns a default value row. 0174 * Values are according to the current assigned sequence. 0175 * 0176 * @return QHash< QString, QVariant > 0177 **/ 0178 QHash<QString, QVariant> DummyRow(); 0179 0180 /** 0181 * @brief This function combines the separated QString in case of quotes 0182 * The function can not handle stray quote marks. 0183 * eg. hello,"",world is acceptable 0184 * hello"",world is not 0185 * 0186 * @param separated a list of QStrings separated at every delimiter 0187 * @return QList< QString > 0188 **/ 0189 QList<QString> CombineQuoteParts(QList<QString> &separated); 0190 0191 /** 0192 * @brief Function to return a QVariant of selected data type 0193 * 0194 * @param input_string QString of what the object should contain 0195 * @param data_type Data Type of input_string 0196 * @return QVariant 0197 **/ 0198 QVariant ConvertToQVariant(const QString &input_string, const DataTypes &data_type, bool &ok); 0199 0200 static const bool parser_debug_mode_; 0201 0202 KSFileReader file_reader_; 0203 QString filename_; 0204 char comment_char_; 0205 0206 QList<QPair<QString, DataTypes>> name_type_sequence_; 0207 QList<int> width_sequence_; 0208 char delimiter_ { 0 }; 0209 };