diff --git a/src/swcio.hpp b/src/swcio.hpp index ba52720a7f1852c88cb60ae51b0f1aee9c10f9b9..6b5db68dd913db031fe07bd6862d1cae7d6e1d97 100644 --- a/src/swcio.hpp +++ b/src/swcio.hpp @@ -2,6 +2,7 @@ #include <exception> #include <iostream> +#include <iterator> #include <string> #include <vector> @@ -60,6 +61,16 @@ public: cell_record(const cell_record &other) = default; cell_record &operator=(const cell_record &other) = default; + bool strict_equals(const cell_record &other) + { + return id_ == other.id_ && + x_ == other.x_ && + y_ == other.y_ && + z_ == other.z_ && + r_ == other.r_ && + parent_id_ == other.parent_id_; + } + // Equality and comparison operators friend bool operator==(const cell_record &lhs, const cell_record &rhs) @@ -151,6 +162,7 @@ private: id_type parent_id_; // cell parent's id }; + class swc_parse_error : public std::runtime_error { public: @@ -200,5 +212,103 @@ std::istream &operator>>(std::istream &is, cell_record &cell); // std::vector<cell_record> swc_read_cells(std::istream &is); +class cell_record_stream_iterator : + public std::iterator<std::forward_iterator_tag, cell_record> +{ +public: + struct eof_tag { }; + + cell_record_stream_iterator(std::istream &is) + : is_(is) + , eof_(false) + { + read_next_record(); + } + + cell_record_stream_iterator(std::istream &is, eof_tag) + : is_(is) + , eof_(true) + { } + + + cell_record_stream_iterator &operator++() + { + if (eof_) { + throw std::out_of_range("attempt to read past eof"); + } + + read_next_record(); + return *this; + } + + cell_record_stream_iterator operator++(int); + + value_type operator*() + { + return curr_record_; + } + + bool operator==(const cell_record_stream_iterator &other) + { + if (eof_ && other.eof_) { + return true; + } else { + return curr_record_.strict_equals(other.curr_record_); + } + } + + bool operator!=(const cell_record_stream_iterator &other) + { + return !(*this == other); + } + +private: + void read_next_record() + { + parser_.parse_record(is_, curr_record_); + if (is_.eof()) { + eof_ = true; + } + } + + std::istream &is_; + swc_parser parser_; + cell_record curr_record_; + + // indicator of eof; we need a way to define an end() iterator without + // seeking to the end of file + bool eof_; +}; + + +class cell_record_range_raw +{ +public: + using value_type = cell_record; + using reference = value_type &; + using const_referene = const value_type &; + using iterator = cell_record_stream_iterator; + using const_iterator = const cell_record_stream_iterator; + + cell_record_range_raw(std::istream &is) + : is_(is) + { } + + iterator begin() + { + return cell_record_stream_iterator(is_); + } + + iterator end() + { + iterator::eof_tag eof; + return cell_record_stream_iterator(is_, eof); + } + +private: + std::istream &is_; +}; + + } // end of nestmc::io } // end of nestmc diff --git a/tests/test_swcio.cpp b/tests/test_swcio.cpp index a3a7336a8716877cb2a6bc084b4b866a9b58a005..2ca3563abdf6b412a9a14ac3cdd67802fcfc5f92 100644 --- a/tests/test_swcio.cpp +++ b/tests/test_swcio.cpp @@ -296,3 +296,25 @@ TEST(swc_parser, input_cleaning) } } + +TEST(cell_record_ranges, raw) +{ + using namespace nestmc::io; + + { + std::stringstream is; + + // Check valid usage + is << "1 1 14.566132 34.873772 7.857000 0.717830 -1\n"; + is << "2 1 14.566132 34.873772 7.857000 0.717830 1\n"; + is << "3 1 14.566132 34.873772 7.857000 0.717830 1\n"; + is << "4 1 14.566132 34.873772 7.857000 0.717830 1\n"; + + std::vector<cell_record> cells; + for (auto &&c : cell_record_range_raw(is)) { + cells.push_back(c); + } + + EXPECT_EQ(4, cells.size()); + } +}