# parser.h

Go to the documentation of this file.

    00001 ///
    00002 /// \file       parser.h
    00003 ///             Virtual parser wrapper
    00004 ///
    00005
    00006 /*
    00007     Copyright (C) 2005-2011, Net Direct Inc. (http://www.netdirect.ca/)
    00008
    00009     This program is free software; you can redistribute it and/or modify
    00010     it under the terms of the GNU General Public License as published by
    00011     the Free Software Foundation; either version 2 of the License, or
    00012     (at your option) any later version.
    00013
    00014     This program is distributed in the hope that it will be useful,
    00015     but WITHOUT ANY WARRANTY; without even the implied warranty of
    00016     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
    00017
    00018     See the GNU General Public License in the COPYING file at the
    00019     root directory of this project for more details.
    00020 */
    00021
    00022 #ifndef __BARRY_PARSER_H__
    00023 #define __BARRY_PARSER_H__
    00024
    00025 #include "dll.h"
    00026 #include "data.h"
    00027 #include "protocol.h"
    00028 #include <stdint.h>             // for uint32_t
    00029 #include <iosfwd>
    00030 #include <map>
    00031
    00032 // forward declarations
    00033 namespace Barry {
    00034         class IConverter;
    00035         class Contact;
    00036         class Message;
    00037         class Calendar;
    00038         class CalendarAll;
    00039         class CallLog;
    00040         class Bookmark;
    00041         class ServiceBook;
    00042         class Memo;
    00043         class Task;
    00044         class PINMessage;
    00045         class SavedMessage;
    00046         class Sms;
    00047         class Folder;
    00048         class Timezone;
    00049         class ContentStore;
    00050 }
    00051
    00052 //
    00053 // This macro can be used to automatically generate code for all known
    00054 // record types.  Just #undef HANDLE_PARSER, then #define it to whatever
    00055 // you need, then use ALL_KNOWN_PARSER_TYPES.  See parser.cc for
    00056 // various examples.
    00057 //
    00058 // These are sorted so their GetDBName()'s will display in alphabetical order.
    00059 //
    00060 #define ALL_KNOWN_PARSER_TYPES \
    00061         HANDLE_PARSER(Contact) \
    00062         HANDLE_PARSER(Bookmark) \
    00063         HANDLE_PARSER(Calendar) \
    00064         HANDLE_PARSER(CalendarAll) \
    00065         HANDLE_PARSER(ContentStore) \
    00066         HANDLE_PARSER(Folder) \
    00067         HANDLE_PARSER(Memo) \
    00068         HANDLE_PARSER(Message) \
    00069         HANDLE_PARSER(CallLog) \
    00070         HANDLE_PARSER(PINMessage) \
    00071         HANDLE_PARSER(SavedMessage) \
    00072         HANDLE_PARSER(ServiceBook) \
    00073         HANDLE_PARSER(Sms) \
    00074         HANDLE_PARSER(Task) \
    00075         HANDLE_PARSER(Timezone)
    00076
    00077 namespace Barry {
    00078
    00079 //
    00080 // Parser class
    00081 //
    00082 /// Base class for the parser hierarchy.
    00083 ///
    00084 /// This class provides the interface that the Controller class uses
    00085 /// to pass raw data it reads from the device.  The Controller, along
    00086 /// with the Packet class, calls each of the virtual functions below
    00087 /// in the same order.
    00088 ///
    00089 /// This class is kept as a pure abstract class, in order to make sure
    00090 /// that the compiler will catch any API changes, for code derived
    00091 /// from it.
    00092 ///
    00093 class BXEXPORT Parser
    00094 {
    00095 public:
    00096         Parser() {}
    00097         virtual ~Parser() {}
    00098
    00099         /// Called to parse sub fields in the raw data packet.
    00100         virtual void ParseRecord(const DBData &data, const IConverter *ic) = 0;
    00101 };
    00102
    00103
    00104 //
    00105 // NullParser class
    00106 //
    00107 /// If in debug mode, this class can be used as a null parser.
    00108 /// Call Init() and the protocol will be dumped to stdout and
    00109 /// no parsing will be done.
    00110 ///
    00111 /// Do NOT derive your own personal parser classes from this,
    00112 /// unless you are perfectly confident that you will catch
    00113 /// future API changes on the devel tree without the compiler's
    00114 /// help.
    00115 ///
    00116 class BXEXPORT NullParser : public Parser
    00117 {
    00118 public:
    00119         NullParser() {}
    00120         virtual ~NullParser() {}
    00121
    00122         virtual void ParseRecord(const DBData &data, const IConverter *ic) {}
    00123 };
    00124
    00125 //
    00126 // HexDumpParser
    00127 //
    00128 /// Dumps raw hex of the given DBData to the given stream.
    00129 ///
    00130 /// Do NOT derive your own personal parser classes from this,
    00131 /// unless you are perfectly confident that you will catch
    00132 /// future API changes on the devel tree without the compiler's
    00133 /// help.
    00134 ///
    00135 class BXEXPORT HexDumpParser : public Parser
    00136 {
    00137         std::ostream &m_os;
    00138         std::string m_last_dbname;
    00139
    00140 public:
    00141         explicit HexDumpParser(std::ostream &os);
    00142
    00143         virtual void ParseRecord(const Barry::DBData &data,
    00144                                  const IConverter *ic);
    00145 };
    00146
    00147 //
    00148 // RecordParserBase
    00149 //
    00150 /// Abstract base class for the following RecordParser template, that exposes
    00151 /// some information on the specifics that the record parser can handle.
    00152 /// Specifically, it exposes the database name it is able to parse
    00153 ///
    00154 class BXEXPORT RecordParserBase : public Parser
    00155 {
    00156 public:
    00157         // These functions are always valid, regardless of the
    00158         // state of the parser.
    00159         virtual const char * GetDBName() const = 0;
    00160         virtual uint8_t GetDefaultRecType() const = 0;
    00161
    00162         // These functions depend on the parser having just parsed
    00163         // a record successfully.
    00164         virtual bool IsRecordValid() const = 0;
    00165         virtual uint8_t GetRecType() const = 0;
    00166         virtual uint32_t GetUniqueId() const = 0;
    00167         virtual void Dump(std::ostream &os) const = 0;
    00168 };
    00169
    00170
    00171 //
    00172 // Note: Store classes take parsed Record objects as a functor.
    00173 //       Parser classes deal with raw data, while Store classes deal with
    00174 //       parsed Record objects.
    00175 //
    00176
    00177 //
    00178 // NullStore
    00179 //
    00180 /// A Storage class for RecordParser<> that does nothing, for the cases
    00181 /// where you only want to dump parsed record data to a stream.
    00182 ///
    00183 template <class RecordT>
    00184 class NullStore
    00185 {
    00186 public:
    00187         void operator() (const RecordT &r)
    00188         {
    00189         }
    00190 };
    00191
    00192 //
    00193 // DumpStore
    00194 //
    00195 /// A Storage class for RecordParser<> that dumps the parsed record data
    00196 /// to the given stream.
    00197 ///
    00198 template <class RecordT>
    00199 class DumpStore
    00200 {
    00201         std::ostream &m_os;
    00202
    00203 public:
    00204         explicit DumpStore(std::ostream &os)
    00205                 : m_os(os)
    00206         {
    00207         }
    00208
    00209         void operator() (const RecordT &r)
    00210         {
    00211                 r.Dump(m_os);
    00212         }
    00213 };
    00214
    00215 //
    00216 // ParseDBData
    00217 //
    00218 /// Contains the proper way to convert a DBData object into a record.
    00219 ///
    00220 template <class RecordT>
    00221 void ParseDBData(const DBData &data, RecordT &rec, const IConverter *ic)
    00222 {
    00223         // start fresh
    00224         rec = RecordT();
    00225
    00226         // parse
    00227         rec.SetIds(data.GetRecType(), data.GetUniqueId());
    00228         size_t offset = data.GetOffset();
    00229         rec.ParseHeader(data.GetData(), offset);
    00230         rec.ParseFields(data.GetData(), offset, ic);
    00231 }
    00232
    00233 //
    00234 // RecordParser template class
    00235 //
    00236 /// Template class for easy creation of specific parser objects.  This template
    00237 /// takes the following template arguments:
    00238 ///
    00239 ///     - RecordT: One of the record parser classes in record.h
    00240 ///     - StorageT: A custom storage functor class.  An object of this type
    00241 ///             will be called as a function with parsed Record as an
    00242 ///             argument.  This happens on the fly as the data is retrieved
    00243 ///             from the device over USB, so it should not block forever.
    00244 ///
    00245 /// Example LoadDatabase() call:
    00246 ///
    00247 /// <pre>
    00248 /// struct StoreContact
    00249 /// {
    00250 ///     std::vector<Contact> &amp;array;
    00251 ///     StoreContact(std::vector<Contact> &amp;a) : array(a) {}
    00252 ///     void operator() (const Contact &amp;c)
    00253 ///     {
    00254 ///         array.push_back(c);
    00255 ///     }
    00256 /// };
    00257 ///
    00258 /// Controller con(probeResult);
    00259 /// con.OpenMode(Controller::Desktop);
    00260 /// std::vector<Contact> contactList;
    00261 /// StoreContact storage(contactList);
    00262 /// RecordParser<Contact, StoreContact> parser(storage);
    00263 /// con.LoadDatabase(con.GetDBID("Address Book"), parser);
    00264 /// </pre>
    00265 ///
    00266 template <class RecordT, class StorageT>
    00267 class RecordParser : public RecordParserBase
    00268 {
    00269         StorageT *m_store;
    00270         bool m_owned;
    00271         RecordT m_rec;
    00272         bool m_record_valid;
    00273
    00274 public:
    00275         /// Constructor that references an externally managed storage object.
    00276         RecordParser(StorageT &storage)
    00277                 : m_store(&storage)
    00278                 , m_owned(false)
    00279                 , m_record_valid(false)
    00280         {
    00281         }
    00282
    00283         /// Constructor that references a locally managed storage object.
    00284         /// The pointer passed in will be stored, and freed when this class
    00285         /// is destroyed.  It is safe to call this constructor with
    00286         /// a 'new'ly created storage object.
    00287         RecordParser(StorageT *storage = 0)
    00288                 : m_store(storage)
    00289                 , m_owned(true)
    00290                 , m_record_valid(false)
    00291         {
    00292         }
    00293
    00294         ~RecordParser()
    00295         {
    00296                 if( this->m_owned )
    00297                         delete m_store;
    00298         }
    00299
    00300         virtual StorageT* GetStore()
    00301         {
    00302                 return m_store;
    00303         }
    00304
    00305         virtual const StorageT* GetStore() const
    00306         {
    00307                 return m_store;
    00308         }
    00309
    00310         virtual void ParseRecord(const DBData &data, const IConverter *ic)
    00311         {
    00312                 m_record_valid = false;
    00313                 ParseDBData(data, m_rec, ic);
    00314                 m_record_valid = true;
    00315
    00316                 if( m_store )
    00317                         (*m_store)(m_rec);
    00318         }
    00319
    00320         //
    00321         // RecordParserBase overrides
    00322         //
    00323
    00324         // These functions are always valid, regardless of the
    00325         // state of the parser.
    00326         virtual const char * GetDBName() const
    00327         {
    00328                 return RecordT::GetDBName();
    00329         }
    00330
    00331         virtual uint8_t GetDefaultRecType() const
    00332         {
    00333                 return RecordT::GetDefaultRecType();
    00334         }
    00335
    00336         // These functions depend on the parser having just parsed
    00337         // a record successfully.
    00338         virtual bool IsRecordValid() const
    00339         {
    00340                 return m_record_valid;
    00341         }
    00342
    00343         virtual uint8_t GetRecType() const
    00344         {
    00345                 return m_rec.GetRecType();
    00346         }
    00347
    00348         virtual uint32_t GetUniqueId() const
    00349         {
    00350                 return m_rec.GetUniqueId();
    00351         }
    00352
    00353         virtual void Dump(std::ostream &os) const
    00354         {
    00355                 m_rec.Dump(os);
    00356         }
    00357 };
    00358
    00359 //
    00360 // AllRecordStore
    00361 //
    00362 /// Base class with overloaded functor behaviour for all available
    00363 /// record classes.  To be used with AllRecordParser.
    00364 ///
    00365 class BXEXPORT AllRecordStore
    00366 {
    00367 public:
    00368         AllRecordStore() {}
    00369         virtual ~AllRecordStore() {}
    00370
    00371 #undef HANDLE_PARSER
    00372 #define HANDLE_PARSER(tname) \
    00373         virtual void operator() (const Barry::tname &) = 0;
    00374
    00375         ALL_KNOWN_PARSER_TYPES
    00376 };
    00377
    00378 //
    00379 // MultiRecordParser
    00380 //
    00381 /// Container parser class that accepts multiple Parser objects
    00382 /// (often RecordParser<> objects but they don't have to be) and
    00383 /// automatically routes incoming records to the appropriate parser.
    00384 /// Note that this container owns *all* Parser objects, and will
    00385 /// free them upon destruction.
    00386 ///
    00387 /// Incoming records that have no matching parser are passed to the
    00388 /// default parser object, if one exists, otherwise they are dropped
    00389 /// silently.  The default parser object is also owned by the container,
    00390 /// and will be freed on destruction.
    00391 ///
    00392 /// Do NOT derive your own personal parser classes from this,
    00393 /// unless you are perfectly confident that you will catch
    00394 /// future API changes on the devel tree without the compiler's
    00395 /// help.
    00396 ///
    00397 class BXEXPORT MultiRecordParser : public Parser
    00398 {
    00399         typedef std::map<std::string, Parser*>                  map_type;
    00400
    00401         Parser *m_delete_default;       // if set, will be freed
    00402         Parser *m_default;              // used by all code for actual work
    00403                                         // and may or may not be "owned" by us
    00404         map_type m_parsers;
    00405
    00406 public:
    00407         // takes ownership of default_parser!
    00408         explicit MultiRecordParser(Parser *default_parser = 0);
    00409
    00410         // does not take ownership of the default_parser
    00411         explicit MultiRecordParser(Parser &default_parser);
    00412
    00413         ~MultiRecordParser();
    00414
    00415         /// Adds given parser to list and takes ownership of it
    00416         void Add(const std::string &dbname, Parser *parser);
    00417
    00418         /// Adds given parser to list and takes ownership of it
    00419         void Add(RecordParserBase *parser);
    00420
    00421         /// Creates a RecordParser<> object using the given record
    00422         /// type and AllRecordStore.  Does NOT take ownership of the
    00423         /// store object, since it can be used multiple times for
    00424         /// multiple records.
    00425         template <class RecordT>
    00426         void Add(AllRecordStore &store)
    00427         {
    00428                 Add( RecordT::GetDBName(),
    00429                         new RecordParser<RecordT, AllRecordStore>(store) );
    00430         }
    00431
    00432         /// Two helper template functions that create the RecordParser<>
    00433         /// automatically based on the function call.  Both pointer and
    00434         /// reference versions.
    00435         template <class RecordT, class StorageT>
    00436         void Add(StorageT *store)
    00437         {
    00438                 Add( RecordT::GetDBName(),
    00439                         new RecordParser<RecordT, StorageT>(store) );
    00440         }
    00441
    00442         template <class RecordT, class StorageT>
    00443         void Add(StorageT &store)
    00444         {
    00445                 Add( RecordT::GetDBName(),
    00446                         new RecordParser<RecordT, StorageT>(store) );
    00447         }
    00448
    00449         /// Creates a RecordParser<> object for the given database name,
    00450         /// using DumpStore<> with the given stream for the output,
    00451         /// and adds it to list.
    00452         /// Returns false if there is no known Record class for dbname.
    00453         bool Add(const std::string &dbname, std::ostream &os);
    00454
    00455         /// Creates a RecordParser<> object for the given database name,
    00456         /// using the given store object.
    00457         /// Returns false if there is no known Record class for dbname.
    00458         bool Add(const std::string &dbname, AllRecordStore &store);
    00459
    00460         // Parser overrides
    00461         virtual void ParseRecord(const DBData &data, const IConverter *ic);
    00462 };
    00463
    00464 //
    00465 // AllRecordDumpStore
    00466 //
    00467 /// Derived from AllRecordStore, which just calls each record's
    00468 /// Dump() member with the given stream.
    00469 ///
    00470 class BXEXPORT AllRecordDumpStore : public AllRecordStore
    00471 {
    00472 protected:
    00473         std::ostream &m_os;
    00474
    00475 public:
    00476         explicit AllRecordDumpStore(std::ostream &os)
    00477                 : m_os(os)
    00478         {
    00479         }
    00480
    00481 #undef HANDLE_PARSER
    00482 #define HANDLE_PARSER(tname) \
    00483         virtual void operator() (const Barry::tname &);
    00484
    00485         ALL_KNOWN_PARSER_TYPES
    00486 };
    00487
    00488 //
    00489 // AllRecordParser
    00490 //
    00491 /// Convenience parser that creates a MultiRecordParser with all known
    00492 /// record parsers added.  If an AllRecordStore pointer is passed in,
    00493 /// this class takes ownership of it, and uses it as the store object
    00494 /// for all the RecordParser<> objects it creates.  If not, then
    00495 /// a custom DumpStore<> object is created with the given stream
    00496 /// for each RecordParser<> added.
    00497 ///
    00498 /// The default parser object behaves just like MultiRecordParser
    00499 ///
    00500 /// This class takes ownership of all pointers passed in.
    00501 ///
    00502 class BXEXPORT AllRecordParser : public MultiRecordParser
    00503 {
    00504         AllRecordStore *m_store;
    00505
    00506 protected:
    00507         // does not take ownership of store, by itself,
    00508         // but the constructor that calls it might
    00509         void AddRecords(std::ostream *os, AllRecordStore *store);
    00510
    00511 public:
    00512         // takes ownership of default_parser and store!
    00513         explicit AllRecordParser(std::ostream &os,
    00514                 Parser *default_parser = 0,
    00515                 AllRecordStore *store = 0);
    00516
    00517         // does not take ownership of default_parser or store
    00518         AllRecordParser(Parser &default_parser, AllRecordStore &store);
    00519
    00520         ~AllRecordParser();
    00521 };
    00522
    00523 //
    00524 // TeeParser
    00525 //
    00526 /// Sends incoming DBData objects to all the parsers in its list.
    00527 /// This parser container does NOT own the parsers added.
    00528 ///
    00529 class BXEXPORT TeeParser : public Parser
    00530 {
    00531         typedef std::vector<Parser*>                    parser_list_type;
    00532
    00533         parser_list_type m_external_parsers, m_owned_parsers;
    00534
    00535 public:
    00536         TeeParser();
    00537         ~TeeParser();
    00538
    00539         /// Adds parser to internal list, and takes ownership of the
    00540         /// pointer.
    00541         void Add(Parser *p);
    00542
    00543         /// Adds parser to internal list.  Does NOT own the parser reference.
    00544         void Add(Parser &p);
    00545
    00546         void ParseRecord(const DBData &data, const IConverter *ic);
    00547 };
    00548
    00549 } // namespace Barry
    00550
    00551 #endif
    00552