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