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