3 /// Virtual parser wrapper
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__
28 #include <stdint.h> // for uint32_t
32 // forward declarations
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
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) \
68 HANDLE_PARSER(Message) \
69 HANDLE_PARSER(CallLog) \
70 HANDLE_PARSER(PINMessage) \
71 HANDLE_PARSER(SavedMessage) \
72 HANDLE_PARSER(ServiceBook) \
75 HANDLE_PARSER(Timezone)
82 /// Base class for the parser hierarchy.
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.
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
99 /// Called to parse sub fields in the raw data packet.
100 virtual void ParseRecord(const DBData
&data
, const IConverter
*ic
) = 0;
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
116 class BXEXPORT NullParser
: public Parser
120 virtual ~NullParser() {}
122 virtual void ParseRecord(const DBData
&data
, const IConverter
*ic
) {}
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
135 class BXEXPORT HexDumpParser
: public Parser
138 std::string m_last_dbname
;
141 explicit HexDumpParser(std::ostream
&os
);
143 virtual void ParseRecord(const Barry::DBData
&data
,
144 const IConverter
*ic
);
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
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.
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
>
187 void operator() (const RecordT
&r
)
195 /// A Storage class for RecordParser<> that dumps the parsed record data
196 /// to the given stream.
198 template <class RecordT
>
204 explicit DumpStore(std::ostream
&os
)
209 void operator() (const RecordT
&r
)
216 // RecordParser template class
218 /// Template class for easy creation of specific parser objects. This template
219 /// takes the following template arguments:
221 /// - RecordT: One of the record parser classes in record.h
222 /// - StorageT: A custom storage functor class. An object of this type
223 /// will be called as a function with parsed Record as an
224 /// argument. This happens on the fly as the data is retrieved
225 /// from the device over USB, so it should not block forever.
227 /// Example LoadDatabase() call:
230 /// struct StoreContact
232 /// std::vector<Contact> &array;
233 /// StoreContact(std::vector<Contact> &a) : array(a) {}
234 /// void operator() (const Contact &c)
236 /// array.push_back(c);
240 /// Controller con(probeResult);
241 /// con.OpenMode(Controller::Desktop);
242 /// std::vector<Contact> contactList;
243 /// StoreContact storage(contactList);
244 /// RecordParser<Contact, StoreContact> parser(storage);
245 /// con.LoadDatabase(con.GetDBID("Address Book"), parser);
248 template <class RecordT
, class StorageT
>
249 class RecordParser
: public RecordParserBase
257 /// Constructor that references an externally managed storage object.
258 RecordParser(StorageT
&storage
)
261 , m_record_valid(false)
265 /// Constructor that references a locally managed storage object.
266 /// The pointer passed in will be stored, and freed when this class
267 /// is destroyed. It is safe to call this constructor with
268 /// a 'new'ly created storage object.
269 RecordParser(StorageT
*storage
= 0)
272 , m_record_valid(false)
282 virtual StorageT
* GetStore()
287 virtual const StorageT
* GetStore() const
292 virtual void ParseRecord(const DBData
&data
, const IConverter
*ic
)
295 m_record_valid
= false;
297 m_rec
.SetIds(data
.GetRecType(), data
.GetUniqueId());
298 size_t offset
= data
.GetOffset();
299 m_rec
.ParseHeader(data
.GetData(), offset
);
300 m_rec
.ParseFields(data
.GetData(), offset
, ic
);
301 m_record_valid
= true;
308 // RecordParserBase overrides
311 // These functions are always valid, regardless of the
312 // state of the parser.
313 virtual const char * GetDBName() const
315 return RecordT::GetDBName();
318 virtual uint8_t GetDefaultRecType() const
320 return RecordT::GetDefaultRecType();
323 // These functions depend on the parser having just parsed
324 // a record successfully.
325 virtual bool IsRecordValid() const
327 return m_record_valid
;
330 virtual uint8_t GetRecType() const
332 return m_rec
.GetRecType();
335 virtual uint32_t GetUniqueId() const
337 return m_rec
.GetUniqueId();
340 virtual void Dump(std::ostream
&os
) const
349 /// Base class with overloaded functor behaviour for all available
350 /// record classes. To be used with AllRecordParser.
352 class BXEXPORT AllRecordStore
356 virtual ~AllRecordStore() {}
359 #define HANDLE_PARSER(tname) \
360 virtual void operator() (const Barry::tname &) = 0;
362 ALL_KNOWN_PARSER_TYPES
368 /// Container parser class that accepts multiple Parser objects
369 /// (often RecordParser<> objects but they don't have to be) and
370 /// automatically routes incoming records to the appropriate parser.
371 /// Note that this container owns *all* Parser objects, and will
372 /// free them upon destruction.
374 /// Incoming records that have no matching parser are passed to the
375 /// default parser object, if one exists, otherwise they are dropped
376 /// silently. The default parser object is also owned by the container,
377 /// and will be freed on destruction.
379 /// Do NOT derive your own personal parser classes from this,
380 /// unless you are perfectly confident that you will catch
381 /// future API changes on the devel tree without the compiler's
384 class BXEXPORT MultiRecordParser
: public Parser
386 typedef std::map
<std::string
, Parser
*> map_type
;
392 // takes ownership of default_parser!
393 explicit MultiRecordParser(Parser
*default_parser
= 0);
394 ~MultiRecordParser();
396 /// Adds given parser to list and takes ownership of it
397 void Add(const std::string
&dbname
, Parser
*parser
);
399 /// Adds given parser to list and takes ownership of it
400 void Add(RecordParserBase
*parser
);
402 /// Creates a RecordParser<> object using the given record
403 /// type and AllRecordStore. Does NOT take ownership of the
404 /// store object, since it can be used multiple times for
405 /// multiple records.
406 template <class RecordT
>
407 void Add(AllRecordStore
&store
)
409 Add( RecordT::GetDBName(),
410 new RecordParser
<RecordT
, AllRecordStore
>(store
) );
413 /// Two helper template functions that create the RecordParser<>
414 /// automatically based on the function call. Both pointer and
415 /// reference versions.
416 template <class RecordT
, class StorageT
>
417 void Add(StorageT
*store
)
419 Add( RecordT::GetDBName(),
420 new RecordParser
<RecordT
, StorageT
>(store
) );
423 template <class RecordT
, class StorageT
>
424 void Add(StorageT
&store
)
426 Add( RecordT::GetDBName(),
427 new RecordParser
<RecordT
, StorageT
>(store
) );
430 /// Creates a RecordParser<> object for the given database name,
431 /// using DumpStore<> with the given stream for the output,
432 /// and adds it to list.
433 /// Returns false if there is no known Record class for dbname.
434 bool Add(const std::string
&dbname
, std::ostream
&os
);
436 /// Creates a RecordParser<> object for the given database name,
437 /// using the given store object.
438 /// Returns false if there is no known Record class for dbname.
439 bool Add(const std::string
&dbname
, AllRecordStore
&store
);
442 virtual void ParseRecord(const DBData
&data
, const IConverter
*ic
);
446 // AllRecordDumpStore
448 /// Derived from AllRecordStore, which just calls each record's
449 /// Dump() member with the given stream.
451 class BXEXPORT AllRecordDumpStore
: public AllRecordStore
457 explicit AllRecordDumpStore(std::ostream
&os
)
463 #define HANDLE_PARSER(tname) \
464 virtual void operator() (const Barry::tname &);
466 ALL_KNOWN_PARSER_TYPES
472 /// Convenience parser that creates a MultiRecordParser with all known
473 /// record parsers added. If an AllRecordStore pointer is passed in,
474 /// this class takes ownership of it, and uses it as the store object
475 /// for all the RecordParser<> objects it creates. If not, then
476 /// a custom DumpStore<> object is created with the given stream
477 /// for each RecordParser<> added.
479 /// The default parser object behaves just like MultiRecordParser
481 /// This class takes ownership of all pointers passed in.
483 class BXEXPORT AllRecordParser
: public MultiRecordParser
485 AllRecordStore
*m_store
;
488 // takes ownership of default_parser and store!
489 explicit AllRecordParser(std::ostream
&os
,
490 Parser
*default_parser
= 0,
491 AllRecordStore
*store
= 0);
498 /// Sends incoming DBData objects to all the parsers in its list.
499 /// This parser container does NOT own the parsers added.
501 class BXEXPORT TeeParser
: public Parser
503 typedef std::vector
<Parser
*> parser_list_type
;
505 parser_list_type m_external_parsers
, m_owned_parsers
;
511 /// Adds parser to internal list, and takes ownership of the
515 /// Adds parser to internal list. Does NOT own the parser reference.
518 void ParseRecord(const DBData
&data
, const IConverter
*ic
);