COIN-OR::LEMON - Graph Library

source: lemon-0.x/src/lemon/bits/item_reader.h @ 1427:14c75970840e

Last change on this file since 1427:14c75970840e was 1427:14c75970840e, checked in by Balazs Dezso, 15 years ago

Two minor changes.

DefaultReader?<std::string>
comment lines

File size: 10.1 KB
Line 
1/* -*- C++ -*-
2 * src/lemon/bits/item_reader.h - Part of LEMON, a generic C++ optimization library
3 *
4 * Copyright (C) 2005 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 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      is.putback(c);
198    }
199
200  };
201
202  /// \ingroup item_io
203  ///
204  /// \brief Reader for standard containers.
205  ///
206  /// Reader for insertable standard containers. The representation
207  /// of the container is the values enumerated between an open and a
208  /// close parse.
209  ///
210  /// \author Balazs Dezso
211  template <
212    typename _Container,
213    typename _ItemReader = DefaultReader<typename _Container::value_type>
214  >
215  class InsertReader {
216  public:
217    typedef _Container Value;
218    typedef _ItemReader ItemReader;
219
220  private:
221
222    ItemReader item_reader;
223
224  public:
225
226    /// \brief Reads the values into the container from the given stream.
227    ///
228    /// Reads the values into the container from the given stream.
229    void read(std::istream& is, Value& value) const {
230      char c;
231      if (!(is >> c) || c != '(')
232        throw DataFormatError("InsertReader format error");
233      while (is >> c && c != ')') {
234        is.putback(c);
235        typename ItemReader::Value item;
236        item_reader.read(is, item);
237        value.insert(item);
238      }
239      if (!is) throw DataFormatError("PushBackReader format error");
240      is.putback(c);
241    }
242
243  };
244
245  /// \ingroup item_io
246  /// \brief Reader for parsed string.
247  ///
248  /// Reader for parsed strings. You can give the open and close
249  /// parse characters.
250  ///
251  /// \author Balazs Dezso
252  class ParsedStringReader {
253  public:
254    typedef std::string Value;
255
256    /// \brief Constructor.
257    ///
258    /// Constructor for ParsedStringReader. You can give as parameter
259    /// the open and close parse characters.
260    ParsedStringReader(char _open = '(', char _close = ')')
261      : open(_open), close(_close) {}
262   
263   
264    /// \brief Reads the parsed string from the given stream.
265    ///
266    /// Reads the parsed string from the given stream.
267    void read(std::istream& is, Value& value) const {
268      char c;
269      if (!(is >> c) || c != open) {
270        throw DataFormatError("ParsedStringReader format error");
271      }
272      value += c;
273      int counter = 1;
274      while (counter > 0 && is >> c) {
275        if (c == close) {
276          --counter;
277        } else if (c == open) {
278          ++counter;
279        }
280        value += c;
281      }
282      if (!is) {
283        throw DataFormatError("ParsedStrinReader format error");
284      }
285    }
286
287  private:
288    char open, close;
289
290  };
291
292  /// \ingroup item_io
293  /// \brief Reader for read the whole line.
294  ///
295  /// Reader for read the whole line.
296  ///
297  /// \author Balazs Dezso
298  class LineReader {
299  public:
300    typedef std::string Value;
301
302    /// \brief Constructor.
303    ///
304    /// Constructor for the LineReader. If the given parameter is
305    /// true then the spaces before the first not space character are
306    /// skipped.
307    LineReader(bool _skipSpaces = true) : skipSpaces(_skipSpaces) {}
308   
309    /// \brief Reads the line from the given stream.
310    ///
311    /// Reads the line from the given stream.
312    void read(std::istream& is, Value& value) {
313      if (skipSpaces) is >> std::ws;
314      if (!getline(is, value)) {
315        throw DataFormatError("LineReader forma error");
316      }
317    }
318  private:
319    bool skipSpaces;
320  };
321
322  /// \ingroup item_io
323  ///
324  /// \brief The default item reader template class.
325  ///
326  /// The default item reader template class. If some section reader
327  /// needs to read a value from a stream it will give the default way for it.
328  ///
329  /// \author Balazs Dezso
330  template <typename _Value>
331  class DefaultReader {
332  public:
333    /// The value type.
334    typedef _Value Value;
335    /// \brief Reads a value from the given stream.
336    ///
337    /// Reads a value from the given stream.
338    void read(std::istream& is, Value& value) const {
339      if (!(is >> value))
340        throw DataFormatError("DefaultReader format error");
341    }
342  };
343
344  template <>
345  class DefaultReader<std::string> {
346  public:
347    typedef std::string Value;
348   
349    void read(std::istream& is, Value& value) const {
350      char c;
351      if (!(is >> c)) return;
352      is.putback(c);
353      switch (c) {
354      case '\"':
355        QuotedStringReader().read(is, value);
356        break;
357      case '(':
358        ParsedStringReader().read(is, value);
359        break;
360      default:
361        is >> value;
362        break;
363      }
364    }
365   
366  };
367
368  template <typename Item>
369  class DefaultReader<std::vector<Item> >
370    : public PushBackReader<std::vector<Item> > {};
371
372  template <typename Item>
373  class DefaultReader<std::deque<Item> >
374    : public PushBackReader<std::deque<Item> > {};
375
376  template <typename Item>
377  class DefaultReader<std::list<Item> >
378    : public PushBackReader<std::list<Item> > {};
379
380  template <typename Item>
381  class DefaultReader<std::set<Item> >
382    : public InsertReader<std::set<Item> > {};
383
384  template <typename Item>
385  class DefaultReader<std::multiset<Item> >
386    : public InsertReader<std::multiset<Item> > {};
387
388  /// \ingroup item_io
389  ///
390  /// \brief The default item reader for skipping a value in the stream.
391  ///
392  /// The default item reader for skipping a value in the stream.
393  ///
394  /// \author Balazs Dezso
395  class DefaultSkipper : public DefaultReader<std::string> {};
396
397  /// \ingroup item_io 
398  /// \brief Standard ReaderTraits for the GraphReader class.
399  ///
400  /// Standard ReaderTraits for the GraphReader class.
401  /// It defines standard reading method for all type of value.
402  /// \author Balazs Dezso
403  struct DefaultReaderTraits {
404
405    template <typename _Value>
406    struct Reader : DefaultReader<_Value> {};
407
408    typedef DefaultSkipper Skipper;
409
410  };
411
412}
413
414#endif
Note: See TracBrowser for help on using the repository browser.