Iterate over mmaped gzip file with boost

I am trying to learn boost and some programming patterns in C ++, but it really is very difficult for me to implement a simple class to iterate Gzip files with mapped_file_source. I am essentially a list of edges in TSV format so that each line in the file is gzip format <src:int><tab><dst:int>. I want to implement a class gz_filethat provides an iterator of start and end, by which I can get an edge ( std::pair<int,int>) every time I request an iterator.

The problem is that the copy constructor is corrupt, since I cannot know where I am placed in the gzip file.

Here is the code that I still have:

class gz_graph {
public:
    gz_graph(const char * filename)
    {
        m_file.open(filename);
        if (!m_file.is_open()) {
            throw std::runtime_error("Error opening file");
        }

        m_data = m_file.data();
        m_data_size = m_file.size() / sizeof(m_data[0]);

        auto ret = posix_madvise((void*)m_data, m_data_size, POSIX_MADV_SEQUENTIAL);
    }

    class iterator;

    iterator begin() const
    {
        return iterator(this, false);
    }

    iterator end() const
    {
        return iterator(this, true);
    }

    class iterator : public std::iterator<std::forward_iterator_tag, Edge> {
        public:
            iterator(gz_graph const * ref, bool consumed)
                : m_ref(ref),
                  m_cur_edge(-1, -1),
                  m_consumed(consumed)
            {
                if (!consumed) {
                    initialize();
                    advance();
                }
            }

            iterator(const iterator& x)
                : m_ref(x.m_ref),
                  m_cur_edge(x.m_cur_edge)
            {
                if (!x.m_consumed) {
                    initialize();
                    advance();
                }

                std::cout << "Copy constructor" << std::endl;
            }

            value_type const& operator*() const
            {
                return m_cur_edge;
            }

            value_type const* operator->() const
            {
                return &m_cur_edge;
            }

            iterator& operator++()
            {
                advance();
                return *this;
            }

            bool operator==(iterator const& other) const
            {
                assert(m_ref == other.m_ref);
                return m_cur_edge == other.m_cur_edge;
            }

            bool operator!=(iterator const& other) const
            {
                return !(*this == other);
            }

        private:
            void initialize()
            {
                boost::iostreams::array_source source(m_ref->m_data, m_ref->m_data_size);
                m_in.push(boost::iostreams::gzip_decompressor());
                m_in.push(source);
            }

            void advance()
            {
                std::string line_str;
                if (!getline(m_in, line_str)) {
                    m_consumed = true;
                    m_cur_edge = Edge(-1, -1);
                    return;
                }

                std::vector<std::string> strs;
                boost::split(strs, line_str, boost::is_any_of("\t"));

                if (strs.size() != 2)
                    throw std::runtime_error("Required 2 fields per line");

                int src = boost::lexical_cast<int>(strs.at(0));
                int dst = boost::lexical_cast<int>(strs.at(1));

                m_cur_edge = Edge(src, dst);

//                std::cout << "Read line " << line_str << std::endl;
            }

            gz_graph const * m_ref;
            Edge m_cur_edge;
            boost::iostreams::filtering_istream m_in;
            bool m_consumed;
        };

private:
    boost::iostreams::mapped_file_source m_file;
    char const* m_data;
    size_t m_data_size;
};
+1
source share
1

std::istream_iterator . , " ", "" :

struct Edge : std::pair<int, int> { };

std::istream& operator>>(std::istream& is, Edge& edge)
{
    using namespace boost::spirit::qi;
    return is >> match("src:" > int_ > '\t' > "dst:" > int_ >> eol, edge.first, edge.second);
}

, , , , ?

for (
        std::istream_iterator<Edge> it(fs >> std::noskipws), end;
        it != end;
        ++it)
{
    std::cout << it->first << " to " << it->second << "\n";
}

fs - filtering_istream, gzip_decompressor. Live On Coliru


#include <boost/iostreams/device/mapped_file.hpp>
#include <boost/iostreams/filtering_stream.hpp>
#include <boost/iostreams/filter/gzip.hpp>

#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/qi_match.hpp>
#include <iterator>

struct Edge : std::pair<int, int> {
};

std::istream& operator>>(std::istream& is, Edge& edge)
{
    using namespace boost::spirit::qi;
    return is >> match("src:" > int_ > '\t' > "dst:" > int_ >> eol, edge.first, edge.second);
}

namespace io = boost::iostreams;

int main()
{
    io::mapped_file_source csv("csv.txt.gz");

    io::stream<io::mapped_file_source> textstream(csv);
    io::filtering_istream fs;
    fs.push(io::gzip_decompressor{});
    fs.push(textstream);

    for (
            std::istream_iterator<Edge> it(fs >> std::noskipws), last;
            it != last;
            ++it)
    {
        std::cout << it->first << " to " << it->second << "\n";
    }
}
+2

All Articles