Chemical Data Processing Library C++ API - Version 1.2.0
CompoundDataReader.hpp
Go to the documentation of this file.
1 /*
2  * CompoundDataReader.hpp
3  *
4  * This file is part of the Chemical Data Processing Toolkit
5  *
6  * Copyright (C) 2003 Thomas Seidel <thomas.seidel@univie.ac.at>
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public License
19  * along with this library; see the file COPYING. If not, write to
20  * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21  * Boston, MA 02111-1307, USA.
22  */
23 
29 #ifndef CDPL_UTIL_COMPOUNDDATAREADER_HPP
30 #define CDPL_UTIL_COMPOUNDDATAREADER_HPP
31 
32 #include <vector>
33 #include <algorithm>
34 #include <functional>
35 
36 #include "CDPL/Base/DataReader.hpp"
37 #include "CDPL/Base/Exceptions.hpp"
38 
39 
40 namespace CDPL
41 {
42 
43  namespace Util
44  {
45 
49  template <typename DataType>
50  class CompoundDataReader : public Base::DataReader<DataType>
51  {
52 
53  public:
54  typedef std::shared_ptr<CompoundDataReader> SharedPointer;
55 
58 
60 
62 
64 
66 
67  void addReader(const ReaderPointer& reader);
68 
69  void removeReader(std::size_t idx);
70 
71  std::size_t getNumReaders();
72 
73  void clear();
74 
75  std::size_t getReaderIDForRecordIndex(std::size_t idx) const;
76 
77  const ReaderPointer& getReader(std::size_t idx) const;
78 
79  CompoundDataReader& read(DataType& obj, bool overwrite = true);
80  CompoundDataReader& read(std::size_t idx, DataType& obj, bool overwrite = true);
81 
83 
84  bool hasMoreData();
85 
86  std::size_t getRecordIndex() const;
87  void setRecordIndex(std::size_t idx);
88 
89  std::size_t getNumRecords();
90 
91  operator const void*() const;
92  bool operator!() const;
93 
94  private:
95  ReaderType* getReaderForRecordIndex(std::size_t& idx) const;
96 
97  typedef std::vector<ReaderPointer> ReaderArray;
98  typedef std::vector<std::size_t> RecordIndexArray;
99 
100  ReaderArray readers;
101  bool state;
102  RecordIndexArray recordIdxBounds;
103  std::size_t recordIdx;
104  std::size_t numRecords;
105  };
106  } // namespace Util
107 } // namespace CDPL
108 
109 
110 // Implementation
111 
112 template <typename DataType>
114  state(false), recordIdx(0), numRecords(0)
115 {}
116 
117 template <typename DataType>
119 {
120  clear();
121 }
122 
123 template <typename DataType>
125 {
126  std::for_each(readers.begin(), readers.end(),
127  std::bind(&ReaderType::setParent, std::placeholders::_1,
128  static_cast<CompoundDataReader*>(0)));
129  readers.clear();
130  recordIdxBounds.clear();
131 
132  numRecords = 0;
133  state = false;
134  recordIdx = 0;
135 }
136 
137 template <typename DataType>
139 {
140  readers.reserve(readers.size() + 1);
141  recordIdxBounds.reserve(readers.size() + 1);
142 
143  reader->setParent(this);
144 
145  std::size_t num_recs = reader->getNumRecords();
146 
147  readers.push_back(reader);
148  numRecords += num_recs;
149  recordIdxBounds.push_back(numRecords);
150 
151  state |= static_cast<bool>(reader->operator const void*());
152 }
153 
154 template <typename DataType>
156 {
157  if (idx >= readers.size())
158  throw Base::IndexError("CompoundDataReader: reader index out of bounds");
159 
160  std::size_t num_lost_records = readers[idx]->getNumRecords();
161 
162  readers[idx]->setParent(0);
163 
164  readers.erase(readers.begin() + idx);
165  recordIdxBounds.erase(recordIdxBounds.begin() + idx);
166 
167  for (; idx < readers.size(); idx++)
168  recordIdxBounds[idx] -= num_lost_records;
169 
170  numRecords -= num_lost_records;
171 }
172 
173 template <typename DataType>
175 {
176  return readers.size();
177 }
178 
179 template <typename DataType>
182 {
183  if (idx >= readers.size())
184  throw Base::IndexError("CompoundDataReader: reader index out of bounds");
185 
186  return readers[idx];
187 }
188 
189 template <typename DataType>
192 {
193  state = false;
194 
195  if (recordIdx >= numRecords)
196  return *this;
197 
198  std::size_t idx = recordIdx;
199  ReaderType* reader = getReaderForRecordIndex(idx);
200 
201  if (reader && (state = reader->read(idx, obj, overwrite))) {
202  recordIdx++;
203  this->invokeIOCallbacks(1.0);
204  }
205 
206  return *this;
207 }
208 
209 template <typename DataType>
211 CDPL::Util::CompoundDataReader<DataType>::read(std::size_t idx, DataType& obj, bool overwrite)
212 {
213  setRecordIndex(idx);
214 
215  return read(obj, overwrite);
216 }
217 
218 template <typename DataType>
221 {
222  state = false;
223 
224  if (recordIdx >= numRecords)
225  return *this;
226 
227  recordIdx++;
228  state = true;
229 
230  this->invokeIOCallbacks(1.0);
231 
232  return *this;
233 }
234 
235 template <typename DataType>
237 {
238  return (recordIdx < numRecords);
239 }
240 
241 template <typename DataType>
243 {
244  return recordIdx;
245 }
246 
247 template <typename DataType>
249 {
250  if (idx > numRecords)
251  throw Base::IndexError("CompoundDataReader: record index out of bounds");
252 
253  recordIdx = idx;
254 }
255 
256 template <typename DataType>
258 {
259  return numRecords;
260 }
261 
262 template <typename DataType>
264 {
265  return (state ? this : 0);
266 }
267 
268 template <typename DataType>
270 {
271  return !state;
272 }
273 
274 template <typename DataType>
276 {
277  for (std::size_t i = 0; i < readers.size(); i++) {
278  if (idx < recordIdxBounds[i])
279  return (i + 1);
280  }
281 
282  return 0;
283 }
284 
285 template <typename DataType>
288 {
289  for (std::size_t i = 0; i < readers.size(); i++) {
290  if (idx < recordIdxBounds[i]) {
291  idx -= (i == 0 ? std::size_t(0) : recordIdxBounds[i - 1]);
292  return readers[i].get();
293  }
294  }
295 
296  return 0;
297 }
298 
299 #endif // CDPL_UTIL_COMPOUNDDATAREADER_HPP
Definition of exception classes.
Definition of the class CDPL::Base::DataReader.
An interface for reading data objects of a given type from an arbitrary data source.
Definition: DataReader.hpp:73
std::shared_ptr< DataReader > SharedPointer
A reference-counted smart pointer [SHPTR] for dynamically allocated DataReader instances.
Definition: DataReader.hpp:84
virtual DataReader & read(DataType &obj, bool overwrite=true)=0
Reads the data record at the current record index and stores the read data in obj.
DataType DataType
The type of the read data objects.
Definition: DataReader.hpp:79
Thrown to indicate that an index is out of range.
Definition: Base/Exceptions.hpp:152
CompoundDataReader.
Definition: CompoundDataReader.hpp:51
void setRecordIndex(std::size_t idx)
Sets the index of the current data record to idx.
Definition: CompoundDataReader.hpp:248
void addReader(const ReaderPointer &reader)
Definition: CompoundDataReader.hpp:138
CompoundDataReader()
Definition: CompoundDataReader.hpp:113
void clear()
Definition: CompoundDataReader.hpp:124
std::size_t getNumReaders()
Definition: CompoundDataReader.hpp:174
std::size_t getRecordIndex() const
Returns the index of the current data record.
Definition: CompoundDataReader.hpp:242
CompoundDataReader & operator=(const CompoundDataReader &)=delete
bool operator!() const
Tells whether the reader is in a bad state.
Definition: CompoundDataReader.hpp:269
const ReaderPointer & getReader(std::size_t idx) const
Definition: CompoundDataReader.hpp:181
CompoundDataReader(const CompoundDataReader &)=delete
~CompoundDataReader()
Definition: CompoundDataReader.hpp:118
CompoundDataReader & skip()
Skips the data record at the current record index.
Definition: CompoundDataReader.hpp:220
ReaderType::SharedPointer ReaderPointer
Definition: CompoundDataReader.hpp:57
void removeReader(std::size_t idx)
Definition: CompoundDataReader.hpp:155
std::shared_ptr< CompoundDataReader > SharedPointer
Definition: CompoundDataReader.hpp:54
bool hasMoreData()
Tells if there are any data records left to read.
Definition: CompoundDataReader.hpp:236
CompoundDataReader & read(DataType &obj, bool overwrite=true)
Reads the data record at the current record index and stores the read data in obj.
Definition: CompoundDataReader.hpp:191
std::size_t getReaderIDForRecordIndex(std::size_t idx) const
Definition: CompoundDataReader.hpp:275
Base::DataReader< DataType > ReaderType
Definition: CompoundDataReader.hpp:56
std::size_t getNumRecords()
Returns the total number of available data records.
Definition: CompoundDataReader.hpp:257
The namespace of the Chemical Data Processing Library.