COIN-OR::LEMON - Graph Library

Changeset 1409:d2d1f8fa187b in lemon-0.x for src/lemon


Ignore:
Timestamp:
05/11/05 13:50:13 (19 years ago)
Author:
Balazs Dezso
Branch:
default
Phase:
public
Convert:
svn:c9d7d8f5-90d6-0310-b91f-818b3a526b0e/lemon/trunk@1876
Message:

LemonWriter? and GraphWriter?.
Little bit better documentation.

Location:
src/lemon
Files:
2 added
3 edited

Legend:

Unmodified
Added
Removed
  • src/lemon/Makefile.am

    r1408 r1409  
    5454        utility.h \
    5555        lemon_reader.h \
     56        lemon_writer.h \
    5657        graph_reader.h \
    5758        graph_writer.h \
     
    6768        bits/erasable_graph_extender.h \
    6869        bits/undir_graph_extender.h \
    69         bits/item_reader.h
     70        bits/item_reader.h \
     71        bits/item_writer.h
    7072
    7173noinst_HEADERS = \
  • src/lemon/graph_writer.h

    r1402 r1409  
    2323
    2424#include <iostream>
    25 #include <sstream>
    26 
    27 #include <map>
    28 #include <vector>
    29 
    30 #include <memory>
    31 
    32 #include <lemon/graph_utils.h>
    33 
    34 #include <lemon/invalid.h>
     25
    3526#include <lemon/error.h>
    36 
     27#include <lemon/lemon_writer.h>
    3728
    3829namespace lemon {
     
    4132  /// @{
    4233
    43   /// \brief Standard WriterTraits for the GraphWriter class.
    44   ///
    45   /// Standard WriterTraits for the GraphWriter class.
    46   /// It defines standard writing method for all type of value.
    47   /// \author Balazs Dezso
    48   struct DefaultWriterTraits {
    49 
    50     /// \brief Template class for writing an value.
    51     ///
    52     /// Template class for writing an value.
    53     /// \author Balazs Dezso
    54     template <typename _Value>
    55     struct Writer {
    56       /// The value type.
    57       typedef _Value Value;
    58 
    59       /// \brief Writes a value to the given stream.
    60       ///
    61       /// Writes a value to the given stream.
    62       void write(std::ostream& os, const Value& value) {
    63         os << value << '\t';
    64       }
    65     };
    66 
    67     /// \brief Returns wheter this name is an ID map name.
    68     ///
    69     /// Returns wheter this name is an ID map name.
    70     static bool idMapName(const std::string& name) {
    71       return name == "id";
    72     }
    73 
    74   };
    75 
    76 
    77   /// \brief Writer class for quoted strings.
    78   ///
    79   /// Writer class for quoted strings. It can process the escape
    80   /// sequences in the string.
    81   /// \author Balazs Dezso
    82   class QuotedStringWriter {
    83   public:
    84     typedef std::string Value;
    85 
    86     /// \brief Constructor for the writer.
    87     ///
    88     /// Constructor for the writer. If the given parameter is true
    89     /// the writer creates escape sequences from special characters.
    90     QuotedStringWriter(bool _escaped = true) : escaped(_escaped) {}
    91 
    92     /// \brief Writes a quoted string to the given stream.
    93     ///
    94     /// Writes a quoted string to the given stream.
    95     void write(std::ostream& os, const std::string& value) {
    96       os << "\"";
    97       if (escaped) {
    98         std::ostringstream ls;
    99         for (int i = 0; i < (int)value.size(); ++i) {
    100           writeEscape(ls, value[i]);
    101         }
    102         os << ls.str();
    103       } else {
    104         os << value;
    105       }
    106       os << "\"";
    107     }
    108 
    109   private:
    110    
    111     static void writeEscape(std::ostream& os, char c) {
    112       switch (c) {
    113       case '\\':
    114         os << "\\\\";
    115         return;
    116       case '\"':
    117         os << "\\\"";
    118         return;
    119       case '\'':
    120         os << "\\\'";
    121         return;
    122       case '\?':
    123         os << "\\\?";
    124         return;
    125       case '\a':
    126         os << "\\a";
    127         return;
    128       case '\b':
    129         os << "\\b";
    130         return;
    131       case '\f':
    132         os << "\\f";
    133         return;
    134       case '\r':
    135         os << "\\r";
    136         return;
    137       case '\n':
    138         os << "\\n";
    139         return;
    140       case '\t':
    141         os << "\\t";
    142         return;
    143       case '\v':
    144         os << "\\v";
    145         return;
    146       default:
    147         if (c < 0x20) {
    148           os << '\\' << std::oct << (int)c;
    149         } else {
    150           os << c;
    151         }
    152         return;
    153       }     
    154     }
    155   private:
    156     bool escaped;
    157   };
    158 
    159   class GUIWriter {
    160   public:
    161     virtual void write(std::ostream& os) = 0;
    162   };
    163 
    164  
    16534  /// \brief The graph writer class.
    16635  ///
     
    232101    typedef _Graph Graph;
    233102    typedef typename Graph::Node Node;
    234     typedef typename Graph::NodeIt NodeIt;
    235103    typedef typename Graph::Edge Edge;
    236     typedef typename Graph::EdgeIt EdgeIt;
    237104
    238105    typedef _WriterTraits WriterTraits;
    239  
     106
    240107    /// \brief Construct a new GraphWriter.
    241108    ///
    242     /// Construct a new GraphWriter. It writes from the given map,
    243     /// it constructs the given map and it use the given writer as the
    244     /// default skipper.
     109    /// Construct a new GraphWriter. It writes the given graph
     110    /// to the given stream.
    245111    GraphWriter(std::ostream& _os, const Graph& _graph)
    246       : gui_writer(0), os(_os), graph(_graph){}
    247 
     112      : writer(new LemonWriter(_os)), own_writer(true),
     113        graph(_graph),
     114        nodeset_writer(*writer, graph, std::string()),
     115        edgeset_writer(*writer, graph, nodeset_writer, std::string()),
     116        node_writer(*writer, nodeset_writer, std::string()),
     117        edge_writer(*writer, edgeset_writer, std::string()),
     118        attribute_writer(*writer, std::string()) {}
     119
     120    /// \brief Construct a new GraphWriter.
     121    ///
     122    /// Construct a new GraphWriter. It writes into the given graph
     123    /// to the given file.
     124    GraphWriter(const std::string& _filename, const Graph& _graph)
     125      : writer(new LemonWriter(_filename)), own_writer(true),
     126        graph(_graph),
     127        nodeset_writer(*writer, graph, std::string(), skipper),
     128        edgeset_writer(*writer, graph, nodeset_writer, std::string(), skipper),
     129        node_writer(*writer, nodeset_writer, std::string()),
     130        edge_writer(*writer, edgeset_writer, std::string()),
     131        attribute_writer(*writer, std::string()) {}
     132
     133    /// \brief Construct a new GraphWriter.
     134    ///
     135    /// Construct a new GraphWriter. It writes into the given graph
     136    /// to given LemonReader.
     137    GraphWriter(LemonWriter& _writer, const Graph& _graph)
     138      : writer(_writer), own_writer(false),
     139        graph(_graph),
     140        nodeset_writer(*writer, graph, std::string()),
     141        edgeset_writer(*writer, graph, nodeset_writer, std::string()),
     142        node_writer(*writer, nodeset_writer, std::string()),
     143        edge_writer(*writer, edgeset_writer, std::string()),
     144        attribute_writer(*writer, std::string()) {}
    248145
    249146    /// \brief Destruct the graph writer.
     
    251148    /// Destruct the graph writer.
    252149    ~GraphWriter() {
    253       for (typename NodeMapWriters::iterator it = node_map_writers.begin();
    254            it != node_map_writers.end(); ++it) {
    255         delete it->second;
    256       }
    257 
    258       for (typename EdgeMapWriters::iterator it = edge_map_writers.begin();
    259            it != edge_map_writers.end(); ++it) {
    260         delete it->second;
    261       }
    262 
    263     }
    264 
    265     // Node map rules
     150      if (own_writer)
     151        delete writer;
     152    }
    266153
    267154    /// \brief Add a new node map writer command for the writer.
     
    270157    template <typename Map>
    271158    GraphWriter& writeNodeMap(std::string name, const Map& map) {
    272       return writeNodeMap<typename WriterTraits::template Writer<
    273         typename Map::Value>, Map>(name, map);
     159      nodeset_writer.writeMap(name, map);
     160      return *this;
    274161    }
    275162
     
    279166    template <typename Writer, typename Map>
    280167    GraphWriter& writeNodeMap(std::string name, const Map& map,
    281                               const Writer& writer = Writer()) {
    282       node_map_writers.push_back(
    283         make_pair(name, new MapWriter<Node, Map, Writer>(map, writer)));
    284       return *this;
    285     }
    286 
    287     // Edge map rules
     168                             const Writer& writer = Writer()) {
     169      nodeset_writer.writeMap(name, map, writer);
     170      return *this;
     171    }
     172
    288173
    289174    /// \brief Add a new edge map writer command for the writer.
     
    292177    template <typename Map>
    293178    GraphWriter& writeEdgeMap(std::string name, const Map& map) {
    294       return writeEdgeMap<typename WriterTraits::template Writer<
    295         typename Map::Value>, Map>(name, map);
     179      edgeset_writer.writeMap(name, map);
     180      return *this;
    296181    }
    297182
     
    301186    /// Add a new edge map writer command for the writer.
    302187    template <typename Writer, typename Map>
    303     GraphWriter& writeEdgeMap(std::string name,
    304                             const Map& map, const Writer& writer = Writer()) {
    305       edge_map_writers.push_back(make_pair(name,
    306         new MapWriter<Edge, Map, Writer>(map, writer)));
     188    GraphWriter& writeEdgeMap(std::string name, const Map& map,
     189                             const Writer& writer = Writer()) {
     190      edgeset_writer.writeMap(name, map, writer);
    307191      return *this;
    308192    }
     
    312196    /// Add a new labeled node writer for the writer.
    313197    GraphWriter& writeNode(std::string name, const Node& node) {
    314       node_writers.push_back(make_pair(name, node));
     198      node_writer.writeNode(name, node);
    315199      return *this;
    316200    }
     
    320204    /// Add a new labeled edge writer for the writer.
    321205    GraphWriter& writeEdge(std::string name, const Edge& edge) {
    322       edge_writers.push_back(make_pair(name, edge));
    323       return *this;
    324     }
    325 
    326     GraphWriter& writeGUI(const GUIWriter& writer) {
    327       gui_writer = &writer;
     206      edge_writer.writeEdge(name, edge);
     207    }
     208
     209    /// \brief Add a new attribute writer command.
     210    ///
     211    ///  Add a new attribute writer command.
     212    template <typename Value>
     213    GraphWriter& writeAttribute(std::string name, const Value& value) {
     214      attribute_writer.writeAttribute(name, value);
     215      return *this;
     216    }
     217   
     218    /// \brief Add a new attribute writer command.
     219    ///
     220    ///  Add a new attribute writer command.
     221    template <typename Writer, typename Value>
     222    GraphWriter& writeAttribute(std::string name, const Value& value,
     223                               const Writer& writer) {
     224      attribute_writer.writeAttribute<Writer>(name, value, writer);
     225      return *this;
     226    }
     227
     228    /// \brief Conversion operator to LemonWriter.
     229    ///
     230    /// Conversion operator to LemonWriter. It make possible
     231    /// to access the encapsulated \e LemonWriter, this way
     232    /// you can attach to this writer new instances of
     233    /// \e LemonWriter::SectionWriter.
     234    operator LemonWriter&() {
     235      return *writer;
    328236    }
    329237
     
    331239    ///
    332240    /// Executes the writer commands.
    333     void run() {   
    334       WriterBase<Node>* nodeWriter = 0;
    335       WriterBase<Edge>* edgeWriter = 0;
    336       writeNodeSet(nodeWriter);
    337       writeEdgeSet(nodeWriter, edgeWriter);
    338       writeNodes(nodeWriter);
    339       writeEdges(edgeWriter);
    340       writeGUI();
    341       os << "@end" << std::endl;
     241    void run() {
     242      writer->run();
    342243    }
    343244
    344245  private:
    345246
    346     template <class _Item>
    347     class WriterBase {
    348     public:
    349       typedef _Item Item;
    350       virtual void write(std::ostream&, const Item&) = 0;
    351     };
    352 
    353     template <class _Item, typename _Map, typename _Writer>
    354     class MapWriter : public WriterBase<_Item> {
    355     public:
    356       typedef _Map Map;
    357       typedef _Writer Writer;
    358       typedef typename Writer::Value Value;
    359       typedef _Item Item;
    360      
    361       const Map& map;
    362       Writer writer;
    363 
    364       MapWriter(const Map& _map, const Writer& _writer)
    365         : map(_map), writer(_writer) {}
    366 
    367 
    368       virtual void write(std::ostream& os, const Item& item) {
    369         writer.write(os, map[item]);
    370       }
    371 
    372     };
    373 
    374     void writeNodeSet(WriterBase<Node>* & nodeWriter) {
    375       if (node_map_writers.size() == 0) return;
    376       os << "@nodeset" << std::endl;
    377       for (int i = 0; i < (int)node_map_writers.size(); ++i) {
    378         const std::string& id = node_map_writers[i].first;
    379         os << id << '\t';
    380         if (WriterTraits::idMapName(id) && nodeWriter == 0) {
    381           nodeWriter = node_map_writers[i].second;
    382         }
    383       }
    384       os << std::endl;
    385       for (NodeIt it(graph); it != INVALID; ++it) {
    386         for (int i = 0; i < (int)node_map_writers.size(); ++i) {
    387           node_map_writers[i].second->write(os, it);
    388         }
    389         os << std::endl;
    390       }
    391 
    392     }
    393 
    394     void writeEdgeSet(WriterBase<Node>* nodeWriter,
    395                       WriterBase<Edge>* & edgeWriter) {
    396       if (edge_map_writers.size() == 0) return;
    397       if (nodeWriter == 0) {
    398         throw DataFormatError("Cannot find node id map");
    399       }
    400       os << "@edgeset" << std::endl;
    401       os << "\t\t";
    402       for (int i = 0; i < (int)edge_map_writers.size(); ++i) {
    403         const std::string& id = edge_map_writers[i].first;
    404         os << id << '\t';
    405         if (WriterTraits::idMapName(id) && edgeWriter == 0) {
    406           edgeWriter = edge_map_writers[i].second;
    407         }
    408       }
    409       os << std::endl;
    410       for (EdgeIt it(graph); it != INVALID; ++it) {
    411         nodeWriter->write(os, graph.source(it));
    412         nodeWriter->write(os, graph.target(it));
    413         for (int i = 0; i < (int)edge_map_writers.size(); ++i) {
    414           edge_map_writers[i].second->write(os, it);
    415         }
    416         os << std::endl;
    417       }
    418     }
    419 
    420     void writeNodes(WriterBase<Node>* nodeWriter) {
    421       if (node_writers.size() == 0) return;
    422       if (nodeWriter == 0) {
    423         throw DataFormatError("Cannot find node id map");
    424       }
    425       os << "@nodes" << std::endl;
    426       for (int i = 0; i < (int)node_writers.size(); ++i) {
    427         os << node_writers[i].first << '\t';
    428         nodeWriter->write(os, node_writers[i].second);
    429         os << std::endl;
    430       }
    431     }
    432 
    433     void writeEdges(WriterBase<Edge>* edgeWriter) {
    434       if (edge_writers.size() == 0) return;
    435       if (edgeWriter == 0) {
    436         throw DataFormatError("Cannot find node id map");
    437       }
    438       os << "@edges" << std::endl;
    439       for (int i = 0; i < (int)edge_writers.size(); ++i) {
    440         os << edge_writers[i].first << '\t';
    441         edgeWriter->write(os, edge_writers[i].second);
    442         os << std::endl;
    443       }
    444     }
     247    LemonWriter* writer;
     248    bool own_writer;
     249
     250    const Graph& graph;
     251
     252    NodeSetWriter<Graph, WriterTraits> nodeset_writer;
     253    EdgeSetWriter<Graph, WriterTraits> edgeset_writer;
     254
     255    NodeWriter<Graph> node_writer;
     256    EdgeWriter<Graph> edge_writer;
    445257   
    446     void writeGUI() {     
    447       if (gui_writer) {
    448         os << "@gui" << std::endl;
    449         gui_writer->write(os);
    450       }
    451     }
    452 
    453 
    454 
    455     typedef std::vector< std::pair<std::string, WriterBase<Node>*> >
    456       NodeMapWriters;
    457     NodeMapWriters node_map_writers;
    458 
    459     typedef std::vector< std::pair<std::string, WriterBase<Edge>*> >
    460       EdgeMapWriters;
    461     EdgeMapWriters edge_map_writers;
    462 
    463     typedef std::vector<std::pair<std::string, Node> > NodeWriters;
    464     NodeWriters node_writers;
    465 
    466     typedef std::vector<std::pair<std::string, Edge> > EdgeWriters;
    467     EdgeWriters edge_writers;
    468 
    469     GUIWriter* gui_writer;
    470 
    471     std::ostream& os;
    472     const Graph& graph;
    473 
     258    AttributeWriter<WriterTraits> attribute_writer;
    474259  };
     260
    475261
    476262  /// \brief Write a graph to the output.
  • src/lemon/lemon_reader.h

    r1408 r1409  
    3131
    3232#include <lemon/error.h>
    33 #include "item_reader.h"
     33#include <lemon/bits/item_reader.h>
    3434
    3535
    3636namespace lemon {
    3737
    38   /// \addtogroup io_group
    39   /// @{
    40 
     38  /// \ingroup io_group
    4139  /// \brief Lemon Format reader class.
    4240  ///
     41  /// The Lemon Format contains several sections. We do not want to
     42  /// determine what sections are in a lemon file we give only a framework
     43  /// to read a section oriented format.
     44  ///
     45  /// In the Lemon Format each section starts with a line contains a \c \@
     46  /// character on the first not white space position. This line is the
     47  /// header line of the section. Each next lines belong to this section
     48  /// while it does not starts with \c \@ character. This line can start a
     49  /// new section or if it can close the file with the \c \@end line.
     50  /// The file format ignore the empty lines and it may contain comments
     51  /// started with a \c # character to the end of the line.
     52  ///
     53  /// The framework provides an abstract LemonReader::SectionReader class
     54  /// what defines the interface of a SectionReader. The SectionReader
     55  /// has the \c header() member function what get a header line string and
     56  /// decides if it want to process the next section. Several SectionReaders
     57  /// can be attached to an LemonReader and the first attached what can
     58  /// process the section will be used. Its \c read() member will called
     59  /// with a stream contains the section. From this stream the empty lines
     60  /// and comments are filtered out.
     61  ///
     62  /// \relates GraphReader
     63  /// \relates NodeSetReader
     64  /// \relates EdgeSetReader
     65  /// \relates NodesReader
     66  /// \relates EdgesReader
     67  /// \relates AttributeReader
    4368  class LemonReader {
    4469  private:
     
    186211  public:
    187212
     213    /// \brief Abstract base class for reading a section.
     214    ///
     215    /// This class has an \c header() member function what get a
     216    /// header line string and decides if it want to process the next
     217    /// section. Several SectionReaders can be attached to an LemonReader
     218    /// and the first attached what can process the section will be used.
     219    /// Its \c read() member will called with a stream contains the section.
     220    /// From this stream the empty lines and comments are filtered out.
    188221    class SectionReader {
    189     public:
    190       /// \e
     222      friend class LemonReader;
     223    protected:
     224      /// \brief Constructor for SectionReader.
     225      ///
     226      /// Constructor for SectionReader. It attach this reader to
     227      /// the given LemonReader.
     228      SectionReader(LemonReader& reader) {
     229        reader.attach(*this);
     230      }
     231
     232      /// \brief Gives back true when the SectionReader can process
     233      /// the section with the given header line.
     234      ///
     235      /// It gives back true when the SectionReader can process
     236      /// the section with the given header line.
    191237      virtual bool header(const std::string& line) = 0;
    192       /// \e
     238
     239      /// \brief Reader function of the section.
     240      ///
     241      /// It reads the content of the section.
    193242      virtual void read(std::istream& is) = 0;
    194243    };
    195244
    196     /// \e
     245    /// \brief Constructor for LemonReader.
     246    ///
     247    /// Constructor for LemonReader which reads from the given stream.
    197248    LemonReader(std::istream& _is)
    198249      : is(&_is), own_is(false) {}
    199250
     251    /// \brief Constructor for LemonReader.
     252    ///
     253    /// Constructor for LemonReader which reads from the given file.
    200254    LemonReader(const std::string& filename)
    201255      : is(0), own_is(true) {
     
    203257    }
    204258
    205 
     259    /// \brief Desctructor for LemonReader.
     260    ///
     261    /// Desctructor for LemonReader.
    206262    ~LemonReader() {
    207263      if (own_is) {
     
    214270    void operator=(const LemonReader&);
    215271
    216   public:
    217    
    218     /// \e
    219272    void attach(SectionReader& reader) {
    220273      readers.push_back(&reader);
    221274    }
    222275
    223     /// \e
    224     void detach(SectionReader& reader) {
    225       std::vector<SectionReader*>::iterator it =
    226         std::find(readers.begin(), readers.end(), &reader);
    227       if (it != readers.end()) {
    228         readers.erase(it);
    229       }
    230     }
    231 
    232     /// \e
     276  public:
     277    /// \brief Executes the LemonReader.
     278    ///
     279    /// It executes the LemonReader.
    233280    void run() {
    234281      int line_num = 0;
     
    265312  };
    266313
    267 
    268   /// \e
     314  /// \brief Helper class for implementing the common SectionReaders.
     315  ///
     316  /// Helper class for implementing the common SectionReaders.
    269317  class CommonSectionReaderBase : public LemonReader::SectionReader {
     318    typedef LemonReader::SectionReader Parent;
    270319  protected:
     320   
     321    /// \brief Constructor for CommonSectionReaderBase.
     322    ///
     323    /// Constructor for CommonSectionReaderBase. It attach this reader to
     324    /// the given LemonReader.
     325    CommonSectionReaderBase(LemonReader& _reader)
     326      : Parent(_reader) {}
     327
    271328    template <typename _Item>
    272329    class ReaderBase;
     
    434491
    435492    template <typename _Item>
    436     class ResolverReaderBase {
     493    class IdReaderBase {
    437494    public:
    438495      typedef _Item Item;
    439       virtual Item resolve(std::istream& is) const = 0;
     496      virtual Item read(std::istream& is) const = 0;
    440497    };
    441498
    442     template <typename _Item, typename _Resolver>
    443     class ResolverReader : public ResolverReaderBase<_Item> {
     499    template <typename _Item, typename _BoxedIdReader>
     500    class IdReader : public IdReaderBase<_Item> {
    444501    public:
    445502      typedef _Item Item;
    446       typedef _Resolver Resolver;
    447 
    448       const Resolver& resolver;
    449 
    450       ResolverReader(const Resolver& _resolver)
    451         : resolver(_resolver) {}
    452 
    453       virtual Item resolve(std::istream& is) const {
    454         return resolver.resolve(is);
     503      typedef _BoxedIdReader BoxedIdReader;
     504     
     505      const BoxedIdReader& boxedIdReader;
     506
     507      IdReader(const BoxedIdReader& _boxedIdReader)
     508        : boxedIdReader(_boxedIdReader) {}
     509
     510      virtual Item read(std::istream& is) const {
     511        return boxedIdReader.readId(is);
    455512      }
    456513    };
     
    480537  };
    481538
    482 
     539  /// \ingroup io_group
     540  /// \brief SectionReader for reading a graph's nodeset.
     541  ///
     542  /// The lemon format can store multiple graph nodesets with several maps.
     543  /// The nodeset section's header line is \c \@nodeset \c nodeset_id, but the
     544  /// \c nodeset_id may be empty.
     545  ///
     546  /// The first line of the section contains the names of the maps separated
     547  /// with white spaces. Each next lines describes a node in the nodeset, and
     548  /// contains the mapped values for each map.
     549  ///
     550  /// If the nodeset contains an \c "id" named map then it will be regarded
     551  /// as id map. This map should contain only unique values and when the
     552  /// \c readId() member will read a value from the given stream it will
     553  /// give back that node which is mapped to this value.
     554  ///
     555  /// \relates LemonReader
    483556  template <typename _Graph, typename _Traits = DefaultReaderTraits>
    484557  class NodeSetReader : public CommonSectionReaderBase {
     
    491564    typedef typename Traits::Skipper DefaultSkipper;
    492565
     566    /// \brief Constructor.
     567    ///
     568    /// Constructor for NodeSetReader. It creates the NodeSetReader and
     569    /// attach it into the given LemonReader. The nodeset reader will
     570    /// add the readed nodes to the given Graph. The reader will read
     571    /// the section when the \c section_id and the \c _id are the same.
    493572    NodeSetReader(LemonReader& _reader, Graph& _graph,
    494573                  const std::string& _id = std::string(),
    495                   const DefaultSkipper& _defreader = DefaultSkipper())
    496       : graph(_graph), id(_id), skipper(_defreader) {
    497       _reader.attach(*this);
    498     }
    499 
     574                  const DefaultSkipper& _skipper = DefaultSkipper())
     575      : Parent(_reader), graph(_graph), id(_id), skipper(_skipper) {}
     576
     577
     578    /// \brief Destructor.
     579    ///
     580    /// Destructor for NodeSetReader.
    500581    virtual ~NodeSetReader() {
    501582      for (typename MapReaders::iterator it = readers.begin();
     
    551632    }
    552633
    553     /// \e
     634  protected:
     635
     636    /// \brief Gives back true when the SectionReader can process
     637    /// the section with the given header line.
     638    ///
     639    /// It gives back true when the header line starts with \c @nodeset,
     640    /// and the header line's id and the nodeset's id are the same.
    554641    virtual bool header(const std::string& line) {
    555642      std::istringstream ls(line);
     
    560647    }
    561648
    562     /// \e
     649    /// \brief Reader function of the section.
     650    ///
     651    /// It reads the content of the section.
    563652    virtual void read(std::istream& is) {
    564653      std::vector<ReaderBase<Item>* > index;
     
    588677    }
    589678
    590     bool isResolver() const {
     679  public:
     680
     681    /// \brief Returns true if the nodeset can give back the node by its id.
     682    ///
     683    /// Returns true if the nodeset can give back the node by its id.
     684    /// It is possible only if an "id" named map was read.
     685    bool isIdReader() const {
    591686      return inverter.get() != 0;
    592687    }
    593688
    594     typename Graph::Node resolve(std::istream& is) const {
     689    /// \brief Gives back the node by its id.
     690    ///
     691    /// It reads an id from the stream and gives back which node belongs to
     692    /// it. It is possible only if there was read an "id" named map.
     693    typename Graph::Node readId(std::istream& is) const {
    595694      return inverter->read(is);
    596695    }
     
    608707  };
    609708
    610 
    611  
    612   /// \e
     709  /// \ingroup io_group
     710  /// \brief SectionReader for reading a graph's edgeset.
     711  ///
     712  /// The lemon format can store multiple graph edgesets with several maps.
     713  /// The edgeset section's header line is \c \@edgeset \c edgeset_id, but the
     714  /// \c edgeset_id may be empty.
     715  ///
     716  /// The first line of the section contains the names of the maps separated
     717  /// with white spaces. Each next lines describes a node in the nodeset. The
     718  /// line contains the two nodes' id and the mapped values for each map.
     719  ///
     720  /// If the edgeset contains an \c "id" named map then it will be regarded
     721  /// as id map. This map should contain only unique values and when the
     722  /// \c readId() member will read a value from the given stream it will
     723  /// give back that edge which is mapped to this value.
     724  ///
     725  /// The edgeset reader needs a node id reader to identify which nodes
     726  /// have to be connected. If a NodeSetReader reads an "id" named map,
     727  /// it will be able to resolve the nodes by ids.
     728  ///
     729  /// \relates LemonReader
    613730  template <typename _Graph, typename _Traits = DefaultReaderTraits>
    614731  class EdgeSetReader : public CommonSectionReaderBase {
     
    621738    typedef typename Traits::Skipper DefaultSkipper;
    622739
    623     template <typename Resolver>
     740    /// \brief Constructor.
     741    ///
     742    /// Constructor for EdgeSetReader. It creates the EdgeSetReader and
     743    /// attach it into the given LemonReader. The edgeset reader will
     744    /// add the readed edges to the given Graph. It will use the given
     745    /// node id reader to read the source and target nodes of the edges.
     746    /// The reader will read the section only if the \c _id and the
     747    /// \c edgset_id are the same.
     748    template <typename NodeIdReader>
    624749    EdgeSetReader(LemonReader& _reader, Graph& _graph,
    625                   const Resolver& _nodeResolver,
     750                  const NodeIdReader& _nodeIdReader,
    626751                  const std::string& _id = std::string(),
    627                   const DefaultSkipper& _defreader = DefaultSkipper())
    628       : graph(_graph), id(_id), skipper(_defreader),
    629       nodeResolver(new ResolverReader<typename Graph::Node, Resolver>
    630                    (_nodeResolver)) {
    631       _reader.attach(*this);
    632     }
    633 
     752                  const DefaultSkipper& _skipper = DefaultSkipper())
     753      : Parent(_reader), graph(_graph), id(_id), skipper(_skipper),
     754        nodeIdReader(new IdReader<typename Graph::Node, NodeIdReader>
     755                     (_nodeIdReader)) {}
     756
     757    /// \brief Destructor.
     758    ///
     759    /// Destructor for EdgeSetReader.
    634760    virtual ~EdgeSetReader() {
    635761      for (typename MapReaders::iterator it = readers.begin();
     
    645771  public:
    646772
    647     /// \brief Add a new node map reader command for the reader.
    648     ///
    649     /// Add a new node map reader command for the reader.
     773    /// \brief Add a new edge map reader command for the reader.
     774    ///
     775    /// Add a new edge map reader command for the reader.
    650776    template <typename Map>
    651777    EdgeSetReader& readMap(std::string name, Map& map) {
     
    654780    }
    655781
    656     /// \brief Add a new node map reader command for the reader.
    657     ///
    658     /// Add a new node map reader command for the reader.
     782    /// \brief Add a new edge map reader command for the reader.
     783    ///
     784    /// Add a new edge map reader command for the reader.
    659785    template <typename Reader, typename Map>
    660786    EdgeSetReader& readMap(std::string name, Map& map,
     
    670796    }
    671797
    672     /// \brief Add a new node map skipper command for the reader.
    673     ///
    674     /// Add a new node map skipper command for the reader.
     798    /// \brief Add a new edge map skipper command for the reader.
     799    ///
     800    /// Add a new edge map skipper command for the reader.
    675801    template <typename Reader>
    676802    EdgeSetReader& skipMap(std::string name,
     
    685811    }
    686812
    687     /// \e
     813  protected:
     814
     815    /// \brief Gives back true when the SectionReader can process
     816    /// the section with the given header line.
     817    ///
     818    /// It gives back true when the header line starts with \c @edgeset,
     819    /// and the header line's id and the edgeset's id are the same.
    688820    virtual bool header(const std::string& line) {
    689821      std::istringstream ls(line);
     
    694826    }
    695827
    696     /// \e
     828    /// \brief Reader function of the section.
     829    ///
     830    /// It reads the content of the section.
    697831    virtual void read(std::istream& is) {
    698832      std::vector<ReaderBase<Item>* > index;
     
    715849      while (getline(is, line)) {       
    716850        std::istringstream ls(line);
    717         typename Graph::Node from = nodeResolver->resolve(ls);
    718         typename Graph::Node to = nodeResolver->resolve(ls);
     851        typename Graph::Node from = nodeIdReader->read(ls);
     852        typename Graph::Node to = nodeIdReader->read(ls);
    719853        typename Graph::Edge edge = graph.addEdge(from, to);
    720854        for (int i = 0; i < (int)index.size(); ++i) {
     
    724858    }
    725859
    726     bool isResolver() const {
     860  public:
     861
     862    /// \brief Returns true if the edgeset can give back the edge by its id.
     863    ///
     864    /// Returns true if the edgeset can give back the edge by its id.
     865    /// It is possible only if an "id" named map was read.
     866    bool isIdReader() const {
    727867      return inverter.get() != 0;
    728868    }
    729869
    730     typename Graph::Edge resolve(std::istream& is) {
     870    /// \brief Gives back the edge by its id.
     871    ///
     872    /// It reads an id from the stream and gives back which edge belongs to
     873    /// it. It is possible only if there was read an "id" named map.
     874    typename Graph::Edge readId(std::istream& is) const {
    731875      return inverter->read(is);
    732876    }
     
    742886
    743887    std::auto_ptr<InverterBase<Item> > inverter;
    744     std::auto_ptr<ResolverReaderBase<typename Graph::Node> > nodeResolver;
     888    std::auto_ptr<IdReaderBase<typename Graph::Node> > nodeIdReader;
    745889  };
    746890
    747 
    748   /// \e
     891  /// \ingroup io_group
     892  /// \brief SectionReader for reading labeled nodes.
     893  ///
     894  /// The nodes section's header line is \c \@nodes \c nodes_id, but the
     895  /// \c nodes_id may be empty.
     896  ///
     897  /// Each line in the section contains the name of the node
     898  /// and then the node id.
     899  ///
     900  /// \relates LemonReader
     901  template <typename _Graph>
     902  class NodeReader : public CommonSectionReaderBase {
     903    typedef CommonSectionReaderBase Parent;
     904    typedef _Graph Graph;
     905    typedef typename Graph::Node Item;
     906  public:
     907   
     908    /// \brief Constructor.
     909    ///
     910    /// Constructor for NodeReader. It creates the NodeReader and
     911    /// attach it into the given LemonReader. It will use the given
     912    /// node id reader to give back the nodes. The reader will read the
     913    /// section only if the \c _id and the \c nodes_id are the same.
     914    template <typename _IdReader>
     915    NodeReader(LemonReader& _reader, const _IdReader& _idReader,
     916               const std::string& _id = std::string())
     917      : Parent(_reader), id(_id),
     918        idReader(new IdReader<typename Graph::Node, _IdReader>(_idReader)) {}
     919
     920    /// \brief Destructor.
     921    ///
     922    /// Destructor for NodeReader.
     923    virtual ~NodeReader() {}
     924
     925  private:
     926    NodeReader(const NodeReader&);
     927    void operator=(const NodeReader&);
     928
     929  public:
     930
     931    /// \brief Add a node reader command for the NodeReader.
     932    ///
     933    /// Add a node reader command for the NodeReader.
     934    void readNode(const std::string& name, Item& item) {
     935      if (readers.find(name) != readers.end()) {
     936        ErrorMessage msg;
     937        msg << "Multiple read rule for node: " << name;
     938        throw IOParameterError(msg.message());
     939      }
     940      readers.insert(make_pair(name, &item));
     941    }
     942
     943  protected:
     944
     945    /// \brief Gives back true when the SectionReader can process
     946    /// the section with the given header line.
     947    ///
     948    /// It gives back true when the header line start with \c @nodes,
     949    /// and the header line's id and the reader's id are the same.
     950    virtual bool header(const std::string& line) {
     951      std::istringstream ls(line);
     952      std::string command;
     953      std::string name;
     954      ls >> command >> name;
     955      return command == "@nodes" && name == id;
     956    }
     957
     958    /// \brief Reader function of the section.
     959    ///
     960    /// It reads the content of the section.
     961    virtual void read(std::istream& is) {
     962      std::string line;
     963      while (getline(is, line)) {
     964        std::istringstream ls(line);
     965        std::string id;
     966        ls >> id;
     967        typename ItemReaders::iterator it = readers.find(id);
     968        if (it != readers.end()) {
     969          *(it->second) = idReader->read(ls);
     970        }       
     971      }
     972    }
     973   
     974  private:
     975
     976    std::string id;
     977
     978    typedef std::map<std::string, Item*> ItemReaders;
     979    ItemReaders readers;
     980    std::auto_ptr<IdReaderBase<Item> > idReader;
     981  };
     982
     983  /// \ingroup io_group
     984  /// \brief SectionReader for reading labeled edges.
     985  ///
     986  /// The edges section's header line is \c \@edges \c edges_id, but the
     987  /// \c edges_id may be empty.
     988  ///
     989  /// Each line in the section contains the name of the edge
     990  /// and then the edge id.
     991  ///
     992  /// \relates LemonReader
     993  template <typename _Graph>
     994  class EdgeReader : public CommonSectionReaderBase {
     995    typedef CommonSectionReaderBase Parent;
     996    typedef _Graph Graph;
     997    typedef typename Graph::Edge Item;
     998  public:
     999   
     1000    /// \brief Constructor.
     1001    ///
     1002    /// Constructor for EdgeReader. It creates the EdgeReader and
     1003    /// attach it into the given LemonReader. It will use the given
     1004    /// edge id reader to give back the edges. The reader will read the
     1005    /// section only if the \c _id and the \c nodes_id are the same.
     1006    template <typename _IdReader>
     1007    EdgeReader(LemonReader& _reader, const _IdReader& _idReader,
     1008               const std::string& _id = std::string())
     1009      : Parent(_reader), id(_id),
     1010        idReader(new IdReader<typename Graph::Edge, _IdReader>(_idReader)) {}
     1011
     1012    /// \brief Destructor.
     1013    ///
     1014    /// Destructor for EdgeReader.
     1015    virtual ~EdgeReader() {}
     1016  private:
     1017    EdgeReader(const EdgeReader&);
     1018    void operator=(const EdgeReader&);
     1019
     1020  public:
     1021
     1022    /// \brief Add an edge reader command for the EdgeReader.
     1023    ///
     1024    /// Add an edge reader command for the EdgeReader.
     1025    void readEdge(const std::string& name, Item& item) {
     1026      if (readers.find(name) != readers.end()) {
     1027        ErrorMessage msg;
     1028        msg << "Multiple read rule for edge: " << name;
     1029        throw IOParameterError(msg.message());
     1030      }
     1031      readers.insert(make_pair(name, &item));
     1032    }
     1033
     1034  protected:
     1035
     1036    /// \brief Gives back true when the SectionReader can process
     1037    /// the section with the given header line.
     1038    ///
     1039    /// It gives back true when the header line start with \c @edges,
     1040    /// and the header line's id and the reader's id are the same.
     1041    virtual bool header(const std::string& line) {
     1042      std::istringstream ls(line);
     1043      std::string command;
     1044      std::string name;
     1045      ls >> command >> name;
     1046      return command == "@edges" && name == id;
     1047    }
     1048
     1049    /// \brief Reader function of the section.
     1050    ///
     1051    /// It reads the content of the section.
     1052    virtual void read(std::istream& is) {
     1053      std::string line;
     1054      while (getline(is, line)) {
     1055        std::istringstream ls(line);
     1056        std::string id;
     1057        ls >> id;
     1058        typename ItemReaders::iterator it = readers.find(id);
     1059        if (it != readers.end()) {
     1060          *(it->second) = idReader->read(ls);
     1061        }       
     1062      }
     1063    }
     1064   
     1065  private:
     1066
     1067    std::string id;
     1068
     1069    typedef std::map<std::string, Item*> ItemReaders;
     1070    ItemReaders readers;
     1071    std::auto_ptr<IdReaderBase<Item> > idReader;
     1072  };
     1073
     1074  /// \ingroup io_group
     1075  /// \brief SectionReader for attributes.
     1076  ///
     1077  /// The lemon format can store multiple attribute set. Each set has
     1078  /// the header line \c \@attributes \c attributeset_id, but the
     1079  /// attributeset_id may be empty.
     1080  ///
     1081  /// The attributeset section contains several lines. Each of them starts
     1082  /// with an attribute and then a the value for the id.
     1083  ///
     1084  /// \relates LemonReader
    7491085  template <typename _Traits = DefaultReaderTraits>
    7501086  class AttributeReader : public CommonSectionReaderBase {
     
    7521088    typedef _Traits Traits;
    7531089  public:
    754     /// \e
     1090    /// \brief Constructor.
     1091    ///
     1092    /// Constructor for AttributeReader. It creates the AttributeReader and
     1093    /// attach it into the given LemonReader. The reader process a section
     1094    /// only if the \c section_id and the \c _id are the same.
    7551095    AttributeReader(LemonReader& _reader,
    756                     const std::string& _id = std::string()) : id(_id) {
    757       _reader.attach(*this);
    758     }
    759 
    760     /// \e
     1096                    const std::string& _id = std::string())
     1097      : Parent(_reader), id(_id) {}
     1098
     1099    /// \brief Destructor.
     1100    ///
     1101    /// Destructor for AttributeReader.
    7611102    virtual ~AttributeReader() {
    7621103      for (typename Readers::iterator it = readers.begin();
     
    7711112
    7721113  public:
    773     /// \e
     1114    /// \brief Add an attribute reader command for the reader.
     1115    ///
     1116    /// Add an attribute reader command for the reader.
    7741117    template <typename Value>
    7751118    AttributeReader& readAttribute(const std::string& id, Value& value) {
     
    7781121    }
    7791122
    780     /// \e
     1123    /// \brief Add an attribute reader command for the reader.
     1124    ///
     1125    /// Add an attribute reader command for the reader.
    7811126    template <typename Reader, typename Value>
    7821127    AttributeReader& readAttribute(const std::string& name, Value& value,
     
    7921137    }
    7931138
    794     /// \e
     1139  protected:
     1140
     1141    /// \brief Gives back true when the SectionReader can process
     1142    /// the section with the given header line.
     1143    ///
     1144    /// It gives back true when the header line start with \c @attributes,
     1145    /// and the header line's id and the attributeset's id are the same.
    7951146    bool header(const std::string& line) {
    7961147      std::istringstream ls(line);
     
    8011152    }
    8021153
    803     /// \e
     1154    /// \brief Reader function of the section.
     1155    ///
     1156    /// It reads the content of the section.
    8041157    void read(std::istream& is) {
    8051158      std::string line;
     
    8191172
    8201173    typedef std::map<std::string, ValueReaderBase*> Readers;
    821     Readers readers;
    822  
     1174    Readers readers; 
    8231175  };
    8241176
    825   template <typename _Graph>
    826   class NodeReader : public CommonSectionReaderBase {
    827     typedef CommonSectionReaderBase Parent;
    828     typedef _Graph Graph;
    829     typedef typename Graph::Node Item;
    830   public:
    831    
    832     template <typename Resolver>
    833     NodeReader(LemonReader& _reader, const Resolver& _resolver,
    834                const std::string& _id = std::string())
    835       : id(_id), resolver(new ResolverReader<typename Graph::Node, Resolver>
    836                      (_resolver)) {
    837       _reader.attach(*this);
    838     }
    839 
    840     virtual ~NodeReader() {}
    841 
    842   private:
    843     NodeReader(const NodeReader&);
    844     void operator=(const NodeReader&);
    845 
    846   public:
    847 
    848     void readNode(const std::string& name, Item& item) {
    849       if (readers.find(name) != readers.end()) {
    850         ErrorMessage msg;
    851         msg << "Multiple read rule for node: " << name;
    852         throw IOParameterError(msg.message());
    853       }
    854       readers.insert(make_pair(name, &item));
    855     }
    856 
    857     virtual bool header(const std::string& line) {
    858       std::istringstream ls(line);
    859       std::string command;
    860       std::string name;
    861       ls >> command >> name;
    862       return command == "@nodes" && name == id;
    863     }
    864 
    865     virtual void read(std::istream& is) {
    866       std::string line;
    867       while (getline(is, line)) {
    868         std::istringstream ls(line);
    869         std::string id;
    870         ls >> id;
    871         typename ItemReaders::iterator it = readers.find(id);
    872         if (it != readers.end()) {
    873           *(it->second) = resolver->resolve(ls);
    874         }       
    875       }
    876     }
    877    
    878   private:
    879 
    880     std::string id;
    881 
    882     typedef std::map<std::string, Item*> ItemReaders;
    883     ItemReaders readers;
    884     std::auto_ptr<ResolverReaderBase<Item> > resolver;
    885   };
    886 
    887   template <typename _Graph>
    888   class EdgeReader : public CommonSectionReaderBase {
    889     typedef CommonSectionReaderBase Parent;
    890     typedef _Graph Graph;
    891     typedef typename Graph::Edge Item;
    892   public:
    893    
    894     template <typename Resolver>
    895     EdgeReader(LemonReader& _reader, const Resolver& _resolver,
    896                const std::string& _id = std::string())
    897       : id(_id), resolver(new ResolverReader<typename Graph::Node, Resolver>
    898                      (_resolver)) {
    899       _reader.attach(*this);
    900     }
    901 
    902     virtual ~EdgeReader() {}
    903   private:
    904     EdgeReader(const EdgeReader&);
    905     void operator=(const EdgeReader&);
    906 
    907   public:
    908 
    909     void readEdge(const std::string& name, Item& item) {
    910       if (readers.find(name) != readers.end()) {
    911         ErrorMessage msg;
    912         msg << "Multiple read rule for edge: " << name;
    913         throw IOParameterError(msg.message());
    914       }
    915       readers.insert(make_pair(name, &item));
    916     }
    917 
    918 
    919     virtual bool header(const std::string& line) {
    920       std::istringstream ls(line);
    921       std::string command;
    922       std::string name;
    923       ls >> command >> name;
    924       return command == "@nodes" && name == id;
    925     }
    926 
    927     virtual void read(std::istream& is) {
    928       std::string line;
    929       while (getline(is, line)) {
    930         std::istringstream ls(line);
    931         std::string id;
    932         ls >> id;
    933         typename ItemReaders::iterator it = readers.find(id);
    934         if (it != readers.end()) {
    935           *(it->second) = resolver->resolve(ls);
    936         }       
    937       }
    938     }
    939    
    940   private:
    941 
    942     std::string id;
    943 
    944     typedef std::map<std::string, Item*> ItemReaders;
    945     ItemReaders readers;
    946     std::auto_ptr<ResolverReaderBase<Item> > resolver;
    947   };
    948 
    949   /// \e
    950   class PrintReader : public LemonReader::SectionReader {
    951     typedef LemonReader::SectionReader Parent;
    952   public:
    953 
    954     /// \e
    955     PrintReader(LemonReader& reader) {
    956       reader.attach(*this);
    957     }
    958 
    959     /// \e
    960     bool header(const std::string& line) {
    961       std::cout << "Asked header: " << line << std::endl;
    962       return true;
    963     }
    964 
    965     /// \e
    966     void read(std::istream& is) {
    967       std::string line;
    968       while (std::getline(is, line)) {
    969         std::cout << line << std::endl;
    970       }
    971     }
    972  
    973   };
    974 
    975   /// @}
     1177
    9761178}
    9771179#endif
Note: See TracChangeset for help on using the changeset viewer.