File: csvreader.hh

package info (click to toggle)
qdmr 0.13.1-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 22,236 kB
  • sloc: cpp: 93,672; xml: 10,526; python: 1,108; makefile: 78; sh: 10
file content (320 lines) | stat: -rw-r--r-- 14,426 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
#ifndef CSVREADER_HH
#define CSVREADER_HH

#include <QObject>
#include <QTextStream>
#include <QMap>
#include <QVector>

#include "channel.hh"
#include "contact.hh"

class Config;
class DMRContact;
class RXGroupList;
class Zone;
class PositioningSystem;
class ScanList;
class RoamingZone;


/** The lexer class divides a text stream into tokens. */
class CSVLexer: public QObject
{
  Q_OBJECT

public:
  /** The token. */
  struct Token {
  public:
    /** Possible token types. */
    enum TokenType {
      T_KEYWORD,         ///< A Keyword/Identifier.
      T_APRSCALL,        ///< A APRS call of form CALL-SSID.
      T_STRING,          ///< A quoted string.
      T_NUMBER,          ///< An integer or floating point number.
      T_DCS_N,           ///< A normal DCS code number.
      T_DCS_I,           ///< An inverted DCS code number.
      T_COLON,           ///< A colon.
      T_NOT_SET,         ///< A dash, being used as "not-set".
      T_ENABLED,         ///< A plus sign, being used as "enabled"
      T_COMMA,           ///< A comma

      T_WHITESPACE,      ///< Any whitespace character excluding newline.
      T_NEWLINE,         ///< A new line.
      T_COMMENT,         ///< A comment starts with # end ends at the line-end.

      T_END_OF_STREAM,   ///< Indicates the end-of-input.
      T_ERROR            ///< Indicates a lexer error.
    };

    /// The token type.
    TokenType type;
    /// The token value.
    QString value;
    /// Line number.
    qint64 line;
    /// Column number.
    qint64 column;
  };

  /// Current state of lexer.
  struct State {
    /// The current stream offset.
    qint64 offset;
    /// The current line count.
    qint64 line;
    /// The current column number.
    qint64 column;
  };

public:
  /** Constructs a lexer for the given stream. */
  CSVLexer(QTextStream &stream, QObject *parent=nullptr);

  /** Saves the current lexer state. */
  void push();
  /** Restores the last lexer state. */
  void pop();
  /** Reads the next token from the stream. */
  Token next();
  /** Returns the last error message. */
  const QString &errorMessage() const;

protected:
  /** Internal used function to get the next token. Also returns ignored tokens like whitespace
   * and comment. */
  Token lex();

protected:
  /// The error message.
  QString _errorMessage;
  /// The text stream to read from.
  QTextStream &_stream;
  /// The stack of saved lexer states
  QVector<State> _stack;
  /// The current line count
  QString _currentLine;
  /// The list of patterns to match
  static QVector< QPair<QRegularExpression, Token::TokenType> > _pattern;
};


/** Basic parse-handler interface.
 *
 * That is, a set of callbacks getting called by the parser on the occurrence of a particular
 * statement in the config file.
 * @ingroup conf */
class CSVHandler: public QObject
{
  Q_OBJECT

protected:
  /** Hidden constructor. */
  explicit CSVHandler(QObject *parent=nullptr);

public:
  /** Destructor. */
  virtual ~CSVHandler();

