COIN-OR::LEMON - Graph Library

source: lemon-0.x/lemon/bits/item_reader.h @ 2426:6e1027a05d73

Last change on this file since 2426:6e1027a05d73 was 2426:6e1027a05d73, checked in by Balazs Dezso, 12 years ago

Allowing 'string' type quoting

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