lib: added non-ownership constructors to MultiRecordParser and AllRecordsParser
[barry.git] / src / parser.h
blob80e0146289b1a1744dfba04e2069fe7be8ce3741
1 ///
2 /// \file parser.h
3 /// Virtual parser wrapper
4 ///
6 /*
7 Copyright (C) 2005-2011, 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;
53 // This macro can be used to automatically generate code for all known
54 // record types. Just #undef HANDLE_PARSER, then #define it to whatever
55 // you need, then use ALL_KNOWN_PARSER_TYPES. See parser.cc for
56 // various examples.
58 // These are sorted so their GetDBName()'s will display in alphabetical order.
60 #define ALL_KNOWN_PARSER_TYPES \
61 HANDLE_PARSER(Contact) \
62 HANDLE_PARSER(Bookmark) \
63 HANDLE_PARSER(Calendar) \
64 HANDLE_PARSER(CalendarAll) \
65 HANDLE_PARSER(ContentStore) \
66 HANDLE_PARSER(Folder) \
67 HANDLE_PARSER(Memo) \
68 HANDLE_PARSER(Message) \
69 HANDLE_PARSER(CallLog) \
70 HANDLE_PARSER(PINMessage) \
71 HANDLE_PARSER(SavedMessage) \
72 HANDLE_PARSER(ServiceBook) \
73 HANDLE_PARSER(Sms) \
74 HANDLE_PARSER(Task) \
75 HANDLE_PARSER(Timezone)
77 namespace Barry {
80 // Parser class
82 /// Base class for the parser hierarchy.
83 ///
84 /// This class provides the interface that the Controller class uses
85 /// to pass raw data it reads from the device. The Controller, along
86 /// with the Packet class, calls each of the virtual functions below
87 /// in the same order.
88 ///
89 /// This class is kept as a pure abstract class, in order to make sure
90 /// that the compiler will catch any API changes, for code derived
91 /// from it.
92 ///
93 class BXEXPORT Parser
95 public:
96 Parser() {}
97 virtual ~Parser() {}
99 /// Called to parse sub fields in the raw data packet.
100 virtual void ParseRecord(const DBData &data, const IConverter *ic) = 0;
105 // NullParser class
107 /// If in debug mode, this class can be used as a null parser.
108 /// Call Init() and the protocol will be dumped to stdout and
109 /// no parsing will be done.
111 /// Do NOT derive your own personal parser classes from this,
112 /// unless you are perfectly confident that you will catch
113 /// future API changes on the devel tree without the compiler's
114 /// help.
116 class BXEXPORT NullParser : public Parser
118 public:
119 NullParser() {}
120 virtual ~NullParser() {}
122 virtual void ParseRecord(const DBData &data, const IConverter *ic) {}
126 // HexDumpParser
128 /// Dumps raw hex of the given DBData to the given stream.
130 /// Do NOT derive your own personal parser classes from this,
131 /// unless you are perfectly confident that you will catch
132 /// future API changes on the devel tree without the compiler's
133 /// help.
135 class BXEXPORT HexDumpParser : public Parser
137 std::ostream &m_os;
138 std::string m_last_dbname;
140 public:
141 explicit HexDumpParser(std::ostream &os);
143 virtual void ParseRecord(const Barry::DBData &data,
144 const IConverter *ic);
148 // RecordParserBase
150 /// Abstract base class for the following RecordParser template, that exposes
151 /// some information on the specifics that the record parser can handle.
152 /// Specifically, it exposes the database name it is able to parse
154 class BXEXPORT RecordParserBase : public Parser
156 public:
157 // These functions are always valid, regardless of the
158 // state of the parser.
159 virtual const char * GetDBName() const = 0;
160 virtual uint8_t GetDefaultRecType() const = 0;
162 // These functions depend on the parser having just parsed
163 // a record successfully.
164 virtual bool IsRecordValid() const = 0;
165 virtual uint8_t GetRecType() const = 0;
166 virtual uint32_t GetUniqueId() const = 0;
167 virtual void Dump(std::ostream &os) const = 0;
172 // Note: Store classes take parsed Record objects as a functor.
173 // Parser classes deal with raw data, while Store classes deal with
174 // parsed Record objects.
178 // NullStore
180 /// A Storage class for RecordParser<> that does nothing, for the cases
181 /// where you only want to dump parsed record data to a stream.
183 template <class RecordT>
184 class NullStore
186 public:
187 void operator() (const RecordT &r)
193 // DumpStore
195 /// A Storage class for RecordParser<> that dumps the parsed record data
196 /// to the given stream.
198 template <class RecordT>
199 class DumpStore
201 std::ostream &m_os;
203 public:
204 explicit DumpStore(std::ostream &os)
205 : m_os(os)
209 void operator() (const RecordT &r)
211 r.Dump(m_os);
216 // ParseDBData
218 /// Contains the proper way to convert a DBData object into a record.
220 template <class RecordT>
221 void ParseDBData(const DBData &data, RecordT &rec, const IConverter *ic)
223 // start fresh
224 rec = RecordT();
226 // parse
227 rec.SetIds(data.GetRecType(), data.GetUniqueId());
228 size_t offset = data.GetOffset();
229 rec.ParseHeader(data.GetData(), offset);
230 rec.ParseFields(data.GetData(), offset, ic);
234 // RecordParser template class
236 /// Template class for easy creation of specific parser objects. This template
237 /// takes the following template arguments:
239 /// - RecordT: One of the record parser classes in record.h
240 /// - StorageT: A custom storage functor class. An object of this type
241 /// will be called as a function with parsed Record as an
242 /// argument. This happens on the fly as the data is retrieved
243 /// from the device over USB, so it should not block forever.
245 /// Example LoadDatabase() call:
247 /// <pre>
248 /// struct StoreContact
249 /// {
250 /// std::vector<Contact> &amp;array;
251 /// StoreContact(std::vector<Contact> &amp;a) : array(a) {}
252 /// void operator() (const Contact &amp;c)
253 /// {
254 /// array.push_back(c);
255 /// }
256 /// };
258 /// Controller con(probeResult);
259 /// con.OpenMode(Controller::Desktop);
260 /// std::vector<Contact> contactList;
261 /// StoreContact storage(contactList);
262 /// RecordParser<Contact, StoreContact> parser(storage);
263 /// con.LoadDatabase(con.GetDBID("Address Book"), parser);
264 /// </pre>
266 template <class RecordT, class StorageT>
267 class RecordParser : public RecordParserBase
269 StorageT *m_store;
270 bool m_owned;
271 RecordT m_rec;
272 bool m_record_valid;
274 public:
275 /// Constructor that references an externally managed storage object.
276 RecordParser(StorageT &storage)
277 : m_store(&storage)
278 , m_owned(false)
279 , m_record_valid(false)
283 /// Constructor that references a locally managed storage object.
284 /// The pointer passed in will be stored, and freed when this class
285 /// is destroyed. It is safe to call this constructor with
286 /// a 'new'ly created storage object.
287 RecordParser(StorageT *storage = 0)
288 : m_store(storage)
289 , m_owned(true)
290 , m_record_valid(false)
294 ~RecordParser()
296 if( this->m_owned )
297 delete m_store;
300 virtual StorageT* GetStore()
302 return m_store;
305 virtual const StorageT* GetStore() const
307 return m_store;
310 virtual void ParseRecord(const DBData &data, const IConverter *ic)
312 m_record_valid = false;
313 ParseDBData(data, m_rec, ic);
314 m_record_valid = true;
316 if( m_store )
317 (*m_store)(m_rec);
321 // RecordParserBase overrides
324 // These functions are always valid, regardless of the
325 // state of the parser.
326 virtual const char * GetDBName() const
328 return RecordT::GetDBName();
331 virtual uint8_t GetDefaultRecType() const
333 return RecordT::GetDefaultRecType();
336 // These functions depend on the parser having just parsed
337 // a record successfully.
338 virtual bool IsRecordValid() const
340 return m_record_valid;
343 virtual uint8_t GetRecType() const
345 return m_rec.GetRecType();
348 virtual uint32_t GetUniqueId() const
350 return m_rec.GetUniqueId();
353 virtual void Dump(std::ostream &os) const
355 m_rec.Dump(os);
360 // AllRecordStore
362 /// Base class with overloaded functor behaviour for all available
363 /// record classes. To be used with AllRecordParser.
365 class BXEXPORT AllRecordStore
367 public:
368 AllRecordStore() {}
369 virtual ~AllRecordStore() {}
371 #undef HANDLE_PARSER
372 #define HANDLE_PARSER(tname) \
373 virtual void operator() (const Barry::tname &) = 0;
375 ALL_KNOWN_PARSER_TYPES
379 // MultiRecordParser
381 /// Container parser class that accepts multiple Parser objects
382 /// (often RecordParser<> objects but they don't have to be) and
383 /// automatically routes incoming records to the appropriate parser.
384 /// Note that this container owns *all* Parser objects, and will
385 /// free them upon destruction.
387 /// Incoming records that have no matching parser are passed to the
388 /// default parser object, if one exists, otherwise they are dropped
389 /// silently. The default parser object is also owned by the container,
390 /// and will be freed on destruction.
392 /// Do NOT derive your own personal parser classes from this,
393 /// unless you are perfectly confident that you will catch
394 /// future API changes on the devel tree without the compiler's
395 /// help.
397 class BXEXPORT MultiRecordParser : public Parser
399 typedef std::map<std::string, Parser*> map_type;
401 Parser *m_delete_default; // if set, will be freed
402 Parser *m_default; // used by all code for actual work
403 // and may or may not be "owned" by us
404 map_type m_parsers;
406 public:
407 // takes ownership of default_parser!
408 explicit MultiRecordParser(Parser *default_parser = 0);
410 // does not take ownership of the default_parser
411 explicit MultiRecordParser(Parser &default_parser);
413 ~MultiRecordParser();
415 /// Adds given parser to list and takes ownership of it
416 void Add(const std::string &dbname, Parser *parser);
418 /// Adds given parser to list and takes ownership of it
419 void Add(RecordParserBase *parser);
421 /// Creates a RecordParser<> object using the given record
422 /// type and AllRecordStore. Does NOT take ownership of the
423 /// store object, since it can be used multiple times for
424 /// multiple records.
425 template <class RecordT>
426 void Add(AllRecordStore &store)
428 Add( RecordT::GetDBName(),
429 new RecordParser<RecordT, AllRecordStore>(store) );
432 /// Two helper template functions that create the RecordParser<>
433 /// automatically based on the function call. Both pointer and
434 /// reference versions.
435 template <class RecordT, class StorageT>
436 void Add(StorageT *store)
438 Add( RecordT::GetDBName(),
439 new RecordParser<RecordT, StorageT>(store) );
442 template <class RecordT, class StorageT>
443 void Add(StorageT &store)
445 Add( RecordT::GetDBName(),
446 new RecordParser<RecordT, StorageT>(store) );
449 /// Creates a RecordParser<> object for the given database name,
450 /// using DumpStore<> with the given stream for the output,
451 /// and adds it to list.
452 /// Returns false if there is no known Record class for dbname.
453 bool Add(const std::string &dbname, std::ostream &os);
455 /// Creates a RecordParser<> object for the given database name,
456 /// using the given store object.
457 /// Returns false if there is no known Record class for dbname.
458 bool Add(const std::string &dbname, AllRecordStore &store);
460 // Parser overrides
461 virtual void ParseRecord(const DBData &data, const IConverter *ic);
465 // AllRecordDumpStore
467 /// Derived from AllRecordStore, which just calls each record's
468 /// Dump() member with the given stream.
470 class BXEXPORT AllRecordDumpStore : public AllRecordStore
472 protected:
473 std::ostream &m_os;
475 public:
476 explicit AllRecordDumpStore(std::ostream &os)
477 : m_os(os)
481 #undef HANDLE_PARSER
482 #define HANDLE_PARSER(tname) \
483 virtual void operator() (const Barry::tname &);
485 ALL_KNOWN_PARSER_TYPES
489 // AllRecordParser
491 /// Convenience parser that creates a MultiRecordParser with all known
492 /// record parsers added. If an AllRecordStore pointer is passed in,
493 /// this class takes ownership of it, and uses it as the store object
494 /// for all the RecordParser<> objects it creates. If not, then
495 /// a custom DumpStore<> object is created with the given stream
496 /// for each RecordParser<> added.
498 /// The default parser object behaves just like MultiRecordParser
500 /// This class takes ownership of all pointers passed in.
502 class BXEXPORT AllRecordParser : public MultiRecordParser
504 AllRecordStore *m_store;
506 protected:
507 // does not take ownership of store, by itself,
508 // but the constructor that calls it might
509 void AddRecords(std::ostream *os, AllRecordStore *store);
511 public:
512 // takes ownership of default_parser and store!
513 explicit AllRecordParser(std::ostream &os,
514 Parser *default_parser = 0,
515 AllRecordStore *store = 0);
517 // does not take ownership of default_parser or store
518 AllRecordParser(Parser &default_parser, AllRecordStore &store);
520 ~AllRecordParser();
524 // TeeParser
526 /// Sends incoming DBData objects to all the parsers in its list.
527 /// This parser container does NOT own the parsers added.
529 class BXEXPORT TeeParser : public Parser
531 typedef std::vector<Parser*> parser_list_type;
533 parser_list_type m_external_parsers, m_owned_parsers;
535 public:
536 TeeParser();
537 ~TeeParser();
539 /// Adds parser to internal list, and takes ownership of the
540 /// pointer.
541 void Add(Parser *p);
543 /// Adds parser to internal list. Does NOT own the parser reference.
544 void Add(Parser &p);
546 void ParseRecord(const DBData &data, const IConverter *ic);
549 } // namespace Barry
551 #endif