COIN-OR::LEMON - Graph Library

source: lemon-0.x/lemon/bits/item_reader.h @ 2000:ebcc93ead7da

Last change on this file since 2000:ebcc93ead7da was 1956:a055123339d5, checked in by Alpar Juttner, 14 years ago

Unified copyright notices

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