Chemical Data Processing Library C++ API - Version 1.4.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 
52  template <typename DataType>
53  class CompoundDataReader : public Base::DataReader<DataType>
54  {
55 
56  public:
58  typedef std::shared_ptr<CompoundDataReader> SharedPointer;
59 
64 
69 
74 
76 
78 
83  void addReader(const ReaderPointer& reader);
84 
90  void removeReader(std::size_t idx);
91 
96  std::size_t getNumReaders();
97 
101  void clear();
102 
108  std::size_t getReaderIDForRecordIndex(std::size_t idx) const;
109 
116  const ReaderPointer& getReader(std::size_t idx) const;
117 
124  CompoundDataReader& read(DataType& obj, bool overwrite = true);
125 
134  CompoundDataReader& read(std::size_t idx, DataType& obj, bool overwrite = true);
135 
141 
146  bool hasMoreData();
147 
152  std::size_t getRecordIndex() const;
153 
159  void setRecordIndex(std::size_t idx);
160 
165  std::size_t getNumRecords();
166 
171  operator const void*() const;
172 
177  bool operator!() const;
178 
179  private:
180  ReaderType* getReaderForRecordIndex(std::size_t& idx) const;
181 
182  typedef std::vector<ReaderPointer> ReaderArray;
183  typedef std::vector<std::size_t> RecordIndexArray;
184 
185  ReaderArray readers;
186  bool state;
187  RecordIndexArray recordIdxBounds;
188  std::size_t recordIdx;
189  std::size_t numRecords;
190  };
191  } // namespace Util
192 } // namespace CDPL
193 
194 
195 // Implementation
196 
197 template <typename DataType>
199  state(false), recordIdx(0), numRecords(0)
200 {}
201 
202 template <typename DataType>
204 {
205  clear();
206 }
207 
208 template <typename DataType>
210 {
211  std::for_each(readers.begin(), readers.end(),
212  std::bind(&ReaderType::setParent, std::placeholders::_1,
213  static_cast<CompoundDataReader*>(0)));
214  readers.clear();
215  recordIdxBounds.clear();
216 
217  numRecords = 0;
218  state = false;
219  recordIdx = 0;
220 }
221 
222 template <typename DataType>
224 {
225  readers.reserve(readers.size() + 1);
226  recordIdxBounds.reserve(readers.size() + 1);
227 
228  reader->setParent(this);
229 
230  std::size_t num_recs = reader->getNumRecords();
231 
232  readers.push_back(reader);
233  numRecords += num_recs;
234  recordIdxBounds.push_back(numRecords);
235 
236  state |= static_cast<bool>(reader->operator const void*());
237 }
238 
239 template <typename DataType>
241 {
242  if (idx >= readers.size())
243  throw Base::IndexError("CompoundDataReader: reader index out of bounds");
244 
245  std::size_t num_lost_records = readers[idx]->getNumRecords();
246 
247  readers[idx]->setParent(0);
248 
249  readers.erase(readers.begin() + idx);
250  recordIdxBounds.erase(recordIdxBounds.begin() + idx);
251 
252  for ( ; idx < readers.size(); idx++)
253  recordIdxBounds[idx] -= num_lost_records;
254 
255  numRecords -= num_lost_records;
256 }
257 
258 template <typename DataType>
260 {
261  return readers.size();
262 }
263 
264 template <typename DataType>
267 {
268  if (idx >= readers.size())
269  throw Base::IndexError("CompoundDataReader: reader index out of bounds");
270 
271  return readers[idx];
272 }
273 
274 template <typename DataType>
277 {
278  state = false;
279 
280  if (recordIdx >= numRecords)
281  return *this;
282 
283  std::size_t idx = recordIdx;
284  ReaderType* reader = getReaderForRecordIndex(idx);
285 
286  if (reader && (state = reader->read(idx, obj, overwrite))) {
287  recordIdx++;
288  this->invokeIOCallbacks(1.0);
289  }
290 
291  return *this;
292 }
293 
294 template <typename DataType>
296 CDPL::Util::CompoundDataReader<DataType>::read(std::size_t idx, DataType& obj, bool overwrite)
297 {
298  state = false;
299 
300  if (idx >= numRecords)
301  throw Base::IndexError("CompoundDataReader: record index out of bounds");
302 
303  std::size_t tmp_idx = idx;
304  ReaderType* reader = getReaderForRecordIndex(tmp_idx);
305 
306  if (reader) {
307  recordIdx = idx;
308 
309  if ((state = reader->read(tmp_idx, obj, overwrite))) {
310  recordIdx++;
311  this->invokeIOCallbacks(1.0);
312  }
313  }
314 
315  return *this;
316 }
317 
318 template <typename DataType>
321 {
322  state = false;
323 
324  if (recordIdx >= numRecords)
325  return *this;
326 
327  recordIdx++;
328  state = true;
329 
330  this->invokeIOCallbacks(1.0);
331 
332  return *this;
333 }
334 
335 template <typename DataType>
337 {
338  return (recordIdx < numRecords);
339 }
340 
341 template <typename DataType>
343 {
344  return recordIdx;
345 }
346 
347 template <typename DataType>
349 {
350  if (idx > numRecords)
351  throw Base::IndexError("CompoundDataReader: record index out of bounds");
352 
353  recordIdx = idx;
354 }
355 
356 template <typename DataType>
358 {
359  return numRecords;
360 }
361 
362 template <typename DataType>
364 {
365  return (state ? this : 0);
366 }
367 
368 template <typename DataType>
370 {
371  return !state;
372 }
373 
374 template <typename DataType>
376 {
377  for (std::size_t i = 0; i < readers.size(); i++) {
378  if (idx < recordIdxBounds[i])
379  return (i + 1);
380  }
381 
382  return 0;
383 }
384 
385 template <typename DataType>
388 {
389  for (std::size_t i = 0; i < readers.size(); i++) {
390  if (idx < recordIdxBounds[i]) {
391  idx -= (i == 0 ? std::size_t(0) : recordIdxBounds[i - 1]);
392  return readers[i].get();
393  }
394  }
395 
396  return 0;
397 }
398 
399 #endif // CDPL_UTIL_COMPOUNDDATAREADER_HPP
Definition of exception classes.
Definition of class CDPL::Base::DataReader.
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
Composite Base::DataReader that aggregates several underlying readers and presents their records as o...
Definition: CompoundDataReader.hpp:54
void setRecordIndex(std::size_t idx)
Sets the current global record index.
Definition: CompoundDataReader.hpp:348
void addReader(const ReaderPointer &reader)
Appends reader to the list of underlying readers.
Definition: CompoundDataReader.hpp:223
CompoundDataReader()
Constructs an empty CompoundDataReader instance.
Definition: CompoundDataReader.hpp:198
void clear()
Removes all underlying readers.
Definition: CompoundDataReader.hpp:209
std::size_t getNumReaders()
Returns the number of underlying readers.
Definition: CompoundDataReader.hpp:259
std::size_t getRecordIndex() const
Returns the current global record index.
Definition: CompoundDataReader.hpp:342
CompoundDataReader & operator=(const CompoundDataReader &)=delete
bool operator!() const
Tells whether the reader is in a bad (non-readable) state.
Definition: CompoundDataReader.hpp:369
const ReaderPointer & getReader(std::size_t idx) const
Returns the underlying reader at index idx.
Definition: CompoundDataReader.hpp:266
CompoundDataReader(const CompoundDataReader &)=delete
~CompoundDataReader()
Destructor.
Definition: CompoundDataReader.hpp:203
CompoundDataReader & skip()
Skips the next record.
Definition: CompoundDataReader.hpp:320
ReaderType::SharedPointer ReaderPointer
Shared-pointer type for the underlying readers.
Definition: CompoundDataReader.hpp:63
void removeReader(std::size_t idx)
Removes the reader at index idx from the list of underlying readers.
Definition: CompoundDataReader.hpp:240
std::shared_ptr< CompoundDataReader > SharedPointer
A reference-counted smart pointer [SHPTR] for dynamically allocated CompoundDataReader instances.
Definition: CompoundDataReader.hpp:58
bool hasMoreData()
Tells whether more records are available.
Definition: CompoundDataReader.hpp:336
CompoundDataReader & read(DataType &obj, bool overwrite=true)
Reads the next record into obj.
Definition: CompoundDataReader.hpp:276
std::size_t getReaderIDForRecordIndex(std::size_t idx) const
Returns the index of the underlying reader that owns the global record index idx.
Definition: CompoundDataReader.hpp:375
Base::DataReader< DataType > ReaderType
Type of the underlying Base::DataReader specialization.
Definition: CompoundDataReader.hpp:61
std::size_t getNumRecords()
Returns the total number of records across all underlying readers.
Definition: CompoundDataReader.hpp:357
The namespace of the Chemical Data Processing Library.