3 /// Virtual protocol packet builder wrapper
7 Copyright (C) 2005-2010, Net Direct Inc. (http://www.netdirect.ca/)
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
18 See the GNU General Public License in the COPYING file at the
19 root directory of this project for more details.
22 #ifndef __BARRY_BUILDER_H__
23 #define __BARRY_BUILDER_H__
32 // forward declarations
38 /// Base class for the builder functor hierarchy.
40 /// This defines the API used by the Controller and Packet classes
41 /// for building a raw device record to write to the device.
43 class BXEXPORT Builder
49 /// Called first in the sequence, to allow the application to
50 /// load the needed data from memory, disk, etc. If successful,
51 /// return true. If at the end of the series, return false.
52 /// Note that this function, if it returns true, may be called
53 /// more than once, and it is the builder's responsibility
54 /// to not retrieve the next item until BuildDone() is called.
55 /// If Retrieve() returns false to mark the end-of-series,
56 /// it does not have to return false next time, since a new
57 /// series may begin. It is the caller's responsibility to
59 virtual bool Retrieve() = 0;
61 /// Sometimes a builder can have multiple databases stored
62 /// in it, so when Retrieve() returns false, check if there
63 /// is more data with this function. This function is
64 /// not used by database-oriented functions, but by pipe-
65 /// oriented functions.
66 virtual bool EndOfFile() const = 0;
68 /// Called to build the record field data. Store the raw data
69 /// in data, using offset to know where to write. Be sure to
70 /// update offset, and be sure to adjust the size of the data
71 /// packet (possibly with Data::ReleaseBuffer()).
72 virtual void BuildRecord(DBData
&data
, size_t &offset
,
73 const IConverter
*ic
) = 0;
75 /// Called last to signify to the application that the library
76 /// is finished with this record. The next Retrieve() call
77 /// can load the next item after this call.
78 virtual void BuildDone() = 0;
83 // RecordBuilder template class
85 /// Template class for easy creation of specific protocol packet builder
86 /// objects. This template takes the following template arguments:
88 /// - RecordT: One of the record classes in record.h
89 /// - StorageT: A custom storage functor class. An object of this type
90 /// will be called as a function with empty Record as an
91 /// argument. The storage class is expected to fill the
92 /// record object in preparation for building the packet
93 /// out of that data. These calls happen on the fly as the data
94 /// is sent to the device over USB, so it should not block forever.
96 /// Example SaveDatabase() call:
102 template <class RecordT
, class StorageT
>
103 class RecordBuilder
: public Builder
107 bool m_record_loaded
;
112 /// Constructor that references an externally managed storage object.
113 RecordBuilder(StorageT
&storage
)
114 : m_storage(&storage
)
116 , m_record_loaded(false)
117 , m_end_of_file(false)
121 /// Constructor that references a locally managed storage object.
122 /// The pointer passed in will be stored, and freed when this class
123 /// is destroyed. It is safe to call this constructor with
124 /// a 'new'ly created storage object.
125 RecordBuilder(StorageT
*storage
)
128 , m_record_loaded(false)
129 , m_end_of_file(false)
139 virtual bool Retrieve()
143 if( m_record_loaded
)
146 m_record_loaded
= (*m_storage
)(m_rec
, *this);
147 if( !m_record_loaded
)
148 m_end_of_file
= true;
149 return m_record_loaded
;
152 virtual bool EndOfFile() const
154 return m_end_of_file
;
157 virtual void BuildRecord(DBData
&data
, size_t &offset
,
158 const IConverter
*ic
)
160 data
.SetVersion(DBData::REC_VERSION_1
);
161 data
.SetDBName(RecordT::GetDBName());
162 data
.SetIds(m_rec
.GetRecType(), m_rec
.GetUniqueId());
163 data
.SetOffset(offset
);
164 m_rec
.BuildHeader(data
.UseData(), offset
);
165 m_rec
.BuildFields(data
.UseData(), offset
, ic
);
168 virtual void BuildDone()
170 m_record_loaded
= false;
176 // RecordFetch template class
178 /// Generic record fetch class, to help with using records without
181 template <class RecordT
>
184 const RecordT
&m_rec
;
188 RecordFetch(const RecordT
&rec
) : m_rec(rec
), m_done(false) {}
189 bool operator()(RecordT
&rec
, Builder
&) const