COIN-OR::LEMON - Graph Library

source: lemon-0.x/src/work/deba/graph_reader.h @ 1118:62296604afb4

Last change on this file since 1118:62296604afb4 was 1115:444f69240539, checked in by Balazs Dezso, 21 years ago

Some changes in the IO and map utilities.

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