tools: MimeDump<> can have all static members
[barry.git] / src / builder.h
blob0fafe705e689160388a85dc05c0f896e7976dac4
1 ///
2 /// \file builder.h
3 /// Virtual protocol packet builder wrapper
4 ///
6 /*
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__
25 #include "dll.h"
26 #include "data.h"
27 #include <stdint.h>
28 #include <string>
31 // This macro can be used to automatically generate code for all known
32 // record types. Just #undef HANDLE_BUILDER, then #define it to whatever
33 // you need, then use ALL_KNOWN_BUILDER_TYPES. See parser.cc for
34 // various examples.
36 // These are sorted so their GetDBName()'s will display in alphabetical order.
38 #define ALL_KNOWN_BUILDER_TYPES \
39 HANDLE_BUILDER(Contact) \
40 HANDLE_BUILDER(Calendar) \
41 HANDLE_BUILDER(CalendarAll) \
42 HANDLE_BUILDER(Memo) \
43 HANDLE_BUILDER(Task) \
45 namespace Barry {
47 // forward declarations
48 class IConverter;
51 // Builder class
53 /// Base class for the builder functor hierarchy.
54 ///
55 /// This defines the API used by the Controller and Packet classes
56 /// for building a raw device record to write to the device.
57 ///
58 class BXEXPORT Builder
60 public:
61 Builder() {}
62 virtual ~Builder() {}
64 /// Called to build the record field data. Store the raw data
65 /// in data, using offset to know where to write. Be sure to
66 /// update offset, and be sure to adjust the size of the data
67 /// packet (possibly with Data::ReleaseBuffer()).
68 ///
69 /// Returns true if successful, and false if at the end of
70 /// the series. Note that if EndOfFile() is false after
71 /// this function returns false, then there may be another
72 /// series available, which the next call to BuildRecord()
73 /// will determine.
74 ///
75 virtual bool BuildRecord(DBData &data, size_t &offset,
76 const IConverter *ic) = 0;
78 /// Same as BuildRecord, but does not care about any offsets.
79 /// The caller should call DBData::GetOffset() afterward
80 /// to discover if there is an offset to the result.
81 ///
82 /// This is usually the fastest of the two functions, since
83 /// extra copying may be required if a specific offset is
84 /// given. When building records from Record classes, both
85 /// functions are the same speed. But when building records
86 /// from the device, the device decides the offset, so FetchRecord()
87 /// is faster, since BuildRecord requires a copy to adjust
88 /// to the right offset.
89 ///
90 /// The caller should use the function that results in the least
91 /// amount of copying for the caller. If the caller doesn't
92 /// care about where the resulting record is in data, use
93 /// FetchRecord().
94 ///
95 virtual bool FetchRecord(DBData &data, const IConverter *ic) = 0;
97 /// Sometimes a builder can have multiple databases stored
98 /// in it, so when Build/Fetch returns false, check if there
99 /// is more data with this function. This function is
100 /// not used by database-oriented functions, but by pipe-
101 /// oriented functions.
102 virtual bool EndOfFile() const = 0;
107 // DBDataBuilder
109 /// Wrapper class around a DBData object, to make it easy to pass a DBData
110 /// object into a function or API that requires a builder. The main
111 /// advantage to this is that the Builder API allows for movement of
112 /// data, depending on the required offsets.
114 class BXEXPORT DBDataBuilder : public Builder
116 const DBData &m_orig;
118 public:
119 explicit DBDataBuilder(const DBData &orig);
120 virtual ~DBDataBuilder();
122 virtual bool BuildRecord(DBData &data, size_t &offset,
123 const IConverter *ic);
124 virtual bool FetchRecord(DBData &data, const IConverter *ic);
125 virtual bool EndOfFile() const;
130 // RecordBuilder template class
132 /// Template class for easy creation of specific protocol packet builder
133 /// objects. This template takes the following template arguments:
135 /// - RecordT: One of the record classes in record.h
136 /// - StorageT: A custom storage functor class. An object of this type
137 /// will be called as a function with empty Record as an
138 /// argument. The storage class is expected to fill the
139 /// record object in preparation for building the packet
140 /// out of that data. These calls happen on the fly as the data
141 /// is sent to the device over USB, so it should not block forever.
143 /// Example SaveDatabase() call:
145 /// <pre>
146 /// FIXME
147 /// </pre>
149 template <class RecordT, class StorageT>
150 class RecordBuilder : public Builder
152 StorageT *m_storage;
153 bool m_owned;
154 bool m_record_loaded;
155 bool m_end_of_file;
156 RecordT m_rec;
158 public:
159 /// Constructor that references an externally managed storage object.
160 RecordBuilder(StorageT &storage)
161 : m_storage(&storage)
162 , m_owned(false)
163 , m_record_loaded(false)
164 , m_end_of_file(false)
168 /// Constructor that references a locally managed storage object.
169 /// The pointer passed in will be stored, and freed when this class
170 /// is destroyed. It is safe to call this constructor with
171 /// a 'new'ly created storage object.
172 RecordBuilder(StorageT *storage)
173 : m_storage(storage)
174 , m_owned(true)
175 , m_record_loaded(false)
176 , m_end_of_file(false)
180 ~RecordBuilder()
182 if( this->m_owned )
183 delete m_storage;
186 virtual bool BuildRecord(DBData &data, size_t &offset,
187 const IConverter *ic)
189 if( m_end_of_file )
190 return false;
192 if( !(*m_storage)(m_rec, *this) ) {
193 m_end_of_file = true;
194 return false;
197 data.SetVersion(DBData::REC_VERSION_1);
198 data.SetDBName(RecordT::GetDBName());
199 data.SetIds(m_rec.GetRecType(), m_rec.GetUniqueId());
200 data.SetOffset(offset);
201 m_rec.BuildHeader(data.UseData(), offset);
202 m_rec.BuildFields(data.UseData(), offset, ic);
203 return true;
206 virtual bool FetchRecord(DBData &data, const IConverter *ic)
208 size_t offset = 0;
209 return BuildRecord(data, offset, ic);
212 virtual bool EndOfFile() const
214 return m_end_of_file;
220 // RecordFetch template class
222 /// Generic record fetch class, to help with using records without
223 /// builder classes.
225 template <class RecordT>
226 class RecordFetch
228 const RecordT &m_rec;
229 mutable bool m_done;
231 public:
232 RecordFetch(const RecordT &rec) : m_rec(rec), m_done(false) {}
233 bool operator()(RecordT &rec, Builder &) const
235 if( m_done )
236 return false;
237 rec = m_rec;
238 m_done = true;
239 return true;
244 } // namespace Barry
246 #endif