lib: reworked the bookmark parser
[barry.git] / src / builder.h
blob9509a68d36eddf53aba41ad059c860fdbc5f6c37
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>
30 namespace Barry {
32 // forward declarations
33 class IConverter;
36 // Builder class
38 /// Base class for the builder functor hierarchy.
39 ///
40 /// This defines the API used by the Controller and Packet classes
41 /// for building a raw device record to write to the device.
42 ///
43 class BXEXPORT Builder
45 public:
46 Builder() {}
47 virtual ~Builder() {}
49 /// Called to build the record field data. Store the raw data
50 /// in data, using offset to know where to write. Be sure to
51 /// update offset, and be sure to adjust the size of the data
52 /// packet (possibly with Data::ReleaseBuffer()).
53 ///
54 /// Returns true if successful, and false if at the end of
55 /// the series. Note that if EndOfFile() is false after
56 /// this function returns false, then there may be another
57 /// series available, which the next call to BuildRecord()
58 /// will determine.
59 ///
60 virtual bool BuildRecord(DBData &data, size_t &offset,
61 const IConverter *ic) = 0;
63 /// Same as BuildRecord, but does not care about any offsets.
64 /// The caller should call DBData::GetOffset() afterward
65 /// to discover if there is an offset to the result.
66 ///
67 /// This is usually the fastest of the two functions, since
68 /// extra copying may be required if a specific offset is
69 /// given. When building records from Record classes, both
70 /// functions are the same speed. But when building records
71 /// from the device, the device decides the offset, so FetchRecord()
72 /// is faster, since BuildRecord requires a copy to adjust
73 /// to the right offset.
74 ///
75 /// The caller should use the function that results in the least
76 /// amount of copying for the caller. If the caller doesn't
77 /// care about where the resulting record is in data, use
78 /// FetchRecord().
79 ///
80 virtual bool FetchRecord(DBData &data, const IConverter *ic) = 0;
82 /// Sometimes a builder can have multiple databases stored
83 /// in it, so when Retrieve() returns false, check if there
84 /// is more data with this function. This function is
85 /// not used by database-oriented functions, but by pipe-
86 /// oriented functions.
87 virtual bool EndOfFile() const = 0;
92 // RecordBuilder template class
94 /// Template class for easy creation of specific protocol packet builder
95 /// objects. This template takes the following template arguments:
96 ///
97 /// - RecordT: One of the record classes in record.h
98 /// - StorageT: A custom storage functor class. An object of this type
99 /// will be called as a function with empty Record as an
100 /// argument. The storage class is expected to fill the
101 /// record object in preparation for building the packet
102 /// out of that data. These calls happen on the fly as the data
103 /// is sent to the device over USB, so it should not block forever.
105 /// Example SaveDatabase() call:
107 /// <pre>
108 /// FIXME
109 /// </pre>
111 template <class RecordT, class StorageT>
112 class RecordBuilder : public Builder
114 StorageT *m_storage;
115 bool m_owned;
116 bool m_record_loaded;
117 bool m_end_of_file;
118 RecordT m_rec;
120 public:
121 /// Constructor that references an externally managed storage object.
122 RecordBuilder(StorageT &storage)
123 : m_storage(&storage)
124 , m_owned(false)
125 , m_record_loaded(false)
126 , m_end_of_file(false)
130 /// Constructor that references a locally managed storage object.
131 /// The pointer passed in will be stored, and freed when this class
132 /// is destroyed. It is safe to call this constructor with
133 /// a 'new'ly created storage object.
134 RecordBuilder(StorageT *storage)
135 : m_storage(storage)
136 , m_owned(true)
137 , m_record_loaded(false)
138 , m_end_of_file(false)
142 ~RecordBuilder()
144 if( this->m_owned )
145 delete m_storage;
148 virtual bool BuildRecord(DBData &data, size_t &offset,
149 const IConverter *ic)
151 if( m_end_of_file )
152 return false;
154 if( !(*m_storage)(m_rec, *this) ) {
155 m_end_of_file = true;
156 return false;
159 data.SetVersion(DBData::REC_VERSION_1);
160 data.SetDBName(RecordT::GetDBName());
161 data.SetIds(m_rec.GetRecType(), m_rec.GetUniqueId());
162 data.SetOffset(offset);
163 m_rec.BuildHeader(data.UseData(), offset);
164 m_rec.BuildFields(data.UseData(), offset, ic);
165 return true;
168 virtual bool FetchRecord(DBData &data, const IConverter *ic)
170 size_t offset = 0;
171 return BuildRecord(data, offset, ic);
174 virtual bool EndOfFile() const
176 return m_end_of_file;
182 // RecordFetch template class
184 /// Generic record fetch class, to help with using records without
185 /// builder classes.
187 template <class RecordT>
188 class RecordFetch
190 const RecordT &m_rec;
191 mutable bool m_done;
193 public:
194 RecordFetch(const RecordT &rec) : m_rec(rec), m_done(false) {}
195 bool operator()(RecordT &rec, Builder &) const
197 if( m_done )
198 return false;
199 rec = m_rec;
200 m_done = true;
201 return true;
206 } // namespace Barry
208 #endif