COIN-OR::LEMON - Graph Library

source: lemon-0.x/src/work/deba/graph_reader.h @ 1036:2f514b5c7122

Last change on this file since 1036:2f514b5c7122 was 1036:2f514b5c7122, checked in by Balazs Dezso, 19 years ago

reader under construction

File size: 12.7 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 <lemon/error.h>
28
29/// \todo fix exceptions
30
31
32namespace lemon {
33
34  // Exceptions
35
36  class IOException {
37  public:
38    virtual string what() const = 0;
39  };
40
41  class DataFormatException : public IOException {
42    std::string message;
43  public:
44    DataFormatException(const std::string& _message)
45      : message(_message) {}
46    std::string what() const {
47      return "DataFormatException: " + message;
48    }
49  };
50
51  class StreamException : public IOException {
52  public:
53    virtual int line() = 0;
54  private:
55    IOException* exception;
56    int line_num;
57  }; 
58
59
60  // Readers and ReaderTraits
61 
62  struct DefaultReaderTraits {
63
64    template <typename _Value>
65    struct Reader {
66      typedef _Value Value;
67      void read(std::istream& is, Value& value) {
68        if (!(is >> value))
69          throw DataFormatException("Default Reader format exception");
70      }
71    };
72
73    typedef Reader<std::string> DefaultReader;
74
75  };
76
77  class QuotedStringReader {
78  public:
79    typedef std::string Value;
80
81    QuotedStringReader(bool _escaped = true) : escaped(_escaped) {}
82
83    void read(std::istream& is, std::string& value) {
84      char c;
85      value.clear();
86      is >> ws;
87      if (!is.get(c) || c != '\"') throw DataFormatException("Quoted string format exception");
88      while (is.get(c) && c != '\"') {
89        if (escaped && c == '\\') {
90          value += readEscape(is);
91        } else {
92          value += c;
93        }
94      }
95      if (!is) throw DataFormatException("Quoted string format exception");
96    }
97
98  private:
99   
100    static char readEscape(std::istream& is) {
101      char c;
102      switch (is.get(c), c) {
103      case '\\':
104        return '\\';
105      case '\"':
106        return '\"';
107      case '\'':
108        return '\'';
109      case '\?':
110        return '\?';
111      case 'a':
112        return '\a';
113      case 'b':
114        return '\b';
115      case 'f':
116        return '\f';
117      case 'n':
118        return '\n';
119      case 'r':
120        return '\r';
121      case 't':
122        return '\t';
123      case 'v':
124        return '\v';
125      case 'x':
126        {
127          int code;
128          if (!is.get(c) || !isHex(c)) throw DataFormatException("Escape format exception");
129          else if (code = valueHex(c), !is.get(c) || !isHex(c)) is.putback(c);
130          else code = code * 16 + valueHex(c);
131          return code;
132        }
133      default:
134        {
135          int code;
136          if (!isOct(c)) throw DataFormatException("Escape format exception");
137          else if (code = valueOct(c), !is.get(c) || !isOct(c)) is.putback(c);
138          else if (code = code * 8 + valueOct(c), !is.get(c) || !isOct(c)) is.putback(c);
139          else code = code * 8 + valueOct(c);
140          return code;
141        }             
142      }
143    }
144
145    static bool isOct(char c) {
146      return '0' <= c && c <='7';
147    }
148   
149    static int valueOct(char c) {
150      return c - '0';
151    }
152
153   static bool isHex(char c) {
154      return ('0' <= c && c <= '9') || ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z');
155    }
156   
157    static int valueHex(char c) {
158      if ('0' <= c && c <= '9') return c - '0';
159      if ('a' <= c && c <= 'z') return c - 'a' + 10;
160      return c - 'A' + 10;
161    }
162
163    bool escaped;
164  };
165
166
167
168
169
170  // Graph reader
171 
172  template <typename _Graph, typename _ReaderTraits = DefaultReaderTraits>
173  class GraphReader {
174
175  public:
176   
177    typedef _Graph Graph;
178    typedef typename Graph::Node Node;
179    typedef typename Graph::Edge Edge;
180
181    typedef _ReaderTraits ReaderTraits;
182    typedef typename ReaderTraits::DefaultReader DefaultReader;
183
184    GraphReader(istream& _is, Graph& _graph, const DefaultReader& _reader = DefaultReader())
185      : is(_is), graph(_graph), nodeSkipper(_reader), edgeSkipper(_reader) {}
186
187
188    ~GraphReader() {
189
190      for (typename NodeReaders::iterator it = node_readers.begin(); it != node_readers.end(); ++it) {
191        delete it->second;
192      }
193
194      for (typename EdgeReaders::iterator it = edge_readers.begin(); it != edge_readers.end(); ++it) {
195        delete it->second;
196      }
197
198    }
199
200    template <typename Map>
201    GraphReader& readNodeMap(std::string name, Map& map) {
202      return readNodeMap<typename ReaderTraits::template Reader<typename Map::Value>, Map>(name, map);
203    }
204
205    template <typename Reader, typename Map>
206    GraphReader& readNodeMap(std::string name, Map& map, const Reader& reader = Reader()) {
207      if (node_readers.find(name) != node_readers.end()) {
208        Exception e;
209        e << "Multiple read rule for node map: " << name;
210        throw e;
211      }
212      node_readers.insert(make_pair(name, new MapReader<Node, Map, Reader>(map, reader)));
213      return *this;
214    }
215
216    template <typename Reader>
217    GraphReader& skipNodeMap(std::string name, const Reader& reader = Reader()) {
218      if (node_readers.find(name) != node_readers.end()) {
219        Exception e;
220        e << "Multiple read rule for node map: " << name;
221        throw e;
222      }
223      node_readers.insert(make_pair(name, new SkipReader<Node, Reader>(reader)));
224      return *this;
225    }
226
227    template <typename Map>
228    GraphReader& readEdgeMap(std::string name, Map& map) {
229      return readEdgeMap<typename ReaderTraits::template Reader<typename Map::Value>, Map>(name, map);
230    }
231
232
233    template <typename Reader, typename Map>
234    GraphReader& readEdgeMap(std::string name, Map& map, const Reader& reader = Reader()) {
235      if (edge_readers.find(name) != edge_readers.end()) {
236        Exception e;
237        e << "Multiple read rule for edge map: " << name;
238        throw e;
239      }
240      edge_readers.insert(make_pair(name, new MapReader<Edge, Map, Reader>(map, reader)));
241      return *this;
242    }
243
244    template <typename Reader>
245    GraphReader& skipEdgeMap(std::string name, const Reader& reader = Reader()) {
246      if (edge_readers.find(name) != edge_readers.end()) {
247        Exception e;
248        e << "Multiple read rule for edge map: " << name;
249        throw e;
250      }
251      edge_readers.insert(make_pair(name, new SkipReader<Edge, Reader>(reader)));
252      return *this;
253    }
254
255    void read() {
256      int line_num = 0;
257      InverterBase<Node>* nodeInverter = 0;
258      InverterBase<Edge>* edgeInverter = 0;
259      // \todo delete the inverters
260      //      try {
261        {
262          std::string line = readNotEmptyLine(is, line_num);
263        }
264        readNodeSet(line_num, nodeInverter);
265        readEdgeSet(line_num, edgeInverter, nodeInverter);
266        //      } catch (...){
267        if (nodeInverter != 0) delete nodeInverter;
268        if (edgeInverter != 0) delete edgeInverter;
269        //      }
270    }
271
272  private:
273
274    template <typename Item> class InverterBase;
275    //    template <typename Item> class InverterBase;
276
277    void readNodeSet(int& line_num, InverterBase<Node>* & nodeInverter) {
278      int n = 0;
279      std::vector<ReaderBase<Node>*> index;
280      {
281        std::string line = readNotEmptyLine(is, line_num);   
282        std::string id;
283        std::istringstream ls(line);   
284        while (ls >> id) {
285          if (id[0] == '#') break;
286          typename NodeReaders::iterator it = node_readers.find(id);
287          if (it != node_readers.end()) {
288            index.push_back(it->second);
289          } else {
290            index.push_back(&nodeSkipper);
291          }
292          ++n;
293        }
294      }
295
296      nodeInverter = index[0]->getInverter();
297      std::string line;
298      while (line = readNotEmptyLine(is, line_num), line[0] != '@') {
299        Node node = graph.addNode();
300        std::istringstream ls(line);
301        nodeInverter->read(ls, node);
302        for (int i = 1; i < n; ++i) {
303          index[i]->read(ls, node);
304        }
305      }
306    }
307
308    void readEdgeSet(int& line_num, InverterBase<Edge>* & edgeInverter, InverterBase<Node>* & nodeInverter) {
309      int n = 0;
310      std::vector<ReaderBase<Edge>*> index;
311      {
312        std::string line = readNotEmptyLine(is, line_num);   
313        std::string id;
314        std::istringstream ls(line);   
315        while (ls >> id) {
316          if (id[0] == '#') break;
317          typename EdgeReaders::iterator it = edge_readers.find(id);
318          if (it != edge_readers.end()) {
319            index.push_back(it->second);
320          } else {
321            index.push_back(&edgeSkipper);
322          }
323          ++n;
324        }
325      }
326      edgeInverter = index[0]->getInverter();
327      std::string line;
328      while (line = readNotEmptyLine(is, line_num), line[0] != '@') {   
329        std::istringstream ls(line);
330        Node source = nodeInverter->read(ls);
331        Node target = nodeInverter->read(ls);
332        Edge edge = graph.addEdge(source, target);
333        edgeInverter->read(ls, edge);
334        for (int i = 1; i < n; ++i) {
335          index[i]->read(ls, edge);
336        }
337      }     
338    }
339
340    std::string readNotEmptyLine(std::istream& is, int& line_num) {
341      std::string line;
342      while (++line_num, getline(is, line)) {   
343        int vi = line.find_first_not_of(" \t");
344        if (vi != string::npos && line[vi] != '#') {
345          return line.substr(vi);
346        }
347      }
348      throw Exception();
349    }
350   
351    template <typename _Item>
352    class InverterBase {
353    public:
354      typedef _Item Item;
355      virtual void read(istream&, const Item&) = 0;
356      virtual Item read(istream&) = 0;
357    };
358
359    template <typename _Item, typename _Map, typename _Reader>
360    class MapReaderInverter : public InverterBase<_Item> {
361    public:
362      typedef _Item Item;
363      typedef _Reader Reader;
364      typedef typename Reader::Value Value;
365      typedef _Map Map;
366      typedef std::map<Value, Item> Inverse;
367
368      Map& map;
369      Reader reader;
370      Inverse inverse;
371
372      MapReaderInverter(Map& _map, const Reader& _reader)
373        : map(_map), reader(_reader) {}
374
375      virtual void read(istream& is, const Item& item) {
376        Value value;
377        reader.read(is, value);
378        map.set(item, value);
379        typename Inverse::iterator it = inverse.find(value);
380        if (it == inverse.end()) {
381          inverse.insert(make_pair(value, item));
382        } else {
383          throw DataFormatException("Multiple ID occurence");
384        }
385      }
386
387      virtual Item read(istream& is) {
388        Value value;
389        reader.read(is, value);
390        typename Inverse::const_iterator it = inverse.find(value);
391        if (it != inverse.end()) {
392          return it->second;
393        } else {
394          throw DataFormatException("Invalid ID");
395        }
396      }     
397    };
398
399    template <typename _Item, typename _Reader>
400    class SkipReaderInverter : public InverterBase<_Item> {
401    public:
402      typedef _Item Item;
403      typedef _Reader Reader;
404      typedef typename Reader::Value Value;
405      typedef std::map<Value, Item> Inverse;
406
407      Reader reader;
408
409      SkipReaderInverter(const Reader& _reader)
410        : reader(_reader) {}
411
412      virtual void read(istream& is, const Item& item) {
413        Value value;
414        reader.read(is, value);
415        typename Inverse::iterator it = inverse.find(value);
416        if (it == inverse.end()) {
417          inverse.insert(make_pair(value, item));
418        } else {
419          throw DataFormatException("Multiple ID occurence");
420        }
421      }
422
423      virtual Item read(istream& is) {
424        Value value;
425        reader.read(is, value);
426        typename Inverse::const_iterator it = inverse.find(value);
427        if (it != inverse.end()) {
428          return it->second;
429        } else {
430          throw DataFormatException("Invalid ID");
431        }
432      }     
433    private:
434      Inverse inverse;
435    };
436
437
438    template <typename _Item>   
439    class ReaderBase {
440    public:
441      typedef _Item Item;
442      virtual void read(istream& is, const Item& item) = 0;
443      virtual InverterBase<_Item>* getInverter() = 0;
444    };
445
446    template <typename _Item, typename _Map, typename _Reader>
447    class MapReader : public ReaderBase<_Item> {
448    public:
449      typedef _Map Map;
450      typedef _Reader Reader;
451      typedef typename Reader::Value Value;
452      typedef _Item Item;
453     
454      Map& map;
455      Reader reader;
456
457      MapReader(Map& _map, const Reader& _reader)
458        : map(_map), reader(_reader) {}
459
460
461      virtual void read(istream& is, const Item& item) {
462        Value value;
463        reader.read(is, value);
464        map.set(item, value);
465      }
466
467      virtual InverterBase<_Item>* getInverter() {
468        return new MapReaderInverter<Item, Map, Reader>(map, reader);
469      }
470    };
471
472
473    template <typename _Item, typename _Reader>
474    class SkipReader : public ReaderBase<_Item> {
475    public:
476      typedef _Reader Reader;
477      typedef typename Reader::Value Value;
478      typedef _Item Item;
479
480      Reader reader;
481      SkipReader(const Reader& _reader) : reader(_reader) {}
482
483      virtual void read(istream& is, const Item& item) {
484        Value value;
485        reader.read(is, value);
486      }     
487
488      virtual InverterBase<Item>* getInverter() {
489        return new SkipReaderInverter<Item, Reader>(reader);
490      }
491    };
492
493
494    typedef std::map<std::string, ReaderBase<Node>* > NodeReaders;
495    NodeReaders node_readers;
496
497    typedef std::map<std::string, ReaderBase<Edge>* > EdgeReaders;
498    EdgeReaders edge_readers;
499
500    std::istream& is;
501    Graph& graph;
502
503    SkipReader<Node, DefaultReader> nodeSkipper;
504    SkipReader<Edge, DefaultReader> edgeSkipper;
505
506  };
507
508}
Note: See TracBrowser for help on using the repository browser.