lib: added corresponding ALL_KNOWN_BUILDER_TYPES to builder.h
[barry.git] / src / parser.h
blob98c47d8c525ca7f6bd7560501699cadcad0d29b6
1 ///
2 /// \file parser.h
3 /// Virtual parser wrapper
4 ///
6 /*
7 Copyright (C) 2005-2010, Net Direct Inc. (http://www.netdirect.ca/)
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
18 See the GNU General Public License in the COPYING file at the
19 root directory of this project for more details.
22 #ifndef __BARRY_PARSER_H__
23 #define __BARRY_PARSER_H__
25 #include "dll.h"
26 #include "data.h"
27 #include "protocol.h"
28 #include <stdint.h> // for uint32_t
29 #include <iosfwd>
30 #include <map>
32 // forward declarations
33 namespace Barry {
34 class IConverter;
35 class Contact;
36 class Message;
37 class Calendar;
38 class CalendarAll;
39 class CallLog;
40 class Bookmark;
41 class ServiceBook;
42 class Memo;
43 class Task;
44 class PINMessage;
45 class SavedMessage;
46 class Sms;
47 class Folder;
48 class Timezone;
52 // This macro can be used to automatically generate code for all known
53 // record types. Just #undef HANDLE_PARSER, then #define it to whatever
54 // you need, then use ALL_KNOWN_PARSER_TYPES. See parser.cc for
55 // various examples.
57 // These are sorted so their GetDBName()'s will display in alphabetical order.
59 #define ALL_KNOWN_PARSER_TYPES \
60 HANDLE_PARSER(Contact) \
61 HANDLE_PARSER(Bookmark) \
62 HANDLE_PARSER(Calendar) \
63 HANDLE_PARSER(CalendarAll) \
64 HANDLE_PARSER(Folder) \
65 HANDLE_PARSER(Memo) \
66 HANDLE_PARSER(Message) \
67 HANDLE_PARSER(CallLog) \
68 HANDLE_PARSER(PINMessage) \
69 HANDLE_PARSER(SavedMessage) \
70 HANDLE_PARSER(ServiceBook) \
71 HANDLE_PARSER(Sms) \
72 HANDLE_PARSER(Task) \
73 HANDLE_PARSER(Timezone)
75 namespace Barry {
78 // Parser class
80 /// Base class for the parser hierarchy.
81 ///
82 /// This class provides the interface that the Controller class uses
83 /// to pass raw data it reads from the device. The Controller, along
84 /// with the Packet class, calls each of the virtual functions below
85 /// in the same order.
86 ///
87 /// This class is kept as a pure abstract class, in order to make sure
88 /// that the compiler will catch any API changes, for code derived
89 /// from it.
90 ///
91 class BXEXPORT Parser
93 public:
94 Parser() {}
95 virtual ~Parser() {}
97 /// Called to parse sub fields in the raw data packet.
98 virtual void ParseRecord(const DBData &data, const IConverter *ic) = 0;
103 // NullParser class
105 /// If in debug mode, this class can be used as a null parser.
106 /// Call Init() and the protocol will be dumped to stdout and
107 /// no parsing will be done.
109 /// Do NOT derive your own personal parser classes from this,
110 /// unless you are perfectly confident that you will catch
111 /// future API changes on the devel tree without the compiler's
112 /// help.
114 class BXEXPORT NullParser : public Parser
116 public:
117 NullParser() {}
118 virtual ~NullParser() {}
120 virtual void ParseRecord(const DBData &data, const IConverter *ic) {}
124 // HexDumpParser
126 /// Dumps raw hex of the given DBData to the given stream.
128 /// Do NOT derive your own personal parser classes from this,
129 /// unless you are perfectly confident that you will catch
130 /// future API changes on the devel tree without the compiler's
131 /// help.
133 class BXEXPORT HexDumpParser : public Parser
135 std::ostream &m_os;
137 public:
138 explicit HexDumpParser(std::ostream &os);
140 virtual void ParseRecord(const Barry::DBData &data,
141 const IConverter *ic);
145 // RecordParserBase
147 /// Abstract base class for the following RecordParser template, that exposes
148 /// some information on the specifics that the record parser can handle.
149 /// Specifically, it exposes the database name it is able to parse
151 class BXEXPORT RecordParserBase : public Parser
153 public:
154 // These functions are always valid, regardless of the
155 // state of the parser.
156 virtual const char * GetDBName() const = 0;
157 virtual uint8_t GetDefaultRecType() const = 0;
159 // These functions depend on the parser having just parsed
160 // a record successfully.
161 virtual bool IsRecordValid() const = 0;
162 virtual uint8_t GetRecType() const = 0;
163 virtual uint32_t GetUniqueId() const = 0;
164 virtual void Dump(std::ostream &os) const = 0;
169 // Note: Store classes take parsed Record objects as a functor.
170 // Parser classes deal with raw data, while Store classes deal with
171 // parsed Record objects.
175 // NullStore
177 /// A Storage class for RecordParser<> that does nothing, for the cases
178 /// where you only want to dump parsed record data to a stream.
180 template <class RecordT>
181 class NullStore
183 public:
184 void operator() (const RecordT &r)
190 // DumpStore
192 /// A Storage class for RecordParser<> that dumps the parsed record data
193 /// to the given stream.
195 template <class RecordT>
196 class DumpStore
198 std::ostream &m_os;
200 public:
201 explicit DumpStore(std::ostream &os)
202 : m_os(os)
206 void operator() (const RecordT &r)
208 r.Dump(m_os);
213 // RecordParser template class
215 /// Template class for easy creation of specific parser objects. This template
216 /// takes the following template arguments:
218 /// - RecordT: One of the record parser classes in record.h
219 /// - StorageT: A custom storage functor class. An object of this type
220 /// will be called as a function with parsed Record as an
221 /// argument. This happens on the fly as the data is retrieved
222 /// from the device over USB, so it should not block forever.
224 /// Example LoadDatabase() call:
226 /// <pre>
227 /// struct StoreContact
228 /// {
229 /// std::vector<Contact> &amp;array;
230 /// StoreContact(std::vector<Contact> &amp;a) : array(a) {}
231 /// void operator() (const Contact &amp;c)
232 /// {
233 /// array.push_back(c);
234 /// }
235 /// };
237 /// Controller con(probeResult);
238 /// con.OpenMode(Controller::Desktop);
239 /// std::vector<Contact> contactList;
240 /// StoreContact storage(contactList);
241 /// RecordParser<Contact, StoreContact> parser(storage);
242 /// con.LoadDatabase(con.GetDBID("Address Book"), parser);
243 /// </pre>
245 template <class RecordT, class StorageT>
246 class RecordParser : public RecordParserBase
248 StorageT *m_store;
249 bool m_owned;
250 RecordT m_rec;
251 bool m_record_valid;
253 public:
254 /// Constructor that references an externally managed storage object.
255 RecordParser(StorageT &storage)
256 : m_store(&storage)
257 , m_owned(false)
258 , m_record_valid(false)
262 /// Constructor that references a locally managed storage object.
263 /// The pointer passed in will be stored, and freed when this class
264 /// is destroyed. It is safe to call this constructor with
265 /// a 'new'ly created storage object.
266 RecordParser(StorageT *storage = 0)
267 : m_store(storage)
268 , m_owned(true)
269 , m_record_valid(false)
273 ~RecordParser()
275 if( this->m_owned )
276 delete m_store;
279 virtual StorageT* GetStore()
281 return m_store;
284 virtual const StorageT* GetStore() const
286 return m_store;
289 virtual void ParseRecord(const DBData &data, const IConverter *ic)
291 m_rec = RecordT();
292 m_record_valid = false;
294 m_rec.SetIds(data.GetRecType(), data.GetUniqueId());
295 size_t offset = data.GetOffset();
296 m_rec.ParseHeader(data.GetData(), offset);
297 m_rec.ParseFields(data.GetData(), offset, ic);
298 m_record_valid = true;
300 if( m_store )
301 (*m_store)(m_rec);
305 // RecordParserBase overrides
308 // These functions are always valid, regardless of the
309 // state of the parser.
310 virtual const char * GetDBName() const
312 return RecordT::GetDBName();
315 virtual uint8_t GetDefaultRecType() const
317 return RecordT::GetDefaultRecType();
320 // These functions depend on the parser having just parsed
321 // a record successfully.
322 virtual bool IsRecordValid() const
324 return m_record_valid;
327 virtual uint8_t GetRecType() const
329 return m_rec.GetRecType();
332 virtual uint32_t GetUniqueId() const
334 return m_rec.GetUniqueId();
337 virtual void Dump(std::ostream &os) const
339 m_rec.Dump(os);
344 // MultiRecordParser
346 /// Container parser class that accepts multiple Parser objects
347 /// (often RecordParser<> objects but they don't have to be) and
348 /// automatically routes incoming records to the appropriate parser.
349 /// Note that this container owns *all* Parser objects, and will
350 /// free them upon destruction.
352 /// Incoming records that have no matching parser are passed to the
353 /// default parser object, if one exists, otherwise they are dropped
354 /// silently. The default parser object is also owned by the container,
355 /// and will be freed on destruction.
357 /// Do NOT derive your own personal parser classes from this,
358 /// unless you are perfectly confident that you will catch
359 /// future API changes on the devel tree without the compiler's
360 /// help.
362 class BXEXPORT MultiRecordParser : public Parser
364 typedef std::map<std::string, Parser*> map_type;
366 Parser *m_default;
367 map_type m_parsers;
369 public:
370 // takes ownership of default_parser!
371 explicit MultiRecordParser(Parser *default_parser = 0);
372 ~MultiRecordParser();
374 /// Adds given parser to list and takes ownership of it
375 void Add(const std::string &dbname, Parser *parser);
377 /// Adds given parser to list and takes ownership of it
378 void Add(RecordParserBase *parser);
380 /// Creates a RecordParser<> object for the given database name,
381 /// using DumpStore<> with the given stream for the output,
382 /// and adds it to list.
383 /// Returns false if there is no known Record class for dbname.
384 bool Add(const std::string &dbname, std::ostream &os);
386 // Parser overrides
387 virtual void ParseRecord(const DBData &data, const IConverter *ic);
391 // AllRecordStore
393 /// Base class with overloaded functor behaviour for all available
394 /// record classes. To be used with AllRecordParser.
396 class BXEXPORT AllRecordStore
398 public:
399 AllRecordStore() {}
400 virtual ~AllRecordStore() {}
402 virtual void operator() (const Barry::Contact &) = 0;
403 virtual void operator() (const Barry::Message &) = 0;
404 virtual void operator() (const Barry::Calendar &) = 0;
405 virtual void operator() (const Barry::CalendarAll &) = 0;
406 virtual void operator() (const Barry::CallLog &) = 0;
407 virtual void operator() (const Barry::Bookmark &) = 0;
408 virtual void operator() (const Barry::ServiceBook &) = 0;
409 virtual void operator() (const Barry::Memo &) = 0;
410 virtual void operator() (const Barry::Task &) = 0;
411 virtual void operator() (const Barry::PINMessage &) = 0;
412 virtual void operator() (const Barry::SavedMessage &) = 0;
413 virtual void operator() (const Barry::Sms &) = 0;
414 virtual void operator() (const Barry::Folder &) = 0;
415 virtual void operator() (const Barry::Timezone &) = 0;
419 // AllRecordDumpStore
421 /// Derived from AllRecordStore, which just calls each record's
422 /// Dump() member with the given stream.
424 class BXEXPORT AllRecordDumpStore : public AllRecordStore
426 protected:
427 std::ostream &m_os;
429 public:
430 explicit AllRecordDumpStore(std::ostream &os)
431 : m_os(os)
435 virtual void operator() (const Barry::Contact &);
436 virtual void operator() (const Barry::Message &);
437 virtual void operator() (const Barry::Calendar &);
438 virtual void operator() (const Barry::CalendarAll &);
439 virtual void operator() (const Barry::CallLog &);
440 virtual void operator() (const Barry::Bookmark &);
441 virtual void operator() (const Barry::ServiceBook &);
442 virtual void operator() (const Barry::Memo &);
443 virtual void operator() (const Barry::Task &);
444 virtual void operator() (const Barry::PINMessage &);
445 virtual void operator() (const Barry::SavedMessage &);
446 virtual void operator() (const Barry::Sms &);
447 virtual void operator() (const Barry::Folder &);
448 virtual void operator() (const Barry::Timezone &);
452 // AllRecordParser
454 /// Convenience parser that creates a MultiRecordParser with all known
455 /// record parsers added. If an AllRecordStore pointer is passed in,
456 /// this class takes ownership of it, and uses it as the store object
457 /// for all the RecordParser<> objects it creates. If not, then
458 /// a custom DumpStore<> object is created with the given stream
459 /// for each RecordParser<> added.
461 /// The default parser object behaves just like MultiRecordParser
463 /// This class takes ownership of all pointers passed in.
465 class BXEXPORT AllRecordParser : public MultiRecordParser
467 AllRecordStore *m_store;
469 public:
470 // takes ownership of default_parser and store!
471 explicit AllRecordParser(std::ostream &os,
472 Parser *default_parser = 0,
473 AllRecordStore *store = 0);
474 ~AllRecordParser();
478 // TeeParser
480 /// Sends incoming DBData objects to all the parsers in its list.
481 /// This parser container does NOT own the parsers added.
483 class BXEXPORT TeeParser : public Parser
485 typedef std::vector<Parser*> parser_list_type;
487 parser_list_type m_external_parsers, m_owned_parsers;
489 public:
490 TeeParser();
491 ~TeeParser();
493 /// Adds parser to internal list, and takes ownership of the
494 /// pointer.
495 void Add(Parser *p);
497 /// Adds parser to internal list. Does NOT own the parser reference.
498 void Add(Parser &p);
500 void ParseRecord(const DBData &data, const IConverter *ic);
503 } // namespace Barry
505 #endif