  /** Gets called once the DMR IDs has been parsed. */
  virtual bool handleRadioId(const QList<qint64> &ids, qint64 line, qint64 column, QString &errorMessage);
  /** Gets called once the radio name has been parsed. */
  virtual bool handleRadioName(const QString &name, qint64 line, qint64 column, QString &errorMessage);
  /** Gets called once the first intro line has been parsed. */
  virtual bool handleIntroLine1(const QString &text, qint64 line, qint64 column, QString &errorMessage);
  /** Gets called once the second intro line has been parsed. */
  virtual bool handleIntroLine2(const QString &text, qint64 line, qint64 column, QString &errorMessage);
  /** Gets called once the MIC level has been parsed. */
  virtual bool handleMicLevel(unsigned level, qint64 line, qint64 column, QString &errorMessage);
  /** Gets called once the Speech flag has been parsed. */
  virtual bool handleSpeech(bool speech, qint64 line, qint64 column, QString &errorMessage);
  /** Gets called once a DTMF contact has been parsed. */
  virtual bool handleDTMFContact(qint64 idx, const QString &name, const QString &num, bool rxTone,
                                 qint64 line, qint64 column, QString &errorMessage);
  /** Gets called once a digital contact has been parsed. */
  virtual bool handleDigitalContact(qint64 idx, const QString &name, DMRContact::Type type, qint64 id,
                                    bool rxTone, qint64 line, qint64 column, QString &errorMessage);
  /** Gets called once an RX group list has been parsed. */
  virtual bool handleGroupList(qint64 idx, const QString &name, const QList<qint64> &contacts,
                               qint64 line, qint64 column, QString &errorMessage);
  /** Gets called once a digital channel has been parsed. */
  virtual bool handleDigitalChannel(qint64 idx, const QString &name, double rx, double tx, Channel::Power power, qint64 scan,
      qint64 tot, bool ro, DMRChannel::Admit admit, qint64 color, DMRChannel::TimeSlot slot,
      qint64 gl, qint64 contact, qint64 gps, qint64 roam, qint64 radioID, qint64 line, qint64 column, QString &errorMessage);
  /** Gets called once a analog channel has been parsed. */
  virtual bool handleAnalogChannel(qint64 idx, const QString &name, double rx, double tx, Channel::Power power, qint64 scan, qint64 aprs,
      qint64 tot, bool ro, FMChannel::Admit admit, qint64 squelch, const SelectiveCall &rxTone, const SelectiveCall &txTone,
      FMChannel::Bandwidth bw, qint64 line, qint64 column, QString &errorMessage);
  /** Gets called once a zone list has been parsed. */
  virtual bool handleZone(qint64 idx, const QString &name, bool a, const QList<qint64> &channels,
                          qint64 line, qint64 column, QString &errorMessage);
  /** Gets called once a GPS system has been parsed. */
  virtual bool handleGPSSystem(qint64 idx, const QString &name, qint64 contactIdx, qint64 period,
                               qint64 revertChannelIdx, qint64 line, qint64 column, QString &errorMessage);
  /** Gets called once a APRS system has been parsed. */
  virtual bool handleAPRSSystem(qint64 idx, const QString &name, qint64 channelIdx, qint64 period,
                                const QString &src, unsigned srcSSID, const QString &dest, unsigned destSSID,
                                const QString &path, const QString &icon, const QString &message,
                                qint64 line, qint64 column, QString &errorMessage);
  /** Gets called once a scan list has been parsed. */
  virtual bool handleScanList(qint64 idx, const QString &name, qint64 pch1, qint64 pch2, qint64 txch,
                              const QList<qint64> &channels, qint64 line, qint64 column, QString &errorMessage);
  /** Gets called once a roaming zone list has been parsed. */
  virtual bool handleRoamingZone(qint64 idx, const QString &name, const QList<qint64> &channels,
                                 qint64 line, qint64 column, QString &errorMessage);

};


/** The actual config file parser.
 *
 * This class parses the config file and calls the associated callback functions of a handler
 * instance that is responsible to assemble the final @c Config instance. */
class CSVParser: public QObject
{
  Q_OBJECT

public:
  /** Constructs a parser using the given handler instance. */
  explicit CSVParser(CSVHandler *handler, QObject *parent=nullptr);

  /** Parses the given text stream. */
  bool parse(QTextStream &stream);

  /** Returns the current error message, for example if @c parse returns @c false. */
  const QString &errorMessage() const;

protected:
  /** Internal function to parse DMR IDs. */
  bool _parse_radio_id(CSVLexer &lexer);
  /** Internal function to parse radio names. */
  bool _parse_radio_name(CSVLexer &lexer);
  /** Internal function to parse intro line 1. */
  bool _parse_introline1(CSVLexer &lexer);
  /** Internal function to parse intro line 2. */
  bool _parse_introline2(CSVLexer &lexer);
  /** Internal function to parse MIC level. */
  bool _parse_mic_level(CSVLexer &lexer);
  /** Internal function to parse Speech flag. */
  bool _parse_speech(CSVLexer &lexer);
  /** Internal function to parse UserDB flag. */
  bool _parse_userdb(CSVLexer &lexer);
  /** Internal function to parse a digital contact list. */
  bool _parse_contacts(CSVLexer &lexer);
  /** Internal function to parse digital contact. */
  bool _parse_contact(qint64 id, CSVLexer &lexer);
  /** Internal function to parse an RX group list. */
  bool _parse_rx_groups(CSVLexer &lexer);
  /** Internal function to parse an RX group. */
  bool _parse_rx_group(qint64 id, CSVLexer &lexer);
  /** Internal function to parse a digital channel list. */
  bool _parse_digital_channels(CSVLexer &lexer);
  /** Internal function to parse a digital channel. */
  bool _parse_digital_channel(qint64 id, CSVLexer &lexer);
  /** Internal function to parse an analog channel list. */
  bool _parse_analog_channels(CSVLexer &lexer);
  /** Internal function to parse an analog channel. */
  bool _parse_analog_channel(qint64 id, CSVLexer &lexer);
  /** Internal function to parse a zone list. */
  bool _parse_zones(CSVLexer &lexer);
  /** Internal function to parse a zone. */
  bool _parse_zone(qint64 id, CSVLexer &lexer);
  /** Internal function to parse a GPS system list. */
  bool _parse_gps_systems(CSVLexer &lexer);
  /** Internal function to parse a GPS system. */
  bool _parse_gps_system(qint64 id, CSVLexer &lexer);
  /** Internal function to parse a APRS system list. */
  bool _parse_aprs_systems(CSVLexer &lexer);
  /** Internal function to parse a APRS system. */
  bool _parse_aprs_system(qint64 id, CSVLexer &lexer);
  /** Internal function to parse a scanlist list. */
  bool _parse_scanlists(CSVLexer &lexer);
  /** Internal function to parse a scanlist. */
  bool _parse_scanlist(qint64 id, CSVLexer &lexer);
  /** Internal function to parse a roaming zone list. */
  bool _parse_roaming_zones(CSVLexer &lexer);
  /** Internal function to parse a zone. */
  bool _parse_roaming_zone(qint64 id, CSVLexer &lexer);

protected:
  /** Holds the current error message. */
  QString _errorMessage;
  /** The handler instance. */
  CSVHandler *_handler;
};



