1 /* This file is part of Jellyfish. 2 3 Jellyfish is free software: you can redistribute it and/or modify 4 it under the terms of the GNU General Public License as published by 5 the Free Software Foundation, either version 3 of the License, or 6 (at your option) any later version. 7 8 Jellyfish is distributed in the hope that it will be useful, 9 but WITHOUT ANY WARRANTY; without even the implied warranty of 10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 GNU General Public License for more details. 12 13 You should have received a copy of the GNU General Public License 14 along with Jellyfish. If not, see <http://www.gnu.org/licenses/>. 15 */ 16 17 18 #ifndef __STREAM_ITERATOR_HPP__ 19 #define __STREAM_ITERATOR_HPP__ 20 21 #include <assert.h> 22 23 #include <iostream> 24 #include <fstream> 25 #include <iterator> 26 #include <stdexcept> 27 #include <memory> 28 29 #include <jellyfish/err.hpp> 30 31 namespace jellyfish { 32 /// Transform an iterator of paths (c string: const char*) into an 33 /// iterator of std::ifstream. Every file is opened and closed in 34 /// turn. The object instantiated with no argument is the end marker. 35 template<typename PathIterator> 36 class stream_iterator : public std::iterator<std::forward_iterator_tag, std::ifstream> { 37 PathIterator begin_, end_; 38 std::ifstream* stream_; 39 public: stream_iterator(PathIterator begin,PathIterator end)40 stream_iterator(PathIterator begin, PathIterator end) : 41 begin_(begin), end_(end), stream_(0) 42 { 43 if(begin_ != end_) { 44 stream_ = new std::ifstream; 45 open_file(); 46 } 47 } stream_iterator(const stream_iterator & rhs)48 stream_iterator(const stream_iterator& rhs) : 49 begin_(rhs.begin_), end_(rhs.end_), stream_(rhs.stream_) 50 { } stream_iterator()51 stream_iterator() : begin_(), end_(), stream_() { } 52 operator ==(const stream_iterator & rhs) const53 bool operator==(const stream_iterator& rhs) const { 54 return stream_ == rhs.stream_; 55 } operator !=(const stream_iterator & rhs) const56 bool operator!=(const stream_iterator& rhs) const { 57 return stream_ != rhs.stream_; 58 } 59 operator *()60 std::ifstream& operator*() { return *stream_; } operator ->()61 std::ifstream* operator->() { return stream_; } 62 operator ++()63 stream_iterator& operator++() { 64 stream_->close(); 65 if(++begin_ != end_) { 66 open_file(); 67 } else { 68 delete stream_; 69 stream_ = 0; 70 } 71 72 return *this; 73 } operator ++(int)74 stream_iterator operator++(int) { 75 stream_iterator res(*this); 76 ++*this; 77 return res; 78 } 79 80 protected: open_file()81 void open_file() { 82 stream_->open(*begin_); 83 if(stream_->fail()) 84 throw std::runtime_error(err::msg() << "Failed to open file '" << *begin_ << "'"); 85 } 86 }; 87 88 } 89 90 #endif /* __STREAM_ITERATOR_HPP__ */ 91