# builder.h

Go to the documentation of this file.

    00001 ///
    00002 /// \file       builder.h
    00003 ///             Virtual protocol packet builder 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_BUILDER_H__
    00023 #define __BARRY_BUILDER_H__
    00024
    00025 #include "dll.h"
    00026 #include "data.h"
    00027 #include <stdint.h>
    00028 #include <string>
    00029
    00030 //
    00031 // This macro can be used to automatically generate code for all known
    00032 // record types.  Just #undef HANDLE_BUILDER, then #define it to whatever
    00033 // you need, then use ALL_KNOWN_BUILDER_TYPES.  See parser.cc for
    00034 // various examples.
    00035 //
    00036 // These are sorted so their GetDBName()'s will display in alphabetical order.
    00037 //
    00038 #define ALL_KNOWN_BUILDER_TYPES \
    00039         HANDLE_BUILDER(Contact) \
    00040         HANDLE_BUILDER(Calendar) \
    00041         HANDLE_BUILDER(CalendarAll) \
    00042         HANDLE_BUILDER(ContentStore) \
    00043         HANDLE_BUILDER(Memo) \
    00044         HANDLE_BUILDER(Task) \
    00045
    00046 namespace Barry {
    00047
    00048 // forward declarations
    00049 class IConverter;
    00050
    00051 //
    00052 // Builder class
    00053 //
    00054 /// Base class for the builder functor hierarchy.
    00055 ///
    00056 /// This defines the API used by the Controller and Packet classes
    00057 /// for building a raw device record to write to the device.
    00058 ///
    00059 class BXEXPORT Builder
    00060 {
    00061 public:
    00062         Builder() {}
    00063         virtual ~Builder() {}
    00064
    00065         /// Called to build the record field data.  Store the raw data
    00066         /// in data, using offset to know where to write.  Be sure to
    00067         /// update offset, and be sure to adjust the size of the data
    00068         /// packet (possibly with Data::ReleaseBuffer()).
    00069         ///
    00070         /// Returns true if successful, and false if at the end of
    00071         /// the series.  Note that if EndOfFile() is false after
    00072         /// this function returns false, then there may be another
    00073         /// series available, which the next call to BuildRecord()
    00074         /// will determine.
    00075         ///
    00076         virtual bool BuildRecord(DBData &data, size_t &offset,
    00077                 const IConverter *ic) = 0;
    00078
    00079         /// Same as BuildRecord, but does not care about any offsets.
    00080         /// The caller should call DBData::GetOffset() afterward
    00081         /// to discover if there is an offset to the result.
    00082         ///
    00083         /// This is usually the fastest of the two functions, since
    00084         /// extra copying may be required if a specific offset is
    00085         /// given.  When building records from Record classes, both
    00086         /// functions are the same speed.  But when building records
    00087         /// from the device, the device decides the offset, so FetchRecord()
    00088         /// is faster, since BuildRecord requires a copy to adjust
    00089         /// to the right offset.
    00090         ///
    00091         /// The caller should use the function that results in the least
    00092         /// amount of copying for the caller.  If the caller doesn't
    00093         /// care about where the resulting record is in data, use
    00094         /// FetchRecord().
    00095         ///
    00096         virtual bool FetchRecord(DBData &data, const IConverter *ic) = 0;
    00097
    00098         /// Sometimes a builder can have multiple databases stored
    00099         /// in it, so when Build/Fetch returns false, check if there
    00100         /// is more data with this function.  This function is
    00101         /// not used by database-oriented functions, but by pipe-
    00102         /// oriented functions.
    00103         virtual bool EndOfFile() const = 0;
    00104 };
    00105
    00106
    00107 //
    00108 // DBDataBuilder
    00109 //
    00110 /// Wrapper class around a DBData object, to make it easy to pass a DBData
    00111 /// object into a function or API that requires a builder.  The main
    00112 /// advantage to this is that the Builder API allows for movement of
    00113 /// data, depending on the required offsets.
    00114 ///
    00115 class BXEXPORT DBDataBuilder : public Builder
    00116 {
    00117         const DBData &m_orig;
    00118
    00119 public:
    00120         explicit DBDataBuilder(const DBData &orig);
    00121         virtual ~DBDataBuilder();
    00122
    00123         virtual bool BuildRecord(DBData &data, size_t &offset,
    00124                 const IConverter *ic);
    00125         virtual bool FetchRecord(DBData &data, const IConverter *ic);
    00126         virtual bool EndOfFile() const;
    00127 };
    00128
    00129 //
    00130 // SetDBData
    00131 //
    00132 /// Contains the proper way to convert a record object into a DBData object.
    00133 ///
    00134 template <class RecordT>
    00135 void SetDBData(const RecordT &rec, DBData &data, size_t &offset,
    00136                 const IConverter *ic)
    00137 {
    00138         data.SetVersion(DBData::REC_VERSION_1);
    00139         data.SetOffset(offset);
    00140         data.SetDBName(RecordT::GetDBName());
    00141         data.SetIds(rec.GetRecType(), rec.GetUniqueId());
    00142         rec.BuildHeader(data.UseData(), offset);
    00143         rec.BuildFields(data.UseData(), offset, ic);
    00144 }
    00145
    00146 //
    00147 // RecordBuilder template class
    00148 //
    00149 /// Template class for easy creation of specific protocol packet builder
    00150 /// objects.  This template takes the following template arguments:
    00151 ///
    00152 ///     - RecordT: One of the record classes in record.h
    00153 ///     - StorageT: A custom storage functor class.  An object of this type
    00154 ///             will be called as a function with empty Record as an
    00155 ///             argument.  The storage class is expected to fill the
    00156 ///             record object in preparation for building the packet
    00157 ///             out of that data.  These calls happen on the fly as the data
    00158 ///             is sent to the device over USB, so it should not block forever.
    00159 ///
    00160 /// Example SaveDatabase() call:
    00161 ///
    00162 /// <pre>
    00163 /// FIXME
    00164 /// </pre>
    00165 ///
    00166 template <class RecordT, class StorageT>
    00167 class RecordBuilder : public Builder
    00168 {
    00169         StorageT *m_storage;
    00170         bool m_owned;
    00171         bool m_record_loaded;
    00172         bool m_end_of_file;
    00173         RecordT m_rec;
    00174
    00175 public:
    00176         /// Constructor that references an externally managed storage object.
    00177         RecordBuilder(StorageT &storage)
    00178                 : m_storage(&storage)
    00179                 , m_owned(false)
    00180                 , m_record_loaded(false)
    00181                 , m_end_of_file(false)
    00182         {
    00183         }
    00184
    00185         /// Constructor that references a locally managed storage object.
    00186         /// The pointer passed in will be stored, and freed when this class
    00187         /// is destroyed.  It is safe to call this constructor with
    00188         /// a 'new'ly created storage object.
    00189         RecordBuilder(StorageT *storage)
    00190                 : m_storage(storage)
    00191                 , m_owned(true)
    00192                 , m_record_loaded(false)
    00193                 , m_end_of_file(false)
    00194         {
    00195         }
    00196
    00197         ~RecordBuilder()
    00198         {
    00199                 if( this->m_owned )
    00200                         delete m_storage;
    00201         }
    00202
    00203         virtual bool BuildRecord(DBData &data, size_t &offset,
    00204                                 const IConverter *ic)
    00205         {
    00206                 if( m_end_of_file )
    00207                         return false;
    00208
    00209                 if( !(*m_storage)(m_rec, *this) ) {
    00210                         m_end_of_file = true;
    00211                         return false;
    00212                 }
    00213
    00214                 SetDBData(m_rec, data, offset, ic);
    00215                 return true;
    00216         }
    00217
    00218         virtual bool FetchRecord(DBData &data, const IConverter *ic)
    00219         {
    00220                 size_t offset = 0;
    00221                 return BuildRecord(data, offset, ic);
    00222         }
    00223
    00224         virtual bool EndOfFile() const
    00225         {
    00226                 return m_end_of_file;
    00227         }
    00228 };
    00229
    00230
    00231 //
    00232 // RecordFetch template class
    00233 //
    00234 /// Generic record fetch class, to help with using records without
    00235 /// builder classes.
    00236 ///
    00237 template <class RecordT>
    00238 class RecordFetch
    00239 {
    00240         const RecordT &m_rec;
    00241         mutable bool m_done;
    00242
    00243 public:
    00244         RecordFetch(const RecordT &rec) : m_rec(rec), m_done(false) {}
    00245         bool operator()(RecordT &rec, Builder &) const
    00246         {
    00247                 if( m_done )
    00248                         return false;
    00249                 rec = m_rec;
    00250                 m_done = true;
    00251                 return true;
    00252         }
    00253 };
    00254
    00255
    00256 } // namespace Barry
    00257
    00258 #endif
    00259