tzwrapper.cc: fixed use of iterator after erase
[barry.git] / src / parser.h
blob4d9b401d429c538ab8d874eae05222ce9c4619d6
1 ///
2 /// \file parser.h
3 /// Virtual parser wrapper
4 ///
6 /*
7 Copyright (C) 2005-2013, 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;
49 class ContentStore;
50 class HandheldAgent;
54 // This macro can be used to automatically generate code for all known
55 // record types. Just #undef HANDLE_PARSER, then #define it to whatever
56 // you need, then use ALL_KNOWN_PARSER_TYPES. See parser.cc for
57 // various examples.
59 // These are sorted so their GetDBName()'s will display in alphabetical order.
61 #define ALL_KNOWN_PARSER_TYPES \
62 HANDLE_PARSER(Contact) \
63 HANDLE_PARSER(Bookmark) \
64 HANDLE_PARSER(Calendar) \
65 HANDLE_PARSER(CalendarAll) \
66 HANDLE_PARSER(ContentStore) \
67 HANDLE_PARSER(Folder) \
68 HANDLE_PARSER(HandheldAgent) \
69 HANDLE_PARSER(Memo) \
70 HANDLE_PARSER(Message) \
71 HANDLE_PARSER(CallLog) \
72 HANDLE_PARSER(PINMessage) \
73 HANDLE_PARSER(SavedMessage) \
74 HANDLE_PARSER(ServiceBook) \
75 HANDLE_PARSER(Sms) \
76 HANDLE_PARSER(Task) \
77 HANDLE_PARSER(TimeZone)
79 namespace Barry {
82 // Parser class
84 /// Base class for the parser hierarchy.
85 ///
86 /// This class provides the interface that the Controller class uses
87 /// to pass raw data it reads from the device. The Controller, along
88 /// with the Packet class, calls each of the virtual functions below
89 /// in the same order.
90 ///
91 /// This class is kept as a pure abstract class, in order to make sure
92 /// that the compiler will catch any API changes, for code derived
93 /// from it.
94 ///
95 class BXEXPORT Parser
97 public:
98 Parser() {}
99 virtual ~Parser() {}
101 /// Called to parse sub fields in the raw data packet.
102 virtual void ParseRecord(const DBData &data, const IConverter *ic) = 0;
107 // NullParser class
109 /// If in debug mode, this class can be used as a null parser.
110 /// Call Init() and the protocol will be dumped to stdout and
111 /// no parsing will be done.
113 /// Do NOT derive your own personal parser classes from this,
114 /// unless you are perfectly confident that you will catch
115 /// future API changes on the devel tree without the compiler's
116 /// help.
118 class BXEXPORT NullParser : public Parser
120 public:
121 NullParser() {}
122 virtual ~NullParser() {}
124 virtual void ParseRecord(const DBData &data, const IConverter *ic) {}
128 // HexDumpParser
130 /// Dumps raw hex of the given DBData to the given stream.
132 /// Do NOT derive your own personal parser classes from this,
133 /// unless you are perfectly confident that you will catch
134 /// future API changes on the devel tree without the compiler's
135 /// help.
137 class BXEXPORT HexDumpParser : public Parser
139 std::ostream &m_os;
140 std::string m_last_dbname;
142 public:
143 explicit HexDumpParser(std::ostream &os);
145 virtual void ParseRecord(const Barry::DBData &data,
146 const IConverter *ic);
150 // DBNamesOnlyParser
152 /// Prints only the unique databases names found in the stream.
154 /// Do NOT derive your own personal parser classes from this,
155 /// unless you are perfectly confident that you will catch
156 /// future API changes on the devel tree without the compiler's
157 /// help.
159 class BXEXPORT DBNamesOnlyParser : public Parser
161 std::ostream &m_os;
162 std::string m_last_dbname;
164 public:
165 explicit DBNamesOnlyParser(std::ostream &os);
167 virtual void ParseRecord(const Barry::DBData &data,
168 const IConverter *ic);
172 // RecordParserBase
174 /// Abstract base class for the following RecordParser template, that exposes
175 /// some information on the specifics that the record parser can handle.
176 /// Specifically, it exposes the database name it is able to parse
178 class BXEXPORT RecordParserBase : public Parser
180 public:
181 // These functions are always valid, regardless of the
182 // state of the parser.
183 virtual const char * GetDBName() const = 0;
184 virtual uint8_t GetDefaultRecType() const = 0;
186 // These functions depend on the parser having just parsed
187 // a record successfully.
188 virtual bool IsRecordValid() const = 0;
189 virtual uint8_t GetRecType() const = 0;
190 virtual uint32_t GetUniqueId() const = 0;
191 virtual void Dump(std::ostream &os) const = 0;
196 // Note: Store classes take parsed Record objects as a functor.
197 // Parser classes deal with raw data, while Store classes deal with
198 // parsed Record objects.
202 // NullStore
204 /// A Storage class for RecordParser<> that does nothing, for the cases
205 /// where you only want to dump parsed record data to a stream.
207 template <class RecordT>
208 class NullStore
210 public:
211 void operator() (const RecordT &r)
217 // DumpStore
219 /// A Storage class for RecordParser<> that dumps the parsed record data
220 /// to the given stream.
222 template <class RecordT>
223 class DumpStore
225 std::ostream &m_os;
227 public:
228 explicit DumpStore(std::ostream &os)
229 : m_os(os)
233 void operator() (const RecordT &r)
235 r.Dump(m_os);
240 // RecordStore
242 /// A Storage class for RecordParser that stores a copy of the parsed record.
244 template <class RecordT>
245 class RecordStore
247 public:
248 RecordT m_rec;
250 void operator() (const RecordT &r)
252 m_rec = r;
257 // ParseDBData
259 /// Contains the proper way to convert a DBData object into a record.
261 template <class RecordT>
262 void ParseDBData(const DBData &data, RecordT &rec, const IConverter *ic)
264 // start fresh
265 rec = RecordT();
267 // parse
268 rec.SetIds(data.GetRecType(), data.GetUniqueId());
269 size_t offset = data.GetOffset();
270 rec.ParseHeader(data.GetData(), offset);
271 rec.ParseFields(data.GetData(), offset, ic);
275 // RecordParser template class
277 /// Template class for easy creation of specific parser objects. This template
278 /// takes the following template arguments:
280 /// - RecordT: One of the record parser classes in record.h
281 /// - StorageT: A custom storage functor class. An object of this type
282 /// will be called as a function with parsed Record as an
283 /// argument. This happens on the fly as the data is retrieved
284 /// from the device over USB, so it should not block forever.
286 /// Example LoadDatabase() call:
288 /// <pre>
289 /// struct StoreContact
290 /// {
291 /// std::vector<Contact> &amp;array;
292 /// StoreContact(std::vector<Contact> &amp;a) : array(a) {}
293 /// void operator() (const Contact &amp;c)
294 /// {
295 /// array.push_back(c);
296 /// }
297 /// };
299 /// Controller con(probeResult);
300 /// con.OpenMode(Controller::Desktop);
301 /// std::vector<Contact> contactList;
302 /// StoreContact storage(contactList);
303 /// RecordParser<Contact, StoreContact> parser(storage);
304 /// con.LoadDatabase(con.GetDBID("Address Book"), parser);
305 /// </pre>
307 template <class RecordT, class StorageT>
308 class RecordParser : public RecordParserBase
310 StorageT *m_store;
311 bool m_owned;
312 RecordT m_rec;
313 bool m_record_valid;
315 public:
316 /// Constructor that references an externally managed storage object.
317 RecordParser(StorageT &storage)
318 : m_store(&storage)
319 , m_owned(false)
320 , m_record_valid(false)
324 /// Constructor that references a locally managed storage object.
325 /// The pointer passed in will be stored, and freed when this class
326 /// is destroyed. It is safe to call this constructor with
327 /// a 'new'ly created storage object.
328 RecordParser(StorageT *storage = 0)
329 : m_store(storage)
330 , m_owned(true)
331 , m_record_valid(false)
335 ~RecordParser()
337 if( this->m_owned )
338 delete m_store;
341 virtual StorageT* GetStore()
343 return m_store;
346 virtual const StorageT* GetStore() const
348 return m_store;
351 virtual void ParseRecord(const DBData &data, const IConverter *ic)
353 m_record_valid = false;
354 ParseDBData(data, m_rec, ic);
355 m_record_valid = true;
357 if( m_store )
358 (*m_store)(m_rec);
362 // RecordParserBase overrides
365 // These functions are always valid, regardless of the
366 // state of the parser.
367 virtual const char * GetDBName() const
369 return RecordT::GetDBName();
372 virtual uint8_t GetDefaultRecType() const
374 return RecordT::GetDefaultRecType();
377 // These functions depend on the parser having just parsed
378 // a record successfully.
379 virtual bool IsRecordValid() const
381 return m_record_valid;
384 virtual const RecordT& GetRecord() const
386 return m_rec;
389 virtual uint8_t GetRecType() const
391 return m_rec.GetRecType();
394 virtual uint32_t GetUniqueId() const
396 return m_rec.GetUniqueId();
399 virtual void Dump(std::ostream &os) const
401 m_rec.Dump(os);
406 // AllRecordStore
408 /// Base class with overloaded functor behaviour for all available
409 /// record classes. To be used with AllRecordParser.
411 class BXEXPORT AllRecordStore
413 public:
414 AllRecordStore() {}
415 virtual ~AllRecordStore() {}
417 #undef HANDLE_PARSER
418 #define HANDLE_PARSER(tname) \
419 virtual void operator() (const Barry::tname &) = 0;
421 ALL_KNOWN_PARSER_TYPES
425 // MultiRecordParser
427 /// Container parser class that accepts multiple Parser objects
428 /// (often RecordParser<> objects but they don't have to be) and
429 /// automatically routes incoming records to the appropriate parser.
430 /// Note that this container owns *all* Parser objects, and will
431 /// free them upon destruction.
433 /// Incoming records that have no matching parser are passed to the
434 /// default parser object, if one exists, otherwise they are dropped
435 /// silently. The default parser object is also owned by the container,
436 /// and will be freed on destruction.
438 /// Do NOT derive your own personal parser classes from this,
439 /// unless you are perfectly confident that you will catch
440 /// future API changes on the devel tree without the compiler's
441 /// help.
443 class BXEXPORT MultiRecordParser : public Parser
445 typedef std::map<std::string, Parser*> map_type;
447 Parser *m_delete_default; // if set, will be freed
448 Parser *m_default; // used by all code for actual work
449 // and may or may not be "owned" by us
450 map_type m_parsers;
452 public:
453 // takes ownership of default_parser!
454 explicit MultiRecordParser(Parser *default_parser = 0);
456 // does not take ownership of the default_parser
457 explicit MultiRecordParser(Parser &default_parser);
459 ~MultiRecordParser();
461 /// Adds given parser to list and takes ownership of it
462 void Add(const std::string &dbname, Parser *parser);
464 /// Adds given parser to list and takes ownership of it
465 void Add(RecordParserBase *parser);
467 /// Creates a RecordParser<> object using the given record
468 /// type and AllRecordStore. Does NOT take ownership of the
469 /// store object, since it can be used multiple times for
470 /// multiple records.
471 template <class RecordT>
472 void Add(AllRecordStore &store)
474 Add( RecordT::GetDBName(),
475 new RecordParser<RecordT, AllRecordStore>(store) );
478 /// Two helper template functions that create the RecordParser<>
479 /// automatically based on the function call. Both pointer and
480 /// reference versions.
481 template <class RecordT, class StorageT>
482 void Add(StorageT *store)
484 Add( RecordT::GetDBName(),
485 new RecordParser<RecordT, StorageT>(store) );
488 template <class RecordT, class StorageT>
489 void Add(StorageT &store)
491 Add( RecordT::GetDBName(),
492 new RecordParser<RecordT, StorageT>(store) );
495 /// Creates a RecordParser<> object for the given database name,
496 /// using DumpStore<> with the given stream for the output,
497 /// and adds it to list.
498 /// Returns false if there is no known Record class for dbname.
499 bool Add(const std::string &dbname, std::ostream &os);
501 /// Creates a RecordParser<> object for the given database name,
502 /// using the given store object.
503 /// Returns false if there is no known Record class for dbname.
504 bool Add(const std::string &dbname, AllRecordStore &store);
506 // Parser overrides
507 virtual void ParseRecord(const DBData &data, const IConverter *ic);
511 // AllRecordDumpStore
513 /// Derived from AllRecordStore, which just calls each record's
514 /// Dump() member with the given stream.
516 class BXEXPORT AllRecordDumpStore : public AllRecordStore
518 protected:
519 std::ostream &m_os;
521 public:
522 explicit AllRecordDumpStore(std::ostream &os)
523 : m_os(os)
527 #undef HANDLE_PARSER
528 #define HANDLE_PARSER(tname) \
529 virtual void operator() (const Barry::tname &);
531 ALL_KNOWN_PARSER_TYPES
535 // AllRecordParser
537 /// Convenience parser that creates a MultiRecordParser with all known
538 /// record parsers added. If an AllRecordStore pointer is passed in,
539 /// this class takes ownership of it, and uses it as the store object
540 /// for all the RecordParser<> objects it creates. If not, then
541 /// a custom DumpStore<> object is created with the given stream
542 /// for each RecordParser<> added.
544 /// The default parser object behaves just like MultiRecordParser
546 /// This class takes ownership of all pointers passed in.
548 class BXEXPORT AllRecordParser : public MultiRecordParser
550 AllRecordStore *m_store;
552 protected:
553 // does not take ownership of store, by itself,
554 // but the constructor that calls it might
555 void AddRecords(std::ostream *os, AllRecordStore *store);
557 public:
558 // takes ownership of default_parser and store!
559 explicit AllRecordParser(std::ostream &os,
560 Parser *default_parser = 0,
561 AllRecordStore *store = 0);
563 // does not take ownership of default_parser or store
564 AllRecordParser(Parser &default_parser, AllRecordStore &store);
566 ~AllRecordParser();
570 // TeeParser
572 /// Sends incoming DBData objects to all the parsers in its list.
573 /// This parser container does NOT own the parsers added.
575 class BXEXPORT TeeParser : public Parser
577 typedef std::vector<Parser*> parser_list_type;
579 parser_list_type m_external_parsers, m_owned_parsers;
581 public:
582 TeeParser();
583 ~TeeParser();
585 /// Adds parser to internal list, and takes ownership of the
586 /// pointer.
587 void Add(Parser *p);
589 /// Adds parser to internal list. Does NOT own the parser reference.
590 void Add(Parser &p);
592 void ParseRecord(const DBData &data, const IConverter *ic);
595 } // namespace Barry
597 #endif