COIN-OR::LEMON - Graph Library

source: lemon-0.x/lemon/bits/item_reader.h @ 2229:4dbb6dd2dd4b

Last change on this file since 2229:4dbb6dd2dd4b was 2016:ecb067198349, checked in by Balazs Dezso, 14 years ago

Doc rearrangement
Section readers moved to own group

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