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 

Generated on Tue Mar 1 17:50:15 2011 for Barry by  doxygen 1.5.6