COIN-OR::LEMON - Graph Library

source: lemon-0.x/src/work/deba/graph_reader.h @ 1133:9fd485470fee

Last change on this file since 1133:9fd485470fee was 1133:9fd485470fee, checked in by Balazs Dezso, 19 years ago

Documentation

File size: 18.1 KB
RevLine 
[1032]1/* -*- C++ -*-
2 * src/lemon/graph_reader.h - Part of LEMON, a generic C++ optimization library
3 *
4 * Copyright (C) 2004 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
5 * (Egervary Combinatorial Optimization Research Group, EGRES).
6 *
7 * Permission to use, modify and distribute this software is granted
8 * provided that this copyright notice appears in all copies. For
9 * precise terms see the accompanying LICENSE file.
10 *
11 * This software is provided "AS IS" with no warranty of any kind,
12 * express or implied, and with no claim as to its suitability for any
13 * purpose.
14 *
15 */
16
17///\ingroup gio
18///\file
[1036]19///\brief Graph reader.
[1032]20
21#include <iostream>
22#include <sstream>
23
24#include <map>
25#include <vector>
26
[1037]27#include <memory>
28
[1032]29#include <lemon/error.h>
30
31/// \todo fix exceptions
32
33
34namespace lemon {
[1036]35
36  // Exceptions
37
38  class IOException {
39  public:
[1115]40    virtual ~IOException() {}
[1036]41    virtual string what() const = 0;
42  };
43
44  class DataFormatException : public IOException {
45    std::string message;
46  public:
47    DataFormatException(const std::string& _message)
48      : message(_message) {}
49    std::string what() const {
50      return "DataFormatException: " + message;
51    }
52  };
53
[1037]54  template <typename _Exception>
55  class StreamException : public _Exception {
[1036]56  public:
[1037]57    typedef _Exception Exception;
58    StreamException(int _line, Exception _exception)
[1115]59      : Exception(_exception), line_num(_line) {}
[1037]60    virtual int line() const {
61      return line_num;
62    }
[1115]63
64    virtual ~StreamException() {}
65
[1037]66    virtual std::string what() const {
67      ostringstream os;
68      os << Exception::what() << " in line " << line();
69      return os.str();
70    }
[1036]71  private:
72    int line_num;
73  }; 
74
75
[1115]76  /// \brief Standard ReaderTraits for the GraphReader class.
77  ///
[1133]78  /// Standard ReaderTraits for the GraphReader class.
79  /// It defines standard reading method for all type of value.
[1032]80  struct DefaultReaderTraits {
81
[1133]82    /// \brief Template class for reading an value.
83    ///
84    /// Template class for reading an value.
[1032]85    template <typename _Value>
86    struct Reader {
[1133]87      /// The value type.
[1032]88      typedef _Value Value;
[1133]89      /// \brief Reads a value from the given stream.
90      ///
91      /// Reads a value from the given stream.
[1032]92      void read(std::istream& is, Value& value) {
[1036]93        if (!(is >> value))
94          throw DataFormatException("Default Reader format exception");
[1032]95      }
96    };
97
[1133]98    /// The reader class for the not needed maps.
[1036]99    typedef Reader<std::string> DefaultReader;
[1032]100
101  };
102
[1133]103  /// \brief Reader class for quoted strings.
104  ///
105  /// Reader class for quoted strings. It can process the escape
106  /// sequences in the string.
[1036]107  class QuotedStringReader {
108  public:
109    typedef std::string Value;
[1133]110   
111    /// \brief Constructor for the reader.
112    ///
113    /// Constructor for the reader. If the given parameter is true
114    /// the reader processes the escape sequences.
[1036]115    QuotedStringReader(bool _escaped = true) : escaped(_escaped) {}
[1133]116   
117    /// \brief Reads a quoted string from the given stream.
118    ///
119    /// Reads a quoted string from the given stream.
[1036]120    void read(std::istream& is, std::string& value) {
121      char c;
122      value.clear();
123      is >> ws;
[1115]124      if (!is.get(c) || c != '\"')
125        throw DataFormatException("Quoted string format");
[1036]126      while (is.get(c) && c != '\"') {
127        if (escaped && c == '\\') {
128          value += readEscape(is);
129        } else {
130          value += c;
131        }
132      }
[1037]133      if (!is) throw DataFormatException("Quoted string format");
[1036]134    }
135
136  private:
137   
138    static char readEscape(std::istream& is) {
139      char c;
140      switch (is.get(c), c) {
141      case '\\':
142        return '\\';
143      case '\"':
144        return '\"';
145      case '\'':
146        return '\'';
147      case '\?':
148        return '\?';
149      case 'a':
150        return '\a';
151      case 'b':
152        return '\b';
153      case 'f':
154        return '\f';
155      case 'n':
156        return '\n';
157      case 'r':
158        return '\r';
159      case 't':
160        return '\t';
161      case 'v':
162        return '\v';
163      case 'x':
164        {
165          int code;
[1133]166          if (!is.get(c) || !isHex(c))
167            throw DataFormatException("Escape format exception");
[1036]168          else if (code = valueHex(c), !is.get(c) || !isHex(c)) is.putback(c);
169          else code = code * 16 + valueHex(c);
170          return code;
171        }
172      default:
173        {
174          int code;
[1133]175          if (!isOct(c))
176            throw DataFormatException("Escape format exception");
177          else if (code = valueOct(c), !is.get(c) || !isOct(c))
178            is.putback(c);
179          else if (code = code * 8 + valueOct(c), !is.get(c) || !isOct(c))
180            is.putback(c);
[1036]181          else code = code * 8 + valueOct(c);
182          return code;
183        }             
184      }
185    }
186
187    static bool isOct(char c) {
188      return '0' <= c && c <='7';
189    }
190   
191    static int valueOct(char c) {
192      return c - '0';
193    }
194
195   static bool isHex(char c) {
[1133]196      return ('0' <= c && c <= '9') ||
197        ('a' <= c && c <= 'z') ||
198        ('A' <= c && c <= 'Z');
[1036]199    }
200   
201    static int valueHex(char c) {
202      if ('0' <= c && c <= '9') return c - '0';
203      if ('a' <= c && c <= 'z') return c - 'a' + 10;
204      return c - 'A' + 10;
205    }
206
207    bool escaped;
[1032]208  };
209
[1133]210  /// \brief The graph reader class.
211  ///
212  /// The reader class for the graph input.
213  /// \see graph-io-page
[1032]214  template <typename _Graph, typename _ReaderTraits = DefaultReaderTraits>
215  class GraphReader {
216  public:
217   
218    typedef _Graph Graph;
219    typedef typename Graph::Node Node;
220    typedef typename Graph::Edge Edge;
221
222    typedef _ReaderTraits ReaderTraits;
[1036]223    typedef typename ReaderTraits::DefaultReader DefaultReader;
[1032]224
[1133]225    /// \brief Construct a new GraphReader.
226    ///
227    /// Construct a new GraphReader. It reads from the given map,
228    /// it constructs the given map and it use the given reader as the
229    /// default skipper.
[1115]230    GraphReader(std::istream& _is, Graph& _graph,
231                const DefaultReader& _reader = DefaultReader())
[1036]232      : is(_is), graph(_graph), nodeSkipper(_reader), edgeSkipper(_reader) {}
233
[1133]234    /// \brief Destruct the graph reader.
235    ///
236    /// Destruct the graph reader.
[1036]237    ~GraphReader() {
238
[1115]239      for (typename NodeMapReaders::iterator it = node_map_readers.begin();
240           it != node_map_readers.end(); ++it) {
[1036]241        delete it->second;
242      }
243
[1115]244      for (typename EdgeMapReaders::iterator it = edge_map_readers.begin();
245           it != edge_map_readers.end(); ++it) {
[1036]246        delete it->second;
247      }
248
249    }
[1032]250
[1133]251    /// \brief Add a new node map reader command for the reader.
252    ///
253    /// Add a new node map reader command for the reader.
[1032]254    template <typename Map>
[1115]255    GraphReader& addNodeMap(std::string name, Map& map) {
256      return addNodeMap<typename ReaderTraits::template
257        Reader<typename Map::Value>, Map>(name, map);
[1032]258    }
259
[1133]260    /// \brief Add a new node map reader command for the reader.
261    ///
262    /// Add a new node map reader command for the reader.
[1036]263    template <typename Reader, typename Map>
[1115]264    GraphReader& addNodeMap(std::string name, Map& map,
265                             const Reader& reader = Reader()) {
[1037]266      if (node_map_readers.find(name) != node_map_readers.end()) {
267        throw Exception() << "Multiple read rule for node map: " << name;
[1036]268      }
[1115]269      node_map_readers.insert(
270        make_pair(name, new MapReader<Node, Map, Reader>(map, reader)));
[1032]271      return *this;
272    }
273
[1133]274    /// \brief Add a new node map skipper command for the reader.
275    ///
276    /// Add a new node map skipper command for the reader.
[1036]277    template <typename Reader>
[1115]278    GraphReader& skipNodeMap(std::string name,
279                             const Reader& reader = Reader()) {
[1037]280      if (node_map_readers.find(name) != node_map_readers.end()) {
281        throw Exception() << "Multiple read rule for node map: " << name;
[1036]282      }
[1115]283      node_map_readers.insert(
284        make_pair(name, new SkipReader<Node, Reader>(reader)));
[1036]285      return *this;
[1032]286    }
287
[1133]288    /// \brief Add a new edge map reader command for the reader.
289    ///
290    /// Add a new edge map reader command for the reader.
[1036]291    template <typename Map>
[1115]292    GraphReader& addEdgeMap(std::string name, Map& map) {
293      return addEdgeMap<typename ReaderTraits::template
294        Reader<typename Map::Value>, Map>(name, map);
[1036]295    }
296
297
[1133]298    /// \brief Add a new edge map reader command for the reader.
299    ///
300    /// Add a new edge map reader command for the reader.
[1036]301    template <typename Reader, typename Map>
[1115]302    GraphReader& addEdgeMap(std::string name, Map& map,
303                             const Reader& reader = Reader()) {
[1037]304      if (edge_map_readers.find(name) != edge_map_readers.end()) {
305        throw Exception() << "Multiple read rule for edge map: " << name;
[1036]306      }
[1115]307      edge_map_readers.insert(
308        make_pair(name, new MapReader<Edge, Map, Reader>(map, reader)));
[1032]309      return *this;
310    }
311
[1133]312    /// \brief Add a new edge map skipper command for the reader.
313    ///
314    /// Add a new edge map skipper command for the reader.
[1036]315    template <typename Reader>
[1115]316    GraphReader& skipEdgeMap(std::string name,
317                             const Reader& reader = Reader()) {
[1037]318      if (edge_map_readers.find(name) != edge_map_readers.end()) {
319        throw Exception() << "Multiple read rule for edge map: " << name;
320      }
[1115]321      edge_map_readers.insert(
322        make_pair(name, new SkipReader<Edge, Reader>(reader)));
[1037]323      return *this;
324    }
325
[1133]326    /// \brief Add a new labeled node reader for the reader.
327    ///
328    /// Add a new labeled node reader for the reader.
[1115]329    GraphReader& addNode(std::string name, Node& node) {
[1037]330      if (node_readers.find(name) != node_readers.end()) {
331        throw Exception() << "Multiple read rule for node";
332      }
333      node_readers.insert(make_pair(name, &node));
[1115]334      return *this;
[1037]335    }
336
[1133]337    /// \brief Add a new labeled edge reader for the reader.
338    ///
339    /// Add a new labeled edge reader for the reader.
[1115]340    GraphReader& addEdge(std::string name, Edge& edge) {
[1036]341      if (edge_readers.find(name) != edge_readers.end()) {
[1037]342        throw Exception() << "Multiple read rule for edge";
[1036]343      }
[1037]344      edge_readers.insert(make_pair(name, &edge));
[1115]345      return *this;
[1036]346    }
347
[1133]348    /// \brief Executes the reader commands.
349    ///
350    /// Executes the reader commands.
351    void run() {
[1032]352      int line_num = 0;
[1037]353      std::auto_ptr<InverterBase<Node> > nodeInverter;
354      std::auto_ptr<InverterBase<Edge> > edgeInverter;
355      try {
356        std::string line = readNotEmptyLine(is, line_num);
357        if (line.find("@nodeset") == 0) {
358          line = readNodeSet(line_num, nodeInverter);
359        }
360        if (line.find("@edgeset") == 0) {
361          line = readEdgeSet(line_num, edgeInverter, nodeInverter);
[1036]362        }
[1037]363        if (line.find("@nodes") == 0) {
364          line = readNodes(line_num, nodeInverter);
365        }
366        if (line.find("@edges") == 0) {
367          line = readEdges(line_num, edgeInverter);
368        }
369        if (line.find("@end") != 0) {
370          throw DataFormatException("Invalid control sequence: " + line);
371        }
372      } catch (DataFormatException e) {
373        throw StreamException<DataFormatException>(line_num, e);
374      }
[1032]375    }
376
377  private:
378
[1036]379    template <typename Item> class InverterBase;
380
[1115]381    std::string readNodeSet(int& line_num,
382                            auto_ptr<InverterBase<Node> > & nodeInverter) {
[1037]383      std::vector<ReaderBase<Node>* > index;
[1032]384      {
385        std::string line = readNotEmptyLine(is, line_num);   
386        std::string id;
387        std::istringstream ls(line);   
388        while (ls >> id) {
[1036]389          if (id[0] == '#') break;
[1037]390          typename NodeMapReaders::iterator it = node_map_readers.find(id);
391          if (it != node_map_readers.end()) {
[1032]392            index.push_back(it->second);
[1037]393            node_map_readers.erase(it);
[1032]394          } else {
[1036]395            index.push_back(&nodeSkipper);
[1032]396          }
397        }
398      }
[1036]399
[1037]400      if (index.size() == 0) {
401        throw DataFormatException("No node map found");
402      }
403
404      nodeInverter = auto_ptr<InverterBase<Node> >(index[0]->getInverter());
[1032]405      std::string line;
406      while (line = readNotEmptyLine(is, line_num), line[0] != '@') {
407        Node node = graph.addNode();
408        std::istringstream ls(line);
[1036]409        nodeInverter->read(ls, node);
[1115]410        for (int i = 1; i < (int)index.size(); ++i) {
[1036]411          index[i]->read(ls, node);
[1032]412        }
413      }
[1037]414      return line;
[1032]415    }
416
[1037]417    std::string readEdgeSet(int& line_num,
[1115]418                            auto_ptr<InverterBase<Edge> > & edgeInverter,
419                            auto_ptr<InverterBase<Node> > & nodeInverter) {
[1036]420      std::vector<ReaderBase<Edge>*> index;
421      {
422        std::string line = readNotEmptyLine(is, line_num);   
423        std::string id;
424        std::istringstream ls(line);   
425        while (ls >> id) {
426          if (id[0] == '#') break;
[1037]427          typename EdgeMapReaders::iterator it = edge_map_readers.find(id);
428          if (it != edge_map_readers.end()) {
[1036]429            index.push_back(it->second);
[1037]430            edge_map_readers.erase(it);
[1036]431          } else {
432            index.push_back(&edgeSkipper);
433          }
434        }
435      }
[1037]436
437      if (index.size() == 0) {
438        throw DataFormatException("No edge map found");
439      }
440
441      edgeInverter = auto_ptr<InverterBase<Edge> >(index[0]->getInverter());
[1036]442      std::string line;
443      while (line = readNotEmptyLine(is, line_num), line[0] != '@') {   
444        std::istringstream ls(line);
445        Node source = nodeInverter->read(ls);
446        Node target = nodeInverter->read(ls);
447        Edge edge = graph.addEdge(source, target);
448        edgeInverter->read(ls, edge);
[1115]449        for (int i = 1; i < (int)index.size(); ++i) {
[1036]450          index[i]->read(ls, edge);
451        }
452      }     
[1037]453      return line;
454    }
455
[1115]456    std::string readNodes(int& line_num,
457                          auto_ptr<InverterBase<Node> >& nodeInverter) {
[1037]458      std::string line;
459      while (line = readNotEmptyLine(is, line_num), line[0] != '@') {
460        std::istringstream ls(line);
461        std::string name;
462        ls >> name;
463        typename NodeReaders::iterator it = node_readers.find(name);
464        if (it != node_readers.end()) {
465          *(it -> second) = nodeInverter->read(ls);
466        }
467      }       
468      return line;
469    }
470
[1115]471    std::string readEdges(int& line_num,
472                          auto_ptr<InverterBase<Edge> >& edgeInverter) {
[1037]473      std::string line;
474      while (line = readNotEmptyLine(is, line_num), line[0] != '@') {
475        std::istringstream ls(line);
476        std::string name;
477        ls >> name;
478        typename EdgeReaders::iterator it = edge_readers.find(name);
479        if (it != edge_readers.end()) {
480          *(it -> second) = edgeInverter->read(ls);
481        }
482      }       
483      return line;   
[1032]484    }
485
486    std::string readNotEmptyLine(std::istream& is, int& line_num) {
487      std::string line;
488      while (++line_num, getline(is, line)) {   
489        int vi = line.find_first_not_of(" \t");
[1115]490        if (vi != (int)string::npos && line[vi] != '#') {
[1032]491          return line.substr(vi);
492        }
493      }
[1037]494      throw DataFormatException("End of stream");
[1032]495    }
496   
[1037]497    // Inverters store and give back the Item from the id,
498    // and may put the ids into a map.
499   
[1036]500    template <typename _Item>
501    class InverterBase {
502    public:
503      typedef _Item Item;
[1037]504      virtual void read(std::istream&, const Item&) = 0;
505      virtual Item read(std::istream&) = 0;
[1036]506    };
[1032]507
[1036]508    template <typename _Item, typename _Map, typename _Reader>
509    class MapReaderInverter : public InverterBase<_Item> {
510    public:
511      typedef _Item Item;
512      typedef _Reader Reader;
513      typedef typename Reader::Value Value;
514      typedef _Map Map;
515      typedef std::map<Value, Item> Inverse;
516
517      Map& map;
518      Reader reader;
519      Inverse inverse;
520
521      MapReaderInverter(Map& _map, const Reader& _reader)
522        : map(_map), reader(_reader) {}
523
[1115]524      virtual ~MapReaderInverter() {}
525
[1037]526      virtual void read(std::istream& is, const Item& item) {
[1036]527        Value value;
528        reader.read(is, value);
529        map.set(item, value);
530        typename Inverse::iterator it = inverse.find(value);
531        if (it == inverse.end()) {
532          inverse.insert(make_pair(value, item));
533        } else {
534          throw DataFormatException("Multiple ID occurence");
535        }
536      }
537
[1037]538      virtual Item read(std::istream& is) {
[1036]539        Value value;
540        reader.read(is, value);
541        typename Inverse::const_iterator it = inverse.find(value);
542        if (it != inverse.end()) {
543          return it->second;
544        } else {
545          throw DataFormatException("Invalid ID");
546        }
547      }     
548    };
549
550    template <typename _Item, typename _Reader>
551    class SkipReaderInverter : public InverterBase<_Item> {
552    public:
553      typedef _Item Item;
554      typedef _Reader Reader;
555      typedef typename Reader::Value Value;
556      typedef std::map<Value, Item> Inverse;
557
558      Reader reader;
559
560      SkipReaderInverter(const Reader& _reader)
561        : reader(_reader) {}
562
[1115]563      virtual ~SkipReaderInverter() {}
564
[1037]565      virtual void read(std::istream& is, const Item& item) {
[1036]566        Value value;
567        reader.read(is, value);
568        typename Inverse::iterator it = inverse.find(value);
569        if (it == inverse.end()) {
570          inverse.insert(make_pair(value, item));
571        } else {
572          throw DataFormatException("Multiple ID occurence");
573        }
574      }
575
[1037]576      virtual Item read(std::istream& is) {
[1036]577        Value value;
578        reader.read(is, value);
579        typename Inverse::const_iterator it = inverse.find(value);
580        if (it != inverse.end()) {
581          return it->second;
582        } else {
583          throw DataFormatException("Invalid ID");
584        }
585      }     
586    private:
587      Inverse inverse;
588    };
589
[1037]590    // Readers
[1032]591
592    template <typename _Item>   
[1036]593    class ReaderBase {
[1032]594    public:
595      typedef _Item Item;
[1037]596
[1115]597      //      virtual ~ReaderBase() {}
598
[1037]599      virtual void read(std::istream& is, const Item& item) = 0;
[1036]600      virtual InverterBase<_Item>* getInverter() = 0;
[1032]601    };
[1036]602
[1032]603    template <typename _Item, typename _Map, typename _Reader>
[1036]604    class MapReader : public ReaderBase<_Item> {
[1032]605    public:
606      typedef _Map Map;
607      typedef _Reader Reader;
[1036]608      typedef typename Reader::Value Value;
[1032]609      typedef _Item Item;
610     
611      Map& map;
612      Reader reader;
613
614      MapReader(Map& _map, const Reader& _reader)
615        : map(_map), reader(_reader) {}
616
[1115]617      virtual ~MapReader() {}
[1032]618
[1037]619      virtual void read(std::istream& is, const Item& item) {
[1036]620        Value value;
[1032]621        reader.read(is, value);
622        map.set(item, value);
623      }
[1036]624
625      virtual InverterBase<_Item>* getInverter() {
626        return new MapReaderInverter<Item, Map, Reader>(map, reader);
627      }
[1032]628    };
629
[1036]630
631    template <typename _Item, typename _Reader>
632    class SkipReader : public ReaderBase<_Item> {
633    public:
634      typedef _Reader Reader;
635      typedef typename Reader::Value Value;
636      typedef _Item Item;
637
638      Reader reader;
639      SkipReader(const Reader& _reader) : reader(_reader) {}
640
[1115]641      virtual ~SkipReader() {}
642
[1037]643      virtual void read(std::istream& is, const Item& item) {
[1036]644        Value value;
645        reader.read(is, value);
646      }     
647
648      virtual InverterBase<Item>* getInverter() {
649        return new SkipReaderInverter<Item, Reader>(reader);
650      }
651    };
652
653
[1037]654    typedef std::map<std::string, ReaderBase<Node>*> NodeMapReaders;
655    NodeMapReaders node_map_readers;
656
657    typedef std::map<std::string, ReaderBase<Edge>*> EdgeMapReaders;
658    EdgeMapReaders edge_map_readers;
659
660    typedef std::map<std::string, Node*> NodeReaders;
[1032]661    NodeReaders node_readers;
662
[1037]663    typedef std::map<std::string, Edge*> EdgeReaders;
[1032]664    EdgeReaders edge_readers;
665
[1036]666    std::istream& is;
667    Graph& graph;
668
669    SkipReader<Node, DefaultReader> nodeSkipper;
670    SkipReader<Edge, DefaultReader> edgeSkipper;
671
[1032]672  };
673
674}
Note: See TracBrowser for help on using the repository browser.