COIN-OR::LEMON - Graph Library

source: lemon-0.x/src/lemon/bits/item_reader.h @ 1426:91eb70983697

Last change on this file since 1426:91eb70983697 was 1415:2a5810c2f806, checked in by Balazs Dezso, 19 years ago

Moved to subgroup

File size: 10.0 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 <typename Item>
345  class DefaultReader<std::vector<Item> >
346    : public PushBackReader<std::vector<Item> > {};
347
348  template <typename Item>
349  class DefaultReader<std::deque<Item> >
350    : public PushBackReader<std::deque<Item> > {};
351
352  template <typename Item>
353  class DefaultReader<std::list<Item> >
354    : public PushBackReader<std::list<Item> > {};
355
356  template <typename Item>
357  class DefaultReader<std::set<Item> >
358    : public InsertReader<std::set<Item> > {};
359
360  template <typename Item>
361  class DefaultReader<std::multiset<Item> >
362    : public InsertReader<std::multiset<Item> > {};
363
364  /// \ingroup item_io
365  ///
366  /// \brief The default item reader for skipping a value in the stream.
367  ///
368  /// The default item reader for skipping a value in the stream.
369  ///
370  /// \author Balazs Dezso
371  class DefaultSkipper {
372  public:
373    typedef std::string Value;
374   
375    void read(std::istream& is, Value& value) const {
376      char c;
377      if (!(is >> c)) return;
378      is.putback(c);
379      switch (c) {
380      case '\"':
381        QuotedStringReader().read(is, value);
382        break;
383      case '(':
384        ParsedStringReader().read(is, value);
385        break;
386      default:
387        DefaultReader<std::string>().read(is, value);
388        break;
389      }
390    }
391  };
392
393  /// \ingroup item_io 
394  /// \brief Standard ReaderTraits for the GraphReader class.
395  ///
396  /// Standard ReaderTraits for the GraphReader class.
397  /// It defines standard reading method for all type of value.
398  /// \author Balazs Dezso
399  struct DefaultReaderTraits {
400
401    template <typename _Value>
402    struct Reader : DefaultReader<_Value> {};
403
404    typedef DefaultSkipper Skipper;
405
406  };
407
408}
409
410#endif
Note: See TracBrowser for help on using the repository browser.