lib: simplified parser and builder API, using the new DBData class
[barry.git] / src / builder.h
blobbb8c55c098d723c6de0e55a68b00f3644d38e18d
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 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
58 /// handle this.
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:
87 ///
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.
95 ///
96 /// Example SaveDatabase() call:
97 ///
98 /// <pre>
99 /// FIXME
100 /// </pre>
102 template <class RecordT, class StorageT>
103 class RecordBuilder : public Builder
105 StorageT *m_storage;
106 bool m_owned;
107 bool m_record_loaded;
108 bool m_end_of_file;
109 RecordT m_rec;
111 public:
112 /// Constructor that references an externally managed storage object.
113 RecordBuilder(StorageT &storage)
114 : m_storage(&storage)
115 , m_owned(false)
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)
126 : m_storage(storage)
127 , m_owned(true)
128 , m_record_loaded(false)
129 , m_end_of_file(false)
133 ~RecordBuilder()
135 if( this->m_owned )
136 delete m_storage;
139 virtual bool Retrieve()
141 if( m_end_of_file )
142 return false;
143 if( m_record_loaded )
144 return true;
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
179 /// builder classes.
181 template <class RecordT>
182 class RecordFetch
184 const RecordT &m_rec;
185 mutable bool m_done;
187 public:
188 RecordFetch(const RecordT &rec) : m_rec(rec), m_done(false) {}
189 bool operator()(RecordT &rec, Builder &) const
191 if( m_done )
192 return false;
193 rec = m_rec;
194 m_done = true;
195 return true;
200 } // namespace Barry
202 #endif