COIN-OR::LEMON - Graph Library

source: lemon-0.x/lemon/bits/item_reader.h @ 2287:16954ac69517

Last change on this file since 2287:16954ac69517 was 2254:50cb2b90daa9, checked in by Balazs Dezso, 17 years ago

Some improvements on item readers and writers

File size: 17.1 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 unformatted strings.
42  ///
43  /// Reader class for unformatted strings. This class want to be
44  /// a general reader type which can read the most
45  ///
46  /// \author Balazs Dezso
47  class UnformattedReader {
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.
57    UnformattedReader() {}
58   
59    /// \brief Reads an unformatted string from the given stream.
60    ///
61    /// Reads an unformatted 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      while (is.get(c) && !whiteSpace(c)) {
67        processChar(c, is, value);
68      }
69    }
70
71  private:
72
73    void processChar(char c, std::istream& is, Value& value) const {
74      switch (c) {
75      case '(':
76        is.putback(c);
77        readParsed('(', ')', is, value);
78        break;
79      case '[':
80        is.putback(c);
81        readParsed('[', ']', is, value);
82        break;
83      case '{':
84        is.putback(c);
85        readParsed('{', '}', is, value);
86        break;
87      case '/':
88        is.putback(c);
89        readParsed('/', '/', is, value);
90        break;
91      case '\"':
92        is.putback(c);
93        readQuoted('\"', is, value);
94        break;
95      case '\'':
96        is.putback(c);
97        readQuoted('\'', is, value);
98        break;
99      default:
100        value += c;
101        break;
102      }
103    }
104
105    void readParsed(char open, char close,
106                    std::istream& is, Value& value) const {
107      char c;
108      if (!is.get(c) || c != open)
109        throw DataFormatError("Unformatted string format error");
110      value += c;
111      while (is.get(c) && c != close) {
112        processChar(c, is, value);
113      }
114      if (!is)
115        throw DataFormatError("Unformatted string format error");
116      value += c;     
117    }
118
119    void readQuoted(char quote, std::istream& is, Value& value) const {
120      char c;
121      bool esc = false;
122      if (!is.get(c) || c != quote)
123        throw DataFormatError("Unformatted string format error");
124      value += c;
125      while (is.get(c) && (c != quote || esc)) {
126        if (c == '\\') esc = !esc;
127        else esc = false;
128        value += c;
129      }
130      if (!is)
131        throw DataFormatError("Unformatted string format error");
132      value += c;
133    }
134
135
136
137    static bool whiteSpace(char c) {
138      return c == ' ' || c == '\t' || c == '\v' ||
139        c == '\n' || c == '\r' || c == '\f';
140    }
141
142   
143  };
144
145  /// \ingroup item_io
146  ///
147  /// \brief Reader class for quoted strings.
148  ///
149  /// Reader class for quoted strings. It can process the escape
150  /// sequences in the string.
151  ///
152  /// \author Balazs Dezso
153  class QuotedStringReader {
154    friend class QuotedCharReader;
155  public:
156    /// \brief The value type of reader.
157    ///
158    /// The value type of reader.
159    typedef std::string Value;
160   
161    /// \brief Constructor for the reader.
162    ///
163    /// Constructor for the reader. If the given parameter is true
164    /// the reader processes the escape sequences.
165    QuotedStringReader(bool _escaped = true)
166      : escaped(_escaped) {}
167   
168    /// \brief Reads a quoted string from the given stream.
169    ///
170    /// Reads a quoted string from the given stream.
171    void read(std::istream& is, std::string& value) const {
172      char c;
173      value.clear();
174      is >> std::ws;
175      if (!is.get(c) || c != '\"')
176        throw DataFormatError("Quoted format error");
177      while (is.get(c) && c != '\"') {
178        if (escaped && c == '\\') {
179          value += readEscape(is);
180        } else {
181          value += c;
182        }
183      }
184      if (!is) throw DataFormatError("Quoted format error");
185    }
186
187  private:
188   
189    static char readEscape(std::istream& is) {
190      char c;
191      switch (is.get(c), c) {
192      case '\\':
193        return '\\';
194      case '\"':
195        return '\"';
196      case '\'':
197        return '\'';
198      case '\?':
199        return '\?';
200      case 'a':
201        return '\a';
202      case 'b':
203        return '\b';
204      case 'f':
205        return '\f';
206      case 'n':
207        return '\n';
208      case 'r':
209        return '\r';
210      case 't':
211        return '\t';
212      case 'v':
213        return '\v';
214      case 'x':
215        {
216          int code;
217          if (!is.get(c) || !isHex(c))
218            throw DataFormatError("Escape format error");
219          else if (code = valueHex(c), !is.get(c) || !isHex(c)) is.putback(c);
220          else code = code * 16 + valueHex(c);
221          return code;
222        }
223      default:
224        {
225          int code;
226          if (!isOct(c))
227            throw DataFormatError("Escape format error");
228          else if (code = valueOct(c), !is.get(c) || !isOct(c))
229            is.putback(c);
230          else if (code = code * 8 + valueOct(c), !is.get(c) || !isOct(c))
231            is.putback(c);
232          else code = code * 8 + valueOct(c);
233          return code;
234        }             
235      }
236    }
237
238    static bool isOct(char c) {
239      return '0' <= c && c <='7';
240    }
241   
242    static int valueOct(char c) {
243      return c - '0';
244    }
245
246   static bool isHex(char c) {
247      return ('0' <= c && c <= '9') ||
248        ('a' <= c && c <= 'z') ||
249        ('A' <= c && c <= 'Z');
250    }
251   
252    static int valueHex(char c) {
253      if ('0' <= c && c <= '9') return c - '0';
254      if ('a' <= c && c <= 'z') return c - 'a' + 10;
255      return c - 'A' + 10;
256    }
257
258    bool escaped;
259  };
260
261  /// \ingroup item_io
262  ///
263  /// \brief Reader class for quoted strings.
264  ///
265  /// Reader class for quoted strings. It can process the escape
266  /// sequences in the string.
267  ///
268  /// \author Balazs Dezso
269  class QuotedCharReader {
270  public:
271    /// \brief The value type of reader.
272    ///
273    /// The value type of reader.
274    typedef char Value;
275   
276    /// \brief Constructor for the reader.
277    ///
278    /// Constructor for the reader. If the given parameter is true
279    /// the reader processes the escape sequences.
280    QuotedCharReader(bool _escaped = true)
281      : escaped(_escaped) {}
282   
283    /// \brief Reads a quoted string from the given stream.
284    ///
285    /// Reads a quoted string from the given stream.
286    void read(std::istream& is, char& value) const {
287      char c;
288      is >> std::ws;
289      if (!is.get(c) || c != '\'')
290        throw DataFormatError("Quoted format error");
291      if (!is.get(c))
292        throw DataFormatError("Quoted format error");
293      if (escaped && c == '\\') {
294        value = QuotedStringReader::readEscape(is);
295      } else {
296        value = c;
297      }
298      if (!is.get(c) || c != '\'')
299        throw DataFormatError("Quoted format error");
300    }
301
302  private:
303    bool escaped;
304  };
305
306  /// \ingroup item_io
307  /// \brief Reader for standard containers.
308  ///
309  /// Reader for back insertable standard containers. The representation
310  /// of the container is the values enumerated between an open and a
311  /// close parse.
312  ///
313  /// \author Balazs Dezso
314  template <
315    typename _Container,
316    typename _ItemReader = DefaultReader<typename _Container::value_type>
317  >
318  class PushBackReader {
319  public:
320    typedef _Container Value;
321    typedef _ItemReader ItemReader;
322
323  private:
324
325    ItemReader item_reader;
326
327  public:
328
329    /// \brief Constructor for InsertReader
330    ///
331    /// Constructor for InsertReader
332    PushBackReader(const ItemReader& _item_reader = ItemReader())
333      : item_reader(_item_reader) {}
334
335    /// \brief Reads the values into the container from the given stream.
336    ///
337    /// Reads the values into the container from the given stream.
338    void read(std::istream& is, Value& value) const {
339      char c;
340      if (!(is >> c) || c != '(')
341        throw DataFormatError("PushBackReader format error");
342      while (is >> c && c != ')') {
343        is.putback(c);
344        typename ItemReader::Value item;
345        item_reader.read(is, item);
346        value.push_back(item);
347      }
348      if (!is) throw DataFormatError("PushBackReader format error");
349    }
350
351  };
352
353  /// \ingroup item_io
354  ///
355  /// \brief Reader for standard containers.
356  ///
357  /// Reader for insertable standard containers. The representation
358  /// of the container is the values enumerated between an open and a
359  /// close parse.
360  ///
361  /// \author Balazs Dezso
362  template <
363    typename _Container,
364    typename _ItemReader = DefaultReader<typename _Container::value_type>
365  >
366  class InsertReader {
367  public:
368    typedef _Container Value;
369    typedef _ItemReader ItemReader;
370
371  private:
372
373    ItemReader item_reader;
374
375  public:
376
377    /// \brief Constructor for InsertReader
378    ///
379    /// Constructor for InsertReader
380    InsertReader(const ItemReader& _item_reader = ItemReader())
381      : item_reader(_item_reader) {}
382
383    /// \brief Reads the values into the container from the given stream.
384    ///
385    /// Reads the values into the container from the given stream.
386    void read(std::istream& is, Value& value) const {
387      char c;
388      if (!(is >> c) || c != '(')
389        throw DataFormatError("InsertReader format error");
390      while (is >> c && c != ')') {
391        is.putback(c);
392        typename ItemReader::Value item;
393        item_reader.read(is, item);
394        value.insert(item);
395      }
396      if (!is) throw DataFormatError("PushBackReader format error");
397    }
398
399  };
400
401  /// \ingroup item_io
402  /// \brief Reader for parsed string.
403  ///
404  /// Reader for parsed strings. You can define the open and close
405  /// parse characters. It reads from the input a character sequence
406  /// which is right parsed.
407  ///
408  /// \author Balazs Dezso
409  class ParsedStringReader {
410  public:
411    typedef std::string Value;
412
413    /// \brief Constructor.
414    ///
415    /// Constructor for ParsedStringReader. You can give as parameter
416    /// the open and close parse characters.
417    ParsedStringReader(char _open = '(', char _close = ')')
418      : open(_open), close(_close) {}
419   
420   
421    /// \brief Reads the parsed string from the given stream.
422    ///
423    /// Reads the parsed string from the given stream.
424    void read(std::istream& is, Value& value) const {
425      char c;
426      value.clear();
427      if (!(is >> c) || c != open) {
428        throw DataFormatError("ParsedStringReader format error");
429      }
430      value += c;
431      int counter = 1;
432      while (counter > 0 && is >> c) {
433        if (c == close) {
434          --counter;
435        } else if (c == open) {
436          ++counter;
437        }
438        value += c;
439      }
440      if (!is) {
441        throw DataFormatError("ParsedStrinReader format error");
442      }
443    }
444
445  private:
446    char open, close;
447
448  };
449
450  /// \ingroup item_io
451  /// \brief Reader for read the whole line.
452  ///
453  /// Reader for read the whole line.
454  ///
455  /// \author Balazs Dezso
456  class LineReader {
457  public:
458    typedef std::string Value;
459
460    /// \brief Constructor.
461    ///
462    /// Constructor for the LineReader. If the given parameter is
463    /// true then the spaces before the first not space character are
464    /// skipped.
465    LineReader(bool _skipSpaces = true) : skipSpaces(_skipSpaces) {}
466   
467    /// \brief Reads the line from the given stream.
468    ///
469    /// Reads the line from the given stream.
470    void read(std::istream& is, Value& value) const {
471      if (skipSpaces) is >> std::ws;
472      if (!getline(is, value)) {
473        throw DataFormatError("LineReader format error");
474      }
475    }
476  private:
477    bool skipSpaces;
478  };
479
480  /// \ingroup item_io
481  /// \brief Reader for std::pair.
482  ///
483  /// Reader for std::pair.
484  ///
485  /// \author Balazs Dezso
486  template <typename _Pair,
487            typename _FirstReader =
488            DefaultReader<typename _Pair::first_type>,
489            typename _SecondReader =
490            DefaultReader<typename _Pair::second_type> >
491  class PairReader {
492  public:
493    typedef _Pair Value;
494
495    typedef _FirstReader FirstReader;
496    typedef _SecondReader SecondReader;
497
498  private:
499
500    FirstReader first_reader;
501    SecondReader second_reader;
502
503  public:
504   
505    /// \brief Constructor.
506    ///
507    /// Constructor for the PairReader.
508    PairReader(const FirstReader& _first_reader = FirstReader(),
509               const SecondReader& _second_reader = SecondReader())
510      : first_reader(_first_reader), second_reader(_second_reader) {}
511   
512    /// \brief Reads the pair from the given stream.
513    ///
514    /// Reads the pair from the given stream.
515    void read(std::istream& is, Value& value) const {
516      char c;
517      if (!(is >> c) || c != '(') {
518        throw DataFormatError("PairReader format error");
519      }
520      first_reader.read(is, value.first);
521      if (!(is >> c) || c != '=') {
522        throw DataFormatError("PairReader format error");
523      }
524      if (!(is >> c) || c != '>') {
525        throw DataFormatError("PairReader format error");
526      }
527      second_reader.read(is, value.second);
528      if (!(is >> c) || c != ')') {
529        throw DataFormatError("PairReader format error");
530      }
531    }
532  };
533
534  /// \ingroup item_io
535  ///
536  /// \brief The default item reader template class.
537  ///
538  /// The default item reader template class. If some section reader
539  /// needs to read a value from a stream it will give the default way for it.
540  ///
541  /// \author Balazs Dezso
542  template <typename _Value>
543  class DefaultReader {
544  public:
545    /// The value type.
546    typedef _Value Value;
547    /// \brief Reads a value from the given stream.
548    ///
549    /// Reads a value from the given stream.
550    void read(std::istream& is, Value& value) const {
551      if (!(is >> value))
552        throw DataFormatError("DefaultReader format error");
553    }
554  };
555
556  template <>
557  class DefaultReader<std::string> {
558  public:
559    typedef std::string Value;
560   
561    void read(std::istream& is, Value& value) const {
562      char c;
563      if (!(is >> std::ws >> c))
564        throw DataFormatError("DefaultReader<string> format error");
565      is.putback(c);
566      switch (c) {
567      case '\"':
568        QuotedStringReader().read(is, value);
569        break;
570      default:
571        UnformattedReader().read(is, value);
572        break;
573      }
574    }
575   
576  };
577
578  template <>
579  class DefaultReader<char> {
580  public:
581    typedef char Value;
582   
583    void read(std::istream& is, Value& value) const {
584      char c;
585      if (!(is >> std::ws >> c))
586        throw DataFormatError("DefaultReader<char> format error");
587      is.putback(c);
588      switch (c) {
589      case '\'':
590        QuotedCharReader().read(is, value);
591        break;
592      default:
593        {
594          int temp;         
595          if (!(is >> temp))
596            throw DataFormatError("DefaultReader<char> format error");
597          value = (char)temp;
598          break;
599        }
600      }
601    }   
602  };
603
604  template <>
605  class DefaultReader<bool> {
606  public:
607    typedef bool Value;
608   
609    void read(std::istream& is, Value& value) const {
610      std::string rep;
611      if (!(is >> rep))
612        throw DataFormatError("DefaultReader<bool> format error");
613      if (rep == "true" || rep == "t" || rep == "1") {
614        value = true;
615      } else if (rep == "false" || rep == "f" || rep == "0") {
616        value = false;
617      } else throw DataFormatError("DefaultReader<bool> format error");
618    }   
619  };
620
621  template <typename Item>
622  class DefaultReader<std::vector<Item> >
623    : public PushBackReader<std::vector<Item> > {};
624
625  template <typename Item>
626  class DefaultReader<std::deque<Item> >
627    : public PushBackReader<std::deque<Item> > {};
628
629  template <typename Item>
630  class DefaultReader<std::list<Item> >
631    : public PushBackReader<std::list<Item> > {};
632
633  template <typename Item>
634  class DefaultReader<std::set<Item> >
635    : public InsertReader<std::set<Item> > {};
636
637  template <typename Key, typename Value>
638  class DefaultReader<std::map<Key, Value> >
639    : public InsertReader<std::map<Key, Value>,
640                          DefaultReader<std::pair<Key, Value> > > {};
641
642  template <typename Item>
643  class DefaultReader<std::multiset<Item> >
644    : public InsertReader<std::multiset<Item> > {};
645
646  template <typename Key, typename Value>
647  class DefaultReader<std::multimap<Key, Value> >
648    : public InsertReader<std::multimap<Key, Value>,
649                          DefaultReader<std::pair<Key, Value> > > {};
650
651  template <typename First, typename Second>
652  class DefaultReader<std::pair<First, Second> >
653    : public PairReader<std::pair<First, Second> > {};
654
655  /// \ingroup item_io
656  ///
657  /// \brief The default item reader for skipping a value in the stream.
658  ///
659  /// The default item reader for skipping a value in the stream.
660  ///
661  /// \author Balazs Dezso
662  class DefaultSkipper : public UnformattedReader {};
663
664  /// \ingroup item_io 
665  /// \brief Standard ReaderTraits for the GraphReader class.
666  ///
667  /// Standard ReaderTraits for the GraphReader class.
668  /// It defines standard reading method for all type of value.
669  /// \author Balazs Dezso
670  struct DefaultReaderTraits {
671
672    template <typename _Value>
673    struct Reader : DefaultReader<_Value> {};
674
675    typedef DefaultSkipper Skipper;
676
677  };
678
679}
680
681#endif
Note: See TracBrowser for help on using the repository browser.