COIN-OR::LEMON - Graph Library

source: lemon-0.x/lemon/bits/item_reader.h @ 1882:2c3f6c7e01b4

Last change on this file since 1882:2c3f6c7e01b4 was 1875:98698b69a902, checked in by Alpar Juttner, 14 years ago

Happy new year to LEMON

File size: 12.7 KB
Line 
1/* -*- C++ -*-
2 * lemon/bits/item_reader.h - Part of LEMON, a generic C++ optimization library
3 *
4 * Copyright (C) 2006 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
5 * (Egervary Research Group on Combinatorial Optimization, 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/// @defgroup item_io Item Readers and Writers
18/// @ingroup io_group
19/// \brief Item Readers and Writers
20///
21/// The Input-Output classes can handle more data type by example
22/// as map or attribute value. Each of these should be written and
23/// read some way. The module make possible to do this. 
24
25/// \ingroup item_io
26/// \file
27/// \brief Item reader bits for lemon input.
28
29#ifndef LEMON_BITS_ITEM_READER_H
30#define LEMON_BITS_ITEM_READER_H
31
32#include <iostream>
33#include <string>
34
35#include <vector>
36#include <deque>
37#include <list>
38#include <set>
39
40namespace lemon {
41 
42  template <typename Value>
43  class DefaultReader;
44
45  /// \ingroup item_io
46  ///
47  /// \brief Reader class for quoted strings.
48  ///
49  /// Reader class for quoted strings. It can process the escape
50  /// sequences in the string.
51  ///
52  /// \author Balazs Dezso
53  class QuotedStringReader {
54  public:
55    /// \brief The value type of reader.
56    ///
57    /// The value type of reader.
58    typedef std::string Value;
59   
60    /// \brief Constructor for the reader.
61    ///
62    /// Constructor for the reader. If the given parameter is true
63    /// the reader processes the escape sequences.
64    QuotedStringReader(bool _escaped = true)
65      : escaped(_escaped) {}
66   
67    /// \brief Reads a quoted string from the given stream.
68    ///
69    /// Reads a quoted string from the given stream.
70    void read(std::istream& is, std::string& value) const {
71      char c;
72      value.clear();
73      is >> std::ws;
74      if (!is.get(c) || c != '\"')
75        throw DataFormatError("Quoted string format error");
76      while (is.get(c) && c != '\"') {
77        if (escaped && c == '\\') {
78          value += readEscape(is);
79        } else {
80          value += c;
81        }
82      }
83      if (!is) throw DataFormatError("Quoted string format error");
84    }
85
86  private:
87   
88    static char readEscape(std::istream& is) {
89      char c;
90      switch (is.get(c), c) {
91      case '\\':
92        return '\\';
93      case '\"':
94        return '\"';
95      case '\'':
96        return '\'';
97      case '\?':
98        return '\?';
99      case 'a':
100        return '\a';
101      case 'b':
102        return '\b';
103      case 'f':
104        return '\f';
105      case 'n':
106        return '\n';
107      case 'r':
108        return '\r';
109      case 't':
110        return '\t';
111      case 'v':
112        return '\v';
113      case 'x':
114        {
115          int code;
116          if (!is.get(c) || !isHex(c))
117            throw DataFormatError("Escape format error");
118          else if (code = valueHex(c), !is.get(c) || !isHex(c)) is.putback(c);
119          else code = code * 16 + valueHex(c);
120          return code;
121        }
122      default:
123        {
124          int code;
125          if (!isOct(c))
126            throw DataFormatError("Escape format error");
127          else if (code = valueOct(c), !is.get(c) || !isOct(c))
128            is.putback(c);
129          else if (code = code * 8 + valueOct(c), !is.get(c) || !isOct(c))
130            is.putback(c);
131          else code = code * 8 + valueOct(c);
132          return code;
133        }             
134      }
135    }
136
137    static bool isOct(char c) {
138      return '0' <= c && c <='7';
139    }
140   
141    static int valueOct(char c) {
142      return c - '0';
143    }
144
145   static bool isHex(char c) {
146      return ('0' <= c && c <= '9') ||
147        ('a' <= c && c <= 'z') ||
148        ('A' <= c && c <= 'Z');
149    }
150   
151    static int valueHex(char c) {
152      if ('0' <= c && c <= '9') return c - '0';
153      if ('a' <= c && c <= 'z') return c - 'a' + 10;
154      return c - 'A' + 10;
155    }
156
157    bool escaped;
158  };
159
160  /// \ingroup item_io
161  /// \brief Reader for standard containers.
162  ///
163  /// Reader for back insertable standard containers. The representation
164  /// of the container is the values enumerated between an open and a
165  /// close parse.
166  ///
167  /// \author Balazs Dezso
168  template <
169    typename _Container,
170    typename _ItemReader = DefaultReader<typename _Container::value_type>
171  >
172  class PushBackReader {
173  public:
174    typedef _Container Value;
175    typedef _ItemReader ItemReader;
176
177  private:
178
179    ItemReader item_reader;
180
181  public:
182
183    /// \brief Constructor for InsertReader
184    ///
185    /// Constructor for InsertReader
186    PushBackReader(const ItemReader& _item_reader = ItemReader())
187      : item_reader(_item_reader) {}
188
189    /// \brief Reads the values into the container from the given stream.
190    ///
191    /// Reads the values into the container from the given stream.
192    void read(std::istream& is, Value& value) const {
193      char c;
194      if (!(is >> c) || c != '(')
195        throw DataFormatError("PushBackReader format error");
196      while (is >> c && c != ')') {
197        is.putback(c);
198        typename ItemReader::Value item;
199        item_reader.read(is, item);
200        value.push_back(item);
201      }
202      if (!is) throw DataFormatError("PushBackReader format error");
203    }
204
205  };
206
207  /// \ingroup item_io
208  ///
209  /// \brief Reader for standard containers.
210  ///
211  /// Reader for insertable standard containers. The representation
212  /// of the container is the values enumerated between an open and a
213  /// close parse.
214  ///
215  /// \author Balazs Dezso
216  template <
217    typename _Container,
218    typename _ItemReader = DefaultReader<typename _Container::value_type>
219  >
220  class InsertReader {
221  public:
222    typedef _Container Value;
223    typedef _ItemReader ItemReader;
224
225  private:
226
227    ItemReader item_reader;
228
229  public:
230
231    /// \brief Constructor for InsertReader
232    ///
233    /// Constructor for InsertReader
234    InsertReader(const ItemReader& _item_reader = ItemReader())
235      : item_reader(_item_reader) {}
236
237    /// \brief Reads the values into the container from the given stream.
238    ///
239    /// Reads the values into the container from the given stream.
240    void read(std::istream& is, Value& value) const {
241      char c;
242      if (!(is >> c) || c != '(')
243        throw DataFormatError("InsertReader format error");
244      while (is >> c && c != ')') {
245        is.putback(c);
246        typename ItemReader::Value item;
247        item_reader.read(is, item);
248        value.insert(item);
249      }
250      if (!is) throw DataFormatError("PushBackReader format error");
251    }
252
253  };
254
255  /// \ingroup item_io
256  /// \brief Reader for parsed string.
257  ///
258  /// Reader for parsed strings. You can define the open and close
259  /// parse characters. It reads from the input a character sequence
260  /// which is right parsed.
261  ///
262  /// \author Balazs Dezso
263  class ParsedStringReader {
264  public:
265    typedef std::string Value;
266
267    /// \brief Constructor.
268    ///
269    /// Constructor for ParsedStringReader. You can give as parameter
270    /// the open and close parse characters.
271    ParsedStringReader(char _open = '(', char _close = ')')
272      : open(_open), close(_close) {}
273   
274   
275    /// \brief Reads the parsed string from the given stream.
276    ///
277    /// Reads the parsed string from the given stream.
278    void read(std::istream& is, Value& value) const {
279      char c;
280      if (!(is >> c) || c != open) {
281        throw DataFormatError("ParsedStringReader format error");
282      }
283      value += c;
284      int counter = 1;
285      while (counter > 0 && is >> c) {
286        if (c == close) {
287          --counter;
288        } else if (c == open) {
289          ++counter;
290        }
291        value += c;
292      }
293      if (!is) {
294        throw DataFormatError("ParsedStrinReader format error");
295      }
296    }
297
298  private:
299    char open, close;
300
301  };
302
303  /// \ingroup item_io
304  /// \brief Reader for read the whole line.
305  ///
306  /// Reader for read the whole line.
307  ///
308  /// \author Balazs Dezso
309  class LineReader {
310  public:
311    typedef std::string Value;
312
313    /// \brief Constructor.
314    ///
315    /// Constructor for the LineReader. If the given parameter is
316    /// true then the spaces before the first not space character are
317    /// skipped.
318    LineReader(bool _skipSpaces = true) : skipSpaces(_skipSpaces) {}
319   
320    /// \brief Reads the line from the given stream.
321    ///
322    /// Reads the line from the given stream.
323    void read(std::istream& is, Value& value) const {
324      if (skipSpaces) is >> std::ws;
325      if (!getline(is, value)) {
326        throw DataFormatError("LineReader format error");
327      }
328    }
329  private:
330    bool skipSpaces;
331  };
332
333  /// \ingroup item_io
334  /// \brief Reader for std::pair.
335  ///
336  /// Reader for std::pair.
337  ///
338  /// \author Balazs Dezso
339  template <typename _Pair,
340            typename _FirstReader =
341            DefaultReader<typename _Pair::first_type>,
342            typename _SecondReader =
343            DefaultReader<typename _Pair::second_type> >
344  class PairReader {
345  public:
346    typedef _Pair Value;
347
348    typedef _FirstReader FirstReader;
349    typedef _SecondReader SecondReader;
350
351  private:
352
353    FirstReader first_reader;
354    SecondReader second_reader;
355
356  public:
357   
358    /// \brief Constructor.
359    ///
360    /// Constructor for the PairReader.
361    PairReader(const FirstReader& _first_reader = FirstReader(),
362               const SecondReader& _second_reader = SecondReader())
363      : first_reader(_first_reader), second_reader(_second_reader) {}
364   
365    /// \brief Reads the pair from the given stream.
366    ///
367    /// Reads the pair from the given stream.
368    void read(std::istream& is, Value& value) const {
369      char c;
370      if (!(is >> c) || c != '(') {
371        throw DataFormatError("PairReader format error");
372      }
373      first_reader.read(is, value.first);
374      if (!(is >> c) || c != '=') {
375        throw DataFormatError("PairReader format error");
376      }
377      if (!(is >> c) || c != '>') {
378        throw DataFormatError("PairReader format error");
379      }
380      second_reader.read(is, value.second);
381      if (!(is >> c) || c != ')') {
382        throw DataFormatError("PairReader format error");
383      }
384    }
385  };
386
387  /// \ingroup item_io
388  ///
389  /// \brief The default item reader template class.
390  ///
391  /// The default item reader template class. If some section reader
392  /// needs to read a value from a stream it will give the default way for it.
393  ///
394  /// \author Balazs Dezso
395  template <typename _Value>
396  class DefaultReader {
397  public:
398    /// The value type.
399    typedef _Value Value;
400    /// \brief Reads a value from the given stream.
401    ///
402    /// Reads a value from the given stream.
403    void read(std::istream& is, Value& value) const {
404      if (!(is >> value))
405        throw DataFormatError("DefaultReader format error");
406    }
407  };
408
409  template <>
410  class DefaultReader<std::string> {
411  public:
412    typedef std::string Value;
413   
414    void read(std::istream& is, Value& value) const {
415      char c;
416      if (!(is >> std::ws >> c)) return;
417      is.putback(c);
418      switch (c) {
419      case '\"':
420        QuotedStringReader().read(is, value);
421        break;
422      case '(':
423        ParsedStringReader().read(is, value);
424        break;
425      case '[':
426        ParsedStringReader('[', ']').read(is, value);
427        break;
428      case '/':
429        ParsedStringReader('/', '/').read(is, value);
430        break;
431      default:
432        if (!(is >> value))
433          throw DataFormatError("DefaultReader format error");
434        break;
435      }
436    }
437   
438  };
439
440  template <typename Item>
441  class DefaultReader<std::vector<Item> >
442    : public PushBackReader<std::vector<Item> > {};
443
444  template <typename Item>
445  class DefaultReader<std::deque<Item> >
446    : public PushBackReader<std::deque<Item> > {};
447
448  template <typename Item>
449  class DefaultReader<std::list<Item> >
450    : public PushBackReader<std::list<Item> > {};
451
452  template <typename Item>
453  class DefaultReader<std::set<Item> >
454    : public InsertReader<std::set<Item> > {};
455
456  template <typename Key, typename Value>
457  class DefaultReader<std::map<Key, Value> >
458    : public InsertReader<std::map<Key, Value>,
459                          DefaultReader<std::pair<Key, Value> > > {};
460
461  template <typename Item>
462  class DefaultReader<std::multiset<Item> >
463    : public InsertReader<std::multiset<Item> > {};
464
465  template <typename Key, typename Value>
466  class DefaultReader<std::multimap<Key, Value> >
467    : public InsertReader<std::multimap<Key, Value>,
468                          DefaultReader<std::pair<Key, Value> > > {};
469
470  template <typename First, typename Second>
471  class DefaultReader<std::pair<First, Second> >
472    : public PairReader<std::pair<First, Second> > {};
473
474  /// \ingroup item_io
475  ///
476  /// \brief The default item reader for skipping a value in the stream.
477  ///
478  /// The default item reader for skipping a value in the stream.
479  ///
480  /// \author Balazs Dezso
481  class DefaultSkipper : public DefaultReader<std::string> {};
482
483  /// \ingroup item_io 
484  /// \brief Standard ReaderTraits for the GraphReader class.
485  ///
486  /// Standard ReaderTraits for the GraphReader class.
487  /// It defines standard reading method for all type of value.
488  /// \author Balazs Dezso
489  struct DefaultReaderTraits {
490
491    template <typename _Value>
492    struct Reader : DefaultReader<_Value> {};
493
494    typedef DefaultSkipper Skipper;
495
496  };
497
498}
499
500#endif
Note: See TracBrowser for help on using the repository browser.