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