/** Implements the text-file codeplug reader.
 * @ingroup conf */
class CSVReader : public CSVHandler
{
	Q_OBJECT

protected:
  /** Hidden constructor. Consider using the static @c read method. */
  CSVReader(Config *config, QObject *parent=nullptr);

public:
  /** Reads a config file from @c stream and stores the read configuration into @c config.
   * @returns @c true on success. */
  static bool read(Config *config, QTextStream &stream, QString &errorMessage);

  virtual bool handleRadioId(const QList<qint64> &ids, qint64 line, qint64 column, QString &errorMessage);
  virtual bool handleRadioName(const QString &name, qint64 line, qint64 column, QString &errorMessage);
  virtual bool handleIntroLine1(const QString &text, qint64 line, qint64 column, QString &errorMessage);
  virtual bool handleIntroLine2(const QString &text, qint64 line, qint64 column, QString &errorMessage);
  virtual bool handleMicLevel(unsigned level, qint64 line, qint64 column, QString &errorMessage);
  virtual bool handleSpeech(bool speech, qint64 line, qint64 column, QString &errorMessage);
  virtual bool handleDTMFContact(qint64 idx, const QString &name, const QString &num, bool rxTone,
                                 qint64 line, qint64 column, QString &errorMessage);
  virtual bool handleDigitalContact(
      qint64 idx, const QString &name, DMRContact::Type type, qint64 id, bool rxTone,
      qint64 line, qint64 column, QString &errorMessage);
  virtual bool handleGroupList(qint64 idx, const QString &name, const QList<qint64> &contacts,
                               qint64 line, qint64 column, QString &errorMessage);
  virtual bool handleDigitalChannel(
      qint64 idx, const QString &name, double rx, double tx, Channel::Power power, qint64 scan,
      qint64 tot, bool ro, DMRChannel::Admit admit, qint64 color, DMRChannel::TimeSlot slot,
      qint64 gl, qint64 contact, qint64 gps, qint64 roam, qint64 radioID, qint64 line, qint64 column, QString &errorMessage);
  virtual bool handleAnalogChannel(qint64 idx, const QString &name, double rx, double tx, Channel::Power power, qint64 scan, qint64 aprs,
      qint64 tot, bool ro, FMChannel::Admit admit, qint64 squelch, const SelectiveCall &rxTone, const SelectiveCall &txTone,
      FMChannel::Bandwidth bw, qint64 line, qint64 column, QString &errorMessage);
  virtual bool handleZone(qint64 idx, const QString &name, bool a, const QList<qint64> &channels,
                          qint64 line, qint64 column, QString &errorMessage);
  virtual bool handleGPSSystem(qint64 idx, const QString &name, qint64 contactIdx, qint64 period,
                               qint64 revertChannelIdx, qint64 line, qint64 column, QString &errorMessage);
  virtual bool handleAPRSSystem(qint64 idx, const QString &name, qint64 channelIdx, qint64 period,
                                const QString &src, unsigned srcSSID, const QString &dest, unsigned destSSID, const QString &path,
                                const QString &icon, const QString &message,
                                qint64 line, qint64 column, QString &errorMessage);
  virtual bool handleScanList(qint64 idx, const QString &name, qint64 pch1, qint64 pch2, qint64 txch,
                              const QList<qint64> &channels, qint64 line, qint64 column, QString &errorMessage);
  virtual bool handleRoamingZone(qint64 idx, const QString &name, const QList<qint64> &channels,
                                 qint64 line, qint64 column, QString &errorMessage);

protected:
  /** If @c true, the reader is in "link" mode. */
  bool _link;
  /** The configuration to read. */
  Config *_config;
  /** Index <-> Channel map. */
	QMap<int, Channel *> _channels;
  /** Index <-> Digital contact map. */
  QMap<int, DMRContact *> _digital_contacts;
  /** Index <-> RX group list map. */
  QMap<int, RXGroupList *> _rxgroups;
  /** Index <-> Zone map. */
  QMap<int, Zone *> _zones;
  /** Index <-> GPS System map. */
  QMap<int, PositioningSystem *> _posSystems;
  /** Index <-> Scan list map. */
  QMap<int, ScanList *> _scanlists;
  /** Index <-> RoamingZone map */
  QMap<int, RoamingZone *> _roamingZones;
  /** Index <-> radio ID map */
  QMap<int, DMRRadioID *> _radioIDs;
};

#endif // CSVREADER_HH