COIN-OR::LEMON - Graph Library

source: lemon-0.x/src/lemon/bits/item_reader.h @ 1414:01d9d6bc1284

Last change on this file since 1414:01d9d6bc1284 was 1408:892c29484414, checked in by Balazs Dezso, 19 years ago

New graph reader interface.

File size: 9.5 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/// \ingroup io_group
18/// \file
19/// \brief Item reader bits for lemon input.
20
21#ifndef LEMON_BITS_ITEM_READER_H
22#define LEMON_BITS_ITEM_READER_H
23
24#include <iostream>
25#include <string>
26
27#include <vector>
28#include <deque>
29#include <list>
30#include <set>
31
32namespace lemon {
33 
34  template <typename Value>
35  class DefaultReader;
36
37  /// \ingroup io_group
38  ///
39  /// \brief Reader class for quoted strings.
40  ///
41  /// Reader class for quoted strings. It can process the escape
42  /// sequences in the string.
43  ///
44  /// \author Balazs Dezso
45  class QuotedStringReader {
46  public:
47    /// \brief The value type of reader.
48    ///
49    /// The value type of reader.
50    typedef std::string Value;
51   
52    /// \brief Constructor for the reader.
53    ///
54    /// Constructor for the reader. If the given parameter is true
55    /// the reader processes the escape sequences.
56    QuotedStringReader(bool _escaped = true)
57      : escaped(_escaped) {}
58   
59    /// \brief Reads a quoted string from the given stream.
60    ///
61    /// Reads a quoted string from the given stream.
62    void read(std::istream& is, std::string& value) const {
63      char c;
64      value.clear();
65      is >> std::ws;
66      if (!is.get(c) || c != '\"')
67        throw DataFormatError("Quoted string format error");
68      while (is.get(c) && c != '\"') {
69        if (escaped && c == '\\') {
70          value += readEscape(is);
71        } else {
72          value += c;
73        }
74      }
75      if (!is) throw DataFormatError("Quoted string format error");
76    }
77
78  private:
79   
80    static char readEscape(std::istream& is) {
81      char c;
82      switch (is.get(c), c) {
83      case '\\':
84        return '\\';
85      case '\"':
86        return '\"';
87      case '\'':
88        return '\'';
89      case '\?':
90        return '\?';
91      case 'a':
92        return '\a';
93      case 'b':
94        return '\b';
95      case 'f':
96        return '\f';
97      case 'n':
98        return '\n';
99      case 'r':
100        return '\r';
101      case 't':
102        return '\t';
103      case 'v':
104        return '\v';
105      case 'x':
106        {
107          int code;
108          if (!is.get(c) || !isHex(c))
109            throw DataFormatError("Escape format error");
110          else if (code = valueHex(c), !is.get(c) || !isHex(c)) is.putback(c);
111          else code = code * 16 + valueHex(c);
112          return code;
113        }
114      default:
115        {
116          int code;
117          if (!isOct(c))
118            throw DataFormatError("Escape format error");
119          else if (code = valueOct(c), !is.get(c) || !isOct(c))
120            is.putback(c);
121          else if (code = code * 8 + valueOct(c), !is.get(c) || !isOct(c))
122            is.putback(c);
123          else code = code * 8 + valueOct(c);
124          return code;
125        }             
126      }
127    }
128
129    static bool isOct(char c) {
130      return '0' <= c && c <='7';
131    }
132   
133    static int valueOct(char c) {
134      return c - '0';
135    }
136
137   static bool isHex(char c) {
138      return ('0' <= c && c <= '9') ||
139        ('a' <= c && c <= 'z') ||
140        ('A' <= c && c <= 'Z');
141    }
142   
143    static int valueHex(char c) {
144      if ('0' <= c && c <= '9') return c - '0';
145      if ('a' <= c && c <= 'z') return c - 'a' + 10;
146      return c - 'A' + 10;
147    }
148
149    bool escaped;
150  };
151
152  /// \ingroup io_group
153  /// \brief Reader for standard containers.
154  ///
155  /// Reader for back insertable standard containers. The representation
156  /// of the container is the values enumerated between an open and a
157  /// close parse.
158  ///
159  /// \author Balazs Dezso
160  template <
161    typename _Container,
162    typename _ItemReader = DefaultReader<typename _Container::value_type>
163  >
164  class PushBackReader {
165  public:
166    typedef _Container Value;
167    typedef _ItemReader ItemReader;
168
169  private:
170
171    ItemReader item_reader;
172
173  public:
174
175    /// \brief Reads the values into the container from the given stream.
176    ///
177    /// Reads the values into the container from the given stream.
178    void read(std::istream& is, Value& value) const {
179      char c;
180      if (!(is >> c) || c != '(')
181        throw DataFormatError("PushBackReader format error");
182      while (is >> c && c != ')') {
183        is.putback(c);
184        typename ItemReader::Value item;
185        item_reader.read(is, item);
186        value.push_back(item);
187      }
188      if (!is) throw DataFormatError("PushBackReader format error");
189      is.putback(c);
190    }
191
192  };
193
194  /// \ingroup io_group
195  ///
196  /// \brief Reader for standard containers.
197  ///
198  /// Reader for insertable standard containers. The representation
199  /// of the container is the values enumerated between an open and a
200  /// close parse.
201  ///
202  /// \author Balazs Dezso
203  template <
204    typename _Container,
205    typename _ItemReader = DefaultReader<typename _Container::value_type>
206  >
207  class InsertReader {
208  public:
209    typedef _Container Value;
210    typedef _ItemReader ItemReader;
211
212  private:
213
214    ItemReader item_reader;
215
216  public:
217
218    /// \brief Reads the values into the container from the given stream.
219    ///
220    /// Reads the values into the container from the given stream.
221    void read(std::istream& is, Value& value) const {
222      char c;
223      if (!(is >> c) || c != '(')
224        throw DataFormatError("InsertReader format error");
225      while (is >> c && c != ')') {
226        is.putback(c);
227        typename ItemReader::Value item;
228        item_reader.read(is, item);
229        value.insert(item);
230      }
231      if (!is) throw DataFormatError("PushBackReader format error");
232      is.putback(c);
233    }
234
235  };
236
237  /// \ingroup io_group
238  /// \brief Reader for parsed string.
239  ///
240  /// Reader for parsed strings. You can give the open and close
241  /// parse characters.
242  ///
243  /// \author Balazs Dezso
244  class ParsedStringReader {
245  public:
246    typedef std::string Value;
247
248    /// \brief Constructor.
249    ///
250    /// Constructor for ParsedStringReader. You can give as parameter
251    /// the open and close parse characters.
252    ParsedStringReader(char _open = '(', char _close = ')')
253      : open(_open), close(_close) {}
254   
255   
256    /// \brief Reads the parsed string from the given stream.
257    ///
258    /// Reads the parsed string from the given stream.
259    void read(std::istream& is, Value& value) const {
260      char c;
261      if (!(is >> c) || c != open) {
262        throw DataFormatError("ParsedStringReader format error");
263      }
264      value += c;
265      int counter = 1;
266      while (counter > 0 && is >> c) {
267        if (c == close) {
268          --counter;
269        } else if (c == open) {
270          ++counter;
271        }
272        value += c;
273      }
274      if (!is) {
275        throw DataFormatError("ParsedStrinReader format error");
276      }
277    }
278
279  private:
280    char open, close;
281
282  };
283
284  /// \ingroup io_group
285  /// \brief Reader for read the whole line.
286  ///
287  /// Reader for read the whole line.
288  ///
289  /// \author Balazs Dezso
290  class LineReader {
291  public:
292    typedef std::string Value;
293
294    /// \brief Constructor.
295    ///
296    /// Constructor for the LineReader. If the given parameter is
297    /// true then the spaces before the first not space character are
298    /// skipped.
299    LineReader(bool _skipSpaces = true) : skipSpaces(_skipSpaces) {}
300   
301    /// \brief Reads the line from the given stream.
302    ///
303    /// Reads the line from the given stream.
304    void read(std::istream& is, Value& value) {
305      if (skipSpaces) is >> std::ws;
306      if (!getline(is, value)) {
307        throw DataFormatError("LineReader forma error");
308      }
309    }
310  private:
311    bool skipSpaces;
312  };
313
314  /// \ingroup io_group
315  ///
316  /// \brief The default item reader template class.
317  ///
318  /// The default item reader template class. If some section reader
319  /// needs to read a value from a stream it will give the default way for it.
320  ///
321  /// \author Balazs Dezso
322  template <typename _Value>
323  class DefaultReader {
324  public:
325    /// The value type.
326    typedef _Value Value;
327    /// \brief Reads a value from the given stream.
328    ///
329    /// Reads a value from the given stream.
330    void read(std::istream& is, Value& value) const {
331      if (!(is >> value))
332        throw DataFormatError("DefaultReader format error");
333    }
334  };
335
336  template <typename Item>
337  class DefaultReader<std::vector<Item> >
338    : public PushBackReader<std::vector<Item> > {};
339
340  template <typename Item>
341  class DefaultReader<std::deque<Item> >
342    : public PushBackReader<std::deque<Item> > {};
343
344  template <typename Item>
345  class DefaultReader<std::list<Item> >
346    : public PushBackReader<std::list<Item> > {};
347
348  template <typename Item>
349  class DefaultReader<std::set<Item> >
350    : public InsertReader<std::set<Item> > {};
351
352  template <typename Item>
353  class DefaultReader<std::multiset<Item> >
354    : public InsertReader<std::multiset<Item> > {};
355
356  /// \ingroup io_group
357  class DefaultSkipper {
358  public:
359    typedef std::string Value;
360   
361    void read(std::istream& is, Value& value) const {
362      char c;
363      if (!(is >> c)) return;
364      is.putback(c);
365      switch (c) {
366      case '\"':
367        QuotedStringReader().read(is, value);
368        break;
369      case '(':
370        ParsedStringReader().read(is, value);
371        break;
372      default:
373        DefaultReader<std::string>().read(is, value);
374        break;
375      }
376    }
377  };
378 
379  /// \brief Standard ReaderTraits for the GraphReader class.
380  ///
381  /// Standard ReaderTraits for the GraphReader class.
382  /// It defines standard reading method for all type of value.
383  /// \author Balazs Dezso
384  struct DefaultReaderTraits {
385
386    template <typename _Value>
387    struct Reader : DefaultReader<_Value> {};
388
389    typedef DefaultSkipper Skipper;
390
391  };
392
393}
394
395#endif
Note: See TracBrowser for help on using the repository browser.