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