| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374 | // Copyright 2005 The Trustees of Indiana University.// Use, modification and distribution is subject to the Boost Software// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at// http://www.boost.org/LICENSE_1_0.txt)//  Authors: Alex Breuer//           Andrew Lumsdaine#ifndef BOOST_GRAPH_DIMACS_HPP#define BOOST_GRAPH_DIMACS_HPP#include <string>#include <sstream>#include <iostream>#include <fstream>#include <iterator>#include <exception>#include <vector>#include <queue>#include <boost/assert.hpp>namespace boost{namespace graph{    class BOOST_SYMBOL_VISIBLE dimacs_exception : public std::exception    {    };    class dimacs_basic_reader    {    public:        typedef std::size_t vertices_size_type;        typedef std::size_t edges_size_type;        typedef double vertex_weight_type;        typedef double edge_weight_type;        typedef std::pair< vertices_size_type, vertices_size_type > edge_type;        enum incr_mode        {            edge,            edge_weight        };        dimacs_basic_reader(std::istream& in, bool want_weights = true)        : inpt(in), seen_edges(0), want_weights(want_weights)        {            while (getline(inpt, buf) && !buf.empty() && buf[0] == 'c')                ;            if (buf[0] != 'p')            {                boost::throw_exception(dimacs_exception());            }            std::stringstream instr(buf);            std::string junk;            instr >> junk >> junk >> num_vertices >> num_edges;            read_edge_weights.push(-1);            incr(edge_weight);        }        // for a past the end iterator        dimacs_basic_reader()        : inpt(std::cin)        , num_vertices(0)        , num_edges(0)        , seen_edges(0)        , want_weights(false)        {        }        edge_type edge_deref()        {            BOOST_ASSERT(!read_edges.empty());            return read_edges.front();        }        inline edge_type* edge_ref()        {            BOOST_ASSERT(!read_edges.empty());            return &read_edges.front();        }        inline edge_weight_type edge_weight_deref()        {            BOOST_ASSERT(!read_edge_weights.empty());            return read_edge_weights.front();        }        inline dimacs_basic_reader incr(incr_mode mode)        {            if (mode == edge)            {                BOOST_ASSERT(!read_edges.empty());                read_edges.pop();            }            else if (mode == edge_weight)            {                BOOST_ASSERT(!read_edge_weights.empty());                read_edge_weights.pop();            }            if ((mode == edge && read_edges.empty())                || (mode == edge_weight && read_edge_weights.empty()))            {                if (seen_edges > num_edges)                {                    boost::throw_exception(dimacs_exception());                }                while (getline(inpt, buf) && !buf.empty() && buf[0] == 'c')                    ;                if (!inpt.eof())                {                    int source, dest, weight;                    read_edge_line((char*)buf.c_str(), source, dest, weight);                    seen_edges++;                    source--;                    dest--;                    read_edges.push(edge_type(source, dest));                    if (want_weights)                    {                        read_edge_weights.push(weight);                    }                }                BOOST_ASSERT(read_edges.size() < 100);                BOOST_ASSERT(read_edge_weights.size() < 100);            }            // the 1000000 just happens to be about how many edges can be read            // in 10s            //     if( !(seen_edges % 1000000) && !process_id( pg ) && mode ==            //     edge ) {            //       std::cout << "read " << seen_edges << " edges" <<            //       std::endl;            //     }            return *this;        }        inline bool done_edges()        {            return inpt.eof() && read_edges.size() == 0;        }        inline bool done_edge_weights()        {            return inpt.eof() && read_edge_weights.size() == 0;        }        inline vertices_size_type n_vertices() { return num_vertices; }        inline vertices_size_type processed_edges()        {            return seen_edges - read_edges.size();        }        inline vertices_size_type processed_edge_weights()        {            return seen_edges - read_edge_weights.size();        }        inline vertices_size_type n_edges() { return num_edges; }    protected:        bool read_edge_line(char* linebuf, int& from, int& to, int& weight)        {            char *fs = NULL, *ts = NULL, *ws = NULL;            char* tmp = linebuf + 2;            fs = tmp;            if ('e' == linebuf[0])            {                while (*tmp != '\n' && *tmp != '\0')                {                    if (*tmp == ' ')                    {                        *tmp = '\0';                        ts = ++tmp;                        break;                    }                    tmp++;                }                *tmp = '\0';                if (NULL == fs || NULL == ts)                    return false;                from = atoi(fs);                to = atoi(ts);                weight = 0;            }            else if ('a' == linebuf[0])            {                while (*tmp != '\n' && *tmp != '\0')                {                    if (*tmp == ' ')                    {                        *tmp = '\0';                        ts = ++tmp;                        break;                    }                    tmp++;                }                while (*tmp != '\n' && *tmp != '\0')                {                    if (*tmp == ' ')                    {                        *tmp = '\0';                        ws = ++tmp;                        break;                    }                    tmp++;                }                while (*tmp != '\n' && *tmp != '\0')                    tmp++;                *tmp = '\0';                if (fs == NULL || ts == NULL || ws == NULL)                    return false;                from = atoi(fs);                to = atoi(ts);                if (want_weights)                    weight = atoi(ws);                else                    weight = 0;            }            else            {                return false;            }            return true;        }        std::queue< edge_type > read_edges;        std::queue< edge_weight_type > read_edge_weights;        std::istream& inpt;        std::string buf;        vertices_size_type num_vertices, num_edges, seen_edges;        bool want_weights;    };    template < typename T > class dimacs_edge_iterator    {    public:        typedef dimacs_basic_reader::edge_type edge_type;        typedef dimacs_basic_reader::incr_mode incr_mode;        typedef std::input_iterator_tag iterator_category;        typedef edge_type value_type;        typedef value_type reference;        typedef edge_type* pointer;        typedef std::ptrdiff_t difference_type;        dimacs_edge_iterator(T& reader) : reader(reader) {}        inline dimacs_edge_iterator& operator++()        {            reader.incr(dimacs_basic_reader::edge);            return *this;        }        inline edge_type operator*() { return reader.edge_deref(); }        inline edge_type* operator->() { return reader.edge_ref(); }        // don't expect this to do the right thing if you're not comparing        // against a general past-the-end-iterator made with the default        // constructor for dimacs_basic_reader        inline bool operator==(dimacs_edge_iterator arg)        {            if (reader.n_vertices() == 0)            {                return arg.reader.done_edges();            }            else if (arg.reader.n_vertices() == 0)            {                return reader.done_edges();            }            else            {                return false;            }            return false;        }        inline bool operator!=(dimacs_edge_iterator arg)        {            if (reader.n_vertices() == 0)            {                return !arg.reader.done_edges();            }            else if (arg.reader.n_vertices() == 0)            {                return !reader.done_edges();            }            else            {                return true;            }            return true;        }    private:        T& reader;    };    template < typename T > class dimacs_edge_weight_iterator    {    public:        typedef dimacs_basic_reader::edge_weight_type edge_weight_type;        typedef dimacs_basic_reader::incr_mode incr_mode;        dimacs_edge_weight_iterator(T& reader) : reader(reader) {}        inline dimacs_edge_weight_iterator& operator++()        {            reader.incr(dimacs_basic_reader::edge_weight);            return *this;        }        inline edge_weight_type operator*()        {            return reader.edge_weight_deref();        }        // don't expect this to do the right thing if you're not comparing        // against a general past-the-end-iterator made with the default        // constructor for dimacs_basic_reader        inline bool operator==(dimacs_edge_weight_iterator arg)        {            if (reader.n_vertices() == 0)            {                return arg.reader.done_edge_weights();            }            else if (arg.reader.n_vertices() == 0)            {                return reader.done_edge_weights();            }            else            {                return false;            }            return false;        }        inline bool operator!=(dimacs_edge_weight_iterator arg)        {            if (reader.n_vertices() == 0)            {                return !arg.reader.done_edge_weights();            }            else if (arg.reader.n_vertices() == 0)            {                return !reader.done_edge_weights();            }            else            {                return true;            }            return true;        }    private:        T& reader;    };}} // end namespace boost::graph#endif
 |