00001 /// 00002 /// \file builder.h 00003 /// Virtual protocol packet builder wrapper 00004 /// 00005 00006 /* 00007 Copyright (C) 2005-2009, 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 00027 namespace Barry { 00028 00029 // forward declarations 00030 class IConverter; 00031 00032 // 00033 // Builder class 00034 // 00035 /// Base class for the builder functor hierarchy. 00036 /// 00037 /// This defines the API used by the Controller and Packet classes 00038 /// for building a raw device record to write to the device. 00039 /// 00040 class BXEXPORT Builder 00041 { 00042 public: 00043 Builder() {} 00044 virtual ~Builder() {} 00045 00046 /// Called first in the sequence, to allow the application to 00047 /// load the needed data from memory, disk, etc. If successful, 00048 /// return true. If at the end of the series, return false. 00049 virtual bool Retrieve(unsigned int databaseId) = 0; 00050 00051 /// Called to retrive the unique ID for this record. 00052 virtual uint8_t GetRecType() const = 0; 00053 virtual uint32_t GetUniqueId() const = 0; 00054 00055 /// Called before BuildFields() in order to build the header 00056 /// for this record. Store the raw data in data, at the 00057 /// offset given in offset. When finished, update offset to 00058 /// point to the next spot to put new data. 00059 virtual void BuildHeader(Data &data, size_t &offset) = 0; 00060 00061 /// Called to build the record field data. Store the raw data 00062 /// in data, using offset to know where to write. Be sure to 00063 /// update offset, and be sure to adjust the size of the data 00064 /// packet (possibly with Data::ReleaseBuffer()). 00065 virtual void BuildFields(Data &data, size_t &offset, 00066 const IConverter *ic) = 0; 00067 }; 00068 00069 00070 // 00071 // RecordBuilder template class 00072 // 00073 /// Template class for easy creation of specific protocol packet builder 00074 /// objects. This template takes the following template arguments: 00075 /// 00076 /// - RecordT: One of the record classes in record.h 00077 /// - StorageT: A custom storage functor class. An object of this type 00078 /// will be called as a function with empty Record as an 00079 /// argument. The storage class is expected to fill the 00080 /// record object in preparation for building the packet 00081 /// out of that data. These calls happen on the fly as the data 00082 /// is sent to the device over USB, so it should not block forever. 00083 /// 00084 /// Example SaveDatabase() call: 00085 /// 00086 /// <pre> 00087 /// FIXME 00088 /// </pre> 00089 /// 00090 template <class RecordT, class StorageT> 00091 class RecordBuilder : public Builder 00092 { 00093 StorageT *m_storage; 00094 bool m_owned; 00095 RecordT m_rec; 00096 00097 public: 00098 /// Constructor that references an externally managed storage object. 00099 RecordBuilder(StorageT &storage) 00100 : m_storage(&storage), m_owned(false) {} 00101 00102 /// Constructor that references a locally managed storage object. 00103 /// The pointer passed in will be stored, and freed when this class 00104 /// is destroyed. It is safe to call this constructor with 00105 /// a 'new'ly created storage object. 00106 RecordBuilder(StorageT *storage) 00107 : m_storage(storage), m_owned(true) {} 00108 00109 ~RecordBuilder() 00110 { 00111 if( this->m_owned ) 00112 delete m_storage; 00113 } 00114 00115 virtual bool Retrieve(unsigned int databaseId) 00116 { 00117 return (*m_storage)(m_rec, databaseId); 00118 } 00119 00120 virtual uint8_t GetRecType() const 00121 { 00122 return m_rec.GetRecType(); 00123 } 00124 00125 virtual uint32_t GetUniqueId() const 00126 { 00127 return m_rec.GetUniqueId(); 00128 } 00129 00130 /// Functor member called by Controller::SaveDatabase() during 00131 /// processing. 00132 virtual void BuildHeader(Data &data, size_t &offset) 00133 { 00134 m_rec.BuildHeader(data, offset); 00135 } 00136 00137 virtual void BuildFields(Data &data, size_t &offset, const IConverter *ic) 00138 { 00139 m_rec.BuildFields(data, offset, ic); 00140 } 00141 }; 00142 00143 00144 // 00145 // RecordFetch template class 00146 // 00147 /// Generic record fetch class, to help with using records without 00148 /// builder classes. 00149 /// 00150 template <class RecordT> 00151 class RecordFetch 00152 { 00153 const RecordT &m_rec; 00154 mutable bool m_done; 00155 00156 public: 00157 RecordFetch(const RecordT &rec) : m_rec(rec), m_done(false) {} 00158 bool operator()(RecordT &rec, unsigned int dbId) const 00159 { 00160 if( m_done ) 00161 return false; 00162 rec = m_rec; 00163 m_done = true; 00164 return true; 00165 } 00166 }; 00167 00168 00169 } // namespace Barry 00170 00171 #endif 00172